From b0055516e6631d26fedfd499769984a7f2963f79 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 29 Mar 2022 15:21:35 +0200 Subject: [PATCH 001/898] OP-2834 - Fix getting non-active model panel. --- .../maya/plugins/publish/extract_playblast.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/openpype/hosts/maya/plugins/publish/extract_playblast.py b/openpype/hosts/maya/plugins/publish/extract_playblast.py index bb1ecf279d7..7fa9a840e97 100644 --- a/openpype/hosts/maya/plugins/publish/extract_playblast.py +++ b/openpype/hosts/maya/plugins/publish/extract_playblast.py @@ -90,6 +90,24 @@ def process(self, instance): else: preset["viewport_options"] = {"imagePlane": image_plane} + # Image planes do not update the file sequence unless the active panel + # is viewing through the camera. + model_panel = instance.context.data.get("model_panel") + if not model_panel: + model_panels = cmds.getPanel(type="modelPanel") + visible_panels = cmds.getPanel(visiblePanels=True) + model_panel = list( + set(visible_panels) - (set(visible_panels) - set(model_panels)) + )[0] + instance.context.data["model_panel"] = model_panel + + panel_camera = instance.context.data.get("panel_camera") + if not panel_camera: + panel_camera = capture.parse_view(model_panel)["camera"] + instance.context.data["panel_camera"] = panel_camera + + cmds.modelPanel(model_panel, edit=True, camera=preset["camera"]) + with maintained_time(): filename = preset.get("filename", "%TEMP%") @@ -108,6 +126,9 @@ def process(self, instance): path = capture.capture(**preset) + # Restore panel camera. + cmds.modelPanel(model_panel, edit=True, camera=panel_camera) + self.log.debug("playblast path {}".format(path)) collected_files = os.listdir(stagingdir) From 3770eb69b653f31292faee388ed416f7bf8a171f Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 29 Mar 2022 18:34:34 +0300 Subject: [PATCH 002/898] add rstex function --- .../maya/plugins/publish/extract_look.py | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index a8893072d08..15164952789 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -6,6 +6,7 @@ import tempfile import contextlib import subprocess +from openpype.lib.vendor_bin_utils import find_executable from collections import OrderedDict from maya import cmds # noqa @@ -42,6 +43,58 @@ def find_paths_by_hash(texture_hash): return io.distinct(key, {"type": "version"}) +def rstex(source, *args): + """Make `.rstexbin` using `redshiftTextureProcessor` + with some default settings. + + This function requires the `REDSHIFT_COREDATAPATH` + to be in `PATH`. + + Args: + source (str): Path to source file. + *args: Additional arguments for `redshiftTextureProcessor`. + + Returns: + str: Output of `redshiftTextureProcessor` command. + + """ + if "REDSHIFT_COREDATAPATH" not in os.environ: + raise RuntimeError("Must have Redshift available.") + + redshift_bin_path = os.path.join( + os.environ["REDSHIFT_COREDATAPATH"], + "bin", + "redshiftTextureProcessor" + ) + + texture_processor_path = find_executable(redshift_bin_path) + + cmd = [ + texture_processor_path, + escape_space(source), + + ] + + cmd.extend(args) + + cmd = " ".join(cmd) + + CREATE_NO_WINDOW = 0x08000000 + kwargs = dict(args=cmd, stderr=subprocess.STDOUT) + + if sys.platform == "win32": + kwargs["creationflags"] = CREATE_NO_WINDOW + try: + out = subprocess.check_output(**kwargs) + except subprocess.CalledProcessError as exc: + print(exc) + import traceback + + traceback.print_exc() + raise + return out + + def maketx(source, destination, *args): """Make `.tx` using `maketx` with some default settings. From 72b45229e943c419083e243ae27a540373edd6e2 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 29 Mar 2022 19:23:25 +0300 Subject: [PATCH 003/898] fix style warnings --- openpype/hosts/maya/plugins/publish/extract_look.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 15164952789..6102b311a3c 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -65,10 +65,10 @@ def rstex(source, *args): os.environ["REDSHIFT_COREDATAPATH"], "bin", "redshiftTextureProcessor" - ) + ) texture_processor_path = find_executable(redshift_bin_path) - + cmd = [ texture_processor_path, escape_space(source), @@ -83,7 +83,7 @@ def rstex(source, *args): kwargs = dict(args=cmd, stderr=subprocess.STDOUT) if sys.platform == "win32": - kwargs["creationflags"] = CREATE_NO_WINDOW + kwargs["creationflags"] = CREATE_NO_WINDOW try: out = subprocess.check_output(**kwargs) except subprocess.CalledProcessError as exc: From e65a1ea7d144abdcd0681641b45c50d11e903405 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 29 Mar 2022 19:45:00 +0300 Subject: [PATCH 004/898] remove extra line --- openpype/hosts/maya/plugins/publish/extract_look.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 6102b311a3c..cd647a67331 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -71,8 +71,7 @@ def rstex(source, *args): cmd = [ texture_processor_path, - escape_space(source), - + escape_space(source), ] cmd.extend(args) From 2406f78f4717451c2408a21b0f36bd66bd4ec95b Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 29 Mar 2022 19:45:49 +0300 Subject: [PATCH 005/898] fix trailing whitespace --- openpype/hosts/maya/plugins/publish/extract_look.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index cd647a67331..fb90d7538ba 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -71,7 +71,7 @@ def rstex(source, *args): cmd = [ texture_processor_path, - escape_space(source), + escape_space(source), ] cmd.extend(args) From be840d3a8b8b786c3fdfb56ab8ef7577c04747f3 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Mon, 4 Apr 2022 15:50:33 +0300 Subject: [PATCH 006/898] add exectuable path finder function --- openpype/lib/vendor_bin_utils.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/openpype/lib/vendor_bin_utils.py b/openpype/lib/vendor_bin_utils.py index 23e28ea3042..c30a1ee7092 100644 --- a/openpype/lib/vendor_bin_utils.py +++ b/openpype/lib/vendor_bin_utils.py @@ -120,6 +120,26 @@ def get_oiio_tools_path(tool="oiiotool"): return find_executable(os.path.join(oiio_dir, tool)) +def get_redshift_tool(tool_name): + """Path to redshift texture processor. + + On Windows it adds .exe extension if missing from tool argument. + + Args: + tool (string): Tool name. + + Returns: + str: Full path to redshift texture processor executable. + """ + redshift_tool_path = os.path.join( + os.environ["REDSHIFT_COREDATAPATH"], + "bin", + tool_name + ) + + return find_executable(redshift_tool_path) + + def get_ffmpeg_tool_path(tool="ffmpeg"): """Path to vendorized FFmpeg executable. From d4b8d47b18ed1605cdffa9a635586b40e29a6adf Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Mon, 4 Apr 2022 15:51:31 +0300 Subject: [PATCH 007/898] use redshift tool finder in extractor --- openpype/hosts/maya/plugins/publish/extract_look.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index fb90d7538ba..6ce3a981f47 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -6,7 +6,7 @@ import tempfile import contextlib import subprocess -from openpype.lib.vendor_bin_utils import find_executable +from openpype.lib.vendor_bin_utils import get_redshift_tool from collections import OrderedDict from maya import cmds # noqa @@ -61,13 +61,7 @@ def rstex(source, *args): if "REDSHIFT_COREDATAPATH" not in os.environ: raise RuntimeError("Must have Redshift available.") - redshift_bin_path = os.path.join( - os.environ["REDSHIFT_COREDATAPATH"], - "bin", - "redshiftTextureProcessor" - ) - - texture_processor_path = find_executable(redshift_bin_path) + texture_processor_path = get_redshift_tool("TextureProcessor") cmd = [ texture_processor_path, From abc299e86eea14ec425c07e46c5af51551cf1a3e Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 5 Apr 2022 20:00:54 +0300 Subject: [PATCH 008/898] Add redshift texture processing option to schema --- .../schemas/projects_schema/schemas/schema_maya_create.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json index 0544b4bab70..b0bd46d20fb 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json @@ -21,6 +21,11 @@ "key": "make_tx", "label": "Make tx files" }, + { + "type": "boolean", + "key": "rstex", + "label": "Make Redshift texture files" + }, { "type": "list", "key": "defaults", From 640415a0959bbc67f0e516b2363c4998b5d74508 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 5 Apr 2022 20:18:42 +0300 Subject: [PATCH 009/898] adjust key name --- .../schemas/projects_schema/schemas/schema_maya_create.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json index b0bd46d20fb..bf3c9b3fe84 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json @@ -23,7 +23,7 @@ }, { "type": "boolean", - "key": "rstex", + "key": "rs_tex", "label": "Make Redshift texture files" }, { From 0bcf353c82df569dc4bab517f3f2713f05f29b71 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 5 Apr 2022 20:26:47 +0300 Subject: [PATCH 010/898] add redshift texture create option to look creator --- openpype/hosts/maya/plugins/create/create_look.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/create/create_look.py b/openpype/hosts/maya/plugins/create/create_look.py index 56e2640919f..c190a73ade0 100644 --- a/openpype/hosts/maya/plugins/create/create_look.py +++ b/openpype/hosts/maya/plugins/create/create_look.py @@ -12,6 +12,7 @@ class CreateLook(plugin.Creator): family = "look" icon = "paint-brush" make_tx = True + rs_tex = False def __init__(self, *args, **kwargs): super(CreateLook, self).__init__(*args, **kwargs) @@ -20,6 +21,7 @@ def __init__(self, *args, **kwargs): # Whether to automatically convert the textures to .tx upon publish. self.data["maketx"] = self.make_tx - + # Whether to automatically convert the textures to .rstex upon publish. + self.data["rstex"] = self.rs_tex # Enable users to force a copy. self.data["forceCopy"] = False From 7bbf381c6e8fbd6a12a9ecf58d891f15d0e5ad83 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 5 Apr 2022 20:29:54 +0300 Subject: [PATCH 011/898] add rs_tex option to schema defaults --- openpype/settings/defaults/project_settings/maya.json | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index 19d9a955954..7c09fa78912 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -34,6 +34,7 @@ "CreateLook": { "enabled": true, "make_tx": true, + "rs_tex": false, "defaults": [ "Main" ] From 078775e9b6bb5e814d1f284202419760853e631a Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 5 Apr 2022 21:16:02 +0300 Subject: [PATCH 012/898] add rstex variable to process_resources --- openpype/hosts/maya/plugins/publish/extract_look.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 6ce3a981f47..11f62ab80b6 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -363,7 +363,8 @@ def process_resources(self, instance, staging_dir): # be the input file to multiple nodes. resources = instance.data["resources"] do_maketx = instance.data.get("maketx", False) - + # Option to convert textures to native redshift textures + do_rstex = instance.data.get("rstex", False) # Collect all unique files used in the resources files_metadata = {} for resource in resources: From 6ac5cd4a4a5efad533512b9deea45fe0bba4532a Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Fri, 8 Apr 2022 07:22:49 +0300 Subject: [PATCH 013/898] Add redshift texture processing flag --- openpype/hosts/maya/plugins/publish/extract_look.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 11f62ab80b6..87e66256530 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -396,6 +396,7 @@ def process_resources(self, instance, staging_dir): source, mode, texture_hash = self._process_texture( filepath, + do_rstex, do_maketx, staging=staging_dir, linearize=linearize, @@ -487,7 +488,7 @@ def resource_destination(self, instance, filepath, do_maketx): resources_dir, basename + ext ) - def _process_texture(self, filepath, do_maketx, staging, linearize, force): + def _process_texture(self, filepath, do_rstex, do_maketx, staging, linearize, force): """Process a single texture file on disk for publishing. This will: 1. Check whether it's already published, if so it will do hardlink From c43ec04003c7763d82d62944cc36c62512f11fb4 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Fri, 8 Apr 2022 07:50:49 +0300 Subject: [PATCH 014/898] add redshift processor call to generate .rstexbin --- openpype/hosts/maya/plugins/publish/extract_look.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 87e66256530..6ce8ff60528 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -548,6 +548,10 @@ def _process_texture(self, filepath, do_rstex, do_maketx, staging, linearize, fo return converted, COPY, texture_hash + self.log.info("Generating .rstexbin file for %s .." % filepath) + # Generates Redshift optimized textures using Redshift processor + if do_rstex: + rstex(filepath) return filepath, COPY, texture_hash From 92c1ac7342d94889abb79a71a9be8b8750d7fba7 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 19 Apr 2022 21:33:11 +0300 Subject: [PATCH 015/898] refactor convertor function to abstract class and inherited class --- .../maya/plugins/publish/extract_look.py | 75 +++++++++++-------- 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index e0a5bff56cc..7f236637214 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- """Maya look extractor.""" +from abc import ABC, abstractmethod import os import sys import json @@ -43,50 +44,60 @@ def find_paths_by_hash(texture_hash): key = "data.sourceHashes.{0}".format(texture_hash) return io.distinct(key, {"type": "version"}) +class TextureProcessor(metaclass=ABC.ABCMeta): + def __init__(self): + #TODO: Figure out design for predetermined objects to be initialized. + + @abstractmethod + def process(self, filepath): -def rstex(source, *args): - """Make `.rstexbin` using `redshiftTextureProcessor` - with some default settings. + - This function requires the `REDSHIFT_COREDATAPATH` - to be in `PATH`. +class MakeRSTexBin(TextureProcessor): + + def process(source, *args): + """Make `.rstexbin` using `redshiftTextureProcessor` + with some default settings. - Args: - source (str): Path to source file. - *args: Additional arguments for `redshiftTextureProcessor`. + This function requires the `REDSHIFT_COREDATAPATH` + to be in `PATH`. - Returns: - str: Output of `redshiftTextureProcessor` command. + Args: + source (str): Path to source file. + *args: Additional arguments for `redshiftTextureProcessor`. - """ - if "REDSHIFT_COREDATAPATH" not in os.environ: - raise RuntimeError("Must have Redshift available.") + Returns: + str: Output of `redshiftTextureProcessor` command. - texture_processor_path = get_redshift_tool("TextureProcessor") + """ + if "REDSHIFT_COREDATAPATH" not in os.environ: + raise RuntimeError("Must have Redshift available.") - cmd = [ - texture_processor_path, - escape_space(source), - ] + texture_processor_path = get_redshift_tool("TextureProcessor") - cmd.extend(args) + cmd = [ + texture_processor_path, + escape_space(source), + ] - cmd = " ".join(cmd) + cmd.extend(args) - CREATE_NO_WINDOW = 0x08000000 - kwargs = dict(args=cmd, stderr=subprocess.STDOUT) + cmd = " ".join(cmd) - if sys.platform == "win32": - kwargs["creationflags"] = CREATE_NO_WINDOW - try: - out = subprocess.check_output(**kwargs) - except subprocess.CalledProcessError as exc: - print(exc) - import traceback + CREATE_NO_WINDOW = 0x08000000 + kwargs = dict(args=cmd, stderr=subprocess.STDOUT) - traceback.print_exc() - raise - return out + if sys.platform == "win32": + kwargs["creationflags"] = CREATE_NO_WINDOW + try: + processed_filepath = subprocess.check_output(**kwargs) + except subprocess.CalledProcessError as exc: + print(exc) + import traceback + + traceback.print_exc() + raise + return processed_filepath def maketx(source, destination, *args): From 74f2c78415b091cdbc9bd447549d20dc0b796235 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 19 Apr 2022 21:34:26 +0300 Subject: [PATCH 016/898] refactor tx conversion into class --- .../maya/plugins/publish/extract_look.py | 92 +++++++++---------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 7f236637214..54ab7b7877b 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -99,65 +99,65 @@ def process(source, *args): raise return processed_filepath +class MakeTX(TextureProcessor): + def process(source, destination, *args): + """Make `.tx` using `maketx` with some default settings. -def maketx(source, destination, *args): - """Make `.tx` using `maketx` with some default settings. + The settings are based on default as used in Arnold's + txManager in the scene. + This function requires the `maketx` executable to be + on the `PATH`. - The settings are based on default as used in Arnold's - txManager in the scene. - This function requires the `maketx` executable to be - on the `PATH`. - - Args: - source (str): Path to source file. - destination (str): Writing destination path. - *args: Additional arguments for `maketx`. + Args: + source (str): Path to source file. + destination (str): Writing destination path. + *args: Additional arguments for `maketx`. - Returns: - str: Output of `maketx` command. + Returns: + str: Output of `maketx` command. - """ - from openpype.lib import get_oiio_tools_path + """ + from openpype.lib import get_oiio_tools_path - maketx_path = get_oiio_tools_path("maketx") + maketx_path = get_oiio_tools_path("maketx") - if not os.path.exists(maketx_path): - print( - "OIIO tool not found in {}".format(maketx_path)) - raise AssertionError("OIIO tool not found") + if not os.path.exists(maketx_path): + print( + "OIIO tool not found in {}".format(maketx_path)) + raise AssertionError("OIIO tool not found") - cmd = [ - maketx_path, - "-v", # verbose - "-u", # update mode - # unpremultiply before conversion (recommended when alpha present) - "--unpremult", - "--checknan", - # use oiio-optimized settings for tile-size, planarconfig, metadata - "--oiio", - "--filter lanczos3", - ] + cmd = [ + maketx_path, + "-v", # verbose + "-u", # update mode + # unpremultiply before conversion (recommended when alpha present) + "--unpremult", + "--checknan", + # use oiio-optimized settings for tile-size, planarconfig, metadata + "--oiio", + "--filter lanczos3", + ] - cmd.extend(args) - cmd.extend(["-o", escape_space(destination), escape_space(source)]) + cmd.extend(args) + cmd.extend(["-o", escape_space(destination), escape_space(source)]) - cmd = " ".join(cmd) + cmd = " ".join(cmd) - CREATE_NO_WINDOW = 0x08000000 # noqa - kwargs = dict(args=cmd, stderr=subprocess.STDOUT) + CREATE_NO_WINDOW = 0x08000000 # noqa + kwargs = dict(args=cmd, stderr=subprocess.STDOUT) - if sys.platform == "win32": - kwargs["creationflags"] = CREATE_NO_WINDOW - try: - out = subprocess.check_output(**kwargs) - except subprocess.CalledProcessError as exc: - print(exc) - import traceback + if sys.platform == "win32": + kwargs["creationflags"] = CREATE_NO_WINDOW + try: + processed_filepath = subprocess.check_output(**kwargs) + except subprocess.CalledProcessError as exc: + print(exc) + import traceback - traceback.print_exc() - raise + traceback.print_exc() + raise - return out + return processed_filepath @contextlib.contextmanager From 7b1346e300c047654d6378c300916a4ac76acf56 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 19 Apr 2022 21:41:48 +0300 Subject: [PATCH 017/898] add processor list and adjust logic for more options later --- openpype/hosts/maya/plugins/publish/extract_look.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 54ab7b7877b..4b77a47729a 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -374,9 +374,15 @@ def process_resources(self, instance, staging_dir): # might be included more than once amongst the resources as they could # be the input file to multiple nodes. resources = instance.data["resources"] + # Specify texture processing executables to activate + processors = [] do_maketx = instance.data.get("maketx", False) + if do_maketx: + processors.append(MakeTX) # Option to convert textures to native redshift textures do_rstex = instance.data.get("rstex", False) + if do_rstex: + processors.append(MakeRSTexBin) # Collect all unique files used in the resources files_metadata = {} for resource in resources: From 0100ea5bf8496915875ad0f7ca90ec1bd93e88de Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 7 Jun 2022 15:46:30 +0300 Subject: [PATCH 018/898] Move redshift tool finder function to extractor. --- .../maya/plugins/publish/extract_look.py | 29 +++++++++++++++---- openpype/lib/vendor_bin_utils.py | 20 ------------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 92d8f5ab17f..357f7a44305 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -8,7 +8,7 @@ import platform import contextlib import subprocess -from openpype.lib.vendor_bin_utils import get_redshift_tool +from openpype.lib.vendor_bin_utils import find_executable from collections import OrderedDict from maya import cmds # noqa @@ -46,15 +46,13 @@ def find_paths_by_hash(texture_hash): class TextureProcessor(metaclass=ABC.ABCMeta): def __init__(self): - #TODO: Figure out design for predetermined objects to be initialized. - + #TODO: Figure out design for predetermined objects to be initialized. + @abstractmethod def process(self, filepath): - class MakeRSTexBin(TextureProcessor): - def process(source, *args): """Make `.rstexbin` using `redshiftTextureProcessor` with some default settings. @@ -99,6 +97,7 @@ def process(source, *args): raise return processed_filepath + class MakeTX(TextureProcessor): def process(source, destination, *args): """Make `.tx` using `maketx` with some default settings. @@ -603,3 +602,23 @@ def get_maya_scene_type(self, instance): self.scene_type = self.scene_type_prefix + self.scene_type return typ + + +def get_redshift_tool(tool_name): + """Path to redshift texture processor. + + On Windows it adds .exe extension if missing from tool argument. + + Args: + tool (string): Tool name. + + Returns: + str: Full path to redshift texture processor executable. + """ + redshift_tool_path = os.path.join( + os.environ["REDSHIFT_COREDATAPATH"], + "bin", + tool_name + ) + + return find_executable(redshift_tool_path) diff --git a/openpype/lib/vendor_bin_utils.py b/openpype/lib/vendor_bin_utils.py index cdc12904007..e5ab2872a0e 100644 --- a/openpype/lib/vendor_bin_utils.py +++ b/openpype/lib/vendor_bin_utils.py @@ -123,26 +123,6 @@ def get_oiio_tools_path(tool="oiiotool"): return find_executable(os.path.join(oiio_dir, tool)) -def get_redshift_tool(tool_name): - """Path to redshift texture processor. - - On Windows it adds .exe extension if missing from tool argument. - - Args: - tool (string): Tool name. - - Returns: - str: Full path to redshift texture processor executable. - """ - redshift_tool_path = os.path.join( - os.environ["REDSHIFT_COREDATAPATH"], - "bin", - tool_name - ) - - return find_executable(redshift_tool_path) - - def get_ffmpeg_tool_path(tool="ffmpeg"): """Path to vendorized FFmpeg executable. From 2102e4f4fa86778542d96e9758dbb12967b6b762 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 7 Jun 2022 15:46:50 +0300 Subject: [PATCH 019/898] Add variable for redshift os path. --- openpype/hosts/maya/plugins/publish/extract_look.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 357f7a44305..69d7eb78af8 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -615,8 +615,10 @@ def get_redshift_tool(tool_name): Returns: str: Full path to redshift texture processor executable. """ + redshift_os_path = os.environ["REDSHIFT_COREDATAPATH"] + redshift_tool_path = os.path.join( - os.environ["REDSHIFT_COREDATAPATH"], + redshift_os_path, "bin", tool_name ) From 406ac826e018ffcac07aa9145f5c532b86ddfd27 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 7 Jun 2022 16:09:53 +0300 Subject: [PATCH 020/898] Style fix --- openpype/hosts/maya/plugins/publish/extract_look.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 69d7eb78af8..2e83af1437c 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -46,7 +46,7 @@ def find_paths_by_hash(texture_hash): class TextureProcessor(metaclass=ABC.ABCMeta): def __init__(self): - #TODO: Figure out design for predetermined objects to be initialized. + # TODO: Figure out design for predetermined objects to be initialized. @abstractmethod def process(self, filepath): From 710ed3a889ee3d7043501d514d0cc3be3e8d571e Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Wed, 8 Jun 2022 10:37:46 +0300 Subject: [PATCH 021/898] Start moving processors logic. --- .../maya/plugins/publish/extract_look.py | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 2e83af1437c..cce2643dba1 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -44,6 +44,7 @@ def find_paths_by_hash(texture_hash): key = "data.sourceHashes.{0}".format(texture_hash) return legacy_io.distinct(key, {"type": "version"}) + class TextureProcessor(metaclass=ABC.ABCMeta): def __init__(self): # TODO: Figure out design for predetermined objects to be initialized. @@ -51,6 +52,8 @@ def __init__(self): @abstractmethod def process(self, filepath): + return processed_texture_path + class MakeRSTexBin(TextureProcessor): def process(source, *args): @@ -373,15 +376,6 @@ def process_resources(self, instance, staging_dir): # might be included more than once amongst the resources as they could # be the input file to multiple nodes. resources = instance.data["resources"] - # Specify texture processing executables to activate - processors = [] - do_maketx = instance.data.get("maketx", False) - if do_maketx: - processors.append(MakeTX) - # Option to convert textures to native redshift textures - do_rstex = instance.data.get("rstex", False) - if do_rstex: - processors.append(MakeRSTexBin) # Collect all unique files used in the resources files_metadata = {} for resource in resources: @@ -420,8 +414,7 @@ def process_resources(self, instance, staging_dir): source, mode, texture_hash = self._process_texture( filepath, - do_rstex, - do_maketx, + processors, staging=staging_dir, linearize=linearize, force=force_copy @@ -514,7 +507,7 @@ def resource_destination(self, instance, filepath, do_maketx): resources_dir, basename + ext ) - def _process_texture(self, filepath, do_rstex, do_maketx, staging, linearize, force): + def _process_texture(self, filepath, processors, staging, linearize, force): """Process a single texture file on disk for publishing. This will: 1. Check whether it's already published, if so it will do hardlink @@ -546,7 +539,17 @@ def _process_texture(self, filepath, do_rstex, do_maketx, staging, linearize, fo ("Paths not found on disk, " "skipping hardlink: %s") % (existing,) ) - + texture_files = self.collect_text + # Specify texture processing executables to activate + processors = [] + do_maketx = instance.data.get("maketx", False) + if do_maketx: + processors.append(MakeTX) + # Option to convert textures to native redshift textures + do_rstex = instance.data.get("rstex", False) + if do_rstex: + processors.append(MakeRSTexBin) + if do_maketx and ext != ".tx": # Produce .tx file in staging if source file is not .tx converted = os.path.join(staging, "resources", fname + ".tx") From 68caaa7528882654077a208b835a712f3e319850 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Thu, 9 Jun 2022 10:56:26 +0300 Subject: [PATCH 022/898] move function --- .../maya/plugins/publish/extract_look.py | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index cce2643dba1..d6c35882804 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -24,6 +24,28 @@ HARDLINK = 2 +def get_redshift_tool(tool_name): + """Path to redshift texture processor. + + On Windows it adds .exe extension if missing from tool argument. + + Args: + tool (string): Tool name. + + Returns: + str: Full path to redshift texture processor executable. + """ + redshift_os_path = os.environ["REDSHIFT_COREDATAPATH"] + + redshift_tool_path = os.path.join( + redshift_os_path, + "bin", + tool_name + ) + + return find_executable(redshift_tool_path) + + def escape_space(path): """Ensure path is enclosed by quotes to allow paths with spaces""" return '"{}"'.format(path) if " " in path else path @@ -605,25 +627,3 @@ def get_maya_scene_type(self, instance): self.scene_type = self.scene_type_prefix + self.scene_type return typ - - -def get_redshift_tool(tool_name): - """Path to redshift texture processor. - - On Windows it adds .exe extension if missing from tool argument. - - Args: - tool (string): Tool name. - - Returns: - str: Full path to redshift texture processor executable. - """ - redshift_os_path = os.environ["REDSHIFT_COREDATAPATH"] - - redshift_tool_path = os.path.join( - redshift_os_path, - "bin", - tool_name - ) - - return find_executable(redshift_tool_path) From 29b69bcbb805702080fe54e52505fe09a3741f99 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Thu, 9 Jun 2022 20:47:26 +0300 Subject: [PATCH 023/898] Class cleanup --- openpype/hosts/maya/plugins/publish/extract_look.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index d7b179daf2c..be31deeb6eb 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -69,12 +69,12 @@ def find_paths_by_hash(texture_hash): class TextureProcessor(metaclass=ABC.ABCMeta): def __init__(self): - # TODO: Figure out design for predetermined objects to be initialized. + pass @abstractmethod def process(self, filepath): - return processed_texture_path + pass class MakeRSTexBin(TextureProcessor): @@ -544,8 +544,7 @@ def _process_texture(self, filepath, processors, staging, linearize, force): fname, ext = os.path.splitext(os.path.basename(filepath)) args = [] - if do_maketx: - args.append("maketx") + texture_hash = openpype.api.source_hash(filepath, *args) # If source has been published before with the same settings, @@ -571,7 +570,7 @@ def _process_texture(self, filepath, processors, staging, linearize, force): do_rstex = instance.data.get("rstex", False) if do_rstex: processors.append(MakeRSTexBin) - + if do_maketx and ext != ".tx": # Produce .tx file in staging if source file is not .tx converted = os.path.join(staging, "resources", fname + ".tx") From e78314ca92283b38fd05d8995aeb9c06b460277e Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Thu, 9 Jun 2022 20:49:07 +0300 Subject: [PATCH 024/898] Remove unused maketx code. --- .../maya/plugins/publish/extract_look.py | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index be31deeb6eb..3e1f91f5b7d 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -544,7 +544,6 @@ def _process_texture(self, filepath, processors, staging, linearize, force): fname, ext = os.path.splitext(os.path.basename(filepath)) args = [] - texture_hash = openpype.api.source_hash(filepath, *args) # If source has been published before with the same settings, @@ -571,32 +570,6 @@ def _process_texture(self, filepath, processors, staging, linearize, force): if do_rstex: processors.append(MakeRSTexBin) - if do_maketx and ext != ".tx": - # Produce .tx file in staging if source file is not .tx - converted = os.path.join(staging, "resources", fname + ".tx") - - if linearize: - self.log.info("tx: converting sRGB -> linear") - colorconvert = "--colorconvert sRGB linear" - else: - colorconvert = "" - - # Ensure folder exists - if not os.path.exists(os.path.dirname(converted)): - os.makedirs(os.path.dirname(converted)) - - self.log.info("Generating .tx file for %s .." % filepath) - maketx( - filepath, - converted, - # Include `source-hash` as string metadata - "-sattrib", - "sourceHash", - escape_space(texture_hash), - colorconvert, - ) - - return converted, COPY, texture_hash self.log.info("Generating .rstexbin file for %s .." % filepath) # Generates Redshift optimized textures using Redshift processor From 00d877e2dfca6b1e89a4b4d289b2621a6e8b2037 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Thu, 9 Jun 2022 20:50:51 +0300 Subject: [PATCH 025/898] Move processors list --- .../maya/plugins/publish/extract_look.py | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 3e1f91f5b7d..88c93a8e3ba 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -433,7 +433,15 @@ def process_resources(self, instance, staging_dir): # if do_maketx: # color_space = "Raw" - + # Specify texture processing executables to activate + processors = [] + do_maketx = instance.data.get("maketx", False) + if do_maketx: + processors.append(MakeTX) + # Option to convert textures to native redshift textures + do_rstex = instance.data.get("rstex", False) + if do_rstex: + processors.append(MakeRSTexBin) source, mode, texture_hash = self._process_texture( filepath, processors, @@ -559,16 +567,6 @@ def _process_texture(self, filepath, processors, staging, linearize, force): ("Paths not found on disk, " "skipping hardlink: %s") % (existing,) ) - texture_files = self.collect_text - # Specify texture processing executables to activate - processors = [] - do_maketx = instance.data.get("maketx", False) - if do_maketx: - processors.append(MakeTX) - # Option to convert textures to native redshift textures - do_rstex = instance.data.get("rstex", False) - if do_rstex: - processors.append(MakeRSTexBin) self.log.info("Generating .rstexbin file for %s .." % filepath) From 2933e409c769f13afd0e1df778fdacd06cf7b848 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Thu, 9 Jun 2022 20:59:19 +0300 Subject: [PATCH 026/898] Handle texture processing through processors separately --- openpype/hosts/maya/plugins/publish/extract_look.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 88c93a8e3ba..73d661168a3 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -442,6 +442,7 @@ def process_resources(self, instance, staging_dir): do_rstex = instance.data.get("rstex", False) if do_rstex: processors.append(MakeRSTexBin) + source, mode, texture_hash = self._process_texture( filepath, processors, @@ -567,12 +568,9 @@ def _process_texture(self, filepath, processors, staging, linearize, force): ("Paths not found on disk, " "skipping hardlink: %s") % (existing,) ) - - - self.log.info("Generating .rstexbin file for %s .." % filepath) - # Generates Redshift optimized textures using Redshift processor - if do_rstex: - rstex(filepath) + for processor in processors: + processor().process(filepath) + self.log.info("Generating .rstexbin file for %s .." % filepath) return filepath, COPY, texture_hash From b054175d6e834dabd7b3d8719eed901ab139062f Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Thu, 9 Jun 2022 21:06:02 +0300 Subject: [PATCH 027/898] Reorganize functionality for do_maketx to linearize properly. --- openpype/hosts/maya/plugins/publish/extract_look.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 73d661168a3..e90f9759f9e 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -426,23 +426,20 @@ def process_resources(self, instance, staging_dir): for filepath in files_metadata: linearize = False - if do_maketx and files_metadata[filepath]["color_space"].lower() == "srgb": # noqa: E501 - linearize = True - # set its file node to 'raw' as tx will be linearized - files_metadata[filepath]["color_space"] = "Raw" - # if do_maketx: - # color_space = "Raw" # Specify texture processing executables to activate processors = [] do_maketx = instance.data.get("maketx", False) + do_rstex = instance.data.get("rstex", False) if do_maketx: processors.append(MakeTX) # Option to convert textures to native redshift textures - do_rstex = instance.data.get("rstex", False) if do_rstex: processors.append(MakeRSTexBin) - + if do_maketx and files_metadata[filepath]["color_space"].lower() == "srgb": # noqa: E501 + linearize = True + # set its file node to 'raw' as tx will be linearized + files_metadata[filepath]["color_space"] = "Raw" source, mode, texture_hash = self._process_texture( filepath, processors, From fd3125deda242f2676f1262fffb4e93212ffa300 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Thu, 9 Jun 2022 21:07:26 +0300 Subject: [PATCH 028/898] Style fixes --- openpype/hosts/maya/plugins/publish/extract_look.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index e90f9759f9e..018e45a01f1 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -436,6 +436,7 @@ def process_resources(self, instance, staging_dir): # Option to convert textures to native redshift textures if do_rstex: processors.append(MakeRSTexBin) + if do_maketx and files_metadata[filepath]["color_space"].lower() == "srgb": # noqa: E501 linearize = True # set its file node to 'raw' as tx will be linearized From 41e7ac78aa340d4af45c48b036fb3ccf39c56f79 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Thu, 9 Jun 2022 22:11:12 +0300 Subject: [PATCH 029/898] adjust comment --- openpype/hosts/maya/plugins/publish/extract_look.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 018e45a01f1..922e3475612 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -568,7 +568,7 @@ def _process_texture(self, filepath, processors, staging, linearize, force): ) for processor in processors: processor().process(filepath) - self.log.info("Generating .rstexbin file for %s .." % filepath) + self.log.info("Generating texture file for %s .." % filepath) return filepath, COPY, texture_hash From 35be81615ee986b0b71482a8f13097fa469ab477 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Fri, 10 Jun 2022 10:51:19 +0300 Subject: [PATCH 030/898] Fix returned filepath --- openpype/hosts/maya/plugins/publish/extract_look.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 922e3475612..7693e917659 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -567,9 +567,9 @@ def _process_texture(self, filepath, processors, staging, linearize, force): "skipping hardlink: %s") % (existing,) ) for processor in processors: - processor().process(filepath) + processed_path = processor().process(filepath) self.log.info("Generating texture file for %s .." % filepath) - return filepath, COPY, texture_hash + return processed_path, COPY, texture_hash class ExtractModelRenderSets(ExtractLook): From cfb90934289a742572d93323d48df6ae061acdb7 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Fri, 10 Jun 2022 20:32:58 +0300 Subject: [PATCH 031/898] Append processors check, append path return. --- openpype/hosts/maya/plugins/publish/extract_look.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 7693e917659..c72aede0d4c 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -566,9 +566,13 @@ def _process_texture(self, filepath, processors, staging, linearize, force): ("Paths not found on disk, " "skipping hardlink: %s") % (existing,) ) - for processor in processors: - processed_path = processor().process(filepath) - self.log.info("Generating texture file for %s .." % filepath) + + if bool(processors): + for processor in processors: + processed_path = processor().process(filepath) + self.log.info("Generating texture file for %s .." % filepath) + return processed_path + return processed_path, COPY, texture_hash From eb9994484e94f9e595d95fac302da49cef986cc4 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Fri, 10 Jun 2022 20:35:53 +0300 Subject: [PATCH 032/898] Style fix --- openpype/hosts/maya/plugins/publish/extract_look.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index c72aede0d4c..6d8b6f1d8e4 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -536,7 +536,7 @@ def resource_destination(self, instance, filepath, do_maketx): resources_dir, basename + ext ) - def _process_texture(self, filepath, processors, staging, linearize, force): + def _process_texture(self, filepath, processors, staging, linearize, force): # noqa """Process a single texture file on disk for publishing. This will: 1. Check whether it's already published, if so it will do hardlink From e5fdd9e9302fe82620b5fb0c94c4ce1188c4a731 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 26 Jul 2022 20:45:54 +0300 Subject: [PATCH 033/898] Syntax fix. --- openpype/hosts/maya/plugins/publish/extract_look.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 6d8b6f1d8e4..3fe8139dd65 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """Maya look extractor.""" -from abc import ABC, abstractmethod +import abc import os import sys import json @@ -67,11 +67,11 @@ def find_paths_by_hash(texture_hash): return legacy_io.distinct(key, {"type": "version"}) -class TextureProcessor(metaclass=ABC.ABCMeta): +class TextureProcessor(abc.ABCMeta): def __init__(self): pass - @abstractmethod + @abc.abstractmethod def process(self, filepath): pass From ab14895753c72177ebdfc7ff4f6e8b0bb1eb68ec Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 26 Jul 2022 23:27:11 +0300 Subject: [PATCH 034/898] Change metaclass inheritance formatting to 2.7 --- openpype/hosts/maya/plugins/publish/extract_look.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 3fe8139dd65..be6d8638783 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """Maya look extractor.""" -import abc +from abc import ABCMeta, abstractmethod import os import sys import json @@ -67,11 +67,13 @@ def find_paths_by_hash(texture_hash): return legacy_io.distinct(key, {"type": "version"}) -class TextureProcessor(abc.ABCMeta): +class TextureProcessor(object): + __metaclass__ = ABCMeta + def __init__(self): pass - @abc.abstractmethod + @abstractmethod def process(self, filepath): pass From c471bbe71e20f09df30c1ea734a958f3a308e3f6 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Wed, 27 Jul 2022 02:26:18 +0300 Subject: [PATCH 035/898] Fix inheritance with `six`, adjust processing code --- .../maya/plugins/publish/extract_look.py | 33 ++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index be6d8638783..19e0bd9568f 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- """Maya look extractor.""" from abc import ABCMeta, abstractmethod +import six import os import sys import json @@ -67,9 +68,9 @@ def find_paths_by_hash(texture_hash): return legacy_io.distinct(key, {"type": "version"}) -class TextureProcessor(object): - __metaclass__ = ABCMeta - +@six.add_metaclass(ABCMeta) +class TextureProcessor: + @abstractmethod def __init__(self): pass @@ -80,7 +81,10 @@ def process(self, filepath): class MakeRSTexBin(TextureProcessor): - def process(source, *args): + def __init__(self): + super(TextureProcessor, self).__init__() + + def process(self, source, *args): """Make `.rstexbin` using `redshiftTextureProcessor` with some default settings. @@ -126,7 +130,10 @@ def process(source, *args): class MakeTX(TextureProcessor): - def process(source, destination, *args): + def __init__(self): + super(TextureProcessor, self).__init__() + + def process(self, source, destination, *args): """Make `.tx` using `maketx` with some default settings. The settings are based on default as used in Arnold's @@ -558,6 +565,10 @@ def _process_texture(self, filepath, processors, staging, linearize, force): # n # If source has been published before with the same settings, # then don't reprocess but hardlink from the original existing = find_paths_by_hash(texture_hash) + # if processors["do_maketx"]: + # Produce .tx file in staging if source file is not .tx + + if existing and not force: self.log.info("Found hash in database, preparing hardlink..") source = next((p for p in existing if os.path.exists(p)), None) @@ -571,9 +582,15 @@ def _process_texture(self, filepath, processors, staging, linearize, force): # n if bool(processors): for processor in processors: - processed_path = processor().process(filepath) - self.log.info("Generating texture file for %s .." % filepath) - return processed_path + if processor == MakeTX: + converted = os.path.join(staging, "resources", fname + ".tx") + processed_path = processor().process(converted, filepath) + self.log.info("Generating texture file for %s .." % filepath) # noqa + return processed_path + elif processor == MakeRSTexBin: + processed_path = processor().process(filepath) + self.log.info("Generating texture file for %s .." % filepath) # noqa + return processed_path return processed_path, COPY, texture_hash From 5f4d06baecce44fd735e1a26770f0a617c0284fb Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Wed, 27 Jul 2022 02:48:43 +0300 Subject: [PATCH 036/898] Remove unnecessary comment, style fixes. --- openpype/hosts/maya/plugins/publish/extract_look.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 19e0bd9568f..bb4335a3d52 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -172,7 +172,7 @@ def process(self, source, destination, *args): ] cmd.extend(args) - cmd.extend(["-o", escape_space(destination), escape_space(source)]) + cmd.extend([escape_space(source), "-o", escape_space(destination)]) cmd = " ".join(cmd) @@ -188,6 +188,8 @@ def process(self, source, destination, *args): import traceback traceback.print_exc() + print(exc.returncode) + print(exc.output) raise return processed_filepath @@ -565,9 +567,6 @@ def _process_texture(self, filepath, processors, staging, linearize, force): # n # If source has been published before with the same settings, # then don't reprocess but hardlink from the original existing = find_paths_by_hash(texture_hash) - # if processors["do_maketx"]: - # Produce .tx file in staging if source file is not .tx - if existing and not force: self.log.info("Found hash in database, preparing hardlink..") @@ -583,8 +582,8 @@ def _process_texture(self, filepath, processors, staging, linearize, force): # n if bool(processors): for processor in processors: if processor == MakeTX: - converted = os.path.join(staging, "resources", fname + ".tx") - processed_path = processor().process(converted, filepath) + converted = os.path.join(staging, "resources", fname + ".tx") # noqa + processed_path = processor().process(filepath, converted) self.log.info("Generating texture file for %s .." % filepath) # noqa return processed_path elif processor == MakeRSTexBin: From 9b0cc4dfac23100fa3979b53418734c39399c5ca Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Mon, 1 Aug 2022 03:28:26 +0300 Subject: [PATCH 037/898] Continue refactor --- .../maya/plugins/publish/extract_look.py | 52 +++++++++++-------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 136b64a5474..8d302686191 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -615,12 +615,29 @@ def _process_texture(self, filepath, processors, staging, linearize, force): # n ("Paths not found on disk, " "skipping hardlink: %s") % (existing,) ) + config_path = get_ocio_config_path("nuke-default") + color_config = "--colorconfig {0}".format(config_path) + # Ensure folder exists + if linearize: + self.log.info("tx: converting sRGB -> linear") + colorconvert = "--colorconvert sRGB linear" + else: + colorconvert = "" + + converted = os.path.join(staging, "resources", fname + ".tx") + if not os.path.exists(os.path.dirname(converted)): + os.makedirs(os.path.dirname(converted)) if bool(processors): for processor in processors: if processor == MakeTX: - converted = os.path.join(staging, "resources", fname + ".tx") # noqa - processed_path = processor().process(filepath, converted) + processed_path = processor().process(filepath, + converted, + "--sattrib", + "sourceHash %", + escape_space(texture_hash), # noqa + colorconvert, + color_config) self.log.info("Generating texture file for %s .." % filepath) # noqa return processed_path elif processor == MakeRSTexBin: @@ -628,27 +645,18 @@ def _process_texture(self, filepath, processors, staging, linearize, force): # n self.log.info("Generating texture file for %s .." % filepath) # noqa return processed_path - return processed_path, COPY, texture_hash - - config_path = get_ocio_config_path("nuke-default") - color_config = "--colorconfig {0}".format(config_path) - # Ensure folder exists - if not os.path.exists(os.path.dirname(converted)): - os.makedirs(os.path.dirname(converted)) - - self.log.info("Generating .tx file for %s .." % filepath) - maketx( - filepath, - converted, - # Include `source-hash` as string metadata - "--sattrib", - "sourceHash", - escape_space(texture_hash), - colorconvert, - color_config - ) - return converted, COPY, texture_hash + # self.log.info("Generating .tx file for %s .." % filepath) + # maketx( + # filepath, + # converted, + # # Include `source-hash` as string metadata + # "--sattrib", + # "sourceHash", + # escape_space(texture_hash), + # colorconvert, + # color_config + # ) return filepath, COPY, texture_hash From c35f1cfe3c295d7915e4a2b856f48ecae85cab38 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Mon, 1 Aug 2022 04:09:09 +0300 Subject: [PATCH 038/898] Remove leftover code --- .../maya/plugins/publish/extract_look.py | 32 +------------------ 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 8d302686191..ecbb0709161 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -114,27 +114,10 @@ def process(self, source, *args): This function requires the `REDSHIFT_COREDATAPATH` to be in `PATH`. - cmd = [ - maketx_path, - "-v", # verbose - "-u", # update mode - # unpremultiply before conversion (recommended when alpha present) - "--unpremult", - "--checknan", - # use oiio-optimized settings for tile-size, planarconfig, metadata - "--oiio", - "--filter lanczos3", - escape_space(source) - ] Args: source (str): Path to source file. *args: Additional arguments for `redshiftTextureProcessor`. - cmd.extend(args) - cmd.extend(["-o", escape_space(destination)]) - Returns: - str: Output of `redshiftTextureProcessor` command. - """ if "REDSHIFT_COREDATAPATH" not in os.environ: raise RuntimeError("Must have Redshift available.") @@ -634,7 +617,7 @@ def _process_texture(self, filepath, processors, staging, linearize, force): # n processed_path = processor().process(filepath, converted, "--sattrib", - "sourceHash %", + "sourceHash", escape_space(texture_hash), # noqa colorconvert, color_config) @@ -645,19 +628,6 @@ def _process_texture(self, filepath, processors, staging, linearize, force): # n self.log.info("Generating texture file for %s .." % filepath) # noqa return processed_path - - # self.log.info("Generating .tx file for %s .." % filepath) - # maketx( - # filepath, - # converted, - # # Include `source-hash` as string metadata - # "--sattrib", - # "sourceHash", - # escape_space(texture_hash), - # colorconvert, - # color_config - # ) - return filepath, COPY, texture_hash From 099dfba8fa19dca4bc1cc9a30632f659854c9300 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Mon, 1 Aug 2022 05:06:58 +0300 Subject: [PATCH 039/898] Fix return bug --- openpype/hosts/maya/plugins/publish/extract_look.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index ecbb0709161..53b6dcbf358 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -622,11 +622,11 @@ def _process_texture(self, filepath, processors, staging, linearize, force): # n colorconvert, color_config) self.log.info("Generating texture file for %s .." % filepath) # noqa - return processed_path + return processed_path, COPY, texture_hash elif processor == MakeRSTexBin: processed_path = processor().process(filepath) self.log.info("Generating texture file for %s .." % filepath) # noqa - return processed_path + return processed_path, COPY, texture_hash return filepath, COPY, texture_hash From 8995dcdff4a9a6c5c951958fb71b99ee93b44029 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Mon, 1 Aug 2022 12:26:44 +0300 Subject: [PATCH 040/898] Check for return value, adjust argument --- .../hosts/maya/plugins/publish/extract_look.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 53b6dcbf358..48af6443264 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- """Maya look extractor.""" from abc import ABCMeta, abstractmethod + import six import os import sys @@ -189,10 +190,11 @@ def process(self, source, destination, *args): # use oiio-optimized settings for tile-size, planarconfig, metadata "--oiio", "--filter lanczos3", + escape_space(source) ] cmd.extend(args) - cmd.extend([escape_space(source), "-o", escape_space(destination)]) + cmd.extend(["-o", escape_space(destination)]) cmd = " ".join(cmd) @@ -620,13 +622,21 @@ def _process_texture(self, filepath, processors, staging, linearize, force): # n "sourceHash", escape_space(texture_hash), # noqa colorconvert, - color_config) + color_config, + ) self.log.info("Generating texture file for %s .." % filepath) # noqa - return processed_path, COPY, texture_hash + self.log.info(converted) + if processed_path: + return processed_path + else: + self.log.info("maketx has returned nothing") elif processor == MakeRSTexBin: processed_path = processor().process(filepath) self.log.info("Generating texture file for %s .." % filepath) # noqa - return processed_path, COPY, texture_hash + if processed_path: + return processed_path + else: + self.log.info("redshift texture converter has returned nothing") # noqa return filepath, COPY, texture_hash From 46411c9723a80a781ec513d6a2cfd175cec44644 Mon Sep 17 00:00:00 2001 From: Simone Barbieri Date: Thu, 4 Aug 2022 11:10:45 +0100 Subject: [PATCH 041/898] Implemented review --- openpype/hosts/blender/api/__init__.py | 5 + openpype/hosts/blender/api/capture.py | 278 ++++++++++++++++ openpype/hosts/blender/api/lib.py | 9 + openpype/hosts/blender/api/plugin.py | 7 +- .../blender/plugins/create/create_review.py | 47 +++ .../blender/plugins/publish/collect_review.py | 64 ++++ .../plugins/publish/extract_playblast.py | 125 +++++++ .../plugins/publish/extract_thumbnail.py | 102 ++++++ .../plugins/publish/integrate_thumbnail.py | 10 + openpype/plugins/publish/extract_review.py | 1 + .../defaults/project_settings/blender.json | 137 ++++++++ .../schema_project_blender.json | 4 + .../schemas/schema_blender_publish.json | 308 ++++++++++++++++++ 13 files changed, 1095 insertions(+), 2 deletions(-) create mode 100644 openpype/hosts/blender/api/capture.py create mode 100644 openpype/hosts/blender/plugins/create/create_review.py create mode 100644 openpype/hosts/blender/plugins/publish/collect_review.py create mode 100644 openpype/hosts/blender/plugins/publish/extract_playblast.py create mode 100644 openpype/hosts/blender/plugins/publish/extract_thumbnail.py create mode 100644 openpype/hosts/blender/plugins/publish/integrate_thumbnail.py create mode 100644 openpype/settings/entities/schemas/projects_schema/schemas/schema_blender_publish.json diff --git a/openpype/hosts/blender/api/__init__.py b/openpype/hosts/blender/api/__init__.py index e017d74d912..75a11affde6 100644 --- a/openpype/hosts/blender/api/__init__.py +++ b/openpype/hosts/blender/api/__init__.py @@ -31,10 +31,13 @@ lsattrs, read, maintained_selection, + maintained_time, get_selection, # unique_name, ) +from .capture import capture + __all__ = [ "install", @@ -56,9 +59,11 @@ # Utility functions "maintained_selection", + "maintained_time", "lsattr", "lsattrs", "read", "get_selection", + "capture", # "unique_name", ] diff --git a/openpype/hosts/blender/api/capture.py b/openpype/hosts/blender/api/capture.py new file mode 100644 index 00000000000..7cf9e52cb61 --- /dev/null +++ b/openpype/hosts/blender/api/capture.py @@ -0,0 +1,278 @@ + +"""Blender Capture +Playblasting with independent viewport, camera and display options +""" +import contextlib +import bpy + +from .lib import maintained_time +from .plugin import deselect_all, create_blender_context + + +def capture( + camera=None, + width=None, + height=None, + filename=None, + start_frame=None, + end_frame=None, + step_frame=None, + sound=None, + isolate=None, + maintain_aspect_ratio=True, + overwrite=False, + image_settings=None, + display_options=None +): + """Playblast in an independent windows + Arguments: + camera (str, optional): Name of camera, defaults to "Camera" + width (int, optional): Width of output in pixels + height (int, optional): Height of output in pixels + filename (str, optional): Name of output file path. Defaults to current + render output path. + start_frame (int, optional): Defaults to current start frame. + end_frame (int, optional): Defaults to current end frame. + step_frame (int, optional): Defaults to 1. + sound (str, optional): Specify the sound node to be used during + playblast. When None (default) no sound will be used. + isolate (list): List of nodes to isolate upon capturing + maintain_aspect_ratio (bool, optional): Modify height in order to + maintain aspect ratio. + overwrite (bool, optional): Whether or not to overwrite if file + already exists. If disabled and file exists and error will be + raised. + image_settings (dict, optional): Supplied image settings for render, + using `ImageSettings` + display_options (dict, optional): Supplied display options for render + """ + + scene = bpy.context.scene + camera = camera or "Camera" + + # Ensure camera exists. + if camera not in scene.objects and camera != "AUTO": + raise RuntimeError("Camera does not exist: {0}".format(camera)) + + # Ensure resolution. + if width and height: + maintain_aspect_ratio = False + width = width or scene.render.resolution_x + height = height or scene.render.resolution_y + if maintain_aspect_ratio: + ratio = scene.render.resolution_x / scene.render.resolution_y + height = round(width / ratio) + + # Get frame range. + if start_frame is None: + start_frame = scene.frame_start + if end_frame is None: + end_frame = scene.frame_end + if step_frame is None: + step_frame = 1 + frame_range = (start_frame, end_frame, step_frame) + + if filename is None: + filename = scene.render.filepath + + render_options = { + "filepath": "{}.".format(filename.rstrip(".")), + "resolution_x": width, + "resolution_y": height, + "use_overwrite": overwrite, + } + + with _independent_window() as window: + + applied_view(window, camera, isolate, options=display_options) + + with contextlib.ExitStack() as stack: + stack.enter_context(maintain_camera(window, camera)) + stack.enter_context(applied_frame_range(window, *frame_range)) + stack.enter_context(applied_render_options(window, render_options)) + stack.enter_context(applied_image_settings(window, image_settings)) + stack.enter_context(maintained_time()) + + bpy.ops.render.opengl( + animation=True, + render_keyed_only=False, + sequencer=False, + write_still=False, + view_context=True + ) + + return filename + + +ImageSettings = { + "file_format": "FFMPEG", + "color_mode": "RGB", + "ffmpeg": { + "format": "QUICKTIME", + "use_autosplit": False, + "codec": "H264", + "constant_rate_factor": "MEDIUM", + "gopsize": 18, + "use_max_b_frames": False, + }, +} + + +def isolate_objects(window, objects): + """Isolate selection""" + deselect_all() + + for obj in objects: + obj.select_set(True) + + context = create_blender_context(selected=objects, window=window) + + bpy.ops.view3d.view_axis(context, type="FRONT") + bpy.ops.view3d.localview(context) + + deselect_all() + + +def _apply_options(entity, options): + for option, value in options.items(): + if isinstance(value, dict): + _apply_options(getattr(entity, option), value) + else: + setattr(entity, option, value) + + +def applied_view(window, camera, isolate=None, options=None): + """Apply view options to window.""" + area = window.screen.areas[0] + space = area.spaces[0] + + area.ui_type = "VIEW_3D" + + meshes = [obj for obj in window.scene.objects if obj.type == "MESH"] + + if camera == "AUTO": + space.region_3d.view_perspective = "ORTHO" + isolate_objects(window, isolate or meshes) + else: + isolate_objects(window, isolate or meshes) + space.camera = window.scene.objects.get(camera) + space.region_3d.view_perspective = "CAMERA" + + if isinstance(options, dict): + _apply_options(space, options) + else: + space.shading.type = "SOLID" + space.shading.color_type = "MATERIAL" + space.show_gizmo = False + space.overlay.show_overlays = False + + +@contextlib.contextmanager +def applied_frame_range(window, start, end, step): + """Context manager for setting frame range.""" + # Store current frame range + current_frame_start = window.scene.frame_start + current_frame_end = window.scene.frame_end + current_frame_step = window.scene.frame_step + # Apply frame range + window.scene.frame_start = start + window.scene.frame_end = end + window.scene.frame_step = step + try: + yield + finally: + # Restore frame range + window.scene.frame_start = current_frame_start + window.scene.frame_end = current_frame_end + window.scene.frame_step = current_frame_step + + +@contextlib.contextmanager +def applied_render_options(window, options): + """Context manager for setting render options.""" + render = window.scene.render + + # Store current settings + original = {} + for opt in options.copy(): + try: + original[opt] = getattr(render, opt) + except ValueError: + options.pop(opt) + + # Apply settings + _apply_options(render, options) + + try: + yield + finally: + # Restore previous settings + _apply_options(render, original) + + +@contextlib.contextmanager +def applied_image_settings(window, options): + """Context manager to override image settings.""" + + options = options or ImageSettings.copy() + ffmpeg = options.pop("ffmpeg", {}) + render = window.scene.render + + # Store current image settings + original = {} + for opt in options.copy(): + try: + original[opt] = getattr(render.image_settings, opt) + except ValueError: + options.pop(opt) + + # Store current ffmpeg settings + original_ffmpeg = {} + for opt in ffmpeg.copy(): + try: + original_ffmpeg[opt] = getattr(render.ffmpeg, opt) + except ValueError: + ffmpeg.pop(opt) + + # Apply image settings + for opt, value in options.items(): + setattr(render.image_settings, opt, value) + + # Apply ffmpeg settings + for opt, value in ffmpeg.items(): + setattr(render.ffmpeg, opt, value) + + try: + yield + finally: + # Restore previous settings + for opt, value in original.items(): + setattr(render.image_settings, opt, value) + for opt, value in original_ffmpeg.items(): + setattr(render.ffmpeg, opt, value) + + +@contextlib.contextmanager +def maintain_camera(window, camera): + """Context manager to override camera.""" + current_camera = window.scene.camera + if camera in window.scene.objects: + window.scene.camera = window.scene.objects.get(camera) + try: + yield + finally: + window.scene.camera = current_camera + + +@contextlib.contextmanager +def _independent_window(): + """Create capture-window context.""" + context = create_blender_context() + current_windows = set(bpy.context.window_manager.windows) + bpy.ops.wm.window_new(context) + window = list(set(bpy.context.window_manager.windows) - current_windows)[0] + context["window"] = window + try: + yield window + finally: + bpy.ops.wm.window_close(context) \ No newline at end of file diff --git a/openpype/hosts/blender/api/lib.py b/openpype/hosts/blender/api/lib.py index 20098c0fe81..ee127ab313b 100644 --- a/openpype/hosts/blender/api/lib.py +++ b/openpype/hosts/blender/api/lib.py @@ -284,3 +284,12 @@ def maintained_selection(): # This could happen if the active node was deleted during the # context. log.exception("Failed to set active object.") + +@contextlib.contextmanager +def maintained_time(): + """Maintain current frame during context.""" + current_time = bpy.context.scene.frame_current + try: + yield + finally: + bpy.context.scene.frame_current = current_time diff --git a/openpype/hosts/blender/api/plugin.py b/openpype/hosts/blender/api/plugin.py index c59be8d7ff9..1274795c6be 100644 --- a/openpype/hosts/blender/api/plugin.py +++ b/openpype/hosts/blender/api/plugin.py @@ -62,7 +62,8 @@ def prepare_data(data, container_name=None): def create_blender_context(active: Optional[bpy.types.Object] = None, - selected: Optional[bpy.types.Object] = None,): + selected: Optional[bpy.types.Object] = None, + window: Optional[bpy.types.Window] = None): """Create a new Blender context. If an object is passed as parameter, it is set as selected and active. """ @@ -72,7 +73,9 @@ def create_blender_context(active: Optional[bpy.types.Object] = None, override_context = bpy.context.copy() - for win in bpy.context.window_manager.windows: + windows = [window] if window else bpy.context.window_manager.windows + + for win in windows: for area in win.screen.areas: if area.type == 'VIEW_3D': for region in area.regions: diff --git a/openpype/hosts/blender/plugins/create/create_review.py b/openpype/hosts/blender/plugins/create/create_review.py new file mode 100644 index 00000000000..bf4ea6a7cd6 --- /dev/null +++ b/openpype/hosts/blender/plugins/create/create_review.py @@ -0,0 +1,47 @@ +"""Create review.""" + +import bpy + +from openpype.pipeline import legacy_io +from openpype.hosts.blender.api import plugin, lib, ops +from openpype.hosts.blender.api.pipeline import AVALON_INSTANCES + + +class CreateReview(plugin.Creator): + """Single baked camera""" + + name = "reviewDefault" + label = "Review" + family = "review" + icon = "video-camera" + + def process(self): + """ Run the creator on Blender main thread""" + mti = ops.MainThreadItem(self._process) + ops.execute_in_main_thread(mti) + + def _process(self): + # Get Instance Container or create it if it does not exist + instances = bpy.data.collections.get(AVALON_INSTANCES) + if not instances: + instances = bpy.data.collections.new(name=AVALON_INSTANCES) + bpy.context.scene.collection.children.link(instances) + + # Create instance object + asset = self.data["asset"] + subset = self.data["subset"] + name = plugin.asset_name(asset, subset) + asset_group = bpy.data.collections.new(name=name) + instances.children.link(asset_group) + self.data['task'] = legacy_io.Session.get('AVALON_TASK') + lib.imprint(asset_group, self.data) + + if (self.options or {}).get("useSelection"): + selected = lib.get_selection() + for obj in selected: + asset_group.objects.link(obj) + elif (self.options or {}).get("asset_group"): + obj = (self.options or {}).get("asset_group") + asset_group.objects.link(obj) + + return asset_group diff --git a/openpype/hosts/blender/plugins/publish/collect_review.py b/openpype/hosts/blender/plugins/publish/collect_review.py new file mode 100644 index 00000000000..09b5558d317 --- /dev/null +++ b/openpype/hosts/blender/plugins/publish/collect_review.py @@ -0,0 +1,64 @@ +import bpy + +import pyblish.api +from openpype.pipeline import legacy_io + + +class CollectReview(pyblish.api.InstancePlugin): + """Collect Review data + + """ + + order = pyblish.api.CollectorOrder + 0.3 + label = "Collect Review Data" + families = ["review"] + + def process(self, instance): + + self.log.debug(f"instance: {instance}") + + # get cameras + cameras = [ + obj + for obj in instance + if isinstance(obj, bpy.types.Object) and obj.type == "CAMERA" + ] + + assert len(cameras) == 1, ( + f"Not a single camera found in extraction: {cameras}" + ) + camera = cameras[0].name + self.log.debug(f"camera: {camera}") + + # get isolate objects list from meshes instance members . + isolate_objects = [ + obj + for obj in instance + if isinstance(obj, bpy.types.Object) and obj.type == "MESH" + ] + + if not instance.data.get("remove"): + + task = legacy_io.Session.get("AVALON_TASK") + + instance.data.update({ + "subset": f"{task}Review", + "review_camera": camera, + "frameStart": instance.context.data["frameStart"], + "frameEnd": instance.context.data["frameEnd"], + "fps": instance.context.data["fps"], + "isolate": isolate_objects, + }) + + self.log.debug(f"instance data: {instance.data}") + + # TODO : Collect audio + audio_tracks = [] + instance.data["audio"] = [] + for track in audio_tracks: + instance.data["audio"].append( + { + "offset": track.offset.get(), + "filename": track.filename.get(), + } + ) \ No newline at end of file diff --git a/openpype/hosts/blender/plugins/publish/extract_playblast.py b/openpype/hosts/blender/plugins/publish/extract_playblast.py new file mode 100644 index 00000000000..d07968d4692 --- /dev/null +++ b/openpype/hosts/blender/plugins/publish/extract_playblast.py @@ -0,0 +1,125 @@ +import os +import clique + +import bpy + +import pyblish.api +import openpype.api +from openpype.hosts.blender.api import capture +from openpype.hosts.blender.api.lib import maintained_time + + +class ExtractPlayblast(openpype.api.Extractor): + """ + Extract viewport playblast. + + Takes review camera and creates review Quicktime video based on viewport + capture. + """ + + label = "Extract Playblast" + hosts = ["blender"] + families = ["review"] + optional = True + order = pyblish.api.ExtractorOrder + 0.01 + + + def process(self, instance): + self.log.info("Extracting capture..") + + self.log.info(instance.data) + print(instance.context.data) + + # get scene fps + fps = instance.data.get("fps") + if fps is None: + fps = bpy.context.scene.render.fps + instance.data["fps"] = fps + + self.log.info(f"fps: {fps}") + + # If start and end frames cannot be determined, + # get them from Blender timeline. + start = instance.data.get("frameStart", bpy.context.scene.frame_start) + end = instance.data.get("frameEnd", bpy.context.scene.frame_end) + + self.log.info(f"start: {start}, end: {end}") + assert end > start, "Invalid time range !" + + # get cameras + camera = instance.data("review_camera", None) + + # get isolate objects list + isolate = instance.data("isolate", None) + + # get ouput path + stagingdir = self.staging_dir(instance) + filename = instance.name + path = os.path.join(stagingdir, filename) + + self.log.info(f"Outputting images to {path}") + + project_settings = instance.context.data["project_settings"]["blender"] + presets = project_settings["publish"]["ExtractPlayblast"]["presets"] + preset = presets.get("default") + preset.update({ + "camera": camera, + "start_frame": start, + "end_frame": end, + "filename": path, + "overwrite": True, + "isolate": isolate, + }) + preset.setdefault( + "image_settings", + { + "file_format": "PNG", + "color_mode": "RGB", + "color_depth": "8", + "compression": 15, + }, + ) + + with maintained_time(): + path = capture(**preset) + + self.log.debug(f"playblast path {path}") + + collected_files = os.listdir(stagingdir) + collections, remainder = clique.assemble( + collected_files, + patterns=[f"{filename}\\.{clique.DIGITS_PATTERN}\\.png$"], + ) + + if len(collections) > 1: + raise RuntimeError( + f"More than one collection found in stagingdir: {stagingdir}" + ) + elif len(collections) == 0: + raise RuntimeError( + f"No collection found in stagingdir: {stagingdir}" + ) + + frame_collection = collections[0] + + self.log.info(f"We found collection of interest {frame_collection}") + + instance.data.setdefault("representations", []) + + tags = ["review"] + if not instance.data.get("keepImages"): + tags.append("delete") + + representation = { + "name": "png", + "ext": "png", + "files": list(frame_collection), + "stagingDir": stagingdir, + "frameStart": start, + "frameEnd": end, + "fps": fps, + "preview": True, + "tags": tags, + "camera_name": camera + } + instance.data["representations"].append(representation) \ No newline at end of file diff --git a/openpype/hosts/blender/plugins/publish/extract_thumbnail.py b/openpype/hosts/blender/plugins/publish/extract_thumbnail.py new file mode 100644 index 00000000000..3fabdf61e08 --- /dev/null +++ b/openpype/hosts/blender/plugins/publish/extract_thumbnail.py @@ -0,0 +1,102 @@ +import os +import glob + +import pyblish.api +import openpype.api +from openpype.hosts.blender.api import capture +from openpype.hosts.blender.api.lib import maintained_time + +import bpy + + +class ExtractThumbnail(openpype.api.Extractor): + """Extract viewport thumbnail. + + Takes review camera and creates a thumbnail based on viewport + capture. + + """ + + label = "Extract Thumbnail" + hosts = ["blender"] + families = ["review"] + order = pyblish.api.ExtractorOrder + 0.01 + + def process(self, instance): + self.log.info("Extracting capture..") + + stagingdir = self.staging_dir(instance) + filename = instance.name + path = os.path.join(stagingdir, filename) + + self.log.info(f"Outputting images to {path}") + + camera = instance.data.get("review_camera", "AUTO") + start = instance.data.get("frameStart", bpy.context.scene.frame_start) + family = instance.data.get("family") + isolate = instance.data("isolate", None) + + project_settings = instance.context.data["project_settings"]["blender"] + extractor_settings = project_settings["publish"]["ExtractThumbnail"] + presets = extractor_settings.get("presets") + + preset = presets.get(family, {}) + + preset.update({ + "camera": camera, + "start_frame": start, + "end_frame": start, + "filename": path, + "overwrite": True, + "isolate": isolate, + }) + preset.setdefault( + "image_settings", + { + "file_format": "JPEG", + "color_mode": "RGB", + "quality": 100, + }, + ) + + with maintained_time(): + path = capture(**preset) + + thumbnail = os.path.basename(self._fix_output_path(path)) + + self.log.info(f"thumbnail: {thumbnail}") + + instance.data.setdefault("representations", []) + + representation = { + "name": "thumbnail", + "ext": "jpg", + "files": thumbnail, + "stagingDir": stagingdir, + "thumbnail": True + } + instance.data["representations"].append(representation) + + def _fix_output_path(self, filepath): + """"Workaround to return correct filepath. + + To workaround this we just glob.glob() for any file extensions and + assume the latest modified file is the correct file and return it. + + """ + # Catch cancelled playblast + if filepath is None: + self.log.warning( + "Playblast did not result in output path. " + "Playblast is probably interrupted." + ) + return None + + if not os.path.exists(filepath): + files = glob.glob(f"{filepath}.*.jpg") + + if not files: + raise RuntimeError(f"Couldn't find playblast from: {filepath}") + filepath = max(files, key=os.path.getmtime) + + return filepath \ No newline at end of file diff --git a/openpype/hosts/blender/plugins/publish/integrate_thumbnail.py b/openpype/hosts/blender/plugins/publish/integrate_thumbnail.py new file mode 100644 index 00000000000..489db673dea --- /dev/null +++ b/openpype/hosts/blender/plugins/publish/integrate_thumbnail.py @@ -0,0 +1,10 @@ +import pyblish.api +from openpype.plugins.publish import integrate_thumbnail + + +class IntegrateThumbnails(integrate_thumbnail.IntegrateThumbnails): + """Integrate Thumbnails.""" + + label = "Integrate Thumbnails" + order = pyblish.api.IntegratorOrder + 0.01 + families = ["review"] diff --git a/openpype/plugins/publish/extract_review.py b/openpype/plugins/publish/extract_review.py index 533a87acb40..5068b0261ed 100644 --- a/openpype/plugins/publish/extract_review.py +++ b/openpype/plugins/publish/extract_review.py @@ -41,6 +41,7 @@ class ExtractReview(pyblish.api.InstancePlugin): hosts = [ "nuke", "maya", + "blender", "shell", "hiero", "premiere", diff --git a/openpype/settings/defaults/project_settings/blender.json b/openpype/settings/defaults/project_settings/blender.json index a7262dcb5d7..e3be0b50ee0 100644 --- a/openpype/settings/defaults/project_settings/blender.json +++ b/openpype/settings/defaults/project_settings/blender.json @@ -2,5 +2,142 @@ "workfile_builder": { "create_first_version": false, "custom_templates": [] + }, + "publish": { + "ValidateLinkedVersion": { + "enabled": true, + "optional": true, + "active": true + }, + "ValidateLinkedData": { + "enabled": true, + "optional": true, + "active": true + }, + "ExtractBlend": { + "enabled": true, + "optional": true, + "active": true, + "pack_images": true + }, + "ExtractBlendAnimation": { + "enabled": true, + "optional": true, + "active": true + }, + "ExtractCamera": { + "enabled": true, + "optional": true, + "active": true + }, + "ExtractFBX": { + "enabled": true, + "optional": true, + "active": true, + "scale_length": 0 + }, + "ExtractAnimationFBX": { + "enabled": true, + "optional": true, + "active": true + }, + "ExtractABC": { + "enabled": true, + "optional": true, + "active": true + }, + "ExtractLayout": { + "enabled": true, + "optional": true, + "active": true + }, + "ExtractThumbnail": { + "enabled": true, + "optional": true, + "active": true, + "presets": { + "model": { + "image_settings": { + "file_format": "JPEG", + "color_mode": "RGB", + "quality": 100 + }, + "display_options": { + "shading": { + "light": "STUDIO", + "studio_light": "Default", + "type": "SOLID", + "color_type": "OBJECT", + "show_xray": false, + "show_shadows": false, + "show_cavity": true + }, + "overlay": { + "show_overlays": false + } + } + }, + "rig": { + "image_settings": { + "file_format": "JPEG", + "color_mode": "RGB", + "quality": 100 + }, + "display_options": { + "shading": { + "light": "STUDIO", + "studio_light": "Default", + "type": "SOLID", + "color_type": "OBJECT", + "show_xray": true, + "show_shadows": false, + "show_cavity": false + }, + "overlay": { + "show_overlays": true, + "show_ortho_grid": false, + "show_floor": false, + "show_axis_x": false, + "show_axis_y": false, + "show_axis_z": false, + "show_text": false, + "show_stats": false, + "show_cursor": false, + "show_annotation": false, + "show_extras": false, + "show_relationship_lines": false, + "show_outline_selected": false, + "show_motion_paths": false, + "show_object_origins": false, + "show_bones": true + } + } + } + } + }, + "ExtractPlayblast": { + "enabled": true, + "optional": true, + "active": true, + "presets": { + "default": { + "image_settings": { + "file_format": "PNG", + "color_mode": "RGB", + "color_depth": "8", + "compression": 15 + }, + "display_options": { + "shading": { + "type": "MATERIAL", + "render_pass": "COMBINED" + }, + "overlay": { + "show_overlays": false + } + } + } + } + } } } \ No newline at end of file diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_blender.json b/openpype/settings/entities/schemas/projects_schema/schema_project_blender.json index af09329a034..4c72ebda2fa 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_blender.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_blender.json @@ -12,6 +12,10 @@ "workfile_builder/builder_on_start", "workfile_builder/profiles" ] + }, + { + "type": "schema", + "name": "schema_blender_publish" } ] } diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_blender_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_blender_publish.json new file mode 100644 index 00000000000..a634b6dabe2 --- /dev/null +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_blender_publish.json @@ -0,0 +1,308 @@ +{ + "type": "dict", + "collapsible": true, + "key": "publish", + "label": "Publish plugins", + "children": [ + { + "type": "label", + "label": "Validators" + }, + { + "type": "dict", + "collapsible": true, + "key": "ValidateLinkedVersion", + "label": "Validate Linked Version", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ValidateLinkedData", + "label": "Validate Linked Data", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + } + ] + }, + { + "type": "splitter" + }, + { + "type": "label", + "label": "Extractors" + }, + { + "type": "dict", + "collapsible": true, + "key": "ExtractBlend", + "label": "Extract Blend", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + }, + { + "type": "boolean", + "key": "pack_images", + "label": "Pack Images" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ExtractBlendAnimation", + "label": "Extract Blend Animation", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ExtractCamera", + "label": "Extract Camera as FBX", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ExtractFBX", + "label": "Extract FBX (model and rig)", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + }, + { + "type": "number", + "key": "scale_length", + "label": "Scale length", + "decimal": 3, + "minimum": 0, + "maximum": 1000 + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ExtractAnimationFBX", + "label": "Extract Animation FBX", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ExtractABC", + "label": "Extract ABC (model and pointcache)", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ExtractLayout", + "label": "Extract Layout as JSON", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ExtractThumbnail", + "label": "ExtractThumbnail", + "checkbox_key": "enabled", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + }, + { + "type": "raw-json", + "key": "presets", + "label": "Presets" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ExtractPlayblast", + "label": "ExtractPlayblast", + "checkbox_key": "enabled", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + }, + { + "type": "raw-json", + "key": "presets", + "label": "Presets" + } + ] + } + ] +} \ No newline at end of file From 13997f4b4cc55c2168c360870593ea561daf1eeb Mon Sep 17 00:00:00 2001 From: Simone Barbieri Date: Thu, 4 Aug 2022 12:22:44 +0100 Subject: [PATCH 042/898] Removed thumbnail integrator --- .../blender/plugins/publish/integrate_thumbnail.py | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 openpype/hosts/blender/plugins/publish/integrate_thumbnail.py diff --git a/openpype/hosts/blender/plugins/publish/integrate_thumbnail.py b/openpype/hosts/blender/plugins/publish/integrate_thumbnail.py deleted file mode 100644 index 489db673dea..00000000000 --- a/openpype/hosts/blender/plugins/publish/integrate_thumbnail.py +++ /dev/null @@ -1,10 +0,0 @@ -import pyblish.api -from openpype.plugins.publish import integrate_thumbnail - - -class IntegrateThumbnails(integrate_thumbnail.IntegrateThumbnails): - """Integrate Thumbnails.""" - - label = "Integrate Thumbnails" - order = pyblish.api.IntegratorOrder + 0.01 - families = ["review"] From 3cd7fd503c0cb94ef3f4da86a3c465ff6bc26cb1 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Mon, 15 Aug 2022 04:23:24 +0300 Subject: [PATCH 043/898] Fix assignment bug, remove unnecessary class sugar --- openpype/hosts/maya/plugins/publish/extract_look.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 48af6443264..c092e2ac251 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -94,7 +94,7 @@ def find_paths_by_hash(texture_hash): @six.add_metaclass(ABCMeta) class TextureProcessor: - @abstractmethod + def __init__(self): pass @@ -106,7 +106,7 @@ def process(self, filepath): class MakeRSTexBin(TextureProcessor): def __init__(self): - super(TextureProcessor, self).__init__() + super(MakeRSTexBin, self).__init__() def process(self, source, *args): """Make `.rstexbin` using `redshiftTextureProcessor` @@ -152,7 +152,7 @@ def process(self, source, *args): class MakeTX(TextureProcessor): def __init__(self): - super(TextureProcessor, self).__init__() + super(MakeTX, self).__init__() def process(self, source, destination, *args): """Make `.tx` using `maketx` with some default settings. @@ -627,18 +627,18 @@ def _process_texture(self, filepath, processors, staging, linearize, force): # n self.log.info("Generating texture file for %s .." % filepath) # noqa self.log.info(converted) if processed_path: - return processed_path + return processed_path, COPY, texture_hash else: self.log.info("maketx has returned nothing") elif processor == MakeRSTexBin: processed_path = processor().process(filepath) self.log.info("Generating texture file for %s .." % filepath) # noqa if processed_path: - return processed_path + return processed_path, COPY, texture_hash else: self.log.info("redshift texture converter has returned nothing") # noqa - return filepath, COPY, texture_hash + return processed_path, COPY, texture_hash class ExtractModelRenderSets(ExtractLook): From 9ec42cb4376e0e14eb990cfd22c6a9f1c38e0575 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 23 Aug 2022 13:05:37 +0300 Subject: [PATCH 044/898] Fix bugs --- .../hosts/maya/plugins/publish/extract_look.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 52751eea813..19765d43966 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -125,7 +125,7 @@ def process(self, source, *args): if "REDSHIFT_COREDATAPATH" not in os.environ: raise RuntimeError("Must have Redshift available.") - texture_processor_path = get_redshift_tool("TextureProcessor") + texture_processor_path = get_redshift_tool("redshiftTextureProcessor") cmd = [ texture_processor_path, @@ -142,14 +142,14 @@ def process(self, source, *args): if sys.platform == "win32": kwargs["creationflags"] = CREATE_NO_WINDOW try: - processed_filepath = subprocess.check_output(**kwargs) + subprocess.check_output(**kwargs) except subprocess.CalledProcessError as exc: print(exc) import traceback traceback.print_exc() raise - return processed_filepath + return source class MakeTX(TextureProcessor): @@ -206,7 +206,7 @@ def process(self, source, destination, *args): if sys.platform == "win32": kwargs["creationflags"] = CREATE_NO_WINDOW try: - processed_filepath = subprocess.check_output(**kwargs) + subprocess.check_output(**kwargs) except subprocess.CalledProcessError as exc: print(exc) import traceback @@ -216,7 +216,7 @@ def process(self, source, destination, *args): print(exc.output) raise - return processed_filepath + return destination @contextlib.contextmanager @@ -629,7 +629,7 @@ def _process_texture(self, filepath, processors, staging, linearize, force): # n if bool(processors): for processor in processors: - if processor == MakeTX: + if processor is MakeTX: processed_path = processor().process(filepath, converted, "--sattrib", @@ -644,7 +644,7 @@ def _process_texture(self, filepath, processors, staging, linearize, force): # n return processed_path, COPY, texture_hash else: self.log.info("maketx has returned nothing") - elif processor == MakeRSTexBin: + elif processor is MakeRSTexBin: processed_path = processor().process(filepath) self.log.info("Generating texture file for %s .." % filepath) # noqa if processed_path: From cc62035e1be2e02d38c3e1972bd37f458f70eb83 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 23 Aug 2022 13:22:59 +0300 Subject: [PATCH 045/898] Fix destination finding for copying resrouce. --- .../maya/plugins/publish/extract_look.py | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 19765d43966..7f79867cea5 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -483,9 +483,15 @@ def process_resources(self, instance, staging_dir): linearize=linearize, force=force_copy ) - destination = self.resource_destination(instance, - source, - do_maketx) + for processor in processors: + if processor is MakeTX: + destination = self.resource_destination( + instance, source, MakeTX + ) + elif processor is MakeRSTexBin: + destination = self.resource_destination( + instance, source, MakeRSTexBin + ) # Force copy is specified. if force_copy: @@ -512,9 +518,15 @@ def process_resources(self, instance, staging_dir): if source not in destinations: # Cache destination as source resource might be included # multiple times - destinations[source] = self.resource_destination( - instance, source, do_maketx - ) + for processor in processors: + if processor is MakeTX: + destinations[source] = self.resource_destination( + instance, source, MakeTX + ) + elif processor is MakeRSTexBin: + destinations[source] = self.resource_destination( + instance, source, MakeRSTexBin + ) # Preserve color space values (force value after filepath change) # This will also trigger in the same order at end of context to @@ -555,7 +567,7 @@ def process_resources(self, instance, staging_dir): "attrRemap": remap, } - def resource_destination(self, instance, filepath, do_maketx): + def resource_destination(self, instance, filepath, processor): """Get resource destination path. This is utility function to change path if resource file name is @@ -564,7 +576,7 @@ def resource_destination(self, instance, filepath, do_maketx): Args: instance: Current Instance. filepath (str): Resource path - do_maketx (bool): Flag if resource is processed by `maketx`. + processor: Texture processor converting resource. Returns: str: Path to resource file @@ -576,8 +588,10 @@ def resource_destination(self, instance, filepath, do_maketx): basename, ext = os.path.splitext(os.path.basename(filepath)) # If `maketx` then the texture will always end with .tx - if do_maketx: + if processor == MakeTX: ext = ".tx" + elif processor == MakeRSTexBin: + ext = ".rstexbin" return os.path.join( resources_dir, basename + ext From ad8177cee3c7ee6241b995b781b9dc93fead19b1 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 23 Aug 2022 16:10:44 +0300 Subject: [PATCH 046/898] Removed submodule vendor/configs/OpenColorIO-Configs --- vendor/configs/OpenColorIO-Configs | 1 - 1 file changed, 1 deletion(-) delete mode 160000 vendor/configs/OpenColorIO-Configs diff --git a/vendor/configs/OpenColorIO-Configs b/vendor/configs/OpenColorIO-Configs deleted file mode 160000 index 0bb079c08be..00000000000 --- a/vendor/configs/OpenColorIO-Configs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0bb079c08be410030669cbf5f19ff869b88af953 From f4c2f268642db18eb111410a2867832f52dc1c19 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 13 Sep 2022 18:00:04 +0200 Subject: [PATCH 047/898] Implement draft for opengl reviews from Houdini --- openpype/hosts/houdini/api/lib.py | 2 + .../houdini/plugins/create/create_review.py | 57 +++++++++++++++++++ .../houdini/plugins/publish/collect_frames.py | 2 +- .../houdini/plugins/publish/extract_review.py | 52 +++++++++++++++++ 4 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 openpype/hosts/houdini/plugins/create/create_review.py create mode 100644 openpype/hosts/houdini/plugins/publish/extract_review.py diff --git a/openpype/hosts/houdini/api/lib.py b/openpype/hosts/houdini/api/lib.py index c8a7f92bb99..aa7fb66aeab 100644 --- a/openpype/hosts/houdini/api/lib.py +++ b/openpype/hosts/houdini/api/lib.py @@ -125,6 +125,8 @@ def get_output_parameter(node): return node.parm("filename") elif node_type == "comp": return node.parm("copoutput") + elif node_type == "opengl": + return node.parm("picture") elif node_type == "arnold": if node.evalParm("ar_ass_export_enable"): return node.parm("ar_ass_file") diff --git a/openpype/hosts/houdini/plugins/create/create_review.py b/openpype/hosts/houdini/plugins/create/create_review.py new file mode 100644 index 00000000000..3d0f33ad517 --- /dev/null +++ b/openpype/hosts/houdini/plugins/create/create_review.py @@ -0,0 +1,57 @@ +from openpype.hosts.houdini.api import plugin + + +class CreateReview(plugin.Creator): + """Review with OpenGL ROP""" + + label = "Review" + family = "review" + icon = "video-camera" + + def __init__(self, *args, **kwargs): + super(CreateReview, self).__init__(*args, **kwargs) + + # Remove the active, we are checking the bypass flag of the nodes + self.data.pop("active", None) + + self.data.update({"node_type": "opengl"}) + + def _process(self, instance): + """Creator main entry point. + + Args: + instance (hou.Node): Created Houdini instance. + + """ + import hou + + frame_range = hou.playbar.frameRange() + + parms = { + "picture": "$HIP/pyblish/{0}/{0}.$F4.png".format(self.name), + # Render frame range + "trange": 1, + + # Unlike many other ROP nodes the opengl node does not default + # to expression of $FSTART and $FEND so we preserve that behavior + # but do set the range to the frame range of the playbar + "f1": frame_range[0], + "f2": frame_range[1] + } + + if self.nodes: + # todo: allow only object paths? + node_paths = " ".join(node.path() for node in self.nodes) + parms.update({"scenepath": node_paths}) + + instance.setParms(parms) + + # Lock any parameters in this list + to_lock = [ + # Lock some Avalon attributes + "family", + "id", + ] + for name in to_lock: + parm = instance.parm(name) + parm.lock(True) diff --git a/openpype/hosts/houdini/plugins/publish/collect_frames.py b/openpype/hosts/houdini/plugins/publish/collect_frames.py index 9bd43d8a096..4ceeac3a623 100644 --- a/openpype/hosts/houdini/plugins/publish/collect_frames.py +++ b/openpype/hosts/houdini/plugins/publish/collect_frames.py @@ -20,7 +20,7 @@ class CollectFrames(pyblish.api.InstancePlugin): order = pyblish.api.CollectorOrder label = "Collect Frames" - families = ["vdbcache", "imagesequence", "ass", "redshiftproxy"] + families = ["vdbcache", "imagesequence", "ass", "redshiftproxy", "review"] def process(self, instance): diff --git a/openpype/hosts/houdini/plugins/publish/extract_review.py b/openpype/hosts/houdini/plugins/publish/extract_review.py new file mode 100644 index 00000000000..18b2765b32d --- /dev/null +++ b/openpype/hosts/houdini/plugins/publish/extract_review.py @@ -0,0 +1,52 @@ +import os + +import pyblish.api +import openpype.api +from openpype.hosts.houdini.api.lib import render_rop + + +class ExtractOpenGL(openpype.api.Extractor): + + order = pyblish.api.ExtractorOrder + label = "Extract OpenGL (Review)" + families = ["review"] + hosts = ["houdini"] + optional = True + + def process(self, instance): + + ropnode = instance[0] + + # Get the filename from the filename parameter + # `.evalParm(parameter)` will make sure all tokens are resolved + output = ropnode.evalParm("picture") + staging_dir = os.path.dirname(output) + instance.data["stagingDir"] = staging_dir + file_name = os.path.basename(output) + + # We run the render + self.log.info("Extracting '%s' to '%s'" % (file_name, staging_dir)) + render_rop(ropnode) + + # Unfortunately user interrupting the extraction does not raise an + # error and thus still continues to the integrator. To capture that + # we make sure all files exist + files = instance.data["frames"] + missing = [fname for fname in files + if not os.path.exists(os.path.join(staging_dir, fname))] + if missing: + raise RuntimeError("Failed to complete review extraction. " + "Missing output files: {}".format(missing)) + + representation = { + "name": "png", + "ext": "png", + "files": files, + "stagingDir": staging_dir, + "frameStart": instance.data["frameStart"], + "frameEnd": instance.data["frameEnd"], + } + + if "representations" not in instance.data: + instance.data["representations"] = [] + instance.data["representations"].append(representation) From 1f05d5b532e36c734db9a820bbb5fc6c2d37d8cc Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 13 Sep 2022 18:07:09 +0200 Subject: [PATCH 048/898] Add houdini to ExtractReview --- openpype/plugins/publish/extract_review.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/plugins/publish/extract_review.py b/openpype/plugins/publish/extract_review.py index 27117510b2f..7daaeef0220 100644 --- a/openpype/plugins/publish/extract_review.py +++ b/openpype/plugins/publish/extract_review.py @@ -41,6 +41,7 @@ class ExtractReview(pyblish.api.InstancePlugin): hosts = [ "nuke", "maya", + "houdini", "shell", "hiero", "premiere", From a2f077555a403af8d5ef5a6b1fd29d3db290f655 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 13 Sep 2022 18:10:54 +0200 Subject: [PATCH 049/898] Add review tag to representation --- openpype/hosts/houdini/plugins/publish/extract_review.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/houdini/plugins/publish/extract_review.py b/openpype/hosts/houdini/plugins/publish/extract_review.py index 18b2765b32d..3bf4e39aeb9 100644 --- a/openpype/hosts/houdini/plugins/publish/extract_review.py +++ b/openpype/hosts/houdini/plugins/publish/extract_review.py @@ -45,6 +45,7 @@ def process(self, instance): "stagingDir": staging_dir, "frameStart": instance.data["frameStart"], "frameEnd": instance.data["frameEnd"], + "tags": ["review"] } if "representations" not in instance.data: From 79812118215b11280dac110f5ab2736591e6c820 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 13 Sep 2022 22:35:05 +0200 Subject: [PATCH 050/898] Set resolution on OpenGL rop node instead of inheriting from camera node --- .../houdini/plugins/create/create_review.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/houdini/plugins/create/create_review.py b/openpype/hosts/houdini/plugins/create/create_review.py index 3d0f33ad517..f24fa7e1cd1 100644 --- a/openpype/hosts/houdini/plugins/create/create_review.py +++ b/openpype/hosts/houdini/plugins/create/create_review.py @@ -8,6 +8,13 @@ class CreateReview(plugin.Creator): family = "review" icon = "video-camera" + # Default settings for the ROP + # todo: expose in OpenPype settings? + override_resolution = True + width = 1280 + height = 720 + aspect = 1.0 + def __init__(self, *args, **kwargs): super(CreateReview, self).__init__(*args, **kwargs) @@ -36,9 +43,18 @@ def _process(self, instance): # to expression of $FSTART and $FEND so we preserve that behavior # but do set the range to the frame range of the playbar "f1": frame_range[0], - "f2": frame_range[1] + "f2": frame_range[1], } + if self.override_resolution: + # Override resolution + parms.update({ + "tres": True, # Override Camera Resolution + "res0": self.width, + "res1": self.height, + "aspect": self.aspect + }) + if self.nodes: # todo: allow only object paths? node_paths = " ".join(node.path() for node in self.nodes) From 4cb8276287de0dd083ad1e48cb0e8dc98a6ae3a9 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 13 Sep 2022 22:39:01 +0200 Subject: [PATCH 051/898] Fix parm names --- openpype/hosts/houdini/plugins/create/create_review.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/houdini/plugins/create/create_review.py b/openpype/hosts/houdini/plugins/create/create_review.py index f24fa7e1cd1..36d87ba8dee 100644 --- a/openpype/hosts/houdini/plugins/create/create_review.py +++ b/openpype/hosts/houdini/plugins/create/create_review.py @@ -50,8 +50,8 @@ def _process(self, instance): # Override resolution parms.update({ "tres": True, # Override Camera Resolution - "res0": self.width, - "res1": self.height, + "res1": self.width, + "res2": self.height, "aspect": self.aspect }) From c687fe0b818a3bf04da1f3302485e998727ba37c Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 15 Sep 2022 00:29:30 +0200 Subject: [PATCH 052/898] Relabel to Extract OpenGL to avoid confusion with global Extract Review plugin --- .../plugins/publish/{extract_review.py => extract_opengl.py} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename openpype/hosts/houdini/plugins/publish/{extract_review.py => extract_opengl.py} (97%) diff --git a/openpype/hosts/houdini/plugins/publish/extract_review.py b/openpype/hosts/houdini/plugins/publish/extract_opengl.py similarity index 97% rename from openpype/hosts/houdini/plugins/publish/extract_review.py rename to openpype/hosts/houdini/plugins/publish/extract_opengl.py index 3bf4e39aeb9..f99c9876342 100644 --- a/openpype/hosts/houdini/plugins/publish/extract_review.py +++ b/openpype/hosts/houdini/plugins/publish/extract_opengl.py @@ -8,7 +8,7 @@ class ExtractOpenGL(openpype.api.Extractor): order = pyblish.api.ExtractorOrder - label = "Extract OpenGL (Review)" + label = "Extract OpenGL" families = ["review"] hosts = ["houdini"] optional = True From 937d0c5833ff41e57ae9deafede32f1aac55d42a Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 15 Sep 2022 00:29:39 +0200 Subject: [PATCH 053/898] Add houdini --- openpype/plugins/publish/extract_burnin.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/plugins/publish/extract_burnin.py b/openpype/plugins/publish/extract_burnin.py index 4179199317e..5a5fda38cd7 100644 --- a/openpype/plugins/publish/extract_burnin.py +++ b/openpype/plugins/publish/extract_burnin.py @@ -50,7 +50,8 @@ class ExtractBurnin(publish.Extractor): "webpublisher", "aftereffects", "photoshop", - "flame" + "flame", + "houdini" # "resolve" ] optional = True From 2ace936a951c6562145b4dd359e104eca629bd05 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 20 Sep 2022 23:32:13 +0200 Subject: [PATCH 054/898] Draft to refactor fusion to new publisher and use as FusionHost --- openpype/hosts/fusion/api/__init__.py | 27 +-- openpype/hosts/fusion/api/menu.py | 2 +- openpype/hosts/fusion/api/pipeline.py | 190 ++++++++++++------ openpype/hosts/fusion/api/workio.py | 45 ----- .../deploy/MenuScripts/openpype_menu.py | 4 +- .../fusion/plugins/create/create_exr_saver.py | 42 +++- 6 files changed, 167 insertions(+), 143 deletions(-) delete mode 100644 openpype/hosts/fusion/api/workio.py diff --git a/openpype/hosts/fusion/api/__init__.py b/openpype/hosts/fusion/api/__init__.py index ed70dbca508..495fe286d58 100644 --- a/openpype/hosts/fusion/api/__init__.py +++ b/openpype/hosts/fusion/api/__init__.py @@ -1,20 +1,11 @@ from .pipeline import ( - install, - uninstall, - + FusionHost, ls, imprint_container, - parse_container -) - -from .workio import ( - open_file, - save_file, - current_file, - has_unsaved_changes, - file_extensions, - work_root + parse_container, + list_instances, + remove_instance ) from .lib import ( @@ -30,21 +21,11 @@ __all__ = [ # pipeline - "install", - "uninstall", "ls", "imprint_container", "parse_container", - # workio - "open_file", - "save_file", - "current_file", - "has_unsaved_changes", - "file_extensions", - "work_root", - # lib "maintained_selection", "update_frame_range", diff --git a/openpype/hosts/fusion/api/menu.py b/openpype/hosts/fusion/api/menu.py index 7a6293807f2..4e415cafbaf 100644 --- a/openpype/hosts/fusion/api/menu.py +++ b/openpype/hosts/fusion/api/menu.py @@ -144,7 +144,7 @@ def on_create_clicked(self): host_tools.show_creator() def on_publish_clicked(self): - host_tools.show_publish() + host_tools.show_publisher() def on_load_clicked(self): host_tools.show_loader(use_context=True) diff --git a/openpype/hosts/fusion/api/pipeline.py b/openpype/hosts/fusion/api/pipeline.py index c92d072ef70..b73759fee0c 100644 --- a/openpype/hosts/fusion/api/pipeline.py +++ b/openpype/hosts/fusion/api/pipeline.py @@ -3,6 +3,7 @@ """ import os import logging +import contextlib import pyblish.api @@ -14,15 +15,14 @@ register_loader_plugin_path, register_creator_plugin_path, register_inventory_action_path, - deregister_loader_plugin_path, - deregister_creator_plugin_path, - deregister_inventory_action_path, AVALON_CONTAINER_ID, ) from openpype.pipeline.load import any_outdated_containers from openpype.hosts.fusion import FUSION_HOST_DIR +from openpype.host import HostBase, IWorkfileHost, ILoadHost, INewPublisher from openpype.tools.utils import host_tools + from .lib import ( get_current_comp, comp_lock_and_undo_chunk, @@ -47,71 +47,99 @@ def emit(self, record): comp.Print(entry) -def install(): - """Install fusion-specific functionality of OpenPype. +class FusionHost(HostBase, IWorkfileHost, ILoadHost, INewPublisher): + name = "fusion" - This is where you install menus and register families, data - and loaders into fusion. + def install(self): + """Install fusion-specific functionality of OpenPype. - It is called automatically when installing via - `openpype.pipeline.install_host(openpype.hosts.fusion.api)` + This is where you install menus and register families, data + and loaders into fusion. - See the Maya equivalent for inspiration on how to implement this. + It is called automatically when installing via + `openpype.pipeline.install_host(openpype.hosts.fusion.api)` - """ - # Remove all handlers associated with the root logger object, because - # that one always logs as "warnings" incorrectly. - for handler in logging.root.handlers[:]: - logging.root.removeHandler(handler) - - # Attach default logging handler that prints to active comp - logger = logging.getLogger() - formatter = logging.Formatter(fmt="%(message)s\n") - handler = CompLogHandler() - handler.setFormatter(formatter) - logger.addHandler(handler) - logger.setLevel(logging.DEBUG) - - pyblish.api.register_host("fusion") - pyblish.api.register_plugin_path(PUBLISH_PATH) - log.info("Registering Fusion plug-ins..") - - register_loader_plugin_path(LOAD_PATH) - register_creator_plugin_path(CREATE_PATH) - register_inventory_action_path(INVENTORY_PATH) - - pyblish.api.register_callback( - "instanceToggled", on_pyblish_instance_toggled - ) - - # Fusion integration currently does not attach to direct callbacks of - # the application. So we use workfile callbacks to allow similar behavior - # on save and open - register_event_callback("workfile.open.after", on_after_open) - - -def uninstall(): - """Uninstall all that was installed - - This is where you undo everything that was done in `install()`. - That means, removing menus, deregistering families and data - and everything. It should be as though `install()` was never run, - because odds are calling this function means the user is interested - in re-installing shortly afterwards. If, for example, he has been - modifying the menu or registered families. + See the Maya equivalent for inspiration on how to implement this. - """ - pyblish.api.deregister_host("fusion") - pyblish.api.deregister_plugin_path(PUBLISH_PATH) - log.info("Deregistering Fusion plug-ins..") + """ + # Remove all handlers associated with the root logger object, because + # that one always logs as "warnings" incorrectly. + for handler in logging.root.handlers[:]: + logging.root.removeHandler(handler) + + # Attach default logging handler that prints to active comp + logger = logging.getLogger() + formatter = logging.Formatter(fmt="%(message)s\n") + handler = CompLogHandler() + handler.setFormatter(formatter) + logger.addHandler(handler) + logger.setLevel(logging.DEBUG) + + pyblish.api.register_host("fusion") + pyblish.api.register_plugin_path(PUBLISH_PATH) + log.info("Registering Fusion plug-ins..") + + register_loader_plugin_path(LOAD_PATH) + register_creator_plugin_path(CREATE_PATH) + register_inventory_action_path(INVENTORY_PATH) + + pyblish.api.register_callback("instanceToggled", + on_pyblish_instance_toggled) + + # Fusion integration currently does not attach to direct callbacks of + # the application. So we use workfile callbacks to allow similar + # behavior on save and open + register_event_callback("workfile.open.after", on_after_open) + + # region workfile io api + def has_unsaved_changes(self): + comp = get_current_comp() + return comp.GetAttrs()["COMPB_Modified"] + + def get_workfile_extensions(self): + return [".comp"] + + def save_workfile(self, dst_path=None): + comp = get_current_comp() + comp.Save(dst_path) + + def open_workfile(self, filepath): + # Hack to get fusion, see + # openpype.hosts.fusion.api.pipeline.get_current_comp() + fusion = getattr(sys.modules["__main__"], "fusion", None) + + return fusion.LoadComp(filepath) + + def get_current_workfile(self): + comp = get_current_comp() + current_filepath = comp.GetAttrs()["COMPS_FileName"] + if not current_filepath: + return None + + return current_filepath + + def work_root(self, session): + work_dir = session["AVALON_WORKDIR"] + scene_dir = session.get("AVALON_SCENEDIR") + if scene_dir: + return os.path.join(work_dir, scene_dir) + else: + return work_dir + # endregion - deregister_loader_plugin_path(LOAD_PATH) - deregister_creator_plugin_path(CREATE_PATH) - deregister_inventory_action_path(INVENTORY_PATH) + @contextlib.contextmanager + def maintained_selection(self): + from .lib import maintained_selection + return maintained_selection() - pyblish.api.deregister_callback( - "instanceToggled", on_pyblish_instance_toggled - ) + def get_containers(self): + return ls() + + def update_context_data(self, data, changes): + print(data, changes) + + def get_context_data(self): + return {} def on_pyblish_instance_toggled(instance, old_value, new_value): @@ -254,3 +282,43 @@ def parse_container(tool): return container +def list_instances(creator_id=None): + """Return created instances in current workfile which will be published. + + Returns: + (list) of dictionaries matching instances format + """ + + comp = get_current_comp() + tools = comp.GetToolList(False, "Loader").values() + + instance_signature = { + "id": "pyblish.avalon.instance", + "identifier": creator_id + } + instances = [] + for tool in tools: + + data = tool.GetData('openpype') + if not isinstance(data, dict): + return + + if creator_id and data.get("identifier") != creator_id: + continue + + if data.get("id") != instance_signature["id"]: + continue + + instances.append(tool) + + return instances + + +def remove_instance(instance): + """Remove instance from current workfile. + + Args: + instance (dict): instance representation from subsetmanager model + """ + # Assume instance is a Fusion tool directly + instance.Delete() diff --git a/openpype/hosts/fusion/api/workio.py b/openpype/hosts/fusion/api/workio.py deleted file mode 100644 index 939b2ff4be1..00000000000 --- a/openpype/hosts/fusion/api/workio.py +++ /dev/null @@ -1,45 +0,0 @@ -"""Host API required Work Files tool""" -import sys -import os - -from .lib import get_current_comp - - -def file_extensions(): - return [".comp"] - - -def has_unsaved_changes(): - comp = get_current_comp() - return comp.GetAttrs()["COMPB_Modified"] - - -def save_file(filepath): - comp = get_current_comp() - comp.Save(filepath) - - -def open_file(filepath): - # Hack to get fusion, see - # openpype.hosts.fusion.api.pipeline.get_current_comp() - fusion = getattr(sys.modules["__main__"], "fusion", None) - - return fusion.LoadComp(filepath) - - -def current_file(): - comp = get_current_comp() - current_filepath = comp.GetAttrs()["COMPS_FileName"] - if not current_filepath: - return None - - return current_filepath - - -def work_root(session): - work_dir = session["AVALON_WORKDIR"] - scene_dir = session.get("AVALON_SCENEDIR") - if scene_dir: - return os.path.join(work_dir, scene_dir) - else: - return work_dir diff --git a/openpype/hosts/fusion/deploy/MenuScripts/openpype_menu.py b/openpype/hosts/fusion/deploy/MenuScripts/openpype_menu.py index 2918c552c88..685e58d58fa 100644 --- a/openpype/hosts/fusion/deploy/MenuScripts/openpype_menu.py +++ b/openpype/hosts/fusion/deploy/MenuScripts/openpype_menu.py @@ -13,11 +13,11 @@ def main(env): # However the contents of that folder can conflict with Qt library dlls # so we make sure to move out of it to avoid DLL Load Failed errors. os.chdir("..") - from openpype.hosts.fusion import api + from openpype.hosts.fusion.api import FusionHost from openpype.hosts.fusion.api import menu # activate resolve from pype - install_host(api) + install_host(FusionHost()) log = Logger.get_logger(__name__) log.info(f"Registered host: {registered_host()}") diff --git a/openpype/hosts/fusion/plugins/create/create_exr_saver.py b/openpype/hosts/fusion/plugins/create/create_exr_saver.py index 6d93fe710ab..74cd1cbea57 100644 --- a/openpype/hosts/fusion/plugins/create/create_exr_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_exr_saver.py @@ -1,24 +1,29 @@ import os -from openpype.pipeline import ( - LegacyCreator, - legacy_io -) from openpype.hosts.fusion.api import ( get_current_comp, - comp_lock_and_undo_chunk + comp_lock_and_undo_chunk, + remove_instance, + list_instances ) +from openpype.pipeline import ( + legacy_io, + Creator, + CreatedInstance +) -class CreateOpenEXRSaver(LegacyCreator): +class CreateOpenEXRSaver(Creator): + identifier = "io.openpype.creators.fusion.saver" name = "openexrDefault" label = "Create OpenEXR Saver" - hosts = ["fusion"] family = "render" - defaults = ["Main"] + default_variants = ["Main"] + + selected_nodes = [] - def process(self): + def create(self, subset_name, instance_data, pre_create_data): file_format = "OpenEXRFormat" @@ -26,13 +31,13 @@ def process(self): workdir = os.path.normpath(legacy_io.Session["AVALON_WORKDIR"]) - filename = "{}..exr".format(self.name) + filename = "{}..exr".format(subset_name) filepath = os.path.join(workdir, "render", filename) with comp_lock_and_undo_chunk(comp): args = (-32768, -32768) # Magical position numbers saver = comp.AddTool("Saver", *args) - saver.SetAttrs({"TOOLS_Name": self.name}) + saver.SetAttrs({"TOOLS_Name": subset_name}) # Setting input attributes is different from basic attributes # Not confused with "MainInputAttributes" which @@ -47,3 +52,18 @@ def process(self): # Set file format attributes saver[file_format]["Depth"] = 1 # int8 | int16 | float32 | other saver[file_format]["SaveAlpha"] = 0 + + def collect_instances(self): + for instance in list_instances(creator_id=self.identifier): + created_instance = CreatedInstance.from_existing(instance, self) + self._add_instance_to_context(created_instance) + + def update_instances(self, update_list): + print(update_list) + + def remove_instances(self, instances): + for instance in instances: + remove_instance(instance) + + def get_pre_create_attr_defs(self): + return [] \ No newline at end of file From 13cb1f4bc0756eae2cf1cf7d07726e137a03a37f Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 20 Sep 2022 23:37:32 +0200 Subject: [PATCH 055/898] Ensure newline --- openpype/hosts/fusion/plugins/create/create_exr_saver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/plugins/create/create_exr_saver.py b/openpype/hosts/fusion/plugins/create/create_exr_saver.py index 74cd1cbea57..4809832cd0b 100644 --- a/openpype/hosts/fusion/plugins/create/create_exr_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_exr_saver.py @@ -66,4 +66,4 @@ def remove_instances(self, instances): remove_instance(instance) def get_pre_create_attr_defs(self): - return [] \ No newline at end of file + return [] From 218c836026fcb99dd157fa56e6dfabc8bf3a8271 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 21 Sep 2022 09:12:41 +0200 Subject: [PATCH 056/898] Reorder logic - makes more sense to check id first --- openpype/hosts/fusion/api/pipeline.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/api/pipeline.py b/openpype/hosts/fusion/api/pipeline.py index b73759fee0c..f5900a2ddef 100644 --- a/openpype/hosts/fusion/api/pipeline.py +++ b/openpype/hosts/fusion/api/pipeline.py @@ -303,10 +303,10 @@ def list_instances(creator_id=None): if not isinstance(data, dict): return - if creator_id and data.get("identifier") != creator_id: + if data.get("id") != instance_signature["id"]: continue - if data.get("id") != instance_signature["id"]: + if creator_id and data.get("identifier") != creator_id: continue instances.append(tool) From 1cf86a68f7b1961118f127cadc068e6b37e62d77 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 21 Sep 2022 14:19:56 +0200 Subject: [PATCH 057/898] Remove creator in menu in favor of new publisher --- openpype/hosts/fusion/api/menu.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/openpype/hosts/fusion/api/menu.py b/openpype/hosts/fusion/api/menu.py index 4e415cafbaf..ec8747298c9 100644 --- a/openpype/hosts/fusion/api/menu.py +++ b/openpype/hosts/fusion/api/menu.py @@ -52,7 +52,6 @@ def __init__(self, *args, **kwargs): asset_label.setAlignment(QtCore.Qt.AlignHCenter) workfiles_btn = QtWidgets.QPushButton("Workfiles...", self) - create_btn = QtWidgets.QPushButton("Create...", self) publish_btn = QtWidgets.QPushButton("Publish...", self) load_btn = QtWidgets.QPushButton("Load...", self) manager_btn = QtWidgets.QPushButton("Manage...", self) @@ -75,7 +74,6 @@ def __init__(self, *args, **kwargs): layout.addSpacing(20) - layout.addWidget(create_btn) layout.addWidget(load_btn) layout.addWidget(publish_btn) layout.addWidget(manager_btn) @@ -100,7 +98,6 @@ def __init__(self, *args, **kwargs): self.asset_label = asset_label workfiles_btn.clicked.connect(self.on_workfile_clicked) - create_btn.clicked.connect(self.on_create_clicked) publish_btn.clicked.connect(self.on_publish_clicked) load_btn.clicked.connect(self.on_load_clicked) manager_btn.clicked.connect(self.on_manager_clicked) @@ -140,9 +137,6 @@ def deregister_all_callbacks(self): def on_workfile_clicked(self): host_tools.show_workfiles() - def on_create_clicked(self): - host_tools.show_creator() - def on_publish_clicked(self): host_tools.show_publisher() From ae5c565ab61609a3affcecc7b398ee9d0a6a874f Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 21 Sep 2022 14:20:50 +0200 Subject: [PATCH 058/898] Fix logic - add comments that these will remain unused however --- openpype/hosts/fusion/api/pipeline.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/fusion/api/pipeline.py b/openpype/hosts/fusion/api/pipeline.py index f5900a2ddef..1587381b1a9 100644 --- a/openpype/hosts/fusion/api/pipeline.py +++ b/openpype/hosts/fusion/api/pipeline.py @@ -282,6 +282,7 @@ def parse_container(tool): return container +# TODO: Function below is currently unused prototypes def list_instances(creator_id=None): """Return created instances in current workfile which will be published. @@ -290,7 +291,7 @@ def list_instances(creator_id=None): """ comp = get_current_comp() - tools = comp.GetToolList(False, "Loader").values() + tools = comp.GetToolList(False).values() instance_signature = { "id": "pyblish.avalon.instance", @@ -301,7 +302,7 @@ def list_instances(creator_id=None): data = tool.GetData('openpype') if not isinstance(data, dict): - return + continue if data.get("id") != instance_signature["id"]: continue @@ -314,6 +315,7 @@ def list_instances(creator_id=None): return instances +# TODO: Function below is currently unused prototypes def remove_instance(instance): """Remove instance from current workfile. @@ -321,4 +323,4 @@ def remove_instance(instance): instance (dict): instance representation from subsetmanager model """ # Assume instance is a Fusion tool directly - instance.Delete() + instance["tool"].Delete() From d62e1eef82bbb84902a96d1d48fa26538f9a2f81 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 21 Sep 2022 14:21:28 +0200 Subject: [PATCH 059/898] Continue refactor to new publisher --- .../fusion/plugins/create/create_exr_saver.py | 74 ++++++++++++++++++- .../plugins/publish/collect_instances.py | 44 +++-------- 2 files changed, 84 insertions(+), 34 deletions(-) diff --git a/openpype/hosts/fusion/plugins/create/create_exr_saver.py b/openpype/hosts/fusion/plugins/create/create_exr_saver.py index 4809832cd0b..c2adb48bacc 100644 --- a/openpype/hosts/fusion/plugins/create/create_exr_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_exr_saver.py @@ -1,5 +1,7 @@ import os +import qtawesome + from openpype.hosts.fusion.api import ( get_current_comp, comp_lock_and_undo_chunk, @@ -19,7 +21,9 @@ class CreateOpenEXRSaver(Creator): name = "openexrDefault" label = "Create OpenEXR Saver" family = "render" - default_variants = ["Main"] + default_variants = ["Main"] + + description = "Fusion Saver to generate EXR image sequence" selected_nodes = [] @@ -27,6 +31,10 @@ def create(self, subset_name, instance_data, pre_create_data): file_format = "OpenEXRFormat" + print(subset_name) + print(instance_data) + print(pre_create_data) + comp = get_current_comp() workdir = os.path.normpath(legacy_io.Session["AVALON_WORKDIR"]) @@ -53,17 +61,79 @@ def create(self, subset_name, instance_data, pre_create_data): saver[file_format]["Depth"] = 1 # int8 | int16 | float32 | other saver[file_format]["SaveAlpha"] = 0 + # Save all data in a "openpype.{key}" = value data + for key, value in instance_data.items(): + saver.SetData("openpype.{}".format(key), value) + def collect_instances(self): - for instance in list_instances(creator_id=self.identifier): + + comp = get_current_comp() + tools = comp.GetToolList(False, "Saver").values() + + # Allow regular non-managed savers to also be picked up + project = legacy_io.Session["AVALON_PROJECT"] + asset = legacy_io.Session["AVALON_ASSET"] + task = legacy_io.Session["AVALON_TASK"] + + for tool in tools: + + path = tool["Clip"][comp.TIME_UNDEFINED] + fname = os.path.basename(path) + fname, _ext = os.path.splitext(fname) + subset = fname.rstrip(".") + + attrs = tool.GetAttrs() + passthrough = attrs["TOOLB_PassThrough"] + variant = subset[len("render"):] + + # TODO: this should not be done this way - this should actually + # get the data as stored on the tool explicitly (however) + # that would disallow any 'regular saver' to be collected + # unless the instance data is stored on it to begin with + instance = { + # Required data + "project": project, + "asset": asset, + "subset": subset, + "task": task, + "variant": variant, + "active": not passthrough, + "family": self.family, + + # Fusion data + "tool_name": tool.Name + } + + # Use the explicit data on the saver (if any) + data = tool.GetData("openpype") + if data: + instance.update(data) + + # Add instance created_instance = CreatedInstance.from_existing(instance, self) + + # TODO: move this to lifetime data or alike + # (Doing this before CreatedInstance.from_existing wouldn't + # work because `tool` isn't JSON serializable) + created_instance["tool"] = tool + self._add_instance_to_context(created_instance) + def get_icon(self): + return qtawesome.icon("fa.eye", color="white") + def update_instances(self, update_list): + # TODO: Not sure what to do here? print(update_list) def remove_instances(self, instances): for instance in instances: + + # Remove the tool from the scene remove_instance(instance) + # Remove the collected CreatedInstance to remove from UI directly + self._remove_instance_from_context(instance) + def get_pre_create_attr_defs(self): return [] diff --git a/openpype/hosts/fusion/plugins/publish/collect_instances.py b/openpype/hosts/fusion/plugins/publish/collect_instances.py index fe60b838270..e42e7b5f707 100644 --- a/openpype/hosts/fusion/plugins/publish/collect_instances.py +++ b/openpype/hosts/fusion/plugins/publish/collect_instances.py @@ -30,7 +30,7 @@ class CollectInstances(pyblish.api.ContextPlugin): """ order = pyblish.api.CollectorOrder - label = "Collect Instances" + label = "Collect Instances Data" hosts = ["fusion"] def process(self, context): @@ -39,67 +39,47 @@ def process(self, context): from openpype.hosts.fusion.api.lib import get_frame_path comp = context.data["currentComp"] - - # Get all savers in the comp - tools = comp.GetToolList(False).values() - savers = [tool for tool in tools if tool.ID == "Saver"] - start, end, global_start, global_end = get_comp_render_range(comp) context.data["frameStart"] = int(start) context.data["frameEnd"] = int(end) context.data["frameStartHandle"] = int(global_start) context.data["frameEndHandle"] = int(global_end) - for tool in savers: - path = tool["Clip"][comp.TIME_UNDEFINED] + # Comp tools by name + tools = {tool.Name: tool for tool in comp.GetToolList(False).values()} - tool_attrs = tool.GetAttrs() - active = not tool_attrs["TOOLB_PassThrough"] + for instance in context: - if not path: - self.log.warning("Skipping saver because it " - "has no path set: {}".format(tool.Name)) - continue + tool_name = instance.data["tool_name"] + tool = tools[tool_name] + path = tool["Clip"][comp.TIME_UNDEFINED] filename = os.path.basename(path) head, padding, tail = get_frame_path(filename) ext = os.path.splitext(path)[1] assert tail == ext, ("Tail does not match %s" % ext) - subset = head.rstrip("_. ") # subset is head of the filename # Include start and end render frame in label + subset = instance.data["subset"] label = "{subset} ({start}-{end})".format(subset=subset, start=int(start), end=int(end)) - - instance = context.create_instance(subset) instance.data.update({ - "asset": os.environ["AVALON_ASSET"], # todo: not a constant - "subset": subset, "path": path, "outputDir": os.path.dirname(path), - "ext": ext, # todo: should be redundant + "ext": ext, # todo: should be redundant? "label": label, + # todo: Allow custom frame range per instance "frameStart": context.data["frameStart"], "frameEnd": context.data["frameEnd"], "frameStartHandle": context.data["frameStartHandle"], "frameEndHandle": context.data["frameStartHandle"], "fps": context.data["fps"], "families": ["render", "review"], - "family": "render", - "active": active, - "publish": active # backwards compatibility + "family": "render" }) + # Add tool itself as member instance.append(tool) self.log.info("Found: \"%s\" " % path) - - # Sort/grouped by family (preserving local index) - context[:] = sorted(context, key=self.sort_by_family) - - return context - - def sort_by_family(self, instance): - """Sort by family""" - return instance.data.get("families", instance.data.get("family")) From 33cf1c3089cfa91601e9a10afc8df926ef5db95a Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 21 Sep 2022 19:57:45 +0200 Subject: [PATCH 060/898] Cleanup and fixes --- .../fusion/plugins/create/create_exr_saver.py | 59 ++++++++++--------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/openpype/hosts/fusion/plugins/create/create_exr_saver.py b/openpype/hosts/fusion/plugins/create/create_exr_saver.py index c2adb48bacc..e0366c65326 100644 --- a/openpype/hosts/fusion/plugins/create/create_exr_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_exr_saver.py @@ -4,9 +4,7 @@ from openpype.hosts.fusion.api import ( get_current_comp, - comp_lock_and_undo_chunk, - remove_instance, - list_instances + comp_lock_and_undo_chunk ) from openpype.pipeline import ( @@ -16,25 +14,20 @@ ) -class CreateOpenEXRSaver(Creator): +class CreateSaver(Creator): identifier = "io.openpype.creators.fusion.saver" - name = "openexrDefault" - label = "Create OpenEXR Saver" + name = "saver" + label = "Create Saver" family = "render" default_variants = ["Main"] - description = "Fusion Saver to generate EXR image sequence" - - selected_nodes = [] + description = "Fusion Saver to generate image sequence" def create(self, subset_name, instance_data, pre_create_data): + # TODO: Add pre_create attributes to choose file format? file_format = "OpenEXRFormat" - print(subset_name) - print(instance_data) - print(pre_create_data) - comp = get_current_comp() workdir = os.path.normpath(legacy_io.Session["AVALON_WORKDIR"]) @@ -61,9 +54,7 @@ def create(self, subset_name, instance_data, pre_create_data): saver[file_format]["Depth"] = 1 # int8 | int16 | float32 | other saver[file_format]["SaveAlpha"] = 0 - # Save all data in a "openpype.{key}" = value data - for key, value in instance_data.items(): - saver.SetData("openpype.{}".format(key), value) + self._imprint(saver, instance_data) def collect_instances(self): @@ -112,28 +103,42 @@ def collect_instances(self): # Add instance created_instance = CreatedInstance.from_existing(instance, self) - # TODO: move this to lifetime data or alike - # (Doing this before CreatedInstance.from_existing wouldn't - # work because `tool` isn't JSON serializable) - created_instance["tool"] = tool - self._add_instance_to_context(created_instance) def get_icon(self): return qtawesome.icon("fa.eye", color="white") def update_instances(self, update_list): - # TODO: Not sure what to do here? - print(update_list) + for update in update_list: + instance = update.instance + changes = update.changes + tool = self._get_instance_tool(instance) + self._imprint(tool, changes) def remove_instances(self, instances): for instance in instances: - # Remove the tool from the scene - remove_instance(instance) + tool = self._get_instance_tool(instance) + if tool: + tool.Delete() # Remove the collected CreatedInstance to remove from UI directly self._remove_instance_from_context(instance) - def get_pre_create_attr_defs(self): - return [] + def _imprint(self, tool, data): + + # Save all data in a "openpype.{key}" = value data + for key, value in data.items(): + tool.SetData("openpype.{}".format(key), value) + + def _get_instance_tool(self, instance): + # finds tool name of instance in currently active comp + # TODO: assign `tool` as some sort of lifetime data or alike so that + # the actual tool can be retrieved in current session. We can't store + # it in the instance itself since instance needs to be serializable + comp = get_current_comp() + tool_name = instance["tool_name"] + print(tool_name) + return { + tool.Name: tool for tool in comp.GetToolList(False).values() + }.get(tool_name) From 450a471c42a13d670eaf96a4323c92629c0b20a5 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 21 Sep 2022 19:58:42 +0200 Subject: [PATCH 061/898] Rename `create_exr_saver.py` -> `create_saver.py` --- .../plugins/create/{create_exr_saver.py => create_saver.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename openpype/hosts/fusion/plugins/create/{create_exr_saver.py => create_saver.py} (100%) diff --git a/openpype/hosts/fusion/plugins/create/create_exr_saver.py b/openpype/hosts/fusion/plugins/create/create_saver.py similarity index 100% rename from openpype/hosts/fusion/plugins/create/create_exr_saver.py rename to openpype/hosts/fusion/plugins/create/create_saver.py From 7a046dd446bef43606317df47c487b7809701a81 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 21 Sep 2022 20:02:58 +0200 Subject: [PATCH 062/898] Register the saver directly on create --- openpype/hosts/fusion/plugins/create/create_saver.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/openpype/hosts/fusion/plugins/create/create_saver.py b/openpype/hosts/fusion/plugins/create/create_saver.py index e0366c65326..a0ab1c1fcf8 100644 --- a/openpype/hosts/fusion/plugins/create/create_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_saver.py @@ -56,6 +56,16 @@ def create(self, subset_name, instance_data, pre_create_data): self._imprint(saver, instance_data) + # Register the CreatedInstance + instance = CreatedInstance( + family=self.family, + subset_name=subset_name, + instance_data=instance_data, + creator=self) + self._add_instance_to_context(instance) + + return instance + def collect_instances(self): comp = get_current_comp() From cd0825756e753de983c651413affdcaad110120a Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 21 Sep 2022 20:04:17 +0200 Subject: [PATCH 063/898] Fix keyword --- openpype/hosts/fusion/plugins/create/create_saver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/plugins/create/create_saver.py b/openpype/hosts/fusion/plugins/create/create_saver.py index a0ab1c1fcf8..c2c9ad1cb71 100644 --- a/openpype/hosts/fusion/plugins/create/create_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_saver.py @@ -60,7 +60,7 @@ def create(self, subset_name, instance_data, pre_create_data): instance = CreatedInstance( family=self.family, subset_name=subset_name, - instance_data=instance_data, + data=instance_data, creator=self) self._add_instance_to_context(instance) From 01167e84caf8e1e047ecffc93d7350b34d8ada46 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 21 Sep 2022 23:11:05 +0200 Subject: [PATCH 064/898] Barebones refactor of validators to raise PublishValidationError --- .../publish/validate_background_depth.py | 7 ++- .../plugins/publish/validate_comp_saved.py | 7 ++- .../publish/validate_create_folder_checked.py | 6 ++- .../validate_filename_has_extension.py | 4 +- .../publish/validate_saver_has_input.py | 8 +++- .../publish/validate_saver_passthrough.py | 7 +-- .../publish/validate_unique_subsets.py | 47 +++++++++++++------ 7 files changed, 60 insertions(+), 26 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/validate_background_depth.py b/openpype/hosts/fusion/plugins/publish/validate_background_depth.py index 4268fab528d..f057989535f 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_background_depth.py +++ b/openpype/hosts/fusion/plugins/publish/validate_background_depth.py @@ -1,6 +1,7 @@ import pyblish.api from openpype.pipeline.publish import RepairAction +from openpype.pipeline import PublishValidationError class ValidateBackgroundDepth(pyblish.api.InstancePlugin): @@ -29,8 +30,10 @@ def get_invalid(cls, instance): def process(self, instance): invalid = self.get_invalid(instance) if invalid: - raise RuntimeError("Found %i nodes which are not set to float32" - % len(invalid)) + raise PublishValidationError( + "Found {} Backgrounds tools which" + " are not set to float32".format(len(invalid)), + title=self.label) @classmethod def repair(cls, instance): diff --git a/openpype/hosts/fusion/plugins/publish/validate_comp_saved.py b/openpype/hosts/fusion/plugins/publish/validate_comp_saved.py index cabe65af6e0..748047e8cfb 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_comp_saved.py +++ b/openpype/hosts/fusion/plugins/publish/validate_comp_saved.py @@ -1,6 +1,7 @@ import os import pyblish.api +from openpype.pipeline import PublishValidationError class ValidateFusionCompSaved(pyblish.api.ContextPlugin): @@ -19,10 +20,12 @@ def process(self, context): filename = attrs["COMPS_FileName"] if not filename: - raise RuntimeError("Comp is not saved.") + raise PublishValidationError("Comp is not saved.", + title=self.label) if not os.path.exists(filename): - raise RuntimeError("Comp file does not exist: %s" % filename) + raise PublishValidationError( + "Comp file does not exist: %s" % filename, title=self.label) if attrs["COMPB_Modified"]: self.log.warning("Comp is modified. Save your comp to ensure your " diff --git a/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py b/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py index f6beefefc14..3674b33644c 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py +++ b/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py @@ -1,6 +1,7 @@ import pyblish.api from openpype.pipeline.publish import RepairAction +from openpype.pipeline import PublishValidationError class ValidateCreateFolderChecked(pyblish.api.InstancePlugin): @@ -31,8 +32,9 @@ def get_invalid(cls, instance): def process(self, instance): invalid = self.get_invalid(instance) if invalid: - raise RuntimeError("Found Saver with Create Folder During " - "Render checked off") + raise PublishValidationError( + "Found Saver with Create Folder During Render checked off", + title=self.label) @classmethod def repair(cls, instance): diff --git a/openpype/hosts/fusion/plugins/publish/validate_filename_has_extension.py b/openpype/hosts/fusion/plugins/publish/validate_filename_has_extension.py index 4795a2aa051..22f1db809c1 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_filename_has_extension.py +++ b/openpype/hosts/fusion/plugins/publish/validate_filename_has_extension.py @@ -1,6 +1,7 @@ import os import pyblish.api +from openpype.pipeline import PublishValidationError class ValidateFilenameHasExtension(pyblish.api.InstancePlugin): @@ -20,7 +21,8 @@ class ValidateFilenameHasExtension(pyblish.api.InstancePlugin): def process(self, instance): invalid = self.get_invalid(instance) if invalid: - raise RuntimeError("Found Saver without an extension") + raise PublishValidationError("Found Saver without an extension", + title=self.label) @classmethod def get_invalid(cls, instance): diff --git a/openpype/hosts/fusion/plugins/publish/validate_saver_has_input.py b/openpype/hosts/fusion/plugins/publish/validate_saver_has_input.py index 7243b44a3e7..8d961525f0b 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_saver_has_input.py +++ b/openpype/hosts/fusion/plugins/publish/validate_saver_has_input.py @@ -1,4 +1,5 @@ import pyblish.api +from openpype.pipeline import PublishValidationError class ValidateSaverHasInput(pyblish.api.InstancePlugin): @@ -25,5 +26,8 @@ def get_invalid(cls, instance): def process(self, instance): invalid = self.get_invalid(instance) if invalid: - raise RuntimeError("Saver has no incoming connection: " - "{} ({})".format(instance, invalid[0].Name)) + saver_name = invalid[0].Name + raise PublishValidationError( + "Saver has no incoming connection: {} ({})".format(instance, + saver_name), + title=self.label) diff --git a/openpype/hosts/fusion/plugins/publish/validate_saver_passthrough.py b/openpype/hosts/fusion/plugins/publish/validate_saver_passthrough.py index aed3835de3e..c191d6669c7 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_saver_passthrough.py +++ b/openpype/hosts/fusion/plugins/publish/validate_saver_passthrough.py @@ -1,4 +1,5 @@ import pyblish.api +from openpype.pipeline import PublishValidationError class ValidateSaverPassthrough(pyblish.api.ContextPlugin): @@ -27,8 +28,8 @@ def process(self, context): if invalid_instances: self.log.info("Reset pyblish to collect your current scene state, " "that should fix error.") - raise RuntimeError("Invalid instances: " - "{0}".format(invalid_instances)) + raise PublishValidationError( + "Invalid instances: {0}".format(invalid_instances)) def is_invalid(self, instance): @@ -36,7 +37,7 @@ def is_invalid(self, instance): attr = saver.GetAttrs() active = not attr["TOOLB_PassThrough"] - if active != instance.data["publish"]: + if active != instance.data.get("publish", True): self.log.info("Saver has different passthrough state than " "Pyblish: {} ({})".format(instance, saver.Name)) return [saver] diff --git a/openpype/hosts/fusion/plugins/publish/validate_unique_subsets.py b/openpype/hosts/fusion/plugins/publish/validate_unique_subsets.py index b218a311baa..b78f185a3a1 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_unique_subsets.py +++ b/openpype/hosts/fusion/plugins/publish/validate_unique_subsets.py @@ -1,7 +1,10 @@ +from collections import defaultdict + import pyblish.api +from openpype.pipeline import PublishValidationError -class ValidateUniqueSubsets(pyblish.api.InstancePlugin): +class ValidateUniqueSubsets(pyblish.api.ContextPlugin): """Ensure all instances have a unique subset name""" order = pyblish.api.ValidatorOrder @@ -10,20 +13,36 @@ class ValidateUniqueSubsets(pyblish.api.InstancePlugin): hosts = ["fusion"] @classmethod - def get_invalid(cls, instance): - - context = instance.context - subset = instance.data["subset"] - for other_instance in context: - if other_instance == instance: - continue - - if other_instance.data["subset"] == subset: - return [instance] # current instance is invalid - - return [] + def get_invalid(cls, context): + + # Collect instances per subset per asset + instances_per_subset_asset = defaultdict(lambda: defaultdict(list)) + for instance in context: + asset = instance.data.get("asset", context.data.get("asset")) + subset = instance.data.get("subset", context.data.get("subset")) + instances_per_subset_asset[asset][subset].append(instance) + + # Find which asset + subset combination has more than one instance + # Those are considered invalid because they'd integrate to the same + # destination. + invalid = [] + for asset, instances_per_subset in instances_per_subset_asset.items(): + for subset, instances in instances_per_subset.items(): + if len(instances) > 1: + cls.log.warning( + "{asset} > {subset} used by more than " + "one instance: {instances}".format( + asset=asset, + subset=subset, + instances=instances + )) + invalid.extend(instances) + + return invalid def process(self, instance): invalid = self.get_invalid(instance) if invalid: - raise RuntimeError("Animation content is invalid. See log.") + raise PublishValidationError("Multiple instances are set to " + "the same asset > subset.", + title=self.label) From ce954651182b2f4c526f981fcd5c086989f23b36 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 21 Sep 2022 23:17:31 +0200 Subject: [PATCH 065/898] Fix bugs in Creator --- .../fusion/plugins/create/create_saver.py | 154 +++++++++++------- 1 file changed, 99 insertions(+), 55 deletions(-) diff --git a/openpype/hosts/fusion/plugins/create/create_saver.py b/openpype/hosts/fusion/plugins/create/create_saver.py index c2c9ad1cb71..347aaaf4970 100644 --- a/openpype/hosts/fusion/plugins/create/create_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_saver.py @@ -29,20 +29,12 @@ def create(self, subset_name, instance_data, pre_create_data): file_format = "OpenEXRFormat" comp = get_current_comp() - - workdir = os.path.normpath(legacy_io.Session["AVALON_WORKDIR"]) - - filename = "{}..exr".format(subset_name) - filepath = os.path.join(workdir, "render", filename) - with comp_lock_and_undo_chunk(comp): args = (-32768, -32768) # Magical position numbers saver = comp.AddTool("Saver", *args) - saver.SetAttrs({"TOOLS_Name": subset_name}) - # Setting input attributes is different from basic attributes - # Not confused with "MainInputAttributes" which - saver["Clip"] = filepath + self._update_tool_with_data(saver, data=instance_data) + saver["OutputFormat"] = file_format # Check file format settings are available @@ -54,6 +46,9 @@ def create(self, subset_name, instance_data, pre_create_data): saver[file_format]["Depth"] = 1 # int8 | int16 | float32 | other saver[file_format]["SaveAlpha"] = 0 + # Fusion data for the instance data + instance_data["tool_name"] = saver.Name + self._imprint(saver, instance_data) # Register the CreatedInstance @@ -70,49 +65,17 @@ def collect_instances(self): comp = get_current_comp() tools = comp.GetToolList(False, "Saver").values() - - # Allow regular non-managed savers to also be picked up - project = legacy_io.Session["AVALON_PROJECT"] - asset = legacy_io.Session["AVALON_ASSET"] - task = legacy_io.Session["AVALON_TASK"] - for tool in tools: - path = tool["Clip"][comp.TIME_UNDEFINED] - fname = os.path.basename(path) - fname, _ext = os.path.splitext(fname) - subset = fname.rstrip(".") - - attrs = tool.GetAttrs() - passthrough = attrs["TOOLB_PassThrough"] - variant = subset[len("render"):] - - # TODO: this should not be done this way - this should actually - # get the data as stored on the tool explicitly (however) - # that would disallow any 'regular saver' to be collected - # unless the instance data is stored on it to begin with - instance = { - # Required data - "project": project, - "asset": asset, - "subset": subset, - "task": task, - "variant": variant, - "active": not passthrough, - "family": self.family, - - # Fusion data - "tool_name": tool.Name - } + data = self.get_managed_tool_data(tool) + if not data: + data = self._collect_unmanaged_saver(tool) - # Use the explicit data on the saver (if any) - data = tool.GetData("openpype") - if data: - instance.update(data) + # Collect non-stored data + data["tool_name"] = tool.Name # Add instance - created_instance = CreatedInstance.from_existing(instance, self) - + created_instance = CreatedInstance.from_existing(data, self) self._add_instance_to_context(created_instance) def get_icon(self): @@ -121,9 +84,18 @@ def get_icon(self): def update_instances(self, update_list): for update in update_list: instance = update.instance - changes = update.changes + + # Get the new values after the changes by key, ignore old value + new_data = { + key: new for key, (_old, new) in update.changes.items() + } + tool = self._get_instance_tool(instance) - self._imprint(tool, changes) + self._update_tool_with_data(tool, new_data) + self._imprint(tool, new_data) + + # Ensure tool name is up-to-date + instance["tool_name"] = tool.Name def remove_instances(self, instances): for instance in instances: @@ -136,19 +108,91 @@ def remove_instances(self, instances): self._remove_instance_from_context(instance) def _imprint(self, tool, data): - # Save all data in a "openpype.{key}" = value data for key, value in data.items(): tool.SetData("openpype.{}".format(key), value) def _get_instance_tool(self, instance): # finds tool name of instance in currently active comp - # TODO: assign `tool` as some sort of lifetime data or alike so that - # the actual tool can be retrieved in current session. We can't store - # it in the instance itself since instance needs to be serializable + # TODO: assign `tool` as 'lifetime' data instead of name so the + # tool can be retrieved in current session. We can't store currently + # in the CreatedInstance data because it needs to be serializable comp = get_current_comp() tool_name = instance["tool_name"] - print(tool_name) return { tool.Name: tool for tool in comp.GetToolList(False).values() }.get(tool_name) + + def _update_tool_with_data(self, tool, data): + """Update tool node name and output path based on subset data""" + if "subset" not in data: + return + + original_subset = tool.GetData("openpype.subset") + subset = data["subset"] + if original_subset != subset: + # Subset change detected + # Update output filepath + workdir = os.path.normpath(legacy_io.Session["AVALON_WORKDIR"]) + filename = "{}..exr".format(subset) + filepath = os.path.join(workdir, "render", subset, filename) + tool["Clip"] = filepath + + # Rename tool + if tool.Name != subset: + print(f"Renaming {tool.Name} -> {subset}") + tool.SetAttrs({"TOOLS_Name": subset}) + + def _collect_unmanaged_saver(self, tool): + + # TODO: this should not be done this way - this should actually + # get the data as stored on the tool explicitly (however) + # that would disallow any 'regular saver' to be collected + # unless the instance data is stored on it to begin with + + print("Collecting unmanaged saver..") + comp = tool.Comp() + + # Allow regular non-managed savers to also be picked up + project = legacy_io.Session["AVALON_PROJECT"] + asset = legacy_io.Session["AVALON_ASSET"] + task = legacy_io.Session["AVALON_TASK"] + + path = tool["Clip"][comp.TIME_UNDEFINED] + fname = os.path.basename(path) + fname, _ext = os.path.splitext(fname) + subset = fname.rstrip(".") + + attrs = tool.GetAttrs() + passthrough = attrs["TOOLB_PassThrough"] + variant = subset[len("render"):] + return { + # Required data + "project": project, + "asset": asset, + "subset": subset, + "task": task, + "variant": variant, + "active": not passthrough, + "family": self.family, + + # Unique identifier for instance and this creator + "id": "pyblish.avalon.instance", + "creator_identifier": self.identifier + } + + def get_managed_tool_data(self, tool): + """Return data of the tool if it matches creator identifier""" + data = tool.GetData('openpype') + if not isinstance(data, dict): + return + + required = { + "id": "pyblish.avalon.instance", + "creator_identifier": self.identifier + } + for key, value in required.items(): + if key not in data or data[key] != value: + return + + return data From af8662c87525012a8c7fd9915dcc1f2ce725c967 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 21 Sep 2022 23:24:28 +0200 Subject: [PATCH 066/898] Fix refactor to ContextPlugin --- .../hosts/fusion/plugins/publish/validate_unique_subsets.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/validate_unique_subsets.py b/openpype/hosts/fusion/plugins/publish/validate_unique_subsets.py index b78f185a3a1..5f0f93f7642 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_unique_subsets.py +++ b/openpype/hosts/fusion/plugins/publish/validate_unique_subsets.py @@ -40,8 +40,8 @@ def get_invalid(cls, context): return invalid - def process(self, instance): - invalid = self.get_invalid(instance) + def process(self, context): + invalid = self.get_invalid(context) if invalid: raise PublishValidationError("Multiple instances are set to " "the same asset > subset.", From fe857b84429cda78235084d16c32ba3e58701aba Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 21 Sep 2022 23:26:03 +0200 Subject: [PATCH 067/898] Add title to error --- .../hosts/fusion/plugins/publish/validate_saver_passthrough.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/plugins/publish/validate_saver_passthrough.py b/openpype/hosts/fusion/plugins/publish/validate_saver_passthrough.py index c191d6669c7..bbafd8949e9 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_saver_passthrough.py +++ b/openpype/hosts/fusion/plugins/publish/validate_saver_passthrough.py @@ -29,7 +29,8 @@ def process(self, context): self.log.info("Reset pyblish to collect your current scene state, " "that should fix error.") raise PublishValidationError( - "Invalid instances: {0}".format(invalid_instances)) + "Invalid instances: {0}".format(invalid_instances), + title=self.label) def is_invalid(self, instance): From 6abfabed4057292419059fa193bf5ffcbc8b9d21 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 21 Sep 2022 23:33:13 +0200 Subject: [PATCH 068/898] Fix missing import --- openpype/hosts/fusion/api/pipeline.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/fusion/api/pipeline.py b/openpype/hosts/fusion/api/pipeline.py index 1587381b1a9..6fc3902949a 100644 --- a/openpype/hosts/fusion/api/pipeline.py +++ b/openpype/hosts/fusion/api/pipeline.py @@ -2,6 +2,7 @@ Basic avalon integration """ import os +import sys import logging import contextlib From bdfe2414583480c06f0ee35113b0deea3fced1c6 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 23 Sep 2022 17:31:35 +0200 Subject: [PATCH 069/898] Refactor new publish logic to make use of "transientData" on the Creator --- .../fusion/plugins/create/create_saver.py | 33 +++++++------------ .../plugins/publish/collect_instances.py | 11 +++---- 2 files changed, 16 insertions(+), 28 deletions(-) diff --git a/openpype/hosts/fusion/plugins/create/create_saver.py b/openpype/hosts/fusion/plugins/create/create_saver.py index 347aaaf4970..b3a912c56ae 100644 --- a/openpype/hosts/fusion/plugins/create/create_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_saver.py @@ -46,9 +46,6 @@ def create(self, subset_name, instance_data, pre_create_data): saver[file_format]["Depth"] = 1 # int8 | int16 | float32 | other saver[file_format]["SaveAlpha"] = 0 - # Fusion data for the instance data - instance_data["tool_name"] = saver.Name - self._imprint(saver, instance_data) # Register the CreatedInstance @@ -57,6 +54,10 @@ def create(self, subset_name, instance_data, pre_create_data): subset_name=subset_name, data=instance_data, creator=self) + + # Insert the transient data + instance.transient_data["tool"] = saver + self._add_instance_to_context(instance) return instance @@ -71,11 +72,12 @@ def collect_instances(self): if not data: data = self._collect_unmanaged_saver(tool) - # Collect non-stored data - data["tool_name"] = tool.Name - # Add instance created_instance = CreatedInstance.from_existing(data, self) + + # Collect transient data + created_instance.transient_data["tool"] = tool + self._add_instance_to_context(created_instance) def get_icon(self): @@ -90,17 +92,15 @@ def update_instances(self, update_list): key: new for key, (_old, new) in update.changes.items() } - tool = self._get_instance_tool(instance) + tool = instance.transient_data["tool"] self._update_tool_with_data(tool, new_data) self._imprint(tool, new_data) - # Ensure tool name is up-to-date - instance["tool_name"] = tool.Name - def remove_instances(self, instances): for instance in instances: # Remove the tool from the scene - tool = self._get_instance_tool(instance) + + tool = instance.transient_data["tool"] if tool: tool.Delete() @@ -112,17 +112,6 @@ def _imprint(self, tool, data): for key, value in data.items(): tool.SetData("openpype.{}".format(key), value) - def _get_instance_tool(self, instance): - # finds tool name of instance in currently active comp - # TODO: assign `tool` as 'lifetime' data instead of name so the - # tool can be retrieved in current session. We can't store currently - # in the CreatedInstance data because it needs to be serializable - comp = get_current_comp() - tool_name = instance["tool_name"] - return { - tool.Name: tool for tool in comp.GetToolList(False).values() - }.get(tool_name) - def _update_tool_with_data(self, tool, data): """Update tool node name and output path based on subset data""" if "subset" not in data: diff --git a/openpype/hosts/fusion/plugins/publish/collect_instances.py b/openpype/hosts/fusion/plugins/publish/collect_instances.py index e42e7b5f707..2f3e82fded7 100644 --- a/openpype/hosts/fusion/plugins/publish/collect_instances.py +++ b/openpype/hosts/fusion/plugins/publish/collect_instances.py @@ -45,13 +45,9 @@ def process(self, context): context.data["frameStartHandle"] = int(global_start) context.data["frameEndHandle"] = int(global_end) - # Comp tools by name - tools = {tool.Name: tool for tool in comp.GetToolList(False).values()} - for instance in context: - tool_name = instance.data["tool_name"] - tool = tools[tool_name] + tool = instance.data["transientData"]["tool"] path = tool["Clip"][comp.TIME_UNDEFINED] filename = os.path.basename(path) @@ -76,7 +72,10 @@ def process(self, context): "frameEndHandle": context.data["frameStartHandle"], "fps": context.data["fps"], "families": ["render", "review"], - "family": "render" + "family": "render", + + # Backwards compatibility: embed tool in instance.data + "tool": tool }) # Add tool itself as member From 87621c14f5d47de295ae476879c00fbbe7efcf14 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 23 Sep 2022 17:34:47 +0200 Subject: [PATCH 070/898] Refactor `INewPublisher` to `IPublishHost` --- openpype/hosts/fusion/api/pipeline.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/api/pipeline.py b/openpype/hosts/fusion/api/pipeline.py index 6fc3902949a..3e30c5eaf57 100644 --- a/openpype/hosts/fusion/api/pipeline.py +++ b/openpype/hosts/fusion/api/pipeline.py @@ -20,7 +20,7 @@ ) from openpype.pipeline.load import any_outdated_containers from openpype.hosts.fusion import FUSION_HOST_DIR -from openpype.host import HostBase, IWorkfileHost, ILoadHost, INewPublisher +from openpype.host import HostBase, IWorkfileHost, ILoadHost, IPublishHost from openpype.tools.utils import host_tools @@ -48,7 +48,7 @@ def emit(self, record): comp.Print(entry) -class FusionHost(HostBase, IWorkfileHost, ILoadHost, INewPublisher): +class FusionHost(HostBase, IWorkfileHost, ILoadHost, IPublishHost): name = "fusion" def install(self): From 11bd9e8bb1f5a62c501f4fe4388c79fe82d8bc8a Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 23 Sep 2022 17:44:05 +0200 Subject: [PATCH 071/898] Add Select Invalid Action --- openpype/hosts/fusion/api/action.py | 54 +++++++++++++++++++ .../publish/validate_saver_has_input.py | 3 ++ 2 files changed, 57 insertions(+) create mode 100644 openpype/hosts/fusion/api/action.py diff --git a/openpype/hosts/fusion/api/action.py b/openpype/hosts/fusion/api/action.py new file mode 100644 index 00000000000..17509209504 --- /dev/null +++ b/openpype/hosts/fusion/api/action.py @@ -0,0 +1,54 @@ +import pyblish.api + + +from openpype.hosts.fusion.api.lib import get_current_comp +from openpype.pipeline.publish import get_errored_instances_from_context + + +class SelectInvalidAction(pyblish.api.Action): + """Select invalid nodes in Maya when plug-in failed. + + To retrieve the invalid nodes this assumes a static `get_invalid()` + method is available on the plugin. + + """ + label = "Select invalid" + on = "failed" # This action is only available on a failed plug-in + icon = "search" # Icon from Awesome Icon + + def process(self, context, plugin): + errored_instances = get_errored_instances_from_context(context) + + # Apply pyblish.logic to get the instances for the plug-in + instances = pyblish.api.instances_by_plugin(errored_instances, plugin) + + # Get the invalid nodes for the plug-ins + self.log.info("Finding invalid nodes..") + invalid = list() + for instance in instances: + invalid_nodes = plugin.get_invalid(instance) + if invalid_nodes: + if isinstance(invalid_nodes, (list, tuple)): + invalid.extend(invalid_nodes) + else: + self.log.warning("Plug-in returned to be invalid, " + "but has no selectable nodes.") + + if not invalid: + # Assume relevant comp is current comp and clear selection + self.log.info("No invalid tools found.") + comp = get_current_comp() + flow = comp.CurrentFrame.FlowView + flow.Select() # No args equals clearing selection + return + + # Assume a single comp + first_tool = invalid[0] + comp = first_tool.Comp() + flow = comp.CurrentFrame.FlowView + flow.Select() # No args equals clearing selection + names = set() + for tool in invalid: + flow.Select(tool, True) + names.add(tool.Name) + self.log.info("Selecting invalid tools: %s" % ", ".join(sorted(names))) diff --git a/openpype/hosts/fusion/plugins/publish/validate_saver_has_input.py b/openpype/hosts/fusion/plugins/publish/validate_saver_has_input.py index 8d961525f0b..e02125f5315 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_saver_has_input.py +++ b/openpype/hosts/fusion/plugins/publish/validate_saver_has_input.py @@ -1,6 +1,8 @@ import pyblish.api from openpype.pipeline import PublishValidationError +from openpype.hosts.fusion.api.action import SelectInvalidAction + class ValidateSaverHasInput(pyblish.api.InstancePlugin): """Validate saver has incoming connection @@ -13,6 +15,7 @@ class ValidateSaverHasInput(pyblish.api.InstancePlugin): label = "Validate Saver Has Input" families = ["render"] hosts = ["fusion"] + actions = [SelectInvalidAction] @classmethod def get_invalid(cls, instance): From 0f1ed036231d91ba6f8105d85b0c6e341e5b6487 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 23 Sep 2022 17:47:19 +0200 Subject: [PATCH 072/898] Add Select Invalid action to more validators --- .../fusion/plugins/publish/validate_background_depth.py | 4 ++++ .../plugins/publish/validate_create_folder_checked.py | 3 +++ .../plugins/publish/validate_filename_has_extension.py | 3 +++ .../fusion/plugins/publish/validate_saver_passthrough.py | 3 +++ .../hosts/fusion/plugins/publish/validate_unique_subsets.py | 6 ++++++ 5 files changed, 19 insertions(+) diff --git a/openpype/hosts/fusion/plugins/publish/validate_background_depth.py b/openpype/hosts/fusion/plugins/publish/validate_background_depth.py index f057989535f..261533de019 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_background_depth.py +++ b/openpype/hosts/fusion/plugins/publish/validate_background_depth.py @@ -3,6 +3,8 @@ from openpype.pipeline.publish import RepairAction from openpype.pipeline import PublishValidationError +from openpype.hosts.fusion.api.action import SelectInvalidAction + class ValidateBackgroundDepth(pyblish.api.InstancePlugin): """Validate if all Background tool are set to float32 bit""" @@ -14,6 +16,8 @@ class ValidateBackgroundDepth(pyblish.api.InstancePlugin): families = ["render"] optional = True + actions = [SelectInvalidAction] + @classmethod def get_invalid(cls, instance): diff --git a/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py b/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py index 3674b33644c..ba943abacb0 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py +++ b/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py @@ -3,6 +3,8 @@ from openpype.pipeline.publish import RepairAction from openpype.pipeline import PublishValidationError +from openpype.hosts.fusion.api.action import SelectInvalidAction + class ValidateCreateFolderChecked(pyblish.api.InstancePlugin): """Valid if all savers have the input attribute CreateDir checked on @@ -16,6 +18,7 @@ class ValidateCreateFolderChecked(pyblish.api.InstancePlugin): label = "Validate Create Folder Checked" families = ["render"] hosts = ["fusion"] + actions = [SelectInvalidAction] @classmethod def get_invalid(cls, instance): diff --git a/openpype/hosts/fusion/plugins/publish/validate_filename_has_extension.py b/openpype/hosts/fusion/plugins/publish/validate_filename_has_extension.py index 22f1db809c1..bbba2dde6ec 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_filename_has_extension.py +++ b/openpype/hosts/fusion/plugins/publish/validate_filename_has_extension.py @@ -3,6 +3,8 @@ import pyblish.api from openpype.pipeline import PublishValidationError +from openpype.hosts.fusion.api.action import SelectInvalidAction + class ValidateFilenameHasExtension(pyblish.api.InstancePlugin): """Ensure the Saver has an extension in the filename path @@ -17,6 +19,7 @@ class ValidateFilenameHasExtension(pyblish.api.InstancePlugin): label = "Validate Filename Has Extension" families = ["render"] hosts = ["fusion"] + actions = [SelectInvalidAction] def process(self, instance): invalid = self.get_invalid(instance) diff --git a/openpype/hosts/fusion/plugins/publish/validate_saver_passthrough.py b/openpype/hosts/fusion/plugins/publish/validate_saver_passthrough.py index bbafd8949e9..56f2e7e6b8f 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_saver_passthrough.py +++ b/openpype/hosts/fusion/plugins/publish/validate_saver_passthrough.py @@ -1,6 +1,8 @@ import pyblish.api from openpype.pipeline import PublishValidationError +from openpype.hosts.fusion.api.action import SelectInvalidAction + class ValidateSaverPassthrough(pyblish.api.ContextPlugin): """Validate saver passthrough is similar to Pyblish publish state""" @@ -9,6 +11,7 @@ class ValidateSaverPassthrough(pyblish.api.ContextPlugin): label = "Validate Saver Passthrough" families = ["render"] hosts = ["fusion"] + actions = [SelectInvalidAction] def process(self, context): diff --git a/openpype/hosts/fusion/plugins/publish/validate_unique_subsets.py b/openpype/hosts/fusion/plugins/publish/validate_unique_subsets.py index 5f0f93f7642..28bab599495 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_unique_subsets.py +++ b/openpype/hosts/fusion/plugins/publish/validate_unique_subsets.py @@ -3,6 +3,8 @@ import pyblish.api from openpype.pipeline import PublishValidationError +from openpype.hosts.fusion.api.action import SelectInvalidAction + class ValidateUniqueSubsets(pyblish.api.ContextPlugin): """Ensure all instances have a unique subset name""" @@ -11,6 +13,7 @@ class ValidateUniqueSubsets(pyblish.api.ContextPlugin): label = "Validate Unique Subsets" families = ["render"] hosts = ["fusion"] + actions = [SelectInvalidAction] @classmethod def get_invalid(cls, context): @@ -38,6 +41,9 @@ def get_invalid(cls, context): )) invalid.extend(instances) + # Return tools for the invalid instances so they can be selected + invalid = [instance.data["tool"] for instance in invalid] + return invalid def process(self, context): From a64a551fa19a472c4efe36528051394866f37cf1 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 27 Sep 2022 10:56:34 +0200 Subject: [PATCH 073/898] Tweak label --- openpype/hosts/fusion/plugins/create/create_saver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/plugins/create/create_saver.py b/openpype/hosts/fusion/plugins/create/create_saver.py index b3a912c56ae..99aa7583f16 100644 --- a/openpype/hosts/fusion/plugins/create/create_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_saver.py @@ -17,7 +17,7 @@ class CreateSaver(Creator): identifier = "io.openpype.creators.fusion.saver" name = "saver" - label = "Create Saver" + label = "Saver" family = "render" default_variants = ["Main"] From 85cb398b6ee14b66ece629fb446c97ee9fd2347a Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 27 Sep 2022 10:59:41 +0200 Subject: [PATCH 074/898] Implement draft for Create Workfile --- .../fusion/plugins/create/create_workfile.py | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 openpype/hosts/fusion/plugins/create/create_workfile.py diff --git a/openpype/hosts/fusion/plugins/create/create_workfile.py b/openpype/hosts/fusion/plugins/create/create_workfile.py new file mode 100644 index 00000000000..26a73abb640 --- /dev/null +++ b/openpype/hosts/fusion/plugins/create/create_workfile.py @@ -0,0 +1,129 @@ +import collections + +import qtawesome + +import openpype.hosts.fusion.api as api +from openpype.client import get_asset_by_name +from openpype.pipeline import ( + AutoCreator, + CreatedInstance, + legacy_io, +) + + +def flatten_dict(d, parent_key=None, separator="."): + items = [] + for key, v in d.items(): + new_key = parent_key + separator + key if parent_key else key + if isinstance(v, collections.MutableMapping): + items.extend(flatten_dict(v, new_key, separator=separator).items()) + else: + items.append((new_key, v)) + return dict(items) + + +class FusionWorkfileCreator(AutoCreator): + identifier = "workfile" + family = "workfile" + label = "Workfile" + + default_variant = "Main" + + create_allow_context_change = False + + data_key = "openpype.workfile" + + def collect_instances(self): + + comp = api.get_current_comp() + data = comp.GetData(self.data_key) + if not data: + return + + instance = CreatedInstance( + family=self.family, + subset_name=data["subset"], + data=data, + creator=self + ) + instance.transient_data["comp"] = comp + instance.transient_data["tool"] = None + + self._add_instance_to_context(instance) + + def update_instances(self, update_list): + for update in update_list: + instance = update.instance + comp = instance.transient_data["comp"] + if not hasattr(comp, "SetData"): + # Comp is not alive anymore, likely closed by the user + self.log.error("Workfile comp not found for existing instance." + " Comp might have been closed in the meantime.") + continue + + # TODO: It appears sometimes this could be 'nested' + # Get the new values after the changes by key, ignore old value + new_data = { + key: new for key, (_old, new) in update.changes.items() + } + self._imprint(comp, new_data) + + def create(self, options=None): + + comp = api.get_current_comp() + if not comp: + self.log.error("Unable to find current comp") + return + + # TODO: Is this really necessary? + # Force kill any existing "workfile" instances + for instance in self.create_context.instances: + if instance.family == self.family: + self.log.debug(f"Removing instance: {instance}") + self._remove_instance_from_context(instance) + + project_name = legacy_io.Session["AVALON_PROJECT"] + asset_name = legacy_io.Session["AVALON_ASSET"] + task_name = legacy_io.Session["AVALON_TASK"] + host_name = legacy_io.Session["AVALON_APP"] + + asset_doc = get_asset_by_name(project_name, asset_name) + subset_name = self.get_subset_name( + self.default_variant, task_name, asset_doc, + project_name, host_name + ) + data = { + "asset": asset_name, + "task": task_name, + "variant": self.default_variant + } + data.update(self.get_dynamic_data( + self.default_variant, task_name, asset_doc, + project_name, host_name + )) + + instance = CreatedInstance( + self.family, subset_name, data, self + ) + instance.transient_data["comp"] = comp + instance.transient_data["tool"] = None + self._add_instance_to_context(instance) + + self._imprint(comp, data) + + def get_icon(self): + return qtawesome.icon("fa.file-o", color="white") + + def _imprint(self, comp, data): + + # TODO: Should this keys persist or not? I'd prefer not + # Do not persist the current context for the Workfile + for key in ["variant", "subset", "asset", "task"]: + data.pop(key, None) + + # Flatten any potential nested dicts + data = flatten_dict(data, separator=".") + + # Prefix with data key openpype.workfile + data = {f"{self.data_key}.{key}" for key, value in data.items()} + comp.SetData(data) From f555c1bf9a11200d8a48a9a68bac6f5e4695e347 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 27 Sep 2022 11:00:35 +0200 Subject: [PATCH 075/898] Shush hound --- .../hosts/fusion/plugins/publish/validate_unique_subsets.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/plugins/publish/validate_unique_subsets.py b/openpype/hosts/fusion/plugins/publish/validate_unique_subsets.py index 28bab599495..5b6ceb2fdb7 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_unique_subsets.py +++ b/openpype/hosts/fusion/plugins/publish/validate_unique_subsets.py @@ -38,7 +38,8 @@ def get_invalid(cls, context): asset=asset, subset=subset, instances=instances - )) + ) + ) invalid.extend(instances) # Return tools for the invalid instances so they can be selected From b8f4a0a3969b841f50cb66f15e08717d3d3cd890 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 27 Sep 2022 11:41:55 +0200 Subject: [PATCH 076/898] Specifiy families explicitly (to avoid issues with workfile family not having a `tool`) --- openpype/hosts/fusion/plugins/publish/collect_inputs.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openpype/hosts/fusion/plugins/publish/collect_inputs.py b/openpype/hosts/fusion/plugins/publish/collect_inputs.py index 8f9857b02ff..e06649da998 100644 --- a/openpype/hosts/fusion/plugins/publish/collect_inputs.py +++ b/openpype/hosts/fusion/plugins/publish/collect_inputs.py @@ -97,10 +97,15 @@ class CollectUpstreamInputs(pyblish.api.InstancePlugin): label = "Collect Inputs" order = pyblish.api.CollectorOrder + 0.2 hosts = ["fusion"] + families = ["render"] def process(self, instance): # Get all upstream and include itself + if not any(instance[:]): + self.log.debug("No tool found in instance, skipping..") + return + tool = instance[0] nodes = list(iter_upstream(tool)) nodes.append(tool) From 2afc8ba573ee06ed790146eb113d1a74cbe705b3 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 27 Sep 2022 11:42:38 +0200 Subject: [PATCH 077/898] Fix collector with workfile present --- .../plugins/publish/collect_instances.py | 48 +++++++++++-------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/collect_instances.py b/openpype/hosts/fusion/plugins/publish/collect_instances.py index 2f3e82fded7..ad264f04784 100644 --- a/openpype/hosts/fusion/plugins/publish/collect_instances.py +++ b/openpype/hosts/fusion/plugins/publish/collect_instances.py @@ -46,24 +46,12 @@ def process(self, context): context.data["frameEndHandle"] = int(global_end) for instance in context: - - tool = instance.data["transientData"]["tool"] - - path = tool["Clip"][comp.TIME_UNDEFINED] - filename = os.path.basename(path) - head, padding, tail = get_frame_path(filename) - ext = os.path.splitext(path)[1] - assert tail == ext, ("Tail does not match %s" % ext) - # Include start and end render frame in label subset = instance.data["subset"] label = "{subset} ({start}-{end})".format(subset=subset, start=int(start), end=int(end)) instance.data.update({ - "path": path, - "outputDir": os.path.dirname(path), - "ext": ext, # todo: should be redundant? "label": label, # todo: Allow custom frame range per instance "frameStart": context.data["frameStart"], @@ -71,14 +59,32 @@ def process(self, context): "frameStartHandle": context.data["frameStartHandle"], "frameEndHandle": context.data["frameStartHandle"], "fps": context.data["fps"], - "families": ["render", "review"], - "family": "render", - - # Backwards compatibility: embed tool in instance.data - "tool": tool }) - # Add tool itself as member - instance.append(tool) - - self.log.info("Found: \"%s\" " % path) + if instance.data["family"] == "render": + # TODO: This should probably move into a collector of + # its own for the "render" family + # This is only the case for savers currently but not + # for workfile instances. So we assume saver here. + tool = instance.data["transientData"]["tool"] + path = tool["Clip"][comp.TIME_UNDEFINED] + + filename = os.path.basename(path) + head, padding, tail = get_frame_path(filename) + ext = os.path.splitext(path)[1] + assert tail == ext, ("Tail does not match %s" % ext) + + instance.data.update({ + "path": path, + "outputDir": os.path.dirname(path), + "ext": ext, # todo: should be redundant? + + "families": ["render", "review"], + "family": "render", + + # Backwards compatibility: embed tool in instance.data + "tool": tool + }) + + # Add tool itself as member + instance.append(tool) From d0ea9171b3cbd2c52ab3e027f496f75e6bb36768 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 27 Sep 2022 11:43:25 +0200 Subject: [PATCH 078/898] Remove storage of empty tool placeholder value --- openpype/hosts/fusion/plugins/create/create_workfile.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openpype/hosts/fusion/plugins/create/create_workfile.py b/openpype/hosts/fusion/plugins/create/create_workfile.py index 26a73abb640..19ad04f5723 100644 --- a/openpype/hosts/fusion/plugins/create/create_workfile.py +++ b/openpype/hosts/fusion/plugins/create/create_workfile.py @@ -47,7 +47,6 @@ def collect_instances(self): creator=self ) instance.transient_data["comp"] = comp - instance.transient_data["tool"] = None self._add_instance_to_context(instance) @@ -106,7 +105,6 @@ def create(self, options=None): self.family, subset_name, data, self ) instance.transient_data["comp"] = comp - instance.transient_data["tool"] = None self._add_instance_to_context(instance) self._imprint(comp, data) From 3a952d5038b51e7d05e64d70e10054a8c9b5bd4c Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 27 Sep 2022 11:43:37 +0200 Subject: [PATCH 079/898] Cosmetics/readability --- openpype/hosts/fusion/plugins/create/create_workfile.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/plugins/create/create_workfile.py b/openpype/hosts/fusion/plugins/create/create_workfile.py index 19ad04f5723..783d3a147a7 100644 --- a/openpype/hosts/fusion/plugins/create/create_workfile.py +++ b/openpype/hosts/fusion/plugins/create/create_workfile.py @@ -102,7 +102,10 @@ def create(self, options=None): )) instance = CreatedInstance( - self.family, subset_name, data, self + family=self.family, + subset_name=subset_name, + data=data, + creator=self ) instance.transient_data["comp"] = comp self._add_instance_to_context(instance) From 00d9aa216bd8689862a189eb32fcd1dd692303fe Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 27 Sep 2022 12:01:11 +0200 Subject: [PATCH 080/898] Apply to workfile family - like other hosts do --- .../fusion/plugins/publish/increment_current_file_deadline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/plugins/publish/increment_current_file_deadline.py b/openpype/hosts/fusion/plugins/publish/increment_current_file_deadline.py index 5c595638e92..42891446f74 100644 --- a/openpype/hosts/fusion/plugins/publish/increment_current_file_deadline.py +++ b/openpype/hosts/fusion/plugins/publish/increment_current_file_deadline.py @@ -11,7 +11,7 @@ class FusionIncrementCurrentFile(pyblish.api.ContextPlugin): label = "Increment current file" order = pyblish.api.IntegratorOrder + 9.0 hosts = ["fusion"] - families = ["render.farm"] + families = ["workfile"] optional = True def process(self, context): From 34c1346961a621726dfc4f9352606c038d650ec4 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 27 Sep 2022 12:01:28 +0200 Subject: [PATCH 081/898] Refactor filename --- ...crement_current_file_deadline.py => increment_current_file.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename openpype/hosts/fusion/plugins/publish/{increment_current_file_deadline.py => increment_current_file.py} (100%) diff --git a/openpype/hosts/fusion/plugins/publish/increment_current_file_deadline.py b/openpype/hosts/fusion/plugins/publish/increment_current_file.py similarity index 100% rename from openpype/hosts/fusion/plugins/publish/increment_current_file_deadline.py rename to openpype/hosts/fusion/plugins/publish/increment_current_file.py From d6080593e3213df882b5e4b6dc112223531d109e Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 27 Sep 2022 12:02:16 +0200 Subject: [PATCH 082/898] Include workfile family --- openpype/hosts/fusion/plugins/publish/save_scene.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/plugins/publish/save_scene.py b/openpype/hosts/fusion/plugins/publish/save_scene.py index 0cdfafa0956..a249c453d81 100644 --- a/openpype/hosts/fusion/plugins/publish/save_scene.py +++ b/openpype/hosts/fusion/plugins/publish/save_scene.py @@ -7,7 +7,7 @@ class FusionSaveComp(pyblish.api.ContextPlugin): label = "Save current file" order = pyblish.api.ExtractorOrder - 0.49 hosts = ["fusion"] - families = ["render"] + families = ["render", "workfile"] def process(self, context): From eed65758e651acf372d6814b4d7061990d6ad993 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 27 Sep 2022 12:21:31 +0200 Subject: [PATCH 083/898] Move Submit Fusion Deadline to Deadline Module --- .../deadline/plugins/publish/submit_fusion_deadline.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename openpype/{hosts/fusion/plugins/publish/submit_deadline.py => modules/deadline/plugins/publish/submit_fusion_deadline.py} (100%) diff --git a/openpype/hosts/fusion/plugins/publish/submit_deadline.py b/openpype/modules/deadline/plugins/publish/submit_fusion_deadline.py similarity index 100% rename from openpype/hosts/fusion/plugins/publish/submit_deadline.py rename to openpype/modules/deadline/plugins/publish/submit_fusion_deadline.py From 590538eb128dc8e7e8e6eee0b8d16ab593530e5e Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 4 Oct 2022 11:07:09 +0300 Subject: [PATCH 084/898] Fix import bug --- openpype/hosts/maya/plugins/publish/extract_look.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 7e640c375d0..f3128306eeb 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -11,13 +11,14 @@ import contextlib import subprocess from openpype.lib.vendor_bin_utils import find_executable +from openpype.lib import source_hash from collections import OrderedDict from maya import cmds # noqa import pyblish.api -from openpype.lib import source_hash, run_subprocess + from openpype.pipeline import legacy_io, publish from openpype.hosts.maya.api import lib @@ -93,7 +94,6 @@ def find_paths_by_hash(texture_hash): key = "data.sourceHashes.{0}".format(texture_hash) return legacy_io.distinct(key, {"type": "version"}) - @six.add_metaclass(ABCMeta) class TextureProcessor: @@ -612,7 +612,7 @@ def _process_texture(self, filepath, processors, staging, linearize, force): # n fname, ext = os.path.splitext(os.path.basename(filepath)) args = [] - texture_hash = openpype.api.source_hash(filepath, *args) + texture_hash = source_hash(filepath, *args) # If source has been published before with the same settings, # then don't reprocess but hardlink from the original From 035281fa4c939e6e56d356a97535cf837cc933a2 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 4 Oct 2022 11:08:27 +0300 Subject: [PATCH 085/898] Style fix --- openpype/hosts/maya/plugins/publish/extract_look.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index f3128306eeb..6b0fe36d8f5 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -94,6 +94,7 @@ def find_paths_by_hash(texture_hash): key = "data.sourceHashes.{0}".format(texture_hash) return legacy_io.distinct(key, {"type": "version"}) + @six.add_metaclass(ABCMeta) class TextureProcessor: From 18435fa7065065d8446c3b0448f664f9ef4a8123 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 4 Oct 2022 14:11:30 +0300 Subject: [PATCH 086/898] Add validation to check for texture --- .../plugins/publish/validate_look_contents.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/openpype/hosts/maya/plugins/publish/validate_look_contents.py b/openpype/hosts/maya/plugins/publish/validate_look_contents.py index 53501d11e52..837e8ea3a29 100644 --- a/openpype/hosts/maya/plugins/publish/validate_look_contents.py +++ b/openpype/hosts/maya/plugins/publish/validate_look_contents.py @@ -1,6 +1,7 @@ import pyblish.api import openpype.hosts.maya.api.action from openpype.pipeline.publish import ValidateContentsOrder +from maya import cmds # noqa class ValidateLookContents(pyblish.api.InstancePlugin): @@ -85,6 +86,7 @@ def validate_lookdata_attributes(cls, instance): invalid.add(instance.name) return list(invalid) + @classmethod def validate_looks(cls, instance): @@ -112,3 +114,23 @@ def validate_files(cls, instance): invalid.append(node) return invalid + + @classmethod + def validate_renderer(cls, instance): + + renderer = cmds.getAttr( + 'defaultRenderGlobals.currentRenderer').lower() + do_maketx = instance.data.get("maketx", False) + do_rstex = instance.data.get("rstex", False) + processors = [] + + if do_maketx: + processors.append('arnold') + if do_rstex: + processors.append('redshift') + + for processor in processors: + if processor == renderer: + continue + else: + cls.log.error("Converted texture does not match current renderer.") # noqa From 3728ce0a586820bd0e7619dd7acc5cff82e0f918 Mon Sep 17 00:00:00 2001 From: Allan Ihsan Date: Tue, 4 Oct 2022 14:16:54 +0300 Subject: [PATCH 087/898] Style fix --- openpype/hosts/maya/plugins/publish/validate_look_contents.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_look_contents.py b/openpype/hosts/maya/plugins/publish/validate_look_contents.py index 837e8ea3a29..5e242ed3d2f 100644 --- a/openpype/hosts/maya/plugins/publish/validate_look_contents.py +++ b/openpype/hosts/maya/plugins/publish/validate_look_contents.py @@ -119,7 +119,7 @@ def validate_files(cls, instance): def validate_renderer(cls, instance): renderer = cmds.getAttr( - 'defaultRenderGlobals.currentRenderer').lower() + 'defaultRenderGlobals.currentRenderer').lower() do_maketx = instance.data.get("maketx", False) do_rstex = instance.data.get("rstex", False) processors = [] From dc2baf29069afddad2c1c3a9acff64c85b7d8968 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 4 Jan 2023 14:56:40 +0800 Subject: [PATCH 088/898] check whether the ocio config enabled in maya for colorspace in maya --- .../hosts/maya/plugins/publish/extract_look.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index df07a674dcb..efe6c3c062a 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -367,10 +367,19 @@ def process_resources(self, instance, staging_dir): for filepath in files_metadata: linearize = False - if do_maketx and files_metadata[filepath]["color_space"].lower() == "srgb": # noqa: E501 - linearize = True - # set its file node to 'raw' as tx will be linearized - files_metadata[filepath]["color_space"] = "Raw" + # if OCIO color management enabled + # it wont take the condition of the files_metadata + + # TODO: if do_maketx: linearize=False + ocio_maya = cmds.colorManagementPrefs(q=True, + cmConfigFileEnabled=True, + cmEnabled=True) + + if do_maketx and not ocio_maya: + if files_metadata[filepath]["color_space"].lower() == "srgb": # noqa: E501 + linearize = True + # set its file node to 'raw' as tx will be linearized + files_metadata[filepath]["color_space"] = "Raw" # if do_maketx: # color_space = "Raw" @@ -421,6 +430,7 @@ def process_resources(self, instance, staging_dir): color_space_attr = resource["node"] + ".colorSpace" try: color_space = cmds.getAttr(color_space_attr) + self.log.info("current colorspace: {0}".format(color_space)) except ValueError: # node doesn't have color space attribute color_space = "Raw" From e045cc95be4d9dc242536bfa5388a002171659b5 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 4 Jan 2023 15:10:43 +0800 Subject: [PATCH 089/898] check whether the ocio config enabled in maya for colorspace in maya --- openpype/hosts/maya/plugins/publish/extract_look.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index efe6c3c062a..878c2dceae7 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -370,7 +370,6 @@ def process_resources(self, instance, staging_dir): # if OCIO color management enabled # it wont take the condition of the files_metadata - # TODO: if do_maketx: linearize=False ocio_maya = cmds.colorManagementPrefs(q=True, cmConfigFileEnabled=True, cmEnabled=True) @@ -430,7 +429,6 @@ def process_resources(self, instance, staging_dir): color_space_attr = resource["node"] + ".colorSpace" try: color_space = cmds.getAttr(color_space_attr) - self.log.info("current colorspace: {0}".format(color_space)) except ValueError: # node doesn't have color space attribute color_space = "Raw" From 1ba5223801fa9fa6695fa62a59dd53eaca7be27c Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 4 Jan 2023 23:49:07 +0800 Subject: [PATCH 090/898] adding optional validator for maya color space --- .../publish/validate_look_color_space.py | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 openpype/hosts/maya/plugins/publish/validate_look_color_space.py diff --git a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py new file mode 100644 index 00000000000..6839df1d723 --- /dev/null +++ b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py @@ -0,0 +1,28 @@ +from maya import cmds + +import pyblish.api +import openpype.hosts.maya.api.action +from openpype.pipeline.publish import ValidateContentsOrder + + +class ValidateMayaColorSpace(pyblish.api.InstancePlugin): + """ + Check if the OCIO Color Management and maketx options + enabled at the same time + + """ + + order = ValidateContentsOrder + families = ['look'] + hosts = ['maya'] + label = 'Maya Color Space' + optional = True + + def process(self, instance): + ocio_maya = cmds.colorManagementPrefs(q=True, + cmConfigFileEnabled=True, + cmEnabled=True) + maketx = instance.data["maketx"] + + if ocio_maya and maketx: + raise Exception("Maya is color managed and maketx option is on. OpenPype doesn't support this combination yet.") # noqa From e9b149ee6a62372daf903b0f0060b58e566eaa9a Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 4 Jan 2023 23:50:05 +0800 Subject: [PATCH 091/898] adding optional validator for maya color space --- openpype/hosts/maya/plugins/publish/validate_look_color_space.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py index 6839df1d723..e309e25da9d 100644 --- a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py +++ b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py @@ -1,7 +1,6 @@ from maya import cmds import pyblish.api -import openpype.hosts.maya.api.action from openpype.pipeline.publish import ValidateContentsOrder From e436dbb57e86948b54cc4f54591376f5f6ff42ca Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 5 Jan 2023 11:53:17 +0800 Subject: [PATCH 092/898] add the validator into the settings --- .../hosts/maya/plugins/publish/validate_look_color_space.py | 1 - openpype/settings/defaults/project_settings/maya.json | 5 +++++ .../schemas/projects_schema/schemas/schema_maya_publish.json | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py index e309e25da9d..933951501cb 100644 --- a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py +++ b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py @@ -15,7 +15,6 @@ class ValidateMayaColorSpace(pyblish.api.InstancePlugin): families = ['look'] hosts = ['maya'] label = 'Maya Color Space' - optional = True def process(self, instance): ocio_maya = cmds.colorManagementPrefs(q=True, diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index 5f40c2a10c3..21815278a8d 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -306,6 +306,11 @@ "optional": true, "active": true }, + "ValidateMayaColorSpace": { + "enabled": true, + "optional": true, + "active": true + }, "ValidateAttributes": { "enabled": false, "attributes": {} diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json index 9aaff248abb..a920d5aeae1 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json @@ -144,6 +144,10 @@ { "key": "ValidateShadingEngine", "label": "Validate Look Shading Engine Naming" + }, + { + "key": "ValidateMayaColorSpace", + "label": "ValidateMayaColorSpace" } ] }, From baca6a93c3d1208960b68d95dbc3b19bd58d5725 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 9 Jan 2023 16:44:40 +0800 Subject: [PATCH 093/898] remove the validator for color-space --- .../publish/validate_look_color_space.py | 26 ------------------- .../defaults/project_settings/maya.json | 5 ---- .../schemas/schema_maya_publish.json | 4 --- 3 files changed, 35 deletions(-) delete mode 100644 openpype/hosts/maya/plugins/publish/validate_look_color_space.py diff --git a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py deleted file mode 100644 index 933951501cb..00000000000 --- a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py +++ /dev/null @@ -1,26 +0,0 @@ -from maya import cmds - -import pyblish.api -from openpype.pipeline.publish import ValidateContentsOrder - - -class ValidateMayaColorSpace(pyblish.api.InstancePlugin): - """ - Check if the OCIO Color Management and maketx options - enabled at the same time - - """ - - order = ValidateContentsOrder - families = ['look'] - hosts = ['maya'] - label = 'Maya Color Space' - - def process(self, instance): - ocio_maya = cmds.colorManagementPrefs(q=True, - cmConfigFileEnabled=True, - cmEnabled=True) - maketx = instance.data["maketx"] - - if ocio_maya and maketx: - raise Exception("Maya is color managed and maketx option is on. OpenPype doesn't support this combination yet.") # noqa diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index 21815278a8d..5f40c2a10c3 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -306,11 +306,6 @@ "optional": true, "active": true }, - "ValidateMayaColorSpace": { - "enabled": true, - "optional": true, - "active": true - }, "ValidateAttributes": { "enabled": false, "attributes": {} diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json index a920d5aeae1..9aaff248abb 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json @@ -144,10 +144,6 @@ { "key": "ValidateShadingEngine", "label": "Validate Look Shading Engine Naming" - }, - { - "key": "ValidateMayaColorSpace", - "label": "ValidateMayaColorSpace" } ] }, From a380069aad8ff9445666637aac638ae37f04eac4 Mon Sep 17 00:00:00 2001 From: Simone Barbieri Date: Mon, 9 Jan 2023 16:23:46 +0000 Subject: [PATCH 094/898] Hound fixes --- openpype/hosts/blender/api/capture.py | 2 +- openpype/hosts/blender/api/lib.py | 1 + openpype/hosts/blender/plugins/publish/collect_review.py | 2 +- openpype/hosts/blender/plugins/publish/extract_playblast.py | 3 +-- openpype/hosts/blender/plugins/publish/extract_thumbnail.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/blender/api/capture.py b/openpype/hosts/blender/api/capture.py index 7cf9e52cb61..849f8ee6298 100644 --- a/openpype/hosts/blender/api/capture.py +++ b/openpype/hosts/blender/api/capture.py @@ -275,4 +275,4 @@ def _independent_window(): try: yield window finally: - bpy.ops.wm.window_close(context) \ No newline at end of file + bpy.ops.wm.window_close(context) diff --git a/openpype/hosts/blender/api/lib.py b/openpype/hosts/blender/api/lib.py index dd3cc48a985..6526f1fb870 100644 --- a/openpype/hosts/blender/api/lib.py +++ b/openpype/hosts/blender/api/lib.py @@ -285,6 +285,7 @@ def maintained_selection(): # context. log.exception("Failed to set active object.") + @contextlib.contextmanager def maintained_time(): """Maintain current frame during context.""" diff --git a/openpype/hosts/blender/plugins/publish/collect_review.py b/openpype/hosts/blender/plugins/publish/collect_review.py index 09b5558d317..d6abd9d967a 100644 --- a/openpype/hosts/blender/plugins/publish/collect_review.py +++ b/openpype/hosts/blender/plugins/publish/collect_review.py @@ -61,4 +61,4 @@ def process(self, instance): "offset": track.offset.get(), "filename": track.filename.get(), } - ) \ No newline at end of file + ) diff --git a/openpype/hosts/blender/plugins/publish/extract_playblast.py b/openpype/hosts/blender/plugins/publish/extract_playblast.py index d07968d4692..1114b633be0 100644 --- a/openpype/hosts/blender/plugins/publish/extract_playblast.py +++ b/openpype/hosts/blender/plugins/publish/extract_playblast.py @@ -23,7 +23,6 @@ class ExtractPlayblast(openpype.api.Extractor): optional = True order = pyblish.api.ExtractorOrder + 0.01 - def process(self, instance): self.log.info("Extracting capture..") @@ -122,4 +121,4 @@ def process(self, instance): "tags": tags, "camera_name": camera } - instance.data["representations"].append(representation) \ No newline at end of file + instance.data["representations"].append(representation) diff --git a/openpype/hosts/blender/plugins/publish/extract_thumbnail.py b/openpype/hosts/blender/plugins/publish/extract_thumbnail.py index 3fabdf61e08..5e9d876989f 100644 --- a/openpype/hosts/blender/plugins/publish/extract_thumbnail.py +++ b/openpype/hosts/blender/plugins/publish/extract_thumbnail.py @@ -99,4 +99,4 @@ def _fix_output_path(self, filepath): raise RuntimeError(f"Couldn't find playblast from: {filepath}") filepath = max(files, key=os.path.getmtime) - return filepath \ No newline at end of file + return filepath From 1575f24539b134f4e19315529338060c4d6ab00f Mon Sep 17 00:00:00 2001 From: Simone Barbieri Date: Wed, 11 Jan 2023 15:51:01 +0000 Subject: [PATCH 095/898] Remove OCIO submodule --- vendor/configs/OpenColorIO-Configs | 1 - 1 file changed, 1 deletion(-) delete mode 160000 vendor/configs/OpenColorIO-Configs diff --git a/vendor/configs/OpenColorIO-Configs b/vendor/configs/OpenColorIO-Configs deleted file mode 160000 index 0bb079c08be..00000000000 --- a/vendor/configs/OpenColorIO-Configs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0bb079c08be410030669cbf5f19ff869b88af953 From 255fd940a1bb2c9cfab2bca9e064a036abf86ab4 Mon Sep 17 00:00:00 2001 From: Simone Barbieri Date: Wed, 11 Jan 2023 15:51:28 +0000 Subject: [PATCH 096/898] Fix default settings syntax error --- openpype/settings/defaults/project_settings/blender.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/settings/defaults/project_settings/blender.json b/openpype/settings/defaults/project_settings/blender.json index e0adeb96daf..7eabec61060 100644 --- a/openpype/settings/defaults/project_settings/blender.json +++ b/openpype/settings/defaults/project_settings/blender.json @@ -65,7 +65,7 @@ "enabled": true, "optional": true, "active": false - } + }, "ExtractThumbnail": { "enabled": true, "optional": true, From 1f45f8c5b37a3d42936ff068467ba78725fad84b Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 13 Jan 2023 23:08:23 +0800 Subject: [PATCH 097/898] add validator to the look publish --- .../publish/validate_look_color_space.py | 25 +++++++++++++++++++ .../defaults/project_settings/maya.json | 5 ++++ .../schemas/schema_maya_publish.json | 4 +++ 3 files changed, 34 insertions(+) create mode 100644 openpype/hosts/maya/plugins/publish/validate_look_color_space.py diff --git a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py new file mode 100644 index 00000000000..05a10fd9f6b --- /dev/null +++ b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py @@ -0,0 +1,25 @@ +from maya import cmds + +import pyblish.api +from openpype.pipeline.publish import ValidateContentsOrder + + +class ValidateMayaColorSpace(pyblish.api.InstancePlugin): + """ + Check if the OCIO Color Management and maketx options + enabled at the same time + """ + + order = ValidateContentsOrder + families = ['look'] + hosts = ['maya'] + label = 'Maya Color Space' + + def process(self, instance): + ocio_maya = cmds.colorManagementPrefs(q=True, + cmConfigFileEnabled=True, + cmEnabled=True) + maketx = instance.data["maketx"] + + if ocio_maya and maketx: + raise Exception("Maya is color managed and maketx option is on. OpenPype doesn't support this combination yet.") # noqa diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index 5f40c2a10c3..21815278a8d 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -306,6 +306,11 @@ "optional": true, "active": true }, + "ValidateMayaColorSpace": { + "enabled": true, + "optional": true, + "active": true + }, "ValidateAttributes": { "enabled": false, "attributes": {} diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json index 9aaff248abb..a920d5aeae1 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json @@ -144,6 +144,10 @@ { "key": "ValidateShadingEngine", "label": "Validate Look Shading Engine Naming" + }, + { + "key": "ValidateMayaColorSpace", + "label": "ValidateMayaColorSpace" } ] }, From d206a64e936569c6b0b3719279dc82716ff9ba60 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Sat, 14 Jan 2023 00:09:16 +0800 Subject: [PATCH 098/898] adding info to tell user the tx conversion based on ocio.config --- openpype/hosts/maya/plugins/publish/extract_look.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 878c2dceae7..860872c3a6a 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -535,6 +535,9 @@ def _process_texture(self, filepath, do_maketx, staging, linearize, force): self.log.info("tx: converting sRGB -> linear") additional_args.extend(["--colorconvert", "sRGB", "linear"]) + self.log.info("Using nuke-default ocio config instead of maya ocio config!") # noqa + self.log.info("The tx conversion is different from the maya tx conversion!") # noqa + config_path = get_ocio_config_path("nuke-default") additional_args.extend(["--colorconfig", config_path]) # Ensure folder exists From 1da3854c82e6145e42d2e986263e4dbe7f5d950e Mon Sep 17 00:00:00 2001 From: Simone Barbieri Date: Mon, 16 Jan 2023 11:04:22 +0000 Subject: [PATCH 099/898] Implemented suggestions --- .../hosts/blender/plugins/publish/extract_thumbnail.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/blender/plugins/publish/extract_thumbnail.py b/openpype/hosts/blender/plugins/publish/extract_thumbnail.py index 5e9d876989f..ba455cf450a 100644 --- a/openpype/hosts/blender/plugins/publish/extract_thumbnail.py +++ b/openpype/hosts/blender/plugins/publish/extract_thumbnail.py @@ -21,6 +21,7 @@ class ExtractThumbnail(openpype.api.Extractor): hosts = ["blender"] families = ["review"] order = pyblish.api.ExtractorOrder + 0.01 + presets = {} def process(self, instance): self.log.info("Extracting capture..") @@ -36,11 +37,7 @@ def process(self, instance): family = instance.data.get("family") isolate = instance.data("isolate", None) - project_settings = instance.context.data["project_settings"]["blender"] - extractor_settings = project_settings["publish"]["ExtractThumbnail"] - presets = extractor_settings.get("presets") - - preset = presets.get(family, {}) + preset = self.presets.get(family, {}) preset.update({ "camera": camera, From 93c5d507a3fa6d8ea8592e1ad5217cc31fa0fbb9 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 16 Jan 2023 22:25:54 +0800 Subject: [PATCH 100/898] use RuntimeError instead of Exception and rename the validator --- .../hosts/maya/plugins/publish/validate_look_color_space.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py index 05a10fd9f6b..9225feda243 100644 --- a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py +++ b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py @@ -1,3 +1,4 @@ +import os from maya import cmds import pyblish.api @@ -13,7 +14,7 @@ class ValidateMayaColorSpace(pyblish.api.InstancePlugin): order = ValidateContentsOrder families = ['look'] hosts = ['maya'] - label = 'Maya Color Space' + label = 'Color Management with maketx' def process(self, instance): ocio_maya = cmds.colorManagementPrefs(q=True, @@ -22,4 +23,4 @@ def process(self, instance): maketx = instance.data["maketx"] if ocio_maya and maketx: - raise Exception("Maya is color managed and maketx option is on. OpenPype doesn't support this combination yet.") # noqa + raise RuntimeError("Maya is color managed and maketx option is on. OpenPype doesn't support this combination yet.") # noqa From d57a7c67cd7ded6eae21ebf0145acf2642b54e63 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 16 Jan 2023 22:26:59 +0800 Subject: [PATCH 101/898] use RuntimeError instead of Exception and rename the validator --- openpype/hosts/maya/plugins/publish/validate_look_color_space.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py index 9225feda243..b354d51fefe 100644 --- a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py +++ b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py @@ -1,4 +1,3 @@ -import os from maya import cmds import pyblish.api From 36eeb976f78cd3a038454caeebdad0703f673c4f Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 26 Jan 2023 16:04:41 +0100 Subject: [PATCH 102/898] New style creator --- .../houdini/plugins/create/create_review.py | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/openpype/hosts/houdini/plugins/create/create_review.py b/openpype/hosts/houdini/plugins/create/create_review.py index 36d87ba8dee..a1bcfc23edb 100644 --- a/openpype/hosts/houdini/plugins/create/create_review.py +++ b/openpype/hosts/houdini/plugins/create/create_review.py @@ -1,9 +1,14 @@ from openpype.hosts.houdini.api import plugin +from openpype.pipeline import ( + CreatedInstance, + OpenPypePyblishPluginMixin +) -class CreateReview(plugin.Creator): +class CreateReview(plugin.HoudiniCreator, OpenPypePyblishPluginMixin): """Review with OpenGL ROP""" + identifier = "io.openpype.creators.houdini.review" label = "Review" family = "review" icon = "video-camera" @@ -15,27 +20,26 @@ class CreateReview(plugin.Creator): height = 720 aspect = 1.0 - def __init__(self, *args, **kwargs): - super(CreateReview, self).__init__(*args, **kwargs) + def create(self, subset_name, instance_data, pre_create_data): - # Remove the active, we are checking the bypass flag of the nodes - self.data.pop("active", None) + import hou - self.data.update({"node_type": "opengl"}) + # Remove the active, we are checking the bypass flag of the nodes + instance_data.pop("active", None) - def _process(self, instance): - """Creator main entry point. + instance_data["node_type"] = "opengl" - Args: - instance (hou.Node): Created Houdini instance. + instance = super(CreateReview, self).create( + subset_name, + instance_data, + pre_create_data) # type: CreatedInstance - """ - import hou + instance_node = hou.node(instance.get("instance_node")) frame_range = hou.playbar.frameRange() parms = { - "picture": "$HIP/pyblish/{0}/{0}.$F4.png".format(self.name), + "picture": '$HIP/pyblish/`chs("subset")`/`chs("subset")`.$F4.png', # Render frame range "trange": 1, @@ -55,19 +59,16 @@ def _process(self, instance): "aspect": self.aspect }) - if self.nodes: + if self.selected_nodes: # todo: allow only object paths? - node_paths = " ".join(node.path() for node in self.nodes) + node_paths = " ".join(node.path() for node in self.selected_nodes) parms.update({"scenepath": node_paths}) - instance.setParms(parms) + instance_node.setParms(parms) # Lock any parameters in this list to_lock = [ - # Lock some Avalon attributes "family", - "id", + "id" ] - for name in to_lock: - parm = instance.parm(name) - parm.lock(True) + self.lock_parameters(instance_node, to_lock) From e02b6f7073861c20b26782eac480a2a1e7f10f54 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 26 Jan 2023 16:07:11 +0100 Subject: [PATCH 103/898] Fix extractor for new style creator --- openpype/hosts/houdini/plugins/publish/extract_opengl.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/houdini/plugins/publish/extract_opengl.py b/openpype/hosts/houdini/plugins/publish/extract_opengl.py index f99c9876342..8357e188a80 100644 --- a/openpype/hosts/houdini/plugins/publish/extract_opengl.py +++ b/openpype/hosts/houdini/plugins/publish/extract_opengl.py @@ -4,6 +4,8 @@ import openpype.api from openpype.hosts.houdini.api.lib import render_rop +import hou + class ExtractOpenGL(openpype.api.Extractor): @@ -15,7 +17,7 @@ class ExtractOpenGL(openpype.api.Extractor): def process(self, instance): - ropnode = instance[0] + ropnode = hou.node(instance.data["instance_node"]) # Get the filename from the filename parameter # `.evalParm(parameter)` will make sure all tokens are resolved From 9c221a36c30a05de6c9b67e17b4ca941f01a4c31 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Sun, 29 Jan 2023 15:22:52 +0300 Subject: [PATCH 104/898] use recommended Reactor env variables --- openpype/hosts/fusion/deploy/fusion_shared.prefs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/deploy/fusion_shared.prefs b/openpype/hosts/fusion/deploy/fusion_shared.prefs index 998c6a6d663..5bfde9a5c9e 100644 --- a/openpype/hosts/fusion/deploy/fusion_shared.prefs +++ b/openpype/hosts/fusion/deploy/fusion_shared.prefs @@ -4,8 +4,7 @@ Global = { Paths = { Map = { ["OpenPype:"] = "$(OPENPYPE_FUSION)/deploy", - ["Reactor:"] = "$(REACTOR)", - + ["Reactor:"] = "$(REACTOR_INSTALL_PATHMAP)/Reactor", ["Config:"] = "UserPaths:Config;OpenPype:Config", ["Scripts:"] = "UserPaths:Scripts;Reactor:System/Scripts;OpenPype:Scripts", ["UserPaths:"] = "UserData:;AllData:;Fusion:;Reactor:Deploy" From bb0d128f1d4b22f6744eed58ad91f649b8642d83 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Sun, 29 Jan 2023 22:37:07 +0300 Subject: [PATCH 105/898] nightly version is not parsed --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ceab9eeff1e..2fc4f6fe390 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "OpenPype" -version = "3.15.1-nightly.1" # OpenPype +version = "3.15.1" # OpenPype description = "Open VFX and Animation pipeline with support." authors = ["OpenPype Team "] license = "MIT License" From c1f88602a09bd7b476344f2a1fbf8efb8789734d Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Tue, 31 Jan 2023 03:14:43 +0300 Subject: [PATCH 106/898] split get comp and get fusion, add get comp name just in case --- openpype/hosts/fusion/api/lib.py | 22 +++++++++++++++++++--- openpype/hosts/fusion/api/workio.py | 7 ++----- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/fusion/api/lib.py b/openpype/hosts/fusion/api/lib.py index a33e5cf289b..851e9ec94a7 100644 --- a/openpype/hosts/fusion/api/lib.py +++ b/openpype/hosts/fusion/api/lib.py @@ -302,10 +302,26 @@ def get_frame_path(path): return filename, padding, ext +def get_comp_name(comp=None): + """Get basename of the comp's filename""" + if comp: + comp_name = os.path.basename(comp.GetAttrs()["COMPS_FileName"]) + return comp_name + + +def get_fusion(): + """Get Fusion instance""" + app = getattr(sys.modules["BlackmagicFusion"], "scriptapp", None) + if app: + fusion = app("Fusion", "localhost") + return fusion + + def get_current_comp(): - """Hack to get current comp in this session""" - fusion = getattr(sys.modules["__main__"], "fusion", None) - return fusion.CurrentComp if fusion else None + """Get current comp in this session""" + fusion = get_fusion() + comp = fusion.CurrentComp + return comp @contextlib.contextmanager diff --git a/openpype/hosts/fusion/api/workio.py b/openpype/hosts/fusion/api/workio.py index 939b2ff4be1..da36a83988e 100644 --- a/openpype/hosts/fusion/api/workio.py +++ b/openpype/hosts/fusion/api/workio.py @@ -2,7 +2,7 @@ import sys import os -from .lib import get_current_comp +from .lib import get_fusion, get_current_comp def file_extensions(): @@ -20,10 +20,7 @@ def save_file(filepath): def open_file(filepath): - # Hack to get fusion, see - # openpype.hosts.fusion.api.pipeline.get_current_comp() - fusion = getattr(sys.modules["__main__"], "fusion", None) - + fusion = get_fusion() return fusion.LoadComp(filepath) From c0c859b6f1f0c34db4c0024a4b751c9715d5c6bf Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Tue, 31 Jan 2023 03:15:43 +0300 Subject: [PATCH 107/898] set a temporary profile folder, copy existing prefs there --- .../hosts/fusion/hooks/pre_fusion_setup.py | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index d043d543227..f6cec86e3bb 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -1,4 +1,7 @@ import os +import shutil +import platform +from pathlib import Path from openpype.lib import PreLaunchHook, ApplicationLaunchFailed from openpype.hosts.fusion import FUSION_HOST_DIR @@ -17,6 +20,25 @@ class FusionPrelaunch(PreLaunchHook): """ app_groups = ["fusion"] + def get_profile_source(self): + fusion_prefs_path = "Blackmagic Design/Fusion/Profiles/Default/Fusion.prefs" + if platform.system() == "Windows": + prefs_source = Path(os.getenv("AppData")) / fusion_prefs_path + elif platform.system() == "Darwin": + prefs_source = Path(os.path.expanduser("~/Library/Application Support/")) / fusion_prefs_path + elif platform.system() == "Linux": + prefs_source = Path(os.path.expanduser("~/.fusion")) / fusion_prefs_path + + return str(prefs_source) + + def copy_existing_prefs(self, profile_directory: str): + dest_folder = os.path.join(profile_directory, "Default") + os.makedirs(dest_folder, exist_ok=True) + prefs_source = self.get_profile_source() + if os.path.exists(prefs_source): + shutil.copy(prefs_source, dest_folder) + self.log.info(f"successfully copied preferences:\n {prefs_source} to {dest_folder}") + def execute(self): # making sure python 3 is installed at provided path # Py 3.3-3.10 for Fusion 18+ or Py 3.6 for Fu 16-17 @@ -50,12 +72,20 @@ def execute(self): # TODO: Detect Fusion version to only set for specific Fusion build self.launch_context.env["FUSION16_PYTHON36_HOME"] = py3_dir - # Add our Fusion Master Prefs which is the only way to customize + # Add custom Fusion Master Prefs and the temporary profile directory variables to customize # Fusion to define where it can read custom scripts and tools from self.log.info(f"Setting OPENPYPE_FUSION: {FUSION_HOST_DIR}") self.launch_context.env["OPENPYPE_FUSION"] = FUSION_HOST_DIR + profile_dir_var = "FUSION16_PROFILE_DIR" # used by Fusion 16, 17 and 18 pref_var = "FUSION16_MasterPrefs" # used by Fusion 16, 17 and 18 + profile_dir = os.path.join(FUSION_HOST_DIR, "deploy", "Prefs") prefs = os.path.join(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") + + # now copy the default Fusion profile to a working directory + if not os.path.exists(profile_dir): + self.copy_existing_prefs(profile_dir) + self.log.info(f"Setting {profile_dir_var}: {profile_dir}") + self.launch_context.env[profile_dir_var] = profile_dir self.log.info(f"Setting {pref_var}: {prefs}") self.launch_context.env[pref_var] = prefs From 0c23f212c08811d2fb3cafa2980f0344afee5a5b Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Tue, 31 Jan 2023 03:18:20 +0300 Subject: [PATCH 108/898] remove Reactor mapping as it is copied from existing prefs --- openpype/hosts/fusion/deploy/fusion_shared.prefs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/deploy/fusion_shared.prefs b/openpype/hosts/fusion/deploy/fusion_shared.prefs index 5bfde9a5c9e..d9451ea295d 100644 --- a/openpype/hosts/fusion/deploy/fusion_shared.prefs +++ b/openpype/hosts/fusion/deploy/fusion_shared.prefs @@ -4,10 +4,9 @@ Global = { Paths = { Map = { ["OpenPype:"] = "$(OPENPYPE_FUSION)/deploy", - ["Reactor:"] = "$(REACTOR_INSTALL_PATHMAP)/Reactor", ["Config:"] = "UserPaths:Config;OpenPype:Config", ["Scripts:"] = "UserPaths:Scripts;Reactor:System/Scripts;OpenPype:Scripts", - ["UserPaths:"] = "UserData:;AllData:;Fusion:;Reactor:Deploy" + ["UserPaths:"] = "UserData:;GIT:;AllData:;Fusion:;Reactor:Deploy" }, }, Script = { From a07aed0c40dfe7d8fc7c7ae83503020ef5238aec Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 1 Feb 2023 16:47:54 +0800 Subject: [PATCH 109/898] some edits on the color convert if the color workflow being linearized --- .../maya/plugins/publish/extract_look.py | 23 ++++++++++++++----- .../publish/validate_look_color_space.py | 1 + 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 860872c3a6a..22c95d04dca 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -385,6 +385,7 @@ def process_resources(self, instance, staging_dir): source, mode, texture_hash = self._process_texture( filepath, + resource, do_maketx, staging=staging_dir, linearize=linearize, @@ -490,7 +491,7 @@ def resource_destination(self, instance, filepath, do_maketx): resources_dir, basename + ext ) - def _process_texture(self, filepath, do_maketx, staging, linearize, force): + def _process_texture(self, filepath, resource, do_maketx, staging, linearize, force): """Process a single texture file on disk for publishing. This will: 1. Check whether it's already published, if so it will do hardlink @@ -532,11 +533,21 @@ def _process_texture(self, filepath, do_maketx, staging, linearize, force): texture_hash ] if linearize: - self.log.info("tx: converting sRGB -> linear") - additional_args.extend(["--colorconvert", "sRGB", "linear"]) - - self.log.info("Using nuke-default ocio config instead of maya ocio config!") # noqa - self.log.info("The tx conversion is different from the maya tx conversion!") # noqa + if cmds.colorManagementPrefs(query=True, cmEnabled=True): + render_colorspace = cmds.colorManagementPrefs(query=True, + renderingSpaceName=True) + color_space_attr = resource["node"] + ".colorSpace" + try: + color_space = cmds.getAttr(color_space_attr) + except ValueError: + # node doesn't have color space attribute + color_space = "Raw" + self.log.info("tx: converting {0} -> {1}".format(color_space, + render_colorspace)) + additional_args.extend(["--colorconvert", color_space, render_colorspace]) + else: + self.log.info("tx: converting sRGB -> linear") + additional_args.extend(["--colorconvert", "sRGB", "Raw"]) config_path = get_ocio_config_path("nuke-default") additional_args.extend(["--colorconfig", config_path]) diff --git a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py index b354d51fefe..103ade09b17 100644 --- a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py +++ b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py @@ -14,6 +14,7 @@ class ValidateMayaColorSpace(pyblish.api.InstancePlugin): families = ['look'] hosts = ['maya'] label = 'Color Management with maketx' + optional = True def process(self, instance): ocio_maya = cmds.colorManagementPrefs(q=True, From aa2f845204b7b4f24e49811d4cb69ce4ccb3858e Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 1 Feb 2023 17:38:18 +0800 Subject: [PATCH 110/898] hound fix --- openpype/hosts/maya/plugins/publish/extract_look.py | 13 +++++++------ .../plugins/publish/validate_look_color_space.py | 1 - 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 22c95d04dca..54b093f7c37 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -491,7 +491,8 @@ def resource_destination(self, instance, filepath, do_maketx): resources_dir, basename + ext ) - def _process_texture(self, filepath, resource, do_maketx, staging, linearize, force): + def _process_texture(self, filepath, resource, + do_maketx, staging, linearize, force): """Process a single texture file on disk for publishing. This will: 1. Check whether it's already published, if so it will do hardlink @@ -534,17 +535,17 @@ def _process_texture(self, filepath, resource, do_maketx, staging, linearize, fo ] if linearize: if cmds.colorManagementPrefs(query=True, cmEnabled=True): - render_colorspace = cmds.colorManagementPrefs(query=True, - renderingSpaceName=True) + render_colorspace = cmds.colorManagementPrefs(query=True, renderingSpaceName=True) # noqa color_space_attr = resource["node"] + ".colorSpace" try: color_space = cmds.getAttr(color_space_attr) except ValueError: # node doesn't have color space attribute color_space = "Raw" - self.log.info("tx: converting {0} -> {1}".format(color_space, - render_colorspace)) - additional_args.extend(["--colorconvert", color_space, render_colorspace]) + self.log.info("tx: converting {0} -> {1}".format(color_space, render_colorspace)) # noqa + additional_args.extend(["--colorconvert", + color_space, + render_colorspace]) else: self.log.info("tx: converting sRGB -> linear") additional_args.extend(["--colorconvert", "sRGB", "Raw"]) diff --git a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py index 103ade09b17..b354d51fefe 100644 --- a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py +++ b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py @@ -14,7 +14,6 @@ class ValidateMayaColorSpace(pyblish.api.InstancePlugin): families = ['look'] hosts = ['maya'] label = 'Color Management with maketx' - optional = True def process(self, instance): ocio_maya = cmds.colorManagementPrefs(q=True, From cfd718d943dc4b0cf22eb5bff5a10b12dfe4cf3b Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Thu, 2 Feb 2023 00:07:27 +0300 Subject: [PATCH 111/898] rollback the get_fusion, properly return comp name --- openpype/hosts/fusion/api/lib.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/fusion/api/lib.py b/openpype/hosts/fusion/api/lib.py index 851e9ec94a7..ac30e1ff997 100644 --- a/openpype/hosts/fusion/api/lib.py +++ b/openpype/hosts/fusion/api/lib.py @@ -305,16 +305,13 @@ def get_frame_path(path): def get_comp_name(comp=None): """Get basename of the comp's filename""" if comp: - comp_name = os.path.basename(comp.GetAttrs()["COMPS_FileName"]) - return comp_name + return comp.GetAttrs()["COMPS_Name"] def get_fusion(): """Get Fusion instance""" - app = getattr(sys.modules["BlackmagicFusion"], "scriptapp", None) - if app: - fusion = app("Fusion", "localhost") - return fusion + fusion = getattr(sys.modules["__main__"], "fusion", None) + return fusion def get_current_comp(): From 90ef934f495dd82606f7a7b702f6b3187622cfd7 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 2 Feb 2023 11:45:08 +0800 Subject: [PATCH 112/898] update the guess colorspace code reference from arnold --- openpype/hosts/maya/api/lib.py | 38 +++++++++++++++++++ .../maya/plugins/publish/extract_look.py | 20 +++++++--- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index 25842a47769..51da7a4b98a 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -15,6 +15,7 @@ from maya import cmds, mel import maya.api.OpenMaya as om +from arnold import * from openpype.client import ( get_project, @@ -3379,3 +3380,40 @@ def dgcontext(mtime): def get_attribute_input(attr): connections = cmds.listConnections(attr, plugs=True, destination=False) return connections[0] if connections else None + + +# Reference from Arnold +# Get Image Information for colorspace +def imageInfo(filepath): + """Take reference from makeTx.py + ImageInfo(filename): Get Image Information + AiTextureGetFormat(filename): Get Texture Format + AiTextureGetBitDepth(filename): Get Texture Bit Depth + """ + # Get Texture Information + img_info = {} + img_info['filename'] = filepath + if os.path.isfile(filepath): + img_info['bit_depth'] = AiTextureGetBitDepth(filepath) + img_info['format'] = AiTextureGetFormat(filepath) + else: + img_info['bit_depth'] = 8 + img_info['format'] = "unknown" + return img_info + +def guess_colorspace(img_info): + ''' Take reference from makeTx.py + Guess the colorspace of the input image filename. + @return: a string suitable for the --colorconvert option of maketx (linear, sRGB, Rec709) + ''' + try: + if img_info['bit_depth'] <= 16 and img_info['format'] in (AI_TYPE_BYTE, AI_TYPE_INT, AI_TYPE_UINT): + return 'sRGB' + else: + return 'linear' + + # now discard the image file as AiTextureGetFormat has loaded it + AiTextureInvalidate(img_info['filename']) + except: + print('[maketx] Error: Could not guess colorspace for "%s"' % img_info['filename']) + return 'linear' diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 54b093f7c37..5ac5d9c728d 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -16,6 +16,7 @@ from openpype.lib import source_hash, run_subprocess from openpype.pipeline import legacy_io, publish from openpype.hosts.maya.api import lib +from openpype.hosts.maya.api.lib import imageInfo, guess_colorspace # Modes for transfer COPY = 1 @@ -541,16 +542,25 @@ def _process_texture(self, filepath, resource, color_space = cmds.getAttr(color_space_attr) except ValueError: # node doesn't have color space attribute - color_space = "Raw" + img_info = imageInfo(filepath) + color_space = guess_colorspace(img_info) self.log.info("tx: converting {0} -> {1}".format(color_space, render_colorspace)) # noqa additional_args.extend(["--colorconvert", color_space, render_colorspace]) else: - self.log.info("tx: converting sRGB -> linear") - additional_args.extend(["--colorconvert", "sRGB", "Raw"]) - - config_path = get_ocio_config_path("nuke-default") + img_info = imageInfo(filepath) + color_space = guess_colorspace(img_info) + if color_space == "sRGB": + self.log.info("tx: converting sRGB -> linear") + additional_args.extend(["--colorconvert", "sRGB", "Raw"]) + else: + self.log.info("tx: texture's colorspace is already linear") + + + config_path = cmds.colorManagementPrefs(query=True, configFilePath=True) + if not os.path.exists(config_path): + raise RuntimeError("No OCIO config path found!") additional_args.extend(["--colorconfig", config_path]) # Ensure folder exists if not os.path.exists(os.path.dirname(converted)): From 1df0eb1fd82460298db2e279a83a299fe5504ee1 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 2 Feb 2023 12:00:49 +0800 Subject: [PATCH 113/898] update the guess colorspace code reference from arnold --- openpype/hosts/maya/api/lib.py | 26 +++++++++++-------- .../maya/plugins/publish/extract_look.py | 11 +++++--- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index 51da7a4b98a..e20ae15228c 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -15,7 +15,7 @@ from maya import cmds, mel import maya.api.OpenMaya as om -from arnold import * +from arnold import * # noqa from openpype.client import ( get_project, @@ -3390,12 +3390,13 @@ def imageInfo(filepath): AiTextureGetFormat(filename): Get Texture Format AiTextureGetBitDepth(filename): Get Texture Bit Depth """ + # Get Texture Information img_info = {} img_info['filename'] = filepath if os.path.isfile(filepath): - img_info['bit_depth'] = AiTextureGetBitDepth(filepath) - img_info['format'] = AiTextureGetFormat(filepath) + img_info['bit_depth'] = AiTextureGetBitDepth(filepath) # noqa + img_info['format'] = AiTextureGetFormat(filepath) # noqa else: img_info['bit_depth'] = 8 img_info['format'] = "unknown" @@ -3404,16 +3405,19 @@ def imageInfo(filepath): def guess_colorspace(img_info): ''' Take reference from makeTx.py Guess the colorspace of the input image filename. - @return: a string suitable for the --colorconvert option of maketx (linear, sRGB, Rec709) + @return: a string suitable for the --colorconvert + option of maketx (linear, sRGB, Rec709) ''' try: - if img_info['bit_depth'] <= 16 and img_info['format'] in (AI_TYPE_BYTE, AI_TYPE_INT, AI_TYPE_UINT): - return 'sRGB' - else: - return 'linear' + if img_info['bit_depth'] <= 16: + if img_info['format'] in (AI_TYPE_BYTE, AI_TYPE_INT, AI_TYPE_UINT): # noqa + return 'sRGB' + else: + return 'linear' # now discard the image file as AiTextureGetFormat has loaded it - AiTextureInvalidate(img_info['filename']) - except: - print('[maketx] Error: Could not guess colorspace for "%s"' % img_info['filename']) + AiTextureInvalidate(img_info['filename']) # noqa + except ValueError: + print('[maketx] Error: Could not guess' + 'colorspace for "%s"' % img_info['filename']) return 'linear' diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 5ac5d9c728d..46f7b0e03d9 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -553,12 +553,15 @@ def _process_texture(self, filepath, resource, color_space = guess_colorspace(img_info) if color_space == "sRGB": self.log.info("tx: converting sRGB -> linear") - additional_args.extend(["--colorconvert", "sRGB", "Raw"]) + additional_args.extend(["--colorconvert", + "sRGB", + "Raw"]) else: - self.log.info("tx: texture's colorspace is already linear") + self.log.info("tx: texture's colorspace " + "is already linear") - - config_path = cmds.colorManagementPrefs(query=True, configFilePath=True) + config_path = cmds.colorManagementPrefs(query=True, + configFilePath=True) if not os.path.exists(config_path): raise RuntimeError("No OCIO config path found!") additional_args.extend(["--colorconfig", config_path]) From c1012bd03105d26c440a31797a0363180bfb0187 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 2 Feb 2023 12:01:54 +0800 Subject: [PATCH 114/898] hound fix --- openpype/hosts/maya/api/lib.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index e20ae15228c..d6a39889223 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -3402,6 +3402,7 @@ def imageInfo(filepath): img_info['format'] = "unknown" return img_info + def guess_colorspace(img_info): ''' Take reference from makeTx.py Guess the colorspace of the input image filename. From 735a35010fb9e667d3191a54cee5e01a24f2ab6a Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 2 Feb 2023 09:55:45 +0000 Subject: [PATCH 115/898] Fix assembly job submission --- .../plugins/publish/submit_maya_deadline.py | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py index 070d4eab18b..230dc526188 100644 --- a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py @@ -410,8 +410,10 @@ def _tile_render(self, payload): assembly_job_info.Name += " - Tile Assembly Job" assembly_job_info.Frames = 1 assembly_job_info.MachineLimit = 1 - assembly_job_info.Priority = instance.data.get("tile_priority", - self.tile_priority) + assembly_job_info.Priority = instance.data.get( + "tile_priority", self.tile_priority + ) + assembly_job_info.TileJob = False assembly_plugin_info = { "CleanupTiles": 1, @@ -438,13 +440,11 @@ def _tile_render(self, payload): frame_assembly_job_info.JobDependencies = tile_job_id # write assembly job config files - now = datetime.now() - config_file = os.path.join( output_dir, "{}_config_{}.txt".format( os.path.splitext(file)[0], - now.strftime("%Y_%m_%d_%H_%M_%S") + datetime.now().strftime("%Y_%m_%d_%H_%M_%S") ) ) try: @@ -455,6 +455,8 @@ def _tile_render(self, payload): self.log.warning("Path is unreachable: " "`{}`".format(output_dir)) + assembly_plugin_info["ConfigFile"] = config_file + with open(config_file, "w") as cf: print("TileCount={}".format(tiles_count), file=cf) print("ImageFileName={}".format(file), file=cf) @@ -463,6 +465,7 @@ def _tile_render(self, payload): print("ImageHeight={}".format( instance.data.get("resolutionHeight")), file=cf) + with open(config_file, "a") as cf: tiles = _format_tiles( file, 0, instance.data.get("tilesX"), @@ -474,14 +477,12 @@ def _tile_render(self, payload): for k, v in sorted(tiles.items()): print("{}={}".format(k, v), file=cf) - payload = self.assemble_payload( - job_info=frame_assembly_job_info, - plugin_info=assembly_plugin_info.copy(), - # todo: aux file transfers don't work with deadline webservice - # add config file as job auxFile - # aux_files=[config_file] + assembly_payloads.append( + self.assemble_payload( + job_info=frame_assembly_job_info, + plugin_info=assembly_plugin_info.copy(), + ) ) - assembly_payloads.append(payload) # Submit assembly jobs assembly_job_ids = [] @@ -491,6 +492,7 @@ def _tile_render(self, payload): "submitting assembly job {} of {}".format(i + 1, num_assemblies) ) + self.log.info(payload) assembly_job_id = self.submit(payload) assembly_job_ids.append(assembly_job_id) From b8084babfd436cef14755de3161dd7fc64d154de Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 2 Feb 2023 18:00:03 +0800 Subject: [PATCH 116/898] update docstring --- openpype/hosts/maya/api/lib.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index d6a39889223..f33b0c8d8e4 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -3382,11 +3382,9 @@ def get_attribute_input(attr): return connections[0] if connections else None -# Reference from Arnold -# Get Image Information for colorspace def imageInfo(filepath): - """Take reference from makeTx.py - ImageInfo(filename): Get Image Information + """Take reference from makeTx.py in Arnold + ImageInfo(filename): Get Image Information for colorspace AiTextureGetFormat(filename): Get Texture Format AiTextureGetBitDepth(filename): Get Texture Bit Depth """ From 0223d94552dda376548e8446bcea88b33de9dd19 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 2 Feb 2023 12:50:52 +0000 Subject: [PATCH 117/898] Fix OpenPypeTileAssembler --- .../OpenPypeTileAssembler.py | 92 +------------------ 1 file changed, 5 insertions(+), 87 deletions(-) diff --git a/openpype/modules/deadline/repository/custom/plugins/OpenPypeTileAssembler/OpenPypeTileAssembler.py b/openpype/modules/deadline/repository/custom/plugins/OpenPypeTileAssembler/OpenPypeTileAssembler.py index 625a3f1a28c..674938e6413 100644 --- a/openpype/modules/deadline/repository/custom/plugins/OpenPypeTileAssembler/OpenPypeTileAssembler.py +++ b/openpype/modules/deadline/repository/custom/plugins/OpenPypeTileAssembler/OpenPypeTileAssembler.py @@ -320,12 +320,7 @@ def render_argument(self): output_file = data["ImageFileName"] output_file = RepositoryUtils.CheckPathMapping(output_file) output_file = self.process_path(output_file) - """ - _, ext = os.path.splitext(output_file) - if "exr" not in ext: - self.FailRender( - "[{}] Only EXR format is supported for now.".format(ext)) - """ + tile_info = [] for tile in range(int(data["TileCount"])): tile_info.append({ @@ -336,11 +331,6 @@ def render_argument(self): "width": int(data["Tile{}Width".format(tile)]) }) - # FFMpeg doesn't support tile coordinates at the moment. - # arguments = self.tile_completer_ffmpeg_args( - # int(data["ImageWidth"]), int(data["ImageHeight"]), - # tile_info, output_file) - arguments = self.tile_oiio_args( int(data["ImageWidth"]), int(data["ImageHeight"]), tile_info, output_file) @@ -362,20 +352,20 @@ def process_path(self, filepath): def pre_render_tasks(self): """Load config file and do remapping.""" self.LogInfo("OpenPype Tile Assembler starting...") - scene_filename = self.GetDataFilename() + config_file = self.GetPluginInfoEntry("ConfigFile") temp_scene_directory = self.CreateTempDirectory( "thread" + str(self.GetThreadNumber())) - temp_scene_filename = Path.GetFileName(scene_filename) + temp_scene_filename = Path.GetFileName(config_file) self.config_file = Path.Combine( temp_scene_directory, temp_scene_filename) if SystemUtils.IsRunningOnWindows(): RepositoryUtils.CheckPathMappingInFileAndReplaceSeparator( - scene_filename, self.config_file, "/", "\\") + config_file, self.config_file, "/", "\\") else: RepositoryUtils.CheckPathMappingInFileAndReplaceSeparator( - scene_filename, self.config_file, "\\", "/") + config_file, self.config_file, "\\", "/") os.chmod(self.config_file, os.stat(self.config_file).st_mode) def post_render_tasks(self): @@ -459,75 +449,3 @@ def tile_oiio_args( args.append(output_path) return args - - def tile_completer_ffmpeg_args( - self, output_width, output_height, tiles_info, output_path): - """Generate ffmpeg arguments for tile assembly. - - Expected inputs are tiled images. - - Args: - output_width (int): Width of output image. - output_height (int): Height of output image. - tiles_info (list): List of tile items, each item must be - dictionary with `filepath`, `pos_x` and `pos_y` keys - representing path to file and x, y coordinates on output - image where top-left point of tile item should start. - output_path (str): Path to file where should be output stored. - - Returns: - (list): ffmpeg arguments. - - """ - previous_name = "base" - ffmpeg_args = [] - filter_complex_strs = [] - - filter_complex_strs.append("nullsrc=size={}x{}[{}]".format( - output_width, output_height, previous_name - )) - - new_tiles_info = {} - for idx, tile_info in enumerate(tiles_info): - # Add input and store input index - filepath = tile_info["filepath"] - ffmpeg_args.append("-i \"{}\"".format(filepath.replace("\\", "/"))) - - # Prepare initial filter complex arguments - index_name = "input{}".format(idx) - filter_complex_strs.append( - "[{}]setpts=PTS-STARTPTS[{}]".format(idx, index_name) - ) - tile_info["index"] = idx - new_tiles_info[index_name] = tile_info - - # Set frames to 1 - ffmpeg_args.append("-frames 1") - - # Concatenation filter complex arguments - global_index = 1 - total_index = len(new_tiles_info) - for index_name, tile_info in new_tiles_info.items(): - item_str = ( - "[{previous_name}][{index_name}]overlay={pos_x}:{pos_y}" - ).format( - previous_name=previous_name, - index_name=index_name, - pos_x=tile_info["pos_x"], - pos_y=tile_info["pos_y"] - ) - new_previous = "tmp{}".format(global_index) - if global_index != total_index: - item_str += "[{}]".format(new_previous) - filter_complex_strs.append(item_str) - previous_name = new_previous - global_index += 1 - - joined_parts = ";".join(filter_complex_strs) - filter_complex_str = "-filter_complex \"{}\"".format(joined_parts) - - ffmpeg_args.append(filter_complex_str) - ffmpeg_args.append("-y") - ffmpeg_args.append("\"{}\"".format(output_path)) - - return ffmpeg_args From ce44ceb1fdd65be4451922b1e8ca0096923dd29f Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 2 Feb 2023 12:51:09 +0000 Subject: [PATCH 118/898] Fix y tiles ordering. --- .../plugins/publish/submit_maya_deadline.py | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py index 230dc526188..6261a697062 100644 --- a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py @@ -466,13 +466,16 @@ def _tile_render(self, payload): instance.data.get("resolutionHeight")), file=cf) with open(config_file, "a") as cf: + # Need to reverse the order of the y tiles, because image + # coordinates are calculated from bottom left corner. tiles = _format_tiles( file, 0, instance.data.get("tilesX"), instance.data.get("tilesY"), instance.data.get("resolutionWidth"), instance.data.get("resolutionHeight"), - payload_plugin_info["OutputFilePrefix"] + payload_plugin_info["OutputFilePrefix"], + reversed_y=True )[1] for k, v in sorted(tiles.items()): print("{}={}".format(k, v), file=cf) @@ -752,8 +755,15 @@ def _iter_expected_files(exp): def _format_tiles( - filename, index, tiles_x, tiles_y, - width, height, prefix): + filename, + index, + tiles_x, + tiles_y, + width, + height, + prefix, + reversed_y=False +): """Generate tile entries for Deadline tile job. Returns two dictionaries - one that can be directly used in Deadline @@ -790,6 +800,7 @@ def _format_tiles( width (int): Width resolution of final image. height (int): Height resolution of final image. prefix (str): Image prefix. + reversed_y (bool): Reverses the order of the y tiles. Returns: (dict, dict): Tuple of two dictionaries - first can be used to @@ -812,12 +823,16 @@ def _format_tiles( cfg["TilesCropped"] = "False" tile = 0 + range_y = range(1, tiles_y + 1) + reversed_y_range = list(reversed(range_y)) for tile_x in range(1, tiles_x + 1): - for tile_y in reversed(range(1, tiles_y + 1)): + for i, tile_y in enumerate(range_y): + tile_y_index = tile_y + if reversed_y: + tile_y_index = reversed_y_range[i] + tile_prefix = "_tile_{}x{}_{}x{}_".format( - tile_x, tile_y, - tiles_x, - tiles_y + tile_x, tile_y_index, tiles_x, tiles_y ) new_filename = "{}/{}{}".format( @@ -832,11 +847,14 @@ def _format_tiles( right = (tile_x * w_space) - 1 # Job info - out["JobInfo"]["OutputFilename{}Tile{}".format(index, tile)] = new_filename # noqa: E501 + key = "OutputFilename{}Tile{}".format(index, tile) + out["JobInfo"][key] = new_filename # Plugin Info - out["PluginInfo"]["RegionPrefix{}".format(str(tile))] = \ - "/{}".format(tile_prefix).join(prefix.rsplit("/", 1)) + key = "RegionPrefix{}".format(str(tile)) + out["PluginInfo"][key] = "/{}".format( + tile_prefix + ).join(prefix.rsplit("/", 1)) out["PluginInfo"]["RegionTop{}".format(tile)] = top out["PluginInfo"]["RegionBottom{}".format(tile)] = bottom out["PluginInfo"]["RegionLeft{}".format(tile)] = left From 5b961887a392f3f99a829562634701d2b8961fe4 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 2 Feb 2023 18:08:09 +0000 Subject: [PATCH 119/898] Add plugin version. --- .../plugins/OpenPypeTileAssembler/OpenPypeTileAssembler.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openpype/modules/deadline/repository/custom/plugins/OpenPypeTileAssembler/OpenPypeTileAssembler.py b/openpype/modules/deadline/repository/custom/plugins/OpenPypeTileAssembler/OpenPypeTileAssembler.py index 674938e6413..f9c5db18003 100644 --- a/openpype/modules/deadline/repository/custom/plugins/OpenPypeTileAssembler/OpenPypeTileAssembler.py +++ b/openpype/modules/deadline/repository/custom/plugins/OpenPypeTileAssembler/OpenPypeTileAssembler.py @@ -16,6 +16,10 @@ FileUtils, RepositoryUtils, SystemUtils) +version_major = 1 +version_minor = 0 +version_patch = 0 +version_string = ".".join([version_major, version_minor, version_patch]) STRING_TAGS = { "format" } @@ -264,6 +268,7 @@ def cleanup(self): def initialize_process(self): """Initialization.""" + print("Plugin version: {}".format(version_string)) self.SingleFramesOnly = True self.StdoutHandling = True self.renderer = self.GetPluginInfoEntryWithDefault( From 97ff180d039c22dce44f5f53e0ecf6177363705e Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 2 Feb 2023 18:20:05 +0000 Subject: [PATCH 120/898] Fix plugin version --- .../plugins/OpenPypeTileAssembler/OpenPypeTileAssembler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/modules/deadline/repository/custom/plugins/OpenPypeTileAssembler/OpenPypeTileAssembler.py b/openpype/modules/deadline/repository/custom/plugins/OpenPypeTileAssembler/OpenPypeTileAssembler.py index f9c5db18003..ef76937b5a3 100644 --- a/openpype/modules/deadline/repository/custom/plugins/OpenPypeTileAssembler/OpenPypeTileAssembler.py +++ b/openpype/modules/deadline/repository/custom/plugins/OpenPypeTileAssembler/OpenPypeTileAssembler.py @@ -19,7 +19,7 @@ version_major = 1 version_minor = 0 version_patch = 0 -version_string = ".".join([version_major, version_minor, version_patch]) +version_string = "{}.{}.{}".format(version_major, version_minor, version_patch) STRING_TAGS = { "format" } @@ -268,7 +268,7 @@ def cleanup(self): def initialize_process(self): """Initialization.""" - print("Plugin version: {}".format(version_string)) + self.LogInfo("Plugin version: {}".format(version_string)) self.SingleFramesOnly = True self.StdoutHandling = True self.renderer = self.GetPluginInfoEntryWithDefault( From 324eaa26b91cbcef39d416bc6cd5bbf9e848cb65 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Fri, 3 Feb 2023 02:21:14 +0300 Subject: [PATCH 121/898] use temp folder to store the prefs, check if FUSION16_PROFILE_DIR exists --- .../hosts/fusion/hooks/pre_fusion_setup.py | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index f6cec86e3bb..01b2a37b746 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -19,8 +19,14 @@ class FusionPrelaunch(PreLaunchHook): """ app_groups = ["fusion"] + OPENPYPE_FUSION_PROFILE_DIR = "~/.openpype/hosts/fusion/prefs" def get_profile_source(self): + fusion_var_prefs_dir = os.getenv("FUSION16_PROFILE_DIR") + if fusion_var_prefs_dir and Path(fusion_var_prefs_dir).is_dir(): + self.log.info(f"local Fusion prefs environment is set to {fusion_var_prefs_dir}") + return os.path.join(fusion_var_prefs_dir, "Fusion.prefs") + fusion_prefs_path = "Blackmagic Design/Fusion/Profiles/Default/Fusion.prefs" if platform.system() == "Windows": prefs_source = Path(os.getenv("AppData")) / fusion_prefs_path @@ -32,16 +38,19 @@ def get_profile_source(self): return str(prefs_source) def copy_existing_prefs(self, profile_directory: str): - dest_folder = os.path.join(profile_directory, "Default") - os.makedirs(dest_folder, exist_ok=True) + dest_folder = Path(profile_directory) / "Default" + dest_folder.mkdir(exist_ok=True, parents=True) prefs_source = self.get_profile_source() - if os.path.exists(prefs_source): - shutil.copy(prefs_source, dest_folder) - self.log.info(f"successfully copied preferences:\n {prefs_source} to {dest_folder}") + if not Path(prefs_source).exists(): + self.log.warning(f"Fusion preferences file not found in {prefs_source}") + return + shutil.copy(prefs_source, dest_folder) + self.log.info(f"successfully copied preferences:\n {prefs_source} to {dest_folder}") def execute(self): # making sure python 3 is installed at provided path # Py 3.3-3.10 for Fusion 18+ or Py 3.6 for Fu 16-17 + py3_var = "FUSION_PYTHON3_HOME" fusion_python3_home = self.launch_context.env.get(py3_var, "") @@ -79,10 +88,11 @@ def execute(self): profile_dir_var = "FUSION16_PROFILE_DIR" # used by Fusion 16, 17 and 18 pref_var = "FUSION16_MasterPrefs" # used by Fusion 16, 17 and 18 - profile_dir = os.path.join(FUSION_HOST_DIR, "deploy", "Prefs") + profile_dir = os.path.expanduser(self.OPENPYPE_FUSION_PROFILE_DIR) prefs = os.path.join(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") # now copy the default Fusion profile to a working directory + # only if the openpype profile folder does not exist if not os.path.exists(profile_dir): self.copy_existing_prefs(profile_dir) self.log.info(f"Setting {profile_dir_var}: {profile_dir}") From 3b0f5601338b3299de1493b00754633a55053bf5 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Fri, 3 Feb 2023 02:22:02 +0300 Subject: [PATCH 122/898] remove custom pathmap --- openpype/hosts/fusion/deploy/fusion_shared.prefs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/deploy/fusion_shared.prefs b/openpype/hosts/fusion/deploy/fusion_shared.prefs index d9451ea295d..0225b2209b9 100644 --- a/openpype/hosts/fusion/deploy/fusion_shared.prefs +++ b/openpype/hosts/fusion/deploy/fusion_shared.prefs @@ -6,7 +6,7 @@ Global = { ["OpenPype:"] = "$(OPENPYPE_FUSION)/deploy", ["Config:"] = "UserPaths:Config;OpenPype:Config", ["Scripts:"] = "UserPaths:Scripts;Reactor:System/Scripts;OpenPype:Scripts", - ["UserPaths:"] = "UserData:;GIT:;AllData:;Fusion:;Reactor:Deploy" + ["UserPaths:"] = "UserData:;AllData:;Fusion:;Reactor:Deploy" }, }, Script = { @@ -14,4 +14,4 @@ Global = { Python3Forced = true }, }, -} \ No newline at end of file +} From 13a364377d93fe33317a6b17b861b89f187fe54b Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Fri, 3 Feb 2023 02:23:30 +0300 Subject: [PATCH 123/898] use get comp filename from lib --- openpype/hosts/fusion/api/lib.py | 20 +++++++++++--------- openpype/hosts/fusion/api/workio.py | 10 +++------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/openpype/hosts/fusion/api/lib.py b/openpype/hosts/fusion/api/lib.py index ac30e1ff997..ec96d6cf181 100644 --- a/openpype/hosts/fusion/api/lib.py +++ b/openpype/hosts/fusion/api/lib.py @@ -302,14 +302,8 @@ def get_frame_path(path): return filename, padding, ext -def get_comp_name(comp=None): - """Get basename of the comp's filename""" - if comp: - return comp.GetAttrs()["COMPS_Name"] - - def get_fusion(): - """Get Fusion instance""" + """Get current Fusion instance""" fusion = getattr(sys.modules["__main__"], "fusion", None) return fusion @@ -317,8 +311,16 @@ def get_fusion(): def get_current_comp(): """Get current comp in this session""" fusion = get_fusion() - comp = fusion.CurrentComp - return comp + if fusion: + comp = fusion.CurrentComp + return comp + + +def get_comp_filename(): + """Get comp's Filename""" + comp = get_current_comp() + if comp: + return comp.GetAttrs()["COMPS_FileName"] @contextlib.contextmanager diff --git a/openpype/hosts/fusion/api/workio.py b/openpype/hosts/fusion/api/workio.py index da36a83988e..048e6e090af 100644 --- a/openpype/hosts/fusion/api/workio.py +++ b/openpype/hosts/fusion/api/workio.py @@ -2,7 +2,7 @@ import sys import os -from .lib import get_fusion, get_current_comp +from .lib import get_fusion, get_current_comp, get_comp_filename def file_extensions(): @@ -25,12 +25,8 @@ def open_file(filepath): def current_file(): - comp = get_current_comp() - current_filepath = comp.GetAttrs()["COMPS_FileName"] - if not current_filepath: - return None - - return current_filepath + current_filepath = get_comp_filename() + return current_filepath or None def work_root(session): From 62319248a10f91488b1417fe52cd78a3fac8e24c Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Fri, 3 Feb 2023 02:26:34 +0300 Subject: [PATCH 124/898] do not override Userpaths --- openpype/hosts/fusion/deploy/fusion_shared.prefs | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/fusion/deploy/fusion_shared.prefs b/openpype/hosts/fusion/deploy/fusion_shared.prefs index 0225b2209b9..8d0e45eae56 100644 --- a/openpype/hosts/fusion/deploy/fusion_shared.prefs +++ b/openpype/hosts/fusion/deploy/fusion_shared.prefs @@ -6,7 +6,6 @@ Global = { ["OpenPype:"] = "$(OPENPYPE_FUSION)/deploy", ["Config:"] = "UserPaths:Config;OpenPype:Config", ["Scripts:"] = "UserPaths:Scripts;Reactor:System/Scripts;OpenPype:Scripts", - ["UserPaths:"] = "UserData:;AllData:;Fusion:;Reactor:Deploy" }, }, Script = { From be90410047508cd4826b933dd57361f3fa576c2c Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Fri, 3 Feb 2023 13:12:35 +0300 Subject: [PATCH 125/898] use pathlib over os.path, check if FUSION_PROFILE is set --- .../hosts/fusion/hooks/pre_fusion_setup.py | 65 +++++++++++-------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index 01b2a37b746..eadcb481e33 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -20,32 +20,41 @@ class FusionPrelaunch(PreLaunchHook): """ app_groups = ["fusion"] OPENPYPE_FUSION_PROFILE_DIR = "~/.openpype/hosts/fusion/prefs" + PROFILE_NUMBER = 16 - def get_profile_source(self): - fusion_var_prefs_dir = os.getenv("FUSION16_PROFILE_DIR") - if fusion_var_prefs_dir and Path(fusion_var_prefs_dir).is_dir(): - self.log.info(f"local Fusion prefs environment is set to {fusion_var_prefs_dir}") - return os.path.join(fusion_var_prefs_dir, "Fusion.prefs") + def get_fusion_profile(self) -> str: + return os.getenv(f"FUSION{self.PROFILE_NUMBER}_PROFILE", "Default") + + def get_profile_source(self) -> Path: + fusion_var_prefs_dir = os.getenv(f"FUSION{self.PROFILE_NUMBER}_PROFILE_DIR") - fusion_prefs_path = "Blackmagic Design/Fusion/Profiles/Default/Fusion.prefs" + # if FUSION16_PROFILE_DIR variable exists, return the profile filepath + if fusion_var_prefs_dir and Path(fusion_var_prefs_dir).is_dir(): + fusion_profile = self.get_fusion_profile() + fusion_prefs_dir = Path(fusion_var_prefs_dir, fusion_profile) + self.log.info(f"Local Fusion prefs environment is set to {fusion_prefs_dir}") + fusion_prefs_filepath = fusion_prefs_dir / "Fusion.prefs" + return fusion_prefs_filepath + + # otherwise get the profile from default prefs location + fusion_prefs_path = f"Blackmagic Design/Fusion/Profiles/{fusion_var_prefs_dir}/Fusion.prefs" if platform.system() == "Windows": prefs_source = Path(os.getenv("AppData")) / fusion_prefs_path elif platform.system() == "Darwin": - prefs_source = Path(os.path.expanduser("~/Library/Application Support/")) / fusion_prefs_path + prefs_source = Path("~/Library/Application Support/", fusion_prefs_path).expanduser() elif platform.system() == "Linux": - prefs_source = Path(os.path.expanduser("~/.fusion")) / fusion_prefs_path + prefs_source = Path("~/.fusion", fusion_prefs_path).expanduser() + + return prefs_source - return str(prefs_source) - - def copy_existing_prefs(self, profile_directory: str): - dest_folder = Path(profile_directory) / "Default" + def copy_existing_prefs(self, copy_from: Path, copy_to: Path) -> None: + dest_folder = copy_to / self.get_fusion_profile() dest_folder.mkdir(exist_ok=True, parents=True) - prefs_source = self.get_profile_source() - if not Path(prefs_source).exists(): - self.log.warning(f"Fusion preferences file not found in {prefs_source}") + if not copy_from.exists(): + self.log.warning(f"Fusion preferences file not found in {copy_from}") return - shutil.copy(prefs_source, dest_folder) - self.log.info(f"successfully copied preferences:\n {prefs_source} to {dest_folder}") + shutil.copy(str(copy_from), str(dest_folder)) # compatible with Python >= 3.6 + self.log.info(f"successfully copied preferences:\n {copy_from} to {dest_folder}") def execute(self): # making sure python 3 is installed at provided path @@ -54,12 +63,12 @@ def execute(self): py3_var = "FUSION_PYTHON3_HOME" fusion_python3_home = self.launch_context.env.get(py3_var, "") - self.log.info(f"Looking for Python 3 in: {fusion_python3_home}") for path in fusion_python3_home.split(os.pathsep): - # Allow defining multiple paths to allow "fallback" to other + # Allow defining multiple paths, separated by os.pathsep, to allow "fallback" to other # path. But make to set only a single path as final variable. py3_dir = os.path.normpath(path) if os.path.isdir(py3_dir): + self.log.info(f"Looking for Python 3 in: {py3_dir}") break else: raise ApplicationLaunchFailed( @@ -88,14 +97,16 @@ def execute(self): profile_dir_var = "FUSION16_PROFILE_DIR" # used by Fusion 16, 17 and 18 pref_var = "FUSION16_MasterPrefs" # used by Fusion 16, 17 and 18 - profile_dir = os.path.expanduser(self.OPENPYPE_FUSION_PROFILE_DIR) - prefs = os.path.join(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") + op_profile_dir = Path(self.OPENPYPE_FUSION_PROFILE_DIR).expanduser() + op_master_prefs = Path(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") + prefs_source = self.get_profile_source() + self.log.info(f"Got Fusion prefs file: {prefs_source}") # now copy the default Fusion profile to a working directory # only if the openpype profile folder does not exist - if not os.path.exists(profile_dir): - self.copy_existing_prefs(profile_dir) - self.log.info(f"Setting {profile_dir_var}: {profile_dir}") - self.launch_context.env[profile_dir_var] = profile_dir - self.log.info(f"Setting {pref_var}: {prefs}") - self.launch_context.env[pref_var] = prefs + if not op_profile_dir.exists(): + self.copy_existing_prefs(prefs_source, op_profile_dir) + self.log.info(f"Setting {profile_dir_var}: {op_profile_dir}") + self.launch_context.env[profile_dir_var] = str(op_profile_dir) + self.log.info(f"Setting {pref_var}: {op_master_prefs}") + self.launch_context.env[pref_var] = str(op_master_prefs) From 95280aef00d3886170f593e47129bb6560502c2b Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Fri, 3 Feb 2023 13:44:30 +0300 Subject: [PATCH 126/898] fix get fusion profile --- openpype/hosts/fusion/hooks/pre_fusion_setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index eadcb481e33..4f000a12b2c 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -26,18 +26,18 @@ def get_fusion_profile(self) -> str: return os.getenv(f"FUSION{self.PROFILE_NUMBER}_PROFILE", "Default") def get_profile_source(self) -> Path: + fusion_profile = self.get_fusion_profile() fusion_var_prefs_dir = os.getenv(f"FUSION{self.PROFILE_NUMBER}_PROFILE_DIR") # if FUSION16_PROFILE_DIR variable exists, return the profile filepath if fusion_var_prefs_dir and Path(fusion_var_prefs_dir).is_dir(): - fusion_profile = self.get_fusion_profile() fusion_prefs_dir = Path(fusion_var_prefs_dir, fusion_profile) self.log.info(f"Local Fusion prefs environment is set to {fusion_prefs_dir}") fusion_prefs_filepath = fusion_prefs_dir / "Fusion.prefs" return fusion_prefs_filepath # otherwise get the profile from default prefs location - fusion_prefs_path = f"Blackmagic Design/Fusion/Profiles/{fusion_var_prefs_dir}/Fusion.prefs" + fusion_prefs_path = f"Blackmagic Design/Fusion/Profiles/{fusion_profile}/Fusion.prefs" if platform.system() == "Windows": prefs_source = Path(os.getenv("AppData")) / fusion_prefs_path elif platform.system() == "Darwin": From 9d8eb7383581b3dc48d378db7ef65986a24118e2 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 3 Feb 2023 12:16:47 +0000 Subject: [PATCH 127/898] Documentation --- website/docs/artist_hosts_maya.md | 16 ++++++++++++++++ website/docs/module_deadline.md | 28 ++++++++++++++++------------ 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/website/docs/artist_hosts_maya.md b/website/docs/artist_hosts_maya.md index 5cd8efa1535..81164eefadf 100644 --- a/website/docs/artist_hosts_maya.md +++ b/website/docs/artist_hosts_maya.md @@ -504,6 +504,22 @@ In the scene from where you want to publish your model create *Render subset*. P model subset (Maya set node) under corresponding `LAYER_` set under *Render instance*. During publish, it will submit this render to farm and after it is rendered, it will be attached to your model subset. +### Tile Rendering +:::note Deadline +This feature is only supported when using Deadline. See [here](module_deadline#openpypetileassembler-plugin) for setup. +::: +On the render instance objectset you'll find: + +* `Tile Rendering` - for enabling tile rendering. +* `Tile X` - number of tiles in the X axis. +* `Tile Y` - number of tiles in the Y axis. + +When submittig to Deadline, you'll get: + +- for each frame a tile rendering job, to render each from Maya. +- for each frame a tile assembly job, to assemble the rendered tiles. +- job to publish the assembled frames. + ## Render Setups ### Publishing Render Setups diff --git a/website/docs/module_deadline.md b/website/docs/module_deadline.md index c96da919097..2c02530b791 100644 --- a/website/docs/module_deadline.md +++ b/website/docs/module_deadline.md @@ -28,16 +28,16 @@ For [AWS Thinkbox Deadline](https://www.awsthinkbox.com/deadline) support you ne OpenPype integration for Deadline consists of two parts: - The `OpenPype` Deadline Plug-in -- A `GlobalJobPreLoad` Deadline Script (this gets triggered for each deadline job) +- A `GlobalJobPreLoad` Deadline Script (this gets triggered for each deadline job) The `GlobalJobPreLoad` handles populating render and publish jobs with proper environment variables using settings from the `OpenPype` Deadline Plug-in. -The `OpenPype` Deadline Plug-in must be configured to point to a valid OpenPype executable location. The executable need to be installed to +The `OpenPype` Deadline Plug-in must be configured to point to a valid OpenPype executable location. The executable need to be installed to destinations accessible by DL process. Check permissions (must be executable and accessible by Deadline process) - Enable `Tools > Super User Mode` in Deadline Monitor -- Go to `Tools > Configure Plugins...`, find `OpenPype` in the list on the left side, find location of OpenPype +- Go to `Tools > Configure Plugins...`, find `OpenPype` in the list on the left side, find location of OpenPype executable. It is recommended to use the `openpype_console` executable as it provides a bit more logging. - In case of multi OS farms, provide multiple locations, each Deadline Worker goes through the list and tries to find the first accessible @@ -45,12 +45,16 @@ executable. It is recommended to use the `openpype_console` executable as it pro ![Configure plugin](assets/deadline_configure_plugin.png) +### OpenPypeTileAssembler Plugin +To setup tile rendering copy the `OpenPypeTileAssembler` plugin to the repository; +`[OpenPype]\openpype\modules\deadline\repository\custom\plugins\OpenPypeTileAssembler` > `[DeadlineRepository]\custom\plugins\OpenPypeTileAssembler` + ## Troubleshooting #### Publishing jobs fail directly in DCCs - Double check that all previously described steps were finished -- Check that `deadlinewebservice` is running on DL server +- Check that `deadlinewebservice` is running on DL server - Check that user's machine has access to deadline server on configured port #### Jobs are failing on DL side @@ -61,40 +65,40 @@ Each publishing from OpenPype consists of 2 jobs, first one is rendering, second - Jobs are failing with `OpenPype executable was not found` error - Check if OpenPype is installed on the Worker handling this job and ensure `OpenPype` Deadline Plug-in is properly [configured](#configuration) + Check if OpenPype is installed on the Worker handling this job and ensure `OpenPype` Deadline Plug-in is properly [configured](#configuration) - Publishing job is failing with `ffmpeg not installed` error - + OpenPype executable has to have access to `ffmpeg` executable, check OpenPype `Setting > General` ![FFmpeg setting](assets/ffmpeg_path.png) - Both jobs finished successfully, but there is no review on Ftrack - Make sure that you correctly set published family to be send to Ftrack. + Make sure that you correctly set published family to be send to Ftrack. ![Ftrack Family](assets/ftrack/ftrack-collect-main.png) Example: I want send to Ftrack review of rendered images from Harmony : - `Host names`: "harmony" - - `Families`: "render" + - `Families`: "render" - `Add Ftrack Family` to "Enabled" - + Make sure that you actually configured to create review for published subset in `project_settings/ftrack/publish/CollectFtrackFamily` ![Ftrack Family](assets/deadline_review.png) - Example: I want to create review for all reviewable subsets in Harmony : + Example: I want to create review for all reviewable subsets in Harmony : - Add "harmony" as a new key an ".*" as a value. - Rendering jobs are stuck in 'Queued' state or failing Make sure that your Deadline is not limiting specific jobs to be run only on specific machines. (Eg. only some machines have installed particular application.) - + Check `project_settings/deadline` - + ![Deadline group](assets/deadline_group.png) Example: I have separated machines with "Harmony" installed into "harmony" group on Deadline. I want rendering jobs published from Harmony to run only on those machines. From b5a4fb59a578309b9f94914546acf97606c271f4 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 3 Feb 2023 12:42:27 +0000 Subject: [PATCH 128/898] Change default settings to Draft Tile Assembler. --- openpype/settings/defaults/project_settings/deadline.json | 4 ++-- .../schemas/projects_schema/schema_project_deadline.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/settings/defaults/project_settings/deadline.json b/openpype/settings/defaults/project_settings/deadline.json index ceb0b2e39af..c4c3d413d11 100644 --- a/openpype/settings/defaults/project_settings/deadline.json +++ b/openpype/settings/defaults/project_settings/deadline.json @@ -23,7 +23,7 @@ "enabled": true, "optional": false, "active": true, - "tile_assembler_plugin": "OpenPypeTileAssembler", + "tile_assembler_plugin": "DraftTileAssembler", "use_published": true, "import_reference": false, "asset_dependencies": true, @@ -106,4 +106,4 @@ } } } -} \ No newline at end of file +} diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json b/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json index 08a505bd47d..87b375bc9f2 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json @@ -121,7 +121,7 @@ "DraftTileAssembler": "Draft Tile Assembler" }, { - "OpenPypeTileAssembler": "Open Image IO" + "OpenPypeTileAssembler": "OpenPype Tile Assembler" } ] }, From 25b4907b35894641930bbb86d9a583fcf82d5dbe Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 3 Feb 2023 15:56:45 +0000 Subject: [PATCH 129/898] Fix for Draft Tile Assembler --- .../modules/deadline/plugins/publish/submit_maya_deadline.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py index 6261a697062..972e1810be2 100644 --- a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py @@ -484,6 +484,9 @@ def _tile_render(self, payload): self.assemble_payload( job_info=frame_assembly_job_info, plugin_info=assembly_plugin_info.copy(), + # This would fail if the client machine and webserice are + # using different storage paths. + aux_files=[config_file] ) ) From 9bba80ff6196cff4c4579bcb78db9f8ef1623081 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Fri, 3 Feb 2023 20:32:38 +0300 Subject: [PATCH 130/898] add copy fusion prefs global settings --- .../system_settings/applications.json | 8 +++++- .../host_settings/schema_fusion.json | 25 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/openpype/settings/defaults/system_settings/applications.json b/openpype/settings/defaults/system_settings/applications.json index 936407a49b9..5d75b3b6064 100644 --- a/openpype/settings/defaults/system_settings/applications.json +++ b/openpype/settings/defaults/system_settings/applications.json @@ -835,6 +835,10 @@ "linux": "/opt/Python/3.6/bin" } }, + "copy_fusion_settings": { + "copy_prefs": false, + "prefs_path": "~/.openpype/hosts/fusion/prefs" + }, "variants": { "18": { "executables": { @@ -1302,7 +1306,9 @@ "variant_label": "Current", "use_python_2": false, "executables": { - "windows": ["C:/Program Files/CelAction/CelAction2D Studio/CelAction2D.exe"], + "windows": [ + "C:/Program Files/CelAction/CelAction2D Studio/CelAction2D.exe" + ], "darwin": [], "linux": [] }, diff --git a/openpype/settings/entities/schemas/system_schema/host_settings/schema_fusion.json b/openpype/settings/entities/schemas/system_schema/host_settings/schema_fusion.json index 5960da77744..360813bcb57 100644 --- a/openpype/settings/entities/schemas/system_schema/host_settings/schema_fusion.json +++ b/openpype/settings/entities/schemas/system_schema/host_settings/schema_fusion.json @@ -19,6 +19,31 @@ "label": "Environment", "type": "raw-json" }, + { + "type": "splitter" + }, + { + "type": "dict", + "key": "copy_fusion_settings", + "collapsible": true, + "checkbox_key": "copy_prefs", + "label": "Copy Fusion preferences", + "children": [ + { + "type": "boolean", + "key": "copy_prefs", + "label": "Enabled" + }, + { + "key": "prefs_path", + "type": "path", + "label": "Local prefs directory" + } + ] + }, + { + "type": "splitter" + }, { "type": "dict-modifiable", "key": "variants", From 3ff8aa5c958e79000bd82967de82e436947c11fd Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Mon, 13 Feb 2023 00:39:55 +0300 Subject: [PATCH 131/898] use system settings to get data, add force sync option --- .../hosts/fusion/hooks/pre_fusion_setup.py | 71 ++++++++++++------- .../system_settings/applications.json | 3 +- .../host_settings/schema_fusion.json | 7 +- 3 files changed, 55 insertions(+), 26 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index 4f000a12b2c..4dc11abce90 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -4,6 +4,7 @@ from pathlib import Path from openpype.lib import PreLaunchHook, ApplicationLaunchFailed from openpype.hosts.fusion import FUSION_HOST_DIR +from openpype.settings import get_system_settings class FusionPrelaunch(PreLaunchHook): @@ -19,14 +20,18 @@ class FusionPrelaunch(PreLaunchHook): """ app_groups = ["fusion"] - OPENPYPE_FUSION_PROFILE_DIR = "~/.openpype/hosts/fusion/prefs" PROFILE_NUMBER = 16 - def get_fusion_profile(self) -> str: + def get_fusion_profile_name(self) -> str: + """usually set to 'Default', unless FUSION16_PROFILE is set""" return os.getenv(f"FUSION{self.PROFILE_NUMBER}_PROFILE", "Default") def get_profile_source(self) -> Path: - fusion_profile = self.get_fusion_profile() + """Get the Fusion preferences (profile) location. + Check https://www.steakunderwater.com/VFXPedia/96.0.243.189/indexad6a.html?title=Per-User_Preferences_and_Paths#Setting_the_profile_directory + for reference. + """ + fusion_profile = self.get_fusion_profile_name() fusion_var_prefs_dir = os.getenv(f"FUSION{self.PROFILE_NUMBER}_PROFILE_DIR") # if FUSION16_PROFILE_DIR variable exists, return the profile filepath @@ -44,11 +49,32 @@ def get_profile_source(self) -> Path: prefs_source = Path("~/Library/Application Support/", fusion_prefs_path).expanduser() elif platform.system() == "Linux": prefs_source = Path("~/.fusion", fusion_prefs_path).expanduser() - + self.log.info(f"Got Fusion prefs file: {prefs_source}") return prefs_source - def copy_existing_prefs(self, copy_from: Path, copy_to: Path) -> None: - dest_folder = copy_to / self.get_fusion_profile() + def get_copy_fusion_prefs_settings(self): + """Git copy prefserences options from the global application settings""" + copy_status = copy_path = None + try: + copy_status, copy_path, force_sync = get_system_settings()["applications"]["fusion"][ + "copy_fusion_settings"].values() + except ValueError: + self.log.error('Copy prefs settings not found') + finally: + return copy_status, copy_path, force_sync + + def copy_existing_prefs(self, copy_from: Path, copy_to: Path, force_sync: bool) -> None: + """On the first Fusion launch copy the Fusion profile to the working directory. + If the Openpype profile folder exists, skip copying, unless Force sync is checked. + If the prefs were not copied on the first launch, clean Fusion profile + will be created in openpype_fusion_profile_dir. + """ + if copy_to.exists() and not force_sync: + self.log.info("Local Fusion preferences folder exists, skipping profile copy") + return + self.log.info(f"Starting copying Fusion preferences") + self.log.info(f"force_sync option is set to {force_sync}") + dest_folder = copy_to / self.get_fusion_profile_name() dest_folder.mkdir(exist_ok=True, parents=True) if not copy_from.exists(): self.log.warning(f"Fusion preferences file not found in {copy_from}") @@ -88,25 +114,22 @@ def execute(self): # Fusion 16 and 17 use FUSION16_PYTHON36_HOME instead of # FUSION_PYTHON3_HOME and will only work with a Python 3.6 version # TODO: Detect Fusion version to only set for specific Fusion build - self.launch_context.env["FUSION16_PYTHON36_HOME"] = py3_dir + self.launch_context.env[f"FUSION{self.PROFILE_NUMBER}_PYTHON36_HOME"] = py3_dir - # Add custom Fusion Master Prefs and the temporary profile directory variables to customize - # Fusion to define where it can read custom scripts and tools from + # Add custom Fusion Master Prefs and the temporary profile directory variables + # to customize Fusion to define where it can read custom scripts and tools from self.log.info(f"Setting OPENPYPE_FUSION: {FUSION_HOST_DIR}") self.launch_context.env["OPENPYPE_FUSION"] = FUSION_HOST_DIR - profile_dir_var = "FUSION16_PROFILE_DIR" # used by Fusion 16, 17 and 18 - pref_var = "FUSION16_MasterPrefs" # used by Fusion 16, 17 and 18 - op_profile_dir = Path(self.OPENPYPE_FUSION_PROFILE_DIR).expanduser() - op_master_prefs = Path(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") - prefs_source = self.get_profile_source() - self.log.info(f"Got Fusion prefs file: {prefs_source}") - - # now copy the default Fusion profile to a working directory - # only if the openpype profile folder does not exist - if not op_profile_dir.exists(): - self.copy_existing_prefs(prefs_source, op_profile_dir) - self.log.info(f"Setting {profile_dir_var}: {op_profile_dir}") - self.launch_context.env[profile_dir_var] = str(op_profile_dir) - self.log.info(f"Setting {pref_var}: {op_master_prefs}") - self.launch_context.env[pref_var] = str(op_master_prefs) + copy_status, openpype_fusion_profile_dir, force_sync = self.get_copy_fusion_prefs_settings() + if copy_status: + prefs_source = self.get_profile_source() + openpype_fusion_profile_dir = Path(openpype_fusion_profile_dir).expanduser() + self.copy_existing_prefs(prefs_source, openpype_fusion_profile_dir, force_sync) + fusion_profile_dir_variable = f"FUSION{self.PROFILE_NUMBER}_PROFILE_DIR" + pref_var = f"FUSION{self.PROFILE_NUMBER}_MasterPrefs" + openpype_master_prefs = Path(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") + self.log.info(f"Setting {fusion_profile_dir_variable}: {openpype_fusion_profile_dir}") + self.launch_context.env[fusion_profile_dir_variable] = str(openpype_fusion_profile_dir) + self.log.info(f"Setting {pref_var}: {openpype_master_prefs}") + self.launch_context.env[pref_var] = str(openpype_master_prefs) diff --git a/openpype/settings/defaults/system_settings/applications.json b/openpype/settings/defaults/system_settings/applications.json index 5d75b3b6064..9fb730568ed 100644 --- a/openpype/settings/defaults/system_settings/applications.json +++ b/openpype/settings/defaults/system_settings/applications.json @@ -837,7 +837,8 @@ }, "copy_fusion_settings": { "copy_prefs": false, - "prefs_path": "~/.openpype/hosts/fusion/prefs" + "prefs_path": "~/.openpype/hosts/fusion/prefs", + "force_sync": false }, "variants": { "18": { diff --git a/openpype/settings/entities/schemas/system_schema/host_settings/schema_fusion.json b/openpype/settings/entities/schemas/system_schema/host_settings/schema_fusion.json index 360813bcb57..48355932ae6 100644 --- a/openpype/settings/entities/schemas/system_schema/host_settings/schema_fusion.json +++ b/openpype/settings/entities/schemas/system_schema/host_settings/schema_fusion.json @@ -27,7 +27,7 @@ "key": "copy_fusion_settings", "collapsible": true, "checkbox_key": "copy_prefs", - "label": "Copy Fusion preferences", + "label": "Copy Fusion settings when launched from OpenPype", "children": [ { "type": "boolean", @@ -38,6 +38,11 @@ "key": "prefs_path", "type": "path", "label": "Local prefs directory" + }, + { + "key":"force_sync", + "type": "boolean", + "label": "Always sync preferences on launch" } ] }, From 76bdcb49ea019fe7028bce87916b14dcf4a829f1 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Mon, 13 Feb 2023 00:40:51 +0300 Subject: [PATCH 132/898] get the prefs path correctly --- openpype/hosts/fusion/hooks/pre_fusion_setup.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index 4dc11abce90..267ee713151 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -61,7 +61,7 @@ def get_copy_fusion_prefs_settings(self): except ValueError: self.log.error('Copy prefs settings not found') finally: - return copy_status, copy_path, force_sync + return copy_status, Path(copy_path).expanduser(), force_sync def copy_existing_prefs(self, copy_from: Path, copy_to: Path, force_sync: bool) -> None: """On the first Fusion launch copy the Fusion profile to the working directory. @@ -124,12 +124,11 @@ def execute(self): copy_status, openpype_fusion_profile_dir, force_sync = self.get_copy_fusion_prefs_settings() if copy_status: prefs_source = self.get_profile_source() - openpype_fusion_profile_dir = Path(openpype_fusion_profile_dir).expanduser() self.copy_existing_prefs(prefs_source, openpype_fusion_profile_dir, force_sync) fusion_profile_dir_variable = f"FUSION{self.PROFILE_NUMBER}_PROFILE_DIR" - pref_var = f"FUSION{self.PROFILE_NUMBER}_MasterPrefs" + master_prefs_variable = f"FUSION{self.PROFILE_NUMBER}_MasterPrefs" openpype_master_prefs = Path(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") self.log.info(f"Setting {fusion_profile_dir_variable}: {openpype_fusion_profile_dir}") self.launch_context.env[fusion_profile_dir_variable] = str(openpype_fusion_profile_dir) - self.log.info(f"Setting {pref_var}: {openpype_master_prefs}") - self.launch_context.env[pref_var] = str(openpype_master_prefs) + self.log.info(f"Setting {master_prefs_variable}: {openpype_master_prefs}") + self.launch_context.env[master_prefs_variable] = str(openpype_master_prefs) From 632beeb1c7ae00146910a3cfa27a8ef855edbc84 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Mon, 13 Feb 2023 00:41:29 +0300 Subject: [PATCH 133/898] use english interface by default --- .../hosts/fusion/deploy/fusion_shared.prefs | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/openpype/hosts/fusion/deploy/fusion_shared.prefs b/openpype/hosts/fusion/deploy/fusion_shared.prefs index 8d0e45eae56..17ac3ad37a2 100644 --- a/openpype/hosts/fusion/deploy/fusion_shared.prefs +++ b/openpype/hosts/fusion/deploy/fusion_shared.prefs @@ -1,16 +1,20 @@ { Locked = true, Global = { - Paths = { - Map = { - ["OpenPype:"] = "$(OPENPYPE_FUSION)/deploy", - ["Config:"] = "UserPaths:Config;OpenPype:Config", - ["Scripts:"] = "UserPaths:Scripts;Reactor:System/Scripts;OpenPype:Scripts", + Paths = { + Map = { + ["OpenPype:"] = "$(OPENPYPE_FUSION)/deploy", + ["Config:"] = "UserPaths:Config;OpenPype:Config", + ["Scripts:"] = "UserPaths:Scripts;Reactor:System/Scripts;OpenPype:Scripts", + }, }, - }, - Script = { - PythonVersion = 3, - Python3Forced = true - }, + Script = { + PythonVersion = 3, + Python3Forced = true + }, + UserInterface = { + Skin = "Neutral", + Language = "en_US" }, + }, } From 807fd736fc7ce26b6e2553cfa9c1c53d7e13360f Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Mon, 13 Feb 2023 01:50:05 +0300 Subject: [PATCH 134/898] fix typo --- openpype/hosts/fusion/hooks/pre_fusion_setup.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index 267ee713151..3bb345b72f6 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -28,8 +28,7 @@ def get_fusion_profile_name(self) -> str: def get_profile_source(self) -> Path: """Get the Fusion preferences (profile) location. - Check https://www.steakunderwater.com/VFXPedia/96.0.243.189/indexad6a.html?title=Per-User_Preferences_and_Paths#Setting_the_profile_directory - for reference. + Check https://www.steakunderwater.com/VFXPedia/96.0.243.189/indexad6a.html?title=Per-User_Preferences_and_Paths for reference. """ fusion_profile = self.get_fusion_profile_name() fusion_var_prefs_dir = os.getenv(f"FUSION{self.PROFILE_NUMBER}_PROFILE_DIR") @@ -53,7 +52,7 @@ def get_profile_source(self) -> Path: return prefs_source def get_copy_fusion_prefs_settings(self): - """Git copy prefserences options from the global application settings""" + """Get copy prefserences options from the global application settings""" copy_status = copy_path = None try: copy_status, copy_path, force_sync = get_system_settings()["applications"]["fusion"][ From 6bd93217daf7a8c8dbe9ef4140357c1d8c34974e Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 14 Feb 2023 15:08:08 +0000 Subject: [PATCH 135/898] Publish cbid with ass files. --- .../publish/extract_arnold_scene_source.py | 24 +++++++ .../publish/validate_arnold_scene_source.py | 2 +- .../validate_arnold_scene_source_cbid.py | 72 +++++++++++++++++++ 3 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index 924ac58c403..bb27705d2c0 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -139,6 +139,30 @@ def _extract(self, nodes, attribute_data, kwargs): duplicate_nodes.append(duplicate_transform) delete_bin.append(duplicate_transform) + # Copy cbId from original to mtoa_constant. + attr_name = "mtoa_constant_cbId" + duplicate_shapes = cmds.listRelatives( + duplicate_transform, shapes=True + ) + original_shapes = cmds.listRelatives(node, shapes=True) + for duplicate_shape in duplicate_shapes: + duplicate_path = ( + duplicate_transform + "|" + duplicate_shape + ) + for original_shape in original_shapes: + original_path = node + "|" + original_shape + if duplicate_shape == original_shape: + cmds.addAttr( + duplicate_path, + longName=attr_name, + dataType="string" + ) + cmds.setAttr( + duplicate_path + "." + attr_name, + cmds.getAttr(original_path + ".cbId"), + type="string" + ) + with attribute_values(attribute_data): with maintained_selection(): self.log.info( diff --git a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py index 3b0ffd52d79..e9f6d218f9c 100644 --- a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py @@ -37,7 +37,7 @@ def _get_nodes_data(self, nodes): nodes_by_name[node_split[-1]] = node for shape in cmds.listRelatives(node, shapes=True): - nodes_by_name[shape.split("|")[-1]] = shape + nodes_by_name[shape.split("|")[-1]] = node + "|" + shape return ungrouped_nodes, nodes_by_name, parents diff --git a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py new file mode 100644 index 00000000000..bb8ea88453c --- /dev/null +++ b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py @@ -0,0 +1,72 @@ +import maya.cmds as cmds + +import pyblish.api +from openpype.pipeline.publish import ( + ValidateContentsOrder, PublishValidationError, RepairAction +) + + +class ValidateArnoldSceneSourceCbid(pyblish.api.InstancePlugin): + """Validate Arnold Scene Source Cbid. + + It is required for the proxy and content nodes to share the same cbid. + """ + + order = ValidateContentsOrder + hosts = ["maya"] + families = ["ass"] + label = "Validate Arnold Scene Source CBID" + actions = [RepairAction] + + @staticmethod + def _get_nodes_data(nodes): + nodes_by_name = {} + for node in nodes: + node_split = node.split("|") + nodes_by_name[node_split[-1]] = node + for shape in cmds.listRelatives(node, shapes=True): + nodes_by_name[shape.split("|")[-1]] = node + "|" + shape + + return nodes_by_name + + def get_invalid_couples(self, instance): + content_nodes_by_name = self._get_nodes_data( + instance.data["setMembers"] + ) + proxy_nodes_by_name = self._get_nodes_data( + instance.data.get("proxy", []) + ) + + invalid_couples = [] + for content_name, content_node in content_nodes_by_name.items(): + for proxy_name, proxy_node in proxy_nodes_by_name.items(): + if content_name == proxy_name: + content_value = cmds.getAttr(content_node + ".cbId") + proxy_value = cmds.getAttr(proxy_node + ".cbId") + if content_value != proxy_value: + invalid_couples.append((content_node, proxy_node)) + + return invalid_couples + + def process(self, instance): + # Proxy validation. + if not instance.data.get("proxy", []): + return + + # Validate for proxy nodes sharing the same cbId as content nodes. + invalid_couples = self.get_invalid_couples(instance) + if invalid_couples: + raise PublishValidationError( + "Found proxy nodes with mismatching cbid:\n{}".format( + invalid_couples + ) + ) + + @classmethod + def repair(cls, instance): + for content_node, proxy_node in cls.get_invalid_couples(cls, instance): + cmds.setAttr( + proxy_node + ".cbId", + cmds.getAttr(content_node + ".cbId"), + type="string" + ) From d4c001684c1f3319ecfe152a054fc84767c387db Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 15 Feb 2023 12:27:50 +0000 Subject: [PATCH 136/898] Working shader assignments --- openpype/tools/mayalookassigner/app.py | 23 +- .../tools/mayalookassigner/arnold_standin.py | 225 ++++++++++++++++++ openpype/tools/mayalookassigner/commands.py | 10 +- 3 files changed, 250 insertions(+), 8 deletions(-) create mode 100644 openpype/tools/mayalookassigner/arnold_standin.py diff --git a/openpype/tools/mayalookassigner/app.py b/openpype/tools/mayalookassigner/app.py index f9508657e50..e66f0d73e2d 100644 --- a/openpype/tools/mayalookassigner/app.py +++ b/openpype/tools/mayalookassigner/app.py @@ -24,6 +24,7 @@ remove_unused_looks ) from .vray_proxies import vrayproxy_assign_look +from . import arnold_standin module = sys.modules[__name__] module.window = None @@ -43,7 +44,7 @@ def __init__(self, parent=None): filename = get_workfile() self.setObjectName("lookManager") - self.setWindowTitle("Look Manager 1.3.0 - [{}]".format(filename)) + self.setWindowTitle("Look Manager 1.4.0 - [{}]".format(filename)) self.setWindowFlags(QtCore.Qt.Window) self.setParent(parent) @@ -240,18 +241,26 @@ def on_process_selected(self): )) nodes = item["nodes"] + # Assign Vray Proxy look. if cmds.pluginInfo('vrayformaya', query=True, loaded=True): self.echo("Getting vray proxy nodes ...") vray_proxies = set(cmds.ls(type="VRayProxy", long=True)) - if vray_proxies: - for vp in vray_proxies: - if vp in nodes: - vrayproxy_assign_look(vp, subset_name) + for vp in vray_proxies: + if vp in nodes: + vrayproxy_assign_look(vp, subset_name) - nodes = list(set(item["nodes"]).difference(vray_proxies)) + nodes = list(set(item["nodes"]).difference(vray_proxies)) - # Assign look + # Assign Arnold Standin look. + arnold_standins = set(cmds.ls(type="aiStandIn", long=True)) + for standin in arnold_standins: + if standin in nodes: + arnold_standin.assign_look(standin, subset_name) + + nodes = list(set(item["nodes"]).difference(arnold_standins)) + + # Assign look if nodes: assign_look_by_version(nodes, version_id=version["_id"]) diff --git a/openpype/tools/mayalookassigner/arnold_standin.py b/openpype/tools/mayalookassigner/arnold_standin.py new file mode 100644 index 00000000000..6b5ab10720d --- /dev/null +++ b/openpype/tools/mayalookassigner/arnold_standin.py @@ -0,0 +1,225 @@ +import os +import re +from collections import defaultdict +import json +import logging + +from maya import cmds + +from openpype.pipeline import ( + legacy_io, + get_representation_path, + registered_host, + discover_loader_plugins, + loaders_from_representation, + load_container +) +from openpype.client import ( + get_representation_by_name, + get_last_version_by_subset_name +) +from openpype.hosts.maya.api import lib + + +log = logging.getLogger(__name__) + + +def get_cbid_by_node(path): + """Get cbid from Arnold Scene Source. + + Args: + path (string): Path to Arnold Scene Source. + + Returns: + (dict): Dictionary with node full name/path and CBID. + """ + import arnold + results = {} + + arnold.AiBegin() + + arnold.AiMsgSetConsoleFlags(arnold.AI_LOG_ALL) + + arnold.AiSceneLoad(None, path, None) + + # Iterate over all shader nodes + iter = arnold.AiUniverseGetNodeIterator(arnold.AI_NODE_SHAPE) + while not arnold.AiNodeIteratorFinished(iter): + node = arnold.AiNodeIteratorGetNext(iter) + if arnold.AiNodeIs(node, "polymesh"): + node_name = arnold.AiNodeGetName(node) + try: + results[arnold.AiNodeGetStr(node, "cbId")].append(node_name) + except KeyError: + results[arnold.AiNodeGetStr(node, "cbId")] = [node_name] + + arnold.AiNodeIteratorDestroy(iter) + arnold.AiEnd() + + return results + + +def get_standin_path(node): + path = cmds.getAttr(node + ".dso") + + # Account for frame extension. + basename = os.path.basename(path) + current_frame = 1 + pattern = "(#+)" + matches = re.findall(pattern, basename) + if matches: + substring = "%{}d".format(str(len(matches[0])).zfill(2)) + path = path.replace(matches[0], substring) + path = path % current_frame + + return path + + +def assign_look(standin, subset): + log.info("Assigning {} to {}.".format(subset, standin)) + + nodes_by_id = get_cbid_by_node(get_standin_path(standin)) + + # Group by asset id so we run over the look per asset + node_ids_by_asset_id = defaultdict(set) + for node_id in nodes_by_id: + asset_id = node_id.split(":", 1)[0] + node_ids_by_asset_id[asset_id].add(node_id) + + project_name = legacy_io.active_project() + for asset_id, node_ids in node_ids_by_asset_id.items(): + + # Get latest look version + version = get_last_version_by_subset_name( + project_name, + subset_name=subset, + asset_id=asset_id, + fields=["_id"] + ) + if not version: + log.info("Didn't find last version for subset name {}".format( + subset + )) + continue + + # Relationships. + json_representation = get_representation_by_name( + project_name, representation_name="json", version_id=version["_id"] + ) + + # Load relationships + shader_relation = get_representation_path(json_representation) + with open(shader_relation, "r") as f: + relationships = json.load(f) + + # Load look. + # Get representations of shader file and relationships + look_representation = get_representation_by_name( + project_name, representation_name="ma", version_id=version["_id"] + ) + + # See if representation is already loaded, if so reuse it. + host = registered_host() + representation_id = str(look_representation['_id']) + for container in host.ls(): + if (container['loader'] == "LookLoader" and + container['representation'] == representation_id): + log.info("Reusing loaded look ...") + container_node = container['objectName'] + break + else: + log.info("Using look for the first time ...") + + # Load file + all_loaders = discover_loader_plugins() + loaders = loaders_from_representation( + all_loaders, representation_id + ) + loader = next( + (i for i in loaders if i.__name__ == "LookLoader"), None) + if loader is None: + raise RuntimeError("Could not find LookLoader, this is a bug") + + # Reference the look file + with lib.maintained_selection(): + container_node = load_container(loader, look_representation) + + # Get container members + shader_nodes = lib.get_container_members(container_node) + + # Get only the node ids and paths related to this asset + # And get the shader edits the look supplies + asset_nodes_by_id = { + node_id: nodes_by_id[node_id] for node_id in node_ids + } + edits = list( + lib.iter_shader_edits( + relationships, shader_nodes, asset_nodes_by_id + ) + ) + + # Create assignments + assignments = {} + for edit in edits: + if edit["action"] == "assign": + nodes = edit["nodes"] + shader = edit["shader"] + if not cmds.ls(shader, type="shadingEngine"): + log.info("Skipping non-shader: %s" % shader) + continue + + inputs = cmds.listConnections( + shader + ".surfaceShader", source=True) + if not inputs: + log.info("Shading engine missing material: %s" % shader) + + # Strip off component assignments + for i, node in enumerate(nodes): + if "." in node: + log.warning( + ("Converting face assignment to full object " + "assignment. This conversion can be lossy: " + "{}").format(node)) + nodes[i] = node.split(".")[0] + + material = inputs[0] + assignments[material] = nodes + + # Assign shader + # Clear all current shader assignments + plug = standin + ".operators" + num = cmds.getAttr(plug, size=True) + for i in reversed(range(num)): + cmds.removeMultiInstance("{}[{}]".format(plug, i), b=True) + + # Create new assignment overrides + index = 0 + for material, paths in assignments.items(): + for path in paths: + operator = cmds.createNode("aiSetParameter") + cmds.setAttr(operator + ".selection", path, type="string") + operator_assignments = { + "shader": { + "value": material, + "index": 0, + "enabled": True + } + } + for assignee, data in operator_assignments.items(): + cmds.setAttr( + "{}.assignment[{}]".format(operator, data["index"]), + "{}='{}'".format(assignee, data["value"]), + type="string" + ) + cmds.setAttr( + "{}.enableAssignment[{}]".format( + operator, data["index"] + ), + data["enabled"] + ) + + cmds.connectAttr( + operator + ".out", "{}[{}]".format(plug, index) + ) + + index += 1 diff --git a/openpype/tools/mayalookassigner/commands.py b/openpype/tools/mayalookassigner/commands.py index 2e7a51efded..69fcc77bce9 100644 --- a/openpype/tools/mayalookassigner/commands.py +++ b/openpype/tools/mayalookassigner/commands.py @@ -1,6 +1,7 @@ from collections import defaultdict import logging import os +import re import maya.cmds as cmds @@ -13,6 +14,7 @@ from openpype.hosts.maya.api import lib from .vray_proxies import get_alembic_ids_cache +from . import arnold_standin log = logging.getLogger(__name__) @@ -107,6 +109,7 @@ def create_asset_id_hash(nodes): """ node_id_hash = defaultdict(list) for node in nodes: + shapes = cmds.ls(cmds.listRelatives(node, shapes=True), long=True) # iterate over content of reference node if cmds.nodeType(node) == "reference": ref_hashes = create_asset_id_hash( @@ -122,7 +125,12 @@ def create_asset_id_hash(nodes): pid = k.split(":")[0] if node not in node_id_hash[pid]: node_id_hash[pid].append(node) - + elif shapes and cmds.nodeType(shapes[0]) == "aiStandIn": + path = arnold_standin.get_standin_path(shapes[0]) + for id, _ in arnold_standin.get_cbid_by_node(path).items(): + pid = id.split(":")[0] + if shapes[0] not in node_id_hash[pid]: + node_id_hash[pid].append(shapes[0]) else: value = lib.get_id(node) if value is None: From fafd55cfb1cbcf797ce5a8fa747f2efbc4497236 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 16 Feb 2023 08:12:26 +0000 Subject: [PATCH 137/898] Better support for namespace when publishing ASS --- .../publish/extract_arnold_scene_source.py | 15 ++++++++++++--- .../publish/validate_arnold_scene_source.py | 5 +++-- .../publish/validate_arnold_scene_source_cbid.py | 5 +++-- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index bb27705d2c0..8c9d90e2e6b 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -113,14 +113,22 @@ def process(self, instance): instance.data["representations"].append(representation) def _extract(self, nodes, attribute_data, kwargs): - self.log.info("Writing: " + kwargs["filename"]) + self.log.info( + "Writing {} with:\n{}".format(kwargs["filename"], kwargs) + ) filenames = [] # Duplicating nodes so they are direct children of the world. This # makes the hierarchy of any exported ass file the same. with delete_after() as delete_bin: duplicate_nodes = [] for node in nodes: + parent = cmds.ls( + cmds.listRelatives(node, parent=True)[0], long=True + )[0] duplicate_transform = cmds.duplicate(node)[0] + duplicate_transform = "{}|{}".format( + parent, duplicate_transform + ) # Discard the children. shapes = cmds.listRelatives(duplicate_transform, shapes=True) @@ -133,8 +141,9 @@ def _extract(self, nodes, attribute_data, kwargs): duplicate_transform, world=True )[0] - cmds.rename(duplicate_transform, node.split("|")[-1]) - duplicate_transform = "|" + node.split("|")[-1] + basename = node.split("|")[-1].split(":")[-1] + cmds.rename(duplicate_transform, basename) + duplicate_transform = "|" + basename duplicate_nodes.append(duplicate_transform) delete_bin.append(duplicate_transform) diff --git a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py index e9f6d218f9c..84240e63e66 100644 --- a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py @@ -35,9 +35,10 @@ def _get_nodes_data(self, nodes): if parent: parents.append(parent) - nodes_by_name[node_split[-1]] = node + nodes_by_name[node_split[-1].split(":")[-1]] = node for shape in cmds.listRelatives(node, shapes=True): - nodes_by_name[shape.split("|")[-1]] = node + "|" + shape + basename = shape.split("|")[-1].split(":")[-1] + nodes_by_name[basename] = node + "|" + shape return ungrouped_nodes, nodes_by_name, parents diff --git a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py index bb8ea88453c..056cc94edfd 100644 --- a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py +++ b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py @@ -23,9 +23,10 @@ def _get_nodes_data(nodes): nodes_by_name = {} for node in nodes: node_split = node.split("|") - nodes_by_name[node_split[-1]] = node + nodes_by_name[node_split[-1].split(":")[-1]] = node for shape in cmds.listRelatives(node, shapes=True): - nodes_by_name[shape.split("|")[-1]] = node + "|" + shape + basename = shape.split("|")[-1].split(":")[-1] + nodes_by_name[basename] = node + "|" + shape return nodes_by_name From cbb04773335311c6af2d9311ad045ae12e42d778 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 16 Feb 2023 08:12:37 +0000 Subject: [PATCH 138/898] Fix loading ASS --- openpype/hosts/maya/plugins/load/load_arnold_standin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/load/load_arnold_standin.py b/openpype/hosts/maya/plugins/load/load_arnold_standin.py index 66e8b696392..5a216b930b2 100644 --- a/openpype/hosts/maya/plugins/load/load_arnold_standin.py +++ b/openpype/hosts/maya/plugins/load/load_arnold_standin.py @@ -179,7 +179,7 @@ def update(self, container, representation): # If no proxy exists, the string operator wont replace anything. cmds.setAttr( string_replace_operator + ".match", - "resources/" + proxy_basename, + proxy_basename, type="string" ) cmds.setAttr( From cf4fd979cb6fd3431a365267661a3720ccb1f436 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 16 Feb 2023 08:13:29 +0000 Subject: [PATCH 139/898] Support attribute assignments --- .../tools/mayalookassigner/arnold_standin.py | 85 ++++++++++++------- 1 file changed, 52 insertions(+), 33 deletions(-) diff --git a/openpype/tools/mayalookassigner/arnold_standin.py b/openpype/tools/mayalookassigner/arnold_standin.py index 6b5ab10720d..3290944df93 100644 --- a/openpype/tools/mayalookassigner/arnold_standin.py +++ b/openpype/tools/mayalookassigner/arnold_standin.py @@ -24,6 +24,12 @@ log = logging.getLogger(__name__) +ATTRIBUTE_MAPPING = { + "aiSubdivType": "subdiv_type", + "aiSubdivIterations": "subdiv_iterations" +} + + def get_cbid_by_node(path): """Get cbid from Arnold Scene Source. @@ -146,6 +152,7 @@ def assign_look(standin, subset): # Get container members shader_nodes = lib.get_container_members(container_node) + namespace = shader_nodes[0].split(":")[0] # Get only the node ids and paths related to this asset # And get the shader edits the look supplies @@ -159,31 +166,49 @@ def assign_look(standin, subset): ) # Create assignments - assignments = {} + node_assignments = {} for edit in edits: + for node in edit["nodes"]: + if node not in node_assignments: + node_assignments[node] = [] + if edit["action"] == "assign": - nodes = edit["nodes"] - shader = edit["shader"] - if not cmds.ls(shader, type="shadingEngine"): - log.info("Skipping non-shader: %s" % shader) + if not cmds.ls(edit["shader"], type="shadingEngine"): + log.info("Skipping non-shader: %s" % edit["shader"]) continue inputs = cmds.listConnections( - shader + ".surfaceShader", source=True) + edit["shader"] + ".surfaceShader", source=True) if not inputs: - log.info("Shading engine missing material: %s" % shader) + log.info( + "Shading engine missing material: %s" % edit["shader"] + ) # Strip off component assignments - for i, node in enumerate(nodes): + for i, node in enumerate(edit["nodes"]): if "." in node: log.warning( ("Converting face assignment to full object " "assignment. This conversion can be lossy: " "{}").format(node)) - nodes[i] = node.split(".")[0] + edit["nodes"][i] = node.split(".")[0] + + assignment = "shader='{}'".format(inputs[0]) + for node in edit["nodes"]: + node_assignments[node].append(assignment) + + if edit["action"] == "setattr": + for attr, value in edit["attributes"].items(): + if attr not in ATTRIBUTE_MAPPING: + log.warning( + "Skipping setting attribute {} on {} because it is" + " not recognized.".format(attr, edit["nodes"]) + ) + continue - material = inputs[0] - assignments[material] = nodes + assignment = "{}={}".format(ATTRIBUTE_MAPPING[attr], value) + for node in edit["nodes"]: + node_assignments[node].append(assignment) # Assign shader # Clear all current shader assignments @@ -194,32 +219,26 @@ def assign_look(standin, subset): # Create new assignment overrides index = 0 - for material, paths in assignments.items(): - for path in paths: + for node, assignments in node_assignments.items(): + if not assignments: + continue + + with lib.maintained_selection(): operator = cmds.createNode("aiSetParameter") - cmds.setAttr(operator + ".selection", path, type="string") - operator_assignments = { - "shader": { - "value": material, - "index": 0, - "enabled": True - } - } - for assignee, data in operator_assignments.items(): - cmds.setAttr( - "{}.assignment[{}]".format(operator, data["index"]), - "{}='{}'".format(assignee, data["value"]), - type="string" - ) - cmds.setAttr( - "{}.enableAssignment[{}]".format( - operator, data["index"] - ), - data["enabled"] - ) + operator = cmds.rename(operator, namespace + ":" + operator) + + cmds.setAttr(operator + ".selection", node, type="string") + for i, assignment in enumerate(assignments): + cmds.setAttr( + "{}.assignment[{}]".format(operator, i), + assignment, + type="string" + ) cmds.connectAttr( operator + ".out", "{}[{}]".format(plug, index) ) index += 1 + + cmds.sets(operator, edit=True, addElement=container_node[0]) From 2cb2ba00b788b1423d86098bf99d50b6f27ccc3b Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 16 Feb 2023 08:30:57 +0000 Subject: [PATCH 140/898] Fix collecting and assigning enum values --- openpype/hosts/maya/plugins/publish/collect_look.py | 2 +- openpype/tools/mayalookassigner/arnold_standin.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_look.py b/openpype/hosts/maya/plugins/publish/collect_look.py index b01160a1c05..287ddc228bb 100644 --- a/openpype/hosts/maya/plugins/publish/collect_look.py +++ b/openpype/hosts/maya/plugins/publish/collect_look.py @@ -556,7 +556,7 @@ def collect_attributes_changed(self, instance): continue if cmds.getAttr(attribute, type=True) == "message": continue - node_attributes[attr] = cmds.getAttr(attribute) + node_attributes[attr] = cmds.getAttr(attribute, asString=True) # Only include if there are any properties we care about if not node_attributes: continue diff --git a/openpype/tools/mayalookassigner/arnold_standin.py b/openpype/tools/mayalookassigner/arnold_standin.py index 3290944df93..392fe321480 100644 --- a/openpype/tools/mayalookassigner/arnold_standin.py +++ b/openpype/tools/mayalookassigner/arnold_standin.py @@ -206,7 +206,11 @@ def assign_look(standin, subset): ) continue + if isinstance(value, str): + value = "'{}'".format(value) + assignment = "{}={}".format(ATTRIBUTE_MAPPING[attr], value) + for node in edit["nodes"]: node_assignments[node].append(assignment) From 0e70a9559bd1238a586ce80bf178ee29ce0313f1 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 16 Feb 2023 09:03:55 +0000 Subject: [PATCH 141/898] Support displacement shader --- .../tools/mayalookassigner/arnold_standin.py | 56 ++++++++++++------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/openpype/tools/mayalookassigner/arnold_standin.py b/openpype/tools/mayalookassigner/arnold_standin.py index 392fe321480..0ba1526cda7 100644 --- a/openpype/tools/mayalookassigner/arnold_standin.py +++ b/openpype/tools/mayalookassigner/arnold_standin.py @@ -81,6 +81,31 @@ def get_standin_path(node): return path +def shading_engine_assignments(shading_engine, attr, nodes, assignments): + shader_inputs = cmds.listConnections( + shading_engine + "." + attr, source=True) + if not shader_inputs: + log.info( + "Shading engine \"{}\" missing input \"{}\"".format( + shading_engine, attr + ) + ) + + # Strip off component assignments + for i, node in enumerate(nodes): + if "." in node: + log.warning( + ("Converting face assignment to full object " + "assignment. This conversion can be lossy: " + "{}").format(node)) + nodes[i] = node.split(".")[0] + + shader_type = "shader" if attr == "surfaceShader" else "disp_map" + assignment = "{}='{}'".format(shader_type, shader_inputs[0]) + for node in nodes: + assignments[node].append(assignment) + + def assign_look(standin, subset): log.info("Assigning {} to {}.".format(subset, standin)) @@ -177,25 +202,18 @@ def assign_look(standin, subset): log.info("Skipping non-shader: %s" % edit["shader"]) continue - inputs = cmds.listConnections( - edit["shader"] + ".surfaceShader", source=True) - if not inputs: - log.info( - "Shading engine missing material: %s" % edit["shader"] - ) - - # Strip off component assignments - for i, node in enumerate(edit["nodes"]): - if "." in node: - log.warning( - ("Converting face assignment to full object " - "assignment. This conversion can be lossy: " - "{}").format(node)) - edit["nodes"][i] = node.split(".")[0] - - assignment = "shader='{}'".format(inputs[0]) - for node in edit["nodes"]: - node_assignments[node].append(assignment) + shading_engine_assignments( + edit["shader"], + "surfaceShader", + edit["nodes"], + node_assignments + ) + shading_engine_assignments( + edit["shader"], + "displacementShader", + edit["nodes"], + node_assignments + ) if edit["action"] == "setattr": for attr, value in edit["attributes"].items(): From d13b74cb29b41d8fb94a7b6e3fbdd0146619ade9 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 16 Feb 2023 10:47:51 +0000 Subject: [PATCH 142/898] Support more parameters. --- .../tools/mayalookassigner/arnold_standin.py | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/openpype/tools/mayalookassigner/arnold_standin.py b/openpype/tools/mayalookassigner/arnold_standin.py index 0ba1526cda7..b7568ec45ff 100644 --- a/openpype/tools/mayalookassigner/arnold_standin.py +++ b/openpype/tools/mayalookassigner/arnold_standin.py @@ -25,11 +25,49 @@ ATTRIBUTE_MAPPING = { + "primaryVisibility": "visibility", # Camera + "castsShadows": "visibility", # Shadow + "receiveShadows": "receive_shadows", + "aiSelfShadows": "self_shadows", + "aiOpaque": "opaque", + "aiMatte": "matte", + "aiVisibleInDiffuseTransmission": "visibility", + "aiVisibleInSpecularTransmission": "visibility", + "aiVisibleInVolume": "visibility", + "aiVisibleInDiffuseReflection": "visibility", + "aiVisibleInSpecularReflection": "visibility", + "aiSubdivUvSmoothing": "subdiv_uv_smoothing", + "aiDispHeight": "disp_height", + "aiDispPadding": "disp_padding", + "aiDispZeroValue": "disp_zero_value", + "aiStepSize": "step_size", + "aiVolumePadding": "volume_padding", "aiSubdivType": "subdiv_type", "aiSubdivIterations": "subdiv_iterations" } +def calculate_visibility_mask(attributes): + # https://arnoldsupport.com/2018/11/21/backdoor-setting-visibility/ + mapping = { + "primaryVisibility": 1, # Camera + "castsShadows": 2, # Shadow + "aiVisibleInDiffuseTransmission": 4, + "aiVisibleInSpecularTransmission": 8, + "aiVisibleInVolume": 16, + "aiVisibleInDiffuseReflection": 32, + "aiVisibleInSpecularReflection": 64 + } + mask = 255 + for attr, value in mapping.items(): + if attributes.get(attr, True): + continue + + mask -= value + + return mask + + def get_cbid_by_node(path): """Get cbid from Arnold Scene Source. @@ -216,6 +254,7 @@ def assign_look(standin, subset): ) if edit["action"] == "setattr": + visibility = False for attr, value in edit["attributes"].items(): if attr not in ATTRIBUTE_MAPPING: log.warning( @@ -227,11 +266,37 @@ def assign_look(standin, subset): if isinstance(value, str): value = "'{}'".format(value) + if ATTRIBUTE_MAPPING[attr] == "visibility": + visibility = True + continue + assignment = "{}={}".format(ATTRIBUTE_MAPPING[attr], value) for node in edit["nodes"]: node_assignments[node].append(assignment) + if visibility: + # https://arnoldsupport.com/2018/11/21/backdoor-setting-visibility/ + mapping = { + "primaryVisibility": 1, # Camera + "castsShadows": 2, # Shadow + "aiVisibleInDiffuseTransmission": 4, + "aiVisibleInSpecularTransmission": 8, + "aiVisibleInVolume": 16, + "aiVisibleInDiffuseReflection": 32, + "aiVisibleInSpecularReflection": 64 + } + mask = 255 + for attr, value in mapping.items(): + if edit["attributes"].get(attr, True): + continue + mask -= value + + assignment = "visibility={}".format(mask) + + for node in edit["nodes"]: + node_assignments[node].append(assignment) + # Assign shader # Clear all current shader assignments plug = standin + ".operators" From 70b607bf15de2bbc35b7fff26ed710cd0f46c443 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 16 Feb 2023 11:05:57 +0000 Subject: [PATCH 143/898] Refactor to share code between vray and arnold --- .../tools/mayalookassigner/arnold_standin.py | 68 ++------------- openpype/tools/mayalookassigner/lib.py | 87 +++++++++++++++++++ 2 files changed, 95 insertions(+), 60 deletions(-) create mode 100644 openpype/tools/mayalookassigner/lib.py diff --git a/openpype/tools/mayalookassigner/arnold_standin.py b/openpype/tools/mayalookassigner/arnold_standin.py index b7568ec45ff..7d3b7e59b3e 100644 --- a/openpype/tools/mayalookassigner/arnold_standin.py +++ b/openpype/tools/mayalookassigner/arnold_standin.py @@ -1,24 +1,14 @@ import os import re from collections import defaultdict -import json import logging from maya import cmds -from openpype.pipeline import ( - legacy_io, - get_representation_path, - registered_host, - discover_loader_plugins, - loaders_from_representation, - load_container -) -from openpype.client import ( - get_representation_by_name, - get_last_version_by_subset_name -) -from openpype.hosts.maya.api import lib +from openpype.pipeline import legacy_io +from openpype.client import get_last_version_by_subset_name +from openpype.hosts.maya import api +from . import lib log = logging.getLogger(__name__) @@ -171,50 +161,8 @@ def assign_look(standin, subset): )) continue - # Relationships. - json_representation = get_representation_by_name( - project_name, representation_name="json", version_id=version["_id"] - ) - - # Load relationships - shader_relation = get_representation_path(json_representation) - with open(shader_relation, "r") as f: - relationships = json.load(f) - - # Load look. - # Get representations of shader file and relationships - look_representation = get_representation_by_name( - project_name, representation_name="ma", version_id=version["_id"] - ) - - # See if representation is already loaded, if so reuse it. - host = registered_host() - representation_id = str(look_representation['_id']) - for container in host.ls(): - if (container['loader'] == "LookLoader" and - container['representation'] == representation_id): - log.info("Reusing loaded look ...") - container_node = container['objectName'] - break - else: - log.info("Using look for the first time ...") - - # Load file - all_loaders = discover_loader_plugins() - loaders = loaders_from_representation( - all_loaders, representation_id - ) - loader = next( - (i for i in loaders if i.__name__ == "LookLoader"), None) - if loader is None: - raise RuntimeError("Could not find LookLoader, this is a bug") - - # Reference the look file - with lib.maintained_selection(): - container_node = load_container(loader, look_representation) - - # Get container members - shader_nodes = lib.get_container_members(container_node) + relationships = lib.get_look_relationships(version["_id"]) + shader_nodes, container_node = lib.load_look(version["_id"]) namespace = shader_nodes[0].split(":")[0] # Get only the node ids and paths related to this asset @@ -223,7 +171,7 @@ def assign_look(standin, subset): node_id: nodes_by_id[node_id] for node_id in node_ids } edits = list( - lib.iter_shader_edits( + api.lib.iter_shader_edits( relationships, shader_nodes, asset_nodes_by_id ) ) @@ -310,7 +258,7 @@ def assign_look(standin, subset): if not assignments: continue - with lib.maintained_selection(): + with api.lib.maintained_selection(): operator = cmds.createNode("aiSetParameter") operator = cmds.rename(operator, namespace + ":" + operator) diff --git a/openpype/tools/mayalookassigner/lib.py b/openpype/tools/mayalookassigner/lib.py new file mode 100644 index 00000000000..5594c53c33e --- /dev/null +++ b/openpype/tools/mayalookassigner/lib.py @@ -0,0 +1,87 @@ +import json +import logging + +from openpype.pipeline import ( + legacy_io, + get_representation_path, + registered_host, + discover_loader_plugins, + loaders_from_representation, + load_container +) +from openpype.client import get_representation_by_name +from openpype.hosts.maya.api import lib + + +log = logging.getLogger(__name__) + + +def get_look_relationships(version_id): + # type: (str) -> dict + """Get relations for the look. + + Args: + version_id (str): Parent version Id. + + Returns: + dict: Dictionary of relations. + """ + + project_name = legacy_io.active_project() + json_representation = get_representation_by_name( + project_name, representation_name="json", version_id=version_id + ) + + # Load relationships + shader_relation = get_representation_path(json_representation) + with open(shader_relation, "r") as f: + relationships = json.load(f) + + return relationships + + +def load_look(version_id): + # type: (str) -> list + """Load look from version. + + Get look from version and invoke Loader for it. + + Args: + version_id (str): Version ID + + Returns: + list of shader nodes. + + """ + + project_name = legacy_io.active_project() + # Get representations of shader file and relationships + look_representation = get_representation_by_name( + project_name, representation_name="ma", version_id=version_id + ) + + # See if representation is already loaded, if so reuse it. + host = registered_host() + representation_id = str(look_representation['_id']) + for container in host.ls(): + if (container['loader'] == "LookLoader" and + container['representation'] == representation_id): + log.info("Reusing loaded look ...") + container_node = container['objectName'] + break + else: + log.info("Using look for the first time ...") + + # Load file + all_loaders = discover_loader_plugins() + loaders = loaders_from_representation(all_loaders, representation_id) + loader = next( + (i for i in loaders if i.__name__ == "LookLoader"), None) + if loader is None: + raise RuntimeError("Could not find LookLoader, this is a bug") + + # Reference the look file + with lib.maintained_selection(): + container_node = load_container(loader, look_representation) + + return lib.get_container_members(container_node), container_node From c426e34761828bfb7540c041fc2b0398ab10acb4 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 16 Feb 2023 11:08:25 +0000 Subject: [PATCH 144/898] Missing refactor code --- .../tools/mayalookassigner/vray_proxies.py | 97 ++----------------- 1 file changed, 7 insertions(+), 90 deletions(-) diff --git a/openpype/tools/mayalookassigner/vray_proxies.py b/openpype/tools/mayalookassigner/vray_proxies.py index 889396e555d..6ee618f37a8 100644 --- a/openpype/tools/mayalookassigner/vray_proxies.py +++ b/openpype/tools/mayalookassigner/vray_proxies.py @@ -3,26 +3,16 @@ import os from collections import defaultdict import logging -import json import six import alembic.Abc from maya import cmds -from openpype.client import ( - get_representation_by_name, - get_last_version_by_subset_name, -) -from openpype.pipeline import ( - legacy_io, - load_container, - loaders_from_representation, - discover_loader_plugins, - get_representation_path, - registered_host, -) -from openpype.hosts.maya.api import lib +from openpype.client import get_last_version_by_subset_name +from openpype.pipeline import legacy_io +from openpype.hosts.maya import api +from . import lib log = logging.getLogger(__name__) @@ -149,79 +139,6 @@ def assign_vrayproxy_shaders(vrayproxy, assignments): index += 1 -def get_look_relationships(version_id): - # type: (str) -> dict - """Get relations for the look. - - Args: - version_id (str): Parent version Id. - - Returns: - dict: Dictionary of relations. - """ - - project_name = legacy_io.active_project() - json_representation = get_representation_by_name( - project_name, representation_name="json", version_id=version_id - ) - - # Load relationships - shader_relation = get_representation_path(json_representation) - with open(shader_relation, "r") as f: - relationships = json.load(f) - - return relationships - - -def load_look(version_id): - # type: (str) -> list - """Load look from version. - - Get look from version and invoke Loader for it. - - Args: - version_id (str): Version ID - - Returns: - list of shader nodes. - - """ - - project_name = legacy_io.active_project() - # Get representations of shader file and relationships - look_representation = get_representation_by_name( - project_name, representation_name="ma", version_id=version_id - ) - - # See if representation is already loaded, if so reuse it. - host = registered_host() - representation_id = str(look_representation['_id']) - for container in host.ls(): - if (container['loader'] == "LookLoader" and - container['representation'] == representation_id): - log.info("Reusing loaded look ...") - container_node = container['objectName'] - break - else: - log.info("Using look for the first time ...") - - # Load file - all_loaders = discover_loader_plugins() - loaders = loaders_from_representation(all_loaders, representation_id) - loader = next( - (i for i in loaders if i.__name__ == "LookLoader"), None) - if loader is None: - raise RuntimeError("Could not find LookLoader, this is a bug") - - # Reference the look file - with lib.maintained_selection(): - container_node = load_container(loader, look_representation) - - # Get container members - shader_nodes = lib.get_container_members(container_node) - return shader_nodes - - def vrayproxy_assign_look(vrayproxy, subset="lookDefault"): # type: (str, str) -> None """Assign look to vray proxy. @@ -263,8 +180,8 @@ def vrayproxy_assign_look(vrayproxy, subset="lookDefault"): )) continue - relationships = get_look_relationships(version["_id"]) - shadernodes = load_look(version["_id"]) + relationships = lib.get_look_relationships(version["_id"]) + shadernodes, _ = lib.load_look(version["_id"]) # Get only the node ids and paths related to this asset # And get the shader edits the look supplies @@ -272,7 +189,7 @@ def vrayproxy_assign_look(vrayproxy, subset="lookDefault"): node_id: nodes_by_id[node_id] for node_id in node_ids } edits = list( - lib.iter_shader_edits( + api.lib.iter_shader_edits( relationships, shadernodes, asset_nodes_by_id)) # Create assignments From 017d85d74b897a85d422e8b6770e4b789ad040e9 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 16 Feb 2023 11:11:29 +0000 Subject: [PATCH 145/898] Hound --- openpype/tools/mayalookassigner/commands.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/tools/mayalookassigner/commands.py b/openpype/tools/mayalookassigner/commands.py index 69fcc77bce9..c22a8c92111 100644 --- a/openpype/tools/mayalookassigner/commands.py +++ b/openpype/tools/mayalookassigner/commands.py @@ -1,7 +1,6 @@ from collections import defaultdict import logging import os -import re import maya.cmds as cmds From da183c2199f6eadb567c0bf4db400124a2583674 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 16 Feb 2023 16:30:16 +0000 Subject: [PATCH 146/898] Saving with default settings properly. --- openpype/settings/defaults/project_settings/deadline.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/settings/defaults/project_settings/deadline.json b/openpype/settings/defaults/project_settings/deadline.json index c563531b39e..e55f33bb411 100644 --- a/openpype/settings/defaults/project_settings/deadline.json +++ b/openpype/settings/defaults/project_settings/deadline.json @@ -107,4 +107,4 @@ } } } -} +} \ No newline at end of file From 63eee639f7a3f01ad15d6e9b8bc5b7608e21084b Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 16 Feb 2023 18:35:23 +0000 Subject: [PATCH 147/898] Fix frames issues. --- .../deadline/plugins/publish/submit_maya_deadline.py | 1 + .../publish/validate_expected_and_rendered_files.py | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py index cb47c854a82..19e8a258f42 100644 --- a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py @@ -442,6 +442,7 @@ def _tile_render(self, payload): frame_assembly_job_info.ExtraInfo[0] = file_hash frame_assembly_job_info.ExtraInfo[1] = file frame_assembly_job_info.JobDependencies = tile_job_id + frame_assembly_job_info.Frames = frame # write assembly job config files config_file = os.path.join( diff --git a/openpype/modules/deadline/plugins/publish/validate_expected_and_rendered_files.py b/openpype/modules/deadline/plugins/publish/validate_expected_and_rendered_files.py index f0a3ddd2463..9311a9d64ae 100644 --- a/openpype/modules/deadline/plugins/publish/validate_expected_and_rendered_files.py +++ b/openpype/modules/deadline/plugins/publish/validate_expected_and_rendered_files.py @@ -68,8 +68,15 @@ def process(self, instance): # files to be in the folder that we might not want to use. missing = expected_files - existing_files if missing: - raise RuntimeError("Missing expected files: {}".format( - sorted(missing))) + raise RuntimeError( + "Missing expected files: {}\n" + "Expected files: {}\n" + "Existing files: {}".format( + sorted(missing), + sorted(expected_files), + sorted(existing_files) + ) + ) def _get_frame_list(self, original_job_id): """Returns list of frame ranges from all render job. From 718f4e748d86177617e12915eae7c53fdc3a5eec Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov <11698866+movalex@users.noreply.github.com> Date: Fri, 17 Feb 2023 00:46:40 +0300 Subject: [PATCH 148/898] Update openpype/hosts/fusion/hooks/pre_fusion_setup.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- .../hosts/fusion/hooks/pre_fusion_setup.py | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index 3bb345b72f6..9ae57d2a170 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -53,14 +53,21 @@ def get_profile_source(self) -> Path: def get_copy_fusion_prefs_settings(self): """Get copy prefserences options from the global application settings""" - copy_status = copy_path = None - try: - copy_status, copy_path, force_sync = get_system_settings()["applications"]["fusion"][ - "copy_fusion_settings"].values() - except ValueError: - self.log.error('Copy prefs settings not found') - finally: - return copy_status, Path(copy_path).expanduser(), force_sync + copy_fusion_settings = ( + self.data + ["system_settings"] + ["applications"] + ["fusion"] + .get("copy_fusion_settings", {}) + ) + if not copy_fusion_settings: + self.log.error("Copy prefs settings not found") + copy_status = copy_fusion_settings.get("copy_status", False) + force_sync = copy_fusion_settings.get("force_sync", False) + copy_path = copy_fusion_settings.get("copy_path") or None + if copy_path: + copy_path = Path(copy_path).expanduser() + return copy_status, copy_path, force_sync def copy_existing_prefs(self, copy_from: Path, copy_to: Path, force_sync: bool) -> None: """On the first Fusion launch copy the Fusion profile to the working directory. From dacc90f9ad8ddab10ad60f814950db818e3327f3 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Fri, 17 Feb 2023 13:31:52 +0300 Subject: [PATCH 149/898] remove redundant get gomp name function --- openpype/hosts/fusion/api/lib.py | 7 ------- openpype/hosts/fusion/api/workio.py | 3 ++- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/fusion/api/lib.py b/openpype/hosts/fusion/api/lib.py index ec96d6cf181..f175d3a1d34 100644 --- a/openpype/hosts/fusion/api/lib.py +++ b/openpype/hosts/fusion/api/lib.py @@ -316,13 +316,6 @@ def get_current_comp(): return comp -def get_comp_filename(): - """Get comp's Filename""" - comp = get_current_comp() - if comp: - return comp.GetAttrs()["COMPS_FileName"] - - @contextlib.contextmanager def comp_lock_and_undo_chunk(comp, undo_queue_name="Script CMD"): """Lock comp and open an undo chunk during the context""" diff --git a/openpype/hosts/fusion/api/workio.py b/openpype/hosts/fusion/api/workio.py index 048e6e090af..8012d600dab 100644 --- a/openpype/hosts/fusion/api/workio.py +++ b/openpype/hosts/fusion/api/workio.py @@ -25,7 +25,8 @@ def open_file(filepath): def current_file(): - current_filepath = get_comp_filename() + comp = get_current_comp() + current_filepath = comp.GetAttrs()["COMPS_FileName"] return current_filepath or None From d77c0e252be994a242d7004b675a8247abfc8326 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Fri, 17 Feb 2023 13:49:32 +0300 Subject: [PATCH 150/898] move fusion prefs settings to project_settings --- .../hosts/fusion/hooks/pre_fusion_setup.py | 23 +++++++------- .../defaults/project_settings/fusion.json | 5 ++++ .../system_settings/applications.json | 5 ---- .../schema_project_fusion.json | 24 +++++++++++++++ .../host_settings/schema_fusion.json | 30 ------------------- 5 files changed, 39 insertions(+), 48 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index 9ae57d2a170..ad2ec7eb2da 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -4,7 +4,6 @@ from pathlib import Path from openpype.lib import PreLaunchHook, ApplicationLaunchFailed from openpype.hosts.fusion import FUSION_HOST_DIR -from openpype.settings import get_system_settings class FusionPrelaunch(PreLaunchHook): @@ -39,11 +38,10 @@ def get_profile_source(self) -> Path: self.log.info(f"Local Fusion prefs environment is set to {fusion_prefs_dir}") fusion_prefs_filepath = fusion_prefs_dir / "Fusion.prefs" return fusion_prefs_filepath - # otherwise get the profile from default prefs location fusion_prefs_path = f"Blackmagic Design/Fusion/Profiles/{fusion_profile}/Fusion.prefs" if platform.system() == "Windows": - prefs_source = Path(os.getenv("AppData")) / fusion_prefs_path + prefs_source = Path(os.getenv("AppData"), fusion_prefs_path) elif platform.system() == "Darwin": prefs_source = Path("~/Library/Application Support/", fusion_prefs_path).expanduser() elif platform.system() == "Linux": @@ -55,8 +53,7 @@ def get_copy_fusion_prefs_settings(self): """Get copy prefserences options from the global application settings""" copy_fusion_settings = ( self.data - ["system_settings"] - ["applications"] + ["project_settings"] ["fusion"] .get("copy_fusion_settings", {}) ) @@ -73,7 +70,7 @@ def copy_existing_prefs(self, copy_from: Path, copy_to: Path, force_sync: bool) """On the first Fusion launch copy the Fusion profile to the working directory. If the Openpype profile folder exists, skip copying, unless Force sync is checked. If the prefs were not copied on the first launch, clean Fusion profile - will be created in openpype_fusion_profile_dir. + will be created in fusion_profile_dir. """ if copy_to.exists() and not force_sync: self.log.info("Local Fusion preferences folder exists, skipping profile copy") @@ -127,14 +124,14 @@ def execute(self): self.log.info(f"Setting OPENPYPE_FUSION: {FUSION_HOST_DIR}") self.launch_context.env["OPENPYPE_FUSION"] = FUSION_HOST_DIR - copy_status, openpype_fusion_profile_dir, force_sync = self.get_copy_fusion_prefs_settings() + copy_status, fusion_profile_dir, force_sync = self.get_copy_fusion_prefs_settings() if copy_status: prefs_source = self.get_profile_source() - self.copy_existing_prefs(prefs_source, openpype_fusion_profile_dir, force_sync) + self.copy_existing_prefs(prefs_source, fusion_profile_dir, force_sync) fusion_profile_dir_variable = f"FUSION{self.PROFILE_NUMBER}_PROFILE_DIR" master_prefs_variable = f"FUSION{self.PROFILE_NUMBER}_MasterPrefs" - openpype_master_prefs = Path(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") - self.log.info(f"Setting {fusion_profile_dir_variable}: {openpype_fusion_profile_dir}") - self.launch_context.env[fusion_profile_dir_variable] = str(openpype_fusion_profile_dir) - self.log.info(f"Setting {master_prefs_variable}: {openpype_master_prefs}") - self.launch_context.env[master_prefs_variable] = str(openpype_master_prefs) + master_prefs = Path(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") + self.log.info(f"Setting {fusion_profile_dir_variable}: {fusion_profile_dir}") + self.launch_context.env[fusion_profile_dir_variable] = str(fusion_profile_dir) + self.log.info(f"Setting {master_prefs_variable}: {master_prefs}") + self.launch_context.env[master_prefs_variable] = str(master_prefs) diff --git a/openpype/settings/defaults/project_settings/fusion.json b/openpype/settings/defaults/project_settings/fusion.json index 720178e17a8..74863ece43c 100644 --- a/openpype/settings/defaults/project_settings/fusion.json +++ b/openpype/settings/defaults/project_settings/fusion.json @@ -16,5 +16,10 @@ "linux": [] } } + }, + "copy_fusion_settings": { + "copy_status": false, + "copy_path": "~/.openpype/hosts/fusion/prefs", + "force_sync": false } } \ No newline at end of file diff --git a/openpype/settings/defaults/system_settings/applications.json b/openpype/settings/defaults/system_settings/applications.json index 9fb730568ed..d498bccda9d 100644 --- a/openpype/settings/defaults/system_settings/applications.json +++ b/openpype/settings/defaults/system_settings/applications.json @@ -835,11 +835,6 @@ "linux": "/opt/Python/3.6/bin" } }, - "copy_fusion_settings": { - "copy_prefs": false, - "prefs_path": "~/.openpype/hosts/fusion/prefs", - "force_sync": false - }, "variants": { "18": { "executables": { diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_fusion.json b/openpype/settings/entities/schemas/projects_schema/schema_project_fusion.json index 8c62d758159..540f840aad3 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_fusion.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_fusion.json @@ -45,6 +45,30 @@ ] } ] + }, + { + "type": "dict", + "key": "copy_fusion_settings", + "collapsible": true, + "checkbox_key": "copy_status", + "label": "Copy Fusion settings on launch", + "children": [ + { + "type": "boolean", + "key": "copy_status", + "label": "Enabled" + }, + { + "key": "copy_path", + "type": "path", + "label": "Local prefs directory" + }, + { + "key":"force_sync", + "type": "boolean", + "label": "Force sync preferences" + } + ] } ] } diff --git a/openpype/settings/entities/schemas/system_schema/host_settings/schema_fusion.json b/openpype/settings/entities/schemas/system_schema/host_settings/schema_fusion.json index 48355932ae6..5960da77744 100644 --- a/openpype/settings/entities/schemas/system_schema/host_settings/schema_fusion.json +++ b/openpype/settings/entities/schemas/system_schema/host_settings/schema_fusion.json @@ -19,36 +19,6 @@ "label": "Environment", "type": "raw-json" }, - { - "type": "splitter" - }, - { - "type": "dict", - "key": "copy_fusion_settings", - "collapsible": true, - "checkbox_key": "copy_prefs", - "label": "Copy Fusion settings when launched from OpenPype", - "children": [ - { - "type": "boolean", - "key": "copy_prefs", - "label": "Enabled" - }, - { - "key": "prefs_path", - "type": "path", - "label": "Local prefs directory" - }, - { - "key":"force_sync", - "type": "boolean", - "label": "Always sync preferences on launch" - } - ] - }, - { - "type": "splitter" - }, { "type": "dict-modifiable", "key": "variants", From 87ab9e35983241b255347d7f98daafadac09def6 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Fri, 17 Feb 2023 13:50:08 +0300 Subject: [PATCH 151/898] rename get_fusion module --- openpype/hosts/fusion/api/lib.py | 4 ++-- openpype/hosts/fusion/api/workio.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/fusion/api/lib.py b/openpype/hosts/fusion/api/lib.py index f175d3a1d34..709d3cbdc6a 100644 --- a/openpype/hosts/fusion/api/lib.py +++ b/openpype/hosts/fusion/api/lib.py @@ -302,7 +302,7 @@ def get_frame_path(path): return filename, padding, ext -def get_fusion(): +def get_fusion_module(): """Get current Fusion instance""" fusion = getattr(sys.modules["__main__"], "fusion", None) return fusion @@ -310,7 +310,7 @@ def get_fusion(): def get_current_comp(): """Get current comp in this session""" - fusion = get_fusion() + fusion = get_fusion_module() if fusion: comp = fusion.CurrentComp return comp diff --git a/openpype/hosts/fusion/api/workio.py b/openpype/hosts/fusion/api/workio.py index 8012d600dab..f51c4fa9c14 100644 --- a/openpype/hosts/fusion/api/workio.py +++ b/openpype/hosts/fusion/api/workio.py @@ -2,7 +2,7 @@ import sys import os -from .lib import get_fusion, get_current_comp, get_comp_filename +from .lib import get_fusion_module, get_current_comp, get_comp_filename def file_extensions(): @@ -20,7 +20,7 @@ def save_file(filepath): def open_file(filepath): - fusion = get_fusion() + fusion = get_fusion_module() return fusion.LoadComp(filepath) From 39ee896d7ebb4ab22d7d747bd2693e79bb7d9512 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov <11698866+movalex@users.noreply.github.com> Date: Sat, 18 Feb 2023 07:47:42 +0300 Subject: [PATCH 152/898] Update openpype/hosts/fusion/api/lib.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- openpype/hosts/fusion/api/lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/api/lib.py b/openpype/hosts/fusion/api/lib.py index 709d3cbdc6a..4830c3b3dfa 100644 --- a/openpype/hosts/fusion/api/lib.py +++ b/openpype/hosts/fusion/api/lib.py @@ -311,7 +311,7 @@ def get_fusion_module(): def get_current_comp(): """Get current comp in this session""" fusion = get_fusion_module() - if fusion: + if fusion is not None: comp = fusion.CurrentComp return comp From ea1f10b9db63f21161cb97c6ac984d07d361e7ed Mon Sep 17 00:00:00 2001 From: Simone Barbieri Date: Mon, 20 Feb 2023 12:52:08 +0000 Subject: [PATCH 153/898] Removed references to openpype.api --- openpype/hosts/blender/plugins/publish/extract_playblast.py | 5 ++--- openpype/hosts/blender/plugins/publish/extract_thumbnail.py | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/blender/plugins/publish/extract_playblast.py b/openpype/hosts/blender/plugins/publish/extract_playblast.py index 1114b633be0..8dc2f66c22a 100644 --- a/openpype/hosts/blender/plugins/publish/extract_playblast.py +++ b/openpype/hosts/blender/plugins/publish/extract_playblast.py @@ -4,12 +4,12 @@ import bpy import pyblish.api -import openpype.api +from openpype.pipeline import publish from openpype.hosts.blender.api import capture from openpype.hosts.blender.api.lib import maintained_time -class ExtractPlayblast(openpype.api.Extractor): +class ExtractPlayblast(publish.Extractor): """ Extract viewport playblast. @@ -27,7 +27,6 @@ def process(self, instance): self.log.info("Extracting capture..") self.log.info(instance.data) - print(instance.context.data) # get scene fps fps = instance.data.get("fps") diff --git a/openpype/hosts/blender/plugins/publish/extract_thumbnail.py b/openpype/hosts/blender/plugins/publish/extract_thumbnail.py index ba455cf450a..65c3627375e 100644 --- a/openpype/hosts/blender/plugins/publish/extract_thumbnail.py +++ b/openpype/hosts/blender/plugins/publish/extract_thumbnail.py @@ -2,14 +2,14 @@ import glob import pyblish.api -import openpype.api +from openpype.pipeline import publish from openpype.hosts.blender.api import capture from openpype.hosts.blender.api.lib import maintained_time import bpy -class ExtractThumbnail(openpype.api.Extractor): +class ExtractThumbnail(publish.Extractor): """Extract viewport thumbnail. Takes review camera and creates a thumbnail based on viewport From 7fe1473dde672e83dc62236d697cc70bd0feebc9 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Tue, 21 Feb 2023 00:13:53 +0300 Subject: [PATCH 154/898] disable root toggle, rename settings --- .../defaults/project_settings/fusion.json | 2 +- .../projects_schema/schema_project_fusion.json | 17 ++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/openpype/settings/defaults/project_settings/fusion.json b/openpype/settings/defaults/project_settings/fusion.json index 74863ece43c..97c1c52579b 100644 --- a/openpype/settings/defaults/project_settings/fusion.json +++ b/openpype/settings/defaults/project_settings/fusion.json @@ -18,8 +18,8 @@ } }, "copy_fusion_settings": { + "copy_path": "~/.openpype/hosts/fusion/profiles", "copy_status": false, - "copy_path": "~/.openpype/hosts/fusion/prefs", "force_sync": false } } \ No newline at end of file diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_fusion.json b/openpype/settings/entities/schemas/projects_schema/schema_project_fusion.json index 540f840aad3..464cf2c06d4 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_fusion.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_fusion.json @@ -50,23 +50,22 @@ "type": "dict", "key": "copy_fusion_settings", "collapsible": true, - "checkbox_key": "copy_status", - "label": "Copy Fusion settings on launch", + "label": "Local Fusion profile settings", "children": [ - { - "type": "boolean", - "key": "copy_status", - "label": "Enabled" - }, { "key": "copy_path", "type": "path", - "label": "Local prefs directory" + "label": "Local Fusion profile directory" + }, + { + "type": "boolean", + "key": "copy_status", + "label": "Copy profile on first launch" }, { "key":"force_sync", "type": "boolean", - "label": "Force sync preferences" + "label": "Resync profile on each launch" } ] } From 7466f576ba9d8c1ca37b272320ae47c251018ca5 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Tue, 21 Feb 2023 00:14:17 +0300 Subject: [PATCH 155/898] remove redundant import --- openpype/hosts/fusion/api/workio.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/api/workio.py b/openpype/hosts/fusion/api/workio.py index f51c4fa9c14..fbb5a588f4d 100644 --- a/openpype/hosts/fusion/api/workio.py +++ b/openpype/hosts/fusion/api/workio.py @@ -2,7 +2,7 @@ import sys import os -from .lib import get_fusion_module, get_current_comp, get_comp_filename +from .lib import get_fusion_module, get_current_comp def file_extensions(): From 1235894970870e0317a3c275c4acbea52504c762 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Tue, 21 Feb 2023 02:41:32 +0300 Subject: [PATCH 156/898] copy all fusion pref files, update docs --- .../hosts/fusion/hooks/pre_fusion_setup.py | 47 ++++++++++++------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index ad2ec7eb2da..949f86d9812 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -17,35 +17,40 @@ class FusionPrelaunch(PreLaunchHook): as set in openpype/hosts/fusion/deploy/fusion_shared.prefs to enable the OpenPype menu and force Python 3 over Python 2. + PROFILE_NUMBER is used because from the Fusion v16 the profile folder + is project-specific, but then it was abandoned by devs, + and despite it is already Fusion version 18, still FUSION16_PROFILE_DIR is used. + The variable is added in case the version number will be updated or deleted + so we could easily change the version or disable it. """ app_groups = ["fusion"] PROFILE_NUMBER = 16 + def get_fusion_profile_name(self) -> str: """usually set to 'Default', unless FUSION16_PROFILE is set""" return os.getenv(f"FUSION{self.PROFILE_NUMBER}_PROFILE", "Default") def get_profile_source(self) -> Path: """Get the Fusion preferences (profile) location. - Check https://www.steakunderwater.com/VFXPedia/96.0.243.189/indexad6a.html?title=Per-User_Preferences_and_Paths for reference. + Check Per-User_Preferences_and_Paths on VFXpedia for reference. """ fusion_profile = self.get_fusion_profile_name() fusion_var_prefs_dir = os.getenv(f"FUSION{self.PROFILE_NUMBER}_PROFILE_DIR") - # if FUSION16_PROFILE_DIR variable exists, return the profile filepath + # if FUSION16_PROFILE_DIR variable exists if fusion_var_prefs_dir and Path(fusion_var_prefs_dir).is_dir(): fusion_prefs_dir = Path(fusion_var_prefs_dir, fusion_profile) self.log.info(f"Local Fusion prefs environment is set to {fusion_prefs_dir}") - fusion_prefs_filepath = fusion_prefs_dir / "Fusion.prefs" - return fusion_prefs_filepath - # otherwise get the profile from default prefs location - fusion_prefs_path = f"Blackmagic Design/Fusion/Profiles/{fusion_profile}/Fusion.prefs" + return fusion_prefs_dir + # otherwise get the profile folder from default location + fusion_prefs_dir = f"Blackmagic Design/Fusion/Profiles/{fusion_profile}" if platform.system() == "Windows": - prefs_source = Path(os.getenv("AppData"), fusion_prefs_path) + prefs_source = Path(os.getenv("AppData"), fusion_prefs_dir) elif platform.system() == "Darwin": - prefs_source = Path("~/Library/Application Support/", fusion_prefs_path).expanduser() + prefs_source = Path("~/Library/Application Support/", fusion_prefs_dir).expanduser() elif platform.system() == "Linux": - prefs_source = Path("~/.fusion", fusion_prefs_path).expanduser() + prefs_source = Path("~/.fusion", fusion_prefs_dir).expanduser() self.log.info(f"Got Fusion prefs file: {prefs_source}") return prefs_source @@ -67,10 +72,11 @@ def get_copy_fusion_prefs_settings(self): return copy_status, copy_path, force_sync def copy_existing_prefs(self, copy_from: Path, copy_to: Path, force_sync: bool) -> None: - """On the first Fusion launch copy the Fusion profile to the working directory. - If the Openpype profile folder exists, skip copying, unless Force sync is checked. - If the prefs were not copied on the first launch, clean Fusion profile - will be created in fusion_profile_dir. + """On the first Fusion launch copy the contents of Fusion profile directory + to the working predefined location. If the Openpype profile folder exists, + skip copying, unless re-sync is checked. + If the prefs were not copied on the first launch, + clean Fusion profile will be created in fusion_profile_dir. """ if copy_to.exists() and not force_sync: self.log.info("Local Fusion preferences folder exists, skipping profile copy") @@ -82,7 +88,10 @@ def copy_existing_prefs(self, copy_from: Path, copy_to: Path, force_sync: bool) if not copy_from.exists(): self.log.warning(f"Fusion preferences file not found in {copy_from}") return - shutil.copy(str(copy_from), str(dest_folder)) # compatible with Python >= 3.6 + for file in copy_from.iterdir(): + if file.suffix in (".prefs", ".def", ".blocklist", "fu"): + # convert Path to str to be compatible with Python 3.6 and above + shutil.copy(str(file), str(dest_folder)) self.log.info(f"successfully copied preferences:\n {copy_from} to {dest_folder}") def execute(self): @@ -93,8 +102,9 @@ def execute(self): fusion_python3_home = self.launch_context.env.get(py3_var, "") for path in fusion_python3_home.split(os.pathsep): - # Allow defining multiple paths, separated by os.pathsep, to allow "fallback" to other - # path. But make to set only a single path as final variable. + # Allow defining multiple paths, separated by os.pathsep, + # to allow "fallback" to other path. + # But make to set only a single path as final variable. py3_dir = os.path.normpath(path) if os.path.isdir(py3_dir): self.log.info(f"Looking for Python 3 in: {py3_dir}") @@ -119,8 +129,9 @@ def execute(self): # TODO: Detect Fusion version to only set for specific Fusion build self.launch_context.env[f"FUSION{self.PROFILE_NUMBER}_PYTHON36_HOME"] = py3_dir - # Add custom Fusion Master Prefs and the temporary profile directory variables - # to customize Fusion to define where it can read custom scripts and tools from + # Add custom Fusion Master Prefs and the temporary + # profile directory variables to customize Fusion + # to define where it can read custom scripts and tools from self.log.info(f"Setting OPENPYPE_FUSION: {FUSION_HOST_DIR}") self.launch_context.env["OPENPYPE_FUSION"] = FUSION_HOST_DIR From 2d6cc7788199c26e338ab6e960aef1fc25caca9b Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Tue, 21 Feb 2023 02:42:36 +0300 Subject: [PATCH 157/898] fle formatting --- .../hosts/fusion/hooks/pre_fusion_setup.py | 45 ++++++++++++------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index 949f86d9812..3f521bb60d4 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -17,16 +17,16 @@ class FusionPrelaunch(PreLaunchHook): as set in openpype/hosts/fusion/deploy/fusion_shared.prefs to enable the OpenPype menu and force Python 3 over Python 2. - PROFILE_NUMBER is used because from the Fusion v16 the profile folder + PROFILE_NUMBER is used because from the Fusion v16 the profile folder is project-specific, but then it was abandoned by devs, and despite it is already Fusion version 18, still FUSION16_PROFILE_DIR is used. The variable is added in case the version number will be updated or deleted so we could easily change the version or disable it. """ + app_groups = ["fusion"] PROFILE_NUMBER = 16 - def get_fusion_profile_name(self) -> str: """usually set to 'Default', unless FUSION16_PROFILE is set""" return os.getenv(f"FUSION{self.PROFILE_NUMBER}_PROFILE", "Default") @@ -41,14 +41,18 @@ def get_profile_source(self) -> Path: # if FUSION16_PROFILE_DIR variable exists if fusion_var_prefs_dir and Path(fusion_var_prefs_dir).is_dir(): fusion_prefs_dir = Path(fusion_var_prefs_dir, fusion_profile) - self.log.info(f"Local Fusion prefs environment is set to {fusion_prefs_dir}") + self.log.info( + f"Local Fusion prefs environment is set to {fusion_prefs_dir}" + ) return fusion_prefs_dir # otherwise get the profile folder from default location fusion_prefs_dir = f"Blackmagic Design/Fusion/Profiles/{fusion_profile}" if platform.system() == "Windows": prefs_source = Path(os.getenv("AppData"), fusion_prefs_dir) elif platform.system() == "Darwin": - prefs_source = Path("~/Library/Application Support/", fusion_prefs_dir).expanduser() + prefs_source = Path( + "~/Library/Application Support/", fusion_prefs_dir + ).expanduser() elif platform.system() == "Linux": prefs_source = Path("~/.fusion", fusion_prefs_dir).expanduser() self.log.info(f"Got Fusion prefs file: {prefs_source}") @@ -56,11 +60,8 @@ def get_profile_source(self) -> Path: def get_copy_fusion_prefs_settings(self): """Get copy prefserences options from the global application settings""" - copy_fusion_settings = ( - self.data - ["project_settings"] - ["fusion"] - .get("copy_fusion_settings", {}) + copy_fusion_settings = self.data["project_settings"]["fusion"].get( + "copy_fusion_settings", {} ) if not copy_fusion_settings: self.log.error("Copy prefs settings not found") @@ -71,7 +72,9 @@ def get_copy_fusion_prefs_settings(self): copy_path = Path(copy_path).expanduser() return copy_status, copy_path, force_sync - def copy_existing_prefs(self, copy_from: Path, copy_to: Path, force_sync: bool) -> None: + def copy_existing_prefs( + self, copy_from: Path, copy_to: Path, force_sync: bool + ) -> None: """On the first Fusion launch copy the contents of Fusion profile directory to the working predefined location. If the Openpype profile folder exists, skip copying, unless re-sync is checked. @@ -79,21 +82,25 @@ def copy_existing_prefs(self, copy_from: Path, copy_to: Path, force_sync: bool) clean Fusion profile will be created in fusion_profile_dir. """ if copy_to.exists() and not force_sync: - self.log.info("Local Fusion preferences folder exists, skipping profile copy") + self.log.info( + "Local Fusion preferences folder exists, skipping profile copy" + ) return self.log.info(f"Starting copying Fusion preferences") self.log.info(f"force_sync option is set to {force_sync}") dest_folder = copy_to / self.get_fusion_profile_name() - dest_folder.mkdir(exist_ok=True, parents=True) + dest_folder.mkdir(exist_ok=True, parents=True) if not copy_from.exists(): self.log.warning(f"Fusion preferences file not found in {copy_from}") return for file in copy_from.iterdir(): if file.suffix in (".prefs", ".def", ".blocklist", "fu"): # convert Path to str to be compatible with Python 3.6 and above - shutil.copy(str(file), str(dest_folder)) - self.log.info(f"successfully copied preferences:\n {copy_from} to {dest_folder}") - + shutil.copy(str(file), str(dest_folder)) + self.log.info( + f"successfully copied preferences:\n {copy_from} to {dest_folder}" + ) + def execute(self): # making sure python 3 is installed at provided path # Py 3.3-3.10 for Fusion 18+ or Py 3.6 for Fu 16-17 @@ -102,7 +109,7 @@ def execute(self): fusion_python3_home = self.launch_context.env.get(py3_var, "") for path in fusion_python3_home.split(os.pathsep): - # Allow defining multiple paths, separated by os.pathsep, + # Allow defining multiple paths, separated by os.pathsep, # to allow "fallback" to other path. # But make to set only a single path as final variable. py3_dir = os.path.normpath(path) @@ -135,7 +142,11 @@ def execute(self): self.log.info(f"Setting OPENPYPE_FUSION: {FUSION_HOST_DIR}") self.launch_context.env["OPENPYPE_FUSION"] = FUSION_HOST_DIR - copy_status, fusion_profile_dir, force_sync = self.get_copy_fusion_prefs_settings() + ( + copy_status, + fusion_profile_dir, + force_sync, + ) = self.get_copy_fusion_prefs_settings() if copy_status: prefs_source = self.get_profile_source() self.copy_existing_prefs(prefs_source, fusion_profile_dir, force_sync) From 709d663870bb703d644ab0fdd8afc08da6c260c8 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 22 Feb 2023 21:47:32 +0800 Subject: [PATCH 158/898] update docstring and style fix --- openpype/hosts/maya/api/lib.py | 58 ++++++++++++------- .../maya/plugins/publish/extract_look.py | 8 +-- .../publish/validate_look_color_space.py | 3 +- 3 files changed, 43 insertions(+), 26 deletions(-) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index 88d37019668..e369b465259 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -16,7 +16,15 @@ from maya import cmds, mel import maya.api.OpenMaya as om -from arnold import * # noqa +from arnold import ( + AiTextureGetBitDepth, + AiTextureGetFormat, + AiTextureInvalidate, + # types + AI_TYPE_BYTE, + AI_TYPE_INT, + AI_TYPE_UINT +) from openpype.client import ( get_project, @@ -3465,19 +3473,23 @@ def write_xgen_file(data, filepath): f.writelines(lines) -def imageInfo(filepath): - """Take reference from makeTx.py in Arnold - ImageInfo(filename): Get Image Information for colorspace - AiTextureGetFormat(filename): Get Texture Format - AiTextureGetBitDepth(filename): Get Texture Bit Depth +def image_info(file_path): + # type: (str) -> dict + """Based on tha texture path, get its bit depth and format information. + Take reference from makeTx.py in Arnold: + ImageInfo(filename): Get Image Information for colorspace + AiTextureGetFormat(filename): Get Texture Format + AiTextureGetBitDepth(filename): Get Texture bit depth + Args: + file_path (str): Path to the texture file. + Returns: + dict: Dictionary with the information about the texture file. """ - # Get Texture Information - img_info = {} - img_info['filename'] = filepath - if os.path.isfile(filepath): - img_info['bit_depth'] = AiTextureGetBitDepth(filepath) # noqa - img_info['format'] = AiTextureGetFormat(filepath) # noqa + img_info = {'filename': file_path} + if os.path.isfile(file_path): + img_info['bit_depth'] = AiTextureGetBitDepth(file_path) # noqa + img_info['format'] = AiTextureGetFormat(file_path) # noqa else: img_info['bit_depth'] = 8 img_info['format'] = "unknown" @@ -3485,21 +3497,25 @@ def imageInfo(filepath): def guess_colorspace(img_info): - ''' Take reference from makeTx.py - Guess the colorspace of the input image filename. - @return: a string suitable for the --colorconvert - option of maketx (linear, sRGB, Rec709) - ''' + # type: (dict) -> str + """Guess the colorspace of the input image filename. + Note: + Reference from makeTx.py + Args: + img_info (dict): Image info generated by :func:`image_info` + Returns: + str: color space name use in the `--colorconvert` + option of maketx. + """ try: if img_info['bit_depth'] <= 16: if img_info['format'] in (AI_TYPE_BYTE, AI_TYPE_INT, AI_TYPE_UINT): # noqa return 'sRGB' else: return 'linear' - # now discard the image file as AiTextureGetFormat has loaded it AiTextureInvalidate(img_info['filename']) # noqa except ValueError: - print('[maketx] Error: Could not guess' - 'colorspace for "%s"' % img_info['filename']) - return 'linear' + print(("[maketx] Error: Could not guess" + "colorspace for {}").format(img_info["filename"])) + return "linear" diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 46f7b0e03d9..d9c19c9139b 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -16,7 +16,7 @@ from openpype.lib import source_hash, run_subprocess from openpype.pipeline import legacy_io, publish from openpype.hosts.maya.api import lib -from openpype.hosts.maya.api.lib import imageInfo, guess_colorspace +from openpype.hosts.maya.api.lib import image_info, guess_colorspace # Modes for transfer COPY = 1 @@ -369,7 +369,7 @@ def process_resources(self, instance, staging_dir): linearize = False # if OCIO color management enabled - # it wont take the condition of the files_metadata + # it won't take the condition of the files_metadata ocio_maya = cmds.colorManagementPrefs(q=True, cmConfigFileEnabled=True, @@ -542,14 +542,14 @@ def _process_texture(self, filepath, resource, color_space = cmds.getAttr(color_space_attr) except ValueError: # node doesn't have color space attribute - img_info = imageInfo(filepath) + img_info = image_info(filepath) color_space = guess_colorspace(img_info) self.log.info("tx: converting {0} -> {1}".format(color_space, render_colorspace)) # noqa additional_args.extend(["--colorconvert", color_space, render_colorspace]) else: - img_info = imageInfo(filepath) + img_info = image_info(filepath) color_space = guess_colorspace(img_info) if color_space == "sRGB": self.log.info("tx: converting sRGB -> linear") diff --git a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py index b354d51fefe..b1bdeb7541b 100644 --- a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py +++ b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py @@ -2,6 +2,7 @@ import pyblish.api from openpype.pipeline.publish import ValidateContentsOrder +from openpype.pipeline import PublishValidationError class ValidateMayaColorSpace(pyblish.api.InstancePlugin): @@ -22,4 +23,4 @@ def process(self, instance): maketx = instance.data["maketx"] if ocio_maya and maketx: - raise RuntimeError("Maya is color managed and maketx option is on. OpenPype doesn't support this combination yet.") # noqa + raise PublishValidationError("Maya is color managed and maketx option is on. OpenPype doesn't support this combination yet.") # noqa From fad36c75a9e485b765a83a24a459540a9d9e7aed Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 23 Feb 2023 16:11:33 +0100 Subject: [PATCH 159/898] nuke: rendersettins lib with farm rendering class --- openpype/hosts/nuke/api/lib_rendersettings.py | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 openpype/hosts/nuke/api/lib_rendersettings.py diff --git a/openpype/hosts/nuke/api/lib_rendersettings.py b/openpype/hosts/nuke/api/lib_rendersettings.py new file mode 100644 index 00000000000..959b461c29e --- /dev/null +++ b/openpype/hosts/nuke/api/lib_rendersettings.py @@ -0,0 +1,86 @@ + +from openpype.lib import Logger +from openpype.settings import ( + get_current_project_settings, + get_system_settings +) + + +class RenderFarmSettings: + """ Class for getting farm settings from project settings + """ + log = Logger.get_logger("RenderFarmSettings") + + _active_farm_module: str = None + _farm_modules: list = [ + "deadline", "muster", "royalrender"] + _farm_plugins: dict = { + "deadline": "NukeSubmitDeadline" + } + _creator_farm_keys: list = [ + "chunk_size", "priority", "concurrent_tasks"] + + def __init__(self, project_settings=None): + """ Get project settings and active farm module + """ + self._project_settings = ( + project_settings or get_current_project_settings() + ) + # Get active farm module from system settings + self._get_active_farm_module_from_system_settings() + + def _get_active_farm_module_from_system_settings(self): + """ Get active farm module from system settings + """ + active_modules = [ + module_ + for module_ in self._farm_modules + if get_system_settings()["modules"][module_]["enabled"] + ] + if not active_modules: + raise ValueError(( + "No active farm module found in system settings." + )) + if len(active_modules) > 1: + raise ValueError(( + "Multiple active farm modules " + "found in system settings. {}".format(active_modules) + )) + + self._active_farm_module = active_modules.pop() + + @property + def active_farm_module(self): + return self._active_farm_module + + def get_rendering_attributes(self): + ''' Get rendering attributes from project settings + + Returns: + dict: rendering attributes + ''' + return_dict = {} + farm_plugin = self._farm_plugins.get(self.active_farm_module) + + if farm_plugin: + raise ValueError(( + "Farm plugin \"{}\" not found in farm plugins." + ).format(farm_plugin)) + + # Get farm module settings + module_settings = self._project_settings[self.active_farm_module] + + # Get farm plugin settings + farm_plugin_settings = ( + module_settings["publish"][farm_plugin]) + + # Get all keys from farm_plugin_settings + for key in self._creator_farm_keys: + if key not in farm_plugin_settings: + self.log.warning(( + "Key \"{}\" not found in farm plugin \"{}\" settings." + ).format(key, farm_plugin)) + continue + return_dict[key] = farm_plugin_settings[key] + + return return_dict From 073f0be7f706fd6ae222c3900cb1c02c523d1c04 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 23 Feb 2023 16:12:49 +0100 Subject: [PATCH 160/898] nuke: creators with new RenderFarmSettings class --- openpype/hosts/nuke/api/plugin.py | 2 +- .../nuke/plugins/create/create_write_prerender.py | 13 ++++++++----- .../nuke/plugins/create/create_write_render.py | 13 ++++++++----- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/openpype/hosts/nuke/api/plugin.py b/openpype/hosts/nuke/api/plugin.py index d3f8357f7d4..ef77e029ad5 100644 --- a/openpype/hosts/nuke/api/plugin.py +++ b/openpype/hosts/nuke/api/plugin.py @@ -1236,7 +1236,7 @@ def family_to_identifier(family): creator_attr["farm_chunk"] = ( node["deadlineChunkSize"].value()) if "deadlineConcurrentTasks" in node.knobs(): - creator_attr["farm_concurency"] = ( + creator_attr["farm_concurrency"] = ( node["deadlineConcurrentTasks"].value()) _remove_old_knobs(node) diff --git a/openpype/hosts/nuke/plugins/create/create_write_prerender.py b/openpype/hosts/nuke/plugins/create/create_write_prerender.py index a15f362dd11..a99bd0c4ab6 100644 --- a/openpype/hosts/nuke/plugins/create/create_write_prerender.py +++ b/openpype/hosts/nuke/plugins/create/create_write_prerender.py @@ -12,6 +12,7 @@ UILabelDef ) from openpype.hosts.nuke import api as napi +from openpype.hosts.nuke.api.lib_rendersettings import RenderFarmSettings class CreateWritePrerender(napi.NukeWriteCreator): @@ -50,6 +51,8 @@ def get_instance_attr_defs(self): self._get_reviewable_bool() ] if "farm_rendering" in self.instance_attributes: + render_farm_settings = RenderFarmSettings().get_rendering_attributes() + attr_defs.extend([ UISeparatorDef(), UILabelDef("Farm rendering attributes"), @@ -59,21 +62,21 @@ def get_instance_attr_defs(self): label="Priority", minimum=1, maximum=99, - default=50 + default=render_farm_settings.get("priority", 50) ), NumberDef( "farm_chunk", label="Chunk size", minimum=1, maximum=99, - default=10 + default=render_farm_settings.get("chunk_size", 10) ), NumberDef( - "farm_concurency", - label="Concurent tasks", + "farm_concurrency", + label="Concurrent tasks", minimum=1, maximum=10, - default=1 + default=render_farm_settings.get("concurrent_tasks", 1) ) ]) return attr_defs diff --git a/openpype/hosts/nuke/plugins/create/create_write_render.py b/openpype/hosts/nuke/plugins/create/create_write_render.py index 481d1d22016..bbaba212c2d 100644 --- a/openpype/hosts/nuke/plugins/create/create_write_render.py +++ b/openpype/hosts/nuke/plugins/create/create_write_render.py @@ -12,6 +12,7 @@ UILabelDef ) from openpype.hosts.nuke import api as napi +from openpype.hosts.nuke.api.lib_rendersettings import RenderFarmSettings class CreateWriteRender(napi.NukeWriteCreator): @@ -47,6 +48,8 @@ def get_instance_attr_defs(self): self._get_reviewable_bool() ] if "farm_rendering" in self.instance_attributes: + render_farm_settings = RenderFarmSettings().get_rendering_attributes() + attr_defs.extend([ UISeparatorDef(), UILabelDef("Farm rendering attributes"), @@ -56,21 +59,21 @@ def get_instance_attr_defs(self): label="Priority", minimum=1, maximum=99, - default=50 + default=render_farm_settings.get("priority", 50) ), NumberDef( "farm_chunk", label="Chunk size", minimum=1, maximum=99, - default=10 + default=render_farm_settings.get("chunk_size", 10) ), NumberDef( - "farm_concurency", - label="Concurent tasks", + "farm_concurrency", + label="Concurrent tasks", minimum=1, maximum=10, - default=1 + default=render_farm_settings.get("concurrent_tasks", 1) ) ]) return attr_defs From 5aaf8eb18a021b76249c561d499e3e664c983886 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 23 Feb 2023 16:13:10 +0100 Subject: [PATCH 161/898] nuke: publishing with new settings --- .../hosts/nuke/plugins/publish/collect_writes.py | 16 ++++++++-------- .../plugins/publish/submit_nuke_deadline.py | 10 +++++----- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/collect_writes.py b/openpype/hosts/nuke/plugins/publish/collect_writes.py index 3054e5a30c5..0aa044f06da 100644 --- a/openpype/hosts/nuke/plugins/publish/collect_writes.py +++ b/openpype/hosts/nuke/plugins/publish/collect_writes.py @@ -132,14 +132,14 @@ def process(self, instance): self.log.info("Publishing rendered frames ...") elif render_target == "farm": - farm_priority = creator_attributes.get("farm_priority") - farm_chunk = creator_attributes.get("farm_chunk") - farm_concurency = creator_attributes.get("farm_concurency") - instance.data.update({ - "deadlineChunkSize": farm_chunk or 1, - "deadlinePriority": farm_priority or 50, - "deadlineConcurrentTasks": farm_concurency or 0 - }) + farm_keys = ["farm_chunk", "farm_priority", "farm_concurrency"] + for key in farm_keys: + # Skip if key is not in creator attributes + if key not in creator_attributes: + continue + # Add farm attributes to instance + instance.data[key] = creator_attributes[key] + # Farm rendering instance.data["transfer"] = False instance.data["farm"] = True diff --git a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py index faa66effbdd..0f8c69629ec 100644 --- a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py @@ -162,16 +162,16 @@ def payload_submit( pass # define chunk and priority - chunk_size = instance.data["deadlineChunkSize"] - if chunk_size == 0 and self.chunk_size: + chunk_size = instance.data.get("farm_chunk") + if not chunk_size: chunk_size = self.chunk_size # define chunk and priority - concurrent_tasks = instance.data["deadlineConcurrentTasks"] - if concurrent_tasks == 0 and self.concurrent_tasks: + concurrent_tasks = instance.data.get("farm_concurrency") + if not concurrent_tasks: concurrent_tasks = self.concurrent_tasks - priority = instance.data["deadlinePriority"] + priority = instance.data.get("farm_priority") if not priority: priority = self.priority From 656318f122fe4cdc167e780b7737c8780890582b Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 23 Feb 2023 16:59:40 +0100 Subject: [PATCH 162/898] adding log to render farm settings class init --- openpype/hosts/nuke/api/lib_rendersettings.py | 10 ++++++++-- .../nuke/plugins/create/create_write_prerender.py | 4 +++- .../hosts/nuke/plugins/create/create_write_render.py | 3 ++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/nuke/api/lib_rendersettings.py b/openpype/hosts/nuke/api/lib_rendersettings.py index 959b461c29e..4d5440fe483 100644 --- a/openpype/hosts/nuke/api/lib_rendersettings.py +++ b/openpype/hosts/nuke/api/lib_rendersettings.py @@ -20,9 +20,12 @@ class RenderFarmSettings: _creator_farm_keys: list = [ "chunk_size", "priority", "concurrent_tasks"] - def __init__(self, project_settings=None): + def __init__(self, project_settings=None, log=None): """ Get project settings and active farm module """ + if log: + self.log = log + self._project_settings = ( project_settings or get_current_project_settings() ) @@ -61,8 +64,9 @@ def get_rendering_attributes(self): ''' return_dict = {} farm_plugin = self._farm_plugins.get(self.active_farm_module) + self.log.debug("Farm plugin: \"{}\"".format(farm_plugin)) - if farm_plugin: + if not farm_plugin: raise ValueError(( "Farm plugin \"{}\" not found in farm plugins." ).format(farm_plugin)) @@ -73,6 +77,8 @@ def get_rendering_attributes(self): # Get farm plugin settings farm_plugin_settings = ( module_settings["publish"][farm_plugin]) + self.log.debug( + "Farm plugin settings: \"{}\"".format(farm_plugin_settings)) # Get all keys from farm_plugin_settings for key in self._creator_farm_keys: diff --git a/openpype/hosts/nuke/plugins/create/create_write_prerender.py b/openpype/hosts/nuke/plugins/create/create_write_prerender.py index a99bd0c4ab6..411a79dbf40 100644 --- a/openpype/hosts/nuke/plugins/create/create_write_prerender.py +++ b/openpype/hosts/nuke/plugins/create/create_write_prerender.py @@ -51,7 +51,9 @@ def get_instance_attr_defs(self): self._get_reviewable_bool() ] if "farm_rendering" in self.instance_attributes: - render_farm_settings = RenderFarmSettings().get_rendering_attributes() + render_farm_settings = RenderFarmSettings( + log=self.log).get_rendering_attributes() + attr_defs.extend([ UISeparatorDef(), diff --git a/openpype/hosts/nuke/plugins/create/create_write_render.py b/openpype/hosts/nuke/plugins/create/create_write_render.py index bbaba212c2d..a51661425fc 100644 --- a/openpype/hosts/nuke/plugins/create/create_write_render.py +++ b/openpype/hosts/nuke/plugins/create/create_write_render.py @@ -48,7 +48,8 @@ def get_instance_attr_defs(self): self._get_reviewable_bool() ] if "farm_rendering" in self.instance_attributes: - render_farm_settings = RenderFarmSettings().get_rendering_attributes() + render_farm_settings = RenderFarmSettings( + log=self.log).get_rendering_attributes() attr_defs.extend([ UISeparatorDef(), From b09bc8d4a3e85eb3187b08b1672ca8bd0528dd99 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 23 Feb 2023 17:00:19 +0100 Subject: [PATCH 163/898] removing unused items from settings --- openpype/settings/defaults/project_settings/deadline.json | 1 - .../schemas/projects_schema/schema_project_deadline.json | 5 ----- 2 files changed, 6 deletions(-) diff --git a/openpype/settings/defaults/project_settings/deadline.json b/openpype/settings/defaults/project_settings/deadline.json index 7183603c4bb..6b6f2d465b5 100644 --- a/openpype/settings/defaults/project_settings/deadline.json +++ b/openpype/settings/defaults/project_settings/deadline.json @@ -52,7 +52,6 @@ "enabled": true, "optional": false, "active": true, - "use_published": true, "priority": 50, "chunk_size": 10, "concurrent_tasks": 1, diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json b/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json index a320dfca4f1..bb5a65e1b7e 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json @@ -285,11 +285,6 @@ "key": "active", "label": "Active" }, - { - "type": "boolean", - "key": "use_published", - "label": "Use Published scene" - }, { "type": "splitter" }, From f2274ec2e963e6eb5e10233ff593804e02ab1f5c Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 23 Feb 2023 17:00:51 +0100 Subject: [PATCH 164/898] removing none existent host also fix typo --- .../plugins/publish/submit_nuke_deadline.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py index 0f8c69629ec..b4b59c4c77c 100644 --- a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py @@ -23,7 +23,7 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin): label = "Submit to Deadline" order = pyblish.api.IntegratorOrder + 0.1 - hosts = ["nuke", "nukestudio"] + hosts = ["nuke"] families = ["render.farm", "prerender.farm"] optional = True targets = ["local"] @@ -141,7 +141,7 @@ def payload_submit( exe_node_name, start_frame, end_frame, - responce_data=None + response_data=None ): render_dir = os.path.normpath(os.path.dirname(render_path)) batch_name = os.path.basename(script_path) @@ -152,8 +152,8 @@ def payload_submit( output_filename_0 = self.preview_fname(render_path) - if not responce_data: - responce_data = {} + if not response_data: + response_data = {} try: # Ensure render folder exists @@ -244,11 +244,11 @@ def payload_submit( "AuxFiles": [] } - if responce_data.get("_id"): + if response_data.get("_id"): payload["JobInfo"].update({ "JobType": "Normal", - "BatchName": responce_data["Props"]["Batch"], - "JobDependency0": responce_data["_id"], + "BatchName": response_data["Props"]["Batch"], + "JobDependency0": response_data["_id"], "ChunkSize": 99999999 }) From de15f1bc3a135738f218fe27db928aef5cdb1af9 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 23 Feb 2023 18:50:21 +0100 Subject: [PATCH 165/898] Updated render_local.py to not only process the first instance Moved the __hasRun to render_once() so the check only happens with the rendering. Currently only the first render node gets the representations added --- .../fusion/plugins/publish/render_local.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/render_local.py b/openpype/hosts/fusion/plugins/publish/render_local.py index 53d8eb64e15..49aaf63a618 100644 --- a/openpype/hosts/fusion/plugins/publish/render_local.py +++ b/openpype/hosts/fusion/plugins/publish/render_local.py @@ -18,15 +18,9 @@ class Fusionlocal(pyblish.api.InstancePlugin): def process(self, instance): - # This plug-in runs only once and thus assumes all instances - # currently will render the same frame range context = instance.context - key = f"__hasRun{self.__class__.__name__}" - if context.data.get(key, False): - return - - context.data[key] = True - + + # Start render self.render_once(context) frame_start = context.data["frameStartHandle"] @@ -60,6 +54,14 @@ def process(self, instance): def render_once(self, context): """Render context comp only once, even with more render instances""" + + # This plug-in assumes all render nodes get rendered at the same time + # to speed up the rendering. The check below makes sure that we only + # execute the rendering once and not for each instance. + key = f"__hasRun{self.__class__.__name__}" + if context.data.get(key, False): + return + context.data[key] = True current_comp = context.data["currentComp"] frame_start = context.data["frameStartHandle"] From d8041562d0e08afd7dfc34158591142158d51e0e Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 23 Feb 2023 18:52:50 +0100 Subject: [PATCH 166/898] Fixed Hounds notes --- openpype/hosts/fusion/plugins/publish/render_local.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/render_local.py b/openpype/hosts/fusion/plugins/publish/render_local.py index 49aaf63a618..c22074d6c63 100644 --- a/openpype/hosts/fusion/plugins/publish/render_local.py +++ b/openpype/hosts/fusion/plugins/publish/render_local.py @@ -19,7 +19,7 @@ class Fusionlocal(pyblish.api.InstancePlugin): def process(self, instance): context = instance.context - + # Start render self.render_once(context) @@ -54,7 +54,7 @@ def process(self, instance): def render_once(self, context): """Render context comp only once, even with more render instances""" - + # This plug-in assumes all render nodes get rendered at the same time # to speed up the rendering. The check below makes sure that we only # execute the rendering once and not for each instance. From 31d7b18e9ff6d5561ddc9d7ea2d003ae3a5c86bd Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 23 Feb 2023 19:18:41 +0100 Subject: [PATCH 167/898] Changed to f-string --- openpype/hosts/fusion/plugins/create/create_saver.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/fusion/plugins/create/create_saver.py b/openpype/hosts/fusion/plugins/create/create_saver.py index 99aa7583f16..59fc1982434 100644 --- a/openpype/hosts/fusion/plugins/create/create_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_saver.py @@ -39,8 +39,9 @@ def create(self, subset_name, instance_data, pre_create_data): # Check file format settings are available if saver[file_format] is None: - raise RuntimeError("File format is not set to {}, " - "this is a bug".format(file_format)) + raise RuntimeError( + f"File format is not set to {file_format}, this is a bug" + ) # Set file format attributes saver[file_format]["Depth"] = 1 # int8 | int16 | float32 | other @@ -110,7 +111,7 @@ def remove_instances(self, instances): def _imprint(self, tool, data): # Save all data in a "openpype.{key}" = value data for key, value in data.items(): - tool.SetData("openpype.{}".format(key), value) + tool.SetData(f"openpype.{key}", value) def _update_tool_with_data(self, tool, data): """Update tool node name and output path based on subset data""" @@ -123,7 +124,7 @@ def _update_tool_with_data(self, tool, data): # Subset change detected # Update output filepath workdir = os.path.normpath(legacy_io.Session["AVALON_WORKDIR"]) - filename = "{}..exr".format(subset) + filename = f"{subset}..exr" filepath = os.path.join(workdir, "render", subset, filename) tool["Clip"] = filepath From 4d3442db70c025a67e5503fb8a728e2c3acd7b96 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 23 Feb 2023 19:19:24 +0100 Subject: [PATCH 168/898] Add subset to instance_data --- openpype/hosts/fusion/plugins/create/create_saver.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/fusion/plugins/create/create_saver.py b/openpype/hosts/fusion/plugins/create/create_saver.py index 59fc1982434..5725b5d0d17 100644 --- a/openpype/hosts/fusion/plugins/create/create_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_saver.py @@ -33,6 +33,7 @@ def create(self, subset_name, instance_data, pre_create_data): args = (-32768, -32768) # Magical position numbers saver = comp.AddTool("Saver", *args) + instance_data["subset"] = subset_name self._update_tool_with_data(saver, data=instance_data) saver["OutputFormat"] = file_format From 8afd6f4f359cf1bdea8f08386a983a1782e35871 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 23 Feb 2023 19:19:52 +0100 Subject: [PATCH 169/898] Change render depth to Auto instead of forcing int16 as it was --- openpype/hosts/fusion/plugins/create/create_saver.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/plugins/create/create_saver.py b/openpype/hosts/fusion/plugins/create/create_saver.py index 5725b5d0d17..439064770e0 100644 --- a/openpype/hosts/fusion/plugins/create/create_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_saver.py @@ -45,8 +45,9 @@ def create(self, subset_name, instance_data, pre_create_data): ) # Set file format attributes - saver[file_format]["Depth"] = 1 # int8 | int16 | float32 | other - saver[file_format]["SaveAlpha"] = 0 + saver[file_format]["Depth"] = 0 # Auto | float16 | float32 + # TODO Is this needed? + saver[file_format]["SaveAlpha"] = 1 self._imprint(saver, instance_data) From f840347f4e27a3f7474fe7e29facf9fa02f4e7ef Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 23 Feb 2023 19:20:20 +0100 Subject: [PATCH 170/898] Import get_current_comp from API directly --- openpype/hosts/fusion/plugins/create/create_workfile.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/fusion/plugins/create/create_workfile.py b/openpype/hosts/fusion/plugins/create/create_workfile.py index 783d3a147a7..05dbcddd522 100644 --- a/openpype/hosts/fusion/plugins/create/create_workfile.py +++ b/openpype/hosts/fusion/plugins/create/create_workfile.py @@ -2,7 +2,9 @@ import qtawesome -import openpype.hosts.fusion.api as api +from openpype.hosts.fusion.api import ( + get_current_comp +) from openpype.client import get_asset_by_name from openpype.pipeline import ( AutoCreator, @@ -35,7 +37,7 @@ class FusionWorkfileCreator(AutoCreator): def collect_instances(self): - comp = api.get_current_comp() + comp = get_current_comp() data = comp.GetData(self.data_key) if not data: return @@ -69,7 +71,7 @@ def update_instances(self, update_list): def create(self, options=None): - comp = api.get_current_comp() + comp = get_current_comp() if not comp: self.log.error("Unable to find current comp") return From f5a40056ab3e8cf18f5562d8961174fe422ce3e1 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 23 Feb 2023 19:21:00 +0100 Subject: [PATCH 171/898] Pass "data" to get_dynamic_data() was missing --- openpype/hosts/fusion/plugins/create/create_workfile.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/plugins/create/create_workfile.py b/openpype/hosts/fusion/plugins/create/create_workfile.py index 05dbcddd522..917780c56e9 100644 --- a/openpype/hosts/fusion/plugins/create/create_workfile.py +++ b/openpype/hosts/fusion/plugins/create/create_workfile.py @@ -99,8 +99,12 @@ def create(self, options=None): "variant": self.default_variant } data.update(self.get_dynamic_data( - self.default_variant, task_name, asset_doc, - project_name, host_name + self.default_variant, + task_name, + asset_doc, + project_name, + host_name, + data )) instance = CreatedInstance( From f0cd353301c6192ec0203a83de2ec7b31e4979c6 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 23 Feb 2023 19:29:03 +0100 Subject: [PATCH 172/898] Fixed Hound's notes --- openpype/hosts/fusion/api/pipeline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/api/pipeline.py b/openpype/hosts/fusion/api/pipeline.py index eb097e5c5bb..2d0a1da8fae 100644 --- a/openpype/hosts/fusion/api/pipeline.py +++ b/openpype/hosts/fusion/api/pipeline.py @@ -463,4 +463,4 @@ def _on_event(self, event): # Comp Opened elif what in {"Comp_Opened"}: - emit_event("open", data=event) \ No newline at end of file + emit_event("open", data=event) From 79b73efa28fd6edfd49f7ee8aa3750a9bc910c86 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 24 Feb 2023 12:41:26 +0800 Subject: [PATCH 173/898] color convert only enabled when there is arnold plugin --- openpype/hosts/maya/api/lib.py | 20 +++++---- .../maya/plugins/publish/extract_look.py | 41 ++++++++++++------- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index 614b04903fd..a4d823b7a19 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -16,15 +16,6 @@ from maya import cmds, mel import maya.api.OpenMaya as om -from arnold import ( - AiTextureGetBitDepth, - AiTextureGetFormat, - AiTextureInvalidate, - # types - AI_TYPE_BYTE, - AI_TYPE_INT, - AI_TYPE_UINT -) from openpype.client import ( get_project, @@ -3532,6 +3523,10 @@ def image_info(file_path): Returns: dict: Dictionary with the information about the texture file. """ + from arnold import ( + AiTextureGetBitDepth, + AiTextureGetFormat +) # Get Texture Information img_info = {'filename': file_path} if os.path.isfile(file_path): @@ -3554,6 +3549,13 @@ def guess_colorspace(img_info): str: color space name use in the `--colorconvert` option of maketx. """ + from arnold import ( + AiTextureInvalidate, + # types + AI_TYPE_BYTE, + AI_TYPE_INT, + AI_TYPE_UINT +) try: if img_info['bit_depth'] <= 16: if img_info['format'] in (AI_TYPE_BYTE, AI_TYPE_INT, AI_TYPE_UINT): # noqa diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index d9c19c9139b..ca110ceaddb 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -537,33 +537,44 @@ def _process_texture(self, filepath, resource, if linearize: if cmds.colorManagementPrefs(query=True, cmEnabled=True): render_colorspace = cmds.colorManagementPrefs(query=True, renderingSpaceName=True) # noqa + config_path = cmds.colorManagementPrefs(query=True, + configFilePath=True) + if not os.path.exists(config_path): + raise RuntimeError("No OCIO config path found!") + color_space_attr = resource["node"] + ".colorSpace" try: color_space = cmds.getAttr(color_space_attr) except ValueError: # node doesn't have color space attribute - img_info = image_info(filepath) - color_space = guess_colorspace(img_info) + if cmds.loadPlugin("mtoa", quiet=True): + img_info = image_info(filepath) + color_space = guess_colorspace(img_info) + else: + color_space = "Raw" self.log.info("tx: converting {0} -> {1}".format(color_space, render_colorspace)) # noqa + additional_args.extend(["--colorconvert", color_space, render_colorspace]) else: - img_info = image_info(filepath) - color_space = guess_colorspace(img_info) - if color_space == "sRGB": - self.log.info("tx: converting sRGB -> linear") - additional_args.extend(["--colorconvert", - "sRGB", - "Raw"]) + + if cmds.loadPlugin("mtoa", quiet=True): + img_info = image_info(filepath) + color_space = guess_colorspace(img_info) + if color_space == "sRGB": + self.log.info("tx: converting sRGB -> linear") + additional_args.extend(["--colorconvert", + "sRGB", + "Raw"]) + else: + self.log.info("tx: texture's colorspace " + "is already linear") else: - self.log.info("tx: texture's colorspace " - "is already linear") + self.log.warning("cannot guess the colorspace" + "color conversion won't be available!") + - config_path = cmds.colorManagementPrefs(query=True, - configFilePath=True) - if not os.path.exists(config_path): - raise RuntimeError("No OCIO config path found!") additional_args.extend(["--colorconfig", config_path]) # Ensure folder exists if not os.path.exists(os.path.dirname(converted)): From 5aba18e089e4947ce7b19d3875ee284d164e2b35 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 22 Feb 2023 10:53:44 +0100 Subject: [PATCH 174/898] extract sequence can ignore layer's transparency --- .../plugins/publish/extract_sequence.py | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/tvpaint/plugins/publish/extract_sequence.py b/openpype/hosts/tvpaint/plugins/publish/extract_sequence.py index f2856c72a97..1a21715aa22 100644 --- a/openpype/hosts/tvpaint/plugins/publish/extract_sequence.py +++ b/openpype/hosts/tvpaint/plugins/publish/extract_sequence.py @@ -59,6 +59,10 @@ def process(self, instance): ) ) + ignore_layers_transparency = instance.data.get( + "ignoreLayersTransparency", False + ) + family_lowered = instance.data["family"].lower() mark_in = instance.context.data["sceneMarkIn"] mark_out = instance.context.data["sceneMarkOut"] @@ -114,7 +118,11 @@ def process(self, instance): else: # Render output result = self.render( - output_dir, mark_in, mark_out, filtered_layers + output_dir, + mark_in, + mark_out, + filtered_layers, + ignore_layers_transparency ) output_filepaths_by_frame_idx, thumbnail_fullpath = result @@ -274,7 +282,9 @@ def render_review( return output_filepaths_by_frame_idx, thumbnail_filepath - def render(self, output_dir, mark_in, mark_out, layers): + def render( + self, output_dir, mark_in, mark_out, layers, ignore_layer_opacity + ): """ Export images from TVPaint. Args: @@ -282,6 +292,7 @@ def render(self, output_dir, mark_in, mark_out, layers): mark_in (int): Starting frame index from which export will begin. mark_out (int): On which frame index export will end. layers (list): List of layers to be exported. + ignore_layer_opacity (bool): Layer's opacity will be ignored. Returns: tuple: With 2 items first is list of filenames second is path to @@ -323,7 +334,7 @@ def render(self, output_dir, mark_in, mark_out, layers): for layer_id, render_data in extraction_data_by_layer_id.items(): layer = layers_by_id[layer_id] filepaths_by_layer_id[layer_id] = self._render_layer( - render_data, layer, output_dir + render_data, layer, output_dir, ignore_layer_opacity ) # Prepare final filepaths where compositing should store result @@ -380,7 +391,9 @@ def _get_review_bg_color(self): red, green, blue = self.review_bg return (red, green, blue) - def _render_layer(self, render_data, layer, output_dir): + def _render_layer( + self, render_data, layer, output_dir, ignore_layer_opacity + ): frame_references = render_data["frame_references"] filenames_by_frame_index = render_data["filenames_by_frame_index"] @@ -389,6 +402,12 @@ def _render_layer(self, render_data, layer, output_dir): "tv_layerset {}".format(layer_id), "tv_SaveMode \"PNG\"" ] + # Set density to 100 and store previous opacity + if ignore_layer_opacity: + george_script_lines.extend([ + "tv_layerdensity 100", + "orig_opacity = result", + ]) filepaths_by_frame = {} frames_to_render = [] @@ -409,6 +428,10 @@ def _render_layer(self, render_data, layer, output_dir): # Store image to output george_script_lines.append("tv_saveimage \"{}\"".format(dst_path)) + # Set density back to origin opacity + if ignore_layer_opacity: + george_script_lines.append("tv_layerdensity orig_opacity") + self.log.debug("Rendering Exposure frames {} of layer {} ({})".format( ",".join(frames_to_render), layer_id, layer["name"] )) From 87b818e37eaf419654468029ff8558215f9dd847 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 22 Feb 2023 10:58:49 +0100 Subject: [PATCH 175/898] collect render instances can set 'ignoreLayersTransparency' --- .../tvpaint/plugins/publish/collect_render_instances.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openpype/hosts/tvpaint/plugins/publish/collect_render_instances.py b/openpype/hosts/tvpaint/plugins/publish/collect_render_instances.py index ba89deac5d6..e89fbf78829 100644 --- a/openpype/hosts/tvpaint/plugins/publish/collect_render_instances.py +++ b/openpype/hosts/tvpaint/plugins/publish/collect_render_instances.py @@ -9,6 +9,8 @@ class CollectRenderInstances(pyblish.api.InstancePlugin): hosts = ["tvpaint"] families = ["render", "review"] + ignore_render_pass_transparency = False + def process(self, instance): context = instance.context creator_identifier = instance.data["creator_identifier"] @@ -63,6 +65,9 @@ def _collect_data_for_render_pass(self, instance): for layer in layers_data if layer["name"] in layer_names ] + instance.data["ignoreLayersTransparency"] = ( + self.ignore_render_pass_transparency + ) render_layer_data = None render_layer_id = creator_attributes["render_layer_instance_id"] From 4b127dedd68900b93062e4a0394f6afb8f1f1d20 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 22 Feb 2023 10:59:03 +0100 Subject: [PATCH 176/898] added settings for Collect Render Instances --- .../defaults/project_settings/tvpaint.json | 3 +++ .../projects_schema/schema_project_tvpaint.json | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/openpype/settings/defaults/project_settings/tvpaint.json b/openpype/settings/defaults/project_settings/tvpaint.json index 0b6d3d7e817..87d3601ae45 100644 --- a/openpype/settings/defaults/project_settings/tvpaint.json +++ b/openpype/settings/defaults/project_settings/tvpaint.json @@ -49,6 +49,9 @@ } }, "publish": { + "CollectRenderInstances": { + "ignore_render_pass_transparency": true + }, "ExtractSequence": { "review_bg": [ 255, diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json b/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json index 57016a83115..708b688ba5f 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json @@ -241,6 +241,20 @@ "key": "publish", "label": "Publish plugins", "children": [ + { + "type": "dict", + "collapsible": true, + "key": "CollectRenderInstances", + "label": "Collect Render Instances", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "ignore_render_pass_transparency", + "label": "Ignore Render Pass opacity" + } + ] + }, { "type": "dict", "collapsible": true, From bdd869b0a8a953fd8e707dd1caf75c2290961991 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 22 Feb 2023 11:19:49 +0100 Subject: [PATCH 177/898] disable ignore transparency by default --- openpype/settings/defaults/project_settings/tvpaint.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/settings/defaults/project_settings/tvpaint.json b/openpype/settings/defaults/project_settings/tvpaint.json index 87d3601ae45..e06a67a2546 100644 --- a/openpype/settings/defaults/project_settings/tvpaint.json +++ b/openpype/settings/defaults/project_settings/tvpaint.json @@ -50,7 +50,7 @@ }, "publish": { "CollectRenderInstances": { - "ignore_render_pass_transparency": true + "ignore_render_pass_transparency": false }, "ExtractSequence": { "review_bg": [ From 131e27008c0e1883f7241f731d0ddfd42df3f77b Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 23 Feb 2023 10:39:10 +0100 Subject: [PATCH 178/898] fix access to not existing settings key --- openpype/hosts/tvpaint/plugins/create/create_render.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/tvpaint/plugins/create/create_render.py b/openpype/hosts/tvpaint/plugins/create/create_render.py index 40386efe91d..7e85977b11d 100644 --- a/openpype/hosts/tvpaint/plugins/create/create_render.py +++ b/openpype/hosts/tvpaint/plugins/create/create_render.py @@ -660,7 +660,6 @@ def apply_settings(self, project_settings, system_settings): ["create"] ["auto_detect_render"] ) - self.enabled = plugin_settings["enabled"] self.allow_group_rename = plugin_settings["allow_group_rename"] self.group_name_template = plugin_settings["group_name_template"] self.group_idx_offset = plugin_settings["group_idx_offset"] From 6568db35af8047bdc2ca46016aca62f9f220e4b7 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 23 Feb 2023 11:30:15 +0100 Subject: [PATCH 179/898] Fix - check existence only if not None review_path might be None --- openpype/modules/slack/plugins/publish/integrate_slack_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/modules/slack/plugins/publish/integrate_slack_api.py b/openpype/modules/slack/plugins/publish/integrate_slack_api.py index 4e2557ccc7d..86c97586d20 100644 --- a/openpype/modules/slack/plugins/publish/integrate_slack_api.py +++ b/openpype/modules/slack/plugins/publish/integrate_slack_api.py @@ -187,7 +187,7 @@ def _get_review_path(self, instance): repre_review_path = get_publish_repre_path( instance, repre, False ) - if os.path.exists(repre_review_path): + if repre_review_path and os.path.exists(repre_review_path): review_path = repre_review_path if "burnin" in tags: # burnin has precedence if exists break From 6ab63823f02fb32edb367567943a9b38ba7cd9c2 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 21 Feb 2023 17:40:29 +0000 Subject: [PATCH 180/898] Implement get_multipart --- openpype/hosts/maya/api/lib_renderproducts.py | 82 ++++++++++++------- 1 file changed, 52 insertions(+), 30 deletions(-) diff --git a/openpype/hosts/maya/api/lib_renderproducts.py b/openpype/hosts/maya/api/lib_renderproducts.py index 60090e9f6d3..e635414029b 100644 --- a/openpype/hosts/maya/api/lib_renderproducts.py +++ b/openpype/hosts/maya/api/lib_renderproducts.py @@ -196,12 +196,18 @@ def __init__(self, layer, render_instance): """Constructor.""" self.layer = layer self.render_instance = render_instance - self.multipart = False + self.multipart = self.get_multipart() # Initialize self.layer_data = self._get_layer_data() self.layer_data.products = self.get_render_products() + def get_multipart(self): + raise NotImplementedError( + "The render product implementation does not have a " + "\"get_multipart\" method." + ) + def has_camera_token(self): # type: () -> bool """Check if camera token is in image prefix. @@ -344,7 +350,6 @@ def match_last(tokens, text): separator = file_prefix[matches[0].end(1):matches[1].start(1)] return separator - def _get_layer_data(self): # type: () -> LayerMetadata # ______________________________________________ @@ -531,16 +536,20 @@ def get_renderer_prefix(self): return prefix - def _get_aov_render_products(self, aov, cameras=None): - """Return all render products for the AOV""" - - products = [] - aov_name = self._get_attr(aov, "name") + def get_multipart(self): multipart = False multilayer = bool(self._get_attr("defaultArnoldDriver.multipart")) merge_AOVs = bool(self._get_attr("defaultArnoldDriver.mergeAOVs")) if multilayer or merge_AOVs: multipart = True + + return multipart + + def _get_aov_render_products(self, aov, cameras=None): + """Return all render products for the AOV""" + + products = [] + aov_name = self._get_attr(aov, "name") ai_drivers = cmds.listConnections("{}.outputs".format(aov), source=True, destination=False, @@ -594,7 +603,7 @@ def _get_aov_render_products(self, aov, cameras=None): ext=ext, aov=aov_name, driver=ai_driver, - multipart=multipart, + multipart=self.multipart, camera=camera) products.append(product) @@ -731,6 +740,14 @@ class RenderProductsVray(ARenderProducts): renderer = "vray" + def get_multipart(self): + multipart = False + image_format = self._get_attr("vraySettings.imageFormatStr") + if image_format == "exr (multichannel)": + multipart = True + + return multipart + def get_renderer_prefix(self): # type: () -> str """Get image prefix for V-Ray. @@ -797,11 +814,6 @@ def get_render_products(self): if default_ext in {"exr (multichannel)", "exr (deep)"}: default_ext = "exr" - # Define multipart. - multipart = False - if image_format_str == "exr (multichannel)": - multipart = True - products = [] # add beauty as default when not disabled @@ -813,7 +825,7 @@ def get_render_products(self): productName="", ext=default_ext, camera=camera, - multipart=multipart + multipart=self.multipart ) ) @@ -826,10 +838,10 @@ def get_render_products(self): productName="Alpha", ext=default_ext, camera=camera, - multipart=multipart + multipart=self.multipart ) ) - if multipart: + if self.multipart: # AOVs are merged in m-channel file, only main layer is rendered return products @@ -989,6 +1001,19 @@ class RenderProductsRedshift(ARenderProducts): renderer = "redshift" unmerged_aovs = {"Cryptomatte"} + def get_multipart(self): + # For Redshift we don't directly return upon forcing multilayer + # due to some AOVs still being written into separate files, + # like Cryptomatte. + # AOVs are merged in multi-channel file + multipart = False + force_layer = bool(self._get_attr("redshiftOptions.exrForceMultilayer")) # noqa + exMultipart = bool(self._get_attr("redshiftOptions.exrMultipart")) + if exMultipart or force_layer: + multipart = True + + return multipart + def get_renderer_prefix(self): """Get image prefix for Redshift. @@ -1028,16 +1053,6 @@ def get_render_products(self): for c in self.get_renderable_cameras() ] - # For Redshift we don't directly return upon forcing multilayer - # due to some AOVs still being written into separate files, - # like Cryptomatte. - # AOVs are merged in multi-channel file - multipart = False - force_layer = bool(self._get_attr("redshiftOptions.exrForceMultilayer")) # noqa - exMultipart = bool(self._get_attr("redshiftOptions.exrMultipart")) - if exMultipart or force_layer: - multipart = True - # Get Redshift Extension from image format image_format = self._get_attr("redshiftOptions.imageFormat") # integer ext = mel.eval("redshiftGetImageExtension(%i)" % image_format) @@ -1059,7 +1074,7 @@ def get_render_products(self): continue aov_type = self._get_attr(aov, "aovType") - if multipart and aov_type not in self.unmerged_aovs: + if self.multipart and aov_type not in self.unmerged_aovs: continue # Any AOVs that still get processed, like Cryptomatte @@ -1094,7 +1109,7 @@ def get_render_products(self): productName=aov_light_group_name, aov=aov_name, ext=ext, - multipart=multipart, + multipart=self.multipart, camera=camera) products.append(product) @@ -1108,7 +1123,7 @@ def get_render_products(self): product = RenderProduct(productName=aov_name, aov=aov_name, ext=ext, - multipart=multipart, + multipart=self.multipart, camera=camera) products.append(product) @@ -1124,7 +1139,7 @@ def get_render_products(self): products.insert(0, RenderProduct(productName=beauty_name, ext=ext, - multipart=multipart, + multipart=self.multipart, camera=camera)) return products @@ -1144,6 +1159,10 @@ class RenderProductsRenderman(ARenderProducts): renderer = "renderman" unmerged_aovs = {"PxrCryptomatte"} + def get_multipart(self): + # Implemented as display specific in "get_render_products". + return False + def get_render_products(self): """Get all AOVs. @@ -1283,6 +1302,9 @@ class RenderProductsMayaHardware(ARenderProducts): {"label": "EXR(exr)", "index": 40, "extension": "exr"} ] + def get_multipart(self): + return False + def _get_extension(self, value): result = None if isinstance(value, int): From d9499d5750c42fc324335f4e7354564ffa7bba0c Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 22 Feb 2023 18:00:11 +0000 Subject: [PATCH 181/898] Fix Redshift expected files. --- openpype/hosts/maya/api/lib_renderproducts.py | 26 +++++++++++++++---- .../maya/plugins/publish/collect_render.py | 7 ++++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/maya/api/lib_renderproducts.py b/openpype/hosts/maya/api/lib_renderproducts.py index e635414029b..4e9e13d2a30 100644 --- a/openpype/hosts/maya/api/lib_renderproducts.py +++ b/openpype/hosts/maya/api/lib_renderproducts.py @@ -1001,6 +1001,20 @@ class RenderProductsRedshift(ARenderProducts): renderer = "redshift" unmerged_aovs = {"Cryptomatte"} + def get_files(self, product): + # When outputting AOVs we need to replace Redshift specific AOV tokens + # with Maya render tokens for generating file sequences. We validate to + # a specific AOV fileprefix so we only need to accout for one + # replacement. + if not product.multipart and product.driver: + file_prefix = self._get_attr(product.driver + ".filePrefix") + self.layer_data.filePrefix = file_prefix.replace( + "/", + "//" + ) + + return super(RenderProductsRedshift, self).get_files(product) + def get_multipart(self): # For Redshift we don't directly return upon forcing multilayer # due to some AOVs still being written into separate files, @@ -1009,7 +1023,7 @@ def get_multipart(self): multipart = False force_layer = bool(self._get_attr("redshiftOptions.exrForceMultilayer")) # noqa exMultipart = bool(self._get_attr("redshiftOptions.exrMultipart")) - if exMultipart or force_layer: + if exMultipart and force_layer: multipart = True return multipart @@ -1109,8 +1123,9 @@ def get_render_products(self): productName=aov_light_group_name, aov=aov_name, ext=ext, - multipart=self.multipart, - camera=camera) + multipart=False, + camera=camera, + driver=aov) products.append(product) if light_groups: @@ -1123,8 +1138,9 @@ def get_render_products(self): product = RenderProduct(productName=aov_name, aov=aov_name, ext=ext, - multipart=self.multipart, - camera=camera) + multipart=False, + camera=camera, + driver=aov) products.append(product) # When a Beauty AOV is added manually, it will be rendered as diff --git a/openpype/hosts/maya/plugins/publish/collect_render.py b/openpype/hosts/maya/plugins/publish/collect_render.py index f2b52621879..338f148f850 100644 --- a/openpype/hosts/maya/plugins/publish/collect_render.py +++ b/openpype/hosts/maya/plugins/publish/collect_render.py @@ -42,6 +42,7 @@ import re import os import platform +import json from maya import cmds import maya.app.renderSetup.model.renderSetup as renderSetup @@ -183,7 +184,11 @@ def process(self, context): self.log.info("multipart: {}".format( multipart)) assert exp_files, "no file names were generated, this is bug" - self.log.info(exp_files) + self.log.info( + "expected files: {}".format( + json.dumps(exp_files, indent=4, sort_keys=True) + ) + ) # if we want to attach render to subset, check if we have AOV's # in expectedFiles. If so, raise error as we cannot attach AOV From 52238488f331781525118e83130394ec20ca1d1c Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 23 Feb 2023 09:20:25 +0000 Subject: [PATCH 182/898] Only use force options as multipart identifier. --- openpype/hosts/maya/api/lib_renderproducts.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/maya/api/lib_renderproducts.py b/openpype/hosts/maya/api/lib_renderproducts.py index 4e9e13d2a30..02e55601b9e 100644 --- a/openpype/hosts/maya/api/lib_renderproducts.py +++ b/openpype/hosts/maya/api/lib_renderproducts.py @@ -1021,9 +1021,10 @@ def get_multipart(self): # like Cryptomatte. # AOVs are merged in multi-channel file multipart = False - force_layer = bool(self._get_attr("redshiftOptions.exrForceMultilayer")) # noqa - exMultipart = bool(self._get_attr("redshiftOptions.exrMultipart")) - if exMultipart and force_layer: + force_layer = bool( + self._get_attr("redshiftOptions.exrForceMultilayer") + ) + if force_layer: multipart = True return multipart From 3724c86c185f86d1271eb9c5c98c7f1e302a7baf Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Thu, 23 Feb 2023 11:53:55 +0000 Subject: [PATCH 183/898] Update openpype/hosts/maya/api/lib_renderproducts.py --- openpype/hosts/maya/api/lib_renderproducts.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/maya/api/lib_renderproducts.py b/openpype/hosts/maya/api/lib_renderproducts.py index 02e55601b9e..463324284bc 100644 --- a/openpype/hosts/maya/api/lib_renderproducts.py +++ b/openpype/hosts/maya/api/lib_renderproducts.py @@ -1320,6 +1320,7 @@ class RenderProductsMayaHardware(ARenderProducts): ] def get_multipart(self): + # MayaHardware does not support multipart EXRs. return False def _get_extension(self, value): From 09ccf1af77b3f05aec8d99469f526a13ce2bafca Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 31 Jan 2023 06:55:36 +0000 Subject: [PATCH 184/898] Batch script for running Openpype on Deadline. --- tools/openpype_console.bat | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tools/openpype_console.bat diff --git a/tools/openpype_console.bat b/tools/openpype_console.bat new file mode 100644 index 00000000000..414b5fdf667 --- /dev/null +++ b/tools/openpype_console.bat @@ -0,0 +1,3 @@ +cd "%~dp0\.." +echo %OPENPYPE_MONGO% +.poetry\bin\poetry.exe run python start.py %* From e7017ff05b70ffbd4c3a6354d76a19f2c3d39a22 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 17 Feb 2023 16:25:35 +0000 Subject: [PATCH 185/898] Commenting for documentation --- tools/openpype_console.bat | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tools/openpype_console.bat b/tools/openpype_console.bat index 414b5fdf667..04b28c389f6 100644 --- a/tools/openpype_console.bat +++ b/tools/openpype_console.bat @@ -1,3 +1,15 @@ +goto comment +SYNOPSIS + Helper script running scripts through the OpenPype environment. + +DESCRIPTION + This script is usually used as a replacement for building when tested farm integration like Deadline. + +EXAMPLE + +cmd> .\openpype_console.bat path/to/python_script.py +:comment + cd "%~dp0\.." echo %OPENPYPE_MONGO% .poetry\bin\poetry.exe run python start.py %* From b387441ad67a1d12a012c8bc8bc9f32d2d08ce94 Mon Sep 17 00:00:00 2001 From: Fabia Serra Arrizabalaga Date: Thu, 23 Feb 2023 00:52:40 +0100 Subject: [PATCH 186/898] Move get_workfile_build_placeholder_plugins to NukeHost class as workfile template builder expects --- openpype/hosts/nuke/api/__init__.py | 3 --- openpype/hosts/nuke/api/pipeline.py | 13 ++++++------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/openpype/hosts/nuke/api/__init__.py b/openpype/hosts/nuke/api/__init__.py index 3b00ca9f6f1..1af5ff365d7 100644 --- a/openpype/hosts/nuke/api/__init__.py +++ b/openpype/hosts/nuke/api/__init__.py @@ -30,7 +30,6 @@ parse_container, update_container, - get_workfile_build_placeholder_plugins, ) from .lib import ( INSTANCE_DATA_KNOB, @@ -79,8 +78,6 @@ "parse_container", "update_container", - "get_workfile_build_placeholder_plugins", - "INSTANCE_DATA_KNOB", "ROOT_DATA_KNOB", "maintained_selection", diff --git a/openpype/hosts/nuke/api/pipeline.py b/openpype/hosts/nuke/api/pipeline.py index 6dec60d81af..d5289010cbe 100644 --- a/openpype/hosts/nuke/api/pipeline.py +++ b/openpype/hosts/nuke/api/pipeline.py @@ -101,6 +101,12 @@ def workfile_has_unsaved_changes(self): def get_workfile_extensions(self): return file_extensions() + def get_workfile_build_placeholder_plugins(self): + return [ + NukePlaceholderLoadPlugin, + NukePlaceholderCreatePlugin + ] + def get_containers(self): return ls() @@ -200,13 +206,6 @@ def _show_workfiles(): host_tools.show_workfiles(parent=None, on_top=False) -def get_workfile_build_placeholder_plugins(): - return [ - NukePlaceholderLoadPlugin, - NukePlaceholderCreatePlugin - ] - - def _install_menu(): # uninstall original avalon menu main_window = get_main_window() From 6bf8b7b8ca3cc8961ba271f914fd0abdbcf5bda8 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 22 Feb 2023 15:40:55 +0100 Subject: [PATCH 187/898] improving deprecation --- openpype/hosts/nuke/api/lib.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index 0325838e781..b13c592fbf3 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -214,8 +214,9 @@ def update_node_data(node, knobname, data): knob.setValue(knob_value) +@deprecated class Knobby(object): - """[DEPRICATED] For creating knob which it's type isn't + """[DEPRECATED] For creating knob which it's type isn't mapped in `create_knobs` Args: @@ -248,8 +249,9 @@ def nice_naming(key): return " ".join(words) +@deprecated def create_knobs(data, tab=None): - """[DEPRICATED] Create knobs by data + """[DEPRECATED] Create knobs by data Depending on the type of each dict value and creates the correct Knob. @@ -342,8 +344,9 @@ def nice_naming(key): return knobs +@deprecated def imprint(node, data, tab=None): - """[DEPRICATED] Store attributes with value on node + """[DEPRECATED] Store attributes with value on node Parse user data into Node knobs. Use `collections.OrderedDict` to ensure knob order. @@ -398,8 +401,9 @@ def imprint(node, data, tab=None): node.addKnob(knob) +@deprecated def add_publish_knob(node): - """[DEPRICATED] Add Publish knob to node + """[DEPRECATED] Add Publish knob to node Arguments: node (nuke.Node): nuke node to be processed @@ -416,8 +420,9 @@ def add_publish_knob(node): return node +@deprecated def set_avalon_knob_data(node, data=None, prefix="avalon:"): - """[DEPRICATED] Sets data into nodes's avalon knob + """[DEPRECATED] Sets data into nodes's avalon knob Arguments: node (nuke.Node): Nuke node to imprint with data, @@ -478,8 +483,9 @@ def set_avalon_knob_data(node, data=None, prefix="avalon:"): return node +@deprecated def get_avalon_knob_data(node, prefix="avalon:", create=True): - """[DEPRICATED] Gets a data from nodes's avalon knob + """[DEPRECATED] Gets a data from nodes's avalon knob Arguments: node (obj): Nuke node to search for data, @@ -521,8 +527,9 @@ def get_avalon_knob_data(node, prefix="avalon:", create=True): return data +@deprecated def fix_data_for_node_create(data): - """[DEPRICATED] Fixing data to be used for nuke knobs + """[DEPRECATED] Fixing data to be used for nuke knobs """ for k, v in data.items(): if isinstance(v, six.text_type): @@ -532,8 +539,9 @@ def fix_data_for_node_create(data): return data +@deprecated def add_write_node_legacy(name, **kwarg): - """[DEPRICATED] Adding nuke write node + """[DEPRECATED] Adding nuke write node Arguments: name (str): nuke node name kwarg (attrs): data for nuke knobs @@ -697,7 +705,7 @@ def get_nuke_imageio_settings(): @deprecated("openpype.hosts.nuke.api.lib.get_nuke_imageio_settings") def get_created_node_imageio_setting_legacy(nodeclass, creator, subset): - '''[DEPRICATED] Get preset data for dataflow (fileType, compression, bitDepth) + '''[DEPRECATED] Get preset data for dataflow (fileType, compression, bitDepth) ''' assert any([creator, nodeclass]), nuke.message( From ea23223977420a60168a922eaf4603f6fe7726b5 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 22 Feb 2023 17:21:17 +0100 Subject: [PATCH 188/898] Nuke: baking with multiple reposition nodes also with settings and defaults --- openpype/hosts/nuke/api/plugin.py | 96 ++++++++++++------- .../defaults/project_settings/nuke.json | 35 +++++++ .../schemas/schema_nuke_publish.json | 47 +++++++++ 3 files changed, 144 insertions(+), 34 deletions(-) diff --git a/openpype/hosts/nuke/api/plugin.py b/openpype/hosts/nuke/api/plugin.py index d3f8357f7d4..5521db99c08 100644 --- a/openpype/hosts/nuke/api/plugin.py +++ b/openpype/hosts/nuke/api/plugin.py @@ -558,9 +558,7 @@ def __init__(self, self.path_in = self.instance.data.get("path", None) self.staging_dir = self.instance.data["stagingDir"] self.collection = self.instance.data.get("collection", None) - self.data = dict({ - "representations": list() - }) + self.data = {"representations": []} def get_file_info(self): if self.collection: @@ -626,7 +624,7 @@ def get_imageio_baking_profile(self): nuke_imageio = opnlib.get_nuke_imageio_settings() # TODO: this is only securing backward compatibility lets remove - # this once all projects's anotomy are updated to newer config + # this once all projects's anatomy are updated to newer config if "baking" in nuke_imageio.keys(): return nuke_imageio["baking"]["viewerProcess"] else: @@ -823,8 +821,41 @@ def generate_mov(self, farm=False, **kwargs): add_tags = [] self.publish_on_farm = farm read_raw = kwargs["read_raw"] + + # TODO: remove this when `reformat_nodes_config` + # is changed in settings reformat_node_add = kwargs["reformat_node_add"] reformat_node_config = kwargs["reformat_node_config"] + + # TODO: make this required in future + reformat_nodes_config = kwargs.get("reformat_nodes_config", {}) + + # TODO: remove this once deprecated is removed + # make sure only reformat_nodes_config is used in future + if reformat_node_add and reformat_nodes_config.get("enabled"): + self.log.warning( + "`reformat_node_add` is deprecated. " + "Please use only `reformat_nodes_config` instead.") + reformat_nodes_config = None + + # TODO: reformat code when backward compatibility is not needed + # warning if reformat_nodes_config is not set + if not reformat_nodes_config: + self.log.warning( + "Please set `reformat_nodes_config` in settings.") + self.log.warning( + "Using `reformat_node_config` instead.") + reformat_nodes_config = { + "enabled": reformat_node_add, + "reposition_nodes": [ + { + "node_class": "Reformat", + "knobs": reformat_node_config + } + ] + } + + bake_viewer_process = kwargs["bake_viewer_process"] bake_viewer_input_process_node = kwargs[ "bake_viewer_input_process"] @@ -846,7 +877,6 @@ def generate_mov(self, farm=False, **kwargs): subset = self.instance.data["subset"] self._temp_nodes[subset] = [] - # ---------- start nodes creation # Read node r_node = nuke.createNode("Read") @@ -860,44 +890,39 @@ def generate_mov(self, farm=False, **kwargs): if read_raw: r_node["raw"].setValue(1) - # connect - self._temp_nodes[subset].append(r_node) - self.previous_node = r_node - self.log.debug("Read... `{}`".format(self._temp_nodes[subset])) + # connect to Read node + self._shift_to_previous_node_and_temp(subset, r_node, "Read... `{}`") # add reformat node - if reformat_node_add: + if reformat_nodes_config["enabled"]: + reposition_nodes = reformat_nodes_config["reposition_nodes"] + for reposition_node in reposition_nodes: + node_class = reposition_node["node_class"] + knobs = reposition_node["knobs"] + node = nuke.createNode(node_class) + set_node_knobs_from_settings(node, knobs) + + # connect in order + self._connect_to_above_nodes( + node, subset, "Reposition node... `{}`" + ) # append reformated tag add_tags.append("reformated") - rf_node = nuke.createNode("Reformat") - set_node_knobs_from_settings(rf_node, reformat_node_config) - - # connect - rf_node.setInput(0, self.previous_node) - self._temp_nodes[subset].append(rf_node) - self.previous_node = rf_node - self.log.debug( - "Reformat... `{}`".format(self._temp_nodes[subset])) - # only create colorspace baking if toggled on if bake_viewer_process: if bake_viewer_input_process_node: # View Process node ipn = get_view_process_node() if ipn is not None: - # connect - ipn.setInput(0, self.previous_node) - self._temp_nodes[subset].append(ipn) - self.previous_node = ipn - self.log.debug( - "ViewProcess... `{}`".format( - self._temp_nodes[subset])) + # connect to ViewProcess node + self._connect_to_above_nodes(ipn, subset, "ViewProcess... `{}`") if not self.viewer_lut_raw: # OCIODisplay dag_node = nuke.createNode("OCIODisplay") + # assign display display, viewer = get_viewer_config_from_string( str(baking_view_profile) ) @@ -907,13 +932,7 @@ def generate_mov(self, farm=False, **kwargs): # assign viewer dag_node["view"].setValue(viewer) - # connect - dag_node.setInput(0, self.previous_node) - self._temp_nodes[subset].append(dag_node) - self.previous_node = dag_node - self.log.debug("OCIODisplay... `{}`".format( - self._temp_nodes[subset])) - + self._connect_to_above_nodes(dag_node, subset, "OCIODisplay... `{}`") # Write node write_node = nuke.createNode("Write") self.log.debug("Path: {}".format(self.path)) @@ -967,6 +986,15 @@ def generate_mov(self, farm=False, **kwargs): return self.data + def _shift_to_previous_node_and_temp(self, subset, node, message): + self._temp_nodes[subset].append(node) + self.previous_node = node + self.log.debug(message.format(self._temp_nodes[subset])) + + def _connect_to_above_nodes(self, node, subset, message): + node.setInput(0, self.previous_node) + self._shift_to_previous_node_and_temp(subset, node, message) + @deprecated("openpype.hosts.nuke.api.plugin.NukeWriteCreator") class AbstractWriteRender(OpenPypeCreator): diff --git a/openpype/settings/defaults/project_settings/nuke.json b/openpype/settings/defaults/project_settings/nuke.json index d475c337d95..2545411e0ad 100644 --- a/openpype/settings/defaults/project_settings/nuke.json +++ b/openpype/settings/defaults/project_settings/nuke.json @@ -446,6 +446,41 @@ "value": false } ], + "reformat_nodes_config": { + "enabled": false, + "reposition_nodes": [ + { + "node_class": "Reformat", + "knobs": [ + { + "type": "text", + "name": "type", + "value": "to format" + }, + { + "type": "text", + "name": "format", + "value": "HD_1080" + }, + { + "type": "text", + "name": "filter", + "value": "Lanczos6" + }, + { + "type": "bool", + "name": "black_outside", + "value": true + }, + { + "type": "bool", + "name": "pbb", + "value": false + } + ] + } + ] + }, "extension": "mov", "add_custom_tags": [] } diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json index 5b9145e7d98..1c542279fca 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json @@ -271,6 +271,10 @@ { "type": "separator" }, + { + "type": "label", + "label": "Currently we are supporting also multiple reposition nodes.
Older single reformat node is still supported
and if it is activated then preference will
be on it. If you want to use multiple reformat
nodes then you need to disable single reformat
node and enable multiple Reformat nodes here." + }, { "type": "boolean", "key": "reformat_node_add", @@ -287,6 +291,49 @@ } ] }, + { + "key": "reformat_nodes_config", + "type": "dict", + "label": "Reformat Nodes", + "collapsible": true, + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "label", + "label": "Reposition knobs supported only.
You can add multiple reformat nodes
and set their knobs. Order of reformat
nodes is important. First reformat node
will be applied first and last reformat
node will be applied last." + }, + { + "key": "reposition_nodes", + "type": "list", + "label": "Reposition nodes", + "object_type": { + "type": "dict", + "children": [ + { + "key": "node_class", + "label": "Node class", + "type": "text" + }, + { + "type": "schema_template", + "name": "template_nuke_knob_inputs", + "template_data": [ + { + "label": "Node knobs", + "key": "knobs" + } + ] + } + ] + } + } + ] + }, { "type": "separator" }, From 15fa8f551c3131b8019e81d46a3f0ab976bf9a63 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 23 Feb 2023 10:57:00 +0100 Subject: [PATCH 189/898] little fixes --- openpype/hosts/nuke/api/lib.py | 9 +++------ openpype/hosts/nuke/api/plugin.py | 6 +++--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index b13c592fbf3..73d4986b644 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -214,7 +214,6 @@ def update_node_data(node, knobname, data): knob.setValue(knob_value) -@deprecated class Knobby(object): """[DEPRECATED] For creating knob which it's type isn't mapped in `create_knobs` @@ -249,9 +248,8 @@ def nice_naming(key): return " ".join(words) -@deprecated def create_knobs(data, tab=None): - """[DEPRECATED] Create knobs by data + """Create knobs by data Depending on the type of each dict value and creates the correct Knob. @@ -344,9 +342,8 @@ def nice_naming(key): return knobs -@deprecated def imprint(node, data, tab=None): - """[DEPRECATED] Store attributes with value on node + """Store attributes with value on node Parse user data into Node knobs. Use `collections.OrderedDict` to ensure knob order. @@ -1249,7 +1246,7 @@ def create_write_node( nodes to be created before write with dependency review (bool)[optional]: adding review knob farm (bool)[optional]: rendering workflow target - kwargs (dict)[optional]: additional key arguments for formating + kwargs (dict)[optional]: additional key arguments for formatting Example: prenodes = { diff --git a/openpype/hosts/nuke/api/plugin.py b/openpype/hosts/nuke/api/plugin.py index 5521db99c08..160ca820a47 100644 --- a/openpype/hosts/nuke/api/plugin.py +++ b/openpype/hosts/nuke/api/plugin.py @@ -842,9 +842,9 @@ def generate_mov(self, farm=False, **kwargs): # warning if reformat_nodes_config is not set if not reformat_nodes_config: self.log.warning( - "Please set `reformat_nodes_config` in settings.") - self.log.warning( - "Using `reformat_node_config` instead.") + "Please set `reformat_nodes_config` in settings. " + "Using `reformat_node_config` instead." + ) reformat_nodes_config = { "enabled": reformat_node_add, "reposition_nodes": [ From ca7bf70e1578f175712c1923683513391a5023e8 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Feb 2023 11:47:32 +0100 Subject: [PATCH 190/898] nuke assist kickoff --- .../system_settings/applications.json | 128 ++++++++++++++++++ .../system_schema/schema_applications.json | 8 ++ 2 files changed, 136 insertions(+) diff --git a/openpype/settings/defaults/system_settings/applications.json b/openpype/settings/defaults/system_settings/applications.json index f84d99e36b4..5fd9b926fb1 100644 --- a/openpype/settings/defaults/system_settings/applications.json +++ b/openpype/settings/defaults/system_settings/applications.json @@ -337,6 +337,134 @@ } } }, + "nukeassist": { + "enabled": true, + "label": "Nuke Assist", + "icon": "{}/app_icons/nuke.png", + "host_name": "nuke", + "environment": { + "NUKE_PATH": [ + "{NUKE_PATH}", + "{OPENPYPE_STUDIO_PLUGINS}/nuke" + ] + }, + "variants": { + "13-2": { + "use_python_2": false, + "executables": { + "windows": [ + "C:\\Program Files\\Nuke13.2v1\\Nuke13.2.exe" + ], + "darwin": [], + "linux": [ + "/usr/local/Nuke13.2v1/Nuke13.2" + ] + }, + "arguments": { + "windows": ["--nukeassist"], + "darwin": ["--nukeassist"], + "linux": ["--nukeassist"] + }, + "environment": {} + }, + "13-0": { + "use_python_2": false, + "executables": { + "windows": [ + "C:\\Program Files\\Nuke13.0v1\\Nuke13.0.exe" + ], + "darwin": [], + "linux": [ + "/usr/local/Nuke13.0v1/Nuke13.0" + ] + }, + "arguments": { + "windows": ["--nukeassist"], + "darwin": ["--nukeassist"], + "linux": ["--nukeassist"] + }, + "environment": {} + }, + "12-2": { + "use_python_2": true, + "executables": { + "windows": [ + "C:\\Program Files\\Nuke12.2v3\\Nuke12.2.exe" + ], + "darwin": [], + "linux": [ + "/usr/local/Nuke12.2v3Nuke12.2" + ] + }, + "arguments": { + "windows": ["--nukeassist"], + "darwin": ["--nukeassist"], + "linux": ["--nukeassist"] + }, + "environment": {} + }, + "12-0": { + "use_python_2": true, + "executables": { + "windows": [ + "C:\\Program Files\\Nuke12.0v1\\Nuke12.0.exe" + ], + "darwin": [], + "linux": [ + "/usr/local/Nuke12.0v1/Nuke12.0" + ] + }, + "arguments": { + "windows": ["--nukeassist"], + "darwin": ["--nukeassist"], + "linux": ["--nukeassist"] + }, + "environment": {} + }, + "11-3": { + "use_python_2": true, + "executables": { + "windows": [ + "C:\\Program Files\\Nuke11.3v1\\Nuke11.3.exe" + ], + "darwin": [], + "linux": [ + "/usr/local/Nuke11.3v5/Nuke11.3" + ] + }, + "arguments": { + "windows": ["--nukeassist"], + "darwin": ["--nukeassist"], + "linux": ["--nukeassist"] + }, + "environment": {} + }, + "11-2": { + "use_python_2": true, + "executables": { + "windows": [ + "C:\\Program Files\\Nuke11.2v2\\Nuke11.2.exe" + ], + "darwin": [], + "linux": [] + }, + "arguments": { + "windows": ["--nukeassist"], + "darwin": ["--nukeassist"], + "linux": ["--nukeassist"] + }, + "environment": {} + }, + "__dynamic_keys_labels__": { + "13-2": "13.2", + "13-0": "13.0", + "12-2": "12.2", + "12-0": "12.0", + "11-3": "11.3", + "11-2": "11.2" + } + } + }, "nukex": { "enabled": true, "label": "Nuke X", diff --git a/openpype/settings/entities/schemas/system_schema/schema_applications.json b/openpype/settings/entities/schemas/system_schema/schema_applications.json index 36c58114965..b17687cf71f 100644 --- a/openpype/settings/entities/schemas/system_schema/schema_applications.json +++ b/openpype/settings/entities/schemas/system_schema/schema_applications.json @@ -25,6 +25,14 @@ "nuke_label": "Nuke" } }, + { + "type": "schema_template", + "name": "template_nuke", + "template_data": { + "nuke_type": "nukeassist", + "nuke_label": "Nuke Assist" + } + }, { "type": "schema_template", "name": "template_nuke", From 8777aa9859e66ecf52cc7cfebb0c1541e5e37785 Mon Sep 17 00:00:00 2001 From: ynput Date: Tue, 21 Feb 2023 14:23:26 +0200 Subject: [PATCH 191/898] adding appgroup to prelaunch hook --- openpype/hooks/pre_foundry_apps.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hooks/pre_foundry_apps.py b/openpype/hooks/pre_foundry_apps.py index 85f68c6b604..2092d5025dc 100644 --- a/openpype/hooks/pre_foundry_apps.py +++ b/openpype/hooks/pre_foundry_apps.py @@ -13,7 +13,7 @@ class LaunchFoundryAppsWindows(PreLaunchHook): # Should be as last hook because must change launch arguments to string order = 1000 - app_groups = ["nuke", "nukex", "hiero", "nukestudio"] + app_groups = ["nuke", "nukeassist", "nukex", "hiero", "nukestudio"] platforms = ["windows"] def execute(self): From 3c84b4195d6077ffc4abf51933359f2c69cec7a8 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Feb 2023 13:39:02 +0100 Subject: [PATCH 192/898] adding nukeassist hook --- openpype/hosts/nuke/hooks/__init__.py | 0 openpype/hosts/nuke/hooks/pre_nukeassist_setup.py | 10 ++++++++++ 2 files changed, 10 insertions(+) create mode 100644 openpype/hosts/nuke/hooks/__init__.py create mode 100644 openpype/hosts/nuke/hooks/pre_nukeassist_setup.py diff --git a/openpype/hosts/nuke/hooks/__init__.py b/openpype/hosts/nuke/hooks/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py b/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py new file mode 100644 index 00000000000..80696c34e5f --- /dev/null +++ b/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py @@ -0,0 +1,10 @@ +from openpype.lib import PreLaunchHook + +class PrelaunchNukeAssistHook(PreLaunchHook): + """ + Adding flag when nukeassist + """ + app_groups = ["nukeassist"] + + def execute(self): + self.launch_context.env["NUKEASSIST"] = True From 633738daa719e78a69e56391f7e46d0c1986a183 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Feb 2023 13:56:17 +0100 Subject: [PATCH 193/898] adding hook to host --- openpype/hosts/nuke/addon.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openpype/hosts/nuke/addon.py b/openpype/hosts/nuke/addon.py index 9d25afe2b64..6a4b91a76d1 100644 --- a/openpype/hosts/nuke/addon.py +++ b/openpype/hosts/nuke/addon.py @@ -63,5 +63,12 @@ def add_implementation_envs(self, env, _app): path_paths.append(quick_time_path) env["PATH"] = os.pathsep.join(path_paths) + def get_launch_hook_paths(self, app): + if app.host_name != self.host_name: + return [] + return [ + os.path.join(NUKE_ROOT_DIR, "hooks") + ] + def get_workfile_extensions(self): return [".nk"] From 6bb6aab0f96ac8903d38b93c529c5e7d8b349b6b Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Feb 2023 14:54:51 +0100 Subject: [PATCH 194/898] adding menu assist variant conditions --- openpype/hosts/nuke/api/pipeline.py | 50 +++++++++++-------- openpype/hosts/nuke/hooks/__init__.py | 0 .../hosts/nuke/hooks/pre_nukeassist_setup.py | 2 +- 3 files changed, 30 insertions(+), 22 deletions(-) delete mode 100644 openpype/hosts/nuke/hooks/__init__.py diff --git a/openpype/hosts/nuke/api/pipeline.py b/openpype/hosts/nuke/api/pipeline.py index d5289010cbe..306fa50de9e 100644 --- a/openpype/hosts/nuke/api/pipeline.py +++ b/openpype/hosts/nuke/api/pipeline.py @@ -71,7 +71,7 @@ INVENTORY_PATH = os.path.join(PLUGINS_DIR, "inventory") MENU_LABEL = os.environ["AVALON_LABEL"] - +ASSIST = bool(os.getenv("NUKEASSIST")) # registering pyblish gui regarding settings in presets if os.getenv("PYBLISH_GUI", None): @@ -207,6 +207,7 @@ def _show_workfiles(): def _install_menu(): + # uninstall original avalon menu main_window = get_main_window() menubar = nuke.menu("Nuke") @@ -217,7 +218,9 @@ def _install_menu(): ) Context.context_label = label context_action = menu.addCommand(label) - context_action.setEnabled(False) + + if not ASSIST: + context_action.setEnabled(False) menu.addSeparator() menu.addCommand( @@ -226,18 +229,20 @@ def _install_menu(): ) menu.addSeparator() - menu.addCommand( - "Create...", - lambda: host_tools.show_publisher( - tab="create" + if not ASSIST: + menu.addCommand( + "Create...", + lambda: host_tools.show_publisher( + tab="create" + ) ) - ) - menu.addCommand( - "Publish...", - lambda: host_tools.show_publisher( - tab="publish" + menu.addCommand( + "Publish...", + lambda: host_tools.show_publisher( + tab="publish" + ) ) - ) + menu.addCommand( "Load...", lambda: host_tools.show_loader( @@ -285,15 +290,18 @@ def _install_menu(): "Build Workfile from template", lambda: build_workfile_template() ) - menu_template.addSeparator() - menu_template.addCommand( - "Create Place Holder", - lambda: create_placeholder() - ) - menu_template.addCommand( - "Update Place Holder", - lambda: update_placeholder() - ) + + if not ASSIST: + menu_template.addSeparator() + menu_template.addCommand( + "Create Place Holder", + lambda: create_placeholder() + ) + menu_template.addCommand( + "Update Place Holder", + lambda: update_placeholder() + ) + menu.addSeparator() menu.addCommand( "Experimental tools...", diff --git a/openpype/hosts/nuke/hooks/__init__.py b/openpype/hosts/nuke/hooks/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py b/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py index 80696c34e5f..054bd677a7d 100644 --- a/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py +++ b/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py @@ -7,4 +7,4 @@ class PrelaunchNukeAssistHook(PreLaunchHook): app_groups = ["nukeassist"] def execute(self): - self.launch_context.env["NUKEASSIST"] = True + self.launch_context.env["NUKEASSIST"] = "1" From 3159facb2083a44785cd4fd1378993b167a57c45 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Feb 2023 15:26:07 +0100 Subject: [PATCH 195/898] moving Assist switch to api level condition for updating nodes --- openpype/hosts/nuke/api/__init__.py | 7 ++++++- openpype/hosts/nuke/api/lib.py | 21 ++++++++++++--------- openpype/hosts/nuke/api/pipeline.py | 2 +- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/openpype/hosts/nuke/api/__init__.py b/openpype/hosts/nuke/api/__init__.py index 1af5ff365d7..7766a94140c 100644 --- a/openpype/hosts/nuke/api/__init__.py +++ b/openpype/hosts/nuke/api/__init__.py @@ -1,3 +1,4 @@ +import os from .workio import ( file_extensions, has_unsaved_changes, @@ -50,6 +51,8 @@ get_colorspace_list ) +ASSIST = bool(os.getenv("NUKEASSIST")) + __all__ = ( "file_extensions", "has_unsaved_changes", @@ -92,5 +95,7 @@ "create_write_node", "colorspace_exists_on_node", - "get_colorspace_list" + "get_colorspace_list", + + "ASSIST" ) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index 73d4986b644..ec5bc58f9ff 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -49,7 +49,7 @@ ) from openpype.pipeline.workfile import BuildWorkfile -from . import gizmo_menu +from . import gizmo_menu, ASSIST from .workio import ( save_file, @@ -2263,14 +2263,17 @@ def reset_frame_range_handles(self): node['frame_range'].setValue(range) node['frame_range_lock'].setValue(True) - set_node_data( - self._root_node, - INSTANCE_DATA_KNOB, - { - "handleStart": int(handle_start), - "handleEnd": int(handle_end) - } - ) + if not ASSIST: + set_node_data( + self._root_node, + INSTANCE_DATA_KNOB, + { + "handleStart": int(handle_start), + "handleEnd": int(handle_end) + } + ) + else: + log.warning("NukeAssist mode is not allowing updating custom knobs...") def reset_resolution(self): """Set resolution to project resolution.""" diff --git a/openpype/hosts/nuke/api/pipeline.py b/openpype/hosts/nuke/api/pipeline.py index 306fa50de9e..94c45186647 100644 --- a/openpype/hosts/nuke/api/pipeline.py +++ b/openpype/hosts/nuke/api/pipeline.py @@ -60,6 +60,7 @@ work_root, current_file ) +from . import ASSIST log = Logger.get_logger(__name__) @@ -71,7 +72,6 @@ INVENTORY_PATH = os.path.join(PLUGINS_DIR, "inventory") MENU_LABEL = os.environ["AVALON_LABEL"] -ASSIST = bool(os.getenv("NUKEASSIST")) # registering pyblish gui regarding settings in presets if os.getenv("PYBLISH_GUI", None): From 02b69f8ba84505c40d01f23048a0ad965a539b72 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Feb 2023 16:06:39 +0100 Subject: [PATCH 196/898] moving ASSIST switch to utils --- openpype/hosts/nuke/api/__init__.py | 7 +------ openpype/hosts/nuke/api/lib.py | 3 ++- openpype/hosts/nuke/api/pipeline.py | 2 +- openpype/hosts/nuke/api/utils.py | 1 + 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/nuke/api/__init__.py b/openpype/hosts/nuke/api/__init__.py index 7766a94140c..1af5ff365d7 100644 --- a/openpype/hosts/nuke/api/__init__.py +++ b/openpype/hosts/nuke/api/__init__.py @@ -1,4 +1,3 @@ -import os from .workio import ( file_extensions, has_unsaved_changes, @@ -51,8 +50,6 @@ get_colorspace_list ) -ASSIST = bool(os.getenv("NUKEASSIST")) - __all__ = ( "file_extensions", "has_unsaved_changes", @@ -95,7 +92,5 @@ "create_write_node", "colorspace_exists_on_node", - "get_colorspace_list", - - "ASSIST" + "get_colorspace_list" ) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index ec5bc58f9ff..dfc647872ba 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -49,7 +49,8 @@ ) from openpype.pipeline.workfile import BuildWorkfile -from . import gizmo_menu, ASSIST +from . import gizmo_menu +from .utils import ASSIST from .workio import ( save_file, diff --git a/openpype/hosts/nuke/api/pipeline.py b/openpype/hosts/nuke/api/pipeline.py index 94c45186647..55cb77bafe9 100644 --- a/openpype/hosts/nuke/api/pipeline.py +++ b/openpype/hosts/nuke/api/pipeline.py @@ -60,7 +60,7 @@ work_root, current_file ) -from . import ASSIST +from .utils import ASSIST log = Logger.get_logger(__name__) diff --git a/openpype/hosts/nuke/api/utils.py b/openpype/hosts/nuke/api/utils.py index 6bcb752dd1d..261eba8401c 100644 --- a/openpype/hosts/nuke/api/utils.py +++ b/openpype/hosts/nuke/api/utils.py @@ -4,6 +4,7 @@ from openpype import resources from .lib import maintained_selection +ASSIST = bool(os.getenv("NUKEASSIST")) def set_context_favorites(favorites=None): """ Adding favorite folders to nuke's browser From 888f436def036d0cddcbeb8b6f4340e641aa0f0c Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Feb 2023 16:38:54 +0100 Subject: [PATCH 197/898] move ASSIST to constant --- openpype/hosts/nuke/api/constants.py | 4 ++++ openpype/hosts/nuke/api/lib.py | 2 +- openpype/hosts/nuke/api/pipeline.py | 2 +- openpype/hosts/nuke/api/utils.py | 1 - 4 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 openpype/hosts/nuke/api/constants.py diff --git a/openpype/hosts/nuke/api/constants.py b/openpype/hosts/nuke/api/constants.py new file mode 100644 index 00000000000..110199720fb --- /dev/null +++ b/openpype/hosts/nuke/api/constants.py @@ -0,0 +1,4 @@ +import os + + +ASSIST = bool(os.getenv("NUKEASSIST")) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index dfc647872ba..9e36fb147b9 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -50,7 +50,7 @@ from openpype.pipeline.workfile import BuildWorkfile from . import gizmo_menu -from .utils import ASSIST +from .constants import ASSIST from .workio import ( save_file, diff --git a/openpype/hosts/nuke/api/pipeline.py b/openpype/hosts/nuke/api/pipeline.py index 55cb77bafe9..f07d150ba58 100644 --- a/openpype/hosts/nuke/api/pipeline.py +++ b/openpype/hosts/nuke/api/pipeline.py @@ -60,7 +60,7 @@ work_root, current_file ) -from .utils import ASSIST +from .constants import ASSIST log = Logger.get_logger(__name__) diff --git a/openpype/hosts/nuke/api/utils.py b/openpype/hosts/nuke/api/utils.py index 261eba8401c..6bcb752dd1d 100644 --- a/openpype/hosts/nuke/api/utils.py +++ b/openpype/hosts/nuke/api/utils.py @@ -4,7 +4,6 @@ from openpype import resources from .lib import maintained_selection -ASSIST = bool(os.getenv("NUKEASSIST")) def set_context_favorites(favorites=None): """ Adding favorite folders to nuke's browser From a6bde83900e369c853cd79696431f79acae3215e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Je=C5=BEek?= Date: Wed, 22 Feb 2023 14:41:36 +0100 Subject: [PATCH 198/898] Update openpype/hosts/nuke/hooks/pre_nukeassist_setup.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- openpype/hosts/nuke/hooks/pre_nukeassist_setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py b/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py index 054bd677a7d..3a0f00413a5 100644 --- a/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py +++ b/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py @@ -8,3 +8,4 @@ class PrelaunchNukeAssistHook(PreLaunchHook): def execute(self): self.launch_context.env["NUKEASSIST"] = "1" + From 47c93bb12ac21de36c26595d9a5db2560098dd38 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 22 Feb 2023 14:44:22 +0100 Subject: [PATCH 199/898] removing line --- openpype/hosts/nuke/hooks/pre_nukeassist_setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py b/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py index 3a0f00413a5..054bd677a7d 100644 --- a/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py +++ b/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py @@ -8,4 +8,3 @@ class PrelaunchNukeAssistHook(PreLaunchHook): def execute(self): self.launch_context.env["NUKEASSIST"] = "1" - From 0a9e8265ed4f660eb3512455f222b8d31dae9871 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 22 Feb 2023 14:52:57 +0100 Subject: [PATCH 200/898] context label is not needed in nukeassist --- openpype/hosts/nuke/api/pipeline.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/nuke/api/pipeline.py b/openpype/hosts/nuke/api/pipeline.py index f07d150ba58..4c0f169ade3 100644 --- a/openpype/hosts/nuke/api/pipeline.py +++ b/openpype/hosts/nuke/api/pipeline.py @@ -207,22 +207,25 @@ def _show_workfiles(): def _install_menu(): + """Install Avalon menu into Nuke's main menu bar.""" # uninstall original avalon menu main_window = get_main_window() menubar = nuke.menu("Nuke") menu = menubar.addMenu(MENU_LABEL) - label = "{0}, {1}".format( - os.environ["AVALON_ASSET"], os.environ["AVALON_TASK"] - ) - Context.context_label = label - context_action = menu.addCommand(label) if not ASSIST: + label = "{0}, {1}".format( + os.environ["AVALON_ASSET"], os.environ["AVALON_TASK"] + ) + Context.context_label = label + context_action = menu.addCommand(label) context_action.setEnabled(False) - menu.addSeparator() + # add separator after context label + menu.addSeparator() + menu.addCommand( "Work Files...", _show_workfiles From c99b5fdb238bb345b1efeebc651afbbb338f77b7 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 22 Feb 2023 14:56:27 +0100 Subject: [PATCH 201/898] adding empty lines --- openpype/hosts/nuke/api/pipeline.py | 1 - openpype/hosts/nuke/hooks/pre_nukeassist_setup.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/nuke/api/pipeline.py b/openpype/hosts/nuke/api/pipeline.py index 4c0f169ade3..2496d66c1d0 100644 --- a/openpype/hosts/nuke/api/pipeline.py +++ b/openpype/hosts/nuke/api/pipeline.py @@ -214,7 +214,6 @@ def _install_menu(): menubar = nuke.menu("Nuke") menu = menubar.addMenu(MENU_LABEL) - if not ASSIST: label = "{0}, {1}".format( os.environ["AVALON_ASSET"], os.environ["AVALON_TASK"] diff --git a/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py b/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py index 054bd677a7d..3948a665c6b 100644 --- a/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py +++ b/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py @@ -1,5 +1,6 @@ from openpype.lib import PreLaunchHook + class PrelaunchNukeAssistHook(PreLaunchHook): """ Adding flag when nukeassist From 36c5a91cb5f4615e736cb53c2a0a46883bbd2c0f Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 22 Feb 2023 14:59:30 +0100 Subject: [PATCH 202/898] hound comments --- openpype/hosts/nuke/api/lib.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index 9e36fb147b9..c08db978d3c 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -2274,7 +2274,10 @@ def reset_frame_range_handles(self): } ) else: - log.warning("NukeAssist mode is not allowing updating custom knobs...") + log.warning( + "NukeAssist mode is not allowing " + "updating custom knobs..." + ) def reset_resolution(self): """Set resolution to project resolution.""" From 68f0602975d8eea61fc56d7fd81a6cd777e42856 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 24 Feb 2023 12:45:00 +0800 Subject: [PATCH 203/898] resolve conflict --- openpype/hosts/maya/plugins/publish/extract_look.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index ca110ceaddb..efeddcfbe40 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -536,9 +536,10 @@ def _process_texture(self, filepath, resource, ] if linearize: if cmds.colorManagementPrefs(query=True, cmEnabled=True): - render_colorspace = cmds.colorManagementPrefs(query=True, renderingSpaceName=True) # noqa + render_colorspace = cmds.colorManagementPrefs(query=True, + renderingSpaceName=True) # noqa config_path = cmds.colorManagementPrefs(query=True, - configFilePath=True) + configFilePath=True) # noqa if not os.path.exists(config_path): raise RuntimeError("No OCIO config path found!") @@ -572,7 +573,7 @@ def _process_texture(self, filepath, resource, "is already linear") else: self.log.warning("cannot guess the colorspace" - "color conversion won't be available!") + "color conversion won't be available!") # noqa additional_args.extend(["--colorconfig", config_path]) From ffb4b64137b0ca91b9f51ea3c6f284c9b27f1887 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 24 Feb 2023 12:48:15 +0800 Subject: [PATCH 204/898] hound fix --- openpype/hosts/maya/api/lib.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index 71ca6b79c88..5e0f80818b6 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -3577,8 +3577,8 @@ def image_info(file_path): dict: Dictionary with the information about the texture file. """ from arnold import ( - AiTextureGetBitDepth, - AiTextureGetFormat + AiTextureGetBitDepth, + AiTextureGetFormat ) # Get Texture Information img_info = {'filename': file_path} @@ -3603,11 +3603,11 @@ def guess_colorspace(img_info): option of maketx. """ from arnold import ( - AiTextureInvalidate, - # types - AI_TYPE_BYTE, - AI_TYPE_INT, - AI_TYPE_UINT + AiTextureInvalidate, + # types + AI_TYPE_BYTE, + AI_TYPE_INT, + AI_TYPE_UINT ) try: if img_info['bit_depth'] <= 16: From 8bbe10e18dfe88107a02a7f2fd1bebdb9d88fe51 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 24 Feb 2023 12:49:39 +0800 Subject: [PATCH 205/898] hound fix --- openpype/hosts/maya/api/lib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index 5e0f80818b6..f3c0f068b82 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -3579,7 +3579,7 @@ def image_info(file_path): from arnold import ( AiTextureGetBitDepth, AiTextureGetFormat -) + ) # Get Texture Information img_info = {'filename': file_path} if os.path.isfile(file_path): @@ -3608,7 +3608,7 @@ def guess_colorspace(img_info): AI_TYPE_BYTE, AI_TYPE_INT, AI_TYPE_UINT -) + ) try: if img_info['bit_depth'] <= 16: if img_info['format'] in (AI_TYPE_BYTE, AI_TYPE_INT, AI_TYPE_UINT): # noqa From c2685a6c57394a4fb839a1618846f1363f470657 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 24 Feb 2023 17:02:18 +0100 Subject: [PATCH 206/898] Nuke: caching settings and retrieved active farm module --- openpype/hosts/nuke/api/lib_rendersettings.py | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/nuke/api/lib_rendersettings.py b/openpype/hosts/nuke/api/lib_rendersettings.py index 4d5440fe483..6784890160e 100644 --- a/openpype/hosts/nuke/api/lib_rendersettings.py +++ b/openpype/hosts/nuke/api/lib_rendersettings.py @@ -12,25 +12,40 @@ class RenderFarmSettings: log = Logger.get_logger("RenderFarmSettings") _active_farm_module: str = None - _farm_modules: list = [ - "deadline", "muster", "royalrender"] + _farm_modules: list = ["deadline"] _farm_plugins: dict = { "deadline": "NukeSubmitDeadline" } _creator_farm_keys: list = [ "chunk_size", "priority", "concurrent_tasks"] + _cached_project_settings = None + _cached_system_settings = None + def __init__(self, project_settings=None, log=None): """ Get project settings and active farm module """ if log: self.log = log - self._project_settings = ( - project_settings or get_current_project_settings() - ) - # Get active farm module from system settings - self._get_active_farm_module_from_system_settings() + if project_settings: + self._cached_project_settings = project_settings + + @property + def project_settings(self): + """ returning cached project settings or getting new one + """ + if not self._cached_project_settings: + self._cached_project_settings = get_current_project_settings() + return self._cached_project_settings + + @property + def system_settings(self): + """ returning cached project settings or getting new one + """ + if not self._cached_system_settings: + self._cached_system_settings = get_system_settings() + return self._cached_system_settings def _get_active_farm_module_from_system_settings(self): """ Get active farm module from system settings @@ -38,7 +53,7 @@ def _get_active_farm_module_from_system_settings(self): active_modules = [ module_ for module_ in self._farm_modules - if get_system_settings()["modules"][module_]["enabled"] + if self.system_settings["modules"][module_]["enabled"] ] if not active_modules: raise ValueError(( @@ -54,6 +69,10 @@ def _get_active_farm_module_from_system_settings(self): @property def active_farm_module(self): + # cache active farm module + if self._active_farm_module is None: + self._get_active_farm_module_from_system_settings() + return self._active_farm_module def get_rendering_attributes(self): From 61cf3a068d5aea4daab92201540e6b33c9a0fe0a Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 24 Feb 2023 17:07:43 +0100 Subject: [PATCH 207/898] Nuke: missing bits --- openpype/hosts/nuke/api/lib_rendersettings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/nuke/api/lib_rendersettings.py b/openpype/hosts/nuke/api/lib_rendersettings.py index 6784890160e..5c23bcb1bcb 100644 --- a/openpype/hosts/nuke/api/lib_rendersettings.py +++ b/openpype/hosts/nuke/api/lib_rendersettings.py @@ -41,7 +41,7 @@ def project_settings(self): @property def system_settings(self): - """ returning cached project settings or getting new one + """ returning cached system settings or getting new one """ if not self._cached_system_settings: self._cached_system_settings = get_system_settings() @@ -91,7 +91,7 @@ def get_rendering_attributes(self): ).format(farm_plugin)) # Get farm module settings - module_settings = self._project_settings[self.active_farm_module] + module_settings = self.project_settings[self.active_farm_module] # Get farm plugin settings farm_plugin_settings = ( From 00f2e16dca2cb37a53a4a6b3096c0f11142a9b66 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Sun, 26 Feb 2023 10:23:39 +0000 Subject: [PATCH 208/898] Static implementation. --- openpype/hosts/maya/plugins/publish/collect_review.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/openpype/hosts/maya/plugins/publish/collect_review.py b/openpype/hosts/maya/plugins/publish/collect_review.py index eb872c29358..c76d4bae974 100644 --- a/openpype/hosts/maya/plugins/publish/collect_review.py +++ b/openpype/hosts/maya/plugins/publish/collect_review.py @@ -139,3 +139,13 @@ def process(self, instance): "filename": node.filename.get() } ) + + # Collect focal length. + data = { + "cameraFocalLength": cmds.getAttr(camera + ".focalLength") + } + + try: + instance.data["customData"].update(data) + except KeyError: + instance.data["customData"] = data From 557ce7c016515f15878d9c37d6a8cf6fb777be43 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 27 Feb 2023 15:08:03 +0100 Subject: [PATCH 209/898] Nuke, Deadline: moving to module plugin centric approach --- openpype/hosts/nuke/api/lib_rendersettings.py | 111 ------------------ .../plugins/create/create_write_prerender.py | 37 +----- .../plugins/create/create_write_render.py | 36 +----- .../plugins/publish/submit_nuke_deadline.py | 83 +++++++++---- 4 files changed, 61 insertions(+), 206 deletions(-) delete mode 100644 openpype/hosts/nuke/api/lib_rendersettings.py diff --git a/openpype/hosts/nuke/api/lib_rendersettings.py b/openpype/hosts/nuke/api/lib_rendersettings.py deleted file mode 100644 index 5c23bcb1bcb..00000000000 --- a/openpype/hosts/nuke/api/lib_rendersettings.py +++ /dev/null @@ -1,111 +0,0 @@ - -from openpype.lib import Logger -from openpype.settings import ( - get_current_project_settings, - get_system_settings -) - - -class RenderFarmSettings: - """ Class for getting farm settings from project settings - """ - log = Logger.get_logger("RenderFarmSettings") - - _active_farm_module: str = None - _farm_modules: list = ["deadline"] - _farm_plugins: dict = { - "deadline": "NukeSubmitDeadline" - } - _creator_farm_keys: list = [ - "chunk_size", "priority", "concurrent_tasks"] - - _cached_project_settings = None - _cached_system_settings = None - - def __init__(self, project_settings=None, log=None): - """ Get project settings and active farm module - """ - if log: - self.log = log - - if project_settings: - self._cached_project_settings = project_settings - - @property - def project_settings(self): - """ returning cached project settings or getting new one - """ - if not self._cached_project_settings: - self._cached_project_settings = get_current_project_settings() - return self._cached_project_settings - - @property - def system_settings(self): - """ returning cached system settings or getting new one - """ - if not self._cached_system_settings: - self._cached_system_settings = get_system_settings() - return self._cached_system_settings - - def _get_active_farm_module_from_system_settings(self): - """ Get active farm module from system settings - """ - active_modules = [ - module_ - for module_ in self._farm_modules - if self.system_settings["modules"][module_]["enabled"] - ] - if not active_modules: - raise ValueError(( - "No active farm module found in system settings." - )) - if len(active_modules) > 1: - raise ValueError(( - "Multiple active farm modules " - "found in system settings. {}".format(active_modules) - )) - - self._active_farm_module = active_modules.pop() - - @property - def active_farm_module(self): - # cache active farm module - if self._active_farm_module is None: - self._get_active_farm_module_from_system_settings() - - return self._active_farm_module - - def get_rendering_attributes(self): - ''' Get rendering attributes from project settings - - Returns: - dict: rendering attributes - ''' - return_dict = {} - farm_plugin = self._farm_plugins.get(self.active_farm_module) - self.log.debug("Farm plugin: \"{}\"".format(farm_plugin)) - - if not farm_plugin: - raise ValueError(( - "Farm plugin \"{}\" not found in farm plugins." - ).format(farm_plugin)) - - # Get farm module settings - module_settings = self.project_settings[self.active_farm_module] - - # Get farm plugin settings - farm_plugin_settings = ( - module_settings["publish"][farm_plugin]) - self.log.debug( - "Farm plugin settings: \"{}\"".format(farm_plugin_settings)) - - # Get all keys from farm_plugin_settings - for key in self._creator_farm_keys: - if key not in farm_plugin_settings: - self.log.warning(( - "Key \"{}\" not found in farm plugin \"{}\" settings." - ).format(key, farm_plugin)) - continue - return_dict[key] = farm_plugin_settings[key] - - return return_dict diff --git a/openpype/hosts/nuke/plugins/create/create_write_prerender.py b/openpype/hosts/nuke/plugins/create/create_write_prerender.py index 411a79dbf40..1603bf17e38 100644 --- a/openpype/hosts/nuke/plugins/create/create_write_prerender.py +++ b/openpype/hosts/nuke/plugins/create/create_write_prerender.py @@ -6,13 +6,9 @@ CreatedInstance ) from openpype.lib import ( - BoolDef, - NumberDef, - UISeparatorDef, - UILabelDef + BoolDef ) from openpype.hosts.nuke import api as napi -from openpype.hosts.nuke.api.lib_rendersettings import RenderFarmSettings class CreateWritePrerender(napi.NukeWriteCreator): @@ -50,37 +46,6 @@ def get_instance_attr_defs(self): self._get_render_target_enum(), self._get_reviewable_bool() ] - if "farm_rendering" in self.instance_attributes: - render_farm_settings = RenderFarmSettings( - log=self.log).get_rendering_attributes() - - - attr_defs.extend([ - UISeparatorDef(), - UILabelDef("Farm rendering attributes"), - BoolDef("suspended_publish", label="Suspended publishing"), - NumberDef( - "farm_priority", - label="Priority", - minimum=1, - maximum=99, - default=render_farm_settings.get("priority", 50) - ), - NumberDef( - "farm_chunk", - label="Chunk size", - minimum=1, - maximum=99, - default=render_farm_settings.get("chunk_size", 10) - ), - NumberDef( - "farm_concurrency", - label="Concurrent tasks", - minimum=1, - maximum=10, - default=render_farm_settings.get("concurrent_tasks", 1) - ) - ]) return attr_defs def create_instance_node(self, subset_name, instance_data): diff --git a/openpype/hosts/nuke/plugins/create/create_write_render.py b/openpype/hosts/nuke/plugins/create/create_write_render.py index a51661425fc..72fcb4f2322 100644 --- a/openpype/hosts/nuke/plugins/create/create_write_render.py +++ b/openpype/hosts/nuke/plugins/create/create_write_render.py @@ -6,13 +6,9 @@ CreatedInstance ) from openpype.lib import ( - BoolDef, - NumberDef, - UISeparatorDef, - UILabelDef + BoolDef ) from openpype.hosts.nuke import api as napi -from openpype.hosts.nuke.api.lib_rendersettings import RenderFarmSettings class CreateWriteRender(napi.NukeWriteCreator): @@ -47,36 +43,6 @@ def get_instance_attr_defs(self): self._get_render_target_enum(), self._get_reviewable_bool() ] - if "farm_rendering" in self.instance_attributes: - render_farm_settings = RenderFarmSettings( - log=self.log).get_rendering_attributes() - - attr_defs.extend([ - UISeparatorDef(), - UILabelDef("Farm rendering attributes"), - BoolDef("suspended_publish", label="Suspended publishing"), - NumberDef( - "farm_priority", - label="Priority", - minimum=1, - maximum=99, - default=render_farm_settings.get("priority", 50) - ), - NumberDef( - "farm_chunk", - label="Chunk size", - minimum=1, - maximum=99, - default=render_farm_settings.get("chunk_size", 10) - ), - NumberDef( - "farm_concurrency", - label="Concurrent tasks", - minimum=1, - maximum=10, - default=render_farm_settings.get("concurrent_tasks", 1) - ) - ]) return attr_defs def create_instance_node(self, subset_name, instance_data): diff --git a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py index b4b59c4c77c..51e380dc032 100644 --- a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py @@ -9,11 +9,19 @@ import nuke from openpype.pipeline import legacy_io +from openpype.pipeline.publish import ( + OpenPypePyblishPluginMixin +) from openpype.tests.lib import is_in_tests -from openpype.lib import is_running_from_build - - -class NukeSubmitDeadline(pyblish.api.InstancePlugin): +from openpype.lib import ( + is_running_from_build, + BoolDef, + NumberDef, + UISeparatorDef +) + +class NukeSubmitDeadline(pyblish.api.InstancePlugin, + OpenPypePyblishPluginMixin): """Submit write to Deadline Renders are submitted to a Deadline Web Service as @@ -21,10 +29,10 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin): """ - label = "Submit to Deadline" + label = "Submit Nuke to Deadline" order = pyblish.api.IntegratorOrder + 0.1 hosts = ["nuke"] - families = ["render.farm", "prerender.farm"] + families = ["render", "prerender.farm"] optional = True targets = ["local"] @@ -39,7 +47,42 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin): env_allowed_keys = [] env_search_replace_values = {} + @classmethod + def get_attribute_defs(cls): + return [ + NumberDef( + "priority", + label="Priority", + default=cls.priority, + decimals=0 + ), + NumberDef( + "chunk", + label="Frames Per Task", + default=cls.chunk_size, + decimals=0, + minimum=1, + maximum=1000 + ), + NumberDef( + "concurrency", + label="Concurency", + default=cls.concurrent_tasks, + decimals=0, + minimum=1, + maximum=10 + ), + BoolDef( + "use_gpu", + default=cls.use_gpu, + label="Use GPU" + ) + ] + def process(self, instance): + instance.data["attributeValues"] = self.get_attr_values_from_data( + instance.data) + instance.data["toBeRenderedOn"] = "deadline" families = instance.data["families"] @@ -161,20 +204,6 @@ def payload_submit( except OSError: pass - # define chunk and priority - chunk_size = instance.data.get("farm_chunk") - if not chunk_size: - chunk_size = self.chunk_size - - # define chunk and priority - concurrent_tasks = instance.data.get("farm_concurrency") - if not concurrent_tasks: - concurrent_tasks = self.concurrent_tasks - - priority = instance.data.get("farm_priority") - if not priority: - priority = self.priority - # resolve any limit groups limit_groups = self.get_limit_groups() self.log.info("Limit groups: `{}`".format(limit_groups)) @@ -193,9 +222,14 @@ def payload_submit( # Arbitrary username, for visualisation in Monitor "UserName": self._deadline_user, - "Priority": priority, - "ChunkSize": chunk_size, - "ConcurrentTasks": concurrent_tasks, + "Priority": instance.data["attributeValues"].get( + "priority", self.priority), + "ChunkSize": instance.data["attributeValues"].get( + "chunk", self.chunk_size), + "ConcurrentTasks": instance.data["attributeValues"].get( + "concurrency", + self.concurrent_tasks + ), "Department": self.department, @@ -234,7 +268,8 @@ def payload_submit( "AWSAssetFile0": render_path, # using GPU by default - "UseGpu": self.use_gpu, + "UseGpu": instance.data["attributeValues"].get( + "use_gpu", self.use_gpu), # Only the specific write node is rendered. "WriteNode": exe_node_name From e444ab3f5e3037cc0528a748df4f0554a597fb78 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 27 Feb 2023 15:16:27 +0100 Subject: [PATCH 210/898] hound comments --- .../modules/deadline/plugins/publish/submit_nuke_deadline.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py index 51e380dc032..aff34c7e4a8 100644 --- a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py @@ -16,10 +16,10 @@ from openpype.lib import ( is_running_from_build, BoolDef, - NumberDef, - UISeparatorDef + NumberDef ) + class NukeSubmitDeadline(pyblish.api.InstancePlugin, OpenPypePyblishPluginMixin): """Submit write to Deadline From 8a6efcd6ef9699f977e58ab8fc6042a6e8e3a0f5 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 28 Feb 2023 10:00:25 +0100 Subject: [PATCH 211/898] Nuke: new version builder from tempate wip --- .../nuke/api/workfile_template_builder.py | 3 +- .../workfile/workfile_template_builder.py | 29 ++++++++++++++++++- .../defaults/project_settings/nuke.json | 12 +++++++- .../schema_templated_workfile_build.json | 6 ++++ 4 files changed, 47 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/nuke/api/workfile_template_builder.py b/openpype/hosts/nuke/api/workfile_template_builder.py index 1b81f24e86b..739c10d56ba 100644 --- a/openpype/hosts/nuke/api/workfile_template_builder.py +++ b/openpype/hosts/nuke/api/workfile_template_builder.py @@ -1,3 +1,4 @@ +import os import collections import nuke @@ -45,7 +46,7 @@ def import_template(self, path): get_template_preset implementation) Returns: - bool: Wether the template was succesfully imported or not + bool: Wether the template was successfully imported or not """ # TODO check if the template is already imported diff --git a/openpype/pipeline/workfile/workfile_template_builder.py b/openpype/pipeline/workfile/workfile_template_builder.py index 119e4aaeb7b..6bbe5f5d13c 100644 --- a/openpype/pipeline/workfile/workfile_template_builder.py +++ b/openpype/pipeline/workfile/workfile_template_builder.py @@ -28,6 +28,7 @@ get_project_settings, get_system_settings, ) +from openpype.host import IWorkfileHost from openpype.host import HostBase from openpype.lib import ( Logger, @@ -416,7 +417,8 @@ def build_template( self, template_path=None, level_limit=None, - keep_placeholders=None + keep_placeholders=None, + create_first_version=None ): """Main callback for building workfile from template path. @@ -433,6 +435,7 @@ def build_template( keep_placeholders (bool): Add flag to placeholder data for hosts to decide if they want to remove placeholder after it is used. + create_first_version (bool): create first version of a workfile """ template_preset = self.get_template_preset() @@ -441,6 +444,11 @@ def build_template( if keep_placeholders is None: keep_placeholders = template_preset["keep_placeholder"] + if create_first_version is None: + create_first_version = template_preset["create_first_version"] + + if create_first_version: + self.create_first_workfile_version() self.import_template(template_path) self.populate_scene_placeholders( @@ -492,6 +500,25 @@ def import_template(self, template_path): pass + @abstractmethod + def create_first_workfile_version(self): + """ + Create first version of workfile. + + Should load the content of template into scene so + 'populate_scene_placeholders' can be started. + + Args: + template_path (str): Fullpath for current task and + host's template file. + """ + last_workfile_path = os.environ.get("AVALON_LAST_WORKFILE") + # Save current scene, continue to open file + if isinstance(self.host, IWorkfileHost): + self.host.save_workfile(last_workfile_path) + else: + self.host.save_file(last_workfile_path) + def _prepare_placeholders(self, placeholders): """Run preparation part for placeholders on plugins. diff --git a/openpype/settings/defaults/project_settings/nuke.json b/openpype/settings/defaults/project_settings/nuke.json index 2545411e0ad..c249955dc8d 100644 --- a/openpype/settings/defaults/project_settings/nuke.json +++ b/openpype/settings/defaults/project_settings/nuke.json @@ -565,7 +565,17 @@ ] }, "templated_workfile_build": { - "profiles": [] + "profiles": [ + { + "task_types": [ + "Compositing" + ], + "task_names": [], + "path": "{project[name]}/templates/comp.nk", + "keep_placeholder": true, + "create_first_version": true + } + ] }, "filters": {} } diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_templated_workfile_build.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_templated_workfile_build.json index b244460bbfb..7bab28fd880 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_templated_workfile_build.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_templated_workfile_build.json @@ -34,6 +34,12 @@ "label": "Keep placeholders", "type": "boolean", "default": true + }, + { + "key": "create_first_version", + "label": "Create first version", + "type": "boolean", + "default": true } ] } From 9229ff9c0b229db2d9d25c8d91b6cb6f7b58de9b Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 28 Feb 2023 13:58:01 +0100 Subject: [PATCH 212/898] hiero: fix effect item node class --- .../hosts/hiero/plugins/publish/collect_clip_effects.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/hiero/plugins/publish/collect_clip_effects.py b/openpype/hosts/hiero/plugins/publish/collect_clip_effects.py index 9489b1c4fb8..95e4b095049 100644 --- a/openpype/hosts/hiero/plugins/publish/collect_clip_effects.py +++ b/openpype/hosts/hiero/plugins/publish/collect_clip_effects.py @@ -120,13 +120,10 @@ def add_effect(self, track_index, sitem): track = sitem.parentTrack().name() # node serialization node = sitem.node() - node_serialized = self.node_serialisation(node) + node_serialized = self.node_serialization(node) node_name = sitem.name() + node_class = node.Class() - if "_" in node_name: - node_class = re.sub(r"(?:_)[_0-9]+", "", node_name) # more numbers - else: - node_class = re.sub(r"\d+", "", node_name) # one number # collect timelineIn/Out effect_t_in = int(sitem.timelineIn()) @@ -148,7 +145,7 @@ def add_effect(self, track_index, sitem): "node": node_serialized }} - def node_serialisation(self, node): + def node_serialization(self, node): node_serialized = {} # adding ignoring knob keys From 2bd4e5c3c91b453bca3b21aed3c1cfd6cf19be37 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 28 Feb 2023 14:11:01 +0100 Subject: [PATCH 213/898] hound comments --- openpype/hosts/hiero/plugins/publish/collect_clip_effects.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/hiero/plugins/publish/collect_clip_effects.py b/openpype/hosts/hiero/plugins/publish/collect_clip_effects.py index 95e4b095049..d455ad4a4ed 100644 --- a/openpype/hosts/hiero/plugins/publish/collect_clip_effects.py +++ b/openpype/hosts/hiero/plugins/publish/collect_clip_effects.py @@ -124,7 +124,6 @@ def add_effect(self, track_index, sitem): node_name = sitem.name() node_class = node.Class() - # collect timelineIn/Out effect_t_in = int(sitem.timelineIn()) effect_t_out = int(sitem.timelineOut()) From 2ed1a97864ba7c9b557b6159c03a78056d804b6f Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 28 Feb 2023 14:22:38 +0100 Subject: [PATCH 214/898] nuke: start new workfile from tempate wip --- openpype/hosts/nuke/api/lib.py | 12 ++++++++++- openpype/hosts/nuke/api/pipeline.py | 3 ++- .../nuke/api/workfile_template_builder.py | 20 +++++++++++++++++- .../workfile/workfile_template_builder.py | 21 +++++++------------ 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index c08db978d3c..2b7aaa9d70b 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -48,7 +48,6 @@ get_imageio_config ) from openpype.pipeline.workfile import BuildWorkfile - from . import gizmo_menu from .constants import ASSIST @@ -2678,6 +2677,17 @@ def process_workfile_builder(): open_file(last_workfile_path) +def start_workfile_template_builder(): + from .workfile_template_builder import ( + build_workfile_template + ) + + # to avoid looping of the callback, remove it! + # nuke.removeOnCreate(start_workfile_template_builder, nodeClass="Root") + log.info("Starting workfile template builder...") + build_workfile_template() + + @deprecated def recreate_instance(origin_node, avalon_data=None): """Recreate input instance to different data diff --git a/openpype/hosts/nuke/api/pipeline.py b/openpype/hosts/nuke/api/pipeline.py index 2496d66c1d0..30270a4e5ff 100644 --- a/openpype/hosts/nuke/api/pipeline.py +++ b/openpype/hosts/nuke/api/pipeline.py @@ -33,6 +33,7 @@ add_publish_knob, WorkfileSettings, process_workfile_builder, + start_workfile_template_builder, launch_workfiles_app, check_inventory_versions, set_avalon_knob_data, @@ -48,7 +49,6 @@ NukePlaceholderLoadPlugin, NukePlaceholderCreatePlugin, build_workfile_template, - update_workfile_template, create_placeholder, update_placeholder, ) @@ -155,6 +155,7 @@ def add_nuke_callbacks(): # Set context settings. nuke.addOnCreate( workfile_settings.set_context_settings, nodeClass="Root") + nuke.addOnCreate(start_workfile_template_builder, nodeClass="Root") nuke.addOnCreate(workfile_settings.set_favorites, nodeClass="Root") nuke.addOnCreate(process_workfile_builder, nodeClass="Root") diff --git a/openpype/hosts/nuke/api/workfile_template_builder.py b/openpype/hosts/nuke/api/workfile_template_builder.py index 739c10d56ba..1c0a41456ac 100644 --- a/openpype/hosts/nuke/api/workfile_template_builder.py +++ b/openpype/hosts/nuke/api/workfile_template_builder.py @@ -15,7 +15,7 @@ from openpype.tools.workfile_template_build import ( WorkfileBuildPlaceholderDialog, ) - +from openpype.host import IWorkfileHost from .lib import ( find_free_space_to_paste_nodes, get_extreme_positions, @@ -56,6 +56,24 @@ def import_template(self, path): return True + def create_first_workfile_version(self): + """ + Create first version of workfile. + + Should load the content of template into scene so + 'populate_scene_placeholders' can be started. + + Args: + template_path (str): Fullpath for current task and + host's template file. + """ + last_workfile_path = os.environ.get("AVALON_LAST_WORKFILE") + # Save current scene, continue to open file + if isinstance(self.host, IWorkfileHost): + self.host.save_workfile(last_workfile_path) + else: + self.host.save_file(last_workfile_path) + class NukePlaceholderPlugin(PlaceholderPlugin): node_color = 4278190335 diff --git a/openpype/pipeline/workfile/workfile_template_builder.py b/openpype/pipeline/workfile/workfile_template_builder.py index 6bbe5f5d13c..1758c30a8b4 100644 --- a/openpype/pipeline/workfile/workfile_template_builder.py +++ b/openpype/pipeline/workfile/workfile_template_builder.py @@ -505,19 +505,8 @@ def create_first_workfile_version(self): """ Create first version of workfile. - Should load the content of template into scene so - 'populate_scene_placeholders' can be started. - - Args: - template_path (str): Fullpath for current task and - host's template file. """ - last_workfile_path = os.environ.get("AVALON_LAST_WORKFILE") - # Save current scene, continue to open file - if isinstance(self.host, IWorkfileHost): - self.host.save_workfile(last_workfile_path) - else: - self.host.save_file(last_workfile_path) + pass def _prepare_placeholders(self, placeholders): """Run preparation part for placeholders on plugins. @@ -702,6 +691,8 @@ def get_template_preset(self): # switch to remove placeholders after they are used keep_placeholder = profile.get("keep_placeholder") + create_first_version = profile.get("create_first_version") + # backward compatibility, since default is True if keep_placeholder is None: keep_placeholder = True @@ -735,7 +726,8 @@ def get_template_preset(self): self.log.info("Found template at: '{}'".format(path)) return { "path": path, - "keep_placeholder": keep_placeholder + "keep_placeholder": keep_placeholder, + "create_first_version": create_first_version } solved_path = None @@ -764,7 +756,8 @@ def get_template_preset(self): return { "path": solved_path, - "keep_placeholder": keep_placeholder + "keep_placeholder": keep_placeholder, + "create_first_version": create_first_version } From 1ef786afb8c7dacfd219bdf3733a52e777082c3f Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 28 Feb 2023 14:39:12 +0100 Subject: [PATCH 215/898] added option to use new creating system in workfile template builder --- .../maya/api/workfile_template_builder.py | 2 + .../workfile/workfile_template_builder.py | 97 ++++++++++++++----- 2 files changed, 74 insertions(+), 25 deletions(-) diff --git a/openpype/hosts/maya/api/workfile_template_builder.py b/openpype/hosts/maya/api/workfile_template_builder.py index 2f550e787ac..90ab6e21e04 100644 --- a/openpype/hosts/maya/api/workfile_template_builder.py +++ b/openpype/hosts/maya/api/workfile_template_builder.py @@ -22,6 +22,8 @@ class MayaTemplateBuilder(AbstractTemplateBuilder): """Concrete implementation of AbstractTemplateBuilder for maya""" + use_legacy_creators = True + def import_template(self, path): """Import template into current scene. Block if a template is already loaded. diff --git a/openpype/pipeline/workfile/workfile_template_builder.py b/openpype/pipeline/workfile/workfile_template_builder.py index 119e4aaeb7b..0167224cb0f 100644 --- a/openpype/pipeline/workfile/workfile_template_builder.py +++ b/openpype/pipeline/workfile/workfile_template_builder.py @@ -43,7 +43,8 @@ load_with_repre_context, ) from openpype.pipeline.create import ( - discover_legacy_creator_plugins + discover_legacy_creator_plugins, + CreateContext, ) @@ -91,6 +92,7 @@ class AbstractTemplateBuilder(object): """ _log = None + use_legacy_creators = False def __init__(self, host): # Get host name @@ -110,6 +112,7 @@ def __init__(self, host): self._placeholder_plugins = None self._loaders_by_name = None self._creators_by_name = None + self._create_context = None self._system_settings = None self._project_settings = None @@ -171,6 +174,14 @@ def current_task_type(self): .get("type") ) + @property + def create_context(self): + if self._create_context is None: + self._create_context = CreateContext( + self.host, discover_publish_plugins=False + ) + return self._create_context + def get_placeholder_plugin_classes(self): """Get placeholder plugin classes that can be used to build template. @@ -235,18 +246,29 @@ def get_loaders_by_name(self): self._loaders_by_name = get_loaders_by_name() return self._loaders_by_name + def _collect_legacy_creators(self): + creators_by_name = {} + for creator in discover_legacy_creator_plugins(): + if not creator.enabled: + continue + creator_name = creator.__name__ + if creator_name in creators_by_name: + raise KeyError( + "Duplicated creator name {} !".format(creator_name) + ) + creators_by_name[creator_name] = creator + self._creators_by_name = creators_by_name + + def _collect_creators(self): + self._creators_by_name = dict(self.create_context.creators) + def get_creators_by_name(self): if self._creators_by_name is None: - self._creators_by_name = {} - for creator in discover_legacy_creator_plugins(): - if not creator.enabled: - continue - creator_name = creator.__name__ - if creator_name in self._creators_by_name: - raise KeyError( - "Duplicated creator name {} !".format(creator_name) - ) - self._creators_by_name[creator_name] = creator + if self.use_legacy_creators: + self._collect_legacy_creators() + else: + self._collect_creators() + return self._creators_by_name def get_shared_data(self, key): @@ -1579,6 +1601,8 @@ def populate_create_placeholder(self, placeholder): placeholder (PlaceholderItem): Placeholder item with information about requested publishable instance. """ + + legacy_create = self.builder.use_legacy_creators creator_name = placeholder.data["creator"] create_variant = placeholder.data["create_variant"] @@ -1589,17 +1613,28 @@ def populate_create_placeholder(self, placeholder): task_name = legacy_io.Session["AVALON_TASK"] asset_name = legacy_io.Session["AVALON_ASSET"] - # get asset id - asset_doc = get_asset_by_name(project_name, asset_name, fields=["_id"]) - assert asset_doc, "No current asset found in Session" - asset_id = asset_doc['_id'] + if legacy_create: + asset_doc = get_asset_by_name( + project_name, asset_name, fields=["_id"] + ) + assert asset_doc, "No current asset found in Session" + subset_name = creator_plugin.get_subset_name( + create_variant, + task_name, + asset_doc["_id"], + project_name + ) - subset_name = creator_plugin.get_subset_name( - create_variant, - task_name, - asset_id, - project_name - ) + else: + asset_doc = get_asset_by_name(project_name, asset_name) + assert asset_doc, "No current asset found in Session" + subset_name = creator_plugin.get_subset_name( + create_variant, + task_name, + asset_doc, + project_name, + self.builder.host_name + ) creator_data = { "creator_name": creator_name, @@ -1612,10 +1647,22 @@ def populate_create_placeholder(self, placeholder): # compile subset name from variant try: - creator_instance = creator_plugin( - subset_name, - asset_name - ).process() + if legacy_create: + creator_instance = creator_plugin( + subset_name, + asset_name + ).process() + else: + creator_instance = creator_plugin.create( + subset_name, + { + "asset": asset_doc["name"], + "task": task_name, + "family": creator_plugin.family, + "variant": create_variant + }, + {} + ) except Exception: failed = True From ee3e346c8df68515d72221bb2e3fe84ab92e9b0e Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 28 Feb 2023 14:53:49 +0100 Subject: [PATCH 216/898] Global: refactory colormanaged exctractor into plugin mixin --- .../plugins/publish/extract_render_local.py | 3 +- openpype/pipeline/publish/__init__.py | 4 +- openpype/pipeline/publish/publish_plugins.py | 42 ++++++++++--------- .../publish/extract_colorspace_data.py | 3 +- 4 files changed, 29 insertions(+), 23 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/extract_render_local.py b/openpype/hosts/nuke/plugins/publish/extract_render_local.py index b99a7a95486..4d7ade9c7a1 100644 --- a/openpype/hosts/nuke/plugins/publish/extract_render_local.py +++ b/openpype/hosts/nuke/plugins/publish/extract_render_local.py @@ -9,7 +9,8 @@ from openpype.lib import collect_frames -class NukeRenderLocal(publish.ExtractorColormanaged): +class NukeRenderLocal(publish.Extractor, + publish.ColormanagedPyblishPluginMixin): """Render the current Nuke composition locally. Extract the result of savers by starting a comp render diff --git a/openpype/pipeline/publish/__init__.py b/openpype/pipeline/publish/__init__.py index 05ba1c9c334..36252c9f3de 100644 --- a/openpype/pipeline/publish/__init__.py +++ b/openpype/pipeline/publish/__init__.py @@ -19,7 +19,7 @@ RepairContextAction, Extractor, - ExtractorColormanaged, + ColormanagedPyblishPluginMixin ) from .lib import ( @@ -64,7 +64,7 @@ "RepairContextAction", "Extractor", - "ExtractorColormanaged", + "ColormanagedPyblishPluginMixin", "get_publish_template_name", diff --git a/openpype/pipeline/publish/publish_plugins.py b/openpype/pipeline/publish/publish_plugins.py index e2ae893aa92..0142919e760 100644 --- a/openpype/pipeline/publish/publish_plugins.py +++ b/openpype/pipeline/publish/publish_plugins.py @@ -3,7 +3,7 @@ from pprint import pformat import pyblish.api from pyblish.plugin import MetaPlugin, ExplicitMetaPlugin - +from openpype.lib.transcoding import VIDEO_EXTENSIONS, IMAGE_EXTENSIONS from openpype.lib import BoolDef from .lib import ( @@ -288,24 +288,25 @@ def staging_dir(self, instance): return get_instance_staging_dir(instance) -class ExtractorColormanaged(Extractor): - """Extractor base for color managed image data. - - Each Extractor intended to export pixel data representation - should inherit from this class to allow color managed data. - Class implements "get_colorspace_settings" and - "set_representation_colorspace" functions used - for injecting colorspace data to representation data for farther - integration into db document. - +class ColormanagedPyblishPluginMixin(object): + """Mixin for colormanaged plugins. + + This class is used to set colorspace data to a publishing + representation. It contains a static method, + get_colorspace_settings, which returns config and + file rules data for the host context. + It also contains a method, set_representation_colorspace, + which sets colorspace data to the representation. + The allowed file extensions are listed in the allowed_ext variable. + he method first checks if the file extension is in + the list of allowed extensions. If it is, it then gets the + colorspace settings from the host context and gets a + matching colorspace from rules. Finally, it infuses this + data into the representation. """ - - allowed_ext = [ - "cin", "dpx", "avi", "dv", "gif", "flv", "mkv", "mov", "mpg", "mpeg", - "mp4", "m4v", "mxf", "iff", "z", "ifl", "jpeg", "jpg", "jfif", "lut", - "1dl", "exr", "pic", "png", "ppm", "pnm", "pgm", "pbm", "rla", "rpf", - "sgi", "rgba", "rgb", "bw", "tga", "tiff", "tif", "img" - ] + allowed_ext = set( + ext.lstrip(".") for ext in IMAGE_EXTENSIONS.union(VIDEO_EXTENSIONS) + ) @staticmethod def get_colorspace_settings(context): @@ -375,7 +376,10 @@ def set_representation_colorspace( ext = representation["ext"] # check extension self.log.debug("__ ext: `{}`".format(ext)) - if ext.lower() not in self.allowed_ext: + + # check if ext in lower case is in self.allowed_ext + if ext.lstrip(".").lower() not in self.allowed_ext: + self.log.debug("Extension is not in allowed extensions.") return if colorspace_settings is None: diff --git a/openpype/plugins/publish/extract_colorspace_data.py b/openpype/plugins/publish/extract_colorspace_data.py index 611fb91cbb6..363df28fb5a 100644 --- a/openpype/plugins/publish/extract_colorspace_data.py +++ b/openpype/plugins/publish/extract_colorspace_data.py @@ -2,7 +2,8 @@ from openpype.pipeline import publish -class ExtractColorspaceData(publish.ExtractorColormanaged): +class ExtractColorspaceData(publish.Extractor, + publish.ColormanagedPyblishPluginMixin): """ Inject Colorspace data to available representations. Input data: From 76f312a3ff026d04feda901b98bc0ad523e3b00b Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 28 Feb 2023 15:04:54 +0100 Subject: [PATCH 217/898] Nuke: adding colorspace to representation when rendered mode --- .../hosts/nuke/plugins/publish/collect_writes.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/collect_writes.py b/openpype/hosts/nuke/plugins/publish/collect_writes.py index 3054e5a30c5..2b741426e6f 100644 --- a/openpype/hosts/nuke/plugins/publish/collect_writes.py +++ b/openpype/hosts/nuke/plugins/publish/collect_writes.py @@ -3,9 +3,10 @@ import nuke import pyblish.api from openpype.hosts.nuke import api as napi +from openpype.pipeline import publish - -class CollectNukeWrites(pyblish.api.InstancePlugin): +class CollectNukeWrites(pyblish.api.InstancePlugin, + publish.ColormanagedPyblishPluginMixin): """Collect all write nodes.""" order = pyblish.api.CollectorOrder - 0.48 @@ -128,6 +129,12 @@ def process(self, instance): else: representation['files'] = collected_frames + # inject colorspace data + self.set_representation_colorspace( + representation, instance.context, + colorspace=colorspace + ) + instance.data["representations"].append(representation) self.log.info("Publishing rendered frames ...") @@ -147,6 +154,8 @@ def process(self, instance): # get colorspace and add to version data colorspace = napi.get_colorspace_from_node(write_node) + + # TODO: remove this when we have proper colorspace support version_data = { "colorspace": colorspace } From 9bb36864be3911b25c37c873d68ae4871fdcf57a Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 28 Feb 2023 15:05:16 +0100 Subject: [PATCH 218/898] Nuke: colorspace from node unified --- openpype/hosts/nuke/plugins/publish/extract_render_local.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/extract_render_local.py b/openpype/hosts/nuke/plugins/publish/extract_render_local.py index 4d7ade9c7a1..e5feda4cd82 100644 --- a/openpype/hosts/nuke/plugins/publish/extract_render_local.py +++ b/openpype/hosts/nuke/plugins/publish/extract_render_local.py @@ -4,7 +4,7 @@ import pyblish.api import clique import nuke - +from openpype.hosts.nuke import api as napi from openpype.pipeline import publish from openpype.lib import collect_frames @@ -86,7 +86,7 @@ def process(self, instance): ) ext = node["file_type"].value() - colorspace = node["colorspace"].value() + colorspace = napi.get_colorspace_from_node(node) if "representations" not in instance.data: instance.data["representations"] = [] From b7e99dacb8b5107a90cbdd933c6b5985dc5bbb79 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 28 Feb 2023 15:45:12 +0100 Subject: [PATCH 219/898] fix spaces --- openpype/pipeline/workfile/workfile_template_builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/pipeline/workfile/workfile_template_builder.py b/openpype/pipeline/workfile/workfile_template_builder.py index 0167224cb0f..7ef2e7378b2 100644 --- a/openpype/pipeline/workfile/workfile_template_builder.py +++ b/openpype/pipeline/workfile/workfile_template_builder.py @@ -1653,7 +1653,7 @@ def populate_create_placeholder(self, placeholder): asset_name ).process() else: - creator_instance = creator_plugin.create( + creator_instance = creator_plugin.create( subset_name, { "asset": asset_doc["name"], From 6b2c10da04cb4494d709d612ba06d9d5b7482bf4 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 28 Feb 2023 16:51:18 +0100 Subject: [PATCH 220/898] use 'create' method on create context to trigger creation --- .../pipeline/workfile/workfile_template_builder.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/openpype/pipeline/workfile/workfile_template_builder.py b/openpype/pipeline/workfile/workfile_template_builder.py index 7ef2e7378b2..26735d77d05 100644 --- a/openpype/pipeline/workfile/workfile_template_builder.py +++ b/openpype/pipeline/workfile/workfile_template_builder.py @@ -1653,15 +1653,11 @@ def populate_create_placeholder(self, placeholder): asset_name ).process() else: - creator_instance = creator_plugin.create( - subset_name, - { - "asset": asset_doc["name"], - "task": task_name, - "family": creator_plugin.family, - "variant": create_variant - }, - {} + creator_instance = self.create_context.create( + creator_plugin.identifier, + create_variant, + asset_doc, + task_name=task_name ) except Exception: From 9acf634d1363d08a580bc8341f45419f2effe721 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 28 Feb 2023 17:09:43 +0100 Subject: [PATCH 221/898] fix attribute access --- openpype/pipeline/workfile/workfile_template_builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/pipeline/workfile/workfile_template_builder.py b/openpype/pipeline/workfile/workfile_template_builder.py index 26735d77d05..6ffe0116e50 100644 --- a/openpype/pipeline/workfile/workfile_template_builder.py +++ b/openpype/pipeline/workfile/workfile_template_builder.py @@ -1653,7 +1653,7 @@ def populate_create_placeholder(self, placeholder): asset_name ).process() else: - creator_instance = self.create_context.create( + creator_instance = self.builder.create_context.create( creator_plugin.identifier, create_variant, asset_doc, From 7c90b6616d50d8106dd6be0811af372d0e5b486c Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 28 Feb 2023 17:32:49 +0100 Subject: [PATCH 222/898] adding headless to creators and workfile builder abstraction --- openpype/hosts/nuke/api/plugin.py | 6 +++++- openpype/hosts/nuke/plugins/create/create_write_image.py | 2 +- .../hosts/nuke/plugins/create/create_write_prerender.py | 2 +- openpype/hosts/nuke/plugins/create/create_write_render.py | 2 +- openpype/pipeline/workfile/workfile_template_builder.py | 6 ++++-- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/nuke/api/plugin.py b/openpype/hosts/nuke/api/plugin.py index 160ca820a47..9518598238e 100644 --- a/openpype/hosts/nuke/api/plugin.py +++ b/openpype/hosts/nuke/api/plugin.py @@ -239,7 +239,11 @@ def remove_instances(self, instances): def get_pre_create_attr_defs(self): return [ - BoolDef("use_selection", label="Use selection") + BoolDef( + "use_selection", + default=not self.create_context.headless, + label="Use selection" + ) ] def get_creator_settings(self, project_settings, settings_key=None): diff --git a/openpype/hosts/nuke/plugins/create/create_write_image.py b/openpype/hosts/nuke/plugins/create/create_write_image.py index 1e23b3ad7f9..d38253ab2f3 100644 --- a/openpype/hosts/nuke/plugins/create/create_write_image.py +++ b/openpype/hosts/nuke/plugins/create/create_write_image.py @@ -35,7 +35,7 @@ def get_pre_create_attr_defs(self): attr_defs = [ BoolDef( "use_selection", - default=True, + default=not self.create_context.headless, label="Use selection" ), self._get_render_target_enum(), diff --git a/openpype/hosts/nuke/plugins/create/create_write_prerender.py b/openpype/hosts/nuke/plugins/create/create_write_prerender.py index a15f362dd11..d0d7f8edfd2 100644 --- a/openpype/hosts/nuke/plugins/create/create_write_prerender.py +++ b/openpype/hosts/nuke/plugins/create/create_write_prerender.py @@ -37,7 +37,7 @@ def get_pre_create_attr_defs(self): attr_defs = [ BoolDef( "use_selection", - default=True, + default=not self.create_context.headless, label="Use selection" ), self._get_render_target_enum() diff --git a/openpype/hosts/nuke/plugins/create/create_write_render.py b/openpype/hosts/nuke/plugins/create/create_write_render.py index 481d1d22016..4e0b42361d6 100644 --- a/openpype/hosts/nuke/plugins/create/create_write_render.py +++ b/openpype/hosts/nuke/plugins/create/create_write_render.py @@ -34,7 +34,7 @@ def get_pre_create_attr_defs(self): attr_defs = [ BoolDef( "use_selection", - default=True, + default=not self.create_context.headless, label="Use selection" ), self._get_render_target_enum() diff --git a/openpype/pipeline/workfile/workfile_template_builder.py b/openpype/pipeline/workfile/workfile_template_builder.py index 6ffe0116e50..6a99314f48a 100644 --- a/openpype/pipeline/workfile/workfile_template_builder.py +++ b/openpype/pipeline/workfile/workfile_template_builder.py @@ -178,7 +178,9 @@ def current_task_type(self): def create_context(self): if self._create_context is None: self._create_context = CreateContext( - self.host, discover_publish_plugins=False + self.host, + discover_publish_plugins=False, + headless=True ) return self._create_context @@ -1660,7 +1662,7 @@ def populate_create_placeholder(self, placeholder): task_name=task_name ) - except Exception: + except: failed = True self.create_failed(placeholder, creator_data) From 6885357c75246e4851aade1ae3261ea89f3a9658 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 28 Feb 2023 18:14:46 +0000 Subject: [PATCH 223/898] Fix broken review publishing. --- .../maya/plugins/publish/extract_playblast.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_playblast.py b/openpype/hosts/maya/plugins/publish/extract_playblast.py index 1966ad7b669..7b9e4214b90 100644 --- a/openpype/hosts/maya/plugins/publish/extract_playblast.py +++ b/openpype/hosts/maya/plugins/publish/extract_playblast.py @@ -118,7 +118,7 @@ def process(self, instance): # Need to explicitly enable some viewport changes so the viewport is # refreshed ahead of playblasting. - panel = cmds.getPanel(withFocus=True) + panel = cmds.getPanel(withFocus=True) or "" keys = [ "useDefaultMaterial", "wireframeOnShaded", @@ -127,12 +127,13 @@ def process(self, instance): "backfaceCulling" ] viewport_defaults = {} - for key in keys: - viewport_defaults[key] = cmds.modelEditor( - panel, query=True, **{key: True} - ) - if preset["viewport_options"][key]: - cmds.modelEditor(panel, edit=True, **{key: True}) + if panel and "modelPanel" in panel: + for key in keys: + viewport_defaults[key] = cmds.modelEditor( + panel, query=True, **{key: True} + ) + if preset["viewport_options"][key]: + cmds.modelEditor(panel, edit=True, **{key: True}) override_viewport_options = ( capture_presets['Viewport Options']['override_viewport_options'] @@ -163,7 +164,8 @@ def process(self, instance): path = capture.capture(log=self.log, **preset) # Restoring viewport options. - cmds.modelEditor(panel, edit=True, **viewport_defaults) + if viewport_defaults: + cmds.modelEditor(panel, edit=True, **viewport_defaults) cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), pan_zoom) From ab22f503c9542d002d22f162b76489caa7fe90ca Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 1 Mar 2023 08:06:05 +0000 Subject: [PATCH 224/898] Fix panel issues. --- .../maya/plugins/publish/collect_review.py | 3 +++ .../maya/plugins/publish/extract_playblast.py | 24 +++++++++---------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_review.py b/openpype/hosts/maya/plugins/publish/collect_review.py index eb872c29358..65ff7cf0fef 100644 --- a/openpype/hosts/maya/plugins/publish/collect_review.py +++ b/openpype/hosts/maya/plugins/publish/collect_review.py @@ -23,6 +23,9 @@ def process(self, instance): task = legacy_io.Session["AVALON_TASK"] + # Get panel. + instance.data["panel"] = cmds.playblast(activeEditor=True) + # get cameras members = instance.data['setMembers'] cameras = cmds.ls(members, long=True, diff --git a/openpype/hosts/maya/plugins/publish/extract_playblast.py b/openpype/hosts/maya/plugins/publish/extract_playblast.py index 7b9e4214b90..94571ff7312 100644 --- a/openpype/hosts/maya/plugins/publish/extract_playblast.py +++ b/openpype/hosts/maya/plugins/publish/extract_playblast.py @@ -118,7 +118,6 @@ def process(self, instance): # Need to explicitly enable some viewport changes so the viewport is # refreshed ahead of playblasting. - panel = cmds.getPanel(withFocus=True) or "" keys = [ "useDefaultMaterial", "wireframeOnShaded", @@ -127,13 +126,14 @@ def process(self, instance): "backfaceCulling" ] viewport_defaults = {} - if panel and "modelPanel" in panel: - for key in keys: - viewport_defaults[key] = cmds.modelEditor( - panel, query=True, **{key: True} + for key in keys: + viewport_defaults[key] = cmds.modelEditor( + instance.data["panel"], query=True, **{key: True} + ) + if preset["viewport_options"][key]: + cmds.modelEditor( + instance.data["panel"], edit=True, **{key: True} ) - if preset["viewport_options"][key]: - cmds.modelEditor(panel, edit=True, **{key: True}) override_viewport_options = ( capture_presets['Viewport Options']['override_viewport_options'] @@ -148,12 +148,10 @@ def process(self, instance): # Update preset with current panel setting # if override_viewport_options is turned off - panel = cmds.getPanel(withFocus=True) or "" - if not override_viewport_options and "modelPanel" in panel: - panel_preset = capture.parse_active_view() + if not override_viewport_options: + panel_preset = capture.parse_view(instance.data["panel"]) panel_preset.pop("camera") preset.update(panel_preset) - cmds.setFocus(panel) self.log.info( "Using preset:\n{}".format( @@ -165,7 +163,9 @@ def process(self, instance): # Restoring viewport options. if viewport_defaults: - cmds.modelEditor(panel, edit=True, **viewport_defaults) + cmds.modelEditor( + instance.data["panel"], edit=True, **viewport_defaults + ) cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), pan_zoom) From d770547c292b2f286d5ba32ee851c336c4a4fe4a Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 1 Mar 2023 12:21:07 +0000 Subject: [PATCH 225/898] Get all descendents in collector. - refactor common code to lib. --- openpype/hosts/maya/api/lib.py | 41 +++++++++++++++++- .../publish/collect_arnold_scene_source.py | 11 +++-- .../maya/plugins/publish/collect_instances.py | 42 +------------------ .../publish/validate_arnold_scene_source.py | 3 -- .../validate_arnold_scene_source_cbid.py | 3 -- 5 files changed, 48 insertions(+), 52 deletions(-) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index 4324d321dc0..7e8bb5439fd 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -4,7 +4,6 @@ import sys import platform import uuid -import math import re import json @@ -3562,3 +3561,43 @@ def get_color_management_output_transform(): if preferences["output_transform_enabled"]: colorspace = preferences["output_transform"] return colorspace + + +def get_all_children(nodes): + """Return all children of `nodes` including each instanced child. + Using maya.cmds.listRelatives(allDescendents=True) includes only the first + instance. As such, this function acts as an optimal replacement with a + focus on a fast query. + + """ + + sel = OpenMaya.MSelectionList() + traversed = set() + iterator = OpenMaya.MItDag(OpenMaya.MItDag.kDepthFirst) + for node in nodes: + + if node in traversed: + # Ignore if already processed as a child + # before + continue + + sel.clear() + sel.add(node) + dag = sel.getDagPath(0) + + iterator.reset(dag) + # ignore self + iterator.next() # noqa: B305 + while not iterator.isDone(): + + path = iterator.fullPathName() + + if path in traversed: + iterator.prune() + iterator.next() # noqa: B305 + continue + + traversed.add(path) + iterator.next() # noqa: B305 + + return list(traversed) diff --git a/openpype/hosts/maya/plugins/publish/collect_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/collect_arnold_scene_source.py index 0415808b7ae..fd4993d09ea 100644 --- a/openpype/hosts/maya/plugins/publish/collect_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/collect_arnold_scene_source.py @@ -1,6 +1,7 @@ from maya import cmds import pyblish.api +from openpype.hosts.maya.api.lib import get_all_children class CollectArnoldSceneSource(pyblish.api.InstancePlugin): @@ -21,11 +22,13 @@ def process(self, instance): self.log.warning("Skipped empty instance: \"%s\" " % objset) continue if objset.endswith("content_SET"): - instance.data["setMembers"] = cmds.ls(members, long=True) - self.log.debug("content members: {}".format(members)) + set_members = get_all_children(cmds.ls(members, long=True)) + instance.data["setMembers"] = set_members + self.log.debug("content members: {}".format(set_members)) elif objset.endswith("proxy_SET"): - instance.data["proxy"] = cmds.ls(members, long=True) - self.log.debug("proxy members: {}".format(members)) + set_members = get_all_children(cmds.ls(members, long=True)) + instance.data["proxy"] = set_members + self.log.debug("proxy members: {}".format(set_members)) # Use camera in object set if present else default to render globals # camera. diff --git a/openpype/hosts/maya/plugins/publish/collect_instances.py b/openpype/hosts/maya/plugins/publish/collect_instances.py index 6c6819f0a24..6bf07563234 100644 --- a/openpype/hosts/maya/plugins/publish/collect_instances.py +++ b/openpype/hosts/maya/plugins/publish/collect_instances.py @@ -1,48 +1,8 @@ from maya import cmds -import maya.api.OpenMaya as om import pyblish.api import json - - -def get_all_children(nodes): - """Return all children of `nodes` including each instanced child. - Using maya.cmds.listRelatives(allDescendents=True) includes only the first - instance. As such, this function acts as an optimal replacement with a - focus on a fast query. - - """ - - sel = om.MSelectionList() - traversed = set() - iterator = om.MItDag(om.MItDag.kDepthFirst) - for node in nodes: - - if node in traversed: - # Ignore if already processed as a child - # before - continue - - sel.clear() - sel.add(node) - dag = sel.getDagPath(0) - - iterator.reset(dag) - # ignore self - iterator.next() # noqa: B305 - while not iterator.isDone(): - - path = iterator.fullPathName() - - if path in traversed: - iterator.prune() - iterator.next() # noqa: B305 - continue - - traversed.add(path) - iterator.next() # noqa: B305 - - return list(traversed) +from openpype.hosts.maya.api.lib import get_all_children class CollectInstances(pyblish.api.ContextPlugin): diff --git a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py index 84240e63e66..e582560e123 100644 --- a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py @@ -36,9 +36,6 @@ def _get_nodes_data(self, nodes): parents.append(parent) nodes_by_name[node_split[-1].split(":")[-1]] = node - for shape in cmds.listRelatives(node, shapes=True): - basename = shape.split("|")[-1].split(":")[-1] - nodes_by_name[basename] = node + "|" + shape return ungrouped_nodes, nodes_by_name, parents diff --git a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py index 056cc94edfd..5d0ef798383 100644 --- a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py +++ b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py @@ -24,9 +24,6 @@ def _get_nodes_data(nodes): for node in nodes: node_split = node.split("|") nodes_by_name[node_split[-1].split(":")[-1]] = node - for shape in cmds.listRelatives(node, shapes=True): - basename = shape.split("|")[-1].split(":")[-1] - nodes_by_name[basename] = node + "|" + shape return nodes_by_name From 4f94a4454ab254018c189c8aa53c21fb12b1392d Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 1 Mar 2023 16:02:12 +0000 Subject: [PATCH 226/898] Only run Maya specific code in Maya. --- .../plugins/publish/submit_publish_job.py | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_publish_job.py b/openpype/modules/deadline/plugins/publish/submit_publish_job.py index 5325715e383..29f6f406dfd 100644 --- a/openpype/modules/deadline/plugins/publish/submit_publish_job.py +++ b/openpype/modules/deadline/plugins/publish/submit_publish_job.py @@ -933,15 +933,18 @@ def process(self, instance): self.log.info(data.get("expectedFiles")) - additional_data = { - "renderProducts": instance.data["renderProducts"], - "colorspaceConfig": instance.data["colorspaceConfig"], - "display": instance.data["colorspaceDisplay"], - "view": instance.data["colorspaceView"], - "colorspaceTemplate": instance.data["colorspaceConfig"].replace( - str(context.data["anatomy"].roots["work"]), "{root[work]}" - ) - } + additional_data = {} + if pyblish.api.current_host() == "maya": + config = instance.data["colorspaceConfig"] + additional_data = { + "renderProducts": instance.data["renderProducts"], + "colorspaceConfig": instance.data["colorspaceConfig"], + "display": instance.data["colorspaceDisplay"], + "view": instance.data["colorspaceView"], + "colorspaceTemplate": config.replace( + str(context.data["anatomy"].roots["work"]), "{root[work]}" + ) + } if isinstance(data.get("expectedFiles")[0], dict): # we cannot attach AOVs to other subsets as we consider every From 491eb3e75010d2f5214385145d05120ce736f93f Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 1 Mar 2023 17:27:16 +0100 Subject: [PATCH 227/898] create first workfile version function to global abstraction --- openpype/hosts/nuke/api/lib.py | 2 +- .../nuke/api/workfile_template_builder.py | 22 +---------- .../workfile/workfile_template_builder.py | 39 ++++++++++++++++--- 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index 2b7aaa9d70b..cd31e426902 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -2685,7 +2685,7 @@ def start_workfile_template_builder(): # to avoid looping of the callback, remove it! # nuke.removeOnCreate(start_workfile_template_builder, nodeClass="Root") log.info("Starting workfile template builder...") - build_workfile_template() + build_workfile_template(run_from_callback=True) @deprecated diff --git a/openpype/hosts/nuke/api/workfile_template_builder.py b/openpype/hosts/nuke/api/workfile_template_builder.py index 1c0a41456ac..80db0d160c4 100644 --- a/openpype/hosts/nuke/api/workfile_template_builder.py +++ b/openpype/hosts/nuke/api/workfile_template_builder.py @@ -56,24 +56,6 @@ def import_template(self, path): return True - def create_first_workfile_version(self): - """ - Create first version of workfile. - - Should load the content of template into scene so - 'populate_scene_placeholders' can be started. - - Args: - template_path (str): Fullpath for current task and - host's template file. - """ - last_workfile_path = os.environ.get("AVALON_LAST_WORKFILE") - # Save current scene, continue to open file - if isinstance(self.host, IWorkfileHost): - self.host.save_workfile(last_workfile_path) - else: - self.host.save_file(last_workfile_path) - class NukePlaceholderPlugin(PlaceholderPlugin): node_color = 4278190335 @@ -966,9 +948,9 @@ def _set_copies_connections(self, placeholder, copies): siblings_input.setInput(0, copy_output) -def build_workfile_template(*args): +def build_workfile_template(*args, **kwargs): builder = NukeTemplateBuilder(registered_host()) - builder.build_template() + builder.build_template(*args, **kwargs) def update_workfile_template(*args): diff --git a/openpype/pipeline/workfile/workfile_template_builder.py b/openpype/pipeline/workfile/workfile_template_builder.py index 3dd02ea14d6..d73168194e1 100644 --- a/openpype/pipeline/workfile/workfile_template_builder.py +++ b/openpype/pipeline/workfile/workfile_template_builder.py @@ -442,7 +442,8 @@ def build_template( template_path=None, level_limit=None, keep_placeholders=None, - create_first_version=None + create_first_version=None, + run_from_callback=False ): """Main callback for building workfile from template path. @@ -460,6 +461,9 @@ def build_template( hosts to decide if they want to remove placeholder after it is used. create_first_version (bool): create first version of a workfile + run_from_callback (bool): If True, it might create first version + but ignore process if version is created + """ template_preset = self.get_template_preset() @@ -471,8 +475,14 @@ def build_template( if create_first_version is None: create_first_version = template_preset["create_first_version"] - if create_first_version: - self.create_first_workfile_version() + # run creation of first version only if it is + # run from callback and no new version is created + first_creation = False + if create_first_version and run_from_callback: + first_creation = not self.create_first_workfile_version() + + if first_creation: + return self.import_template(template_path) self.populate_scene_placeholders( @@ -524,13 +534,32 @@ def import_template(self, template_path): pass - @abstractmethod def create_first_workfile_version(self): """ Create first version of workfile. + Should load the content of template into scene so + 'populate_scene_placeholders' can be started. + + Args: + template_path (str): Fullpath for current task and + host's template file. """ - pass + last_workfile_path = os.environ.get("AVALON_LAST_WORKFILE") + if os.path.exists(last_workfile_path): + # ignore in case workfile existence + self.log.info("Workfile already exists, skipping creation.") + return False + + # Save current scene, continue to open file + if isinstance(self.host, IWorkfileHost): + self.host.save_workfile(last_workfile_path) + else: + self.host.save_file(last_workfile_path) + + # Confirm creation of first version + return True + def _prepare_placeholders(self, placeholders): """Run preparation part for placeholders on plugins. From e1fa9f7c3133c359475dd15145b405406aada8f5 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 1 Mar 2023 17:30:31 +0100 Subject: [PATCH 228/898] adding noqa for hound --- openpype/pipeline/workfile/workfile_template_builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/pipeline/workfile/workfile_template_builder.py b/openpype/pipeline/workfile/workfile_template_builder.py index 6a99314f48a..2d768d216ff 100644 --- a/openpype/pipeline/workfile/workfile_template_builder.py +++ b/openpype/pipeline/workfile/workfile_template_builder.py @@ -1662,7 +1662,7 @@ def populate_create_placeholder(self, placeholder): task_name=task_name ) - except: + except: # noqa: E722 failed = True self.create_failed(placeholder, creator_data) From 2e83019efa4d2831e5299f33bb4052e263341949 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 1 Mar 2023 17:31:45 +0100 Subject: [PATCH 229/898] hound --- openpype/pipeline/workfile/workfile_template_builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/pipeline/workfile/workfile_template_builder.py b/openpype/pipeline/workfile/workfile_template_builder.py index 2d768d216ff..27214af79f6 100644 --- a/openpype/pipeline/workfile/workfile_template_builder.py +++ b/openpype/pipeline/workfile/workfile_template_builder.py @@ -1662,7 +1662,7 @@ def populate_create_placeholder(self, placeholder): task_name=task_name ) - except: # noqa: E722 + except: # noqa: E722 failed = True self.create_failed(placeholder, creator_data) From a3508b14122d6ab884a4303d636bdf37b35ca973 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 2 Mar 2023 08:18:47 +0000 Subject: [PATCH 230/898] Fix _get_representations --- openpype/modules/deadline/plugins/publish/submit_publish_job.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_publish_job.py b/openpype/modules/deadline/plugins/publish/submit_publish_job.py index 29f6f406dfd..adfbcbded88 100644 --- a/openpype/modules/deadline/plugins/publish/submit_publish_job.py +++ b/openpype/modules/deadline/plugins/publish/submit_publish_job.py @@ -588,7 +588,7 @@ def _create_instances_for_aov( self.log.debug("instances:{}".format(instances)) return instances - def _get_representations(self, instance, exp_files, additional_data): + def _get_representations(self, instance, exp_files): """Create representations for file sequences. This will return representations of expected files if they are not From 5bb204cacbfd0f9769f2f4112e50f6e65b4a7f6e Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 2 Mar 2023 11:30:42 +0100 Subject: [PATCH 231/898] nuke flip order --- openpype/hosts/nuke/plugins/publish/collect_writes.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/collect_writes.py b/openpype/hosts/nuke/plugins/publish/collect_writes.py index 2b741426e6f..f6acd24f991 100644 --- a/openpype/hosts/nuke/plugins/publish/collect_writes.py +++ b/openpype/hosts/nuke/plugins/publish/collect_writes.py @@ -67,6 +67,9 @@ def process(self, instance): write_file_path = nuke.filename(write_node) output_dir = os.path.dirname(write_file_path) + # get colorspace and add to version data + colorspace = napi.get_colorspace_from_node(write_node) + self.log.debug('output dir: {}'.format(output_dir)) if render_target == "frames": @@ -152,9 +155,6 @@ def process(self, instance): instance.data["farm"] = True self.log.info("Farm rendering ON ...") - # get colorspace and add to version data - colorspace = napi.get_colorspace_from_node(write_node) - # TODO: remove this when we have proper colorspace support version_data = { "colorspace": colorspace From f0997710818d3ca2f5ece87aed242ddf4c139a6c Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 2 Mar 2023 11:36:17 +0100 Subject: [PATCH 232/898] hound --- openpype/hosts/nuke/plugins/publish/collect_writes.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/nuke/plugins/publish/collect_writes.py b/openpype/hosts/nuke/plugins/publish/collect_writes.py index f6acd24f991..858fa79a4bc 100644 --- a/openpype/hosts/nuke/plugins/publish/collect_writes.py +++ b/openpype/hosts/nuke/plugins/publish/collect_writes.py @@ -5,6 +5,7 @@ from openpype.hosts.nuke import api as napi from openpype.pipeline import publish + class CollectNukeWrites(pyblish.api.InstancePlugin, publish.ColormanagedPyblishPluginMixin): """Collect all write nodes.""" From 91685e3d1fd3b43677fc33a537c3d93a5e8920cb Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 2 Mar 2023 11:06:47 +0000 Subject: [PATCH 233/898] Move AOV code to host agnostic. --- .../deadline/plugins/publish/submit_publish_job.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_publish_job.py b/openpype/modules/deadline/plugins/publish/submit_publish_job.py index adfbcbded88..31df4746bad 100644 --- a/openpype/modules/deadline/plugins/publish/submit_publish_job.py +++ b/openpype/modules/deadline/plugins/publish/submit_publish_job.py @@ -933,8 +933,10 @@ def process(self, instance): self.log.info(data.get("expectedFiles")) - additional_data = {} - if pyblish.api.current_host() == "maya": + if isinstance(data.get("expectedFiles")[0], dict): + # we cannot attach AOVs to other subsets as we consider every + # AOV subset of its own. + config = instance.data["colorspaceConfig"] additional_data = { "renderProducts": instance.data["renderProducts"], @@ -946,10 +948,6 @@ def process(self, instance): ) } - if isinstance(data.get("expectedFiles")[0], dict): - # we cannot attach AOVs to other subsets as we consider every - # AOV subset of its own. - if len(data.get("attachTo")) > 0: assert len(data.get("expectedFiles")[0].keys()) == 1, ( "attaching multiple AOVs or renderable cameras to " From 59cea8c7d070bfe1b757d5f12be96c8f4d1e9a47 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 2 Mar 2023 12:15:37 +0100 Subject: [PATCH 234/898] Catch for each instance whether the render succeeded or not --- .../fusion/plugins/publish/render_local.py | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/render_local.py b/openpype/hosts/fusion/plugins/publish/render_local.py index c22074d6c63..27bd3120486 100644 --- a/openpype/hosts/fusion/plugins/publish/render_local.py +++ b/openpype/hosts/fusion/plugins/publish/render_local.py @@ -59,24 +59,27 @@ def render_once(self, context): # to speed up the rendering. The check below makes sure that we only # execute the rendering once and not for each instance. key = f"__hasRun{self.__class__.__name__}" - if context.data.get(key, False): - return - context.data[key] = True - - current_comp = context.data["currentComp"] - frame_start = context.data["frameStartHandle"] - frame_end = context.data["frameEndHandle"] - - self.log.info("Starting render") - self.log.info(f"Start frame: {frame_start}") - self.log.info(f"End frame: {frame_end}") - - with comp_lock_and_undo_chunk(current_comp): - result = current_comp.Render({ - "Start": frame_start, - "End": frame_end, - "Wait": True - }) - - if not result: + if key not in context.data: + # We initialize as false to indicate it wasn't successful yet + # so we can keep track of whether Fusion succeeded + context.data[key] = False + + current_comp = context.data["currentComp"] + frame_start = context.data["frameStartHandle"] + frame_end = context.data["frameEndHandle"] + + self.log.info("Starting Fusion render") + self.log.info(f"Start frame: {frame_start}") + self.log.info(f"End frame: {frame_end}") + + with comp_lock_and_undo_chunk(current_comp): + result = current_comp.Render({ + "Start": frame_start, + "End": frame_end, + "Wait": True + }) + + context.data[key] = bool(result) + + if context.data[key] is False: raise RuntimeError("Comp render failed") From 185623ff702a3ddc58038a4368e69e5b3ce4cc94 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 24 Feb 2023 16:21:00 +0000 Subject: [PATCH 235/898] Set frame range with handles on review instance. --- openpype/hosts/maya/api/lib.py | 32 +++++++++++++------ .../maya/plugins/create/create_review.py | 6 ++-- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index 4324d321dc0..0d9733fcf7c 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -4,7 +4,6 @@ import sys import platform import uuid -import math import re import json @@ -2064,13 +2063,8 @@ def set_scene_resolution(width, height, pixelAspect): cmds.setAttr("%s.pixelAspect" % control_node, pixelAspect) -def reset_frame_range(): - """Set frame range to current asset""" - - fps = convert_to_maya_fps( - float(legacy_io.Session.get("AVALON_FPS", 25)) - ) - set_scene_fps(fps) +def get_frame_range(): + """Get the current assets frame range and handles.""" # Set frame start/end project_name = legacy_io.active_project() @@ -2097,8 +2091,26 @@ def reset_frame_range(): if handle_end is None: handle_end = handles - frame_start -= int(handle_start) - frame_end += int(handle_end) + return { + "frameStart": frame_start, + "frameEnd": frame_end, + "handleStart": handle_start, + "handleEnd": handle_end + } + + +def reset_frame_range(): + """Set frame range to current asset""" + + fps = convert_to_maya_fps( + float(legacy_io.Session.get("AVALON_FPS", 25)) + ) + set_scene_fps(fps) + + frame_range = get_frame_range() + + frame_start = frame_range["frameStart"] - int(frame_range["handleStart"]) + frame_end = frame_range["frameEnd"] + int(frame_range["handleEnd"]) cmds.playbackOptions(minTime=frame_start) cmds.playbackOptions(maxTime=frame_end) diff --git a/openpype/hosts/maya/plugins/create/create_review.py b/openpype/hosts/maya/plugins/create/create_review.py index ba51ffa0093..6e0bd2e4c36 100644 --- a/openpype/hosts/maya/plugins/create/create_review.py +++ b/openpype/hosts/maya/plugins/create/create_review.py @@ -28,13 +28,13 @@ class CreateReview(plugin.Creator): def __init__(self, *args, **kwargs): super(CreateReview, self).__init__(*args, **kwargs) + data = OrderedDict(**self.data) # get basic animation data : start / end / handles / steps - data = OrderedDict(**self.data) - animation_data = lib.collect_animation_data(fps=True) - for key, value in animation_data.items(): + for key, value in lib.get_frame_range().items(): data[key] = value + data["fps"] = lib.collect_animation_data(fps=True)["fps"] data["review_width"] = self.Width data["review_height"] = self.Height data["isolate"] = self.isolate From db0a3554b62afcfc03a8a33563e20a9a935bef22 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 24 Feb 2023 16:42:01 +0000 Subject: [PATCH 236/898] Validate frame range on instance to asset. - frame start - frame end - handle start - handle end --- .../plugins/publish/validate_frame_range.py | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_frame_range.py b/openpype/hosts/maya/plugins/publish/validate_frame_range.py index d86925184ed..dbf856a30a6 100644 --- a/openpype/hosts/maya/plugins/publish/validate_frame_range.py +++ b/openpype/hosts/maya/plugins/publish/validate_frame_range.py @@ -57,6 +57,10 @@ def process(self, instance): inst_start = int(instance.data.get("frameStartHandle")) inst_end = int(instance.data.get("frameEndHandle")) + inst_frame_start = int(instance.data.get("frameStart")) + inst_frame_end = int(instance.data.get("frameEnd")) + inst_handle_start = int(instance.data.get("handleStart")) + inst_handle_end = int(instance.data.get("handleEnd")) # basic sanity checks assert frame_start_handle <= frame_end_handle, ( @@ -69,7 +73,7 @@ def process(self, instance): if [ef for ef in self.exclude_families if instance.data["family"] in ef]: return - if(inst_start != frame_start_handle): + if (inst_start != frame_start_handle): errors.append("Instance start frame [ {} ] doesn't " "match the one set on instance [ {} ]: " "{}/{}/{}/{} (handle/start/end/handle)".format( @@ -78,7 +82,7 @@ def process(self, instance): handle_start, frame_start, frame_end, handle_end )) - if(inst_end != frame_end_handle): + if (inst_end != frame_end_handle): errors.append("Instance end frame [ {} ] doesn't " "match the one set on instance [ {} ]: " "{}/{}/{}/{} (handle/start/end/handle)".format( @@ -87,6 +91,19 @@ def process(self, instance): handle_start, frame_start, frame_end, handle_end )) + checks = { + "frame start": (frame_start, inst_frame_start), + "frame end": (frame_end, inst_frame_end), + "handle start": (handle_start, inst_handle_start), + "handle end": (handle_end, inst_handle_end) + } + for label, values in checks.items(): + if values[0] != values[1]: + errors.append( + "{} on instance ({}) does not match with the asset " + "({}).".format(label.title(), values[1], values[0]) + ) + for e in errors: self.log.error(e) From d33aa1cc7df5eb7ae73320693b3a9b00183b3d70 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 28 Feb 2023 07:26:50 +0000 Subject: [PATCH 237/898] Better error reports. --- openpype/hosts/maya/plugins/publish/validate_frame_range.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_frame_range.py b/openpype/hosts/maya/plugins/publish/validate_frame_range.py index dbf856a30a6..59b06874b3f 100644 --- a/openpype/hosts/maya/plugins/publish/validate_frame_range.py +++ b/openpype/hosts/maya/plugins/publish/validate_frame_range.py @@ -75,7 +75,7 @@ def process(self, instance): return if (inst_start != frame_start_handle): errors.append("Instance start frame [ {} ] doesn't " - "match the one set on instance [ {} ]: " + "match the one set on asset [ {} ]: " "{}/{}/{}/{} (handle/start/end/handle)".format( inst_start, frame_start_handle, @@ -84,7 +84,7 @@ def process(self, instance): if (inst_end != frame_end_handle): errors.append("Instance end frame [ {} ] doesn't " - "match the one set on instance [ {} ]: " + "match the one set on asset [ {} ]: " "{}/{}/{}/{} (handle/start/end/handle)".format( inst_end, frame_end_handle, From 7bbf5608711c865f3f50c82f1fbd34ddc679982a Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 28 Feb 2023 07:42:58 +0000 Subject: [PATCH 238/898] Backwards compatibility --- .../maya/plugins/create/create_review.py | 8 +++-- .../defaults/project_settings/maya.json | 13 +++++---- .../schemas/schema_maya_create.json | 29 ++++++++++++++++--- 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/openpype/hosts/maya/plugins/create/create_review.py b/openpype/hosts/maya/plugins/create/create_review.py index 6e0bd2e4c36..f1b626c06b9 100644 --- a/openpype/hosts/maya/plugins/create/create_review.py +++ b/openpype/hosts/maya/plugins/create/create_review.py @@ -25,13 +25,17 @@ class CreateReview(plugin.Creator): "depth peeling", "alpha cut" ] + useMayaTimeline = True def __init__(self, *args, **kwargs): super(CreateReview, self).__init__(*args, **kwargs) data = OrderedDict(**self.data) - # get basic animation data : start / end / handles / steps - for key, value in lib.get_frame_range().items(): + # Option for using Maya or asset frame range in settings. + frame_range = lib.get_frame_range() + if self.useMayaTimeline: + frame_range = lib.collect_animation_data(fps=True) + for key, value in frame_range.items(): data[key] = value data["fps"] = lib.collect_animation_data(fps=True)["fps"] diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index 90334a66440..dca0b952935 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -179,6 +179,13 @@ "Main" ] }, + "CreateReview": { + "enabled": true, + "defaults": [ + "Main" + ], + "useMayaTimeline": true + }, "CreateAss": { "enabled": true, "defaults": [ @@ -255,12 +262,6 @@ "Main" ] }, - "CreateReview": { - "enabled": true, - "defaults": [ - "Main" - ] - }, "CreateRig": { "enabled": true, "defaults": [ diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json index 49503cce83b..1598f906439 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json @@ -240,6 +240,31 @@ } ] }, + { + "type": "dict", + "collapsible": true, + "key": "CreateReview", + "label": "Create Review", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "list", + "key": "defaults", + "label": "Default Subsets", + "object_type": "text" + }, + { + "type": "boolean", + "key": "useMayaTimeline", + "label": "Use Maya Timeline for Frame Range." + } + ] + }, { "type": "dict", "collapsible": true, @@ -398,10 +423,6 @@ "key": "CreateRenderSetup", "label": "Create Render Setup" }, - { - "key": "CreateReview", - "label": "Create Review" - }, { "key": "CreateRig", "label": "Create Rig" From db98f65b43517c1930ab3be11f56f0fa672e5c8d Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 23 Feb 2023 16:23:21 +0000 Subject: [PATCH 239/898] Fix publish pool and secondary. --- .../modules/deadline/plugins/publish/submit_publish_job.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_publish_job.py b/openpype/modules/deadline/plugins/publish/submit_publish_job.py index 31df4746bad..53c09ad22f9 100644 --- a/openpype/modules/deadline/plugins/publish/submit_publish_job.py +++ b/openpype/modules/deadline/plugins/publish/submit_publish_job.py @@ -284,6 +284,9 @@ def _submit_deadline_post_job(self, instance, job, instances): args.append("--automatic-tests") # Generate the payload for Deadline submission + secondary_pool = ( + self.deadline_pool_secondary or instance.data.get("secondaryPool") + ) payload = { "JobInfo": { "Plugin": self.deadline_plugin, @@ -297,8 +300,8 @@ def _submit_deadline_post_job(self, instance, job, instances): "Priority": priority, "Group": self.deadline_group, - "Pool": instance.data.get("primaryPool"), - "SecondaryPool": instance.data.get("secondaryPool"), + "Pool": self.deadline_pool or instance.data.get("primaryPool"), + "SecondaryPool": secondary_pool, # ensure the outputdirectory with correct slashes "OutputDirectory0": output_dir.replace("\\", "/") }, From d827ffa8fbabd6fb02dc03e123e22d69c5b87c24 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 23 Feb 2023 16:23:38 +0000 Subject: [PATCH 240/898] Use publish pool for tile jobs. --- .../deadline/plugins/publish/submit_maya_deadline.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py index 22b5c02296f..15025e47f20 100644 --- a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py @@ -419,8 +419,13 @@ def _tile_render(self, payload): assembly_job_info.Name += " - Tile Assembly Job" assembly_job_info.Frames = 1 assembly_job_info.MachineLimit = 1 - assembly_job_info.Priority = instance.data.get("tile_priority", - self.tile_priority) + assembly_job_info.Priority = instance.data.get( + "tile_priority", self.tile_priority + ) + + pool = instance.context.data["project_settings"]["deadline"] + pool = pool["publish"]["ProcessSubmittedJobOnFarm"]["deadline_pool"] + assembly_job_info.Pool = pool or instance.data.get("primaryPool", "") assembly_plugin_info = { "CleanupTiles": 1, From 9117a0d6329c5cf47aee68bf4fd2e57dac5fff6a Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 23 Feb 2023 16:39:10 +0000 Subject: [PATCH 241/898] Documentation --- website/docs/module_deadline.md | 34 +++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/website/docs/module_deadline.md b/website/docs/module_deadline.md index c96da919097..c4b179b98d7 100644 --- a/website/docs/module_deadline.md +++ b/website/docs/module_deadline.md @@ -28,16 +28,16 @@ For [AWS Thinkbox Deadline](https://www.awsthinkbox.com/deadline) support you ne OpenPype integration for Deadline consists of two parts: - The `OpenPype` Deadline Plug-in -- A `GlobalJobPreLoad` Deadline Script (this gets triggered for each deadline job) +- A `GlobalJobPreLoad` Deadline Script (this gets triggered for each deadline job) The `GlobalJobPreLoad` handles populating render and publish jobs with proper environment variables using settings from the `OpenPype` Deadline Plug-in. -The `OpenPype` Deadline Plug-in must be configured to point to a valid OpenPype executable location. The executable need to be installed to +The `OpenPype` Deadline Plug-in must be configured to point to a valid OpenPype executable location. The executable need to be installed to destinations accessible by DL process. Check permissions (must be executable and accessible by Deadline process) - Enable `Tools > Super User Mode` in Deadline Monitor -- Go to `Tools > Configure Plugins...`, find `OpenPype` in the list on the left side, find location of OpenPype +- Go to `Tools > Configure Plugins...`, find `OpenPype` in the list on the left side, find location of OpenPype executable. It is recommended to use the `openpype_console` executable as it provides a bit more logging. - In case of multi OS farms, provide multiple locations, each Deadline Worker goes through the list and tries to find the first accessible @@ -45,12 +45,22 @@ executable. It is recommended to use the `openpype_console` executable as it pro ![Configure plugin](assets/deadline_configure_plugin.png) +### Pools + +The main pools can be configured at `project_settings/deadline/publish/CollectDeadlinePools/primary_pool`, which is applied to the rendering jobs. + +The dependent publishing job's pool uses `project_settings/deadline/publish/ProcessSubmittedJobOnFarm/deadline_pool`. If nothing is specified the pool will fallback to the main pool above. + +:::note maya tile rendering +The logic for publishing job pool assignment applies to tiling jobs. +::: + ## Troubleshooting #### Publishing jobs fail directly in DCCs - Double check that all previously described steps were finished -- Check that `deadlinewebservice` is running on DL server +- Check that `deadlinewebservice` is running on DL server - Check that user's machine has access to deadline server on configured port #### Jobs are failing on DL side @@ -61,40 +71,40 @@ Each publishing from OpenPype consists of 2 jobs, first one is rendering, second - Jobs are failing with `OpenPype executable was not found` error - Check if OpenPype is installed on the Worker handling this job and ensure `OpenPype` Deadline Plug-in is properly [configured](#configuration) + Check if OpenPype is installed on the Worker handling this job and ensure `OpenPype` Deadline Plug-in is properly [configured](#configuration) - Publishing job is failing with `ffmpeg not installed` error - + OpenPype executable has to have access to `ffmpeg` executable, check OpenPype `Setting > General` ![FFmpeg setting](assets/ffmpeg_path.png) - Both jobs finished successfully, but there is no review on Ftrack - Make sure that you correctly set published family to be send to Ftrack. + Make sure that you correctly set published family to be send to Ftrack. ![Ftrack Family](assets/ftrack/ftrack-collect-main.png) Example: I want send to Ftrack review of rendered images from Harmony : - `Host names`: "harmony" - - `Families`: "render" + - `Families`: "render" - `Add Ftrack Family` to "Enabled" - + Make sure that you actually configured to create review for published subset in `project_settings/ftrack/publish/CollectFtrackFamily` ![Ftrack Family](assets/deadline_review.png) - Example: I want to create review for all reviewable subsets in Harmony : + Example: I want to create review for all reviewable subsets in Harmony : - Add "harmony" as a new key an ".*" as a value. - Rendering jobs are stuck in 'Queued' state or failing Make sure that your Deadline is not limiting specific jobs to be run only on specific machines. (Eg. only some machines have installed particular application.) - + Check `project_settings/deadline` - + ![Deadline group](assets/deadline_group.png) Example: I have separated machines with "Harmony" installed into "harmony" group on Deadline. I want rendering jobs published from Harmony to run only on those machines. From 6f5ba9ce2a98aed1777df57731ae02409cc474a2 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 23 Feb 2023 16:42:02 +0000 Subject: [PATCH 242/898] Docs --- website/docs/module_deadline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/module_deadline.md b/website/docs/module_deadline.md index c4b179b98d7..ab1016788d2 100644 --- a/website/docs/module_deadline.md +++ b/website/docs/module_deadline.md @@ -49,7 +49,7 @@ executable. It is recommended to use the `openpype_console` executable as it pro The main pools can be configured at `project_settings/deadline/publish/CollectDeadlinePools/primary_pool`, which is applied to the rendering jobs. -The dependent publishing job's pool uses `project_settings/deadline/publish/ProcessSubmittedJobOnFarm/deadline_pool`. If nothing is specified the pool will fallback to the main pool above. +The dependent publishing job's pool uses `project_settings/deadline/publish/ProcessSubmittedJobOnFarm/deadline_pool`. If nothing is specified the pool will fallback to the primary pool above. :::note maya tile rendering The logic for publishing job pool assignment applies to tiling jobs. From b61f1ed1df5a5a6dcab162ffe320a4093b5efd12 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 28 Feb 2023 08:17:29 +0000 Subject: [PATCH 243/898] Validate against zero polygon mesh. --- .../plugins/publish/validate_mesh_empty.py | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 openpype/hosts/maya/plugins/publish/validate_mesh_empty.py diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_empty.py b/openpype/hosts/maya/plugins/publish/validate_mesh_empty.py new file mode 100644 index 00000000000..848d66c4aeb --- /dev/null +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_empty.py @@ -0,0 +1,54 @@ +from maya import cmds + +import pyblish.api +import openpype.hosts.maya.api.action +from openpype.pipeline.publish import ( + RepairAction, + ValidateMeshOrder +) + + +class ValidateMeshEmpty(pyblish.api.InstancePlugin): + """Validate meshes have some vertices. + + Its possible to have meshes without any vertices. To replicate + this issue, delete all faces/polygons then all edges. + """ + + order = ValidateMeshOrder + hosts = ["maya"] + families = ["model"] + label = "Mesh Empty" + actions = [ + openpype.hosts.maya.api.action.SelectInvalidAction, RepairAction + ] + + @classmethod + def repair(cls, instance): + invalid = cls.get_invalid(instance) + for node in invalid: + cmds.delete(node) + + @classmethod + def get_invalid(cls, instance): + invalid = [] + + meshes = cmds.ls(instance, type="mesh", long=True) + for mesh in meshes: + num_vertices = cmds.polyEvaluate(mesh, vertex=True) + + if num_vertices == 0: + cls.log.warning( + "\"{}\" does not have any vertices.".format(mesh) + ) + invalid.append(mesh) + + return invalid + + def process(self, instance): + + invalid = self.get_invalid(instance) + if invalid: + raise RuntimeError( + "Meshes found in instance without any vertices: %s" % invalid + ) From 206bf55a4909e603e845d0ca5b3fc46896f1ca90 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 28 Feb 2023 08:18:16 +0000 Subject: [PATCH 244/898] Refactor `len_flattened` --- openpype/hosts/maya/api/lib.py | 31 +++++++++++++++++ .../plugins/publish/validate_mesh_has_uv.py | 32 +---------------- .../validate_mesh_vertices_have_edges.py | 34 +------------------ 3 files changed, 33 insertions(+), 64 deletions(-) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index 0d9733fcf7c..954576f02ec 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -3574,3 +3574,34 @@ def get_color_management_output_transform(): if preferences["output_transform_enabled"]: colorspace = preferences["output_transform"] return colorspace + + +def len_flattened(components): + """Return the length of the list as if it was flattened. + + Maya will return consecutive components as a single entry + when requesting with `maya.cmds.ls` without the `flatten` + flag. Though enabling `flatten` on a large list (e.g. millions) + will result in a slow result. This command will return the amount + of entries in a non-flattened list by parsing the result with + regex. + + Args: + components (list): The non-flattened components. + + Returns: + int: The amount of entries. + + """ + assert isinstance(components, (list, tuple)) + n = 0 + + pattern = re.compile(r"\[(\d+):(\d+)\]") + for c in components: + match = pattern.search(c) + if match: + start, end = match.groups() + n += int(end) - int(start) + 1 + else: + n += 1 + return n diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_has_uv.py b/openpype/hosts/maya/plugins/publish/validate_mesh_has_uv.py index 0eece1014ed..1775bd84c6d 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_has_uv.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_has_uv.py @@ -1,39 +1,9 @@ -import re - from maya import cmds import pyblish.api import openpype.hosts.maya.api.action from openpype.pipeline.publish import ValidateMeshOrder - - -def len_flattened(components): - """Return the length of the list as if it was flattened. - - Maya will return consecutive components as a single entry - when requesting with `maya.cmds.ls` without the `flatten` - flag. Though enabling `flatten` on a large list (e.g. millions) - will result in a slow result. This command will return the amount - of entries in a non-flattened list by parsing the result with - regex. - - Args: - components (list): The non-flattened components. - - Returns: - int: The amount of entries. - - """ - assert isinstance(components, (list, tuple)) - n = 0 - for c in components: - match = re.search("\[([0-9]+):([0-9]+)\]", c) - if match: - start, end = match.groups() - n += int(end) - int(start) + 1 - else: - n += 1 - return n +from openpype.hosts.maya.api.lib import len_flattened class ValidateMeshHasUVs(pyblish.api.InstancePlugin): diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_vertices_have_edges.py b/openpype/hosts/maya/plugins/publish/validate_mesh_vertices_have_edges.py index 9ac77355014..51e1ddfc7f5 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_vertices_have_edges.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_vertices_have_edges.py @@ -1,5 +1,3 @@ -import re - from maya import cmds import pyblish.api @@ -8,37 +6,7 @@ RepairAction, ValidateMeshOrder, ) - - -def len_flattened(components): - """Return the length of the list as if it was flattened. - - Maya will return consecutive components as a single entry - when requesting with `maya.cmds.ls` without the `flatten` - flag. Though enabling `flatten` on a large list (e.g. millions) - will result in a slow result. This command will return the amount - of entries in a non-flattened list by parsing the result with - regex. - - Args: - components (list): The non-flattened components. - - Returns: - int: The amount of entries. - - """ - assert isinstance(components, (list, tuple)) - n = 0 - - pattern = re.compile(r"\[(\d+):(\d+)\]") - for c in components: - match = pattern.search(c) - if match: - start, end = match.groups() - n += int(end) - int(start) + 1 - else: - n += 1 - return n +from openpype.hosts.maya.api.lib import len_flattened class ValidateMeshVerticesHaveEdges(pyblish.api.InstancePlugin): From 63177ca7e935cd87e716229831eaf1f456825e66 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 28 Feb 2023 08:18:50 +0000 Subject: [PATCH 245/898] Only mesh empty validator should fail. --- .../plugins/publish/validate_mesh_has_uv.py | 9 +++++++++ .../publish/validate_mesh_non_zero_edge.py | 20 +++++++++++++++++-- .../validate_mesh_vertices_have_edges.py | 7 +++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_has_uv.py b/openpype/hosts/maya/plugins/publish/validate_mesh_has_uv.py index 1775bd84c6d..b7836b3e926 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_has_uv.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_has_uv.py @@ -27,6 +27,15 @@ def get_invalid(cls, instance): invalid = [] for node in cmds.ls(instance, type='mesh'): + num_vertices = cmds.polyEvaluate(node, vertex=True) + + if num_vertices == 0: + cls.log.warning( + "Skipping \"{}\", cause it does not have any " + "vertices.".format(node) + ) + continue + uv = cmds.polyEvaluate(node, uv=True) if uv == 0: diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_non_zero_edge.py b/openpype/hosts/maya/plugins/publish/validate_mesh_non_zero_edge.py index 78e844d2016..b49ba856486 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_non_zero_edge.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_non_zero_edge.py @@ -28,7 +28,10 @@ class ValidateMeshNonZeroEdgeLength(pyblish.api.InstancePlugin): @classmethod def get_invalid(cls, instance): """Return the invalid edges. - Also see: http://help.autodesk.com/view/MAYAUL/2015/ENU/?guid=Mesh__Cleanup + + Also see: + + http://help.autodesk.com/view/MAYAUL/2015/ENU/?guid=Mesh__Cleanup """ @@ -36,8 +39,21 @@ def get_invalid(cls, instance): if not meshes: return list() + valid_meshes = [] + for mesh in meshes: + num_vertices = cmds.polyEvaluate(mesh, vertex=True) + + if num_vertices == 0: + cls.log.warning( + "Skipping \"{}\", cause it does not have any " + "vertices.".format(mesh) + ) + continue + + valid_meshes.append(mesh) + # Get all edges - edges = ['{0}.e[*]'.format(node) for node in meshes] + edges = ['{0}.e[*]'.format(node) for node in valid_meshes] # Filter by constraint on edge length invalid = lib.polyConstraint(edges, diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_vertices_have_edges.py b/openpype/hosts/maya/plugins/publish/validate_mesh_vertices_have_edges.py index 51e1ddfc7f5..d8851580049 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_vertices_have_edges.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_vertices_have_edges.py @@ -55,6 +55,13 @@ def get_invalid(cls, instance): for mesh in meshes: num_vertices = cmds.polyEvaluate(mesh, vertex=True) + if num_vertices == 0: + cls.log.warning( + "Skipping \"{}\", cause it does not have any " + "vertices.".format(mesh) + ) + continue + # Vertices from all edges edges = "%s.e[*]" % mesh vertices = cmds.polyListComponentConversion(edges, toVertex=True) From 04c40b6c727fa7320360eb97dfddf5bf065095f0 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Thu, 2 Mar 2023 19:10:18 +0300 Subject: [PATCH 246/898] check if local profile folder exists, cleanup a bit --- .../hosts/fusion/hooks/pre_fusion_setup.py | 52 ++++++++++--------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index f7b5e684cbb..19d59d38063 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -17,26 +17,26 @@ class FusionPrelaunch(PreLaunchHook): as set in openpype/hosts/fusion/deploy/fusion_shared.prefs to enable the OpenPype menu and force Python 3 over Python 2. - PROFILE_NUMBER is used because from the Fusion v16 the profile folder + VERSION variable is used because from the Fusion v16 the profile folder is project-specific, but then it was abandoned by devs, - and despite it is already Fusion version 18, still FUSION16_PROFILE_DIR is used. - The variable is added in case the version number will be updated or deleted - so we could easily change the version or disable it. + and despite it is already Fusion version 18, still FUSION16_PROFILE_DIR + is used. The variable is added in case the version number will be + updated or deleted so we could easily change the version or disable it. """ app_groups = ["fusion"] - PROFILE_NUMBER = 16 + VERSION = 16 def get_fusion_profile_name(self) -> str: """usually set to 'Default', unless FUSION16_PROFILE is set""" - return os.getenv(f"FUSION{self.PROFILE_NUMBER}_PROFILE", "Default") + return os.getenv(f"FUSION{self.VERSION}_PROFILE", "Default") def get_profile_source(self) -> Path: """Get the Fusion preferences (profile) location. Check Per-User_Preferences_and_Paths on VFXpedia for reference. """ fusion_profile = self.get_fusion_profile_name() - fusion_var_prefs_dir = os.getenv(f"FUSION{self.PROFILE_NUMBER}_PROFILE_DIR") + fusion_var_prefs_dir = os.getenv(f"FUSION{self.VERSION}_PROFILE_DIR") # if FUSION16_PROFILE_DIR variable exists if fusion_var_prefs_dir and Path(fusion_var_prefs_dir).is_dir(): @@ -46,7 +46,7 @@ def get_profile_source(self) -> Path: ) return fusion_prefs_dir # otherwise get the profile folder from default location - fusion_prefs_dir = f"Blackmagic Design/Fusion/Profiles/{fusion_profile}" + fusion_prefs_dir = f"Blackmagic Design/Fusion/Profiles/{fusion_profile}" #noqa if platform.system() == "Windows": prefs_source = Path(os.getenv("AppData"), fusion_prefs_dir) elif platform.system() == "Darwin": @@ -59,7 +59,7 @@ def get_profile_source(self) -> Path: return prefs_source def get_copy_fusion_prefs_settings(self): - """Get copy prefserences options from the global application settings""" + """Get copy preferences options from the global application settings""" copy_fusion_settings = self.data["project_settings"]["fusion"].get( "copy_fusion_settings", {} ) @@ -75,9 +75,9 @@ def get_copy_fusion_prefs_settings(self): def copy_existing_prefs( self, copy_from: Path, copy_to: Path, force_sync: bool ) -> None: - """On the first Fusion launch copy the contents of Fusion profile directory - to the working predefined location. If the Openpype profile folder exists, - skip copying, unless re-sync is checked. + """On the first Fusion launch copy the contents of Fusion profile + directory to the working predefined location. If the Openpype profile + folder exists, skip copying, unless re-sync is checked. If the prefs were not copied on the first launch, clean Fusion profile will be created in fusion_profile_dir. """ @@ -89,13 +89,17 @@ def copy_existing_prefs( self.log.info(f"Starting copying Fusion preferences") self.log.info(f"force_sync option is set to {force_sync}") dest_folder = copy_to / self.get_fusion_profile_name() - dest_folder.mkdir(exist_ok=True, parents=True) + try: + dest_folder.mkdir(exist_ok=True, parents=True) + except Exception: + self.log.warn(f"Could not create folder at {dest_folder}") + return if not copy_from.exists(): - self.log.warning(f"Fusion preferences file not found in {copy_from}") + self.log.warning(f"Fusion preferences not found in {copy_from}") return for file in copy_from.iterdir(): - if file.suffix in (".prefs", ".def", ".blocklist", "fu"): - # convert Path to str to be compatible with Python 3.6 and above + if file.suffix in (".prefs", ".def", ".blocklist", ".fu"): + # convert Path to str to be compatible with Python 3.6+ shutil.copy(str(file), str(dest_folder)) self.log.info( f"successfully copied preferences:\n {copy_from} to {dest_folder}" @@ -134,26 +138,26 @@ def execute(self): # Fusion 16 and 17 use FUSION16_PYTHON36_HOME instead of # FUSION_PYTHON3_HOME and will only work with a Python 3.6 version # TODO: Detect Fusion version to only set for specific Fusion build - self.launch_context.env[f"FUSION{self.PROFILE_NUMBER}_PYTHON36_HOME"] = py3_dir + self.launch_context.env[f"FUSION{self.VERSION}_PYTHON36_HOME"] = py3_dir #noqa # Add custom Fusion Master Prefs and the temporary # profile directory variables to customize Fusion # to define where it can read custom scripts and tools from self.log.info(f"Setting OPENPYPE_FUSION: {FUSION_HOST_DIR}") self.launch_context.env["OPENPYPE_FUSION"] = FUSION_HOST_DIR - ( copy_status, fusion_profile_dir, force_sync, ) = self.get_copy_fusion_prefs_settings() - if copy_status: + if copy_status and fusion_profile_dir is not None: prefs_source = self.get_profile_source() - self.copy_existing_prefs(prefs_source, fusion_profile_dir, force_sync) - fusion_profile_dir_variable = f"FUSION{self.PROFILE_NUMBER}_PROFILE_DIR" - master_prefs_variable = f"FUSION{self.PROFILE_NUMBER}_MasterPrefs" + self.copy_existing_prefs(prefs_source, fusion_profile_dir, force_sync) #noqa + else: + fusion_profile_dir_variable = f"FUSION{self.VERSION}_PROFILE_DIR" + self.log.info(f"Setting {fusion_profile_dir_variable}: {fusion_profile_dir}") #noqa + self.launch_context.env[fusion_profile_dir_variable] = str(fusion_profile_dir) #noqa + master_prefs_variable = f"FUSION{self.VERSION}_MasterPrefs" master_prefs = Path(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") - self.log.info(f"Setting {fusion_profile_dir_variable}: {fusion_profile_dir}") - self.launch_context.env[fusion_profile_dir_variable] = str(fusion_profile_dir) self.log.info(f"Setting {master_prefs_variable}: {master_prefs}") self.launch_context.env[master_prefs_variable] = str(master_prefs) From 997351bfe2ded1e44d76f5d7bf6fecf5771c7105 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Thu, 2 Mar 2023 19:16:44 +0300 Subject: [PATCH 247/898] tame the hound --- openpype/hosts/fusion/hooks/pre_fusion_setup.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index 19d59d38063..129aadf1a57 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -46,7 +46,7 @@ def get_profile_source(self) -> Path: ) return fusion_prefs_dir # otherwise get the profile folder from default location - fusion_prefs_dir = f"Blackmagic Design/Fusion/Profiles/{fusion_profile}" #noqa + fusion_prefs_dir = f"Blackmagic Design/Fusion/Profiles/{fusion_profile}" # noqa if platform.system() == "Windows": prefs_source = Path(os.getenv("AppData"), fusion_prefs_dir) elif platform.system() == "Darwin": @@ -138,7 +138,7 @@ def execute(self): # Fusion 16 and 17 use FUSION16_PYTHON36_HOME instead of # FUSION_PYTHON3_HOME and will only work with a Python 3.6 version # TODO: Detect Fusion version to only set for specific Fusion build - self.launch_context.env[f"FUSION{self.VERSION}_PYTHON36_HOME"] = py3_dir #noqa + self.launch_context.env[f"FUSION{self.VERSION}_PYTHON36_HOME"] = py3_dir # noqa # Add custom Fusion Master Prefs and the temporary # profile directory variables to customize Fusion @@ -152,11 +152,11 @@ def execute(self): ) = self.get_copy_fusion_prefs_settings() if copy_status and fusion_profile_dir is not None: prefs_source = self.get_profile_source() - self.copy_existing_prefs(prefs_source, fusion_profile_dir, force_sync) #noqa + self.copy_existing_prefs(prefs_source, fusion_profile_dir, force_sync) # noqa else: fusion_profile_dir_variable = f"FUSION{self.VERSION}_PROFILE_DIR" - self.log.info(f"Setting {fusion_profile_dir_variable}: {fusion_profile_dir}") #noqa - self.launch_context.env[fusion_profile_dir_variable] = str(fusion_profile_dir) #noqa + self.log.info(f"Setting {fusion_profile_dir_variable}: {fusion_profile_dir}") # noqa + self.launch_context.env[fusion_profile_dir_variable] = str(fusion_profile_dir) # noqa master_prefs_variable = f"FUSION{self.VERSION}_MasterPrefs" master_prefs = Path(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") self.log.info(f"Setting {master_prefs_variable}: {master_prefs}") From ec7392433cc0386feaccca6c0c3adea47281f67c Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Thu, 2 Mar 2023 17:24:41 +0000 Subject: [PATCH 248/898] Maya: Validate missing instance attributes (#4559) * Validate missing instance attributes. * Plugins docs. --- .../maya/plugins/publish/collect_instances.py | 1 + .../publish/validate_instance_attributes.py | 60 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 openpype/hosts/maya/plugins/publish/validate_instance_attributes.py diff --git a/openpype/hosts/maya/plugins/publish/collect_instances.py b/openpype/hosts/maya/plugins/publish/collect_instances.py index 6c6819f0a24..c5946265698 100644 --- a/openpype/hosts/maya/plugins/publish/collect_instances.py +++ b/openpype/hosts/maya/plugins/publish/collect_instances.py @@ -137,6 +137,7 @@ def process(self, context): # Create the instance instance = context.create_instance(objset) instance[:] = members_hierarchy + instance.data["objset"] = objset # Store the exact members of the object set instance.data["setMembers"] = members diff --git a/openpype/hosts/maya/plugins/publish/validate_instance_attributes.py b/openpype/hosts/maya/plugins/publish/validate_instance_attributes.py new file mode 100644 index 00000000000..f870c9f8c45 --- /dev/null +++ b/openpype/hosts/maya/plugins/publish/validate_instance_attributes.py @@ -0,0 +1,60 @@ +from maya import cmds + +import pyblish.api +from openpype.pipeline.publish import ( + ValidateContentsOrder, PublishValidationError, RepairAction +) +from openpype.pipeline import discover_legacy_creator_plugins +from openpype.hosts.maya.api.lib import imprint + + +class ValidateInstanceAttributes(pyblish.api.InstancePlugin): + """Validate Instance Attributes. + + New attributes can be introduced as new features come in. Old instances + will need to be updated with these attributes for the documentation to make + sense, and users do not have to recreate the instances. + """ + + order = ValidateContentsOrder + hosts = ["maya"] + families = ["*"] + label = "Instance Attributes" + plugins_by_family = { + p.family: p for p in discover_legacy_creator_plugins() + } + actions = [RepairAction] + + @classmethod + def get_missing_attributes(self, instance): + plugin = self.plugins_by_family[instance.data["family"]] + subset = instance.data["subset"] + asset = instance.data["asset"] + objset = instance.data["objset"] + + missing_attributes = {} + for key, value in plugin(subset, asset).data.items(): + if not cmds.objExists("{}.{}".format(objset, key)): + missing_attributes[key] = value + + return missing_attributes + + def process(self, instance): + objset = instance.data.get("objset") + if objset is None: + self.log.debug( + "Skipping {} because no objectset found.".format(instance) + ) + return + + missing_attributes = self.get_missing_attributes(instance) + if missing_attributes: + raise PublishValidationError( + "Missing attributes on {}:\n{}".format( + objset, missing_attributes + ) + ) + + @classmethod + def repair(cls, instance): + imprint(instance.data["objset"], cls.get_missing_attributes(instance)) From 173ec225eba1262de024e30917673d4650feb1ee Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 3 Mar 2023 10:32:05 +0100 Subject: [PATCH 249/898] Set image format --- openpype/hosts/maya/api/lib_rendersettings.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/api/lib_rendersettings.py b/openpype/hosts/maya/api/lib_rendersettings.py index f19deb03517..7d44d4eaa62 100644 --- a/openpype/hosts/maya/api/lib_rendersettings.py +++ b/openpype/hosts/maya/api/lib_rendersettings.py @@ -336,7 +336,8 @@ def _set_vray_settings(self, aov_separator, width, height): ) # Set render file format to exr - cmds.setAttr("{}.imageFormatStr".format(node), "exr", type="string") + ext = vray_render_presets["image_format"] + cmds.setAttr("{}.imageFormatStr".format(node), ext, type="string") # animType cmds.setAttr("{}.animType".format(node), 1) From 8fcf6de8c802d78effd5e5e696aa36707f84b473 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 3 Mar 2023 12:58:00 +0100 Subject: [PATCH 250/898] Fixed hound's comments --- .../fusion/plugins/publish/render_local.py | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/render_local.py b/openpype/hosts/fusion/plugins/publish/render_local.py index 27bd3120486..3eb4cbd868b 100644 --- a/openpype/hosts/fusion/plugins/publish/render_local.py +++ b/openpype/hosts/fusion/plugins/publish/render_local.py @@ -17,7 +17,6 @@ class Fusionlocal(pyblish.api.InstancePlugin): families = ["render.local"] def process(self, instance): - context = instance.context # Start render @@ -35,10 +34,10 @@ def process(self, instance): for frame in range(frame_start, frame_end + 1) ] repre = { - 'name': ext[1:], - 'ext': ext[1:], - 'frameStart': f"%0{len(str(frame_end))}d" % frame_start, - 'files': files, + "name": ext[1:], + "ext": ext[1:], + "frameStart": f"%0{len(str(frame_end))}d" % frame_start, + "files": files, "stagingDir": output_dir, } @@ -67,18 +66,20 @@ def render_once(self, context): current_comp = context.data["currentComp"] frame_start = context.data["frameStartHandle"] frame_end = context.data["frameEndHandle"] - + self.log.info("Starting Fusion render") self.log.info(f"Start frame: {frame_start}") self.log.info(f"End frame: {frame_end}") - + with comp_lock_and_undo_chunk(current_comp): - result = current_comp.Render({ - "Start": frame_start, - "End": frame_end, - "Wait": True - }) - + result = current_comp.Render( + { + "Start": frame_start, + "End": frame_end, + "Wait": True, + } + ) + context.data[key] = bool(result) if context.data[key] is False: From f3baace6682bebfbbbae273b54c4aaf38477f4a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Je=C5=BEek?= Date: Fri, 3 Mar 2023 13:17:46 +0100 Subject: [PATCH 251/898] Update openpype/pipeline/publish/publish_plugins.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fabià Serra Arrizabalaga --- openpype/pipeline/publish/publish_plugins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/pipeline/publish/publish_plugins.py b/openpype/pipeline/publish/publish_plugins.py index 0142919e760..7da61fec5e3 100644 --- a/openpype/pipeline/publish/publish_plugins.py +++ b/openpype/pipeline/publish/publish_plugins.py @@ -298,7 +298,7 @@ class ColormanagedPyblishPluginMixin(object): It also contains a method, set_representation_colorspace, which sets colorspace data to the representation. The allowed file extensions are listed in the allowed_ext variable. - he method first checks if the file extension is in + The method first checks if the file extension is in the list of allowed extensions. If it is, it then gets the colorspace settings from the host context and gets a matching colorspace from rules. Finally, it infuses this From 0c517a12a618076fdd3fc043fb1ce80d7e1f3327 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 3 Mar 2023 14:07:20 +0100 Subject: [PATCH 252/898] Nuke: fix the order of plugin to be after anatomy data collector also convert anatomy data with deepcopy --- openpype/hosts/nuke/plugins/publish/collect_writes.py | 2 +- openpype/pipeline/publish/publish_plugins.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/collect_writes.py b/openpype/hosts/nuke/plugins/publish/collect_writes.py index 858fa79a4bc..304b3d8f325 100644 --- a/openpype/hosts/nuke/plugins/publish/collect_writes.py +++ b/openpype/hosts/nuke/plugins/publish/collect_writes.py @@ -10,7 +10,7 @@ class CollectNukeWrites(pyblish.api.InstancePlugin, publish.ColormanagedPyblishPluginMixin): """Collect all write nodes.""" - order = pyblish.api.CollectorOrder - 0.48 + order = pyblish.api.CollectorOrder + 0.0021 label = "Collect Writes" hosts = ["nuke", "nukeassist"] families = ["render", "prerender", "image"] diff --git a/openpype/pipeline/publish/publish_plugins.py b/openpype/pipeline/publish/publish_plugins.py index 7da61fec5e3..2df98221ba9 100644 --- a/openpype/pipeline/publish/publish_plugins.py +++ b/openpype/pipeline/publish/publish_plugins.py @@ -1,3 +1,4 @@ +from copy import deepcopy import inspect from abc import ABCMeta from pprint import pformat @@ -323,7 +324,7 @@ def get_colorspace_settings(context): project_name = context.data["projectName"] host_name = context.data["hostName"] - anatomy_data = context.data["anatomyData"] + anatomy_data = deepcopy(context.data["anatomyData"]) project_settings_ = context.data["project_settings"] config_data = get_imageio_config( From efac55ba8961d75e3fa1fb9d2f2860790f1e58e8 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 3 Mar 2023 14:08:00 +0100 Subject: [PATCH 253/898] Added render log per instance --- openpype/hosts/fusion/plugins/publish/render_local.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/openpype/hosts/fusion/plugins/publish/render_local.py b/openpype/hosts/fusion/plugins/publish/render_local.py index 3eb4cbd868b..86c283952c9 100644 --- a/openpype/hosts/fusion/plugins/publish/render_local.py +++ b/openpype/hosts/fusion/plugins/publish/render_local.py @@ -22,6 +22,15 @@ def process(self, instance): # Start render self.render_once(context) + # Log render status + self.log.info( + "Rendered '{nm}' for asset '{ast}' under the task '{tsk}'".format( + nm=instance.data.name, + ast=instance.data.asset, + tsk=instance.data.task, + ) + ) + frame_start = context.data["frameStartHandle"] frame_end = context.data["frameEndHandle"] path = instance.data["path"] From a63872b54b4e4aaf42e4875a2b437642b345eb27 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 3 Mar 2023 16:07:29 +0100 Subject: [PATCH 254/898] Fixed dict data access --- openpype/hosts/fusion/plugins/publish/render_local.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/render_local.py b/openpype/hosts/fusion/plugins/publish/render_local.py index 86c283952c9..0eca7f6cdd5 100644 --- a/openpype/hosts/fusion/plugins/publish/render_local.py +++ b/openpype/hosts/fusion/plugins/publish/render_local.py @@ -25,9 +25,9 @@ def process(self, instance): # Log render status self.log.info( "Rendered '{nm}' for asset '{ast}' under the task '{tsk}'".format( - nm=instance.data.name, - ast=instance.data.asset, - tsk=instance.data.task, + nm=instance.data["name"], + ast=instance.data["asset"], + tsk=instance.data["task"], ) ) From f2311c686638dd1e9d646333b5dd482129024869 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 28 Feb 2023 09:12:51 +0000 Subject: [PATCH 255/898] Fixes - missing platform extraction from settings - map function should be list comprehension - code cosmetics --- .../maya/plugins/publish/validate_model_name.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_model_name.py b/openpype/hosts/maya/plugins/publish/validate_model_name.py index 2dec9ba267d..0e7adc640f2 100644 --- a/openpype/hosts/maya/plugins/publish/validate_model_name.py +++ b/openpype/hosts/maya/plugins/publish/validate_model_name.py @@ -2,9 +2,11 @@ """Validate model nodes names.""" import os import re +import platform + from maya import cmds -import pyblish.api +import pyblish.api from openpype.pipeline import legacy_io from openpype.pipeline.publish import ValidateContentsOrder import openpype.hosts.maya.api.action @@ -44,7 +46,7 @@ def is_group(group_name): if not cmds.ls(child, transforms=True): return False return True - except: + except Exception: return False invalid = [] @@ -94,9 +96,10 @@ def is_group(group_name): # load shader list file as utf-8 shaders = [] if not use_db: - if cls.material_file: - if os.path.isfile(cls.material_file): - shader_file = open(cls.material_file, "r") + material_file = cls.material_file[platform.system().lower()] + if material_file: + if os.path.isfile(material_file): + shader_file = open(material_file, "r") shaders = shader_file.readlines() shader_file.close() else: @@ -113,7 +116,7 @@ def is_group(group_name): shader_file.close() # strip line endings from list - shaders = map(lambda s: s.rstrip(), shaders) + shaders = [s.rstrip() for s in shaders if s.rstrip()] # compile regex for testing names regex = cls.regex From 6f0cd7fc2f04f8ff13e7a756f932ab7068c29629 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 31 Jan 2023 17:30:27 +0100 Subject: [PATCH 256/898] add visualParent None to Shots and Assets Without this, tray-publisher throws an error and stops working. --- openpype/modules/kitsu/utils/update_op_with_zou.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index 2d14b38bc4f..5af3a61e810 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -389,6 +389,7 @@ def sync_project_from_kitsu(dbcon: AvalonMongoDB, project: dict): "data": { "root_of": r, "tasks": {}, + "visualParent": None, }, } for r in ["Assets", "Shots"] From 76273b7376c5b65423beb3a195c4a6376f0453be Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Wed, 1 Feb 2023 13:38:22 +0100 Subject: [PATCH 257/898] lowercase URL path to match in Kitsu Without this fix the menu-dropdown wouldn't show the correct current page in Kitsu --- openpype/modules/kitsu/actions/launcher_show_in_kitsu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/modules/kitsu/actions/launcher_show_in_kitsu.py b/openpype/modules/kitsu/actions/launcher_show_in_kitsu.py index c95079e0424..4793d60fc38 100644 --- a/openpype/modules/kitsu/actions/launcher_show_in_kitsu.py +++ b/openpype/modules/kitsu/actions/launcher_show_in_kitsu.py @@ -100,7 +100,7 @@ def get_url(self, kitsu_url = kitsu_url[:-len("/api")] sub_url = f"/productions/{project_id}" - asset_type_url = "Shots" if asset_type in shots_url else "Assets" + asset_type_url = "shots" if asset_type in shots_url else "assets" if task_id: # Go to task page From 9795e7c9105777f0ae0c4d20376d5204b23b1b00 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Wed, 1 Feb 2023 15:52:56 +0100 Subject: [PATCH 258/898] Populate items with correct data from Kitsu or project defaults If data doesn't exist in Kitsu, use Projects default data. --- .../modules/kitsu/utils/update_op_with_zou.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index 5af3a61e810..554d90f7a99 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -69,6 +69,7 @@ def set_op_project(dbcon: AvalonMongoDB, project_id: str): def update_op_assets( dbcon: AvalonMongoDB, + gazu_project: dict, project_doc: dict, entities_list: List[dict], asset_doc_ids: Dict[str, dict], @@ -119,21 +120,20 @@ def update_op_assets( # because of zou's legacy design frames_duration = int(item.get("nb_frames", 0)) except (TypeError, ValueError): - frames_duration = 0 + frames_duration = None # Frame out, fallback on frame_in + duration or project's value or 1001 frame_out = item_data.pop("frame_out", None) if not frame_out: - frame_out = frame_in + frames_duration - try: - frame_out = int(frame_out) - except (TypeError, ValueError): - frame_out = 1001 + if frames_duration: + frame_out = frame_in + frames_duration + else: + frame_out = project_doc["data"].get("frameEnd", 1001) item_data["frameEnd"] = frame_out # Fps, fallback to project's value or default value (25.0) try: - fps = float(item_data.get("fps", project_doc["data"].get("fps"))) + fps = float(item_data.get("fps")) except (TypeError, ValueError): - fps = 25.0 + fps = float(gazu_project.get("fps", project_doc["data"].get("fps", 25))) item_data["fps"] = fps # Tasks @@ -424,7 +424,7 @@ def sync_project_from_kitsu(dbcon: AvalonMongoDB, project: dict): [ UpdateOne({"_id": id}, update) for id, update in update_op_assets( - dbcon, project_doc, all_entities, zou_ids_and_asset_docs + dbcon, project, project_doc, all_entities, zou_ids_and_asset_docs ) ] ) From a005d108292821e9a062da8f3cef32f113ad8eca Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Wed, 1 Feb 2023 16:07:45 +0100 Subject: [PATCH 259/898] Add Resolution and Pixel Aspect to each item Without this info eg. Fusion would throw an error and stop working. --- openpype/modules/kitsu/utils/update_op_with_zou.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index 554d90f7a99..cbf7afb413d 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -135,6 +135,17 @@ def update_op_assets( except (TypeError, ValueError): fps = float(gazu_project.get("fps", project_doc["data"].get("fps", 25))) item_data["fps"] = fps + # Resolution, fall back to project default + match_res = re.match(r"(\d+)x(\d+)", item_data.get("resolution", gazu_project.get("resolution"))) + if match_res: + item_data["resolutionWidth"] = int(match_res.group(1)) + item_data["resolutionHeight"] = int(match_res.group(2)) + else: + item_data["resolutionWidth"] = project_doc["data"].get("resolutionWidth") + item_data["resolutionHeight"] = project_doc["data"].get("resolutionHeight") + # Properties that doesn't fully exist in Kitsu. Guessing the property name + # Pixel Aspect Ratio + item_data["pixelAspect"] = item_data.get("pixel_aspect", project_doc["data"].get("pixelAspect")) # Tasks tasks_list = [] From 3b4cdb13db5c3ae89b5c3e3bd6a1b0e73731fe3d Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Wed, 1 Feb 2023 20:13:00 +0100 Subject: [PATCH 260/898] Add parents key to assets and shots Without this you can't open the project in Tray Publisher --- openpype/modules/kitsu/utils/update_op_with_zou.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index cbf7afb413d..1b191ccb1e3 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -401,6 +401,7 @@ def sync_project_from_kitsu(dbcon: AvalonMongoDB, project: dict): "root_of": r, "tasks": {}, "visualParent": None, + "parents": [], }, } for r in ["Assets", "Shots"] From 5dee2b8ff6b8eedbaaf68af164b316874f413059 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 2 Feb 2023 17:15:55 +0100 Subject: [PATCH 261/898] Add missing attributes to each asset Without them, Tray Publisher errors out. --- openpype/modules/kitsu/utils/update_op_with_zou.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index 1b191ccb1e3..d88198eace6 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -146,6 +146,14 @@ def update_op_assets( # Properties that doesn't fully exist in Kitsu. Guessing the property name # Pixel Aspect Ratio item_data["pixelAspect"] = item_data.get("pixel_aspect", project_doc["data"].get("pixelAspect")) + # Handle Start + item_data["handleStart"] = item_data.get("handle_start", project_doc["data"].get("handleStart")) + # Handle End + item_data["handleEnd"] = item_data.get("handle_end", project_doc["data"].get("handleEnd")) + # Clip In + item_data["clipIn"] = item_data.get("clip_in", project_doc["data"].get("clipIn")) + # Clip Out + item_data["clipOut"] = item_data.get("clip_out", project_doc["data"].get("clipOut")) # Tasks tasks_list = [] From 785825751a0e5dacdc6e7bf2825e8360456d906c Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 2 Feb 2023 17:18:16 +0100 Subject: [PATCH 262/898] Add render to families to make sure a task exists to process --- openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py | 2 +- .../modules/kitsu/plugins/publish/integrate_kitsu_review.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index ea98e0b7ccb..b801e0e4d4c 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -8,7 +8,7 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): order = pyblish.api.IntegratorOrder label = "Kitsu Note and Status" - # families = ["kitsu"] + families = ["render", "kitsu"] set_status_note = False note_status_shortname = "wfa" diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py index e5e64394398..9e9eaadc271 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py @@ -8,7 +8,7 @@ class IntegrateKitsuReview(pyblish.api.InstancePlugin): order = pyblish.api.IntegratorOrder + 0.01 label = "Kitsu Review" - # families = ["kitsu"] + families = ["render", "kitsu"] optional = True def process(self, instance): From 27c8a1f36099347f777c538d72c67eb5dcb9dc80 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 2 Feb 2023 19:31:06 +0100 Subject: [PATCH 263/898] Fixed so correct review file gets uploaded to Kitsu --- .../modules/kitsu/plugins/publish/integrate_kitsu_review.py | 2 +- .../projects_schema/schemas/schema_representation_tags.json | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py index 9e9eaadc271..94897b25537 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py @@ -27,7 +27,7 @@ def process(self, instance): # Add review representations as preview of comment for representation in instance.data.get("representations", []): # Skip if not tagged as review - if "review" not in representation.get("tags", []): + if "kitsureview" not in representation.get("tags", []): continue review_path = representation.get("published_path") diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_representation_tags.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_representation_tags.json index a4b28f47bcf..7046952eef7 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_representation_tags.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_representation_tags.json @@ -16,6 +16,9 @@ { "shotgridreview": "Add review to Shotgrid" }, + { + "kitsureview": "Add review to Kitsu" + }, { "delete": "Delete output" }, From 72270005edc887e8e708a8d078f8a3d7ac1ec287 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 2 Feb 2023 23:33:57 +0100 Subject: [PATCH 264/898] Update Kitsu plugin to work without assetEntry --- .../plugins/publish/collect_kitsu_entities.py | 83 +++++++++++-------- 1 file changed, 49 insertions(+), 34 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py index c9e78b59eb5..38c67898ef0 100644 --- a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py +++ b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py @@ -4,6 +4,11 @@ import gazu import pyblish.api +from openpype.client import ( + get_projects, + get_project, + get_assets, +) class CollectKitsuEntities(pyblish.api.ContextPlugin): """Collect Kitsu entities according to the current context""" @@ -12,20 +17,34 @@ class CollectKitsuEntities(pyblish.api.ContextPlugin): label = "Kitsu entities" def process(self, context): + + # Get all needed names + project_name = context.data.get("projectName") + asset_name = context.data.get("asset") + task_name = context.data.get("task") + # If asset and task name doesn't exist in context, look in instance + for instance in context: + if not asset_name: + asset_name = instance.data.get("asset") + if not task_name: + task_name = instance.data.get("task") - asset_data = context.data["assetEntity"]["data"] - zou_asset_data = asset_data.get("zou") + # Get all assets of the local project + asset_docs = { + asset_doc["name"]: asset_doc + for asset_doc in get_assets(project_name) + } + + # Get asset object + asset = asset_docs.get(asset_name) + if not asset: + raise AssertionError("{} not found in DB".format(asset_name)) + + zou_asset_data = asset["data"].get("zou") if not zou_asset_data: raise AssertionError("Zou asset data not found in OpenPype!") self.log.debug("Collected zou asset data: {}".format(zou_asset_data)) - zou_task_data = asset_data["tasks"][os.environ["AVALON_TASK"]].get( - "zou" - ) - if not zou_task_data: - self.log.warning("Zou task data not found in OpenPype!") - self.log.debug("Collected zou task data: {}".format(zou_task_data)) - kitsu_project = gazu.project.get_project(zou_asset_data["project_id"]) if not kitsu_project: raise AssertionError("Project not found in kitsu!") @@ -37,37 +56,33 @@ def process(self, context): kitsu_entity = gazu.shot.get_shot(zou_asset_data["id"]) else: kitsu_entity = gazu.asset.get_asset(zou_asset_data["id"]) - if not kitsu_entity: raise AssertionError("{} not found in kitsu!".format(entity_type)) - context.data["kitsu_entity"] = kitsu_entity self.log.debug( "Collect kitsu {}: {}".format(entity_type, kitsu_entity) ) - if zou_task_data: - kitsu_task = gazu.task.get_task(zou_task_data["id"]) - if not kitsu_task: - raise AssertionError("Task not found in kitsu!") - context.data["kitsu_task"] = kitsu_task - self.log.debug("Collect kitsu task: {}".format(kitsu_task)) - - else: - kitsu_task_type = gazu.task.get_task_type_by_name( - os.environ["AVALON_TASK"] - ) - if not kitsu_task_type: - raise AssertionError( - "Task type {} not found in Kitsu!".format( - os.environ["AVALON_TASK"] + if task_name: + zou_task_data = asset["data"]["tasks"][task_name].get("zou") + self.log.debug("Collected zou task data: {}".format(zou_task_data)) + if zou_task_data: + kitsu_task = gazu.task.get_task(zou_task_data["id"]) + if not kitsu_task: + raise AssertionError("Task not found in kitsu!") + context.data["kitsu_task"] = kitsu_task + self.log.debug("Collect kitsu task: {}".format(kitsu_task)) + else: + kitsu_task_type = gazu.task.get_task_type_by_name(task_name) + if not kitsu_task_type: + raise AssertionError( + "Task type {} not found in Kitsu!".format(task_name) ) - ) - kitsu_task = gazu.task.get_task_by_name( - kitsu_entity, kitsu_task_type - ) - if not kitsu_task: - raise AssertionError("Task not found in kitsu!") - context.data["kitsu_task"] = kitsu_task - self.log.debug("Collect kitsu task: {}".format(kitsu_task)) + kitsu_task = gazu.task.get_task_by_name( + kitsu_entity, kitsu_task_type + ) + if not kitsu_task: + raise AssertionError("Task not found in kitsu!") + context.data["kitsu_task"] = kitsu_task + self.log.debug("Collect kitsu task: {}".format(kitsu_task)) \ No newline at end of file From 62c111e9486e532255d213d0508f00281f40e86c Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 3 Feb 2023 00:55:01 +0100 Subject: [PATCH 265/898] Add kitsureview to default burnin tags --- openpype/settings/defaults/project_settings/global.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/settings/defaults/project_settings/global.json b/openpype/settings/defaults/project_settings/global.json index a5e2d25a886..aad17d54daa 100644 --- a/openpype/settings/defaults/project_settings/global.json +++ b/openpype/settings/defaults/project_settings/global.json @@ -139,7 +139,8 @@ "ext": "mp4", "tags": [ "burnin", - "ftrackreview" + "ftrackreview", + "kitsureview" ], "burnins": [], "ffmpeg_args": { From dc2b519fd5689389a482c4772289af8ba9154176 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 3 Feb 2023 01:07:48 +0100 Subject: [PATCH 266/898] Fixed hound-bots comments --- .../plugins/publish/collect_kitsu_entities.py | 25 ++++++++--------- .../modules/kitsu/utils/update_op_with_zou.py | 27 ++++++++++++------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py index 38c67898ef0..92c8c1823d8 100644 --- a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py +++ b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py @@ -5,11 +5,10 @@ import pyblish.api from openpype.client import ( - get_projects, - get_project, get_assets, ) + class CollectKitsuEntities(pyblish.api.ContextPlugin): """Collect Kitsu entities according to the current context""" @@ -17,7 +16,7 @@ class CollectKitsuEntities(pyblish.api.ContextPlugin): label = "Kitsu entities" def process(self, context): - + # Get all needed names project_name = context.data.get("projectName") asset_name = context.data.get("asset") @@ -38,18 +37,18 @@ def process(self, context): # Get asset object asset = asset_docs.get(asset_name) if not asset: - raise AssertionError("{} not found in DB".format(asset_name)) + raise AssertionError(f"{asset_name} not found in DB") zou_asset_data = asset["data"].get("zou") if not zou_asset_data: raise AssertionError("Zou asset data not found in OpenPype!") - self.log.debug("Collected zou asset data: {}".format(zou_asset_data)) + self.log.debug(f"Collected zou asset data: {zou_asset_data}") kitsu_project = gazu.project.get_project(zou_asset_data["project_id"]) if not kitsu_project: raise AssertionError("Project not found in kitsu!") context.data["kitsu_project"] = kitsu_project - self.log.debug("Collect kitsu project: {}".format(kitsu_project)) + self.log.debug(f"Collect kitsu project: {kitsu_project}") entity_type = zou_asset_data["type"] if entity_type == "Shot": @@ -57,26 +56,24 @@ def process(self, context): else: kitsu_entity = gazu.asset.get_asset(zou_asset_data["id"]) if not kitsu_entity: - raise AssertionError("{} not found in kitsu!".format(entity_type)) + raise AssertionError(f"{entity_type} not found in kitsu!") context.data["kitsu_entity"] = kitsu_entity - self.log.debug( - "Collect kitsu {}: {}".format(entity_type, kitsu_entity) - ) + self.log.debug(f"Collect kitsu {entity_type}: {kitsu_entity}") if task_name: zou_task_data = asset["data"]["tasks"][task_name].get("zou") - self.log.debug("Collected zou task data: {}".format(zou_task_data)) + self.log.debug(f"Collected zou task data: {zou_task_data}") if zou_task_data: kitsu_task = gazu.task.get_task(zou_task_data["id"]) if not kitsu_task: raise AssertionError("Task not found in kitsu!") context.data["kitsu_task"] = kitsu_task - self.log.debug("Collect kitsu task: {}".format(kitsu_task)) + self.log.debug(f"Collect kitsu task: {kitsu_task}") else: kitsu_task_type = gazu.task.get_task_type_by_name(task_name) if not kitsu_task_type: raise AssertionError( - "Task type {} not found in Kitsu!".format(task_name) + f"Task type {task_name} not found in Kitsu!" ) kitsu_task = gazu.task.get_task_by_name( @@ -85,4 +82,4 @@ def process(self, context): if not kitsu_task: raise AssertionError("Task not found in kitsu!") context.data["kitsu_task"] = kitsu_task - self.log.debug("Collect kitsu task: {}".format(kitsu_task)) \ No newline at end of file + self.log.debug(f"Collect kitsu task: {kitsu_task}") diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index d88198eace6..a079fd55292 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -133,27 +133,36 @@ def update_op_assets( try: fps = float(item_data.get("fps")) except (TypeError, ValueError): - fps = float(gazu_project.get("fps", project_doc["data"].get("fps", 25))) + fps = float(gazu_project.get( + "fps", project_doc["data"].get("fps", 25))) item_data["fps"] = fps # Resolution, fall back to project default - match_res = re.match(r"(\d+)x(\d+)", item_data.get("resolution", gazu_project.get("resolution"))) + match_res = re.match( + r"(\d+)x(\d+)", item_data.get("resolution", gazu_project.get("resolution"))) if match_res: item_data["resolutionWidth"] = int(match_res.group(1)) item_data["resolutionHeight"] = int(match_res.group(2)) else: - item_data["resolutionWidth"] = project_doc["data"].get("resolutionWidth") - item_data["resolutionHeight"] = project_doc["data"].get("resolutionHeight") + item_data["resolutionWidth"] = project_doc["data"].get( + "resolutionWidth") + item_data["resolutionHeight"] = project_doc["data"].get( + "resolutionHeight") # Properties that doesn't fully exist in Kitsu. Guessing the property name # Pixel Aspect Ratio - item_data["pixelAspect"] = item_data.get("pixel_aspect", project_doc["data"].get("pixelAspect")) + item_data["pixelAspect"] = item_data.get( + "pixel_aspect", project_doc["data"].get("pixelAspect")) # Handle Start - item_data["handleStart"] = item_data.get("handle_start", project_doc["data"].get("handleStart")) + item_data["handleStart"] = item_data.get( + "handle_start", project_doc["data"].get("handleStart")) # Handle End - item_data["handleEnd"] = item_data.get("handle_end", project_doc["data"].get("handleEnd")) + item_data["handleEnd"] = item_data.get( + "handle_end", project_doc["data"].get("handleEnd")) # Clip In - item_data["clipIn"] = item_data.get("clip_in", project_doc["data"].get("clipIn")) + item_data["clipIn"] = item_data.get( + "clip_in", project_doc["data"].get("clipIn")) # Clip Out - item_data["clipOut"] = item_data.get("clip_out", project_doc["data"].get("clipOut")) + item_data["clipOut"] = item_data.get( + "clip_out", project_doc["data"].get("clipOut")) # Tasks tasks_list = [] From bb61d43c27286bda8b319d5e49da8166c1472ae8 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 3 Feb 2023 11:52:37 +0100 Subject: [PATCH 267/898] Shortened length of line 141 --- openpype/modules/kitsu/utils/update_op_with_zou.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index a079fd55292..15e88947a14 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -138,7 +138,9 @@ def update_op_assets( item_data["fps"] = fps # Resolution, fall back to project default match_res = re.match( - r"(\d+)x(\d+)", item_data.get("resolution", gazu_project.get("resolution"))) + r"(\d+)x(\d+)", + item_data.get("resolution", gazu_project.get("resolution")) + ) if match_res: item_data["resolutionWidth"] = int(match_res.group(1)) item_data["resolutionHeight"] = int(match_res.group(2)) From 47caa760305dcb46639d94ae7c345d8682e724fc Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 10 Feb 2023 13:32:03 +0100 Subject: [PATCH 268/898] Updated Kitsu Sync module to fully work with all events Manually tried all events, added logging for events and cleaned up the code some. --- openpype/modules/kitsu/utils/sync_service.py | 318 +++++++++++++----- .../modules/kitsu/utils/update_op_with_zou.py | 17 +- 2 files changed, 248 insertions(+), 87 deletions(-) diff --git a/openpype/modules/kitsu/utils/sync_service.py b/openpype/modules/kitsu/utils/sync_service.py index 237746bea03..e371c1a9bbb 100644 --- a/openpype/modules/kitsu/utils/sync_service.py +++ b/openpype/modules/kitsu/utils/sync_service.py @@ -1,3 +1,15 @@ +""" +Bugs: + * Error when adding task type to anything that isn't Shot or Assets + * Assets don't get added under an episode if TV show + * Assets added under Main Pack throws error. Can't get the name of Main Pack? + +Features ToDo: + * Select in settings what types you wish to sync + * Print what's updated on entity-update + * Add listener for Edits +""" + import os import threading @@ -5,6 +17,7 @@ from openpype.client import get_project, get_assets, get_asset_by_name from openpype.pipeline import AvalonMongoDB +from openpype.lib import Logger from .credentials import validate_credentials from .update_op_with_zou import ( create_op_asset, @@ -14,6 +27,8 @@ update_op_assets, ) +log = Logger.get_logger(__name__) + class Listener: """Host Kitsu listener.""" @@ -33,7 +48,7 @@ def __init__(self, login, password): self.dbcon = AvalonMongoDB() self.dbcon.install() - gazu.client.set_host(os.environ["KITSU_SERVER"]) + gazu.client.set_host(os.environ['KITSU_SERVER']) # Authenticate if not validate_credentials(login, password): @@ -42,7 +57,7 @@ def __init__(self, login, password): ) gazu.set_event_host( - os.environ["KITSU_SERVER"].replace("api", "socket.io") + os.environ['KITSU_SERVER'].replace("api", "socket.io") ) self.event_client = gazu.events.init() @@ -103,6 +118,8 @@ def __init__(self, login, password): ) def start(self): + """Start listening for events.""" + log.info("Listening to Kitsu events...") gazu.events.run_client(self.event_client) # == Project == @@ -112,36 +129,49 @@ def _new_project(self, data): # Use update process to avoid duplicating code self._update_project(data) + # Print message + ## Happens in write_project_to_op() + def _update_project(self, data): """Update project into OP DB.""" # Get project entity - project = gazu.project.get_project(data["project_id"]) - project_name = project["name"] + project = gazu.project.get_project(data['project_id']) update_project = write_project_to_op(project, self.dbcon) # Write into DB if update_project: - self.dbcon.Session["AVALON_PROJECT"] = project_name + self.dbcon.Session['AVALON_PROJECT'] = get_kitsu_project_name( + data['project_id']) self.dbcon.bulk_write([update_project]) def _delete_project(self, data): """Delete project.""" - project_name = get_kitsu_project_name(data["project_id"]) + collections = self.dbcon.database.list_collection_names() + project_name = None + for collection in collections: + post = self.dbcon.database[collection].find_one( + {"data.zou_id": data['project_id']}) + if post: + project_name = post['name'] + break - # Delete project collection - self.dbcon.database[project_name].drop() + if project_name: + # Delete project collection + self.dbcon.database[project_name].drop() - # == Asset == + # Print message + log.info(f"Project deleted: {project_name}") + # == Asset == def _new_asset(self, data): """Create new asset into OP DB.""" # Get project entity - set_op_project(self.dbcon, data["project_id"]) + set_op_project(self.dbcon, data['project_id']) - # Get gazu entity - asset = gazu.asset.get_asset(data["asset_id"]) + # Get asset entity + asset = gazu.asset.get_asset(data['asset_id']) # Insert doc in DB self.dbcon.insert_one(create_op_asset(asset)) @@ -149,27 +179,43 @@ def _new_asset(self, data): # Update self._update_asset(data) + # Print message + episode = None + ep_id = asset['episode_id'] + if ep_id and ep_id != "": + episode = gazu.asset.get_episode(ep_id) + + msg = "Asset created: " + msg = msg + f"{asset['project_name']} - " + if episode is not None: + msg = msg + f"{episode['name']}_" + msg = msg + f"{asset['asset_type_name']}_" + msg = msg + f"{asset['name']}" + log.info(msg) + def _update_asset(self, data): """Update asset into OP DB.""" - set_op_project(self.dbcon, data["project_id"]) + set_op_project(self.dbcon, data['project_id']) project_name = self.dbcon.active_project() project_doc = get_project(project_name) # Get gazu entity - asset = gazu.asset.get_asset(data["asset_id"]) + asset = gazu.asset.get_asset(data['asset_id']) # Find asset doc # Query all assets of the local project zou_ids_and_asset_docs = { - asset_doc["data"]["zou"]["id"]: asset_doc + asset_doc['data']['zou']['id']: asset_doc for asset_doc in get_assets(project_name) - if asset_doc["data"].get("zou", {}).get("id") + if asset_doc['data'].get("zou", {}).get("id") } - zou_ids_and_asset_docs[asset["project_id"]] = project_doc + zou_ids_and_asset_docs[asset['project_id']] = project_doc + gazu_project = gazu.project.get_project(asset['project_id']) # Update update_op_result = update_op_assets( - self.dbcon, project_doc, [asset], zou_ids_and_asset_docs + self.dbcon, gazu_project, project_doc, + [asset], zou_ids_and_asset_docs ) if update_op_result: asset_doc_id, asset_update = update_op_result[0] @@ -177,21 +223,37 @@ def _update_asset(self, data): def _delete_asset(self, data): """Delete asset of OP DB.""" - set_op_project(self.dbcon, data["project_id"]) + set_op_project(self.dbcon, data['project_id']) - # Delete - self.dbcon.delete_one( - {"type": "asset", "data.zou.id": data["asset_id"]} - ) + asset = self.dbcon.find_one({"data.zou.id": data['asset_id']}) + if asset: + # Delete + self.dbcon.delete_one( + {"type": "asset", "data.zou.id": data['asset_id']} + ) + + # Print message + episode = None + ep_id = asset['data']['zou']['episode_id'] + if ep_id and ep_id != "": + episode = gazu.asset.get_episode(ep_id) + + msg = "Asset deleted: " + msg = msg + f"{asset['data']['zou']['project_name']} - " + if episode is not None: + msg = msg + f"{episode['name']}_" + msg = msg + f"{asset['data']['zou']['asset_type_name']}_" + msg = msg + f"'{asset['name']}" + log.info(msg) # == Episode == def _new_episode(self, data): """Create new episode into OP DB.""" # Get project entity - set_op_project(self.dbcon, data["project_id"]) + set_op_project(self.dbcon, data['project_id']) # Get gazu entity - episode = gazu.shot.get_episode(data["episode_id"]) + episode = gazu.shot.get_episode(data['episode_id']) # Insert doc in DB self.dbcon.insert_one(create_op_asset(episode)) @@ -199,27 +261,34 @@ def _new_episode(self, data): # Update self._update_episode(data) + # Print message + msg = "Episode created: " + msg = msg + f"{episode['project_name']} - " + msg = msg + f"{episode['name']}" + def _update_episode(self, data): """Update episode into OP DB.""" - set_op_project(self.dbcon, data["project_id"]) + set_op_project(self.dbcon, data['project_id']) project_name = self.dbcon.active_project() project_doc = get_project(project_name) # Get gazu entity - episode = gazu.shot.get_episode(data["episode_id"]) + episode = gazu.shot.get_episode(data['episode_id']) # Find asset doc # Query all assets of the local project zou_ids_and_asset_docs = { - asset_doc["data"]["zou"]["id"]: asset_doc + asset_doc['data']['zou']['id']: asset_doc for asset_doc in get_assets(project_name) - if asset_doc["data"].get("zou", {}).get("id") + if asset_doc['data'].get("zou", {}).get("id") } - zou_ids_and_asset_docs[episode["project_id"]] = project_doc + zou_ids_and_asset_docs[episode['project_id']] = project_doc + gazu_project = gazu.project.get_project(episode['project_id']) # Update update_op_result = update_op_assets( - self.dbcon, project_doc, [episode], zou_ids_and_asset_docs + self.dbcon, gazu_project, project_doc, [ + episode], zou_ids_and_asset_docs ) if update_op_result: asset_doc_id, asset_update = update_op_result[0] @@ -227,22 +296,31 @@ def _update_episode(self, data): def _delete_episode(self, data): """Delete shot of OP DB.""" - set_op_project(self.dbcon, data["project_id"]) - print("delete episode") # TODO check bugfix + set_op_project(self.dbcon, data['project_id']) - # Delete - self.dbcon.delete_one( - {"type": "asset", "data.zou.id": data["episode_id"]} - ) + episode = self.dbcon.find_one({"data.zou.id": data['episode_id']}) + if episode: + # Delete + self.dbcon.delete_one( + {"type": "asset", "data.zou.id": data['episode_id']} + ) + + # Print message + project = gazu.project.get_project( + episode['data']['zou']['project_id']) + + msg = "Episode deleted: " + msg = msg + f"{project['name']} - " + msg = msg + f"{episode['name']}" # == Sequence == def _new_sequence(self, data): """Create new sequnce into OP DB.""" # Get project entity - set_op_project(self.dbcon, data["project_id"]) + set_op_project(self.dbcon, data['project_id']) # Get gazu entity - sequence = gazu.shot.get_sequence(data["sequence_id"]) + sequence = gazu.shot.get_sequence(data['sequence_id']) # Insert doc in DB self.dbcon.insert_one(create_op_asset(sequence)) @@ -250,27 +328,43 @@ def _new_sequence(self, data): # Update self._update_sequence(data) + # Print message + + episode = None + ep_id = sequence['episode_id'] + if ep_id and ep_id != "": + episode = gazu.asset.get_episode(ep_id) + + msg = "Sequence created: " + msg = msg + f"{sequence['project_name']} - " + if episode is not None: + msg = msg + f"{episode['name']}_" + msg = msg + f"{sequence['name']}" + log.info(msg) + def _update_sequence(self, data): """Update sequence into OP DB.""" - set_op_project(self.dbcon, data["project_id"]) + set_op_project(self.dbcon, data['project_id']) project_name = self.dbcon.active_project() project_doc = get_project(project_name) # Get gazu entity - sequence = gazu.shot.get_sequence(data["sequence_id"]) + sequence = gazu.shot.get_sequence(data['sequence_id']) # Find asset doc # Query all assets of the local project zou_ids_and_asset_docs = { - asset_doc["data"]["zou"]["id"]: asset_doc + asset_doc['data']['zou']['id']: asset_doc for asset_doc in get_assets(project_name) - if asset_doc["data"].get("zou", {}).get("id") + if asset_doc['data'].get("zou", {}).get("id") } - zou_ids_and_asset_docs[sequence["project_id"]] = project_doc + zou_ids_and_asset_docs[sequence['project_id']] = project_doc + gazu_project = gazu.project.get_project(sequence['project_id']) # Update update_op_result = update_op_assets( - self.dbcon, project_doc, [sequence], zou_ids_and_asset_docs + self.dbcon, gazu_project, project_doc, + [sequence], zou_ids_and_asset_docs ) if update_op_result: asset_doc_id, asset_update = update_op_result[0] @@ -278,22 +372,30 @@ def _update_sequence(self, data): def _delete_sequence(self, data): """Delete sequence of OP DB.""" - set_op_project(self.dbcon, data["project_id"]) - print("delete sequence") # TODO check bugfix + set_op_project(self.dbcon, data['project_id']) + sequence = self.dbcon.find_one({"data.zou.id": data['sequence_id']}) + if sequence: + # Delete + self.dbcon.delete_one( + {"type": "asset", "data.zou.id": data['sequence_id']} + ) - # Delete - self.dbcon.delete_one( - {"type": "asset", "data.zou.id": data["sequence_id"]} - ) + # Print message + gazu_project = gazu.project.get_project( + sequence['data']['zou']['project_id']) + msg = f"Sequence deleted: " + msg = msg + f"{gazu_project['name']} - " + msg = msg + f"{sequence['name']}" + log.info(msg) # == Shot == def _new_shot(self, data): """Create new shot into OP DB.""" # Get project entity - set_op_project(self.dbcon, data["project_id"]) + set_op_project(self.dbcon, data['project_id']) # Get gazu entity - shot = gazu.shot.get_shot(data["shot_id"]) + shot = gazu.shot.get_shot(data['shot_id']) # Insert doc in DB self.dbcon.insert_one(create_op_asset(shot)) @@ -301,89 +403,151 @@ def _new_shot(self, data): # Update self._update_shot(data) + # Print message + episode = None + if shot['episode_id'] and shot['episode_id'] != "": + episode = gazu.asset.get_episode(shot['episode_id']) + + msg = "Shot created: " + msg = msg + f"{shot['project_name']} - " + if episode is not None: + msg = msg + f"{episode['name']}_" + msg = msg + f"{shot['sequence_name']}_" + msg = msg + f"{shot['name']}" + log.info(msg) + def _update_shot(self, data): """Update shot into OP DB.""" - set_op_project(self.dbcon, data["project_id"]) + set_op_project(self.dbcon, data['project_id']) project_name = self.dbcon.active_project() project_doc = get_project(project_name) # Get gazu entity - shot = gazu.shot.get_shot(data["shot_id"]) + shot = gazu.shot.get_shot(data['shot_id']) # Find asset doc # Query all assets of the local project zou_ids_and_asset_docs = { - asset_doc["data"]["zou"]["id"]: asset_doc + asset_doc['data']['zou']['id']: asset_doc for asset_doc in get_assets(project_name) - if asset_doc["data"].get("zou", {}).get("id") + if asset_doc['data'].get("zou", {}).get("id") } - zou_ids_and_asset_docs[shot["project_id"]] = project_doc + zou_ids_and_asset_docs[shot['project_id']] = project_doc + gazu_project = gazu.project.get_project(shot['project_id']) # Update update_op_result = update_op_assets( - self.dbcon, project_doc, [shot], zou_ids_and_asset_docs + self.dbcon, gazu_project, project_doc, + [shot], zou_ids_and_asset_docs ) + if update_op_result: asset_doc_id, asset_update = update_op_result[0] self.dbcon.update_one({"_id": asset_doc_id}, asset_update) def _delete_shot(self, data): """Delete shot of OP DB.""" - set_op_project(self.dbcon, data["project_id"]) + set_op_project(self.dbcon, data['project_id']) + shot = self.dbcon.find_one({"data.zou.id": data['shot_id']}) - # Delete - self.dbcon.delete_one( - {"type": "asset", "data.zou.id": data["shot_id"]} - ) + if shot: + # Delete + self.dbcon.delete_one( + {"type": "asset", "data.zou.id": data['shot_id']} + ) + + # Print message + gazu_project = gazu.project.get_project( + shot['data']['zou']['project_id']) + + msg = "Shot deleted: " + msg = msg + f"{gazu_project['name']} - " + msg = msg + f"{shot['name']}" + log.info(msg) # == Task == def _new_task(self, data): """Create new task into OP DB.""" # Get project entity - set_op_project(self.dbcon, data["project_id"]) + set_op_project(self.dbcon, data['project_id']) project_name = self.dbcon.active_project() # Get gazu entity - task = gazu.task.get_task(data["task_id"]) + task = gazu.task.get_task(data['task_id']) # Find asset doc - parent_name = task["entity"]["name"] + episode = None + ep_id = task['episode_id'] + if ep_id and ep_id != "": + episode = gazu.asset.get_episode(ep_id) + + parent_name = "" + if episode is not None: + parent_name = episode['name'] + "_" + parent_name = parent_name + \ + task['sequence']['name'] + "_" + task['entity']['name'] asset_doc = get_asset_by_name(project_name, parent_name) # Update asset tasks with new one - asset_tasks = asset_doc["data"].get("tasks") - task_type_name = task["task_type"]["name"] + asset_tasks = asset_doc['data'].get("tasks") + task_type_name = task['task_type']['name'] asset_tasks[task_type_name] = {"type": task_type_name, "zou": task} self.dbcon.update_one( - {"_id": asset_doc["_id"]}, {"$set": {"data.tasks": asset_tasks}} + {"_id": asset_doc['_id']}, {"$set": {"data.tasks": asset_tasks}} ) + # Print message + msg = "Task created: " + msg = msg + f"{task['project']['name']} - " + if episode is not None: + msg = msg + f"{episode['name']}_" + msg = msg + f"{task['sequence']['name']}_" + msg = msg + f"{task['entity']['name']} - " + msg = msg + f"{task['task_type']['name']}" + log.info(msg) + def _update_task(self, data): """Update task into OP DB.""" # TODO is it necessary? - pass def _delete_task(self, data): """Delete task of OP DB.""" - set_op_project(self.dbcon, data["project_id"]) + set_op_project(self.dbcon, data['project_id']) project_name = self.dbcon.active_project() # Find asset doc asset_docs = list(get_assets(project_name)) for doc in asset_docs: # Match task - for name, task in doc["data"]["tasks"].items(): - if task.get("zou") and data["task_id"] == task["zou"]["id"]: + for name, task in doc['data']['tasks'].items(): + if task.get("zou") and data['task_id'] == task['zou']['id']: # Pop task - asset_tasks = doc["data"].get("tasks", {}) + asset_tasks = doc['data'].get("tasks", {}) asset_tasks.pop(name) # Delete task in DB self.dbcon.update_one( - {"_id": doc["_id"]}, + {"_id": doc['_id']}, {"$set": {"data.tasks": asset_tasks}}, ) + + # Print message + shot = gazu.shot.get_shot(task['zou']['entity_id']) + + episode = None + ep_id = shot['episode_id'] + if ep_id and ep_id != "": + episode = gazu.asset.get_episode(ep_id) + + msg = "Task deleted: " + msg = msg + f"{shot['project_name']} - " + if episode is not None: + msg = msg + f"{episode['name']}_" + msg = msg + f"{shot['sequence_name']}_" + msg = msg + f"{shot['name']} - " + msg = msg + f"{task['type']}" + log.info(msg) return @@ -396,7 +560,7 @@ def start_listeners(login: str, password: str): """ # Refresh token every week def refresh_token_every_week(): - print("Refreshing token...") + log.info("Refreshing token...") gazu.refresh_token() threading.Timer(7 * 3600 * 24, refresh_token_every_week).start() diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index 15e88947a14..0a59724393b 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -5,10 +5,6 @@ from pymongo import DeleteOne, UpdateOne import gazu -from gazu.task import ( - all_tasks_for_asset, - all_tasks_for_shot, -) from openpype.client import ( get_project, @@ -18,7 +14,6 @@ create_project, ) from openpype.pipeline import AvalonMongoDB -from openpype.settings import get_project_settings from openpype.modules.kitsu.utils.credentials import validate_credentials from openpype.lib import Logger @@ -85,8 +80,10 @@ def update_op_assets( Returns: List[Dict[str, dict]]: List of (doc_id, update_dict) tuples """ + if not project_doc: + return + project_name = project_doc["name"] - project_module_settings = get_project_settings(project_name)["kitsu"] assets_with_update = [] for item in entities_list: @@ -170,9 +167,9 @@ def update_op_assets( tasks_list = [] item_type = item["type"] if item_type == "Asset": - tasks_list = all_tasks_for_asset(item) + tasks_list = gazu.task.all_tasks_for_asset(item) elif item_type == "Shot": - tasks_list = all_tasks_for_shot(item) + tasks_list = gazu.task.all_tasks_for_shot(item) item_data["tasks"] = { t["task_type_name"]: {"type": t["task_type_name"], "zou": t} for t in tasks_list @@ -207,7 +204,7 @@ def update_op_assets( # Root parent folder if exist visual_parent_doc_id = ( - asset_doc_ids[parent_zou_id]["_id"] if parent_zou_id else None + asset_doc_ids[parent_zou_id].get("_id") if parent_zou_id else None ) if visual_parent_doc_id is None: # Find root folder doc ("Assets" or "Shots") @@ -282,7 +279,7 @@ def write_project_to_op(project: dict, dbcon: AvalonMongoDB) -> UpdateOne: project_name = project["name"] project_doc = get_project(project_name) if not project_doc: - log.info(f"Creating project '{project_name}'") + log.info(f"Project created: {project_name}") project_doc = create_project(project_name, project_name) # Project data and tasks From c44c5c9ddbada1264691a32c78cf1765b0b9bce1 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 10 Feb 2023 14:08:33 +0100 Subject: [PATCH 269/898] Get asset and task names from instance only --- .../kitsu/plugins/publish/collect_kitsu_entities.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py index 92c8c1823d8..5499b1782a3 100644 --- a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py +++ b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py @@ -19,14 +19,12 @@ def process(self, context): # Get all needed names project_name = context.data.get("projectName") - asset_name = context.data.get("asset") - task_name = context.data.get("task") + asset_name = None + task_name = None # If asset and task name doesn't exist in context, look in instance for instance in context: - if not asset_name: - asset_name = instance.data.get("asset") - if not task_name: - task_name = instance.data.get("task") + asset_name = instance.data.get("asset") + task_name = instance.data.get("task") # Get all assets of the local project asset_docs = { From 4bc67437b61326540a2a62f141af5169296ee051 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 10 Feb 2023 14:36:17 +0100 Subject: [PATCH 270/898] Fixed line too long and too many '#' for comments --- openpype/modules/kitsu/utils/sync_service.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/modules/kitsu/utils/sync_service.py b/openpype/modules/kitsu/utils/sync_service.py index e371c1a9bbb..00c8c4eafa5 100644 --- a/openpype/modules/kitsu/utils/sync_service.py +++ b/openpype/modules/kitsu/utils/sync_service.py @@ -2,7 +2,7 @@ Bugs: * Error when adding task type to anything that isn't Shot or Assets * Assets don't get added under an episode if TV show - * Assets added under Main Pack throws error. Can't get the name of Main Pack? + * Assets added under Main Pack throws error. No Main Pack name in dict Features ToDo: * Select in settings what types you wish to sync @@ -130,7 +130,7 @@ def _new_project(self, data): self._update_project(data) # Print message - ## Happens in write_project_to_op() + # - Happens in write_project_to_op() def _update_project(self, data): """Update project into OP DB.""" From 8652dab47898e30cbdeb9c3ed9ced2f841c4ec4c Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 16 Feb 2023 13:14:14 +0100 Subject: [PATCH 271/898] Fixed 'instance' code --- .../plugins/publish/collect_kitsu_entities.py | 104 ++++++++---------- .../plugins/publish/integrate_kitsu_note.py | 50 +++++---- .../plugins/publish/integrate_kitsu_review.py | 6 +- 3 files changed, 74 insertions(+), 86 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py index 5499b1782a3..fe6854218dd 100644 --- a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py +++ b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py @@ -1,13 +1,7 @@ # -*- coding: utf-8 -*- -import os - import gazu import pyblish.api -from openpype.client import ( - get_assets, -) - class CollectKitsuEntities(pyblish.api.ContextPlugin): """Collect Kitsu entities according to the current context""" @@ -17,67 +11,61 @@ class CollectKitsuEntities(pyblish.api.ContextPlugin): def process(self, context): - # Get all needed names - project_name = context.data.get("projectName") - asset_name = None - task_name = None - # If asset and task name doesn't exist in context, look in instance + kitsu_project = None + + kitsu_entities_by_id = {} for instance in context: - asset_name = instance.data.get("asset") + asset_doc = instance.data.get("assetEntity") task_name = instance.data.get("task") + if not asset_doc: + continue - # Get all assets of the local project - asset_docs = { - asset_doc["name"]: asset_doc - for asset_doc in get_assets(project_name) - } + zou_asset_data = asset_doc["data"].get("zou") + if not zou_asset_data: + raise AssertionError("Zou asset data not found in OpenPype!") - # Get asset object - asset = asset_docs.get(asset_name) - if not asset: - raise AssertionError(f"{asset_name} not found in DB") + if kitsu_project is None: + kitsu_project = gazu.project.get_project( + zou_asset_data["project_id"]) + if not kitsu_project: + raise AssertionError("Project not found in kitsu!") - zou_asset_data = asset["data"].get("zou") - if not zou_asset_data: - raise AssertionError("Zou asset data not found in OpenPype!") - self.log.debug(f"Collected zou asset data: {zou_asset_data}") - - kitsu_project = gazu.project.get_project(zou_asset_data["project_id"]) - if not kitsu_project: - raise AssertionError("Project not found in kitsu!") - context.data["kitsu_project"] = kitsu_project - self.log.debug(f"Collect kitsu project: {kitsu_project}") + entity_type = zou_asset_data["type"] + kitsu_id = zou_asset_data["id"] + kitsu_entity = kitsu_entities_by_id.get(kitsu_id) + if not kitsu_entity: + if entity_type == "Shot": + kitsu_entity = gazu.shot.get_shot(kitsu_id) + else: + kitsu_entity = gazu.asset.get_asset(kitsu_id) + kitsu_entities_by_id[kitsu_id] = kitsu_entity - entity_type = zou_asset_data["type"] - if entity_type == "Shot": - kitsu_entity = gazu.shot.get_shot(zou_asset_data["id"]) - else: - kitsu_entity = gazu.asset.get_asset(zou_asset_data["id"]) - if not kitsu_entity: - raise AssertionError(f"{entity_type} not found in kitsu!") - context.data["kitsu_entity"] = kitsu_entity - self.log.debug(f"Collect kitsu {entity_type}: {kitsu_entity}") + if not kitsu_entity: + raise AssertionError( + "{} not found in kitsu!".format(entity_type)) + instance.data["kitsu_entity"] = kitsu_entity - if task_name: - zou_task_data = asset["data"]["tasks"][task_name].get("zou") - self.log.debug(f"Collected zou task data: {zou_task_data}") - if zou_task_data: - kitsu_task = gazu.task.get_task(zou_task_data["id"]) - if not kitsu_task: - raise AssertionError("Task not found in kitsu!") - context.data["kitsu_task"] = kitsu_task - self.log.debug(f"Collect kitsu task: {kitsu_task}") - else: + if not task_name: + continue + zou_task_data = asset_doc["data"]["tasks"][task_name].get("zou") + self.log.debug( + "Collected zou task data: {}".format(zou_task_data)) + if not zou_task_data: kitsu_task_type = gazu.task.get_task_type_by_name(task_name) if not kitsu_task_type: raise AssertionError( - f"Task type {task_name} not found in Kitsu!" + "Task type {} not found in Kitsu!".format(task_name) ) + continue + kitsu_task_id = zou_task_data["id"] + kitsu_task = kitsu_entities_by_id.get(kitsu_task_id) + if not kitsu_task: + kitsu_task = gazu.task.get_task(zou_task_data["id"]) + kitsu_entities_by_id[kitsu_task_id] = kitsu_task - kitsu_task = gazu.task.get_task_by_name( - kitsu_entity, kitsu_task_type - ) - if not kitsu_task: - raise AssertionError("Task not found in kitsu!") - context.data["kitsu_task"] = kitsu_task - self.log.debug(f"Collect kitsu task: {kitsu_task}") + if not kitsu_task: + raise AssertionError("Task not found in kitsu!") + instance.data["kitsu_task"] = kitsu_task + self.log.debug("Collect kitsu task: {}".format(kitsu_task)) + + context.data["kitsu_project"] = kitsu_project diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index b801e0e4d4c..aeec2481e0b 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -21,30 +21,32 @@ def process(self, context): self.log.debug("Comment is `{}`".format(publish_comment)) - # Get note status, by default uses the task status for the note - # if it is not specified in the configuration - note_status = context.data["kitsu_task"]["task_status_id"] - if self.set_status_note: - kitsu_status = gazu.task.get_task_status_by_short_name( - self.note_status_shortname - ) - if kitsu_status: - note_status = kitsu_status - self.log.info("Note Kitsu status: {}".format(note_status)) - else: - self.log.info( - "Cannot find {} status. The status will not be " - "changed!".format(self.note_status_shortname) - ) + for instance in context: + + # Get note status, by default uses the task status for the note + # if it is not specified in the configuration + note_status = instance.data["kitsu_task"]["task_status"]["id"] - # Add comment to kitsu task - self.log.debug( - "Add new note in taks id {}".format( - context.data["kitsu_task"]["id"] + if self.set_status_note: + kitsu_status = gazu.task.get_task_status_by_short_name( + self.note_status_shortname + ) + if kitsu_status: + note_status = kitsu_status + self.log.info("Note Kitsu status: {}".format(note_status)) + else: + self.log.info( + "Cannot find {} status. The status will not be " + "changed!".format(self.note_status_shortname) + ) + + # Add comment to kitsu task + task = instance.data["kitsu_task"]["id"] + self.log.debug( + "Add new note in taks id {}".format(task) + ) + kitsu_comment = gazu.task.add_comment( + task, note_status, comment=publish_comment ) - ) - kitsu_comment = gazu.task.add_comment( - context.data["kitsu_task"], note_status, comment=publish_comment - ) - context.data["kitsu_comment"] = kitsu_comment + instance.data["kitsu_comment"] = kitsu_comment diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py index 94897b25537..d8f6cb7ac83 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py @@ -13,9 +13,8 @@ class IntegrateKitsuReview(pyblish.api.InstancePlugin): def process(self, instance): - context = instance.context - task = context.data["kitsu_task"] - comment = context.data.get("kitsu_comment") + task = instance.data["kitsu_task"]["id"] + comment = instance.data["kitsu_comment"]["id"] # Check comment has been created if not comment: @@ -29,7 +28,6 @@ def process(self, instance): # Skip if not tagged as review if "kitsureview" not in representation.get("tags", []): continue - review_path = representation.get("published_path") self.log.debug("Found review at: {}".format(review_path)) From 290709705e2811c1a87a5f18b859b5880bd09772 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 16 Feb 2023 15:02:31 +0100 Subject: [PATCH 272/898] Changed logging from f-string to .format() --- .../modules/kitsu/actions/launcher_show_in_kitsu.py | 12 ++++++------ openpype/modules/kitsu/utils/credentials.py | 2 +- openpype/modules/kitsu/utils/sync_service.py | 2 +- openpype/modules/kitsu/utils/update_op_with_zou.py | 4 ++-- openpype/modules/kitsu/utils/update_zou_with_op.py | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/openpype/modules/kitsu/actions/launcher_show_in_kitsu.py b/openpype/modules/kitsu/actions/launcher_show_in_kitsu.py index 4793d60fc38..e3676afc4cc 100644 --- a/openpype/modules/kitsu/actions/launcher_show_in_kitsu.py +++ b/openpype/modules/kitsu/actions/launcher_show_in_kitsu.py @@ -32,12 +32,12 @@ def process(self, session, **kwargs): project = get_project(project_name=project_name, fields=["data.zou_id"]) if not project: - raise RuntimeError(f"Project {project_name} not found.") + raise RuntimeError("Project {} not found.".format(project_name)) project_zou_id = project["data"].get("zou_id") if not project_zou_id: - raise RuntimeError(f"Project {project_name} has no " - f"connected kitsu id.") + raise RuntimeError( + "Project {} has no connected kitsu id.".format(project_name)) asset_zou_name = None asset_zou_id = None @@ -48,7 +48,7 @@ def process(self, session, **kwargs): asset_zou_name = asset_name asset_fields = ["data.zou.id", "data.zou.type"] if task_name: - asset_fields.append(f"data.tasks.{task_name}.zou.id") + asset_fields.append("data.tasks.{}.zou.id".format(task_name)) asset = get_asset_by_name(project_name, asset_name=asset_name, @@ -67,7 +67,7 @@ def process(self, session, **kwargs): task_data = asset["data"]["tasks"][task_name] task_zou_data = task_data.get("zou", {}) if not task_zou_data: - self.log.debug(f"No zou task data for task: {task_name}") + self.log.debug("No zou task data for task: {}".format(task_name)) task_zou_id = task_zou_data["id"] # Define URL @@ -78,7 +78,7 @@ def process(self, session, **kwargs): task_id=task_zou_id) # Open URL in webbrowser - self.log.info(f"Opening URL: {url}") + self.log.info("Opening URL: {}".format(url)) webbrowser.open(url, # Try in new tab new=2) diff --git a/openpype/modules/kitsu/utils/credentials.py b/openpype/modules/kitsu/utils/credentials.py index adcfb07cd5c..1731e1ca4f1 100644 --- a/openpype/modules/kitsu/utils/credentials.py +++ b/openpype/modules/kitsu/utils/credentials.py @@ -54,7 +54,7 @@ def validate_host(kitsu_url: str) -> bool: if gazu.client.host_is_valid(): return True else: - raise gazu.exception.HostException(f"Host '{kitsu_url}' is invalid.") + raise gazu.exception.HostException("Host '{}' is invalid.".format(kitsu_url)) def clear_credentials(): diff --git a/openpype/modules/kitsu/utils/sync_service.py b/openpype/modules/kitsu/utils/sync_service.py index 00c8c4eafa5..d4ef5ce63a0 100644 --- a/openpype/modules/kitsu/utils/sync_service.py +++ b/openpype/modules/kitsu/utils/sync_service.py @@ -162,7 +162,7 @@ def _delete_project(self, data): self.dbcon.database[project_name].drop() # Print message - log.info(f"Project deleted: {project_name}") + log.info("Project deleted: {}".format(project_name)) # == Asset == def _new_asset(self, data): diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index 0a59724393b..15e6dd70d93 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -279,7 +279,7 @@ def write_project_to_op(project: dict, dbcon: AvalonMongoDB) -> UpdateOne: project_name = project["name"] project_doc = get_project(project_name) if not project_doc: - log.info(f"Project created: {project_name}") + log.info("Project created: {}".format(project_name)) project_doc = create_project(project_name, project_name) # Project data and tasks @@ -373,7 +373,7 @@ def sync_project_from_kitsu(dbcon: AvalonMongoDB, project: dict): if not project: project = gazu.project.get_project_by_name(project["name"]) - log.info(f"Synchronizing {project['name']}...") + log.info("Synchronizing {}...".format(project['name'])) # Get all assets from zou all_assets = gazu.asset.all_assets_for_project(project) diff --git a/openpype/modules/kitsu/utils/update_zou_with_op.py b/openpype/modules/kitsu/utils/update_zou_with_op.py index 39baf31b937..b13c2dd4c64 100644 --- a/openpype/modules/kitsu/utils/update_zou_with_op.py +++ b/openpype/modules/kitsu/utils/update_zou_with_op.py @@ -61,7 +61,7 @@ def sync_zou_from_op_project( project_doc = get_project(project_name) # Get all entities from zou - print(f"Synchronizing {project_name}...") + print("Synchronizing {}...".format(project_name)) zou_project = gazu.project.get_project_by_name(project_name) # Create project @@ -258,7 +258,7 @@ def sync_zou_from_op_project( for asset_doc in asset_docs.values() } for entity_id in deleted_entities: - gazu.raw.delete(f"data/entities/{entity_id}") + gazu.raw.delete("data/entities/{}".format(entity_id)) # Write into DB if bulk_writes: From 793af30caae9782ab9cb328f7b546231f0c727df Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 16 Feb 2023 15:02:53 +0100 Subject: [PATCH 273/898] Changed AssertionError to ValueError --- .../kitsu/plugins/publish/collect_kitsu_entities.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py index fe6854218dd..dc7048cf2af 100644 --- a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py +++ b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py @@ -22,13 +22,13 @@ def process(self, context): zou_asset_data = asset_doc["data"].get("zou") if not zou_asset_data: - raise AssertionError("Zou asset data not found in OpenPype!") + raise ValueError("Zou asset data not found in OpenPype!") if kitsu_project is None: kitsu_project = gazu.project.get_project( zou_asset_data["project_id"]) if not kitsu_project: - raise AssertionError("Project not found in kitsu!") + raise ValueError("Project not found in kitsu!") entity_type = zou_asset_data["type"] kitsu_id = zou_asset_data["id"] @@ -41,7 +41,7 @@ def process(self, context): kitsu_entities_by_id[kitsu_id] = kitsu_entity if not kitsu_entity: - raise AssertionError( + raise ValueError( "{} not found in kitsu!".format(entity_type)) instance.data["kitsu_entity"] = kitsu_entity @@ -53,7 +53,7 @@ def process(self, context): if not zou_task_data: kitsu_task_type = gazu.task.get_task_type_by_name(task_name) if not kitsu_task_type: - raise AssertionError( + raise ValueError( "Task type {} not found in Kitsu!".format(task_name) ) continue @@ -64,7 +64,7 @@ def process(self, context): kitsu_entities_by_id[kitsu_task_id] = kitsu_task if not kitsu_task: - raise AssertionError("Task not found in kitsu!") + raise ValueError("Task not found in kitsu!") instance.data["kitsu_task"] = kitsu_task self.log.debug("Collect kitsu task: {}".format(kitsu_task)) From 7e6c47967f42f26fd6d0f56c33a14a0e08e77906 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 16 Feb 2023 15:04:05 +0100 Subject: [PATCH 274/898] Get episode_id using get() as ep_id might not always exist --- openpype/modules/kitsu/utils/sync_service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/modules/kitsu/utils/sync_service.py b/openpype/modules/kitsu/utils/sync_service.py index d4ef5ce63a0..a449bf8c066 100644 --- a/openpype/modules/kitsu/utils/sync_service.py +++ b/openpype/modules/kitsu/utils/sync_service.py @@ -477,7 +477,7 @@ def _new_task(self, data): # Find asset doc episode = None - ep_id = task['episode_id'] + ep_id = task.get('episode_id') if ep_id and ep_id != "": episode = gazu.asset.get_episode(ep_id) From 1045ee0c1ed5bb10c3c3d8f4e17f399a5f33c754 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 16 Feb 2023 15:04:55 +0100 Subject: [PATCH 275/898] Check if asset_doc exist before processing it --- openpype/modules/kitsu/utils/sync_service.py | 34 ++++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/openpype/modules/kitsu/utils/sync_service.py b/openpype/modules/kitsu/utils/sync_service.py index a449bf8c066..eed259cda66 100644 --- a/openpype/modules/kitsu/utils/sync_service.py +++ b/openpype/modules/kitsu/utils/sync_service.py @@ -487,25 +487,25 @@ def _new_task(self, data): parent_name = parent_name + \ task['sequence']['name'] + "_" + task['entity']['name'] - asset_doc = get_asset_by_name(project_name, parent_name) - # Update asset tasks with new one - asset_tasks = asset_doc['data'].get("tasks") - task_type_name = task['task_type']['name'] - asset_tasks[task_type_name] = {"type": task_type_name, "zou": task} - self.dbcon.update_one( - {"_id": asset_doc['_id']}, {"$set": {"data.tasks": asset_tasks}} - ) + asset_doc = get_asset_by_name(project_name, parent_name) + if asset_doc: + asset_tasks = asset_doc['data'].get("tasks") + task_type_name = task['task_type']['name'] + asset_tasks[task_type_name] = {"type": task_type_name, "zou": task} + self.dbcon.update_one( + {"_id": asset_doc['_id']}, {"$set": {"data.tasks": asset_tasks}} + ) - # Print message - msg = "Task created: " - msg = msg + f"{task['project']['name']} - " - if episode is not None: - msg = msg + f"{episode['name']}_" - msg = msg + f"{task['sequence']['name']}_" - msg = msg + f"{task['entity']['name']} - " - msg = msg + f"{task['task_type']['name']}" - log.info(msg) + # Print message + msg = "Task created: " + msg = msg + f"{task['project']['name']} - " + if episode is not None: + msg = msg + f"{episode['name']}_" + msg = msg + f"{task['sequence']['name']}_" + msg = msg + f"{task['entity']['name']} - " + msg = msg + f"{task['task_type']['name']}" + log.info(msg) def _update_task(self, data): """Update task into OP DB.""" From ef698b4aface5ceff0ba1016a242a318853eaa2a Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 16 Feb 2023 15:11:07 +0100 Subject: [PATCH 276/898] Fixed 1 extra frame at frameEnd Same as #4466 --- openpype/modules/kitsu/utils/update_op_with_zou.py | 6 +++--- openpype/modules/kitsu/utils/update_zou_with_op.py | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index 15e6dd70d93..93d0d5e3fb8 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -111,18 +111,18 @@ def update_op_assets( except (TypeError, ValueError): frame_in = 1001 item_data["frameStart"] = frame_in - # Frames duration, fallback on 0 + # Frames duration, fallback on 1 try: # NOTE nb_frames is stored directly in item # because of zou's legacy design - frames_duration = int(item.get("nb_frames", 0)) + frames_duration = int(item.get("nb_frames", 1)) except (TypeError, ValueError): frames_duration = None # Frame out, fallback on frame_in + duration or project's value or 1001 frame_out = item_data.pop("frame_out", None) if not frame_out: if frames_duration: - frame_out = frame_in + frames_duration + frame_out = frame_in + frames_duration - 1 else: frame_out = project_doc["data"].get("frameEnd", 1001) item_data["frameEnd"] = frame_out diff --git a/openpype/modules/kitsu/utils/update_zou_with_op.py b/openpype/modules/kitsu/utils/update_zou_with_op.py index b13c2dd4c64..b1a9b8b82c3 100644 --- a/openpype/modules/kitsu/utils/update_zou_with_op.py +++ b/openpype/modules/kitsu/utils/update_zou_with_op.py @@ -174,7 +174,8 @@ def sync_zou_from_op_project( doc["name"], frame_in=doc["data"]["frameStart"], frame_out=doc["data"]["frameEnd"], - nb_frames=doc["data"]["frameEnd"] - doc["data"]["frameStart"], + nb_frames=( + doc["data"]["frameEnd"] - doc["data"]["frameStart"] + 1), ) elif match.group(2): # Sequence @@ -229,7 +230,7 @@ def sync_zou_from_op_project( "frame_in": frame_in, "frame_out": frame_out, }, - "nb_frames": frame_out - frame_in, + "nb_frames": frame_out - frame_in + 1, } ) entity = gazu.raw.update("entities", zou_id, entity_data) From c4f1a1f452d8e0f70d6a629db7925642d3acbc8d Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 16 Feb 2023 15:13:51 +0100 Subject: [PATCH 277/898] Fixed hound's "line too long" comments --- openpype/modules/kitsu/actions/launcher_show_in_kitsu.py | 3 ++- openpype/modules/kitsu/utils/credentials.py | 3 ++- openpype/modules/kitsu/utils/sync_service.py | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/openpype/modules/kitsu/actions/launcher_show_in_kitsu.py b/openpype/modules/kitsu/actions/launcher_show_in_kitsu.py index e3676afc4cc..11224f6e523 100644 --- a/openpype/modules/kitsu/actions/launcher_show_in_kitsu.py +++ b/openpype/modules/kitsu/actions/launcher_show_in_kitsu.py @@ -67,7 +67,8 @@ def process(self, session, **kwargs): task_data = asset["data"]["tasks"][task_name] task_zou_data = task_data.get("zou", {}) if not task_zou_data: - self.log.debug("No zou task data for task: {}".format(task_name)) + self.log.debug( + "No zou task data for task: {}".format(task_name)) task_zou_id = task_zou_data["id"] # Define URL diff --git a/openpype/modules/kitsu/utils/credentials.py b/openpype/modules/kitsu/utils/credentials.py index 1731e1ca4f1..941343cc8d8 100644 --- a/openpype/modules/kitsu/utils/credentials.py +++ b/openpype/modules/kitsu/utils/credentials.py @@ -54,7 +54,8 @@ def validate_host(kitsu_url: str) -> bool: if gazu.client.host_is_valid(): return True else: - raise gazu.exception.HostException("Host '{}' is invalid.".format(kitsu_url)) + raise gazu.exception.HostException( + "Host '{}' is invalid.".format(kitsu_url)) def clear_credentials(): diff --git a/openpype/modules/kitsu/utils/sync_service.py b/openpype/modules/kitsu/utils/sync_service.py index eed259cda66..498c8de71e1 100644 --- a/openpype/modules/kitsu/utils/sync_service.py +++ b/openpype/modules/kitsu/utils/sync_service.py @@ -494,7 +494,8 @@ def _new_task(self, data): task_type_name = task['task_type']['name'] asset_tasks[task_type_name] = {"type": task_type_name, "zou": task} self.dbcon.update_one( - {"_id": asset_doc['_id']}, {"$set": {"data.tasks": asset_tasks}} + {"_id": asset_doc['_id']}, + {"$set": {"data.tasks": asset_tasks}} ) # Print message From 07ac3d8d4db54b111fd0117bed4a5cbc5c9b19d7 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 16 Feb 2023 15:58:49 +0100 Subject: [PATCH 278/898] If no task in instance, continue fix fore https://github.com/ynput/OpenPype/pull/4425#discussion_r1108582918 --- .../modules/kitsu/plugins/publish/integrate_kitsu_note.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index aeec2481e0b..54fb6a46785 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -22,10 +22,13 @@ def process(self, context): self.log.debug("Comment is `{}`".format(publish_comment)) for instance in context: + kitsu_task = instance.data.get("kitsu_task") + if kitsu_task is None: + continue # Get note status, by default uses the task status for the note # if it is not specified in the configuration - note_status = instance.data["kitsu_task"]["task_status"]["id"] + note_status = kitsu_task["task_status"]["id"] if self.set_status_note: kitsu_status = gazu.task.get_task_status_by_short_name( @@ -41,7 +44,7 @@ def process(self, context): ) # Add comment to kitsu task - task = instance.data["kitsu_task"]["id"] + task = kitsu_task["id"] self.log.debug( "Add new note in taks id {}".format(task) ) From 915d11040493e1e59d2389e9d5f86f678ef4b9ca Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 16 Feb 2023 16:02:53 +0100 Subject: [PATCH 279/898] Set frame_out to frame_in if no duration exists fix for https://github.com/ynput/OpenPype/pull/4425#discussion_r1108593566 --- openpype/modules/kitsu/utils/update_op_with_zou.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index 93d0d5e3fb8..265c3638cd4 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -124,7 +124,7 @@ def update_op_assets( if frames_duration: frame_out = frame_in + frames_duration - 1 else: - frame_out = project_doc["data"].get("frameEnd", 1001) + frame_out = project_doc["data"].get("frameEnd", frame_in) item_data["frameEnd"] = frame_out # Fps, fallback to project's value or default value (25.0) try: From 4bcef4406803f0210ed3a741ad99de8aa56c80a7 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Sat, 18 Feb 2023 20:52:20 +0100 Subject: [PATCH 280/898] Fixed hound's max-length note --- openpype/modules/kitsu/utils/update_op_with_zou.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index 265c3638cd4..898cf076c8c 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -146,7 +146,8 @@ def update_op_assets( "resolutionWidth") item_data["resolutionHeight"] = project_doc["data"].get( "resolutionHeight") - # Properties that doesn't fully exist in Kitsu. Guessing the property name + # Properties that doesn't fully exist in Kitsu. + # Guessing those property names below: # Pixel Aspect Ratio item_data["pixelAspect"] = item_data.get( "pixel_aspect", project_doc["data"].get("pixelAspect")) @@ -452,7 +453,8 @@ def sync_project_from_kitsu(dbcon: AvalonMongoDB, project: dict): [ UpdateOne({"_id": id}, update) for id, update in update_op_assets( - dbcon, project, project_doc, all_entities, zou_ids_and_asset_docs + dbcon, project, project_doc, + all_entities, zou_ids_and_asset_docs ) ] ) From 3fc2180e51357cc74a82a76f2fcd21fa11752ecc Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 28 Feb 2023 23:06:52 +0100 Subject: [PATCH 281/898] Fixed all quotes types so they now match --- openpype/modules/kitsu/utils/sync_service.py | 133 ++++++++++--------- 1 file changed, 67 insertions(+), 66 deletions(-) diff --git a/openpype/modules/kitsu/utils/sync_service.py b/openpype/modules/kitsu/utils/sync_service.py index 498c8de71e1..1af0b6edc44 100644 --- a/openpype/modules/kitsu/utils/sync_service.py +++ b/openpype/modules/kitsu/utils/sync_service.py @@ -48,16 +48,16 @@ def __init__(self, login, password): self.dbcon = AvalonMongoDB() self.dbcon.install() - gazu.client.set_host(os.environ['KITSU_SERVER']) + gazu.client.set_host(os.environ["KITSU_SERVER"]) # Authenticate if not validate_credentials(login, password): raise gazu.exception.AuthFailedException( - f"Kitsu authentication failed for login: '{login}'..." + 'Kitsu authentication failed for login: "{}"...'.format(login) ) gazu.set_event_host( - os.environ['KITSU_SERVER'].replace("api", "socket.io") + os.environ["KITSU_SERVER"].replace("api", "socket.io") ) self.event_client = gazu.events.init() @@ -135,14 +135,14 @@ def _new_project(self, data): def _update_project(self, data): """Update project into OP DB.""" # Get project entity - project = gazu.project.get_project(data['project_id']) + project = gazu.project.get_project(data["project_id"]) update_project = write_project_to_op(project, self.dbcon) # Write into DB if update_project: - self.dbcon.Session['AVALON_PROJECT'] = get_kitsu_project_name( - data['project_id']) + self.dbcon.Session["AVALON_PROJECT"] = get_kitsu_project_name( + data["project_id"]) self.dbcon.bulk_write([update_project]) def _delete_project(self, data): @@ -168,10 +168,10 @@ def _delete_project(self, data): def _new_asset(self, data): """Create new asset into OP DB.""" # Get project entity - set_op_project(self.dbcon, data['project_id']) + set_op_project(self.dbcon, data["project_id"]) # Get asset entity - asset = gazu.asset.get_asset(data['asset_id']) + asset = gazu.asset.get_asset(data["asset_id"]) # Insert doc in DB self.dbcon.insert_one(create_op_asset(asset)) @@ -181,7 +181,7 @@ def _new_asset(self, data): # Print message episode = None - ep_id = asset['episode_id'] + ep_id = asset.get("episode_id") if ep_id and ep_id != "": episode = gazu.asset.get_episode(ep_id) @@ -195,22 +195,22 @@ def _new_asset(self, data): def _update_asset(self, data): """Update asset into OP DB.""" - set_op_project(self.dbcon, data['project_id']) + set_op_project(self.dbcon, data["project_id"]) project_name = self.dbcon.active_project() project_doc = get_project(project_name) # Get gazu entity - asset = gazu.asset.get_asset(data['asset_id']) + asset = gazu.asset.get_asset(data["asset_id"]) # Find asset doc # Query all assets of the local project zou_ids_and_asset_docs = { - asset_doc['data']['zou']['id']: asset_doc + asset_doc["data"]["zou"]["id"]: asset_doc for asset_doc in get_assets(project_name) - if asset_doc['data'].get("zou", {}).get("id") + if asset_doc["data"].get("zou", {}).get("id") } - zou_ids_and_asset_docs[asset['project_id']] = project_doc - gazu_project = gazu.project.get_project(asset['project_id']) + zou_ids_and_asset_docs[asset["project_id"]] = project_doc + gazu_project = gazu.project.get_project(asset["project_id"]) # Update update_op_result = update_op_assets( @@ -223,18 +223,18 @@ def _update_asset(self, data): def _delete_asset(self, data): """Delete asset of OP DB.""" - set_op_project(self.dbcon, data['project_id']) + set_op_project(self.dbcon, data["project_id"]) - asset = self.dbcon.find_one({"data.zou.id": data['asset_id']}) + asset = self.dbcon.find_one({"data.zou.id": data["asset_id"]}) if asset: # Delete self.dbcon.delete_one( - {"type": "asset", "data.zou.id": data['asset_id']} + {"type": "asset", "data.zou.id": data["asset_id"]} ) # Print message episode = None - ep_id = asset['data']['zou']['episode_id'] + ep_id = asset["data"]["zou"].get("episode_id") if ep_id and ep_id != "": episode = gazu.asset.get_episode(ep_id) @@ -250,10 +250,10 @@ def _delete_asset(self, data): def _new_episode(self, data): """Create new episode into OP DB.""" # Get project entity - set_op_project(self.dbcon, data['project_id']) + set_op_project(self.dbcon, data["project_id"]) # Get gazu entity - episode = gazu.shot.get_episode(data['episode_id']) + ep = gazu.shot.get_episode(data["episode_id"]) # Insert doc in DB self.dbcon.insert_one(create_op_asset(episode)) @@ -268,22 +268,22 @@ def _new_episode(self, data): def _update_episode(self, data): """Update episode into OP DB.""" - set_op_project(self.dbcon, data['project_id']) + set_op_project(self.dbcon, data["project_id"]) project_name = self.dbcon.active_project() project_doc = get_project(project_name) # Get gazu entity - episode = gazu.shot.get_episode(data['episode_id']) + ep = gazu.shot.get_episode(data["episode_id"]) # Find asset doc # Query all assets of the local project zou_ids_and_asset_docs = { - asset_doc['data']['zou']['id']: asset_doc + asset_doc["data"]["zou"]["id"]: asset_doc for asset_doc in get_assets(project_name) - if asset_doc['data'].get("zou", {}).get("id") + if asset_doc["data"].get("zou", {}).get("id") } - zou_ids_and_asset_docs[episode['project_id']] = project_doc - gazu_project = gazu.project.get_project(episode['project_id']) + zou_ids_and_asset_docs[ep["project_id"]] = project_doc + gazu_project = gazu.project.get_project(ep["project_id"]) # Update update_op_result = update_op_assets( @@ -296,7 +296,7 @@ def _update_episode(self, data): def _delete_episode(self, data): """Delete shot of OP DB.""" - set_op_project(self.dbcon, data['project_id']) + set_op_project(self.dbcon, data["project_id"]) episode = self.dbcon.find_one({"data.zou.id": data['episode_id']}) if episode: @@ -317,10 +317,10 @@ def _delete_episode(self, data): def _new_sequence(self, data): """Create new sequnce into OP DB.""" # Get project entity - set_op_project(self.dbcon, data['project_id']) + set_op_project(self.dbcon, data["project_id"]) # Get gazu entity - sequence = gazu.shot.get_sequence(data['sequence_id']) + sequence = gazu.shot.get_sequence(data["sequence_id"]) # Insert doc in DB self.dbcon.insert_one(create_op_asset(sequence)) @@ -331,7 +331,7 @@ def _new_sequence(self, data): # Print message episode = None - ep_id = sequence['episode_id'] + ep_id = sequence.get("episode_id") if ep_id and ep_id != "": episode = gazu.asset.get_episode(ep_id) @@ -344,22 +344,22 @@ def _new_sequence(self, data): def _update_sequence(self, data): """Update sequence into OP DB.""" - set_op_project(self.dbcon, data['project_id']) + set_op_project(self.dbcon, data["project_id"]) project_name = self.dbcon.active_project() project_doc = get_project(project_name) # Get gazu entity - sequence = gazu.shot.get_sequence(data['sequence_id']) + sequence = gazu.shot.get_sequence(data["sequence_id"]) # Find asset doc # Query all assets of the local project zou_ids_and_asset_docs = { - asset_doc['data']['zou']['id']: asset_doc + asset_doc["data"]["zou"]["id"]: asset_doc for asset_doc in get_assets(project_name) - if asset_doc['data'].get("zou", {}).get("id") + if asset_doc["data"].get("zou", {}).get("id") } - zou_ids_and_asset_docs[sequence['project_id']] = project_doc - gazu_project = gazu.project.get_project(sequence['project_id']) + zou_ids_and_asset_docs[sequence["project_id"]] = project_doc + gazu_project = gazu.project.get_project(sequence["project_id"]) # Update update_op_result = update_op_assets( @@ -372,15 +372,16 @@ def _update_sequence(self, data): def _delete_sequence(self, data): """Delete sequence of OP DB.""" - set_op_project(self.dbcon, data['project_id']) - sequence = self.dbcon.find_one({"data.zou.id": data['sequence_id']}) + set_op_project(self.dbcon, data["project_id"]) + sequence = self.dbcon.find_one({"data.zou.id": data["sequence_id"]}) if sequence: # Delete self.dbcon.delete_one( - {"type": "asset", "data.zou.id": data['sequence_id']} + {"type": "asset", "data.zou.id": data["sequence_id"]} ) # Print message + ep_id = sequence["data"]["zou"].get("episode_id") gazu_project = gazu.project.get_project( sequence['data']['zou']['project_id']) msg = f"Sequence deleted: " @@ -392,10 +393,10 @@ def _delete_sequence(self, data): def _new_shot(self, data): """Create new shot into OP DB.""" # Get project entity - set_op_project(self.dbcon, data['project_id']) + set_op_project(self.dbcon, data["project_id"]) # Get gazu entity - shot = gazu.shot.get_shot(data['shot_id']) + shot = gazu.shot.get_shot(data["shot_id"]) # Insert doc in DB self.dbcon.insert_one(create_op_asset(shot)) @@ -405,7 +406,7 @@ def _new_shot(self, data): # Print message episode = None - if shot['episode_id'] and shot['episode_id'] != "": + if shot["episode_id"] and shot["episode_id"] != "": episode = gazu.asset.get_episode(shot['episode_id']) msg = "Shot created: " @@ -418,21 +419,21 @@ def _new_shot(self, data): def _update_shot(self, data): """Update shot into OP DB.""" - set_op_project(self.dbcon, data['project_id']) + set_op_project(self.dbcon, data["project_id"]) project_name = self.dbcon.active_project() project_doc = get_project(project_name) # Get gazu entity - shot = gazu.shot.get_shot(data['shot_id']) + shot = gazu.shot.get_shot(data["shot_id"]) # Find asset doc # Query all assets of the local project zou_ids_and_asset_docs = { - asset_doc['data']['zou']['id']: asset_doc + asset_doc["data"]["zou"]["id"]: asset_doc for asset_doc in get_assets(project_name) - if asset_doc['data'].get("zou", {}).get("id") - } - zou_ids_and_asset_docs[shot['project_id']] = project_doc + if asset_doc["data"].get("zou", {}).get("id")} + zou_ids_and_asset_docs[shot["project_id"]] = project_doc + gazu_project = gazu.project.get_project(shot["project_id"]) gazu_project = gazu.project.get_project(shot['project_id']) # Update @@ -447,18 +448,18 @@ def _update_shot(self, data): def _delete_shot(self, data): """Delete shot of OP DB.""" - set_op_project(self.dbcon, data['project_id']) - shot = self.dbcon.find_one({"data.zou.id": data['shot_id']}) + set_op_project(self.dbcon, data["project_id"]) + shot = self.dbcon.find_one({"data.zou.id": data["shot_id"]}) if shot: # Delete self.dbcon.delete_one( - {"type": "asset", "data.zou.id": data['shot_id']} + {"type": "asset", "data.zou.id": data["shot_id"]} ) # Print message gazu_project = gazu.project.get_project( - shot['data']['zou']['project_id']) + ep_id = shot["data"]["zou"].get("episode_id") msg = "Shot deleted: " msg = msg + f"{gazu_project['name']} - " @@ -469,15 +470,15 @@ def _delete_shot(self, data): def _new_task(self, data): """Create new task into OP DB.""" # Get project entity - set_op_project(self.dbcon, data['project_id']) + set_op_project(self.dbcon, data["project_id"]) project_name = self.dbcon.active_project() # Get gazu entity - task = gazu.task.get_task(data['task_id']) + task = gazu.task.get_task(data["task_id"]) # Find asset doc episode = None - ep_id = task.get('episode_id') + ep_id = task.get("episode_id") if ep_id and ep_id != "": episode = gazu.asset.get_episode(ep_id) @@ -490,11 +491,11 @@ def _new_task(self, data): # Update asset tasks with new one asset_doc = get_asset_by_name(project_name, parent_name) if asset_doc: - asset_tasks = asset_doc['data'].get("tasks") - task_type_name = task['task_type']['name'] + asset_tasks = asset_doc["data"].get("tasks") + task_type_name = task["task_type"]["name"] asset_tasks[task_type_name] = {"type": task_type_name, "zou": task} self.dbcon.update_one( - {"_id": asset_doc['_id']}, + {"_id": asset_doc["_id"]}, {"$set": {"data.tasks": asset_tasks}} ) @@ -515,29 +516,29 @@ def _update_task(self, data): def _delete_task(self, data): """Delete task of OP DB.""" - set_op_project(self.dbcon, data['project_id']) + set_op_project(self.dbcon, data["project_id"]) project_name = self.dbcon.active_project() # Find asset doc asset_docs = list(get_assets(project_name)) for doc in asset_docs: # Match task - for name, task in doc['data']['tasks'].items(): - if task.get("zou") and data['task_id'] == task['zou']['id']: + for name, task in doc["data"]["tasks"].items(): + if task.get("zou") and data["task_id"] == task["zou"]["id"]: # Pop task - asset_tasks = doc['data'].get("tasks", {}) + asset_tasks = doc["data"].get("tasks", {}) asset_tasks.pop(name) # Delete task in DB self.dbcon.update_one( - {"_id": doc['_id']}, + {"_id": doc["_id"]}, {"$set": {"data.tasks": asset_tasks}}, ) # Print message - shot = gazu.shot.get_shot(task['zou']['entity_id']) + entity = gazu.entity.get_entity(task["zou"]["entity_id"]) episode = None - ep_id = shot['episode_id'] + ep_id = entity.get("episode_id") if ep_id and ep_id != "": episode = gazu.asset.get_episode(ep_id) From f9137bdb041690f2ef6cc0a3d26878ee70b321bf Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 28 Feb 2023 23:08:40 +0100 Subject: [PATCH 282/898] Added docstring and changed `doc` to `dict` in var-names --- .../modules/kitsu/utils/update_op_with_zou.py | 78 +++++++++++-------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index 898cf076c8c..93688485325 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -65,30 +65,32 @@ def set_op_project(dbcon: AvalonMongoDB, project_id: str): def update_op_assets( dbcon: AvalonMongoDB, gazu_project: dict, - project_doc: dict, + project_dict: dict, entities_list: List[dict], - asset_doc_ids: Dict[str, dict], + asset_dict_ids: Dict[str, dict], ) -> List[Dict[str, dict]]: """Update OpenPype assets. Set 'data' and 'parent' fields. Args: dbcon (AvalonMongoDB): Connection to DB + gazu_project dict): Dict of gazu, + project_dict dict): Dict of project, entities_list (List[dict]): List of zou entities to update - asset_doc_ids (Dict[str, dict]): Dicts of [{zou_id: asset_doc}, ...] + asset_dict_ids (Dict[str, dict]): Dicts of [{zou_id: asset_doc}, ...] Returns: List[Dict[str, dict]]: List of (doc_id, update_dict) tuples """ - if not project_doc: + if not project_dict: return - project_name = project_doc["name"] + project_name = project_dict["name"] assets_with_update = [] for item in entities_list: # Check asset exists - item_doc = asset_doc_ids.get(item["id"]) + item_doc = asset_dict_ids.get(item["id"]) if not item_doc: # Create asset op_asset = create_op_asset(item) insert_result = dbcon.insert_one(op_asset) @@ -105,7 +107,7 @@ def update_op_assets( try: frame_in = int( item_data.pop( - "frame_in", project_doc["data"].get("frameStart") + "frame_in", project_dict["data"].get("frameStart") ) ) except (TypeError, ValueError): @@ -124,14 +126,14 @@ def update_op_assets( if frames_duration: frame_out = frame_in + frames_duration - 1 else: - frame_out = project_doc["data"].get("frameEnd", frame_in) + frame_out = project_dict["data"].get("frameEnd", frame_in) item_data["frameEnd"] = frame_out # Fps, fallback to project's value or default value (25.0) try: fps = float(item_data.get("fps")) except (TypeError, ValueError): fps = float(gazu_project.get( - "fps", project_doc["data"].get("fps", 25))) + "fps", project_dict["data"].get("fps", 25))) item_data["fps"] = fps # Resolution, fall back to project default match_res = re.match( @@ -142,27 +144,27 @@ def update_op_assets( item_data["resolutionWidth"] = int(match_res.group(1)) item_data["resolutionHeight"] = int(match_res.group(2)) else: - item_data["resolutionWidth"] = project_doc["data"].get( + item_data["resolutionWidth"] = project_dict["data"].get( "resolutionWidth") - item_data["resolutionHeight"] = project_doc["data"].get( + item_data["resolutionHeight"] = project_dict["data"].get( "resolutionHeight") # Properties that doesn't fully exist in Kitsu. # Guessing those property names below: # Pixel Aspect Ratio item_data["pixelAspect"] = item_data.get( - "pixel_aspect", project_doc["data"].get("pixelAspect")) + "pixel_aspect", project_dict["data"].get("pixelAspect")) # Handle Start item_data["handleStart"] = item_data.get( - "handle_start", project_doc["data"].get("handleStart")) + "handle_start", project_dict["data"].get("handleStart")) # Handle End item_data["handleEnd"] = item_data.get( - "handle_end", project_doc["data"].get("handleEnd")) + "handle_end", project_dict["data"].get("handleEnd")) # Clip In item_data["clipIn"] = item_data.get( - "clip_in", project_doc["data"].get("clipIn")) + "clip_in", project_dict["data"].get("clipIn")) # Clip Out item_data["clipOut"] = item_data.get( - "clip_out", project_doc["data"].get("clipOut")) + "clip_out", project_dict["data"].get("clipOut")) # Tasks tasks_list = [] @@ -204,9 +206,14 @@ def update_op_assets( entity_root_asset_name = "Shots" # Root parent folder if exist - visual_parent_doc_id = ( - asset_doc_ids[parent_zou_id].get("_id") if parent_zou_id else None - ) + visual_parent_doc_id = None + if parent_zou_id is not None: + parent_zou_id_dict = asset_dict_ids.get(parent_zou_id) + if parent_zou_id_dict is not None: + visual_parent_doc_id = ( + parent_zou_id_dict.get("_id") + if parent_zou_id_dict else None) + if visual_parent_doc_id is None: # Find root folder doc ("Assets" or "Shots") root_folder_doc = get_asset_by_name( @@ -225,12 +232,15 @@ def update_op_assets( item_data["parents"] = [] ancestor_id = parent_zou_id while ancestor_id is not None: - parent_doc = asset_doc_ids[ancestor_id] - item_data["parents"].insert(0, parent_doc["name"]) + parent_doc = asset_dict_ids.get(ancestor_id) + if parent_doc is not None: + item_data["parents"].insert(0, parent_doc["name"]) - # Get parent entity - parent_entity = parent_doc["data"]["zou"] - ancestor_id = parent_entity.get("parent_id") + # Get parent entity + parent_entity = parent_doc["data"]["zou"] + ancestor_id = parent_entity.get("parent_id") + else: + ancestor_id = None # Build OpenPype compatible name if item_type in ["Shot", "Sequence"] and parent_zou_id is not None: @@ -239,7 +249,7 @@ def update_op_assets( item_name = f"{item_data['parents'][-1]}_{item['name']}" # Update doc name - asset_doc_ids[item["id"]]["name"] = item_name + asset_dict_ids[item["id"]]["name"] = item_name else: item_name = item["name"] @@ -258,7 +268,7 @@ def update_op_assets( "$set": { "name": item_name, "data": item_data, - "parent": project_doc["_id"], + "parent": project_dict["_id"], } }, ) @@ -278,13 +288,13 @@ def write_project_to_op(project: dict, dbcon: AvalonMongoDB) -> UpdateOne: UpdateOne: Update instance for the project """ project_name = project["name"] - project_doc = get_project(project_name) - if not project_doc: + project_dict = get_project(project_name) + if not project_dict: log.info("Project created: {}".format(project_name)) - project_doc = create_project(project_name, project_name) + project_dict = create_project(project_name, project_name) # Project data and tasks - project_data = project_doc["data"] or {} + project_data = project_dict["data"] or {} # Build project code and update Kitsu project_code = project.get("code") @@ -315,7 +325,7 @@ def write_project_to_op(project: dict, dbcon: AvalonMongoDB) -> UpdateOne: ) return UpdateOne( - {"_id": project_doc["_id"]}, + {"_id": project_dict["_id"]}, { "$set": { "config.tasks": { @@ -398,7 +408,7 @@ def sync_project_from_kitsu(dbcon: AvalonMongoDB, project: dict): # Try to find project document project_name = project["name"] dbcon.Session["AVALON_PROJECT"] = project_name - project_doc = get_project(project_name) + project_dict = get_project(project_name) # Query all assets of the local project zou_ids_and_asset_docs = { @@ -406,7 +416,7 @@ def sync_project_from_kitsu(dbcon: AvalonMongoDB, project: dict): for asset_doc in get_assets(project_name) if asset_doc["data"].get("zou", {}).get("id") } - zou_ids_and_asset_docs[project["id"]] = project_doc + zou_ids_and_asset_docs[project["id"]] = project_dict # Create entities root folders to_insert = [ @@ -453,7 +463,7 @@ def sync_project_from_kitsu(dbcon: AvalonMongoDB, project: dict): [ UpdateOne({"_id": id}, update) for id, update in update_op_assets( - dbcon, project, project_doc, + dbcon, project, project_dict, all_entities, zou_ids_and_asset_docs ) ] From 0f76d3a44e4974b5c0ec81f166a19289d9cb4fd6 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 28 Feb 2023 23:13:33 +0100 Subject: [PATCH 283/898] Cleaned up the fetching of the entity_id Also changed the name kitsu_id to entity_id and kitsu_entity to just entity as that's what it is. --- .../plugins/publish/collect_kitsu_entities.py | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py index dc7048cf2af..1531c80e047 100644 --- a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py +++ b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py @@ -16,7 +16,6 @@ def process(self, context): kitsu_entities_by_id = {} for instance in context: asset_doc = instance.data.get("assetEntity") - task_name = instance.data.get("task") if not asset_doc: continue @@ -24,27 +23,24 @@ def process(self, context): if not zou_asset_data: raise ValueError("Zou asset data not found in OpenPype!") - if kitsu_project is None: - kitsu_project = gazu.project.get_project( - zou_asset_data["project_id"]) - if not kitsu_project: - raise ValueError("Project not found in kitsu!") + kitsu_project = gazu.project.get_project( + zou_asset_data["project_id"]) + if not kitsu_project: + raise ValueError("Project not found in kitsu!") - entity_type = zou_asset_data["type"] - kitsu_id = zou_asset_data["id"] - kitsu_entity = kitsu_entities_by_id.get(kitsu_id) - if not kitsu_entity: - if entity_type == "Shot": - kitsu_entity = gazu.shot.get_shot(kitsu_id) - else: - kitsu_entity = gazu.asset.get_asset(kitsu_id) - kitsu_entities_by_id[kitsu_id] = kitsu_entity + entity_id = zou_asset_data["id"] + entity = kitsu_entities_by_id.get(entity_id) + if not entity: + entity = gazu.entity.get_entity(entity_id) + if not entity: + raise ValueError( + "{} was not found in kitsu!".format( + zou_asset_data["name"])) - if not kitsu_entity: - raise ValueError( - "{} not found in kitsu!".format(entity_type)) - instance.data["kitsu_entity"] = kitsu_entity + kitsu_entities_by_id[entity_id] = entity + instance.data["entity"] = entity + task_name = instance.data.get("task") if not task_name: continue zou_task_data = asset_doc["data"]["tasks"][task_name].get("zou") From 13a4c7201e5fd410e3546b4cd898ab8f0068b4ab Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 28 Feb 2023 23:18:43 +0100 Subject: [PATCH 284/898] change task to task_id --- .../modules/kitsu/plugins/publish/integrate_kitsu_note.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 54fb6a46785..006f0bc6d06 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -44,12 +44,12 @@ def process(self, context): ) # Add comment to kitsu task - task = kitsu_task["id"] + task_id = kitsu_task["id"] self.log.debug( - "Add new note in taks id {}".format(task) + "Add new note in taks id {}".format(task_id) ) kitsu_comment = gazu.task.add_comment( - task, note_status, comment=publish_comment + task_id, note_status, comment=publish_comment ) instance.data["kitsu_comment"] = kitsu_comment From bcea2c70a269559a2fa370185393d6c4b675a38b Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 28 Feb 2023 23:20:32 +0100 Subject: [PATCH 285/898] Cleaned up project deletion code --- openpype/modules/kitsu/utils/sync_service.py | 22 ++++++++------------ 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/openpype/modules/kitsu/utils/sync_service.py b/openpype/modules/kitsu/utils/sync_service.py index 1af0b6edc44..6155b396aa7 100644 --- a/openpype/modules/kitsu/utils/sync_service.py +++ b/openpype/modules/kitsu/utils/sync_service.py @@ -149,20 +149,16 @@ def _delete_project(self, data): """Delete project.""" collections = self.dbcon.database.list_collection_names() - project_name = None for collection in collections: - post = self.dbcon.database[collection].find_one( - {"data.zou_id": data['project_id']}) - if post: - project_name = post['name'] - break - - if project_name: - # Delete project collection - self.dbcon.database[project_name].drop() - - # Print message - log.info("Project deleted: {}".format(project_name)) + project = self.dbcon.database[collection].find_one( + {"data.zou_id": data["project_id"]}) + if project: + # Delete project collection + self.dbcon.database[project["name"]].drop() + + # Print message + log.info("Project deleted: {}".format(project["name"])) + return # == Asset == def _new_asset(self, data): From d9ac1ee95255c2d663cffaa00e63ad99a74188af Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 28 Feb 2023 23:24:55 +0100 Subject: [PATCH 286/898] Cleaned up log.info() message creation --- openpype/modules/kitsu/utils/sync_service.py | 181 +++++++++++-------- 1 file changed, 101 insertions(+), 80 deletions(-) diff --git a/openpype/modules/kitsu/utils/sync_service.py b/openpype/modules/kitsu/utils/sync_service.py index 6155b396aa7..b389d25c4f8 100644 --- a/openpype/modules/kitsu/utils/sync_service.py +++ b/openpype/modules/kitsu/utils/sync_service.py @@ -176,17 +176,18 @@ def _new_asset(self, data): self._update_asset(data) # Print message - episode = None + ep = None ep_id = asset.get("episode_id") if ep_id and ep_id != "": - episode = gazu.asset.get_episode(ep_id) - - msg = "Asset created: " - msg = msg + f"{asset['project_name']} - " - if episode is not None: - msg = msg + f"{episode['name']}_" - msg = msg + f"{asset['asset_type_name']}_" - msg = msg + f"{asset['name']}" + ep = gazu.asset.get_episode(ep_id) + + msg = "Asset created: {proj_name} - {ep_name}" \ + "{asset_type_name} - {asset_name}".format( + proj_name=asset["project_name"], + ep_name=ep["name"] + " - " if ep is not None else "", + asset_type_name=asset["asset_type_name"], + asset_name=asset["name"] + ) log.info(msg) def _update_asset(self, data): @@ -229,17 +230,18 @@ def _delete_asset(self, data): ) # Print message - episode = None + ep = None ep_id = asset["data"]["zou"].get("episode_id") if ep_id and ep_id != "": - episode = gazu.asset.get_episode(ep_id) - - msg = "Asset deleted: " - msg = msg + f"{asset['data']['zou']['project_name']} - " - if episode is not None: - msg = msg + f"{episode['name']}_" - msg = msg + f"{asset['data']['zou']['asset_type_name']}_" - msg = msg + f"'{asset['name']}" + ep = gazu.asset.get_episode(ep_id) + + msg = "Asset deleted: {proj_name} - {ep_name}" \ + "{asset_type_name} - {asset_name}".format( + proj_name=asset["data"]["zou"]["project_name"], + ep_name=ep["name"] + " - " if ep is not None else "", + asset_type_name=asset["data"]["zou"]["asset_type_name"], + asset_name=asset["name"] + ) log.info(msg) # == Episode == @@ -252,15 +254,17 @@ def _new_episode(self, data): ep = gazu.shot.get_episode(data["episode_id"]) # Insert doc in DB - self.dbcon.insert_one(create_op_asset(episode)) + self.dbcon.insert_one(create_op_asset(ep)) # Update self._update_episode(data) # Print message - msg = "Episode created: " - msg = msg + f"{episode['project_name']} - " - msg = msg + f"{episode['name']}" + msg = "Episode created: {proj_name} - {ep_name}".format( + proj_name=ep["project_name"], + ep_name=ep["name"] + ) + log.info(msg) def _update_episode(self, data): """Update episode into OP DB.""" @@ -283,8 +287,8 @@ def _update_episode(self, data): # Update update_op_result = update_op_assets( - self.dbcon, gazu_project, project_doc, [ - episode], zou_ids_and_asset_docs + self.dbcon, gazu_project, project_doc, + [ep], zou_ids_and_asset_docs ) if update_op_result: asset_doc_id, asset_update = update_op_result[0] @@ -294,20 +298,22 @@ def _delete_episode(self, data): """Delete shot of OP DB.""" set_op_project(self.dbcon, data["project_id"]) - episode = self.dbcon.find_one({"data.zou.id": data['episode_id']}) - if episode: + ep = self.dbcon.find_one({"data.zou.id": data["episode_id"]}) + if ep: # Delete self.dbcon.delete_one( - {"type": "asset", "data.zou.id": data['episode_id']} + {"type": "asset", "data.zou.id": data["episode_id"]} ) # Print message project = gazu.project.get_project( - episode['data']['zou']['project_id']) + ep["data"]["zou"]["project_id"]) - msg = "Episode deleted: " - msg = msg + f"{project['name']} - " - msg = msg + f"{episode['name']}" + msg = "Episode deleted: {proj_name} - {ep_name}".format( + proj_name=project["name"], + ep_name=ep["name"] + ) + log.info(msg) # == Sequence == def _new_sequence(self, data): @@ -325,17 +331,17 @@ def _new_sequence(self, data): self._update_sequence(data) # Print message - - episode = None + ep = None ep_id = sequence.get("episode_id") if ep_id and ep_id != "": - episode = gazu.asset.get_episode(ep_id) + ep = gazu.asset.get_episode(ep_id) - msg = "Sequence created: " - msg = msg + f"{sequence['project_name']} - " - if episode is not None: - msg = msg + f"{episode['name']}_" - msg = msg + f"{sequence['name']}" + msg = "Sequence created: {proj_name} - {ep_name}" \ + "{sequence_name}".format( + proj_name=sequence["project_name"], + ep_name=ep["name"] + " - " if ep is not None else "", + sequence_name=sequence["name"] + ) log.info(msg) def _update_sequence(self, data): @@ -377,12 +383,20 @@ def _delete_sequence(self, data): ) # Print message + ep = None ep_id = sequence["data"]["zou"].get("episode_id") + if ep_id and ep_id != "": + ep = gazu.asset.get_episode(ep_id) + gazu_project = gazu.project.get_project( - sequence['data']['zou']['project_id']) - msg = f"Sequence deleted: " - msg = msg + f"{gazu_project['name']} - " - msg = msg + f"{sequence['name']}" + sequence["data"]["zou"]["project_id"]) + + msg = "Sequence created: {proj_name} - {ep_name}" \ + "{sequence_name}".format( + proj_name=gazu_project["name"], + ep_name=ep["name"] + " - " if ep is not None else "", + sequence_name=sequence["name"] + ) log.info(msg) # == Shot == @@ -401,16 +415,17 @@ def _new_shot(self, data): self._update_shot(data) # Print message - episode = None + ep = None if shot["episode_id"] and shot["episode_id"] != "": - episode = gazu.asset.get_episode(shot['episode_id']) - - msg = "Shot created: " - msg = msg + f"{shot['project_name']} - " - if episode is not None: - msg = msg + f"{episode['name']}_" - msg = msg + f"{shot['sequence_name']}_" - msg = msg + f"{shot['name']}" + ep = gazu.asset.get_episode(shot["episode_id"]) + + msg = "Shot created: {proj_name} - {ep_name}" \ + "{sequence_name} - {shot_name}".format( + proj_name=shot["project_name"], + ep_name=ep["name"] + " - " if ep is not None else "", + sequence_name=shot["sequence_name"], + shot_name=shot["name"] + ) log.info(msg) def _update_shot(self, data): @@ -430,7 +445,6 @@ def _update_shot(self, data): if asset_doc["data"].get("zou", {}).get("id")} zou_ids_and_asset_docs[shot["project_id"]] = project_doc gazu_project = gazu.project.get_project(shot["project_id"]) - gazu_project = gazu.project.get_project(shot['project_id']) # Update update_op_result = update_op_assets( @@ -454,12 +468,18 @@ def _delete_shot(self, data): ) # Print message - gazu_project = gazu.project.get_project( + ep = None ep_id = shot["data"]["zou"].get("episode_id") - - msg = "Shot deleted: " - msg = msg + f"{gazu_project['name']} - " - msg = msg + f"{shot['name']}" + if ep_id and ep_id != "": + ep = gazu.asset.get_episode(ep_id) + + msg = "Shot deleted: {proj_name} - {ep_name}" \ + "{sequence_name} - {shot_name}".format( + proj_name=shot["data"]["zou"]["project_name"], + ep_name=ep["name"] + " - " if ep is not None else "", + sequence_name=shot["data"]["zou"]["sequence_name"], + shot_name=shot["name"] + ) log.info(msg) # == Task == @@ -472,14 +492,14 @@ def _new_task(self, data): # Get gazu entity task = gazu.task.get_task(data["task_id"]) - # Find asset doc - episode = None + # Print message + ep = None ep_id = task.get("episode_id") if ep_id and ep_id != "": - episode = gazu.asset.get_episode(ep_id) + ep = gazu.asset.get_episode(ep_id) - parent_name = "" - if episode is not None: + parent_name = None + entity_type = None parent_name = episode['name'] + "_" parent_name = parent_name + \ task['sequence']['name'] + "_" + task['entity']['name'] @@ -496,13 +516,13 @@ def _new_task(self, data): ) # Print message - msg = "Task created: " - msg = msg + f"{task['project']['name']} - " - if episode is not None: - msg = msg + f"{episode['name']}_" - msg = msg + f"{task['sequence']['name']}_" - msg = msg + f"{task['entity']['name']} - " - msg = msg + f"{task['task_type']['name']}" + msg = "Task created: {proj_name} - {entity_type}{parent_name}" \ + " - {task_name}".format( + proj_name=task["project"]["name"], + entity_type=entity_type + " - " if entity_type is not None else "", + parent_name=parent_name, + task_name=task["task_type"]["name"] + ) log.info(msg) def _update_task(self, data): @@ -533,19 +553,20 @@ def _delete_task(self, data): # Print message entity = gazu.entity.get_entity(task["zou"]["entity_id"]) - episode = None + ep = None ep_id = entity.get("episode_id") if ep_id and ep_id != "": - episode = gazu.asset.get_episode(ep_id) - - msg = "Task deleted: " - msg = msg + f"{shot['project_name']} - " - if episode is not None: - msg = msg + f"{episode['name']}_" - msg = msg + f"{shot['sequence_name']}_" - msg = msg + f"{shot['name']} - " - msg = msg + f"{task['type']}" + ep = gazu.asset.get_episode(ep_id) + + msg = "Task deleted: {proj_name} - {entity_type}{parent_name}" \ + " - {task_name}".format( + proj_name=task["zou"]["project"]["name"], + entity_type=entity_type + " - " if entity_type is not None else "", + parent_name=parent_name, + task_name=task["type"] + ) log.info(msg) + return From d153e6c224a6d2ea21b11a1c33e88b2c19049123 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 28 Feb 2023 23:26:10 +0100 Subject: [PATCH 287/898] Split up the difference in name and type Assets/Shots generate Before it was only working for shots. Now it also works for Assets. I'm ding an elif as Kitsu now also have tasks for sequences, edits and other things. Will try and add those in at a later stage. --- openpype/modules/kitsu/utils/sync_service.py | 24 +++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/openpype/modules/kitsu/utils/sync_service.py b/openpype/modules/kitsu/utils/sync_service.py index b389d25c4f8..7e7f3f557c8 100644 --- a/openpype/modules/kitsu/utils/sync_service.py +++ b/openpype/modules/kitsu/utils/sync_service.py @@ -500,9 +500,15 @@ def _new_task(self, data): parent_name = None entity_type = None - parent_name = episode['name'] + "_" - parent_name = parent_name + \ - task['sequence']['name'] + "_" + task['entity']['name'] + if task["task_type"]["for_entity"] == "Asset": + parent_name = task["entity"]["name"] + entity_type = task["entity_type"]["name"] + elif task["task_type"]["for_entity"] == "Shot": + parent_name = "{ep_name}{sequence_name} - {shot_name}".format( + ep_name=ep["name"] + " - " if ep is not None else "", + sequence_name=task["sequence"]["name"], + shot_name=task["entity"]["name"] + ) # Update asset tasks with new one asset_doc = get_asset_by_name(project_name, parent_name) @@ -558,6 +564,18 @@ def _delete_task(self, data): if ep_id and ep_id != "": ep = gazu.asset.get_episode(ep_id) + parent_name = None + entity_type = None + if task["task_type"]["for_entity"] == "Asset": + parent_name = task["entity"]["name"] + entity_type = task["entity_type"]["name"] + elif task["task_type"]["for_entity"] == "Shot": + parent_name = "{ep_name}{sequence_name} - {shot_name}".format( + ep_name=ep["name"] + " - " if ep is not None else "", + sequence_name=task["sequence"]["name"], + shot_name=task["entity"]["name"] + ) + msg = "Task deleted: {proj_name} - {entity_type}{parent_name}" \ " - {task_name}".format( proj_name=task["zou"]["project"]["name"], From 7965b91dafd59e0a75b498961d94aa8fdaa14467 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Wed, 1 Mar 2023 11:02:25 +0100 Subject: [PATCH 288/898] Moved kitsu_project out of context loop --- .../plugins/publish/collect_kitsu_entities.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py index 1531c80e047..f68226a4a5e 100644 --- a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py +++ b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py @@ -11,7 +11,13 @@ class CollectKitsuEntities(pyblish.api.ContextPlugin): def process(self, context): - kitsu_project = None + kitsu_project = gazu.project.get_project_by_name( + context.data["projectName"]) + if not kitsu_project: + raise ValueError("Project not found in kitsu!") + + context.data["kitsu_project"] = kitsu_project + self.log.debug("Collect kitsu project: {}".format(kitsu_project)) kitsu_entities_by_id = {} for instance in context: @@ -23,10 +29,10 @@ def process(self, context): if not zou_asset_data: raise ValueError("Zou asset data not found in OpenPype!") - kitsu_project = gazu.project.get_project( - zou_asset_data["project_id"]) - if not kitsu_project: - raise ValueError("Project not found in kitsu!") + task_name = instance.data.get("task") + if not task_name: + continue + entity_id = zou_asset_data["id"] entity = kitsu_entities_by_id.get(entity_id) @@ -63,5 +69,3 @@ def process(self, context): raise ValueError("Task not found in kitsu!") instance.data["kitsu_task"] = kitsu_task self.log.debug("Collect kitsu task: {}".format(kitsu_task)) - - context.data["kitsu_project"] = kitsu_project From 962d0783b06d804cacf1ce628d17e1d0836951b2 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Wed, 1 Mar 2023 11:05:38 +0100 Subject: [PATCH 289/898] Fixed fetching of kitsu_task + moved data checks to the top of loop --- .../plugins/publish/collect_kitsu_entities.py | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py index f68226a4a5e..9b34bd15a9b 100644 --- a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py +++ b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py @@ -33,6 +33,9 @@ def process(self, context): if not task_name: continue + zou_task_data = asset_doc["data"]["tasks"][task_name].get("zou") + self.log.debug( + "Collected zou task data: {}".format(zou_task_data)) entity_id = zou_asset_data["id"] entity = kitsu_entities_by_id.get(entity_id) @@ -45,25 +48,26 @@ def process(self, context): kitsu_entities_by_id[entity_id] = entity instance.data["entity"] = entity - - task_name = instance.data.get("task") - if not task_name: - continue - zou_task_data = asset_doc["data"]["tasks"][task_name].get("zou") self.log.debug( - "Collected zou task data: {}".format(zou_task_data)) - if not zou_task_data: + "Collect kitsu {}: {}".format(zou_asset_data["type"], entity) + ) + + if zou_task_data: + kitsu_task_id = zou_task_data["id"] + kitsu_task = kitsu_entities_by_id.get(kitsu_task_id) + if not kitsu_task: + kitsu_task = gazu.task.get_task(zou_task_data["id"]) + kitsu_entities_by_id[kitsu_task_id] = kitsu_task + else: kitsu_task_type = gazu.task.get_task_type_by_name(task_name) if not kitsu_task_type: raise ValueError( "Task type {} not found in Kitsu!".format(task_name) ) - continue - kitsu_task_id = zou_task_data["id"] - kitsu_task = kitsu_entities_by_id.get(kitsu_task_id) - if not kitsu_task: - kitsu_task = gazu.task.get_task(zou_task_data["id"]) - kitsu_entities_by_id[kitsu_task_id] = kitsu_task + + kitsu_task = gazu.task.get_task_by_name( + entity, kitsu_task_type + ) if not kitsu_task: raise ValueError("Task not found in kitsu!") From 8bf970e8b96b80c2cae601530d076b27d3a6d8f7 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Wed, 1 Mar 2023 11:16:05 +0100 Subject: [PATCH 290/898] fixed hound's comments --- .../kitsu/plugins/publish/collect_kitsu_entities.py | 2 +- openpype/modules/kitsu/utils/sync_service.py | 9 ++++++--- openpype/modules/kitsu/utils/update_op_with_zou.py | 6 ++++-- openpype/modules/kitsu/utils/update_zou_with_op.py | 3 ++- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py index 9b34bd15a9b..71ed5635801 100644 --- a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py +++ b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py @@ -64,7 +64,7 @@ def process(self, context): raise ValueError( "Task type {} not found in Kitsu!".format(task_name) ) - + kitsu_task = gazu.task.get_task_by_name( entity, kitsu_task_type ) diff --git a/openpype/modules/kitsu/utils/sync_service.py b/openpype/modules/kitsu/utils/sync_service.py index 7e7f3f557c8..9c5c9e24ec4 100644 --- a/openpype/modules/kitsu/utils/sync_service.py +++ b/openpype/modules/kitsu/utils/sync_service.py @@ -101,7 +101,8 @@ def __init__(self, login, password): self.event_client, "sequence:delete", self._delete_sequence ) - gazu.events.add_listener(self.event_client, "shot:new", self._new_shot) + gazu.events.add_listener( + self.event_client, "shot:new", self._new_shot) gazu.events.add_listener( self.event_client, "shot:update", self._update_shot ) @@ -109,7 +110,8 @@ def __init__(self, login, password): self.event_client, "shot:delete", self._delete_shot ) - gazu.events.add_listener(self.event_client, "task:new", self._new_task) + gazu.events.add_listener( + self.event_client, "task:new", self._new_task) gazu.events.add_listener( self.event_client, "task:update", self._update_task ) @@ -515,7 +517,8 @@ def _new_task(self, data): if asset_doc: asset_tasks = asset_doc["data"].get("tasks") task_type_name = task["task_type"]["name"] - asset_tasks[task_type_name] = {"type": task_type_name, "zou": task} + asset_tasks[task_type_name] = { + "type": task_type_name, "zou": task} self.dbcon.update_one( {"_id": asset_doc["_id"]}, {"$set": {"data.tasks": asset_tasks}} diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index 93688485325..6590d05a822 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -94,7 +94,8 @@ def update_op_assets( if not item_doc: # Create asset op_asset = create_op_asset(item) insert_result = dbcon.insert_one(op_asset) - item_doc = get_asset_by_id(project_name, insert_result.inserted_id) + item_doc = get_asset_by_id( + project_name, insert_result.inserted_id) # Update asset item_data = deepcopy(item_doc["data"]) @@ -339,7 +340,8 @@ def write_project_to_op(project: dict, dbcon: AvalonMongoDB) -> UpdateOne: ) -def sync_all_projects(login: str, password: str, ignore_projects: list = None): +def sync_all_projects( + login: str, password: str, ignore_projects: list = None): """Update all OP projects in DB with Zou data. Args: diff --git a/openpype/modules/kitsu/utils/update_zou_with_op.py b/openpype/modules/kitsu/utils/update_zou_with_op.py index b1a9b8b82c3..617f037c1e8 100644 --- a/openpype/modules/kitsu/utils/update_zou_with_op.py +++ b/openpype/modules/kitsu/utils/update_zou_with_op.py @@ -82,7 +82,8 @@ def sync_zou_from_op_project( f"x{project_doc['data']['resolutionHeight']}", } ) - gazu.project.update_project_data(zou_project, data=project_doc["data"]) + gazu.project.update_project_data( + zou_project, data=project_doc["data"]) gazu.project.update_project(zou_project) asset_types = gazu.asset.all_asset_types() From 0d981a61291d78f25c53425de4161d3f109f1505 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Wed, 1 Mar 2023 11:42:18 +0100 Subject: [PATCH 291/898] Fixed hound's comments --- openpype/modules/kitsu/utils/sync_service.py | 41 ++++++++++---------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/openpype/modules/kitsu/utils/sync_service.py b/openpype/modules/kitsu/utils/sync_service.py index 9c5c9e24ec4..da81a23495d 100644 --- a/openpype/modules/kitsu/utils/sync_service.py +++ b/openpype/modules/kitsu/utils/sync_service.py @@ -501,10 +501,10 @@ def _new_task(self, data): ep = gazu.asset.get_episode(ep_id) parent_name = None - entity_type = None + ent_type = None if task["task_type"]["for_entity"] == "Asset": parent_name = task["entity"]["name"] - entity_type = task["entity_type"]["name"] + ent_type = task["entity_type"]["name"] elif task["task_type"]["for_entity"] == "Shot": parent_name = "{ep_name}{sequence_name} - {shot_name}".format( ep_name=ep["name"] + " - " if ep is not None else "", @@ -525,12 +525,12 @@ def _new_task(self, data): ) # Print message - msg = "Task created: {proj_name} - {entity_type}{parent_name}" \ - " - {task_name}".format( - proj_name=task["project"]["name"], - entity_type=entity_type + " - " if entity_type is not None else "", - parent_name=parent_name, - task_name=task["task_type"]["name"] + msg = "Task created: {proj} - {ent_type}{parent}" \ + " - {task}".format( + proj=task["project"]["name"], + ent_type=ent_type + " - " if ent_type is not None else "", + parent=parent_name, + task=task["task_type"]["name"] ) log.info(msg) @@ -568,23 +568,24 @@ def _delete_task(self, data): ep = gazu.asset.get_episode(ep_id) parent_name = None - entity_type = None + ent_type = None if task["task_type"]["for_entity"] == "Asset": parent_name = task["entity"]["name"] - entity_type = task["entity_type"]["name"] + ent_type = task["entity_type"]["name"] elif task["task_type"]["for_entity"] == "Shot": - parent_name = "{ep_name}{sequence_name} - {shot_name}".format( - ep_name=ep["name"] + " - " if ep is not None else "", - sequence_name=task["sequence"]["name"], - shot_name=task["entity"]["name"] + parent_name = "{ep}{sequence} - {shot}".format( + ep=ep["name"] + " - " if ep is not None else "", + sequence=task["sequence"]["name"], + shot=task["entity"]["name"] ) - msg = "Task deleted: {proj_name} - {entity_type}{parent_name}" \ - " - {task_name}".format( - proj_name=task["zou"]["project"]["name"], - entity_type=entity_type + " - " if entity_type is not None else "", - parent_name=parent_name, - task_name=task["type"] + ent_type=ent_type + " - " if ent_type is not None else "", + msg = "Task deleted: {proj} - {ent_type}{parent}" \ + " - {task}".format( + proj=task["zou"]["project"]["name"], + ent_type=ent_type, + parent=parent_name, + task=task["type"] ) log.info(msg) From 0beec8c3a710e7c3e950678a4c0b6606f4f079d7 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Wed, 1 Mar 2023 11:44:55 +0100 Subject: [PATCH 292/898] Fixed hound's comments --- openpype/modules/kitsu/utils/sync_service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/modules/kitsu/utils/sync_service.py b/openpype/modules/kitsu/utils/sync_service.py index da81a23495d..91ce84637d1 100644 --- a/openpype/modules/kitsu/utils/sync_service.py +++ b/openpype/modules/kitsu/utils/sync_service.py @@ -579,7 +579,7 @@ def _delete_task(self, data): shot=task["entity"]["name"] ) - ent_type=ent_type + " - " if ent_type is not None else "", + ent_type=ent_type + " - " if ent_type is not None else "" msg = "Task deleted: {proj} - {ent_type}{parent}" \ " - {task}".format( proj=task["zou"]["project"]["name"], From 247778575f2e5c03cf055da288b444034bca4475 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 2 Mar 2023 12:30:19 +0100 Subject: [PATCH 293/898] Project creation logs happens outside of write_project_to_op() function --- openpype/modules/kitsu/utils/sync_service.py | 12 ++++++------ openpype/modules/kitsu/utils/update_op_with_zou.py | 9 ++++++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/openpype/modules/kitsu/utils/sync_service.py b/openpype/modules/kitsu/utils/sync_service.py index 91ce84637d1..172f7555acb 100644 --- a/openpype/modules/kitsu/utils/sync_service.py +++ b/openpype/modules/kitsu/utils/sync_service.py @@ -129,12 +129,9 @@ def _new_project(self, data): """Create new project into OP DB.""" # Use update process to avoid duplicating code - self._update_project(data) + self._update_project(data, new_project=True) - # Print message - # - Happens in write_project_to_op() - - def _update_project(self, data): + def _update_project(self, data, new_project=False): """Update project into OP DB.""" # Get project entity project = gazu.project.get_project(data["project_id"]) @@ -147,6 +144,9 @@ def _update_project(self, data): data["project_id"]) self.dbcon.bulk_write([update_project]) + if new_project: + log.info("Project created: {}".format(project["name"])) + def _delete_project(self, data): """Delete project.""" @@ -579,7 +579,7 @@ def _delete_task(self, data): shot=task["entity"]["name"] ) - ent_type=ent_type + " - " if ent_type is not None else "" + ent_type = ent_type + " - " if ent_type is not None else "" msg = "Task deleted: {proj} - {ent_type}{parent}" \ " - {task}".format( proj=task["zou"]["project"]["name"], diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index 6590d05a822..a559d8a19fb 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -291,7 +291,6 @@ def write_project_to_op(project: dict, dbcon: AvalonMongoDB) -> UpdateOne: project_name = project["name"] project_dict = get_project(project_name) if not project_dict: - log.info("Project created: {}".format(project_name)) project_dict = create_project(project_name, project_name) # Project data and tasks @@ -405,12 +404,16 @@ def sync_project_from_kitsu(dbcon: AvalonMongoDB, project: dict): ] # Sync project. Create if doesn't exist + project_name = project["name"] + project_dict = get_project(project_name) + if not project_dict: + log.info("Project created: {}".format(project_name)) bulk_writes.append(write_project_to_op(project, dbcon)) # Try to find project document - project_name = project["name"] + if not project_dict: + project_dict = get_project(project_name) dbcon.Session["AVALON_PROJECT"] = project_name - project_dict = get_project(project_name) # Query all assets of the local project zou_ids_and_asset_docs = { From 5a9ea0d130ba6009804ac479e3ebe6ef4ff46906 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 2 Mar 2023 12:36:57 +0100 Subject: [PATCH 294/898] Changed back from dict to doc for var names --- .../modules/kitsu/utils/update_op_with_zou.py | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index a559d8a19fb..c215126dacd 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -65,32 +65,32 @@ def set_op_project(dbcon: AvalonMongoDB, project_id: str): def update_op_assets( dbcon: AvalonMongoDB, gazu_project: dict, - project_dict: dict, + project_doc: dict, entities_list: List[dict], - asset_dict_ids: Dict[str, dict], + asset_doc_ids: Dict[str, dict], ) -> List[Dict[str, dict]]: """Update OpenPype assets. Set 'data' and 'parent' fields. Args: dbcon (AvalonMongoDB): Connection to DB - gazu_project dict): Dict of gazu, - project_dict dict): Dict of project, + gazu_project (dict): Dict of gazu, + project_doc (dict): Dict of project, entities_list (List[dict]): List of zou entities to update - asset_dict_ids (Dict[str, dict]): Dicts of [{zou_id: asset_doc}, ...] + asset_doc_ids (Dict[str, dict]): Dicts of [{zou_id: asset_doc}, ...] Returns: List[Dict[str, dict]]: List of (doc_id, update_dict) tuples """ - if not project_dict: + if not project_doc: return - project_name = project_dict["name"] + project_name = project_doc["name"] assets_with_update = [] for item in entities_list: # Check asset exists - item_doc = asset_dict_ids.get(item["id"]) + item_doc = asset_doc_ids.get(item["id"]) if not item_doc: # Create asset op_asset = create_op_asset(item) insert_result = dbcon.insert_one(op_asset) @@ -108,7 +108,7 @@ def update_op_assets( try: frame_in = int( item_data.pop( - "frame_in", project_dict["data"].get("frameStart") + "frame_in", project_doc["data"].get("frameStart") ) ) except (TypeError, ValueError): @@ -127,14 +127,14 @@ def update_op_assets( if frames_duration: frame_out = frame_in + frames_duration - 1 else: - frame_out = project_dict["data"].get("frameEnd", frame_in) + frame_out = project_doc["data"].get("frameEnd", frame_in) item_data["frameEnd"] = frame_out # Fps, fallback to project's value or default value (25.0) try: fps = float(item_data.get("fps")) except (TypeError, ValueError): fps = float(gazu_project.get( - "fps", project_dict["data"].get("fps", 25))) + "fps", project_doc["data"].get("fps", 25))) item_data["fps"] = fps # Resolution, fall back to project default match_res = re.match( @@ -145,27 +145,27 @@ def update_op_assets( item_data["resolutionWidth"] = int(match_res.group(1)) item_data["resolutionHeight"] = int(match_res.group(2)) else: - item_data["resolutionWidth"] = project_dict["data"].get( + item_data["resolutionWidth"] = project_doc["data"].get( "resolutionWidth") - item_data["resolutionHeight"] = project_dict["data"].get( + item_data["resolutionHeight"] = project_doc["data"].get( "resolutionHeight") # Properties that doesn't fully exist in Kitsu. # Guessing those property names below: # Pixel Aspect Ratio item_data["pixelAspect"] = item_data.get( - "pixel_aspect", project_dict["data"].get("pixelAspect")) + "pixel_aspect", project_doc["data"].get("pixelAspect")) # Handle Start item_data["handleStart"] = item_data.get( - "handle_start", project_dict["data"].get("handleStart")) + "handle_start", project_doc["data"].get("handleStart")) # Handle End item_data["handleEnd"] = item_data.get( - "handle_end", project_dict["data"].get("handleEnd")) + "handle_end", project_doc["data"].get("handleEnd")) # Clip In item_data["clipIn"] = item_data.get( - "clip_in", project_dict["data"].get("clipIn")) + "clip_in", project_doc["data"].get("clipIn")) # Clip Out item_data["clipOut"] = item_data.get( - "clip_out", project_dict["data"].get("clipOut")) + "clip_out", project_doc["data"].get("clipOut")) # Tasks tasks_list = [] @@ -209,7 +209,7 @@ def update_op_assets( # Root parent folder if exist visual_parent_doc_id = None if parent_zou_id is not None: - parent_zou_id_dict = asset_dict_ids.get(parent_zou_id) + parent_zou_id_dict = asset_doc_ids.get(parent_zou_id) if parent_zou_id_dict is not None: visual_parent_doc_id = ( parent_zou_id_dict.get("_id") @@ -233,7 +233,7 @@ def update_op_assets( item_data["parents"] = [] ancestor_id = parent_zou_id while ancestor_id is not None: - parent_doc = asset_dict_ids.get(ancestor_id) + parent_doc = asset_doc_ids.get(ancestor_id) if parent_doc is not None: item_data["parents"].insert(0, parent_doc["name"]) @@ -250,7 +250,7 @@ def update_op_assets( item_name = f"{item_data['parents'][-1]}_{item['name']}" # Update doc name - asset_dict_ids[item["id"]]["name"] = item_name + asset_doc_ids[item["id"]]["name"] = item_name else: item_name = item["name"] @@ -269,7 +269,7 @@ def update_op_assets( "$set": { "name": item_name, "data": item_data, - "parent": project_dict["_id"], + "parent": project_doc["_id"], } }, ) From 93eb9fce8609b0d6543a1f91ddb84907f89b63a3 Mon Sep 17 00:00:00 2001 From: Ember Light <49758407+EmberLightVFX@users.noreply.github.com> Date: Thu, 2 Mar 2023 12:38:37 +0100 Subject: [PATCH 295/898] Update openpype/modules/kitsu/utils/sync_service.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Félix David --- openpype/modules/kitsu/utils/sync_service.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/modules/kitsu/utils/sync_service.py b/openpype/modules/kitsu/utils/sync_service.py index 172f7555acb..1efebb2d47d 100644 --- a/openpype/modules/kitsu/utils/sync_service.py +++ b/openpype/modules/kitsu/utils/sync_service.py @@ -178,10 +178,11 @@ def _new_asset(self, data): self._update_asset(data) # Print message - ep = None ep_id = asset.get("episode_id") if ep_id and ep_id != "": ep = gazu.asset.get_episode(ep_id) + else: + ep = None msg = "Asset created: {proj_name} - {ep_name}" \ "{asset_type_name} - {asset_name}".format( From 95e1f95bc1896547bde026f5c2a2517103e9e8e8 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 2 Mar 2023 14:05:36 +0100 Subject: [PATCH 296/898] Moved all ep_dict code into one function --- openpype/modules/kitsu/utils/sync_service.py | 35 ++++++++------------ 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/openpype/modules/kitsu/utils/sync_service.py b/openpype/modules/kitsu/utils/sync_service.py index 1efebb2d47d..d6bdb5391e5 100644 --- a/openpype/modules/kitsu/utils/sync_service.py +++ b/openpype/modules/kitsu/utils/sync_service.py @@ -124,6 +124,11 @@ def start(self): log.info("Listening to Kitsu events...") gazu.events.run_client(self.event_client) + def get_ep_dict(self, ep_id): + if ep_id and ep_id != "": + return gazu.entity.get_entity(ep_id) + return + # == Project == def _new_project(self, data): """Create new project into OP DB.""" @@ -179,10 +184,7 @@ def _new_asset(self, data): # Print message ep_id = asset.get("episode_id") - if ep_id and ep_id != "": - ep = gazu.asset.get_episode(ep_id) - else: - ep = None + ep = self.get_ep_dict(ep_id) msg = "Asset created: {proj_name} - {ep_name}" \ "{asset_type_name} - {asset_name}".format( @@ -233,10 +235,8 @@ def _delete_asset(self, data): ) # Print message - ep = None ep_id = asset["data"]["zou"].get("episode_id") - if ep_id and ep_id != "": - ep = gazu.asset.get_episode(ep_id) + ep = self.get_ep_dict(ep_id) msg = "Asset deleted: {proj_name} - {ep_name}" \ "{asset_type_name} - {asset_name}".format( @@ -334,10 +334,8 @@ def _new_sequence(self, data): self._update_sequence(data) # Print message - ep = None ep_id = sequence.get("episode_id") - if ep_id and ep_id != "": - ep = gazu.asset.get_episode(ep_id) + ep = self.get_ep_dict(ep_id) msg = "Sequence created: {proj_name} - {ep_name}" \ "{sequence_name}".format( @@ -386,10 +384,8 @@ def _delete_sequence(self, data): ) # Print message - ep = None ep_id = sequence["data"]["zou"].get("episode_id") - if ep_id and ep_id != "": - ep = gazu.asset.get_episode(ep_id) + ep = self.get_ep_dict(ep_id) gazu_project = gazu.project.get_project( sequence["data"]["zou"]["project_id"]) @@ -418,9 +414,8 @@ def _new_shot(self, data): self._update_shot(data) # Print message - ep = None - if shot["episode_id"] and shot["episode_id"] != "": - ep = gazu.asset.get_episode(shot["episode_id"]) + ep_id = shot["episode_id"] + ep = self.get_ep_dict(ep_id) msg = "Shot created: {proj_name} - {ep_name}" \ "{sequence_name} - {shot_name}".format( @@ -471,10 +466,8 @@ def _delete_shot(self, data): ) # Print message - ep = None ep_id = shot["data"]["zou"].get("episode_id") - if ep_id and ep_id != "": - ep = gazu.asset.get_episode(ep_id) + ep = self.get_ep_dict(ep_id) msg = "Shot deleted: {proj_name} - {ep_name}" \ "{sequence_name} - {shot_name}".format( @@ -496,10 +489,8 @@ def _new_task(self, data): task = gazu.task.get_task(data["task_id"]) # Print message - ep = None ep_id = task.get("episode_id") - if ep_id and ep_id != "": - ep = gazu.asset.get_episode(ep_id) + ep = self.get_ep_dict(ep_id) parent_name = None ent_type = None From 966ba0166e349b2882cb5db1f686b6235abbd44b Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 2 Mar 2023 14:07:14 +0100 Subject: [PATCH 297/898] Fixed delete_task msg creation to work with assets and episodes --- openpype/modules/kitsu/utils/sync_service.py | 43 ++++++++++---------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/openpype/modules/kitsu/utils/sync_service.py b/openpype/modules/kitsu/utils/sync_service.py index d6bdb5391e5..893d6a8b5e1 100644 --- a/openpype/modules/kitsu/utils/sync_service.py +++ b/openpype/modules/kitsu/utils/sync_service.py @@ -554,31 +554,32 @@ def _delete_task(self, data): # Print message entity = gazu.entity.get_entity(task["zou"]["entity_id"]) - ep = None - ep_id = entity.get("episode_id") - if ep_id and ep_id != "": - ep = gazu.asset.get_episode(ep_id) - - parent_name = None - ent_type = None - if task["task_type"]["for_entity"] == "Asset": - parent_name = task["entity"]["name"] - ent_type = task["entity_type"]["name"] - elif task["task_type"]["for_entity"] == "Shot": - parent_name = "{ep}{sequence} - {shot}".format( + if entity["type"] == "Asset": + ep = self.get_ep_dict(entity["source_id"]) + + parent_name = "{ep}{entity_type} - {entity}".format( ep=ep["name"] + " - " if ep is not None else "", - sequence=task["sequence"]["name"], - shot=task["entity"]["name"] + entity_type=task["zou"]["entity_type_name"], + entity=task["zou"]["entity_name"] ) + elif entity["type"] == "Shot": + shot_dict = gazu.entity.get_entity( + task["zou"]["entity_id"]) + seq_dict = gazu.entity.get_entity( + shot_dict["parent_id"]) + ep = self.get_ep_dict(seq_dict["parent_id"]) - ent_type = ent_type + " - " if ent_type is not None else "" - msg = "Task deleted: {proj} - {ent_type}{parent}" \ - " - {task}".format( - proj=task["zou"]["project"]["name"], - ent_type=ent_type, - parent=parent_name, - task=task["type"] + parent_name = "{ep}{sequence} - {shot}".format( + ep=ep["name"] + " - " if ep is not None else "", + sequence=seq_dict["name"], + shot=shot_dict["name"] ) + + msg = "Task deleted: {proj} - {parent} - {task}".format( + proj=task["zou"]["project_name"], + parent=parent_name, + task=task["zou"]["task_type_name"] + ) log.info(msg) return From 804cdcafd6268d84a3c7d2e887c9e05e5798dec4 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 2 Mar 2023 19:33:11 +0100 Subject: [PATCH 298/898] Store the gazu asset data in OPs DB as sync_service does This isn't the most optimal way to do it but it makes sure the data is consistent through out the code until we can revision sync_service to only use the ID from the dict. --- openpype/modules/kitsu/utils/update_op_with_zou.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index c215126dacd..6797df63441 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -175,7 +175,7 @@ def update_op_assets( elif item_type == "Shot": tasks_list = gazu.task.all_tasks_for_shot(item) item_data["tasks"] = { - t["task_type_name"]: {"type": t["task_type_name"], "zou": t} + t["task_type_name"]: {"type": t["task_type_name"], "zou": gazu.task.get_task(t["id"])} for t in tasks_list } From 7176be9f92e71ee6942971e25ffc72199c1eecf8 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 2 Mar 2023 19:35:07 +0100 Subject: [PATCH 299/898] Log msg for new_task now work for both shot and assets --- openpype/modules/kitsu/utils/sync_service.py | 37 ++++++++++---------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/openpype/modules/kitsu/utils/sync_service.py b/openpype/modules/kitsu/utils/sync_service.py index 893d6a8b5e1..1f12217d446 100644 --- a/openpype/modules/kitsu/utils/sync_service.py +++ b/openpype/modules/kitsu/utils/sync_service.py @@ -239,10 +239,10 @@ def _delete_asset(self, data): ep = self.get_ep_dict(ep_id) msg = "Asset deleted: {proj_name} - {ep_name}" \ - "{asset_type_name} - {asset_name}".format( + "{type_name} - {asset_name}".format( proj_name=asset["data"]["zou"]["project_name"], ep_name=ep["name"] + " - " if ep is not None else "", - asset_type_name=asset["data"]["zou"]["asset_type_name"], + type_name=asset["data"]["zou"]["asset_type_name"], asset_name=asset["name"] ) log.info(msg) @@ -390,7 +390,7 @@ def _delete_sequence(self, data): gazu_project = gazu.project.get_project( sequence["data"]["zou"]["project_id"]) - msg = "Sequence created: {proj_name} - {ep_name}" \ + msg = "Sequence deleted: {proj_name} - {ep_name}" \ "{sequence_name}".format( proj_name=gazu_project["name"], ep_name=ep["name"] + " - " if ep is not None else "", @@ -493,9 +493,12 @@ def _new_task(self, data): ep = self.get_ep_dict(ep_id) parent_name = None + asset_name = None ent_type = None + if task["task_type"]["for_entity"] == "Asset": parent_name = task["entity"]["name"] + asset_name = task["entity"]["name"] ent_type = task["entity_type"]["name"] elif task["task_type"]["for_entity"] == "Shot": parent_name = "{ep_name}{sequence_name} - {shot_name}".format( @@ -503,9 +506,14 @@ def _new_task(self, data): sequence_name=task["sequence"]["name"], shot_name=task["entity"]["name"] ) + asset_name = "{ep_name}{sequence_name}_{shot_name}".format( + ep_name=ep["name"] + "_" if ep is not None else "", + sequence_name=task["sequence"]["name"], + shot_name=task["entity"]["name"] + ) # Update asset tasks with new one - asset_doc = get_asset_by_name(project_name, parent_name) + asset_doc = get_asset_by_name(project_name, asset_name) if asset_doc: asset_tasks = asset_doc["data"].get("tasks") task_type_name = task["task_type"]["name"] @@ -553,32 +561,25 @@ def _delete_task(self, data): # Print message entity = gazu.entity.get_entity(task["zou"]["entity_id"]) + ep = self.get_ep_dict(entity["source_id"]) if entity["type"] == "Asset": - ep = self.get_ep_dict(entity["source_id"]) - parent_name = "{ep}{entity_type} - {entity}".format( ep=ep["name"] + " - " if ep is not None else "", - entity_type=task["zou"]["entity_type_name"], - entity=task["zou"]["entity_name"] + entity_type=task["zou"]["entity_type"]["name"], + entity=task["zou"]["entity"]["name"] ) elif entity["type"] == "Shot": - shot_dict = gazu.entity.get_entity( - task["zou"]["entity_id"]) - seq_dict = gazu.entity.get_entity( - shot_dict["parent_id"]) - ep = self.get_ep_dict(seq_dict["parent_id"]) - parent_name = "{ep}{sequence} - {shot}".format( ep=ep["name"] + " - " if ep is not None else "", - sequence=seq_dict["name"], - shot=shot_dict["name"] + sequence=task["zou"]["sequence"]["name"], + shot=task["zou"]["entity"]["name"] ) msg = "Task deleted: {proj} - {parent} - {task}".format( - proj=task["zou"]["project_name"], + proj=task["zou"]["project"]["name"], parent=parent_name, - task=task["zou"]["task_type_name"] + task=name ) log.info(msg) From c50678bcb8c0a1cb2696fbb526d61cbe4261a361 Mon Sep 17 00:00:00 2001 From: Ember Light <49758407+EmberLightVFX@users.noreply.github.com> Date: Fri, 3 Mar 2023 10:34:17 +0100 Subject: [PATCH 300/898] Update openpype/modules/kitsu/utils/update_op_with_zou.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Félix David --- openpype/modules/kitsu/utils/update_op_with_zou.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index 6797df63441..73b7a4249d9 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -175,7 +175,12 @@ def update_op_assets( elif item_type == "Shot": tasks_list = gazu.task.all_tasks_for_shot(item) item_data["tasks"] = { - t["task_type_name"]: {"type": t["task_type_name"], "zou": gazu.task.get_task(t["id"])} + item_data["tasks"] = { + t["task_type_name"]: { + "type": t["task_type_name"], + "zou": gazu.task.get_task(t["id"]), + } + } for t in tasks_list } From 8fc6978ea2f56778d794e213c541f89888b24795 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 3 Mar 2023 11:10:12 +0100 Subject: [PATCH 301/898] Formatted with Black --- .../kitsu/actions/launcher_show_in_kitsu.py | 67 +++++----- .../publish/collect_kitsu_credential.py | 1 - .../plugins/publish/collect_kitsu_entities.py | 11 +- .../plugins/publish/integrate_kitsu_note.py | 5 +- .../plugins/publish/integrate_kitsu_review.py | 1 - openpype/modules/kitsu/utils/sync_service.py | 114 ++++++++++++------ .../modules/kitsu/utils/update_zou_with_op.py | 9 +- 7 files changed, 124 insertions(+), 84 deletions(-) diff --git a/openpype/modules/kitsu/actions/launcher_show_in_kitsu.py b/openpype/modules/kitsu/actions/launcher_show_in_kitsu.py index 11224f6e523..81d98cfffb7 100644 --- a/openpype/modules/kitsu/actions/launcher_show_in_kitsu.py +++ b/openpype/modules/kitsu/actions/launcher_show_in_kitsu.py @@ -23,36 +23,37 @@ def is_compatible(self, session): return True def process(self, session, **kwargs): - # Context inputs project_name = session["AVALON_PROJECT"] asset_name = session.get("AVALON_ASSET", None) task_name = session.get("AVALON_TASK", None) - project = get_project(project_name=project_name, - fields=["data.zou_id"]) + project = get_project( + project_name=project_name, fields=["data.zou_id"] + ) if not project: raise RuntimeError("Project {} not found.".format(project_name)) project_zou_id = project["data"].get("zou_id") if not project_zou_id: raise RuntimeError( - "Project {} has no connected kitsu id.".format(project_name)) + "Project {} has no connected kitsu id.".format(project_name) + ) asset_zou_name = None asset_zou_id = None - asset_zou_type = 'Assets' + asset_zou_type = "Assets" task_zou_id = None - zou_sub_type = ['AssetType', 'Sequence'] + zou_sub_type = ["AssetType", "Sequence"] if asset_name: asset_zou_name = asset_name asset_fields = ["data.zou.id", "data.zou.type"] if task_name: asset_fields.append("data.tasks.{}.zou.id".format(task_name)) - asset = get_asset_by_name(project_name, - asset_name=asset_name, - fields=asset_fields) + asset = get_asset_by_name( + project_name, asset_name=asset_name, fields=asset_fields + ) asset_zou_data = asset["data"].get("zou") @@ -68,37 +69,43 @@ def process(self, session, **kwargs): task_zou_data = task_data.get("zou", {}) if not task_zou_data: self.log.debug( - "No zou task data for task: {}".format(task_name)) + "No zou task data for task: {}".format(task_name) + ) task_zou_id = task_zou_data["id"] # Define URL - url = self.get_url(project_id=project_zou_id, - asset_name=asset_zou_name, - asset_id=asset_zou_id, - asset_type=asset_zou_type, - task_id=task_zou_id) + url = self.get_url( + project_id=project_zou_id, + asset_name=asset_zou_name, + asset_id=asset_zou_id, + asset_type=asset_zou_type, + task_id=task_zou_id, + ) # Open URL in webbrowser self.log.info("Opening URL: {}".format(url)) - webbrowser.open(url, - # Try in new tab - new=2) - - def get_url(self, - project_id, - asset_name=None, - asset_id=None, - asset_type=None, - task_id=None): - - shots_url = {'Shots', 'Sequence', 'Shot'} - sub_type = {'AssetType', 'Sequence'} + webbrowser.open( + url, + # Try in new tab + new=2, + ) + + def get_url( + self, + project_id, + asset_name=None, + asset_id=None, + asset_type=None, + task_id=None, + ): + shots_url = {"Shots", "Sequence", "Shot"} + sub_type = {"AssetType", "Sequence"} kitsu_module = self.get_kitsu_module() # Get kitsu url with /api stripped kitsu_url = kitsu_module.server_url if kitsu_url.endswith("/api"): - kitsu_url = kitsu_url[:-len("/api")] + kitsu_url = kitsu_url[: -len("/api")] sub_url = f"/productions/{project_id}" asset_type_url = "shots" if asset_type in shots_url else "assets" @@ -121,6 +128,6 @@ def get_url(self, # Add search method if is a sub_type sub_url += f"/{asset_type_url}" if asset_type in sub_type: - sub_url += f'?search={asset_name}' + sub_url += f"?search={asset_name}" return f"{kitsu_url}{sub_url}" diff --git a/openpype/modules/kitsu/plugins/publish/collect_kitsu_credential.py b/openpype/modules/kitsu/plugins/publish/collect_kitsu_credential.py index b7f6f67a407..ac501dd47dd 100644 --- a/openpype/modules/kitsu/plugins/publish/collect_kitsu_credential.py +++ b/openpype/modules/kitsu/plugins/publish/collect_kitsu_credential.py @@ -13,6 +13,5 @@ class CollectKitsuSession(pyblish.api.ContextPlugin): # rename log in # families = ["kitsu"] def process(self, context): - gazu.client.set_host(os.environ["KITSU_SERVER"]) gazu.log_in(os.environ["KITSU_LOGIN"], os.environ["KITSU_PWD"]) diff --git a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py index 71ed5635801..a0bd2b305b1 100644 --- a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py +++ b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py @@ -10,9 +10,9 @@ class CollectKitsuEntities(pyblish.api.ContextPlugin): label = "Kitsu entities" def process(self, context): - kitsu_project = gazu.project.get_project_by_name( - context.data["projectName"]) + context.data["projectName"] + ) if not kitsu_project: raise ValueError("Project not found in kitsu!") @@ -35,7 +35,8 @@ def process(self, context): zou_task_data = asset_doc["data"]["tasks"][task_name].get("zou") self.log.debug( - "Collected zou task data: {}".format(zou_task_data)) + "Collected zou task data: {}".format(zou_task_data) + ) entity_id = zou_asset_data["id"] entity = kitsu_entities_by_id.get(entity_id) @@ -44,7 +45,9 @@ def process(self, context): if not entity: raise ValueError( "{} was not found in kitsu!".format( - zou_asset_data["name"])) + zou_asset_data["name"] + ) + ) kitsu_entities_by_id[entity_id] = entity instance.data["entity"] = entity diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 006f0bc6d06..6702cbe7aa3 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -13,7 +13,6 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): note_status_shortname = "wfa" def process(self, context): - # Get comment text body publish_comment = context.data.get("comment") if not publish_comment: @@ -45,9 +44,7 @@ def process(self, context): # Add comment to kitsu task task_id = kitsu_task["id"] - self.log.debug( - "Add new note in taks id {}".format(task_id) - ) + self.log.debug("Add new note in taks id {}".format(task_id)) kitsu_comment = gazu.task.add_comment( task_id, note_status, comment=publish_comment ) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py index d8f6cb7ac83..12482b56573 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py @@ -12,7 +12,6 @@ class IntegrateKitsuReview(pyblish.api.InstancePlugin): optional = True def process(self, instance): - task = instance.data["kitsu_task"]["id"] comment = instance.data["kitsu_comment"]["id"] diff --git a/openpype/modules/kitsu/utils/sync_service.py b/openpype/modules/kitsu/utils/sync_service.py index 1f12217d446..34714fa4b32 100644 --- a/openpype/modules/kitsu/utils/sync_service.py +++ b/openpype/modules/kitsu/utils/sync_service.py @@ -102,7 +102,8 @@ def __init__(self, login, password): ) gazu.events.add_listener( - self.event_client, "shot:new", self._new_shot) + self.event_client, "shot:new", self._new_shot + ) gazu.events.add_listener( self.event_client, "shot:update", self._update_shot ) @@ -111,7 +112,8 @@ def __init__(self, login, password): ) gazu.events.add_listener( - self.event_client, "task:new", self._new_task) + self.event_client, "task:new", self._new_task + ) gazu.events.add_listener( self.event_client, "task:update", self._update_task ) @@ -146,7 +148,8 @@ def _update_project(self, data, new_project=False): # Write into DB if update_project: self.dbcon.Session["AVALON_PROJECT"] = get_kitsu_project_name( - data["project_id"]) + data["project_id"] + ) self.dbcon.bulk_write([update_project]) if new_project: @@ -158,7 +161,8 @@ def _delete_project(self, data): collections = self.dbcon.database.list_collection_names() for collection in collections: project = self.dbcon.database[collection].find_one( - {"data.zou_id": data["project_id"]}) + {"data.zou_id": data["project_id"]} + ) if project: # Delete project collection self.dbcon.database[project["name"]].drop() @@ -186,13 +190,15 @@ def _new_asset(self, data): ep_id = asset.get("episode_id") ep = self.get_ep_dict(ep_id) - msg = "Asset created: {proj_name} - {ep_name}" \ + msg = ( + "Asset created: {proj_name} - {ep_name}" "{asset_type_name} - {asset_name}".format( proj_name=asset["project_name"], ep_name=ep["name"] + " - " if ep is not None else "", asset_type_name=asset["asset_type_name"], - asset_name=asset["name"] + asset_name=asset["name"], ) + ) log.info(msg) def _update_asset(self, data): @@ -216,8 +222,11 @@ def _update_asset(self, data): # Update update_op_result = update_op_assets( - self.dbcon, gazu_project, project_doc, - [asset], zou_ids_and_asset_docs + self.dbcon, + gazu_project, + project_doc, + [asset], + zou_ids_and_asset_docs, ) if update_op_result: asset_doc_id, asset_update = update_op_result[0] @@ -238,13 +247,15 @@ def _delete_asset(self, data): ep_id = asset["data"]["zou"].get("episode_id") ep = self.get_ep_dict(ep_id) - msg = "Asset deleted: {proj_name} - {ep_name}" \ + msg = ( + "Asset deleted: {proj_name} - {ep_name}" "{type_name} - {asset_name}".format( proj_name=asset["data"]["zou"]["project_name"], ep_name=ep["name"] + " - " if ep is not None else "", type_name=asset["data"]["zou"]["asset_type_name"], - asset_name=asset["name"] + asset_name=asset["name"], ) + ) log.info(msg) # == Episode == @@ -264,8 +275,7 @@ def _new_episode(self, data): # Print message msg = "Episode created: {proj_name} - {ep_name}".format( - proj_name=ep["project_name"], - ep_name=ep["name"] + proj_name=ep["project_name"], ep_name=ep["name"] ) log.info(msg) @@ -290,8 +300,11 @@ def _update_episode(self, data): # Update update_op_result = update_op_assets( - self.dbcon, gazu_project, project_doc, - [ep], zou_ids_and_asset_docs + self.dbcon, + gazu_project, + project_doc, + [ep], + zou_ids_and_asset_docs, ) if update_op_result: asset_doc_id, asset_update = update_op_result[0] @@ -310,11 +323,11 @@ def _delete_episode(self, data): # Print message project = gazu.project.get_project( - ep["data"]["zou"]["project_id"]) + ep["data"]["zou"]["project_id"] + ) msg = "Episode deleted: {proj_name} - {ep_name}".format( - proj_name=project["name"], - ep_name=ep["name"] + proj_name=project["name"], ep_name=ep["name"] ) log.info(msg) @@ -337,12 +350,14 @@ def _new_sequence(self, data): ep_id = sequence.get("episode_id") ep = self.get_ep_dict(ep_id) - msg = "Sequence created: {proj_name} - {ep_name}" \ + msg = ( + "Sequence created: {proj_name} - {ep_name}" "{sequence_name}".format( proj_name=sequence["project_name"], ep_name=ep["name"] + " - " if ep is not None else "", - sequence_name=sequence["name"] + sequence_name=sequence["name"], ) + ) log.info(msg) def _update_sequence(self, data): @@ -366,8 +381,11 @@ def _update_sequence(self, data): # Update update_op_result = update_op_assets( - self.dbcon, gazu_project, project_doc, - [sequence], zou_ids_and_asset_docs + self.dbcon, + gazu_project, + project_doc, + [sequence], + zou_ids_and_asset_docs, ) if update_op_result: asset_doc_id, asset_update = update_op_result[0] @@ -388,14 +406,17 @@ def _delete_sequence(self, data): ep = self.get_ep_dict(ep_id) gazu_project = gazu.project.get_project( - sequence["data"]["zou"]["project_id"]) + sequence["data"]["zou"]["project_id"] + ) - msg = "Sequence deleted: {proj_name} - {ep_name}" \ + msg = ( + "Sequence deleted: {proj_name} - {ep_name}" "{sequence_name}".format( proj_name=gazu_project["name"], ep_name=ep["name"] + " - " if ep is not None else "", - sequence_name=sequence["name"] + sequence_name=sequence["name"], ) + ) log.info(msg) # == Shot == @@ -417,13 +438,15 @@ def _new_shot(self, data): ep_id = shot["episode_id"] ep = self.get_ep_dict(ep_id) - msg = "Shot created: {proj_name} - {ep_name}" \ + msg = ( + "Shot created: {proj_name} - {ep_name}" "{sequence_name} - {shot_name}".format( proj_name=shot["project_name"], ep_name=ep["name"] + " - " if ep is not None else "", sequence_name=shot["sequence_name"], - shot_name=shot["name"] + shot_name=shot["name"], ) + ) log.info(msg) def _update_shot(self, data): @@ -440,14 +463,18 @@ def _update_shot(self, data): zou_ids_and_asset_docs = { asset_doc["data"]["zou"]["id"]: asset_doc for asset_doc in get_assets(project_name) - if asset_doc["data"].get("zou", {}).get("id")} + if asset_doc["data"].get("zou", {}).get("id") + } zou_ids_and_asset_docs[shot["project_id"]] = project_doc gazu_project = gazu.project.get_project(shot["project_id"]) # Update update_op_result = update_op_assets( - self.dbcon, gazu_project, project_doc, - [shot], zou_ids_and_asset_docs + self.dbcon, + gazu_project, + project_doc, + [shot], + zou_ids_and_asset_docs, ) if update_op_result: @@ -469,13 +496,15 @@ def _delete_shot(self, data): ep_id = shot["data"]["zou"].get("episode_id") ep = self.get_ep_dict(ep_id) - msg = "Shot deleted: {proj_name} - {ep_name}" \ + msg = ( + "Shot deleted: {proj_name} - {ep_name}" "{sequence_name} - {shot_name}".format( proj_name=shot["data"]["zou"]["project_name"], ep_name=ep["name"] + " - " if ep is not None else "", sequence_name=shot["data"]["zou"]["sequence_name"], - shot_name=shot["name"] + shot_name=shot["name"], ) + ) log.info(msg) # == Task == @@ -504,12 +533,12 @@ def _new_task(self, data): parent_name = "{ep_name}{sequence_name} - {shot_name}".format( ep_name=ep["name"] + " - " if ep is not None else "", sequence_name=task["sequence"]["name"], - shot_name=task["entity"]["name"] + shot_name=task["entity"]["name"], ) asset_name = "{ep_name}{sequence_name}_{shot_name}".format( ep_name=ep["name"] + "_" if ep is not None else "", sequence_name=task["sequence"]["name"], - shot_name=task["entity"]["name"] + shot_name=task["entity"]["name"], ) # Update asset tasks with new one @@ -518,20 +547,24 @@ def _new_task(self, data): asset_tasks = asset_doc["data"].get("tasks") task_type_name = task["task_type"]["name"] asset_tasks[task_type_name] = { - "type": task_type_name, "zou": task} + "type": task_type_name, + "zou": task, + } self.dbcon.update_one( {"_id": asset_doc["_id"]}, - {"$set": {"data.tasks": asset_tasks}} + {"$set": {"data.tasks": asset_tasks}}, ) # Print message - msg = "Task created: {proj} - {ent_type}{parent}" \ + msg = ( + "Task created: {proj} - {ent_type}{parent}" " - {task}".format( proj=task["project"]["name"], ent_type=ent_type + " - " if ent_type is not None else "", parent=parent_name, - task=task["task_type"]["name"] + task=task["task_type"]["name"], ) + ) log.info(msg) def _update_task(self, data): @@ -567,19 +600,19 @@ def _delete_task(self, data): parent_name = "{ep}{entity_type} - {entity}".format( ep=ep["name"] + " - " if ep is not None else "", entity_type=task["zou"]["entity_type"]["name"], - entity=task["zou"]["entity"]["name"] + entity=task["zou"]["entity"]["name"], ) elif entity["type"] == "Shot": parent_name = "{ep}{sequence} - {shot}".format( ep=ep["name"] + " - " if ep is not None else "", sequence=task["zou"]["sequence"]["name"], - shot=task["zou"]["entity"]["name"] + shot=task["zou"]["entity"]["name"], ) msg = "Task deleted: {proj} - {parent} - {task}".format( proj=task["zou"]["project"]["name"], parent=parent_name, - task=name + task=name, ) log.info(msg) @@ -593,6 +626,7 @@ def start_listeners(login: str, password: str): login (str): Kitsu user login password (str): Kitsu user password """ + # Refresh token every week def refresh_token_every_week(): log.info("Refreshing token...") diff --git a/openpype/modules/kitsu/utils/update_zou_with_op.py b/openpype/modules/kitsu/utils/update_zou_with_op.py index 617f037c1e8..be931af2338 100644 --- a/openpype/modules/kitsu/utils/update_zou_with_op.py +++ b/openpype/modules/kitsu/utils/update_zou_with_op.py @@ -83,7 +83,8 @@ def sync_zou_from_op_project( } ) gazu.project.update_project_data( - zou_project, data=project_doc["data"]) + zou_project, data=project_doc["data"] + ) gazu.project.update_project(zou_project) asset_types = gazu.asset.all_asset_types() @@ -99,8 +100,7 @@ def sync_zou_from_op_project( project_module_settings = get_project_settings(project_name)["kitsu"] dbcon.Session["AVALON_PROJECT"] = project_name asset_docs = { - asset_doc["_id"]: asset_doc - for asset_doc in get_assets(project_name) + asset_doc["_id"]: asset_doc for asset_doc in get_assets(project_name) } # Create new assets @@ -176,7 +176,8 @@ def sync_zou_from_op_project( frame_in=doc["data"]["frameStart"], frame_out=doc["data"]["frameEnd"], nb_frames=( - doc["data"]["frameEnd"] - doc["data"]["frameStart"] + 1), + doc["data"]["frameEnd"] - doc["data"]["frameStart"] + 1 + ), ) elif match.group(2): # Sequence From 67bc287321fd03287aedf222e6d9c7ebf25e3332 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 3 Mar 2023 11:12:17 +0100 Subject: [PATCH 302/898] Fix hound comments --- openpype/modules/kitsu/utils/update_op_with_zou.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index 73b7a4249d9..053e803ff3b 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -175,12 +175,12 @@ def update_op_assets( elif item_type == "Shot": tasks_list = gazu.task.all_tasks_for_shot(item) item_data["tasks"] = { - item_data["tasks"] = { - t["task_type_name"]: { - "type": t["task_type_name"], - "zou": gazu.task.get_task(t["id"]), + item_data["tasks"] = { + t["task_type_name"]: { + "type": t["task_type_name"], + "zou": gazu.task.get_task(t["id"]), + } } - } for t in tasks_list } From 67e8f59935a7a1824aceb71cdc32e354c8a33a98 Mon Sep 17 00:00:00 2001 From: Ynbot Date: Sat, 4 Mar 2023 03:27:48 +0000 Subject: [PATCH 303/898] [Automated] Bump version --- openpype/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/version.py b/openpype/version.py index 4d6f3d43e40..2939ddbbacd 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.15.2-nightly.3" +__version__ = "3.15.2-nightly.4" From 7c9c2864c51a58d7dcb4768d5483fcf35615c3e9 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Sat, 4 Mar 2023 15:41:49 +0300 Subject: [PATCH 304/898] add up to 3 decimals to fps allows input 23.976 to the FPS settings both in Project Manager and the Project Anatomy. --- .../schemas/schema_anatomy_attributes.json | 2 +- .../project_manager/project_manager/delegates.py | 5 ++++- .../tools/project_manager/project_manager/view.py | 14 ++++++++++---- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json index 3667c9d5d85..a7280243761 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json @@ -10,7 +10,7 @@ "type": "number", "key": "fps", "label": "Frame Rate", - "decimal": 2, + "decimal": 3, "minimum": 0 }, { diff --git a/openpype/tools/project_manager/project_manager/delegates.py b/openpype/tools/project_manager/project_manager/delegates.py index 79e9554b0f6..023dd668ecc 100644 --- a/openpype/tools/project_manager/project_manager/delegates.py +++ b/openpype/tools/project_manager/project_manager/delegates.py @@ -83,15 +83,18 @@ class NumberDelegate(QtWidgets.QStyledItemDelegate): decimals(int): How many decimal points can be used. Float will be used as value if is higher than 0. """ - def __init__(self, minimum, maximum, decimals, *args, **kwargs): + def __init__(self, minimum, maximum, decimals, step, *args, **kwargs): super(NumberDelegate, self).__init__(*args, **kwargs) self.minimum = minimum self.maximum = maximum self.decimals = decimals + self.step = step def createEditor(self, parent, option, index): if self.decimals > 0: editor = DoubleSpinBoxScrollFixed(parent) + editor.setSingleStep(self.step) + editor.setDecimals(self.decimals) else: editor = SpinBoxScrollFixed(parent) diff --git a/openpype/tools/project_manager/project_manager/view.py b/openpype/tools/project_manager/project_manager/view.py index fa08943ea53..0dd04aa7b91 100644 --- a/openpype/tools/project_manager/project_manager/view.py +++ b/openpype/tools/project_manager/project_manager/view.py @@ -26,10 +26,11 @@ class NameDef: class NumberDef: - def __init__(self, minimum=None, maximum=None, decimals=None): + def __init__(self, minimum=None, maximum=None, decimals=None, step=None): self.minimum = 0 if minimum is None else minimum self.maximum = 999999999 if maximum is None else maximum self.decimals = 0 if decimals is None else decimals + self.step = 1 if decimals is None else step class TypeDef: @@ -73,14 +74,14 @@ class HierarchyView(QtWidgets.QTreeView): "type": TypeDef(), "frameStart": NumberDef(1), "frameEnd": NumberDef(1), - "fps": NumberDef(1, decimals=2), + "fps": NumberDef(1, decimals=3, step=0.01), "resolutionWidth": NumberDef(0), "resolutionHeight": NumberDef(0), "handleStart": NumberDef(0), "handleEnd": NumberDef(0), "clipIn": NumberDef(1), "clipOut": NumberDef(1), - "pixelAspect": NumberDef(0, decimals=2), + "pixelAspect": NumberDef(0, decimals=2, step=0.1), "tools_env": ToolsDef() } @@ -96,6 +97,10 @@ class HierarchyView(QtWidgets.QTreeView): "stretch": QtWidgets.QHeaderView.Interactive, "width": 140 }, + "fps": { + "stretch": QtWidgets.QHeaderView.Interactive, + "width": 65 + }, "tools_env": { "stretch": QtWidgets.QHeaderView.Interactive, "width": 200 @@ -148,7 +153,8 @@ def __init__(self, dbcon, source_model, parent): delegate = NumberDelegate( item_type.minimum, item_type.maximum, - item_type.decimals + item_type.decimals, + item_type.step ) elif isinstance(item_type, TypeDef): From 384d928d854d086fea75a4ae418e1d81357879d1 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Sat, 4 Mar 2023 22:19:58 +0300 Subject: [PATCH 305/898] set fps and pixel aspect precision steps default values --- openpype/tools/project_manager/project_manager/view.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/tools/project_manager/project_manager/view.py b/openpype/tools/project_manager/project_manager/view.py index 0dd04aa7b91..b35491c5b21 100644 --- a/openpype/tools/project_manager/project_manager/view.py +++ b/openpype/tools/project_manager/project_manager/view.py @@ -74,14 +74,14 @@ class HierarchyView(QtWidgets.QTreeView): "type": TypeDef(), "frameStart": NumberDef(1), "frameEnd": NumberDef(1), - "fps": NumberDef(1, decimals=3, step=0.01), + "fps": NumberDef(1, decimals=3, step=1), "resolutionWidth": NumberDef(0), "resolutionHeight": NumberDef(0), "handleStart": NumberDef(0), "handleEnd": NumberDef(0), "clipIn": NumberDef(1), "clipOut": NumberDef(1), - "pixelAspect": NumberDef(0, decimals=2, step=0.1), + "pixelAspect": NumberDef(0, decimals=2, step=0.01), "tools_env": ToolsDef() } From b077815dc5adcb7c839cc77825498369402ef7af Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 5 Mar 2023 10:32:13 +0100 Subject: [PATCH 306/898] Get and set openpype context data on comp --- openpype/hosts/fusion/api/pipeline.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/api/pipeline.py b/openpype/hosts/fusion/api/pipeline.py index 2d0a1da8fae..b982e1c2e91 100644 --- a/openpype/hosts/fusion/api/pipeline.py +++ b/openpype/hosts/fusion/api/pipeline.py @@ -155,10 +155,12 @@ def get_containers(self): return ls() def update_context_data(self, data, changes): - print(data, changes) + comp = get_current_comp() + comp.SetData("openpype", data) def get_context_data(self): - return {} + comp = get_current_comp() + return comp.GetData("openpype") or {} def on_pyblish_instance_toggled(instance, old_value, new_value): From 406bc798c45fff19edee17730ffaee587a5a8b48 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 5 Mar 2023 10:39:57 +0100 Subject: [PATCH 307/898] Tweak creator updates to newer style updates --- .../fusion/plugins/create/create_saver.py | 11 +++-------- .../fusion/plugins/create/create_workfile.py | 18 ++++-------------- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/openpype/hosts/fusion/plugins/create/create_saver.py b/openpype/hosts/fusion/plugins/create/create_saver.py index 439064770e0..777dfb2e678 100644 --- a/openpype/hosts/fusion/plugins/create/create_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_saver.py @@ -87,15 +87,10 @@ def get_icon(self): return qtawesome.icon("fa.eye", color="white") def update_instances(self, update_list): - for update in update_list: - instance = update.instance + for created_inst, _changes in update_list: - # Get the new values after the changes by key, ignore old value - new_data = { - key: new for key, (_old, new) in update.changes.items() - } - - tool = instance.transient_data["tool"] + new_data = created_inst.data_to_store() + tool = created_inst.transient_data["tool"] self._update_tool_with_data(tool, new_data) self._imprint(tool, new_data) diff --git a/openpype/hosts/fusion/plugins/create/create_workfile.py b/openpype/hosts/fusion/plugins/create/create_workfile.py index 917780c56e9..3f11d694258 100644 --- a/openpype/hosts/fusion/plugins/create/create_workfile.py +++ b/openpype/hosts/fusion/plugins/create/create_workfile.py @@ -53,20 +53,15 @@ def collect_instances(self): self._add_instance_to_context(instance) def update_instances(self, update_list): - for update in update_list: - instance = update.instance - comp = instance.transient_data["comp"] + for created_inst, _changes in update_list: + comp = created_inst.transient_data["comp"] if not hasattr(comp, "SetData"): # Comp is not alive anymore, likely closed by the user self.log.error("Workfile comp not found for existing instance." " Comp might have been closed in the meantime.") continue - # TODO: It appears sometimes this could be 'nested' - # Get the new values after the changes by key, ignore old value - new_data = { - key: new for key, (_old, new) in update.changes.items() - } + new_data = created_inst.data_to_store() self._imprint(comp, new_data) def create(self, options=None): @@ -128,9 +123,4 @@ def _imprint(self, comp, data): for key in ["variant", "subset", "asset", "task"]: data.pop(key, None) - # Flatten any potential nested dicts - data = flatten_dict(data, separator=".") - - # Prefix with data key openpype.workfile - data = {f"{self.data_key}.{key}" for key, value in data.items()} - comp.SetData(data) + comp.SetData(self.data_key, data) From 37591de2913bfadd033e904fdfb88ffee550c4ad Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 5 Mar 2023 10:40:56 +0100 Subject: [PATCH 308/898] Change workfile Creator data key so it doesn't interfere with global comp context data in any way (Fusion allows to access nested dicts (lua tables) using the dot notation) --- openpype/hosts/fusion/plugins/create/create_workfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/plugins/create/create_workfile.py b/openpype/hosts/fusion/plugins/create/create_workfile.py index 3f11d694258..c67a9793dd4 100644 --- a/openpype/hosts/fusion/plugins/create/create_workfile.py +++ b/openpype/hosts/fusion/plugins/create/create_workfile.py @@ -33,7 +33,7 @@ class FusionWorkfileCreator(AutoCreator): create_allow_context_change = False - data_key = "openpype.workfile" + data_key = "openpype_workfile" def collect_instances(self): From 5efc9e0ff0cdf0f410b7a0b92b27cc2ed03256e2 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 6 Mar 2023 11:00:02 +0100 Subject: [PATCH 309/898] Editorial: Fix tasks removal (#4558) Fix tasks removal in editorial --- .../publish/extract_hierarchy_avalon.py | 52 +++++++++++++------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/openpype/plugins/publish/extract_hierarchy_avalon.py b/openpype/plugins/publish/extract_hierarchy_avalon.py index b2a6adc210d..493780645c6 100644 --- a/openpype/plugins/publish/extract_hierarchy_avalon.py +++ b/openpype/plugins/publish/extract_hierarchy_avalon.py @@ -135,6 +135,38 @@ def sync_project(self, context, entity_data): ) return project_doc + def _prepare_new_tasks(self, asset_doc, entity_data): + new_tasks = entity_data.get("tasks") or {} + if not asset_doc: + return new_tasks + + old_tasks = asset_doc.get("data", {}).get("tasks") + # Just use new tasks if old are not available + if not old_tasks: + return new_tasks + + output = deepcopy(old_tasks) + # Create mapping of lowered task names from old tasks + cur_task_low_mapping = { + task_name.lower(): task_name + for task_name in old_tasks + } + # Add/update tasks from new entity data + for task_name, task_info in new_tasks.items(): + task_info = deepcopy(task_info) + task_name_low = task_name.lower() + # Add new task + if task_name_low not in cur_task_low_mapping: + output[task_name] = task_info + continue + + # Update existing task with new info + mapped_task_name = cur_task_low_mapping.pop(task_name_low) + src_task_info = output.pop(mapped_task_name) + src_task_info.update(task_info) + output[task_name] = src_task_info + return output + def sync_asset( self, asset_name, @@ -170,11 +202,12 @@ def sync_asset( data["parents"] = parents asset_doc = asset_docs_by_name.get(asset_name) + + # Tasks + data["tasks"] = self._prepare_new_tasks(asset_doc, entity_data) + # --- Create/Unarchive asset and end --- if not asset_doc: - # Just use tasks from entity data as they are - # - this is different from the case when tasks are updated - data["tasks"] = entity_data.get("tasks") or {} archived_asset_doc = None for archived_entity in archived_asset_docs_by_name[asset_name]: archived_parents = ( @@ -201,19 +234,6 @@ def sync_asset( if "data" not in asset_doc: asset_doc["data"] = {} cur_entity_data = asset_doc["data"] - cur_entity_tasks = cur_entity_data.get("tasks") or {} - - # Tasks - data["tasks"] = {} - new_tasks = entity_data.get("tasks") or {} - for task_name, task_info in new_tasks.items(): - task_info = deepcopy(task_info) - if task_name in cur_entity_tasks: - src_task_info = deepcopy(cur_entity_tasks[task_name]) - src_task_info.update(task_info) - task_info = src_task_info - - data["tasks"][task_name] = task_info changes = {} for key, value in data.items(): From 08c71380709cf672e4b930b351a0671331521610 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 6 Mar 2023 11:13:57 +0100 Subject: [PATCH 310/898] Nuke: moving deepcopy to abstraction --- openpype/pipeline/colorspace.py | 31 ++++++++++---------- openpype/pipeline/publish/publish_plugins.py | 5 ++-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/openpype/pipeline/colorspace.py b/openpype/pipeline/colorspace.py index 6f68bdc5bf6..2085e2d37f2 100644 --- a/openpype/pipeline/colorspace.py +++ b/openpype/pipeline/colorspace.py @@ -335,9 +335,10 @@ def get_imageio_config( get_template_data_from_session) anatomy_data = get_template_data_from_session() + formatting_data = deepcopy(anatomy_data) # add project roots to anatomy data - anatomy_data["root"] = anatomy.roots - anatomy_data["platform"] = platform.system().lower() + formatting_data["root"] = anatomy.roots + formatting_data["platform"] = platform.system().lower() # get colorspace settings imageio_global, imageio_host = _get_imageio_settings( @@ -347,7 +348,7 @@ def get_imageio_config( if config_host.get("enabled"): config_data = _get_config_data( - config_host["filepath"], anatomy_data + config_host["filepath"], formatting_data ) else: config_data = None @@ -356,7 +357,7 @@ def get_imageio_config( # get config path from either global or host_name config_global = imageio_global["ocio_config"] config_data = _get_config_data( - config_global["filepath"], anatomy_data + config_global["filepath"], formatting_data ) if not config_data: @@ -372,12 +373,12 @@ def _get_config_data(path_list, anatomy_data): """Return first existing path in path list. If template is used in path inputs, - then it is formated by anatomy data + then it is formatted by anatomy data and environment variables Args: path_list (list[str]): list of abs paths - anatomy_data (dict): formating data + anatomy_data (dict): formatting data Returns: dict: config data @@ -389,30 +390,30 @@ def _get_config_data(path_list, anatomy_data): # first try host config paths for path_ in path_list: - formated_path = _format_path(path_, formatting_data) + formatted_path = _format_path(path_, formatting_data) - if not os.path.exists(formated_path): + if not os.path.exists(formatted_path): continue return { - "path": os.path.normpath(formated_path), + "path": os.path.normpath(formatted_path), "template": path_ } -def _format_path(tempate_path, formatting_data): - """Single template path formating. +def _format_path(template_path, formatting_data): + """Single template path formatting. Args: - tempate_path (str): template string + template_path (str): template string formatting_data (dict): data to be used for - template formating + template formatting Returns: - str: absolute formated path + str: absolute formatted path """ # format path for anatomy keys - formatted_path = StringTemplate(tempate_path).format( + formatted_path = StringTemplate(template_path).format( formatting_data) return os.path.abspath(formatted_path) diff --git a/openpype/pipeline/publish/publish_plugins.py b/openpype/pipeline/publish/publish_plugins.py index 2df98221ba9..331235fadc7 100644 --- a/openpype/pipeline/publish/publish_plugins.py +++ b/openpype/pipeline/publish/publish_plugins.py @@ -1,4 +1,3 @@ -from copy import deepcopy import inspect from abc import ABCMeta from pprint import pformat @@ -311,7 +310,7 @@ class ColormanagedPyblishPluginMixin(object): @staticmethod def get_colorspace_settings(context): - """Retuns solved settings for the host context. + """Returns solved settings for the host context. Args: context (publish.Context): publishing context @@ -324,7 +323,7 @@ def get_colorspace_settings(context): project_name = context.data["projectName"] host_name = context.data["hostName"] - anatomy_data = deepcopy(context.data["anatomyData"]) + anatomy_data = context.data["anatomyData"] project_settings_ = context.data["project_settings"] config_data = get_imageio_config( From ec78ebff691eec6c124dfc95c10c9760bac1d1b5 Mon Sep 17 00:00:00 2001 From: Simone Barbieri Date: Mon, 6 Mar 2023 10:20:12 +0000 Subject: [PATCH 311/898] Add skeletalmesh family as loadable as reference --- openpype/hosts/maya/plugins/load/load_reference.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/maya/plugins/load/load_reference.py b/openpype/hosts/maya/plugins/load/load_reference.py index 858c9b709e6..d93702a16d6 100644 --- a/openpype/hosts/maya/plugins/load/load_reference.py +++ b/openpype/hosts/maya/plugins/load/load_reference.py @@ -26,6 +26,7 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): "rig", "camerarig", "staticMesh", + "skeletalMesh", "mvLook"] representations = ["ma", "abc", "fbx", "mb"] From 84574eaca8cc8bfa707d39d411c784621754975a Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 6 Mar 2023 11:50:41 +0100 Subject: [PATCH 312/898] Nuke: fix clip sequence loading --- openpype/hosts/nuke/plugins/load/load_clip.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/nuke/plugins/load/load_clip.py b/openpype/hosts/nuke/plugins/load/load_clip.py index d170276addd..cb3da79ef58 100644 --- a/openpype/hosts/nuke/plugins/load/load_clip.py +++ b/openpype/hosts/nuke/plugins/load/load_clip.py @@ -222,18 +222,21 @@ def _representation_with_hash_in_frame(self, representation): """ representation = deepcopy(representation) context = representation["context"] - template = representation["data"]["template"] + + # Get the frame from the context and hash it + frame = context["frame"] + hashed_frame = "#" * len(str(frame)) + + # Replace the frame with the hash in the originalBasename if ( - "{originalBasename}" in template - and "frame" in context + "{originalBasename}" in representation["data"]["template"] ): - frame = context["frame"] - hashed_frame = "#" * len(str(frame)) origin_basename = context["originalBasename"] context["originalBasename"] = origin_basename.replace( frame, hashed_frame ) + # Replace the frame with the hash in the frame representation["context"]["frame"] = hashed_frame return representation From b513bb437d2e48b20f305fadb4b71639724a3875 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 6 Mar 2023 16:28:37 +0100 Subject: [PATCH 313/898] Set subset in a more correct OpenPype way --- .../hosts/fusion/plugins/create/create_saver.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/plugins/create/create_saver.py b/openpype/hosts/fusion/plugins/create/create_saver.py index 777dfb2e678..b0c0d830a38 100644 --- a/openpype/hosts/fusion/plugins/create/create_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_saver.py @@ -12,6 +12,7 @@ Creator, CreatedInstance ) +from openpype.client import get_asset_by_name class CreateSaver(Creator): @@ -145,14 +146,22 @@ def _collect_unmanaged_saver(self, tool): asset = legacy_io.Session["AVALON_ASSET"] task = legacy_io.Session["AVALON_TASK"] + asset_doc = get_asset_by_name(project_name=project, + asset_name=asset) + path = tool["Clip"][comp.TIME_UNDEFINED] fname = os.path.basename(path) fname, _ext = os.path.splitext(fname) - subset = fname.rstrip(".") + variant = fname.rstrip(".") + subset = self.get_subset_name( + variant=variant, + task_name=task, + asset_doc=asset_doc, + project_name=project, + ) attrs = tool.GetAttrs() passthrough = attrs["TOOLB_PassThrough"] - variant = subset[len("render"):] return { # Required data "project": project, From 99637875efa176a7e462212880a5f4c26f2b6f78 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 6 Mar 2023 16:31:09 +0100 Subject: [PATCH 314/898] Do not secretly pop data that OP generates by default --- openpype/hosts/fusion/plugins/create/create_workfile.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/openpype/hosts/fusion/plugins/create/create_workfile.py b/openpype/hosts/fusion/plugins/create/create_workfile.py index c67a9793dd4..e539dcf0192 100644 --- a/openpype/hosts/fusion/plugins/create/create_workfile.py +++ b/openpype/hosts/fusion/plugins/create/create_workfile.py @@ -117,10 +117,4 @@ def get_icon(self): return qtawesome.icon("fa.file-o", color="white") def _imprint(self, comp, data): - - # TODO: Should this keys persist or not? I'd prefer not - # Do not persist the current context for the Workfile - for key in ["variant", "subset", "asset", "task"]: - data.pop(key, None) - comp.SetData(self.data_key, data) From b2eb14914b6644c8d5b3797751da74c37b804e83 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 6 Mar 2023 16:55:05 +0100 Subject: [PATCH 315/898] global, nuke: adding support for first workfile creation --- openpype/hosts/nuke/api/lib.py | 5 +- openpype/hosts/nuke/api/pipeline.py | 2 +- .../nuke/api/workfile_template_builder.py | 1 - openpype/hosts/nuke/api/workio.py | 2 +- .../workfile/workfile_template_builder.py | 46 +++++++++++++------ 5 files changed, 37 insertions(+), 19 deletions(-) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index cd31e426902..793dc8fcdd3 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -2682,11 +2682,12 @@ def start_workfile_template_builder(): build_workfile_template ) + # to avoid looping of the callback, remove it! - # nuke.removeOnCreate(start_workfile_template_builder, nodeClass="Root") log.info("Starting workfile template builder...") - build_workfile_template(run_from_callback=True) + build_workfile_template(workfile_creation_enabled=True) + nuke.removeOnCreate(start_workfile_template_builder, nodeClass="Root") @deprecated def recreate_instance(origin_node, avalon_data=None): diff --git a/openpype/hosts/nuke/api/pipeline.py b/openpype/hosts/nuke/api/pipeline.py index 30270a4e5ff..d649ffae7f9 100644 --- a/openpype/hosts/nuke/api/pipeline.py +++ b/openpype/hosts/nuke/api/pipeline.py @@ -155,8 +155,8 @@ def add_nuke_callbacks(): # Set context settings. nuke.addOnCreate( workfile_settings.set_context_settings, nodeClass="Root") - nuke.addOnCreate(start_workfile_template_builder, nodeClass="Root") nuke.addOnCreate(workfile_settings.set_favorites, nodeClass="Root") + nuke.addOnCreate(start_workfile_template_builder, nodeClass="Root") nuke.addOnCreate(process_workfile_builder, nodeClass="Root") # fix ffmpeg settings on script diff --git a/openpype/hosts/nuke/api/workfile_template_builder.py b/openpype/hosts/nuke/api/workfile_template_builder.py index 80db0d160c4..a6805d1b149 100644 --- a/openpype/hosts/nuke/api/workfile_template_builder.py +++ b/openpype/hosts/nuke/api/workfile_template_builder.py @@ -56,7 +56,6 @@ def import_template(self, path): return True - class NukePlaceholderPlugin(PlaceholderPlugin): node_color = 4278190335 diff --git a/openpype/hosts/nuke/api/workio.py b/openpype/hosts/nuke/api/workio.py index 65b86bf01ba..5692f8e63cb 100644 --- a/openpype/hosts/nuke/api/workio.py +++ b/openpype/hosts/nuke/api/workio.py @@ -13,7 +13,7 @@ def has_unsaved_changes(): def save_file(filepath): path = filepath.replace("\\", "/") - nuke.scriptSaveAs(path) + nuke.scriptSaveAs(path, overwrite=1) nuke.Root()["name"].setValue(path) nuke.Root()["project_directory"].setValue(os.path.dirname(path)) nuke.Root().setModified(False) diff --git a/openpype/pipeline/workfile/workfile_template_builder.py b/openpype/pipeline/workfile/workfile_template_builder.py index 3dd769447fe..d578114de29 100644 --- a/openpype/pipeline/workfile/workfile_template_builder.py +++ b/openpype/pipeline/workfile/workfile_template_builder.py @@ -443,7 +443,7 @@ def build_template( level_limit=None, keep_placeholders=None, create_first_version=None, - run_from_callback=False + workfile_creation_enabled=False ): """Main callback for building workfile from template path. @@ -461,7 +461,7 @@ def build_template( hosts to decide if they want to remove placeholder after it is used. create_first_version (bool): create first version of a workfile - run_from_callback (bool): If True, it might create first version + workfile_creation_enabled (bool): If True, it might create first version but ignore process if version is created """ @@ -475,13 +475,25 @@ def build_template( if create_first_version is None: create_first_version = template_preset["create_first_version"] - # run creation of first version only if it is - # run from callback and no new version is created - first_creation = False - if create_first_version and run_from_callback: - first_creation = not self.create_first_workfile_version() + # check if first version is created + created_version_workfile = self.create_first_workfile_version() - if first_creation: + # if first version is created, import template and populate placeholders + if ( + create_first_version + and workfile_creation_enabled + and created_version_workfile + ): + self.import_template(template_path) + self.populate_scene_placeholders( + level_limit, keep_placeholders) + + # save workfile after template is populated + self.save_workfile(created_version_workfile) + + # ignore process if first workfile is enabled + # but a version is already created + if workfile_creation_enabled: return self.import_template(template_path) @@ -546,20 +558,26 @@ def create_first_workfile_version(self): host's template file. """ last_workfile_path = os.environ.get("AVALON_LAST_WORKFILE") + self.log.info("__ last_workfile_path: {}".format(last_workfile_path)) if os.path.exists(last_workfile_path): # ignore in case workfile existence self.log.info("Workfile already exists, skipping creation.") return False - # Save current scene, continue to open file - if isinstance(self.host, IWorkfileHost): - self.host.save_workfile(last_workfile_path) - else: - self.host.save_file(last_workfile_path) + # Create first version + self.log.info("Creating first version of workfile.") + self.save_workfile(last_workfile_path) # Confirm creation of first version - return True + return last_workfile_path + def save_workfile(self, workfile_path): + """Save workfile in current host.""" + # Save current scene, continue to open file + if isinstance(self.host, IWorkfileHost): + self.host.save_workfile(workfile_path) + else: + self.host.save_file(workfile_path) def _prepare_placeholders(self, placeholders): """Run preparation part for placeholders on plugins. From 6d9084b14424e6c41e859ce633f8b861f6619cd2 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 6 Mar 2023 16:58:17 +0100 Subject: [PATCH 316/898] Match workfile creator logic more with the one from After Effects --- .../fusion/plugins/create/create_workfile.py | 88 ++++++++----------- 1 file changed, 39 insertions(+), 49 deletions(-) diff --git a/openpype/hosts/fusion/plugins/create/create_workfile.py b/openpype/hosts/fusion/plugins/create/create_workfile.py index e539dcf0192..19da2c36a61 100644 --- a/openpype/hosts/fusion/plugins/create/create_workfile.py +++ b/openpype/hosts/fusion/plugins/create/create_workfile.py @@ -13,17 +13,6 @@ ) -def flatten_dict(d, parent_key=None, separator="."): - items = [] - for key, v in d.items(): - new_key = parent_key + separator + key if parent_key else key - if isinstance(v, collections.MutableMapping): - items.extend(flatten_dict(v, new_key, separator=separator).items()) - else: - items.append((new_key, v)) - return dict(items) - - class FusionWorkfileCreator(AutoCreator): identifier = "workfile" family = "workfile" @@ -61,8 +50,9 @@ def update_instances(self, update_list): " Comp might have been closed in the meantime.") continue - new_data = created_inst.data_to_store() - self._imprint(comp, new_data) + # Imprint data into the comp + data = created_inst.data_to_store() + comp.SetData(self.data_key, data) def create(self, options=None): @@ -71,50 +61,50 @@ def create(self, options=None): self.log.error("Unable to find current comp") return - # TODO: Is this really necessary? - # Force kill any existing "workfile" instances + existing_instance = None for instance in self.create_context.instances: if instance.family == self.family: - self.log.debug(f"Removing instance: {instance}") - self._remove_instance_from_context(instance) + existing_instance = instance + break project_name = legacy_io.Session["AVALON_PROJECT"] asset_name = legacy_io.Session["AVALON_ASSET"] task_name = legacy_io.Session["AVALON_TASK"] host_name = legacy_io.Session["AVALON_APP"] - asset_doc = get_asset_by_name(project_name, asset_name) - subset_name = self.get_subset_name( - self.default_variant, task_name, asset_doc, - project_name, host_name - ) - data = { - "asset": asset_name, - "task": task_name, - "variant": self.default_variant - } - data.update(self.get_dynamic_data( - self.default_variant, - task_name, - asset_doc, - project_name, - host_name, - data - )) - - instance = CreatedInstance( - family=self.family, - subset_name=subset_name, - data=data, - creator=self - ) - instance.transient_data["comp"] = comp - self._add_instance_to_context(instance) - - self._imprint(comp, data) + if existing_instance is None: + asset_doc = get_asset_by_name(project_name, asset_name) + subset_name = self.get_subset_name( + self.default_variant, task_name, asset_doc, + project_name, host_name + ) + data = { + "asset": asset_name, + "task": task_name, + "variant": self.default_variant + } + data.update(self.get_dynamic_data( + self.default_variant, task_name, asset_doc, + project_name, host_name, None + )) + + new_instance = CreatedInstance( + self.family, subset_name, data, self + ) + self._add_instance_to_context(new_instance) + + elif ( + existing_instance["asset"] != asset_name + or existing_instance["task"] != task_name + ): + asset_doc = get_asset_by_name(project_name, asset_name) + subset_name = self.get_subset_name( + self.default_variant, task_name, asset_doc, + project_name, host_name + ) + existing_instance["asset"] = asset_name + existing_instance["task"] = task_name + existing_instance["subset"] = subset_name def get_icon(self): return qtawesome.icon("fa.file-o", color="white") - - def _imprint(self, comp, data): - comp.SetData(self.data_key, data) From 52fac29164d279823a72b15a1ad5ac4c1b57b8b6 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 6 Mar 2023 17:07:15 +0100 Subject: [PATCH 317/898] Cleanup unused import --- openpype/hosts/fusion/plugins/create/create_workfile.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openpype/hosts/fusion/plugins/create/create_workfile.py b/openpype/hosts/fusion/plugins/create/create_workfile.py index 19da2c36a61..2f78e4fe52b 100644 --- a/openpype/hosts/fusion/plugins/create/create_workfile.py +++ b/openpype/hosts/fusion/plugins/create/create_workfile.py @@ -1,5 +1,3 @@ -import collections - import qtawesome from openpype.hosts.fusion.api import ( From af393688389346fc590a504514d4eb8de0c375ce Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 6 Mar 2023 17:07:56 +0100 Subject: [PATCH 318/898] hound --- openpype/hosts/nuke/api/lib.py | 2 +- openpype/hosts/nuke/api/workfile_template_builder.py | 4 ---- openpype/pipeline/workfile/workfile_template_builder.py | 8 +++++--- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index 793dc8fcdd3..a5a631cc70f 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -2682,11 +2682,11 @@ def start_workfile_template_builder(): build_workfile_template ) - # to avoid looping of the callback, remove it! log.info("Starting workfile template builder...") build_workfile_template(workfile_creation_enabled=True) + # remove callback since it would be duplicating the workfile nuke.removeOnCreate(start_workfile_template_builder, nodeClass="Root") @deprecated diff --git a/openpype/hosts/nuke/api/workfile_template_builder.py b/openpype/hosts/nuke/api/workfile_template_builder.py index a6805d1b149..fb0afb3d553 100644 --- a/openpype/hosts/nuke/api/workfile_template_builder.py +++ b/openpype/hosts/nuke/api/workfile_template_builder.py @@ -1,8 +1,5 @@ -import os import collections - import nuke - from openpype.pipeline import registered_host from openpype.pipeline.workfile.workfile_template_builder import ( AbstractTemplateBuilder, @@ -15,7 +12,6 @@ from openpype.tools.workfile_template_build import ( WorkfileBuildPlaceholderDialog, ) -from openpype.host import IWorkfileHost from .lib import ( find_free_space_to_paste_nodes, get_extreme_positions, diff --git a/openpype/pipeline/workfile/workfile_template_builder.py b/openpype/pipeline/workfile/workfile_template_builder.py index d578114de29..0ce59de8ad8 100644 --- a/openpype/pipeline/workfile/workfile_template_builder.py +++ b/openpype/pipeline/workfile/workfile_template_builder.py @@ -461,8 +461,9 @@ def build_template( hosts to decide if they want to remove placeholder after it is used. create_first_version (bool): create first version of a workfile - workfile_creation_enabled (bool): If True, it might create first version - but ignore process if version is created + workfile_creation_enabled (bool): If True, it might create + first version but ignore + process if version is created """ template_preset = self.get_template_preset() @@ -478,7 +479,8 @@ def build_template( # check if first version is created created_version_workfile = self.create_first_workfile_version() - # if first version is created, import template and populate placeholders + # if first version is created, import template + # and populate placeholders if ( create_first_version and workfile_creation_enabled From de50783c0435ec75a8ac7d9b29068c96a7bab8de Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 6 Mar 2023 18:34:56 +0100 Subject: [PATCH 319/898] Nuke: Add option to use new creating system in workfile template builder (#4545) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * added option to use new creating system in workfile template builder * fix spaces * use 'create' method on create context to trigger creation * fix attribute access * adding headless to creators and workfile builder abstraction * adding noqa for hound * hound --------- Co-authored-by: Jakub Jezek Co-authored-by: Ondřej Samohel <33513211+antirotor@users.noreply.github.com> --- .../maya/api/workfile_template_builder.py | 2 + openpype/hosts/nuke/api/plugin.py | 6 +- .../nuke/plugins/create/create_write_image.py | 2 +- .../plugins/create/create_write_prerender.py | 2 +- .../plugins/create/create_write_render.py | 2 +- .../workfile/workfile_template_builder.py | 97 ++++++++++++++----- 6 files changed, 81 insertions(+), 30 deletions(-) diff --git a/openpype/hosts/maya/api/workfile_template_builder.py b/openpype/hosts/maya/api/workfile_template_builder.py index 2f550e787ac..90ab6e21e04 100644 --- a/openpype/hosts/maya/api/workfile_template_builder.py +++ b/openpype/hosts/maya/api/workfile_template_builder.py @@ -22,6 +22,8 @@ class MayaTemplateBuilder(AbstractTemplateBuilder): """Concrete implementation of AbstractTemplateBuilder for maya""" + use_legacy_creators = True + def import_template(self, path): """Import template into current scene. Block if a template is already loaded. diff --git a/openpype/hosts/nuke/api/plugin.py b/openpype/hosts/nuke/api/plugin.py index 6c2d4b84be4..aec87be5ab6 100644 --- a/openpype/hosts/nuke/api/plugin.py +++ b/openpype/hosts/nuke/api/plugin.py @@ -239,7 +239,11 @@ def remove_instances(self, instances): def get_pre_create_attr_defs(self): return [ - BoolDef("use_selection", label="Use selection") + BoolDef( + "use_selection", + default=not self.create_context.headless, + label="Use selection" + ) ] def get_creator_settings(self, project_settings, settings_key=None): diff --git a/openpype/hosts/nuke/plugins/create/create_write_image.py b/openpype/hosts/nuke/plugins/create/create_write_image.py index 1e23b3ad7f9..d38253ab2f3 100644 --- a/openpype/hosts/nuke/plugins/create/create_write_image.py +++ b/openpype/hosts/nuke/plugins/create/create_write_image.py @@ -35,7 +35,7 @@ def get_pre_create_attr_defs(self): attr_defs = [ BoolDef( "use_selection", - default=True, + default=not self.create_context.headless, label="Use selection" ), self._get_render_target_enum(), diff --git a/openpype/hosts/nuke/plugins/create/create_write_prerender.py b/openpype/hosts/nuke/plugins/create/create_write_prerender.py index 1603bf17e38..8103cb7c4d5 100644 --- a/openpype/hosts/nuke/plugins/create/create_write_prerender.py +++ b/openpype/hosts/nuke/plugins/create/create_write_prerender.py @@ -34,7 +34,7 @@ def get_pre_create_attr_defs(self): attr_defs = [ BoolDef( "use_selection", - default=True, + default=not self.create_context.headless, label="Use selection" ), self._get_render_target_enum() diff --git a/openpype/hosts/nuke/plugins/create/create_write_render.py b/openpype/hosts/nuke/plugins/create/create_write_render.py index 72fcb4f2322..23efa62e368 100644 --- a/openpype/hosts/nuke/plugins/create/create_write_render.py +++ b/openpype/hosts/nuke/plugins/create/create_write_render.py @@ -31,7 +31,7 @@ def get_pre_create_attr_defs(self): attr_defs = [ BoolDef( "use_selection", - default=True, + default=not self.create_context.headless, label="Use selection" ), self._get_render_target_enum() diff --git a/openpype/pipeline/workfile/workfile_template_builder.py b/openpype/pipeline/workfile/workfile_template_builder.py index 119e4aaeb7b..27214af79f6 100644 --- a/openpype/pipeline/workfile/workfile_template_builder.py +++ b/openpype/pipeline/workfile/workfile_template_builder.py @@ -43,7 +43,8 @@ load_with_repre_context, ) from openpype.pipeline.create import ( - discover_legacy_creator_plugins + discover_legacy_creator_plugins, + CreateContext, ) @@ -91,6 +92,7 @@ class AbstractTemplateBuilder(object): """ _log = None + use_legacy_creators = False def __init__(self, host): # Get host name @@ -110,6 +112,7 @@ def __init__(self, host): self._placeholder_plugins = None self._loaders_by_name = None self._creators_by_name = None + self._create_context = None self._system_settings = None self._project_settings = None @@ -171,6 +174,16 @@ def current_task_type(self): .get("type") ) + @property + def create_context(self): + if self._create_context is None: + self._create_context = CreateContext( + self.host, + discover_publish_plugins=False, + headless=True + ) + return self._create_context + def get_placeholder_plugin_classes(self): """Get placeholder plugin classes that can be used to build template. @@ -235,18 +248,29 @@ def get_loaders_by_name(self): self._loaders_by_name = get_loaders_by_name() return self._loaders_by_name + def _collect_legacy_creators(self): + creators_by_name = {} + for creator in discover_legacy_creator_plugins(): + if not creator.enabled: + continue + creator_name = creator.__name__ + if creator_name in creators_by_name: + raise KeyError( + "Duplicated creator name {} !".format(creator_name) + ) + creators_by_name[creator_name] = creator + self._creators_by_name = creators_by_name + + def _collect_creators(self): + self._creators_by_name = dict(self.create_context.creators) + def get_creators_by_name(self): if self._creators_by_name is None: - self._creators_by_name = {} - for creator in discover_legacy_creator_plugins(): - if not creator.enabled: - continue - creator_name = creator.__name__ - if creator_name in self._creators_by_name: - raise KeyError( - "Duplicated creator name {} !".format(creator_name) - ) - self._creators_by_name[creator_name] = creator + if self.use_legacy_creators: + self._collect_legacy_creators() + else: + self._collect_creators() + return self._creators_by_name def get_shared_data(self, key): @@ -1579,6 +1603,8 @@ def populate_create_placeholder(self, placeholder): placeholder (PlaceholderItem): Placeholder item with information about requested publishable instance. """ + + legacy_create = self.builder.use_legacy_creators creator_name = placeholder.data["creator"] create_variant = placeholder.data["create_variant"] @@ -1589,17 +1615,28 @@ def populate_create_placeholder(self, placeholder): task_name = legacy_io.Session["AVALON_TASK"] asset_name = legacy_io.Session["AVALON_ASSET"] - # get asset id - asset_doc = get_asset_by_name(project_name, asset_name, fields=["_id"]) - assert asset_doc, "No current asset found in Session" - asset_id = asset_doc['_id'] + if legacy_create: + asset_doc = get_asset_by_name( + project_name, asset_name, fields=["_id"] + ) + assert asset_doc, "No current asset found in Session" + subset_name = creator_plugin.get_subset_name( + create_variant, + task_name, + asset_doc["_id"], + project_name + ) - subset_name = creator_plugin.get_subset_name( - create_variant, - task_name, - asset_id, - project_name - ) + else: + asset_doc = get_asset_by_name(project_name, asset_name) + assert asset_doc, "No current asset found in Session" + subset_name = creator_plugin.get_subset_name( + create_variant, + task_name, + asset_doc, + project_name, + self.builder.host_name + ) creator_data = { "creator_name": creator_name, @@ -1612,12 +1649,20 @@ def populate_create_placeholder(self, placeholder): # compile subset name from variant try: - creator_instance = creator_plugin( - subset_name, - asset_name - ).process() + if legacy_create: + creator_instance = creator_plugin( + subset_name, + asset_name + ).process() + else: + creator_instance = self.builder.create_context.create( + creator_plugin.identifier, + create_variant, + asset_doc, + task_name=task_name + ) - except Exception: + except: # noqa: E722 failed = True self.create_failed(placeholder, creator_data) From 16cece3e499b0336e490b1ac0bf01d69f715d0f6 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 6 Mar 2023 19:45:17 +0100 Subject: [PATCH 320/898] Fusion: get filepath from representation instead of listing files from publish folder --- .../fusion/plugins/load/load_sequence.py | 25 ++++++------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/openpype/hosts/fusion/plugins/load/load_sequence.py b/openpype/hosts/fusion/plugins/load/load_sequence.py index 6f44c61d1b3..9daf4b007d0 100644 --- a/openpype/hosts/fusion/plugins/load/load_sequence.py +++ b/openpype/hosts/fusion/plugins/load/load_sequence.py @@ -1,11 +1,9 @@ -import os import contextlib -from openpype.client import get_version_by_id -from openpype.pipeline import ( - load, - legacy_io, - get_representation_path, +import openpype.pipeline.load as load +from openpype.pipeline.load import ( + get_representation_context, + get_representation_path_from_context ) from openpype.hosts.fusion.api import ( imprint_container, @@ -141,7 +139,7 @@ def load(self, context, name, namespace, data): namespace = context['asset']['name'] # Use the first file for now - path = self._get_first_image(os.path.dirname(self.fname)) + path = get_representation_path_from_context(context) # Create the Loader with the filename path set comp = get_current_comp() @@ -210,13 +208,11 @@ def update(self, container, representation): assert tool.ID == "Loader", "Must be Loader" comp = tool.Comp() - root = os.path.dirname(get_representation_path(representation)) - path = self._get_first_image(root) + context = get_representation_context(representation) + path = get_representation_path_from_context(context) # Get start frame from version data - project_name = legacy_io.active_project() - version = get_version_by_id(project_name, representation["parent"]) - start = self._get_start(version, tool) + start = self._get_start(context["version"], tool) with comp_lock_and_undo_chunk(comp, "Update Loader"): @@ -249,11 +245,6 @@ def remove(self, container): with comp_lock_and_undo_chunk(comp, "Remove Loader"): tool.Delete() - def _get_first_image(self, root): - """Get first file in representation root""" - files = sorted(os.listdir(root)) - return os.path.join(root, files[0]) - def _get_start(self, version_doc, tool): """Return real start frame of published files (incl. handles)""" data = version_doc["data"] From bc1ef9229c2250aa0be84917bf6bc23e9ec65354 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 7 Mar 2023 10:39:20 +0100 Subject: [PATCH 321/898] Photoshop: context is not changed in publisher (#4570) * OP-5025 - fix - proper changing of context When PS is already opened, new opening from different context should change it. * OP-5025 - open last workfile for new context if present * OP-5025 - remove unneeded assignemnt * OP-5025 - removed whitespace --- openpype/hosts/photoshop/api/launch_logic.py | 79 ++++++++++++++++---- 1 file changed, 63 insertions(+), 16 deletions(-) diff --git a/openpype/hosts/photoshop/api/launch_logic.py b/openpype/hosts/photoshop/api/launch_logic.py index a4377a9972b..89ba6ad4e6c 100644 --- a/openpype/hosts/photoshop/api/launch_logic.py +++ b/openpype/hosts/photoshop/api/launch_logic.py @@ -10,10 +10,20 @@ from qtpy import QtCore -from openpype.lib import Logger -from openpype.pipeline import legacy_io +from openpype.lib import Logger, StringTemplate +from openpype.pipeline import ( + registered_host, + Anatomy, +) +from openpype.pipeline.workfile import ( + get_workfile_template_key_from_context, + get_last_workfile, +) +from openpype.pipeline.template_data import get_template_data_with_names from openpype.tools.utils import host_tools from openpype.tools.adobe_webserver.app import WebServerTool +from openpype.pipeline.context_tools import change_current_context +from openpype.client import get_asset_by_name from .ws_stub import PhotoshopServerStub @@ -310,23 +320,28 @@ async def ping(self): # client functions async def set_context(self, project, asset, task): """ - Sets 'project' and 'asset' to envs, eg. setting context + Sets 'project' and 'asset' to envs, eg. setting context. - Args: - project (str) - asset (str) + Opens last workile from that context if exists. + + Args: + project (str) + asset (str) + task (str """ log.info("Setting context change") - log.info("project {} asset {} ".format(project, asset)) - if project: - legacy_io.Session["AVALON_PROJECT"] = project - os.environ["AVALON_PROJECT"] = project - if asset: - legacy_io.Session["AVALON_ASSET"] = asset - os.environ["AVALON_ASSET"] = asset - if task: - legacy_io.Session["AVALON_TASK"] = task - os.environ["AVALON_TASK"] = task + log.info(f"project {project} asset {asset} task {task}") + + asset_doc = get_asset_by_name(project, asset) + change_current_context(asset_doc, task) + + last_workfile_path = self._get_last_workfile_path(project, + asset, + task) + if last_workfile_path and os.path.exists(last_workfile_path): + ProcessLauncher.execute_in_main_thread( + lambda: stub().open(last_workfile_path)) + async def read(self): log.debug("photoshop.read client calls server server calls " @@ -356,3 +371,35 @@ def _tool_route(self, _tool_name): # Required return statement. return "nothing" + + def _get_last_workfile_path(self, project_name, asset_name, task_name): + """Returns last workfile path if exists""" + host = registered_host() + host_name = "photoshop" + template_key = get_workfile_template_key_from_context( + asset_name, + task_name, + host_name, + project_name=project_name + ) + anatomy = Anatomy(project_name) + + data = get_template_data_with_names( + project_name, asset_name, task_name, host_name + ) + data["root"] = anatomy.roots + + file_template = anatomy.templates[template_key]["file"] + + # Define saving file extension + extensions = host.get_workfile_extensions() + + folder_template = anatomy.templates[template_key]["folder"] + work_root = StringTemplate.format_strict_template( + folder_template, data + ) + last_workfile_path = get_last_workfile( + work_root, file_template, data, extensions, True + ) + + return last_workfile_path From 73e0ba9cb266507c0f7ea562d6895bcd2dbaaddb Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 7 Mar 2023 10:53:06 +0100 Subject: [PATCH 322/898] Set colorspace based on file rules in imageio settings --- openpype/hosts/fusion/plugins/publish/render_local.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/plugins/publish/render_local.py b/openpype/hosts/fusion/plugins/publish/render_local.py index 0eca7f6cdd5..212242630bd 100644 --- a/openpype/hosts/fusion/plugins/publish/render_local.py +++ b/openpype/hosts/fusion/plugins/publish/render_local.py @@ -1,9 +1,11 @@ import os import pyblish.api +from openpype.pipeline import publish from openpype.hosts.fusion.api import comp_lock_and_undo_chunk -class Fusionlocal(pyblish.api.InstancePlugin): +class Fusionlocal(pyblish.api.InstancePlugin, + publish.ColormanagedPyblishPluginMixin): """Render the current Fusion composition locally. Extract the result of savers by starting a comp render @@ -50,6 +52,11 @@ def process(self, instance): "stagingDir": output_dir, } + self.set_representation_colorspace( + representation=repre, + context=context, + ) + if "representations" not in instance.data: instance.data["representations"] = [] instance.data["representations"].append(repre) From 1bb7dbc9d9707335d246e9a7a924859c1d09fd84 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 7 Mar 2023 10:55:40 +0100 Subject: [PATCH 323/898] Make sure repre preview copy is a deepcopy --- openpype/hosts/fusion/plugins/publish/render_local.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/plugins/publish/render_local.py b/openpype/hosts/fusion/plugins/publish/render_local.py index 212242630bd..9ed17f23c67 100644 --- a/openpype/hosts/fusion/plugins/publish/render_local.py +++ b/openpype/hosts/fusion/plugins/publish/render_local.py @@ -1,4 +1,6 @@ import os +import copy + import pyblish.api from openpype.pipeline import publish from openpype.hosts.fusion.api import comp_lock_and_undo_chunk @@ -62,7 +64,7 @@ def process(self, instance): instance.data["representations"].append(repre) # review representation - repre_preview = repre.copy() + repre_preview = copy.deepcopy(repre) repre_preview["name"] = repre_preview["ext"] = "mp4" repre_preview["tags"] = ["review", "ftrackreview", "delete"] instance.data["representations"].append(repre_preview) From 70611ee884d63400e9466deaa66be7beb89d0003 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 7 Mar 2023 11:36:12 +0100 Subject: [PATCH 324/898] Make sure to add the `comp` transient data for new instances --- openpype/hosts/fusion/plugins/create/create_workfile.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/fusion/plugins/create/create_workfile.py b/openpype/hosts/fusion/plugins/create/create_workfile.py index 2f78e4fe52b..0bb3a0d3d43 100644 --- a/openpype/hosts/fusion/plugins/create/create_workfile.py +++ b/openpype/hosts/fusion/plugins/create/create_workfile.py @@ -89,6 +89,7 @@ def create(self, options=None): new_instance = CreatedInstance( self.family, subset_name, data, self ) + new_instance.transient_data["comp"] = comp self._add_instance_to_context(new_instance) elif ( From 113b958369ae9853a3e9872a00d5c925d359b381 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 7 Mar 2023 12:05:58 +0100 Subject: [PATCH 325/898] Collect Fusion workfile representation --- .../plugins/publish/collect_workfile.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 openpype/hosts/fusion/plugins/publish/collect_workfile.py diff --git a/openpype/hosts/fusion/plugins/publish/collect_workfile.py b/openpype/hosts/fusion/plugins/publish/collect_workfile.py new file mode 100644 index 00000000000..4c288edb3ee --- /dev/null +++ b/openpype/hosts/fusion/plugins/publish/collect_workfile.py @@ -0,0 +1,26 @@ +import os + +import pyblish.api + + +class CollectFusionWorkfile(pyblish.api.InstancePlugin): + """Collect Fusion workfile representation.""" + + order = pyblish.api.CollectorOrder + 0.1 + label = "Collect Workfile" + hosts = ["fusion"] + families = ["workfile"] + + def process(self, instance): + + current_file = instance.context.data["currentFile"] + + folder, file = os.path.split(current_file) + filename, ext = os.path.splitext(file) + + instance.data['representations'] = [{ + 'name': ext.lstrip("."), + 'ext': ext.lstrip("."), + 'files': file, + "stagingDir": folder, + }] From b3636b9f558ace05722798e2343fcbc01ba55ca4 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Tue, 7 Mar 2023 13:45:49 +0100 Subject: [PATCH 326/898] General: Input representation ids are not ObjectIds (#4576) * input representation ids are not ObjectIds during publishing * changed set back to list * use 'setdefault' to set 'inputVersions' * added default value to 'get' * Use default value in second loop too Co-authored-by: Roy Nieterau * simplify variable assignment Co-authored-by: Roy Nieterau --------- Co-authored-by: Roy Nieterau --- .../fusion/plugins/publish/collect_inputs.py | 5 +---- .../houdini/plugins/publish/collect_inputs.py | 5 +---- .../hosts/maya/plugins/publish/collect_inputs.py | 4 +--- .../collect_input_representations_to_versions.py | 15 ++++++++------- 4 files changed, 11 insertions(+), 18 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/collect_inputs.py b/openpype/hosts/fusion/plugins/publish/collect_inputs.py index 8f9857b02ff..b6619fdcd66 100644 --- a/openpype/hosts/fusion/plugins/publish/collect_inputs.py +++ b/openpype/hosts/fusion/plugins/publish/collect_inputs.py @@ -1,5 +1,3 @@ -from bson.objectid import ObjectId - import pyblish.api from openpype.pipeline import registered_host @@ -108,7 +106,6 @@ def process(self, instance): # Collect containers for the given set of nodes containers = collect_input_containers(nodes) - inputs = [ObjectId(c["representation"]) for c in containers] + inputs = [c["representation"] for c in containers] instance.data["inputRepresentations"] = inputs - self.log.info("Collected inputs: %s" % inputs) diff --git a/openpype/hosts/houdini/plugins/publish/collect_inputs.py b/openpype/hosts/houdini/plugins/publish/collect_inputs.py index 0b54b244bbe..6411376ea34 100644 --- a/openpype/hosts/houdini/plugins/publish/collect_inputs.py +++ b/openpype/hosts/houdini/plugins/publish/collect_inputs.py @@ -1,5 +1,3 @@ -from bson.objectid import ObjectId - import pyblish.api from openpype.pipeline import registered_host @@ -117,7 +115,6 @@ def process(self, instance): # Collect containers for the given set of nodes containers = collect_input_containers(nodes) - inputs = [ObjectId(c["representation"]) for c in containers] + inputs = [c["representation"] for c in containers] instance.data["inputRepresentations"] = inputs - self.log.info("Collected inputs: %s" % inputs) diff --git a/openpype/hosts/maya/plugins/publish/collect_inputs.py b/openpype/hosts/maya/plugins/publish/collect_inputs.py index 470fceffc99..9c3f0f5efa7 100644 --- a/openpype/hosts/maya/plugins/publish/collect_inputs.py +++ b/openpype/hosts/maya/plugins/publish/collect_inputs.py @@ -1,5 +1,4 @@ import copy -from bson.objectid import ObjectId from maya import cmds import maya.api.OpenMaya as om @@ -165,9 +164,8 @@ def process(self, instance): containers = collect_input_containers(scene_containers, nodes) - inputs = [ObjectId(c["representation"]) for c in containers] + inputs = [c["representation"] for c in containers] instance.data["inputRepresentations"] = inputs - self.log.info("Collected inputs: %s" % inputs) def _collect_renderlayer_inputs(self, scene_containers, instance): diff --git a/openpype/plugins/publish/collect_input_representations_to_versions.py b/openpype/plugins/publish/collect_input_representations_to_versions.py index 18a19bce804..54a3214647e 100644 --- a/openpype/plugins/publish/collect_input_representations_to_versions.py +++ b/openpype/plugins/publish/collect_input_representations_to_versions.py @@ -23,7 +23,8 @@ def process(self, context): representations = set() for instance in context: inst_repre = instance.data.get("inputRepresentations", []) - representations.update(inst_repre) + if inst_repre: + representations.update(inst_repre) representations_docs = get_representations( project_name=context.data["projectEntity"]["name"], @@ -31,7 +32,8 @@ def process(self, context): fields=["_id", "parent"]) representation_id_to_version_id = { - repre["_id"]: repre["parent"] for repre in representations_docs + str(repre["_id"]): repre["parent"] + for repre in representations_docs } for instance in context: @@ -39,9 +41,8 @@ def process(self, context): if not inst_repre: continue - input_versions = instance.data.get("inputVersions", []) + input_versions = instance.data.setdefault("inputVersions", []) for repre_id in inst_repre: - repre_id = ObjectId(repre_id) - version_id = representation_id_to_version_id[repre_id] - input_versions.append(version_id) - instance.data["inputVersions"] = input_versions + version_id = representation_id_to_version_id.get(repre_id) + if version_id: + input_versions.append(version_id) From f94fb76a238c5fc24ff26d84061fc7f7f5d5c90f Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 7 Mar 2023 13:56:53 +0100 Subject: [PATCH 327/898] Update OCIO config hook to use the correct imageio settings --- .../fusion/hooks/pre_fusion_ocio_hook.py | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_ocio_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_ocio_hook.py index d1ae5f64fd7..6bf0f55081b 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_ocio_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_ocio_hook.py @@ -1,7 +1,7 @@ -import os -import platform +from openpype.lib import PreLaunchHook -from openpype.lib import PreLaunchHook, ApplicationLaunchFailed +from openpype.pipeline.colorspace import get_imageio_config +from openpype.pipeline.template_data import get_template_data_with_names class FusionPreLaunchOCIO(PreLaunchHook): @@ -11,24 +11,22 @@ class FusionPreLaunchOCIO(PreLaunchHook): def execute(self): """Hook entry method.""" - # get image io - project_settings = self.data["project_settings"] - - # make sure anatomy settings are having flame key - imageio_fusion = project_settings["fusion"]["imageio"] - - ocio = imageio_fusion.get("ocio") - enabled = ocio.get("enabled", False) - if not enabled: - return - - platform_key = platform.system().lower() - ocio_path = ocio["configFilePath"][platform_key] - if not ocio_path: - raise ApplicationLaunchFailed( - "Fusion OCIO is enabled in project settings but no OCIO config" - f"path is set for your current platform: {platform_key}" - ) + template_data = get_template_data_with_names( + project_name=self.data["project_name"], + asset_name=self.data["asset_name"], + task_name=self.data["task_name"], + host_name=self.host_name, + system_settings=self.data["system_settings"] + ) + + config_data = get_imageio_config( + project_name=self.data["project_name"], + host_name=self.host_name, + project_settings=self.data["project_settings"], + anatomy_data=template_data, + anatomy=self.data["anatomy"] + ) + ocio_path = config_data["path"] self.log.info(f"Setting OCIO config path: {ocio_path}") - self.launch_context.env["OCIO"] = os.pathsep.join(ocio_path) + self.launch_context.env["OCIO"] = ocio_path From d47f0054deb49827890ad3b070e282d74aa2c62a Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 7 Mar 2023 14:38:42 +0100 Subject: [PATCH 328/898] Fix actions --- .../hosts/fusion/plugins/publish/validate_background_depth.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/validate_background_depth.py b/openpype/hosts/fusion/plugins/publish/validate_background_depth.py index 261533de019..db2c4f0dd95 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_background_depth.py +++ b/openpype/hosts/fusion/plugins/publish/validate_background_depth.py @@ -11,12 +11,11 @@ class ValidateBackgroundDepth(pyblish.api.InstancePlugin): order = pyblish.api.ValidatorOrder label = "Validate Background Depth 32 bit" - actions = [RepairAction] hosts = ["fusion"] families = ["render"] optional = True - actions = [SelectInvalidAction] + actions = [SelectInvalidAction, RepairAction] @classmethod def get_invalid(cls, instance): From b4727101c969689fb8bebbfc7afde20680da7dfb Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 7 Mar 2023 14:39:20 +0100 Subject: [PATCH 329/898] Directly collect comp frame ranges in Collect comp --- .../fusion/plugins/publish/collect_comp.py | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/collect_comp.py b/openpype/hosts/fusion/plugins/publish/collect_comp.py index dfa540fa7f9..911071c9a04 100644 --- a/openpype/hosts/fusion/plugins/publish/collect_comp.py +++ b/openpype/hosts/fusion/plugins/publish/collect_comp.py @@ -1,10 +1,26 @@ -import os - import pyblish.api from openpype.hosts.fusion.api import get_current_comp +def get_comp_render_range(comp): + """Return comp's start-end render range and global start-end range.""" + comp_attrs = comp.GetAttrs() + start = comp_attrs["COMPN_RenderStart"] + end = comp_attrs["COMPN_RenderEnd"] + global_start = comp_attrs["COMPN_GlobalStart"] + global_end = comp_attrs["COMPN_GlobalEnd"] + + # Whenever render ranges are undefined fall back + # to the comp's global start and end + if start == -1000000000: + start = global_start + if end == -1000000000: + end = global_end + + return start, end, global_start, global_end + + class CollectCurrentCompFusion(pyblish.api.ContextPlugin): """Collect current comp""" @@ -15,10 +31,17 @@ class CollectCurrentCompFusion(pyblish.api.ContextPlugin): def process(self, context): """Collect all image sequence tools""" - current_comp = get_current_comp() - assert current_comp, "Must have active Fusion composition" - context.data["currentComp"] = current_comp + comp = get_current_comp() + assert comp, "Must have active Fusion composition" + context.data["currentComp"] = comp # Store path to current file - filepath = current_comp.GetAttrs().get("COMPS_FileName", "") + filepath = comp.GetAttrs().get("COMPS_FileName", "") context.data['currentFile'] = filepath + + # Store comp render ranges + start, end, global_start, global_end = get_comp_render_range(comp) + context.data["frameStart"] = int(start) + context.data["frameEnd"] = int(end) + context.data["frameStartHandle"] = int(global_start) + context.data["frameEndHandle"] = int(global_end) From a4ae05086cbbd7968b37801c3a70f0a763ab487e Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 7 Mar 2023 14:41:16 +0100 Subject: [PATCH 330/898] Allow to enable/disable review per saver instance + Don't create a copy of representation for review but just mark representation as review + Change Collect instances into InstancePlugin to just collect instance data per instance --- .../fusion/plugins/create/create_saver.py | 10 ++ .../plugins/publish/collect_instances.py | 126 ++++++++---------- .../fusion/plugins/publish/render_local.py | 6 +- 3 files changed, 68 insertions(+), 74 deletions(-) diff --git a/openpype/hosts/fusion/plugins/create/create_saver.py b/openpype/hosts/fusion/plugins/create/create_saver.py index b0c0d830a38..bf11dc95c59 100644 --- a/openpype/hosts/fusion/plugins/create/create_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_saver.py @@ -7,6 +7,7 @@ comp_lock_and_undo_chunk ) +from openpype.lib import BoolDef from openpype.pipeline import ( legacy_io, Creator, @@ -192,3 +193,12 @@ def get_managed_tool_data(self, tool): return return data + + def get_instance_attr_defs(self): + return [ + BoolDef( + "review", + default=True, + label="Review" + ) + ] diff --git a/openpype/hosts/fusion/plugins/publish/collect_instances.py b/openpype/hosts/fusion/plugins/publish/collect_instances.py index 4e5e151789c..1e6d095cc23 100644 --- a/openpype/hosts/fusion/plugins/publish/collect_instances.py +++ b/openpype/hosts/fusion/plugins/publish/collect_instances.py @@ -3,25 +3,7 @@ import pyblish.api -def get_comp_render_range(comp): - """Return comp's start-end render range and global start-end range.""" - comp_attrs = comp.GetAttrs() - start = comp_attrs["COMPN_RenderStart"] - end = comp_attrs["COMPN_RenderEnd"] - global_start = comp_attrs["COMPN_GlobalStart"] - global_end = comp_attrs["COMPN_GlobalEnd"] - - # Whenever render ranges are undefined fall back - # to the comp's global start and end - if start == -1000000000: - start = global_start - if end == -1000000000: - end = global_end - - return start, end, global_start, global_end - - -class CollectInstances(pyblish.api.ContextPlugin): +class CollectInstanceData(pyblish.api.InstancePlugin): """Collect Fusion saver instances This additionally stores the Comp start and end render range in the @@ -33,59 +15,63 @@ class CollectInstances(pyblish.api.ContextPlugin): label = "Collect Instances Data" hosts = ["fusion"] - def process(self, context): + def process(self, instance): """Collect all image sequence tools""" - from openpype.hosts.fusion.api.lib import get_frame_path - - comp = context.data["currentComp"] - start, end, global_start, global_end = get_comp_render_range(comp) - context.data["frameStart"] = int(start) - context.data["frameEnd"] = int(end) - context.data["frameStartHandle"] = int(global_start) - context.data["frameEndHandle"] = int(global_end) - - for instance in context: - # Include start and end render frame in label - subset = instance.data["subset"] - label = "{subset} ({start}-{end})".format(subset=subset, - start=int(start), - end=int(end)) + context = instance.context + + # Include creator attributes directly as instance data + creator_attributes = instance.data["creator_attributes"] + instance.data.update(creator_attributes) + + # Include start and end render frame in label + subset = instance.data["subset"] + start = context.data["frameStart"] + end = context.data["frameEnd"] + label = "{subset} ({start}-{end})".format(subset=subset, + start=int(start), + end=int(end)) + instance.data.update({ + "label": label, + + # todo: Allow custom frame range per instance + "frameStart": context.data["frameStart"], + "frameEnd": context.data["frameEnd"], + "frameStartHandle": context.data["frameStartHandle"], + "frameEndHandle": context.data["frameStartHandle"], + "fps": context.data["fps"], + }) + + # Add review family if the instance is marked as 'review' + # This could be done through a 'review' Creator attribute. + if instance.data.get("review", False): + self.log.info("Adding review family..") + instance.data["families"].append("review") + + if instance.data["family"] == "render": + # TODO: This should probably move into a collector of + # its own for the "render" family + from openpype.hosts.fusion.api.lib import get_frame_path + comp = context.data["currentComp"] + + # This is only the case for savers currently but not + # for workfile instances. So we assume saver here. + tool = instance.data["transientData"]["tool"] + path = tool["Clip"][comp.TIME_UNDEFINED] + + filename = os.path.basename(path) + head, padding, tail = get_frame_path(filename) + ext = os.path.splitext(path)[1] + assert tail == ext, ("Tail does not match %s" % ext) + instance.data.update({ - "label": label, - # todo: Allow custom frame range per instance - "task": context.data["task"], - "frameStart": context.data["frameStart"], - "frameEnd": context.data["frameEnd"], - "frameStartHandle": context.data["frameStartHandle"], - "frameEndHandle": context.data["frameStartHandle"], - "fps": context.data["fps"], + "path": path, + "outputDir": os.path.dirname(path), + "ext": ext, # todo: should be redundant? + + # Backwards compatibility: embed tool in instance.data + "tool": tool }) - if instance.data["family"] == "render": - # TODO: This should probably move into a collector of - # its own for the "render" family - # This is only the case for savers currently but not - # for workfile instances. So we assume saver here. - tool = instance.data["transientData"]["tool"] - path = tool["Clip"][comp.TIME_UNDEFINED] - - filename = os.path.basename(path) - head, padding, tail = get_frame_path(filename) - ext = os.path.splitext(path)[1] - assert tail == ext, ("Tail does not match %s" % ext) - - instance.data.update({ - "path": path, - "outputDir": os.path.dirname(path), - "ext": ext, # todo: should be redundant? - - "families": ["render", "review"], - "family": "render", - - # Backwards compatibility: embed tool in instance.data - "tool": tool - }) - - # Add tool itself as member - instance.append(tool) + # Add tool itself as member + instance.append(tool) diff --git a/openpype/hosts/fusion/plugins/publish/render_local.py b/openpype/hosts/fusion/plugins/publish/render_local.py index 53d8eb64e15..30943edd4b0 100644 --- a/openpype/hosts/fusion/plugins/publish/render_local.py +++ b/openpype/hosts/fusion/plugins/publish/render_local.py @@ -53,10 +53,8 @@ def process(self, instance): instance.data["representations"].append(repre) # review representation - repre_preview = repre.copy() - repre_preview["name"] = repre_preview["ext"] = "mp4" - repre_preview["tags"] = ["review", "ftrackreview", "delete"] - instance.data["representations"].append(repre_preview) + if instance.data.get("review", False): + repre["tags"] = ["review", "ftrackreview"] def render_once(self, context): """Render context comp only once, even with more render instances""" From c43a8b073296cb95ba1700faf5e32cb9f7c31fa4 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 7 Mar 2023 16:06:44 +0100 Subject: [PATCH 331/898] Collect comp frame range later in publishing - Otherwise it gets overridden by global plugin `CollectContextEntities` --- .../fusion/plugins/publish/collect_comp.py | 25 ----------- .../publish/collect_comp_frame_range.py | 41 +++++++++++++++++++ 2 files changed, 41 insertions(+), 25 deletions(-) create mode 100644 openpype/hosts/fusion/plugins/publish/collect_comp_frame_range.py diff --git a/openpype/hosts/fusion/plugins/publish/collect_comp.py b/openpype/hosts/fusion/plugins/publish/collect_comp.py index 911071c9a04..d26bf66d1f4 100644 --- a/openpype/hosts/fusion/plugins/publish/collect_comp.py +++ b/openpype/hosts/fusion/plugins/publish/collect_comp.py @@ -3,24 +3,6 @@ from openpype.hosts.fusion.api import get_current_comp -def get_comp_render_range(comp): - """Return comp's start-end render range and global start-end range.""" - comp_attrs = comp.GetAttrs() - start = comp_attrs["COMPN_RenderStart"] - end = comp_attrs["COMPN_RenderEnd"] - global_start = comp_attrs["COMPN_GlobalStart"] - global_end = comp_attrs["COMPN_GlobalEnd"] - - # Whenever render ranges are undefined fall back - # to the comp's global start and end - if start == -1000000000: - start = global_start - if end == -1000000000: - end = global_end - - return start, end, global_start, global_end - - class CollectCurrentCompFusion(pyblish.api.ContextPlugin): """Collect current comp""" @@ -38,10 +20,3 @@ def process(self, context): # Store path to current file filepath = comp.GetAttrs().get("COMPS_FileName", "") context.data['currentFile'] = filepath - - # Store comp render ranges - start, end, global_start, global_end = get_comp_render_range(comp) - context.data["frameStart"] = int(start) - context.data["frameEnd"] = int(end) - context.data["frameStartHandle"] = int(global_start) - context.data["frameEndHandle"] = int(global_end) diff --git a/openpype/hosts/fusion/plugins/publish/collect_comp_frame_range.py b/openpype/hosts/fusion/plugins/publish/collect_comp_frame_range.py new file mode 100644 index 00000000000..dc88dd79c6c --- /dev/null +++ b/openpype/hosts/fusion/plugins/publish/collect_comp_frame_range.py @@ -0,0 +1,41 @@ +import pyblish.api + +from openpype.hosts.fusion.api import get_current_comp + + +def get_comp_render_range(comp): + """Return comp's start-end render range and global start-end range.""" + comp_attrs = comp.GetAttrs() + start = comp_attrs["COMPN_RenderStart"] + end = comp_attrs["COMPN_RenderEnd"] + global_start = comp_attrs["COMPN_GlobalStart"] + global_end = comp_attrs["COMPN_GlobalEnd"] + + # Whenever render ranges are undefined fall back + # to the comp's global start and end + if start == -1000000000: + start = global_start + if end == -1000000000: + end = global_end + + return start, end, global_start, global_end + + +class CollectFusionCompFrameRanges(pyblish.api.ContextPlugin): + """Collect current comp""" + + order = pyblish.api.CollectorOrder - 0.05 + label = "Collect Comp Frame Ranges" + hosts = ["fusion"] + + def process(self, context): + """Collect all image sequence tools""" + + comp = context.data["currentComp"] + + # Store comp render ranges + start, end, global_start, global_end = get_comp_render_range(comp) + context.data["frameStart"] = int(start) + context.data["frameEnd"] = int(end) + context.data["frameStartHandle"] = int(global_start) + context.data["frameEndHandle"] = int(global_end) From f6b8a8df61af591427e1192ecf7ce416db338db6 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 7 Mar 2023 16:07:54 +0100 Subject: [PATCH 332/898] Revert redundant variable name change since plugin is now basically reverted --- openpype/hosts/fusion/plugins/publish/collect_comp.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/collect_comp.py b/openpype/hosts/fusion/plugins/publish/collect_comp.py index d26bf66d1f4..d1c49790fab 100644 --- a/openpype/hosts/fusion/plugins/publish/collect_comp.py +++ b/openpype/hosts/fusion/plugins/publish/collect_comp.py @@ -13,10 +13,10 @@ class CollectCurrentCompFusion(pyblish.api.ContextPlugin): def process(self, context): """Collect all image sequence tools""" - comp = get_current_comp() - assert comp, "Must have active Fusion composition" - context.data["currentComp"] = comp + current_comp = get_current_comp() + assert current_comp, "Must have active Fusion composition" + context.data["currentComp"] = current_comp # Store path to current file - filepath = comp.GetAttrs().get("COMPS_FileName", "") + filepath = current_comp.GetAttrs().get("COMPS_FileName", "") context.data['currentFile'] = filepath From 146f5cd439652d454b656163f00b1521bf5ee227 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 7 Mar 2023 16:09:36 +0100 Subject: [PATCH 333/898] Add descriptive comment --- .../hosts/fusion/plugins/publish/collect_comp_frame_range.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openpype/hosts/fusion/plugins/publish/collect_comp_frame_range.py b/openpype/hosts/fusion/plugins/publish/collect_comp_frame_range.py index dc88dd79c6c..98128e1ccf7 100644 --- a/openpype/hosts/fusion/plugins/publish/collect_comp_frame_range.py +++ b/openpype/hosts/fusion/plugins/publish/collect_comp_frame_range.py @@ -24,6 +24,8 @@ def get_comp_render_range(comp): class CollectFusionCompFrameRanges(pyblish.api.ContextPlugin): """Collect current comp""" + # We run this after CollectorOrder - 0.1 otherwise it gets + # overridden by global plug-in `CollectContextEntities` order = pyblish.api.CollectorOrder - 0.05 label = "Collect Comp Frame Ranges" hosts = ["fusion"] From 43d084cf7f5a7f277a44c50bab623f31a74a8975 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 7 Mar 2023 16:09:55 +0100 Subject: [PATCH 334/898] Remove unused import --- .../hosts/fusion/plugins/publish/collect_comp_frame_range.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/collect_comp_frame_range.py b/openpype/hosts/fusion/plugins/publish/collect_comp_frame_range.py index 98128e1ccf7..c6d7a73a049 100644 --- a/openpype/hosts/fusion/plugins/publish/collect_comp_frame_range.py +++ b/openpype/hosts/fusion/plugins/publish/collect_comp_frame_range.py @@ -1,7 +1,5 @@ import pyblish.api -from openpype.hosts.fusion.api import get_current_comp - def get_comp_render_range(comp): """Return comp's start-end render range and global start-end range.""" From 1b18483f7b480665922847ceb556375d49026d35 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Tue, 7 Mar 2023 16:41:35 +0100 Subject: [PATCH 335/898] use right type for signal emit (#4584) --- openpype/tools/attribute_defs/widgets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/tools/attribute_defs/widgets.py b/openpype/tools/attribute_defs/widgets.py index 18e2e13d067..0d4e1e88a9d 100644 --- a/openpype/tools/attribute_defs/widgets.py +++ b/openpype/tools/attribute_defs/widgets.py @@ -186,7 +186,7 @@ def current_value(self): class _BaseAttrDefWidget(QtWidgets.QWidget): # Type 'object' may not work with older PySide versions - value_changed = QtCore.Signal(object, uuid.UUID) + value_changed = QtCore.Signal(object, str) def __init__(self, attr_def, parent): super(_BaseAttrDefWidget, self).__init__(parent) From 70163a2f255413fbe706101b261dac3c3e65e2a8 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 7 Mar 2023 17:26:09 +0100 Subject: [PATCH 336/898] Added Create button to menu and set tab data for create and publish btn --- openpype/hosts/fusion/api/menu.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/fusion/api/menu.py b/openpype/hosts/fusion/api/menu.py index 568e03464d9..e37380017ed 100644 --- a/openpype/hosts/fusion/api/menu.py +++ b/openpype/hosts/fusion/api/menu.py @@ -7,11 +7,11 @@ from openpype.lib import register_event_callback from openpype.hosts.fusion.scripts import ( set_rendermode, - duplicate_with_inputs + duplicate_with_inputs, ) from openpype.hosts.fusion.api.lib import ( set_asset_framerange, - set_asset_resolution + set_asset_resolution, ) from openpype.pipeline import legacy_io from openpype.resources import get_openpype_icon_filepath @@ -45,14 +45,17 @@ def __init__(self, *args, **kwargs): self.setWindowTitle("OpenPype") asset_label = QtWidgets.QLabel("Context", self) - asset_label.setStyleSheet("""QLabel { + asset_label.setStyleSheet( + """QLabel { font-size: 14px; font-weight: 600; color: #5f9fb8; - }""") + }""" + ) asset_label.setAlignment(QtCore.Qt.AlignHCenter) workfiles_btn = QtWidgets.QPushButton("Workfiles...", self) + create_btn = QtWidgets.QPushButton("Create...", self) publish_btn = QtWidgets.QPushButton("Publish...", self) load_btn = QtWidgets.QPushButton("Load...", self) manager_btn = QtWidgets.QPushButton("Manage...", self) @@ -76,6 +79,7 @@ def __init__(self, *args, **kwargs): layout.addSpacing(20) layout.addWidget(load_btn) + layout.addWidget(create_btn) layout.addWidget(publish_btn) layout.addWidget(manager_btn) @@ -99,13 +103,15 @@ def __init__(self, *args, **kwargs): self.asset_label = asset_label workfiles_btn.clicked.connect(self.on_workfile_clicked) + create_btn.clicked.connect(self.on_create_clicked) publish_btn.clicked.connect(self.on_publish_clicked) load_btn.clicked.connect(self.on_load_clicked) manager_btn.clicked.connect(self.on_manager_clicked) libload_btn.clicked.connect(self.on_libload_clicked) rendermode_btn.clicked.connect(self.on_rendermode_clicked) duplicate_with_inputs_btn.clicked.connect( - self.on_duplicate_with_inputs_clicked) + self.on_duplicate_with_inputs_clicked + ) set_resolution_btn.clicked.connect(self.on_set_resolution_clicked) set_framerange_btn.clicked.connect(self.on_set_framerange_clicked) @@ -127,7 +133,6 @@ def on_task_changed(self): self.asset_label.setText(label) def register_callback(self, name, fn): - # Create a wrapper callback that we only store # for as long as we want it to persist as callback def _callback(*args): @@ -142,8 +147,11 @@ def deregister_all_callbacks(self): def on_workfile_clicked(self): host_tools.show_workfiles() + def on_create_clicked(self): + host_tools.show_publisher(tab="create") + def on_publish_clicked(self): - host_tools.show_publisher() + host_tools.show_publisher(tab="publish") def on_load_clicked(self): host_tools.show_loader(use_context=True) From b1fac42e94a668e9b072dc5f64edca865d06afcd Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 7 Mar 2023 17:26:31 +0100 Subject: [PATCH 337/898] updating pr tempate --- .github/pull_request_template.md | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 20ae298f707..2adaffd23db 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,16 +1,9 @@ -## Brief description -First sentence is brief description. - -## Description -Next paragraf is more elaborate text with more info. This will be displayed for example in collapsed form under the first sentence in a changelog. +## Changelog Description +Paragraphs contain detailed information on the changes made to the product or service, providing an in-depth description of the updates and enhancements. They can be used to explain the reasoning behind the changes, or to highlight the importance of the new features. Paragraphs can often include links to further information or support documentation. ## Additional info -The rest will be ignored in changelog and should contain any additional -technical information. - -## Documentation (add _"type: documentation"_ label) -[feature_documentation](future_url_after_it_will_be_merged) +Paragraphs of text giving context of additional technical information or code examples. ## Testing notes: 1. start with this step -2. follow this step \ No newline at end of file +2. follow this step From 9c9c134a794a5ab9bd36a415ef15d2b2b64dbdd8 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 7 Mar 2023 17:39:05 +0100 Subject: [PATCH 338/898] Use passthrough state of saver tool to store and load the active state --- openpype/hosts/fusion/plugins/create/create_saver.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/openpype/hosts/fusion/plugins/create/create_saver.py b/openpype/hosts/fusion/plugins/create/create_saver.py index bf11dc95c59..e581bac20ff 100644 --- a/openpype/hosts/fusion/plugins/create/create_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_saver.py @@ -109,6 +109,12 @@ def remove_instances(self, instances): def _imprint(self, tool, data): # Save all data in a "openpype.{key}" = value data + + active = data.pop("active", None) + if active is not None: + # Use active value to set the passthrough state + tool.SetAttrs({"TOOLB_PassThrough": not active}) + for key, value in data.items(): tool.SetData(f"openpype.{key}", value) @@ -192,6 +198,11 @@ def get_managed_tool_data(self, tool): if key not in data or data[key] != value: return + # Get active state from the actual tool state + attrs = tool.GetAttrs() + passthrough = attrs["TOOLB_PassThrough"] + data["active"] = not passthrough + return data def get_instance_attr_defs(self): From 5c8bbe28713aaabbabf99b4739f1654a0bea4b71 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 7 Mar 2023 17:41:03 +0100 Subject: [PATCH 339/898] Remove pyblish callback which does nothing in new publisher --- openpype/hosts/fusion/api/pipeline.py | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/openpype/hosts/fusion/api/pipeline.py b/openpype/hosts/fusion/api/pipeline.py index b982e1c2e91..a768a3f0f88 100644 --- a/openpype/hosts/fusion/api/pipeline.py +++ b/openpype/hosts/fusion/api/pipeline.py @@ -102,9 +102,6 @@ def install(self): register_creator_plugin_path(CREATE_PATH) register_inventory_action_path(INVENTORY_PATH) - pyblish.api.register_callback( - "instanceToggled", on_pyblish_instance_toggled) - # Register events register_event_callback("open", on_after_open) register_event_callback("save", on_save) @@ -163,29 +160,6 @@ def get_context_data(self): return comp.GetData("openpype") or {} -def on_pyblish_instance_toggled(instance, old_value, new_value): - """Toggle saver tool passthrough states on instance toggles.""" - comp = instance.context.data.get("currentComp") - if not comp: - return - - savers = [tool for tool in instance if - getattr(tool, "ID", None) == "Saver"] - if not savers: - return - - # Whether instances should be passthrough based on new value - passthrough = not new_value - with comp_lock_and_undo_chunk(comp, - undo_queue_name="Change instance " - "active state"): - for tool in savers: - attrs = tool.GetAttrs() - current = attrs["TOOLB_PassThrough"] - if current != passthrough: - tool.SetAttrs({"TOOLB_PassThrough": passthrough}) - - def on_new(event): comp = event["Rets"]["comp"] validate_comp_prefs(comp, force_repair=True) From 0f037666f83226e9ec832a58a49ee848683b9b04 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 7 Mar 2023 17:49:31 +0100 Subject: [PATCH 340/898] Change menu order to how it was originally and match with e.g. maya menu order --- openpype/hosts/fusion/api/menu.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/api/menu.py b/openpype/hosts/fusion/api/menu.py index e37380017ed..343f5f803ad 100644 --- a/openpype/hosts/fusion/api/menu.py +++ b/openpype/hosts/fusion/api/menu.py @@ -56,8 +56,8 @@ def __init__(self, *args, **kwargs): workfiles_btn = QtWidgets.QPushButton("Workfiles...", self) create_btn = QtWidgets.QPushButton("Create...", self) - publish_btn = QtWidgets.QPushButton("Publish...", self) load_btn = QtWidgets.QPushButton("Load...", self) + publish_btn = QtWidgets.QPushButton("Publish...", self) manager_btn = QtWidgets.QPushButton("Manage...", self) libload_btn = QtWidgets.QPushButton("Library...", self) rendermode_btn = QtWidgets.QPushButton("Set render mode...", self) @@ -78,8 +78,8 @@ def __init__(self, *args, **kwargs): layout.addSpacing(20) - layout.addWidget(load_btn) layout.addWidget(create_btn) + layout.addWidget(load_btn) layout.addWidget(publish_btn) layout.addWidget(manager_btn) From acbfb5985b52516ac99d45bd6b5e7f8121d89b6c Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Mon, 6 Mar 2023 14:50:00 +0100 Subject: [PATCH 341/898] Fixed task itteration From the last PR (https://github.com/ynput/OpenPype/pull/4425) a comment-commit last second messed up and resultet in two lines being the same, crashing the script. This fixes that. --- .../modules/kitsu/utils/update_op_with_zou.py | 55 ++++++++++++------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index 053e803ff3b..4fa8cf9fdd1 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -95,7 +95,8 @@ def update_op_assets( op_asset = create_op_asset(item) insert_result = dbcon.insert_one(op_asset) item_doc = get_asset_by_id( - project_name, insert_result.inserted_id) + project_name, insert_result.inserted_id + ) # Update asset item_data = deepcopy(item_doc["data"]) @@ -133,39 +134,47 @@ def update_op_assets( try: fps = float(item_data.get("fps")) except (TypeError, ValueError): - fps = float(gazu_project.get( - "fps", project_doc["data"].get("fps", 25))) + fps = float( + gazu_project.get("fps", project_doc["data"].get("fps", 25)) + ) item_data["fps"] = fps # Resolution, fall back to project default match_res = re.match( r"(\d+)x(\d+)", - item_data.get("resolution", gazu_project.get("resolution")) + item_data.get("resolution", gazu_project.get("resolution")), ) if match_res: item_data["resolutionWidth"] = int(match_res.group(1)) item_data["resolutionHeight"] = int(match_res.group(2)) else: item_data["resolutionWidth"] = project_doc["data"].get( - "resolutionWidth") + "resolutionWidth" + ) item_data["resolutionHeight"] = project_doc["data"].get( - "resolutionHeight") + "resolutionHeight" + ) # Properties that doesn't fully exist in Kitsu. # Guessing those property names below: # Pixel Aspect Ratio item_data["pixelAspect"] = item_data.get( - "pixel_aspect", project_doc["data"].get("pixelAspect")) + "pixel_aspect", project_doc["data"].get("pixelAspect") + ) # Handle Start item_data["handleStart"] = item_data.get( - "handle_start", project_doc["data"].get("handleStart")) + "handle_start", project_doc["data"].get("handleStart") + ) # Handle End item_data["handleEnd"] = item_data.get( - "handle_end", project_doc["data"].get("handleEnd")) + "handle_end", project_doc["data"].get("handleEnd") + ) # Clip In item_data["clipIn"] = item_data.get( - "clip_in", project_doc["data"].get("clipIn")) + "clip_in", project_doc["data"].get("clipIn") + ) # Clip Out item_data["clipOut"] = item_data.get( - "clip_out", project_doc["data"].get("clipOut")) + "clip_out", project_doc["data"].get("clipOut") + ) # Tasks tasks_list = [] @@ -175,11 +184,9 @@ def update_op_assets( elif item_type == "Shot": tasks_list = gazu.task.all_tasks_for_shot(item) item_data["tasks"] = { - item_data["tasks"] = { - t["task_type_name"]: { - "type": t["task_type_name"], - "zou": gazu.task.get_task(t["id"]), - } + t["task_type_name"]: { + "type": t["task_type_name"], + "zou": gazu.task.get_task(t["id"]), } for t in tasks_list } @@ -218,7 +225,9 @@ def update_op_assets( if parent_zou_id_dict is not None: visual_parent_doc_id = ( parent_zou_id_dict.get("_id") - if parent_zou_id_dict else None) + if parent_zou_id_dict + else None + ) if visual_parent_doc_id is None: # Find root folder doc ("Assets" or "Shots") @@ -345,7 +354,8 @@ def write_project_to_op(project: dict, dbcon: AvalonMongoDB) -> UpdateOne: def sync_all_projects( - login: str, password: str, ignore_projects: list = None): + login: str, password: str, ignore_projects: list = None +): """Update all OP projects in DB with Zou data. Args: @@ -390,7 +400,7 @@ def sync_project_from_kitsu(dbcon: AvalonMongoDB, project: dict): if not project: project = gazu.project.get_project_by_name(project["name"]) - log.info("Synchronizing {}...".format(project['name'])) + log.info("Synchronizing {}...".format(project["name"])) # Get all assets from zou all_assets = gazu.asset.all_assets_for_project(project) @@ -473,8 +483,11 @@ def sync_project_from_kitsu(dbcon: AvalonMongoDB, project: dict): [ UpdateOne({"_id": id}, update) for id, update in update_op_assets( - dbcon, project, project_dict, - all_entities, zou_ids_and_asset_docs + dbcon, + project, + project_dict, + all_entities, + zou_ids_and_asset_docs, ) ] ) From 40125fa6a5518b7ca202a892a3f4196913058600 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 7 Mar 2023 10:17:44 +0100 Subject: [PATCH 342/898] Avoid error in PySide6+ --- openpype/widgets/popup.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/openpype/widgets/popup.py b/openpype/widgets/popup.py index 97a84610602..28bbd450722 100644 --- a/openpype/widgets/popup.py +++ b/openpype/widgets/popup.py @@ -98,15 +98,22 @@ def calculate_window_geometry(self): height = window.height() height = max(height, window.sizeHint().height()) - desktop_geometry = QtWidgets.QDesktopWidget().availableGeometry() - screen_geometry = window.geometry() + try: + screen = QtWidgets.QApplication.primaryScreen() + desktop_geometry = screen.availableGeometry() + except AttributeError: + # Backwards compatibility for older Qt versions + # PySide6 removed QDesktopWidget + desktop_geometry = QtWidgets.QDesktopWidget().availableGeometry() - screen_width = screen_geometry.width() - screen_height = screen_geometry.height() + window_geometry = window.geometry() + + screen_width = window_geometry.width() + screen_height = window_geometry.height() # Calculate width and height of system tray - systray_width = screen_geometry.width() - desktop_geometry.width() - systray_height = screen_geometry.height() - desktop_geometry.height() + systray_width = window_geometry.width() - desktop_geometry.width() + systray_height = window_geometry.height() - desktop_geometry.height() padding = 10 From 300a4435101e8ae6608ef4024f002606f9f867d5 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 7 Mar 2023 11:08:10 +0100 Subject: [PATCH 343/898] Use screen of window instead of primary screen Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- openpype/widgets/popup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/widgets/popup.py b/openpype/widgets/popup.py index 28bbd450722..225c5e18a17 100644 --- a/openpype/widgets/popup.py +++ b/openpype/widgets/popup.py @@ -99,7 +99,7 @@ def calculate_window_geometry(self): height = max(height, window.sizeHint().height()) try: - screen = QtWidgets.QApplication.primaryScreen() + screen = window.screen() desktop_geometry = screen.availableGeometry() except AttributeError: # Backwards compatibility for older Qt versions From ecfea3dee2be05318ec9cfb88802f357fdb2c0e9 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 7 Mar 2023 20:42:49 +0100 Subject: [PATCH 344/898] Explicitly set the `handleStart` and `handleEnd` otherwise other global plug-ins will force in other data like asset data. --- .../hosts/fusion/plugins/publish/collect_comp_frame_range.py | 2 ++ openpype/hosts/fusion/plugins/publish/collect_instances.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/openpype/hosts/fusion/plugins/publish/collect_comp_frame_range.py b/openpype/hosts/fusion/plugins/publish/collect_comp_frame_range.py index c6d7a73a049..fbd7606cd76 100644 --- a/openpype/hosts/fusion/plugins/publish/collect_comp_frame_range.py +++ b/openpype/hosts/fusion/plugins/publish/collect_comp_frame_range.py @@ -39,3 +39,5 @@ def process(self, context): context.data["frameEnd"] = int(end) context.data["frameStartHandle"] = int(global_start) context.data["frameEndHandle"] = int(global_end) + context.data["handleStart"] = int(start) - int(global_start) + context.data["handleEnd"] = int(global_end) - int(end) diff --git a/openpype/hosts/fusion/plugins/publish/collect_instances.py b/openpype/hosts/fusion/plugins/publish/collect_instances.py index 1e6d095cc23..af227f03db2 100644 --- a/openpype/hosts/fusion/plugins/publish/collect_instances.py +++ b/openpype/hosts/fusion/plugins/publish/collect_instances.py @@ -39,6 +39,8 @@ def process(self, instance): "frameEnd": context.data["frameEnd"], "frameStartHandle": context.data["frameStartHandle"], "frameEndHandle": context.data["frameStartHandle"], + "handleStart": context.data["handleStart"], + "handleEnd": context.data["handleEnd"], "fps": context.data["fps"], }) From 962984d29614a7ba7d86f391ba61013a871947f9 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Wed, 8 Mar 2023 02:04:54 +0300 Subject: [PATCH 345/898] add separate fusion profile hook --- openpype/hosts/fusion/__init__.py | 2 + openpype/hosts/fusion/addon.py | 9 ++ .../fusion/hooks/pre_fusion_profile_hook.py | 109 ++++++++++++++++++ .../hosts/fusion/hooks/pre_fusion_setup.py | 105 +---------------- 4 files changed, 125 insertions(+), 100 deletions(-) create mode 100644 openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py diff --git a/openpype/hosts/fusion/__init__.py b/openpype/hosts/fusion/__init__.py index ddae01890b2..baaaa9d6fc8 100644 --- a/openpype/hosts/fusion/__init__.py +++ b/openpype/hosts/fusion/__init__.py @@ -1,10 +1,12 @@ from .addon import ( FusionAddon, FUSION_HOST_DIR, + FUSION_PROFILE_VERSION ) __all__ = ( "FusionAddon", "FUSION_HOST_DIR", + "FUSION_PROFILE_VERSION" ) diff --git a/openpype/hosts/fusion/addon.py b/openpype/hosts/fusion/addon.py index d1bd1566b7e..777c38629ad 100644 --- a/openpype/hosts/fusion/addon.py +++ b/openpype/hosts/fusion/addon.py @@ -3,6 +3,15 @@ FUSION_HOST_DIR = os.path.dirname(os.path.abspath(__file__)) +FUSION_PROFILE_VERSION = 16 + +# FUSION_PROFILE_VERSION variable is used by the pre-launch hooks. +# Since Fusion v16, the profile folder became project-specific, +# but then it was abandoned by BlackmagicDesign devs, and now, despite it is +# already Fusion version 18, still FUSION16_PROFILE_DIR is used. +# The variable is added in case the version number will be +# updated or deleted so we could easily change the version or disable it. + class FusionAddon(OpenPypeModule, IHostAddon): name = "fusion" diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py new file mode 100644 index 00000000000..4af67c1c0d2 --- /dev/null +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -0,0 +1,109 @@ +import os +import shutil +import platform +from pathlib import Path +from openpype.lib import PreLaunchHook, ApplicationLaunchFailed +from openpype.hosts.fusion import FUSION_PROFILE_VERSION as VERSION + + +class FusionCopyPrefsPrelaunch(PreLaunchHook): + """Prepares local Fusion profile directory, copies existing Fusion profile + """ + + app_groups = ["fusion"] + + def get_fusion_profile_name(self) -> str: + """usually set to 'Default', unless FUSION16_PROFILE is set""" + return os.getenv(f"FUSION{VERSION}_PROFILE", "Default") + + def get_profile_source(self) -> Path: + """Get the Fusion preferences (profile) location. + Check Per-User_Preferences_and_Paths on VFXpedia for reference. + """ + fusion_profile = self.get_fusion_profile_name() + fusion_var_prefs_dir = os.getenv(f"FUSION{VERSION}_PROFILE_DIR") + + # if FUSION16_PROFILE_DIR variable exists + if fusion_var_prefs_dir and Path(fusion_var_prefs_dir).is_dir(): + fusion_prefs_dir = Path(fusion_var_prefs_dir, fusion_profile) + self.log.info( + f"Local Fusion prefs environment is set to {fusion_prefs_dir}" + ) + return fusion_prefs_dir + # otherwise get the profile folder from default location + fusion_prefs_dir = f"Blackmagic Design/Fusion/Profiles/{fusion_profile}" # noqa + if platform.system() == "Windows": + prefs_source = Path(os.getenv("AppData"), fusion_prefs_dir) + elif platform.system() == "Darwin": + prefs_source = Path( + "~/Library/Application Support/", fusion_prefs_dir + ).expanduser() + elif platform.system() == "Linux": + prefs_source = Path("~/.fusion", fusion_prefs_dir).expanduser() + self.log.info(f"Got Fusion prefs file: {prefs_source}") + return prefs_source + + def get_copy_fusion_prefs_settings(self): + """Get copy preferences options from the global application settings""" + copy_fusion_settings = self.data["project_settings"]["fusion"].get( + "copy_fusion_settings", {} + ) + if not copy_fusion_settings: + self.log.error("Copy prefs settings not found") + copy_status = copy_fusion_settings.get("copy_status", False) + force_sync = copy_fusion_settings.get("force_sync", False) + copy_path = copy_fusion_settings.get("copy_path") or None + if copy_path: + copy_path = Path(copy_path).expanduser() + return copy_status, copy_path, force_sync + + def copy_existing_prefs( + self, copy_from: Path, copy_to: Path, force_sync: bool + ) -> None: + """On the first Fusion launch copy the contents of Fusion profile + directory to the working predefined location. If the Openpype profile + folder exists, skip copying, unless re-sync is checked. + If the prefs were not copied on the first launch, + clean Fusion profile will be created in fusion_profile_dir. + """ + if copy_to.exists() and not force_sync: + self.log.info( + "Local Fusion preferences folder exists, skipping profile copy" + ) + return + self.log.info(f"Starting copying Fusion preferences") + self.log.info(f"force_sync option is set to {force_sync}") + dest_folder = copy_to / self.get_fusion_profile_name() + try: + dest_folder.mkdir(exist_ok=True, parents=True) + except Exception: + self.log.warn(f"Could not create folder at {dest_folder}") + return + if not copy_from.exists(): + self.log.warning(f"Fusion preferences not found in {copy_from}") + return + for file in copy_from.iterdir(): + if file.suffix in (".prefs", ".def", ".blocklist", ".fu"): + # convert Path to str to be compatible with Python 3.6+ + shutil.copy(str(file), str(dest_folder)) + self.log.info( + f"successfully copied preferences:\n {copy_from} to {dest_folder}" + ) + + def execute(self): + ( + copy_status, + fusion_profile_dir, + force_sync, + ) = self.get_copy_fusion_prefs_settings() + + # do a copy of Fusion profile if copy_status toggle is enabled + if copy_status and fusion_profile_dir is not None: + prefs_source = self.get_profile_source() + self.copy_existing_prefs(prefs_source, fusion_profile_dir, force_sync) # noqa + + # Add temporary profile directory variables to customize Fusion + # to define where it can read custom scripts and tools from + fusion_profile_dir_variable = f"FUSION{VERSION}_PROFILE_DIR" + self.log.info(f"Setting {fusion_profile_dir_variable}: {fusion_profile_dir}") # noqa + self.launch_context.env[fusion_profile_dir_variable] = str(fusion_profile_dir) # noqa \ No newline at end of file diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index 129aadf1a57..bce221d3579 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -4,6 +4,7 @@ from pathlib import Path from openpype.lib import PreLaunchHook, ApplicationLaunchFailed from openpype.hosts.fusion import FUSION_HOST_DIR +from openpype.hosts.fusion import FUSION_PROFILE_VERSION as VERSION class FusionPrelaunch(PreLaunchHook): @@ -16,94 +17,9 @@ class FusionPrelaunch(PreLaunchHook): This also sets FUSION16_MasterPrefs to apply the fusion master prefs as set in openpype/hosts/fusion/deploy/fusion_shared.prefs to enable the OpenPype menu and force Python 3 over Python 2. - - VERSION variable is used because from the Fusion v16 the profile folder - is project-specific, but then it was abandoned by devs, - and despite it is already Fusion version 18, still FUSION16_PROFILE_DIR - is used. The variable is added in case the version number will be - updated or deleted so we could easily change the version or disable it. """ app_groups = ["fusion"] - VERSION = 16 - - def get_fusion_profile_name(self) -> str: - """usually set to 'Default', unless FUSION16_PROFILE is set""" - return os.getenv(f"FUSION{self.VERSION}_PROFILE", "Default") - - def get_profile_source(self) -> Path: - """Get the Fusion preferences (profile) location. - Check Per-User_Preferences_and_Paths on VFXpedia for reference. - """ - fusion_profile = self.get_fusion_profile_name() - fusion_var_prefs_dir = os.getenv(f"FUSION{self.VERSION}_PROFILE_DIR") - - # if FUSION16_PROFILE_DIR variable exists - if fusion_var_prefs_dir and Path(fusion_var_prefs_dir).is_dir(): - fusion_prefs_dir = Path(fusion_var_prefs_dir, fusion_profile) - self.log.info( - f"Local Fusion prefs environment is set to {fusion_prefs_dir}" - ) - return fusion_prefs_dir - # otherwise get the profile folder from default location - fusion_prefs_dir = f"Blackmagic Design/Fusion/Profiles/{fusion_profile}" # noqa - if platform.system() == "Windows": - prefs_source = Path(os.getenv("AppData"), fusion_prefs_dir) - elif platform.system() == "Darwin": - prefs_source = Path( - "~/Library/Application Support/", fusion_prefs_dir - ).expanduser() - elif platform.system() == "Linux": - prefs_source = Path("~/.fusion", fusion_prefs_dir).expanduser() - self.log.info(f"Got Fusion prefs file: {prefs_source}") - return prefs_source - - def get_copy_fusion_prefs_settings(self): - """Get copy preferences options from the global application settings""" - copy_fusion_settings = self.data["project_settings"]["fusion"].get( - "copy_fusion_settings", {} - ) - if not copy_fusion_settings: - self.log.error("Copy prefs settings not found") - copy_status = copy_fusion_settings.get("copy_status", False) - force_sync = copy_fusion_settings.get("force_sync", False) - copy_path = copy_fusion_settings.get("copy_path") or None - if copy_path: - copy_path = Path(copy_path).expanduser() - return copy_status, copy_path, force_sync - - def copy_existing_prefs( - self, copy_from: Path, copy_to: Path, force_sync: bool - ) -> None: - """On the first Fusion launch copy the contents of Fusion profile - directory to the working predefined location. If the Openpype profile - folder exists, skip copying, unless re-sync is checked. - If the prefs were not copied on the first launch, - clean Fusion profile will be created in fusion_profile_dir. - """ - if copy_to.exists() and not force_sync: - self.log.info( - "Local Fusion preferences folder exists, skipping profile copy" - ) - return - self.log.info(f"Starting copying Fusion preferences") - self.log.info(f"force_sync option is set to {force_sync}") - dest_folder = copy_to / self.get_fusion_profile_name() - try: - dest_folder.mkdir(exist_ok=True, parents=True) - except Exception: - self.log.warn(f"Could not create folder at {dest_folder}") - return - if not copy_from.exists(): - self.log.warning(f"Fusion preferences not found in {copy_from}") - return - for file in copy_from.iterdir(): - if file.suffix in (".prefs", ".def", ".blocklist", ".fu"): - # convert Path to str to be compatible with Python 3.6+ - shutil.copy(str(file), str(dest_folder)) - self.log.info( - f"successfully copied preferences:\n {copy_from} to {dest_folder}" - ) def execute(self): # making sure python 3 is installed at provided path @@ -138,26 +54,15 @@ def execute(self): # Fusion 16 and 17 use FUSION16_PYTHON36_HOME instead of # FUSION_PYTHON3_HOME and will only work with a Python 3.6 version # TODO: Detect Fusion version to only set for specific Fusion build - self.launch_context.env[f"FUSION{self.VERSION}_PYTHON36_HOME"] = py3_dir # noqa + self.launch_context.env[f"FUSION{VERSION}_PYTHON36_HOME"] = py3_dir # noqa # Add custom Fusion Master Prefs and the temporary # profile directory variables to customize Fusion # to define where it can read custom scripts and tools from self.log.info(f"Setting OPENPYPE_FUSION: {FUSION_HOST_DIR}") self.launch_context.env["OPENPYPE_FUSION"] = FUSION_HOST_DIR - ( - copy_status, - fusion_profile_dir, - force_sync, - ) = self.get_copy_fusion_prefs_settings() - if copy_status and fusion_profile_dir is not None: - prefs_source = self.get_profile_source() - self.copy_existing_prefs(prefs_source, fusion_profile_dir, force_sync) # noqa - else: - fusion_profile_dir_variable = f"FUSION{self.VERSION}_PROFILE_DIR" - self.log.info(f"Setting {fusion_profile_dir_variable}: {fusion_profile_dir}") # noqa - self.launch_context.env[fusion_profile_dir_variable] = str(fusion_profile_dir) # noqa - master_prefs_variable = f"FUSION{self.VERSION}_MasterPrefs" + + master_prefs_variable = f"FUSION{VERSION}_MasterPrefs" master_prefs = Path(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") self.log.info(f"Setting {master_prefs_variable}: {master_prefs}") - self.launch_context.env[master_prefs_variable] = str(master_prefs) + self.launch_context.env[master_prefs_variable] = str(master_prefs) \ No newline at end of file From e1950a175fbb1a58a1ffeea9ad7620e1a2d05d02 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Wed, 8 Mar 2023 02:11:57 +0300 Subject: [PATCH 346/898] hound comments --- openpype/hosts/fusion/addon.py | 2 +- openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py | 4 ++-- openpype/hosts/fusion/hooks/pre_fusion_setup.py | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/fusion/addon.py b/openpype/hosts/fusion/addon.py index 777c38629ad..6621f88056a 100644 --- a/openpype/hosts/fusion/addon.py +++ b/openpype/hosts/fusion/addon.py @@ -5,7 +5,7 @@ FUSION_PROFILE_VERSION = 16 -# FUSION_PROFILE_VERSION variable is used by the pre-launch hooks. +# FUSION_PROFILE_VERSION variable is used by the pre-launch hooks. # Since Fusion v16, the profile folder became project-specific, # but then it was abandoned by BlackmagicDesign devs, and now, despite it is # already Fusion version 18, still FUSION16_PROFILE_DIR is used. diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py index 4af67c1c0d2..b91c699cc30 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -2,7 +2,7 @@ import shutil import platform from pathlib import Path -from openpype.lib import PreLaunchHook, ApplicationLaunchFailed +from openpype.lib import PreLaunchHook from openpype.hosts.fusion import FUSION_PROFILE_VERSION as VERSION @@ -11,7 +11,7 @@ class FusionCopyPrefsPrelaunch(PreLaunchHook): """ app_groups = ["fusion"] - + def get_fusion_profile_name(self) -> str: """usually set to 'Default', unless FUSION16_PROFILE is set""" return os.getenv(f"FUSION{VERSION}_PROFILE", "Default") diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index bce221d3579..e62c2d7ab76 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -1,6 +1,4 @@ import os -import shutil -import platform from pathlib import Path from openpype.lib import PreLaunchHook, ApplicationLaunchFailed from openpype.hosts.fusion import FUSION_HOST_DIR From 39e694374626544f7dce258c86c5ac2809a0cf19 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Wed, 8 Mar 2023 02:35:00 +0300 Subject: [PATCH 347/898] hound comments --- openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py | 3 ++- openpype/hosts/fusion/hooks/pre_fusion_setup.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py index b91c699cc30..e3a00a3e669 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -106,4 +106,5 @@ def execute(self): # to define where it can read custom scripts and tools from fusion_profile_dir_variable = f"FUSION{VERSION}_PROFILE_DIR" self.log.info(f"Setting {fusion_profile_dir_variable}: {fusion_profile_dir}") # noqa - self.launch_context.env[fusion_profile_dir_variable] = str(fusion_profile_dir) # noqa \ No newline at end of file + self.launch_context.env[fusion_profile_dir_variable] = str(fusion_profile_dir) # noqa + \ No newline at end of file diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index e62c2d7ab76..ccad28401d0 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -63,4 +63,5 @@ def execute(self): master_prefs_variable = f"FUSION{VERSION}_MasterPrefs" master_prefs = Path(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") self.log.info(f"Setting {master_prefs_variable}: {master_prefs}") - self.launch_context.env[master_prefs_variable] = str(master_prefs) \ No newline at end of file + self.launch_context.env[master_prefs_variable] = str(master_prefs) + \ No newline at end of file From a5e0e057db3aa1de71da3d24f75c6833c5219aa0 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Wed, 8 Mar 2023 02:37:59 +0300 Subject: [PATCH 348/898] good boy --- openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py | 1 - openpype/hosts/fusion/hooks/pre_fusion_setup.py | 1 - 2 files changed, 2 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py index e3a00a3e669..71728092524 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -107,4 +107,3 @@ def execute(self): fusion_profile_dir_variable = f"FUSION{VERSION}_PROFILE_DIR" self.log.info(f"Setting {fusion_profile_dir_variable}: {fusion_profile_dir}") # noqa self.launch_context.env[fusion_profile_dir_variable] = str(fusion_profile_dir) # noqa - \ No newline at end of file diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index ccad28401d0..c39b9cd150b 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -64,4 +64,3 @@ def execute(self): master_prefs = Path(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") self.log.info(f"Setting {master_prefs_variable}: {master_prefs}") self.launch_context.env[master_prefs_variable] = str(master_prefs) - \ No newline at end of file From 5088edfdade4bcb8d096ef45502ba0cf235fb6a5 Mon Sep 17 00:00:00 2001 From: Ynbot Date: Wed, 8 Mar 2023 03:30:35 +0000 Subject: [PATCH 349/898] [Automated] Bump version --- openpype/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/version.py b/openpype/version.py index 2939ddbbacd..c7a5e9bea57 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.15.2-nightly.4" +__version__ = "3.15.2-nightly.5" From fb0f39b3ccff52ac2df9e2dfe0cbb743bfb3ac92 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov <11698866+movalex@users.noreply.github.com> Date: Wed, 8 Mar 2023 12:38:23 +0300 Subject: [PATCH 350/898] add up to 3 decimals precision to the frame rate settings (#4571) * add up to 3 decimals to fps allows input 23.976 to the FPS settings both in Project Manager and the Project Anatomy. * set fps and pixel aspect precision steps default values --- .../schemas/schema_anatomy_attributes.json | 2 +- .../project_manager/project_manager/delegates.py | 5 ++++- .../tools/project_manager/project_manager/view.py | 14 ++++++++++---- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json index 3667c9d5d85..a7280243761 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json @@ -10,7 +10,7 @@ "type": "number", "key": "fps", "label": "Frame Rate", - "decimal": 2, + "decimal": 3, "minimum": 0 }, { diff --git a/openpype/tools/project_manager/project_manager/delegates.py b/openpype/tools/project_manager/project_manager/delegates.py index 79e9554b0f6..023dd668ecc 100644 --- a/openpype/tools/project_manager/project_manager/delegates.py +++ b/openpype/tools/project_manager/project_manager/delegates.py @@ -83,15 +83,18 @@ class NumberDelegate(QtWidgets.QStyledItemDelegate): decimals(int): How many decimal points can be used. Float will be used as value if is higher than 0. """ - def __init__(self, minimum, maximum, decimals, *args, **kwargs): + def __init__(self, minimum, maximum, decimals, step, *args, **kwargs): super(NumberDelegate, self).__init__(*args, **kwargs) self.minimum = minimum self.maximum = maximum self.decimals = decimals + self.step = step def createEditor(self, parent, option, index): if self.decimals > 0: editor = DoubleSpinBoxScrollFixed(parent) + editor.setSingleStep(self.step) + editor.setDecimals(self.decimals) else: editor = SpinBoxScrollFixed(parent) diff --git a/openpype/tools/project_manager/project_manager/view.py b/openpype/tools/project_manager/project_manager/view.py index fa08943ea53..b35491c5b21 100644 --- a/openpype/tools/project_manager/project_manager/view.py +++ b/openpype/tools/project_manager/project_manager/view.py @@ -26,10 +26,11 @@ class NameDef: class NumberDef: - def __init__(self, minimum=None, maximum=None, decimals=None): + def __init__(self, minimum=None, maximum=None, decimals=None, step=None): self.minimum = 0 if minimum is None else minimum self.maximum = 999999999 if maximum is None else maximum self.decimals = 0 if decimals is None else decimals + self.step = 1 if decimals is None else step class TypeDef: @@ -73,14 +74,14 @@ class HierarchyView(QtWidgets.QTreeView): "type": TypeDef(), "frameStart": NumberDef(1), "frameEnd": NumberDef(1), - "fps": NumberDef(1, decimals=2), + "fps": NumberDef(1, decimals=3, step=1), "resolutionWidth": NumberDef(0), "resolutionHeight": NumberDef(0), "handleStart": NumberDef(0), "handleEnd": NumberDef(0), "clipIn": NumberDef(1), "clipOut": NumberDef(1), - "pixelAspect": NumberDef(0, decimals=2), + "pixelAspect": NumberDef(0, decimals=2, step=0.01), "tools_env": ToolsDef() } @@ -96,6 +97,10 @@ class HierarchyView(QtWidgets.QTreeView): "stretch": QtWidgets.QHeaderView.Interactive, "width": 140 }, + "fps": { + "stretch": QtWidgets.QHeaderView.Interactive, + "width": 65 + }, "tools_env": { "stretch": QtWidgets.QHeaderView.Interactive, "width": 200 @@ -148,7 +153,8 @@ def __init__(self, dbcon, source_model, parent): delegate = NumberDelegate( item_type.minimum, item_type.maximum, - item_type.decimals + item_type.decimals, + item_type.step ) elif isinstance(item_type, TypeDef): From 0f45af2d36f5a29f550d412c0d346154d0f855c6 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 6 Mar 2023 15:10:37 +0100 Subject: [PATCH 351/898] use 'get_representations' instead of 'legacy_io' query --- .../hosts/unreal/plugins/load/load_layout.py | 50 ++++++++++++------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/openpype/hosts/unreal/plugins/load/load_layout.py b/openpype/hosts/unreal/plugins/load/load_layout.py index c1d66ddf2a8..18653e81cb4 100644 --- a/openpype/hosts/unreal/plugins/load/load_layout.py +++ b/openpype/hosts/unreal/plugins/load/load_layout.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- """Loader for layouts.""" import json +import collections from pathlib import Path import unreal @@ -12,9 +13,7 @@ from unreal import MovieSceneLevelVisibilityTrack from unreal import MovieSceneSubTrack -from bson.objectid import ObjectId - -from openpype.client import get_asset_by_name, get_assets +from openpype.client import get_asset_by_name, get_assets, get_representations from openpype.pipeline import ( discover_loader_plugins, loaders_from_representation, @@ -410,6 +409,29 @@ def _generate_sequence(h, h_dir): return sequence, (min_frame, max_frame) + def _get_repre_docs_by_version_id(self, project_name, data): + version_ids = { + element.get("version") + for element in data + if element.get("representation") + } + version_ids.discard(None) + + output = collections.defaultdict(list) + if not version_ids: + return output + + repre_docs = get_representations( + project_name, + representation_names=["fbx", "abc"], + version_ids=version_ids, + fields=["_id", "parent", "name"] + ) + for repre_doc in repre_docs: + version_id = str(repre_doc["parent"]) + output[version_id].append(repre_doc) + return output + def _process(self, lib_path, asset_dir, sequence, repr_loaded=None): ar = unreal.AssetRegistryHelpers.get_asset_registry() @@ -429,31 +451,21 @@ def _process(self, lib_path, asset_dir, sequence, repr_loaded=None): loaded_assets = [] + repre_docs_by_version_id = self._get_repre_docs_by_version_id(data) for element in data: representation = None repr_format = None if element.get('representation'): - # representation = element.get('representation') - - self.log.info(element.get("version")) - - valid_formats = ['fbx', 'abc'] - - repr_data = legacy_io.find_one({ - "type": "representation", - "parent": ObjectId(element.get("version")), - "name": {"$in": valid_formats} - }) - repr_format = repr_data.get('name') - - if not repr_data: + repre_docs = repre_docs_by_version_id[element.get("version")] + if not repre_docs: self.log.error( f"No valid representation found for version " f"{element.get('version')}") continue + repre_doc = repre_docs[0] + representation = str(repre_doc["_id"]) + repr_format = repre_doc["name"] - representation = str(repr_data.get('_id')) - print(representation) # This is to keep compatibility with old versions of the # json format. elif element.get('reference_fbx'): From 47b1daf0f5ef0cf11b89026c8b342b18782e1956 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 8 Mar 2023 11:21:38 +0100 Subject: [PATCH 352/898] get project name other way --- openpype/hosts/unreal/plugins/load/load_layout.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/unreal/plugins/load/load_layout.py b/openpype/hosts/unreal/plugins/load/load_layout.py index 18653e81cb4..63d415a52b6 100644 --- a/openpype/hosts/unreal/plugins/load/load_layout.py +++ b/openpype/hosts/unreal/plugins/load/load_layout.py @@ -409,7 +409,7 @@ def _generate_sequence(h, h_dir): return sequence, (min_frame, max_frame) - def _get_repre_docs_by_version_id(self, project_name, data): + def _get_repre_docs_by_version_id(self, data): version_ids = { element.get("version") for element in data @@ -421,6 +421,7 @@ def _get_repre_docs_by_version_id(self, project_name, data): if not version_ids: return output + project_name = legacy_io.active_project() repre_docs = get_representations( project_name, representation_names=["fbx", "abc"], From 6e34c4aed26e20bc8b1af0fc0e368060cf684d20 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 9 Mar 2023 16:13:32 +0100 Subject: [PATCH 353/898] Make sure value-data is int or float --- .../modules/kitsu/utils/update_op_with_zou.py | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index 4fa8cf9fdd1..a2b560b75b5 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -128,8 +128,8 @@ def update_op_assets( if frames_duration: frame_out = frame_in + frames_duration - 1 else: - frame_out = project_doc["data"].get("frameEnd", frame_in) - item_data["frameEnd"] = frame_out + frame_out = int(project_doc["data"].get("frameEnd", frame_in)) + item_data["frameEnd"] = int(frame_out) # Fps, fallback to project's value or default value (25.0) try: fps = float(item_data.get("fps")) @@ -147,33 +147,37 @@ def update_op_assets( item_data["resolutionWidth"] = int(match_res.group(1)) item_data["resolutionHeight"] = int(match_res.group(2)) else: - item_data["resolutionWidth"] = project_doc["data"].get( - "resolutionWidth" + item_data["resolutionWidth"] = int( + project_doc["data"].get("resolutionWidth") ) - item_data["resolutionHeight"] = project_doc["data"].get( - "resolutionHeight" + item_data["resolutionHeight"] = int( + project_doc["data"].get("resolutionHeight") ) # Properties that doesn't fully exist in Kitsu. # Guessing those property names below: # Pixel Aspect Ratio - item_data["pixelAspect"] = item_data.get( - "pixel_aspect", project_doc["data"].get("pixelAspect") + item_data["pixelAspect"] = float( + item_data.get( + "pixel_aspect", project_doc["data"].get("pixelAspect") + ) ) # Handle Start - item_data["handleStart"] = item_data.get( - "handle_start", project_doc["data"].get("handleStart") + item_data["handleStart"] = int( + item_data.get( + "handle_start", project_doc["data"].get("handleStart") + ) ) # Handle End - item_data["handleEnd"] = item_data.get( - "handle_end", project_doc["data"].get("handleEnd") + item_data["handleEnd"] = int( + item_data.get("handle_end", project_doc["data"].get("handleEnd")) ) # Clip In - item_data["clipIn"] = item_data.get( - "clip_in", project_doc["data"].get("clipIn") + item_data["clipIn"] = int( + item_data.get("clip_in", project_doc["data"].get("clipIn")) ) # Clip Out - item_data["clipOut"] = item_data.get( - "clip_out", project_doc["data"].get("clipOut") + item_data["clipOut"] = int( + item_data.get("clip_out", project_doc["data"].get("clipOut")) ) # Tasks From 10da5885cd8611354f0c903622a33124dcda4ac4 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 9 Mar 2023 21:13:42 +0100 Subject: [PATCH 354/898] Get the settings up and running --- .../defaults/project_settings/kitsu.json | 6 ++++- .../projects_schema/schema_project_kitsu.json | 26 ++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/openpype/settings/defaults/project_settings/kitsu.json b/openpype/settings/defaults/project_settings/kitsu.json index 95b3da04ae0..280895f1b98 100644 --- a/openpype/settings/defaults/project_settings/kitsu.json +++ b/openpype/settings/defaults/project_settings/kitsu.json @@ -8,6 +8,10 @@ "IntegrateKitsuNote": { "set_status_note": false, "note_status_shortname": "wfa" + }, + "CustomCommentTemplate": { + "enabled": false, + "comment_template": "{comment}\n\n| | |\n|--|--|\n| version| `{version}` |\n| family | `{family}` |\n| name | `{name}` |" } } -} +} \ No newline at end of file diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index fb47670e74a..255190c3962 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -54,8 +54,32 @@ "label": "Note shortname" } ] + }, + { + "type": "dict", + "collapsible": true, + "checkbox_key": "enabled", + "key": "CustomCommentTemplate", + "label": "Custom Comment Template", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "label", + "label": "Kitsu supports markdown and here you can create a custom comment template.
You can use data from your instance's anatomy." + }, + { + "key": "comment_template", + "type": "text", + "multiline": true, + "label": "Custom comment" + } + ] } ] } ] -} +} \ No newline at end of file From b7ac37701bfc24c69bde5e5fd7a853766d4cc87d Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Thu, 9 Mar 2023 23:57:12 +0300 Subject: [PATCH 355/898] WIP get fusion host version (the wrong way) --- openpype/hosts/fusion/__init__.py | 4 +- openpype/hosts/fusion/addon.py | 33 +++++-- .../fusion/hooks/pre_fusion_profile_hook.py | 91 +++++++++++-------- .../hosts/fusion/hooks/pre_fusion_setup.py | 9 +- 4 files changed, 87 insertions(+), 50 deletions(-) diff --git a/openpype/hosts/fusion/__init__.py b/openpype/hosts/fusion/__init__.py index baaaa9d6fc8..f0e7843fffd 100644 --- a/openpype/hosts/fusion/__init__.py +++ b/openpype/hosts/fusion/__init__.py @@ -1,12 +1,12 @@ from .addon import ( + get_fusion_profile_number, FusionAddon, FUSION_HOST_DIR, - FUSION_PROFILE_VERSION ) __all__ = ( + "get_fusion_profile_number", "FusionAddon", "FUSION_HOST_DIR", - "FUSION_PROFILE_VERSION" ) diff --git a/openpype/hosts/fusion/addon.py b/openpype/hosts/fusion/addon.py index 6621f88056a..4b0ce59aaf2 100644 --- a/openpype/hosts/fusion/addon.py +++ b/openpype/hosts/fusion/addon.py @@ -1,16 +1,35 @@ import os +import re from openpype.modules import OpenPypeModule, IHostAddon +from openpype.lib import Logger FUSION_HOST_DIR = os.path.dirname(os.path.abspath(__file__)) -FUSION_PROFILE_VERSION = 16 -# FUSION_PROFILE_VERSION variable is used by the pre-launch hooks. -# Since Fusion v16, the profile folder became project-specific, -# but then it was abandoned by BlackmagicDesign devs, and now, despite it is -# already Fusion version 18, still FUSION16_PROFILE_DIR is used. -# The variable is added in case the version number will be -# updated or deleted so we could easily change the version or disable it. +def get_fusion_profile_number(module: str, app_data: str) -> int: + """ + FUSION_PROFILE_VERSION variable is used by the pre-launch hooks. + Since Fusion v16, the profile folder variable became version-specific, + but then it was abandoned by BlackmagicDesign devs, and now, despite it is + already Fusion version 18, still FUSION16_PROFILE_DIR is used. + The variable is added in case the version number will be + updated or deleted so we could easily change the version or disable it. + """ + + log = Logger.get_logger(__name__) + + if not app_data: + return + fusion16_profile_versions = ("16", "17", "18") + try: + app_version = re.search(r"fusion/(\d+)", app_data).group(1) + log.info(f"{module} found Fusion profile version: {app_version}") + if app_version in fusion16_profile_versions: + return 16 + elif app_version == "9": + return 9 + except AttributeError: + log.info("Fusion version was not found in the app data") class FusionAddon(OpenPypeModule, IHostAddon): diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py index 71728092524..356292c85b2 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -2,8 +2,9 @@ import shutil import platform from pathlib import Path +from pprint import pprint from openpype.lib import PreLaunchHook -from openpype.hosts.fusion import FUSION_PROFILE_VERSION as VERSION +from openpype.hosts.fusion import get_fusion_profile_number class FusionCopyPrefsPrelaunch(PreLaunchHook): @@ -11,40 +12,49 @@ class FusionCopyPrefsPrelaunch(PreLaunchHook): """ app_groups = ["fusion"] + order = 2 + + def get_fusion_profile_name(self, app_version) -> str: + # Returns 'Default', unless FUSION16_PROFILE is set + return os.getenv(f"FUSION{app_version}_PROFILE", "Default") - def get_fusion_profile_name(self) -> str: - """usually set to 'Default', unless FUSION16_PROFILE is set""" - return os.getenv(f"FUSION{VERSION}_PROFILE", "Default") + def check_profile_variable(self, app_version) -> Path: + # Get FUSION_PROFILE_DIR variable + fusion_profile = self.get_fusion_profile_name(app_version) + fusion_var_prefs_dir = os.getenv(f"FUSION{app_version}_PROFILE_DIR") - def get_profile_source(self) -> Path: - """Get the Fusion preferences (profile) location. - Check Per-User_Preferences_and_Paths on VFXpedia for reference. - """ - fusion_profile = self.get_fusion_profile_name() - fusion_var_prefs_dir = os.getenv(f"FUSION{VERSION}_PROFILE_DIR") - - # if FUSION16_PROFILE_DIR variable exists + # Check if FUSION_PROFILE_DIR exists if fusion_var_prefs_dir and Path(fusion_var_prefs_dir).is_dir(): - fusion_prefs_dir = Path(fusion_var_prefs_dir, fusion_profile) + fu_prefs_dir = Path(fusion_var_prefs_dir, fusion_profile) self.log.info( - f"Local Fusion prefs environment is set to {fusion_prefs_dir}" + f"{fusion_var_prefs_dir} is set to {fu_prefs_dir}" ) - return fusion_prefs_dir - # otherwise get the profile folder from default location - fusion_prefs_dir = f"Blackmagic Design/Fusion/Profiles/{fusion_profile}" # noqa + return fu_prefs_dir + + def get_profile_source(self, app_version) -> Path: + """Get Fusion preferences profile location. + See Per-User_Preferences_and_Paths on VFXpedia for reference. + """ + fusion_profile = self.get_fusion_profile_name(app_version) + profile_source = self.check_profile_variable(app_version) + if profile_source: + return profile_source + # otherwise get default location of the profile folder + fu_prefs_dir = f"Blackmagic Design/Fusion/Profiles/{fusion_profile}" if platform.system() == "Windows": - prefs_source = Path(os.getenv("AppData"), fusion_prefs_dir) + profile_source = Path(os.getenv("AppData"), fu_prefs_dir) elif platform.system() == "Darwin": - prefs_source = Path( - "~/Library/Application Support/", fusion_prefs_dir + profile_source = Path( + "~/Library/Application Support/", fu_prefs_dir ).expanduser() elif platform.system() == "Linux": - prefs_source = Path("~/.fusion", fusion_prefs_dir).expanduser() - self.log.info(f"Got Fusion prefs file: {prefs_source}") - return prefs_source + profile_source = Path("~/.fusion", fu_prefs_dir).expanduser() + self.log.info(f"Got Fusion prefs file: {profile_source}") + return profile_source def get_copy_fusion_prefs_settings(self): - """Get copy preferences options from the global application settings""" + # Get copy preferences options from the global application settings + copy_fusion_settings = self.data["project_settings"]["fusion"].get( "copy_fusion_settings", {} ) @@ -57,14 +67,14 @@ def get_copy_fusion_prefs_settings(self): copy_path = Path(copy_path).expanduser() return copy_status, copy_path, force_sync - def copy_existing_prefs( + def copy_fusion_profile( self, copy_from: Path, copy_to: Path, force_sync: bool ) -> None: """On the first Fusion launch copy the contents of Fusion profile directory to the working predefined location. If the Openpype profile folder exists, skip copying, unless re-sync is checked. If the prefs were not copied on the first launch, - clean Fusion profile will be created in fusion_profile_dir. + clean Fusion profile will be created in fu_profile_dir. """ if copy_to.exists() and not force_sync: self.log.info( @@ -73,11 +83,10 @@ def copy_existing_prefs( return self.log.info(f"Starting copying Fusion preferences") self.log.info(f"force_sync option is set to {force_sync}") - dest_folder = copy_to / self.get_fusion_profile_name() try: - dest_folder.mkdir(exist_ok=True, parents=True) + copy_to.mkdir(exist_ok=True, parents=True) except Exception: - self.log.warn(f"Could not create folder at {dest_folder}") + self.log.warn(f"Could not create folder at {copy_to}") return if not copy_from.exists(): self.log.warning(f"Fusion preferences not found in {copy_from}") @@ -85,25 +94,31 @@ def copy_existing_prefs( for file in copy_from.iterdir(): if file.suffix in (".prefs", ".def", ".blocklist", ".fu"): # convert Path to str to be compatible with Python 3.6+ - shutil.copy(str(file), str(dest_folder)) + shutil.copy(str(file), str(copy_to)) self.log.info( - f"successfully copied preferences:\n {copy_from} to {dest_folder}" + f"successfully copied preferences:\n {copy_from} to {copy_to}" ) def execute(self): ( copy_status, - fusion_profile_dir, + fu_profile_dir, force_sync, ) = self.get_copy_fusion_prefs_settings() + # Get launched application context and return correct app version + app_data = self.launch_context.env.get("AVALON_APP_NAME", "fusion/18") + app_version = get_fusion_profile_number(__name__, app_data) + fu_profile = self.get_fusion_profile_name(app_version) + # do a copy of Fusion profile if copy_status toggle is enabled - if copy_status and fusion_profile_dir is not None: - prefs_source = self.get_profile_source() - self.copy_existing_prefs(prefs_source, fusion_profile_dir, force_sync) # noqa + if copy_status and fu_profile_dir is not None: + profile_source = self.get_profile_source(app_version) + dest_folder = Path(fu_profile_dir, fu_profile) + self.copy_fusion_profile(profile_source, dest_folder, force_sync) # Add temporary profile directory variables to customize Fusion # to define where it can read custom scripts and tools from - fusion_profile_dir_variable = f"FUSION{VERSION}_PROFILE_DIR" - self.log.info(f"Setting {fusion_profile_dir_variable}: {fusion_profile_dir}") # noqa - self.launch_context.env[fusion_profile_dir_variable] = str(fusion_profile_dir) # noqa + fu_profile_dir_variable = f"FUSION{app_version}_PROFILE_DIR" + self.log.info(f"Setting {fu_profile_dir_variable}: {fu_profile_dir}") + self.launch_context.env[fu_profile_dir_variable] = str(fu_profile_dir) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index c39b9cd150b..7139252d2fb 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -2,7 +2,7 @@ from pathlib import Path from openpype.lib import PreLaunchHook, ApplicationLaunchFailed from openpype.hosts.fusion import FUSION_HOST_DIR -from openpype.hosts.fusion import FUSION_PROFILE_VERSION as VERSION +from openpype.hosts.fusion import get_fusion_profile_number class FusionPrelaunch(PreLaunchHook): @@ -18,10 +18,13 @@ class FusionPrelaunch(PreLaunchHook): """ app_groups = ["fusion"] + order = 1 def execute(self): # making sure python 3 is installed at provided path # Py 3.3-3.10 for Fusion 18+ or Py 3.6 for Fu 16-17 + app_data = self.launch_context.env.get("AVALON_APP_NAME", "fusion/18") + app_version = get_fusion_profile_number(__name__, app_data) py3_var = "FUSION_PYTHON3_HOME" fusion_python3_home = self.launch_context.env.get(py3_var, "") @@ -52,7 +55,7 @@ def execute(self): # Fusion 16 and 17 use FUSION16_PYTHON36_HOME instead of # FUSION_PYTHON3_HOME and will only work with a Python 3.6 version # TODO: Detect Fusion version to only set for specific Fusion build - self.launch_context.env[f"FUSION{VERSION}_PYTHON36_HOME"] = py3_dir # noqa + self.launch_context.env[f"FUSION{app_version}_PYTHON36_HOME"] = py3_dir # Add custom Fusion Master Prefs and the temporary # profile directory variables to customize Fusion @@ -60,7 +63,7 @@ def execute(self): self.log.info(f"Setting OPENPYPE_FUSION: {FUSION_HOST_DIR}") self.launch_context.env["OPENPYPE_FUSION"] = FUSION_HOST_DIR - master_prefs_variable = f"FUSION{VERSION}_MasterPrefs" + master_prefs_variable = f"FUSION{app_version}_MasterPrefs" master_prefs = Path(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") self.log.info(f"Setting {master_prefs_variable}: {master_prefs}") self.launch_context.env[master_prefs_variable] = str(master_prefs) From d01114595645868da87baf337f8a8e84dabc682b Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Fri, 10 Mar 2023 00:02:26 +0300 Subject: [PATCH 356/898] hound --- .../hosts/fusion/hooks/pre_fusion_profile_hook.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py index 356292c85b2..4369935b49e 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -2,7 +2,6 @@ import shutil import platform from pathlib import Path -from pprint import pprint from openpype.lib import PreLaunchHook from openpype.hosts.fusion import get_fusion_profile_number @@ -13,7 +12,7 @@ class FusionCopyPrefsPrelaunch(PreLaunchHook): app_groups = ["fusion"] order = 2 - + def get_fusion_profile_name(self, app_version) -> str: # Returns 'Default', unless FUSION16_PROFILE is set return os.getenv(f"FUSION{app_version}_PROFILE", "Default") @@ -39,8 +38,8 @@ def get_profile_source(self, app_version) -> Path: profile_source = self.check_profile_variable(app_version) if profile_source: return profile_source - # otherwise get default location of the profile folder - fu_prefs_dir = f"Blackmagic Design/Fusion/Profiles/{fusion_profile}" + # otherwise get default location of the profile folder + fu_prefs_dir = f"Blackmagic Design/Fusion/Profiles/{fusion_profile}" if platform.system() == "Windows": profile_source = Path(os.getenv("AppData"), fu_prefs_dir) elif platform.system() == "Darwin": @@ -110,12 +109,12 @@ def execute(self): app_data = self.launch_context.env.get("AVALON_APP_NAME", "fusion/18") app_version = get_fusion_profile_number(__name__, app_data) fu_profile = self.get_fusion_profile_name(app_version) - + # do a copy of Fusion profile if copy_status toggle is enabled if copy_status and fu_profile_dir is not None: profile_source = self.get_profile_source(app_version) dest_folder = Path(fu_profile_dir, fu_profile) - self.copy_fusion_profile(profile_source, dest_folder, force_sync) + self.copy_fusion_profile(profile_source, dest_folder, force_sync) # Add temporary profile directory variables to customize Fusion # to define where it can read custom scripts and tools from From a04f44dcf9e97ef3fd7d8a028c8334d15ffd850d Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Fri, 10 Mar 2023 00:26:05 +0300 Subject: [PATCH 357/898] use FUSION_PYTHON36_HOME for Fusion 9 --- openpype/hosts/fusion/hooks/pre_fusion_setup.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index 7139252d2fb..4c73a0eee37 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -55,15 +55,13 @@ def execute(self): # Fusion 16 and 17 use FUSION16_PYTHON36_HOME instead of # FUSION_PYTHON3_HOME and will only work with a Python 3.6 version # TODO: Detect Fusion version to only set for specific Fusion build - self.launch_context.env[f"FUSION{app_version}_PYTHON36_HOME"] = py3_dir + if app_version == 9: + self.launch_context.env[f"FUSION_PYTHON36_HOME"] = py3_dir + elif app_version == 16: + self.launch_context.env[f"FUSION{app_version}_PYTHON36_HOME"] = py3_dir # Add custom Fusion Master Prefs and the temporary # profile directory variables to customize Fusion # to define where it can read custom scripts and tools from self.log.info(f"Setting OPENPYPE_FUSION: {FUSION_HOST_DIR}") self.launch_context.env["OPENPYPE_FUSION"] = FUSION_HOST_DIR - - master_prefs_variable = f"FUSION{app_version}_MasterPrefs" - master_prefs = Path(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") - self.log.info(f"Setting {master_prefs_variable}: {master_prefs}") - self.launch_context.env[master_prefs_variable] = str(master_prefs) From d586231aa11ec76fbde4c9357369d2ed0ffa40c5 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Fri, 10 Mar 2023 00:28:41 +0300 Subject: [PATCH 358/898] move masterprefs setup to the correct hook --- openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py index 4369935b49e..543e90cc751 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -3,7 +3,7 @@ import platform from pathlib import Path from openpype.lib import PreLaunchHook -from openpype.hosts.fusion import get_fusion_profile_number +from openpype.hosts.fusion import FUSION_HOST_DIR, get_fusion_profile_number class FusionCopyPrefsPrelaunch(PreLaunchHook): @@ -121,3 +121,8 @@ def execute(self): fu_profile_dir_variable = f"FUSION{app_version}_PROFILE_DIR" self.log.info(f"Setting {fu_profile_dir_variable}: {fu_profile_dir}") self.launch_context.env[fu_profile_dir_variable] = str(fu_profile_dir) + + master_prefs_variable = f"FUSION{app_version}_MasterPrefs" + master_prefs = Path(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") + self.log.info(f"Setting {master_prefs_variable}: {master_prefs}") + self.launch_context.env[master_prefs_variable] = str(master_prefs) From 71e8af5a22007678257412ab2052b2034727729d Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Fri, 10 Mar 2023 00:29:49 +0300 Subject: [PATCH 359/898] noqa line --- openpype/hosts/fusion/hooks/pre_fusion_setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index 4c73a0eee37..e30d241096f 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -58,7 +58,7 @@ def execute(self): if app_version == 9: self.launch_context.env[f"FUSION_PYTHON36_HOME"] = py3_dir elif app_version == 16: - self.launch_context.env[f"FUSION{app_version}_PYTHON36_HOME"] = py3_dir + self.launch_context.env[f"FUSION{app_version}_PYTHON36_HOME"] = py3_dir # noqa # Add custom Fusion Master Prefs and the temporary # profile directory variables to customize Fusion From 8a00c8ae33a910c40eee4bfcacad352119d3975d Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Fri, 10 Mar 2023 00:31:47 +0300 Subject: [PATCH 360/898] remove unused import --- openpype/hosts/fusion/hooks/pre_fusion_setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index e30d241096f..38627b40c12 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -1,5 +1,4 @@ import os -from pathlib import Path from openpype.lib import PreLaunchHook, ApplicationLaunchFailed from openpype.hosts.fusion import FUSION_HOST_DIR from openpype.hosts.fusion import get_fusion_profile_number From c58778194f31b37235b201d9f0132cf97909aa77 Mon Sep 17 00:00:00 2001 From: Joseff Date: Wed, 8 Mar 2023 16:30:30 +0100 Subject: [PATCH 361/898] Implementation of a new splash screen --- .../unreal/hooks/pre_workfile_preparation.py | 90 ++++- .../OpenPype/Private/AssetContainer.cpp | 6 +- openpype/hosts/unreal/lib.py | 22 +- openpype/hosts/unreal/ue_workers.py | 338 ++++++++++++++++++ openpype/widgets/README.md | 102 ++++++ openpype/widgets/splash_screen.py | 253 +++++++++++++ 6 files changed, 793 insertions(+), 18 deletions(-) create mode 100644 openpype/hosts/unreal/ue_workers.py create mode 100644 openpype/widgets/README.md create mode 100644 openpype/widgets/splash_screen.py diff --git a/openpype/hosts/unreal/hooks/pre_workfile_preparation.py b/openpype/hosts/unreal/hooks/pre_workfile_preparation.py index 4c9f8258f56..8ede80f7fde 100644 --- a/openpype/hosts/unreal/hooks/pre_workfile_preparation.py +++ b/openpype/hosts/unreal/hooks/pre_workfile_preparation.py @@ -3,7 +3,11 @@ import os import copy from pathlib import Path +from openpype.widgets.splash_screen import SplashScreen +from qtpy import QtCore +from openpype.hosts.unreal.ue_workers import UEProjectGenerationWorker, UEPluginInstallWorker +from openpype import resources from openpype.lib import ( PreLaunchHook, ApplicationLaunchFailed, @@ -22,6 +26,7 @@ class UnrealPrelaunchHook(PreLaunchHook): shell script. """ + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -58,6 +63,70 @@ def _get_work_filename(self): # Return filename return filled_anatomy[workfile_template_key]["file"] + def exec_plugin_install(self, engine_path: Path, env: dict = None): + # set up the QThread and worker with necessary signals + env = env or os.environ + q_thread = QtCore.QThread() + ue_plugin_worker = UEPluginInstallWorker() + + q_thread.started.connect(ue_plugin_worker.run) + ue_plugin_worker.setup(engine_path, env) + ue_plugin_worker.moveToThread(q_thread) + + splash_screen = SplashScreen("Installing plugin", + resources.get_resource("app_icons", "ue4.png")) + + # set up the splash screen with necessary triggers + ue_plugin_worker.installing.connect(splash_screen.update_top_label_text) + ue_plugin_worker.progress.connect(splash_screen.update_progress) + ue_plugin_worker.log.connect(splash_screen.append_log) + ue_plugin_worker.finished.connect(splash_screen.quit_and_close) + ue_plugin_worker.failed.connect(splash_screen.fail) + + splash_screen.start_thread(q_thread) + splash_screen.show_ui() + + if not splash_screen.was_proc_successful(): + raise ApplicationLaunchFailed("Couldn't run the application! " + "Plugin failed to install!") + + def exec_ue_project_gen(self, + engine_version: str, + unreal_project_name: str, + engine_path: Path, + project_dir: Path): + self.log.info(( + f"{self.signature} Creating unreal " + f"project [ {unreal_project_name} ]" + )) + + q_thread = QtCore.QThread() + ue_project_worker = UEProjectGenerationWorker() + ue_project_worker.setup( + engine_version, + unreal_project_name, + engine_path, + project_dir + ) + ue_project_worker.moveToThread(q_thread) + q_thread.started.connect(ue_project_worker.run) + + splash_screen = SplashScreen("Initializing UE project", + resources.get_resource("app_icons", "ue4.png")) + + ue_project_worker.stage_begin.connect(splash_screen.update_top_label_text) + ue_project_worker.progress.connect(splash_screen.update_progress) + ue_project_worker.log.connect(splash_screen.append_log) + ue_project_worker.finished.connect(splash_screen.quit_and_close) + ue_project_worker.failed.connect(splash_screen.fail) + + splash_screen.start_thread(q_thread) + splash_screen.show_ui() + + if not splash_screen.was_proc_successful(): + raise ApplicationLaunchFailed("Couldn't run the application! " + "Failed to generate the project!") + def execute(self): """Hook entry method.""" workdir = self.launch_context.env["AVALON_WORKDIR"] @@ -137,23 +206,18 @@ def execute(self): if self.launch_context.env.get(env_key): os.environ[env_key] = self.launch_context.env[env_key] - engine_path = detected[engine_version] + engine_path: Path = Path(detected[engine_version]) - unreal_lib.try_installing_plugin(Path(engine_path), os.environ) + if not unreal_lib.check_plugin_existence(engine_path): + self.exec_plugin_install(engine_path) project_file = project_path / unreal_project_filename - if not project_file.is_file(): - self.log.info(( - f"{self.signature} creating unreal " - f"project [ {unreal_project_name} ]" - )) - unreal_lib.create_unreal_project( - unreal_project_name, - engine_version, - project_path, - engine_path=Path(engine_path) - ) + if not project_file.is_file(): + self.exec_ue_project_gen(engine_version, + unreal_project_name, + engine_path, + project_path) self.launch_context.env["OPENPYPE_UNREAL_VERSION"] = engine_version # Append project file to launch arguments diff --git a/openpype/hosts/unreal/integration/UE_5.0/OpenPype/Source/OpenPype/Private/AssetContainer.cpp b/openpype/hosts/unreal/integration/UE_5.0/OpenPype/Source/OpenPype/Private/AssetContainer.cpp index 0bea9e3d787..06dcd678087 100644 --- a/openpype/hosts/unreal/integration/UE_5.0/OpenPype/Source/OpenPype/Private/AssetContainer.cpp +++ b/openpype/hosts/unreal/integration/UE_5.0/OpenPype/Source/OpenPype/Private/AssetContainer.cpp @@ -30,7 +30,7 @@ void UAssetContainer::OnAssetAdded(const FAssetData& AssetData) // get asset path and class FString assetPath = AssetData.GetFullName(); - FString assetFName = AssetData.AssetClassPath.ToString(); + FString assetFName = AssetData.ObjectPath.ToString(); UE_LOG(LogTemp, Log, TEXT("asset name %s"), *assetFName); // split path assetPath.ParseIntoArray(split, TEXT(" "), true); @@ -60,7 +60,7 @@ void UAssetContainer::OnAssetRemoved(const FAssetData& AssetData) // get asset path and class FString assetPath = AssetData.GetFullName(); - FString assetFName = AssetData.AssetClassPath.ToString(); + FString assetFName = AssetData.ObjectPath.ToString(); // split path assetPath.ParseIntoArray(split, TEXT(" "), true); @@ -93,7 +93,7 @@ void UAssetContainer::OnAssetRenamed(const FAssetData& AssetData, const FString& // get asset path and class FString assetPath = AssetData.GetFullName(); - FString assetFName = AssetData.AssetClassPath.ToString(); + FString assetFName = AssetData.ObjectPath.ToString(); // split path assetPath.ParseIntoArray(split, TEXT(" "), true); diff --git a/openpype/hosts/unreal/lib.py b/openpype/hosts/unreal/lib.py index 28a51060428..08cc57a6cdf 100644 --- a/openpype/hosts/unreal/lib.py +++ b/openpype/hosts/unreal/lib.py @@ -365,6 +365,26 @@ def _get_build_id(engine_path: Path, ue_version: str) -> str: return "{" + loaded_modules.get("BuildId") + "}" +def check_plugin_existence(engine_path: Path, env: dict = None) -> bool: + env = env or os.environ + integration_plugin_path: Path = Path(env.get("OPENPYPE_UNREAL_PLUGIN", "")) + + if not os.path.isdir(integration_plugin_path): + raise RuntimeError("Path to the integration plugin is null!") + + # Create a path to the plugin in the engine + op_plugin_path: Path = engine_path / "Engine/Plugins/Marketplace/OpenPype" + + if not op_plugin_path.is_dir(): + return False + + if not (op_plugin_path / "Binaries").is_dir() \ + or not (op_plugin_path / "Intermediate").is_dir(): + return False + + return True + + def try_installing_plugin(engine_path: Path, env: dict = None) -> None: env = env or os.environ @@ -377,7 +397,6 @@ def try_installing_plugin(engine_path: Path, env: dict = None) -> None: op_plugin_path: Path = engine_path / "Engine/Plugins/Marketplace/OpenPype" if not op_plugin_path.is_dir(): - print("--- OpenPype Plugin is not present. Installing ...") op_plugin_path.mkdir(parents=True, exist_ok=True) engine_plugin_config_path: Path = op_plugin_path / "Config" @@ -387,7 +406,6 @@ def try_installing_plugin(engine_path: Path, env: dict = None) -> None: if not (op_plugin_path / "Binaries").is_dir() \ or not (op_plugin_path / "Intermediate").is_dir(): - print("--- Binaries are not present. Building the plugin ...") _build_and_move_plugin(engine_path, op_plugin_path, env) diff --git a/openpype/hosts/unreal/ue_workers.py b/openpype/hosts/unreal/ue_workers.py new file mode 100644 index 00000000000..35735fcaa13 --- /dev/null +++ b/openpype/hosts/unreal/ue_workers.py @@ -0,0 +1,338 @@ +import json +import os +import platform +import re +import subprocess +from distutils import dir_util +from pathlib import Path +from typing import List + +import openpype.hosts.unreal.lib as ue_lib + +from qtpy import QtCore + + +def parse_comp_progress(line: str, progress_signal: QtCore.Signal(int)) -> int: + match = re.search('\[[1-9]+/[0-9]+\]', line) + if match is not None: + split: list[str] = match.group().split('/') + curr: float = float(split[0][1:]) + total: float = float(split[1][:-1]) + progress_signal.emit(int((curr / total) * 100.0)) + + +def parse_prj_progress(line: str, progress_signal: QtCore.Signal(int)) -> int: + match = re.search('@progress', line) + if match is not None: + percent_match = re.search('\d{1,3}', line) + progress_signal.emit(int(percent_match.group())) + + +class UEProjectGenerationWorker(QtCore.QObject): + finished = QtCore.Signal(str) + failed = QtCore.Signal(str) + progress = QtCore.Signal(int) + log = QtCore.Signal(str) + stage_begin = QtCore.Signal(str) + + ue_version: str = None + project_name: str = None + env = None + engine_path: Path = None + project_dir: Path = None + dev_mode = False + + def setup(self, ue_version: str, + project_name, + engine_path: Path, + project_dir: Path, + dev_mode: bool = False, + env: dict = None): + + self.ue_version = ue_version + self.project_dir = project_dir + self.env = env or os.environ + + preset = ue_lib.get_project_settings( + project_name + )["unreal"]["project_setup"] + + if dev_mode or preset["dev_mode"]: + self.dev_mode = True + + self.project_name = project_name + self.engine_path = engine_path + + def run(self): + + + ue_id = ".".join(self.ue_version.split(".")[:2]) + # get unreal engine identifier + # ------------------------------------------------------------------------- + # FIXME (antirotor): As of 4.26 this is problem with UE4 built from + # sources. In that case Engine ID is calculated per machine/user and not + # from Engine files as this code then reads. This then prevents UE4 + # to directly open project as it will complain about project being + # created in different UE4 version. When user convert such project + # to his UE4 version, Engine ID is replaced in uproject file. If some + # other user tries to open it, it will present him with similar error. + + # engine_path should be the location of UE_X.X folder + + ue_editor_exe = ue_lib.get_editor_exe_path(self.engine_path, + self.ue_version) + cmdlet_project = ue_lib.get_path_to_cmdlet_project(self.ue_version) + project_file = self.project_dir / f"{self.project_name}.uproject" + + print("--- Generating a new project ...") + # 1st stage + stage_count = 2 + if self.dev_mode: + stage_count = 4 + + self.stage_begin.emit(f'Generating a new UE project ... 1 out of ' + f'{stage_count}') + + commandlet_cmd = [f'{ue_editor_exe.as_posix()}', + f'{cmdlet_project.as_posix()}', + f'-run=OPGenerateProject', + f'{project_file.resolve().as_posix()}'] + + if self.dev_mode: + commandlet_cmd.append('-GenerateCode') + + gen_process = subprocess.Popen(commandlet_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + + for line in gen_process.stdout: + decoded_line = line.decode(errors="replace") + print(decoded_line, end='') + self.log.emit(decoded_line) + gen_process.stdout.close() + return_code = gen_process.wait() + + if return_code and return_code != 0: + msg = 'Failed to generate ' + self.project_name \ + + f' project! Exited with return code {return_code}' + self.failed.emit(msg, return_code) + raise RuntimeError(msg) + + print("--- Project has been generated successfully.") + self.stage_begin.emit(f'Writing the Engine ID of the build UE ... 1 out' + f' of {stage_count}') + + with open(project_file.as_posix(), mode="r+") as pf: + pf_json = json.load(pf) + pf_json["EngineAssociation"] = ue_lib.get_build_id(self.engine_path, + self.ue_version) + pf.seek(0) + json.dump(pf_json, pf, indent=4) + pf.truncate() + print(f'--- Engine ID has been written into the project file') + + self.progress.emit(90) + if self.dev_mode: + # 2nd stage + self.stage_begin.emit(f'Generating project files ... 2 out of ' + f'{stage_count}') + + self.progress.emit(0) + ubt_path = ue_lib.get_path_to_ubt(self.engine_path, self.ue_version) + + arch = "Win64" + if platform.system().lower() == "windows": + arch = "Win64" + elif platform.system().lower() == "linux": + arch = "Linux" + elif platform.system().lower() == "darwin": + # we need to test this out + arch = "Mac" + + gen_prj_files_cmd = [ubt_path.as_posix(), + "-projectfiles", + f"-project={project_file}", + "-progress"] + gen_proc = subprocess.Popen(gen_prj_files_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + for line in gen_proc.stdout: + decoded_line: str = line.decode(errors='replace') + print(decoded_line, end='') + self.log.emit(decoded_line) + parse_prj_progress(decoded_line, self.progress) + + gen_proc.stdout.close() + return_code = gen_proc.wait() + + if return_code and return_code != 0: + msg = 'Failed to generate project files! ' \ + f'Exited with return code {return_code}' + self.failed.emit(msg, return_code) + raise RuntimeError(msg) + + self.stage_begin.emit(f'Building the project ... 3 out of ' + f'{stage_count}') + self.progress.emit(0) + # 3rd stage + build_prj_cmd = [ubt_path.as_posix(), + f"-ModuleWithSuffix={self.project_name},3555", + arch, + "Development", + "-TargetType=Editor", + f'-Project={project_file}', + f'{project_file}', + "-IgnoreJunk"] + + build_prj_proc = subprocess.Popen(build_prj_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + for line in build_prj_proc.stdout: + decoded_line: str = line.decode(errors='replace') + print(decoded_line, end='') + self.log.emit(decoded_line) + parse_comp_progress(decoded_line, self.progress) + + build_prj_proc.stdout.close() + return_code = build_prj_proc.wait() + + if return_code and return_code != 0: + msg = 'Failed to build project! ' \ + f'Exited with return code {return_code}' + self.failed.emit(msg, return_code) + raise RuntimeError(msg) + + # ensure we have PySide2 installed in engine + + self.progress.emit(0) + self.stage_begin.emit(f'Checking PySide2 installation... {stage_count} ' + f'out of {stage_count}') + python_path = None + if platform.system().lower() == "windows": + python_path = self.engine_path / ("Engine/Binaries/ThirdParty/" + "Python3/Win64/python.exe") + + if platform.system().lower() == "linux": + python_path = self.engine_path / ("Engine/Binaries/ThirdParty/" + "Python3/Linux/bin/python3") + + if platform.system().lower() == "darwin": + python_path = self.engine_path / ("Engine/Binaries/ThirdParty/" + "Python3/Mac/bin/python3") + + if not python_path: + msg = "Unsupported platform" + self.failed.emit(msg, 1) + raise NotImplementedError(msg) + if not python_path.exists(): + msg = f"Unreal Python not found at {python_path}" + self.failed.emit(msg, 1) + raise RuntimeError(msg) + subprocess.check_call( + [python_path.as_posix(), "-m", "pip", "install", "pyside2"] + ) + self.progress.emit(100) + self.finished.emit("Project successfully built!") + + +class UEPluginInstallWorker(QtCore.QObject): + finished = QtCore.Signal(str) + installing = QtCore.Signal(str) + failed = QtCore.Signal(str, int) + progress = QtCore.Signal(int) + log = QtCore.Signal(str) + + engine_path: Path = None + env = None + + def setup(self, engine_path: Path, env: dict = None, ): + self.engine_path = engine_path + self.env = env or os.environ + + def _build_and_move_plugin(self, plugin_build_path: Path): + uat_path: Path = ue_lib.get_path_to_uat(self.engine_path) + src_plugin_dir = Path(self.env.get("OPENPYPE_UNREAL_PLUGIN", "")) + + if not os.path.isdir(src_plugin_dir): + msg = "Path to the integration plugin is null!" + self.failed.emit(msg, 1) + raise RuntimeError(msg) + + if not uat_path.is_file(): + msg = "Building failed! Path to UAT is invalid!" + self.failed.emit(msg, 1) + raise RuntimeError(msg) + + temp_dir: Path = src_plugin_dir.parent / "Temp" + temp_dir.mkdir(exist_ok=True) + uplugin_path: Path = src_plugin_dir / "OpenPype.uplugin" + + # in order to successfully build the plugin, + # It must be built outside the Engine directory and then moved + build_plugin_cmd: List[str] = [f'{uat_path.as_posix()}', + 'BuildPlugin', + f'-Plugin={uplugin_path.as_posix()}', + f'-Package={temp_dir.as_posix()}'] + + build_proc = subprocess.Popen(build_plugin_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + for line in build_proc.stdout: + decoded_line: str = line.decode(errors='replace') + print(decoded_line, end='') + self.log.emit(decoded_line) + parse_comp_progress(decoded_line, self.progress) + + build_proc.stdout.close() + return_code = build_proc.wait() + + if return_code and return_code != 0: + msg = 'Failed to build plugin' \ + f' project! Exited with return code {return_code}' + self.failed.emit(msg, return_code) + raise RuntimeError(msg) + + # Copy the contents of the 'Temp' dir into the + # 'OpenPype' directory in the engine + dir_util.copy_tree(temp_dir.as_posix(), + plugin_build_path.as_posix()) + + # We need to also copy the config folder. + # The UAT doesn't include the Config folder in the build + plugin_install_config_path: Path = plugin_build_path / "Config" + src_plugin_config_path = src_plugin_dir / "Config" + + dir_util.copy_tree(src_plugin_config_path.as_posix(), + plugin_install_config_path.as_posix()) + + dir_util.remove_tree(temp_dir.as_posix()) + + def run(self): + src_plugin_dir = Path(self.env.get("OPENPYPE_UNREAL_PLUGIN", "")) + + if not os.path.isdir(src_plugin_dir): + msg = "Path to the integration plugin is null!" + self.failed.emit(msg, 1) + raise RuntimeError(msg) + + # Create a path to the plugin in the engine + op_plugin_path = self.engine_path / \ + "Engine/Plugins/Marketplace/OpenPype" + + if not op_plugin_path.is_dir(): + self.installing.emit("Installing and building the plugin ...") + op_plugin_path.mkdir(parents=True, exist_ok=True) + + engine_plugin_config_path = op_plugin_path / "Config" + engine_plugin_config_path.mkdir(exist_ok=True) + + dir_util._path_created = {} + + if not (op_plugin_path / "Binaries").is_dir() \ + or not (op_plugin_path / "Intermediate").is_dir(): + self.installing.emit("Building the plugin ...") + print("--- Building the plugin...") + + self._build_and_move_plugin(op_plugin_path) + + self.finished.emit("Plugin successfully installed") diff --git a/openpype/widgets/README.md b/openpype/widgets/README.md new file mode 100644 index 00000000000..cda83a95d39 --- /dev/null +++ b/openpype/widgets/README.md @@ -0,0 +1,102 @@ +# Widgets + +## Splash Screen + +This widget is used for executing a monitoring progress of a process which has been executed on a different thread. + +To properly use this widget certain preparation has to be done in order to correctly execute the process and show the +splash screen. + +### Prerequisites + +In order to run a function or an operation on another thread, a `QtCore.QObject` class needs to be created with the +desired code. The class has to have a method as an entry point for the thread to execute the code. + +For utilizing the functionalities of the splash screen, certain signals need to be declared to let it know what is +happening in the thread and how is it progressing. It is also recommended to have a function to set up certain variables +which are needed in the worker's code + +For example: +```python +from qtpy import QtCore + +class ExampleWorker(QtCore.QObject): + + finished = QtCore.Signal() + failed = QtCore.Signal(str) + progress = QtCore.Signal(int) + log = QtCore.Signal(str) + stage_begin = QtCore.Signal(str) + + foo = None + bar = None + + def run(self): + # The code goes here + print("Hello world!") + self.finished.emit() + + def setup(self, + foo: str, + bar: str,): + self.foo = foo + self.bar = bar +``` + +### Creating the splash screen + +```python +import os +from qtpy import QtCore +from pathlib import Path +from openpype.widgets.splash_screen import SplashScreen +from openpype import resources + + +def exec_plugin_install( engine_path: Path, env: dict = None): + env = env or os.environ + q_thread = QtCore.QThread() + example_worker = ExampleWorker() + + q_thread.started.connect(example_worker.run) + example_worker.setup(engine_path, env) + example_worker.moveToThread(q_thread) + + splash_screen = SplashScreen("Executing process ...", + resources.get_openpype_icon_filepath()) + + # set up the splash screen with necessary events + example_worker.installing.connect(splash_screen.update_top_label_text) + example_worker.progress.connect(splash_screen.update_progress) + example_worker.log.connect(splash_screen.append_log) + example_worker.finished.connect(splash_screen.quit_and_close) + example_worker.failed.connect(splash_screen.fail) + + splash_screen.start_thread(q_thread) + splash_screen.show_ui() +``` + +In this example code, before executing the process the worker needs to be instantiated and moved onto a newly created +`QtCore.QThread` object. After this, needed signals have to be connected to the desired slots to make full use of +the splash screen. Finally, the `start_thread` and `show_ui` is called. + +**Note that when the `show_ui` function is called the thread is blocked until the splash screen quits automatically, or +it is closed by the user in case the process fails! The `start_thread` method in that case must be called before +showing the UI!** + +The most important signals are +```python +q_thread.started.connect(example_worker.run) +``` + and +```python +example_worker.finished.connect(splash_screen.quit_and_close) +``` + +These ensure that when the `start_thread` method is called (which takes as a parameter the `QtCore.QThread` object and +saves it as a reference), the `QThread` object starts and signals the worker to +start executing its own code. Once the worker is done and emits a signal that it has finished with the `quit_and_close` +slot, the splash screen quits the `QtCore.QThread` and closes itself. + +It is highly recommended to also use the `fail` slot in case an exception or other error occurs during the execution of +the worker's code (You would use in this case the `failed` signal in the `ExampleWorker`). diff --git a/openpype/widgets/splash_screen.py b/openpype/widgets/splash_screen.py new file mode 100644 index 00000000000..4a7598180d8 --- /dev/null +++ b/openpype/widgets/splash_screen.py @@ -0,0 +1,253 @@ +from qtpy import QtWidgets, QtCore, QtGui +from openpype import style, resources +from igniter.nice_progress_bar import NiceProgressBar + + +class SplashScreen(QtWidgets.QDialog): + """Splash screen for executing a process on another thread. It is able + to inform about the progress of the process and log given information. + """ + + splash_icon = None + top_label = None + show_log_btn: QtWidgets.QLabel = None + progress_bar = None + log_text: QtWidgets.QLabel = None + scroll_area: QtWidgets.QScrollArea = None + close_btn: QtWidgets.QPushButton = None + scroll_bar: QtWidgets.QScrollBar = None + + is_log_visible = False + is_scroll_auto = True + + thread_return_code = None + q_thread: QtCore.QThread = None + + def __init__(self, + window_title: str, + splash_icon=None, + window_icon=None): + """ + Args: + window_title (str): String which sets the window title + splash_icon (str | bytes | None): A resource (pic) which is used for + the splash icon + window_icon (str | bytes | None: A resource (pic) which is used for + the window's icon + """ + super(SplashScreen, self).__init__() + + if splash_icon is None: + splash_icon = resources.get_openpype_icon_filepath() + + if window_icon is None: + window_icon = resources.get_openpype_icon_filepath() + + self.splash_icon = splash_icon + self.setWindowIcon(QtGui.QIcon(window_icon)) + self.setWindowTitle(window_title) + self.init_ui() + + def was_proc_successful(self) -> bool: + if self.thread_return_code == 0: + return True + return False + + def start_thread(self, q_thread: QtCore.QThread): + """Saves the reference to this thread and starts it. + + Args: + q_thread (QtCore.QThread): A QThread containing a given worker + (QtCore.QObject) + + Returns: + None + """ + if not q_thread: + raise RuntimeError("Failed to run a worker thread! The thread is null!") + + self.q_thread = q_thread + self.q_thread.start() + + @QtCore.Slot() + def quit_and_close(self): + """Quits the thread and closes the splash screen. Note that this means + the thread has exited with the return code 0! + + Returns: + None + """ + self.thread_return_code = 0 + self.q_thread.quit() + self.close() + + @QtCore.Slot() + def toggle_log(self): + if self.is_log_visible: + self.scroll_area.hide() + width = self.width() + self.adjustSize() + self.resize(width, self.height()) + else: + self.scroll_area.show() + self.scroll_bar.setValue(self.scroll_bar.maximum()) + self.resize(self.width(), 300) + + self.is_log_visible = not self.is_log_visible + + def show_ui(self): + """Shows the splash screen. BEWARE THAT THIS FUNCTION IS BLOCKING + (The execution of code can not proceed further beyond this function + until the splash screen is closed!) + + Returns: + None + """ + self.show() + self.exec_() + + def init_ui(self): + self.resize(450, 100) + self.setMinimumWidth(250) + self.setStyleSheet(style.load_stylesheet()) + + # Top Section + self.top_label = QtWidgets.QLabel(self); + self.top_label.setText("Starting process ...") + self.top_label.setWordWrap(True) + + icon = QtWidgets.QLabel(self) + icon.setPixmap(QtGui.QPixmap(self.splash_icon)) + icon.setFixedHeight(45) + icon.setFixedWidth(45) + icon.setScaledContents(True) + + self.close_btn = QtWidgets.QPushButton(self) + self.close_btn.setText("Quit") + self.close_btn.clicked.connect(self.close) + self.close_btn.setFixedWidth(80) + self.close_btn.hide() + + self.show_log_btn = QtWidgets.QPushButton(self) + self.show_log_btn.setText("Show log") + self.show_log_btn.setFixedWidth(80) + self.show_log_btn.clicked.connect(self.toggle_log) + + button_layout = QtWidgets.QVBoxLayout() + button_layout.addWidget(self.show_log_btn) + button_layout.addWidget(self.close_btn) + + # Progress Bar + self.progress_bar = NiceProgressBar() + self.progress_bar.setValue(0) + self.progress_bar.setAlignment(QtCore.Qt.AlignTop) + + # Log Content + self.scroll_area = QtWidgets.QScrollArea(self) + self.scroll_area.hide() + log_widget = QtWidgets.QWidget(self.scroll_area) + self.scroll_area.setWidgetResizable(True) + self.scroll_area.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) + self.scroll_area.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) + self.scroll_area.setWidget(log_widget) + + self.scroll_bar = self.scroll_area.verticalScrollBar() + self.scroll_bar.sliderMoved.connect(self.on_scroll) + + self.log_text = QtWidgets.QLabel(self) + self.log_text.setText('') + self.log_text.setAlignment(QtCore.Qt.AlignTop) + + log_layout = QtWidgets.QVBoxLayout(log_widget) + log_layout.addWidget(self.log_text) + + top_layout = QtWidgets.QHBoxLayout() + top_layout.setAlignment(QtCore.Qt.AlignTop) + top_layout.addWidget(icon) + top_layout.addSpacing(10) + top_layout.addWidget(self.top_label) + top_layout.addSpacing(10) + top_layout.addLayout(button_layout) + + main_layout = QtWidgets.QVBoxLayout(self) + main_layout.addLayout(top_layout) + main_layout.addSpacing(10) + main_layout.addWidget(self.progress_bar) + main_layout.addSpacing(10) + main_layout.addWidget(self.scroll_area) + + self.setWindowFlags( + QtCore.Qt.Window + | QtCore.Qt.CustomizeWindowHint + | QtCore.Qt.WindowTitleHint + | QtCore.Qt.WindowMinimizeButtonHint + ) + + desktop_rect = QtWidgets.QApplication.desktop().availableGeometry(self) + center = desktop_rect.center() + self.move( + center.x() - (self.width() * 0.5), + center.y() - (self.height() * 0.5) + ) + + @QtCore.Slot(int) + def update_progress(self, value: int): + self.progress_bar.setValue(value) + + @QtCore.Slot(str) + def update_top_label_text(self, text: str): + self.top_label.setText(text) + + @QtCore.Slot(str, str) + def append_log(self, text: str, end: str = ''): + """A slot used for receiving log info and appending it to scroll area's + content. + Args: + text (str): A log text that will append to the current one in the scroll + area. + end (str): end string which can be appended to the end of the given + line (for ex. a line break). + + Returns: + None + """ + self.log_text.setText(self.log_text.text() + text + end) + if self.is_scroll_auto: + self.scroll_bar.setValue(self.scroll_bar.maximum()) + + @QtCore.Slot(int) + def on_scroll(self, position: int): + """ + A slot for the vertical scroll bar's movement. This ensures the + auto-scrolling feature of the scroll area when the scroll bar is at its + maximum value. + + Args: + position (int): Position value of the scroll bar. + + Returns: + None + """ + if self.scroll_bar.maximum() == position: + self.is_scroll_auto = True + return + + self.is_scroll_auto = False + + @QtCore.Slot(str, int) + def fail(self, text: str, return_code: int = 1): + """ + A slot used for signals which can emit when a worker (process) has + failed. at this moment the splash screen doesn't close by itself. + it has to be closed by the user. + + Args: + text (str): A text which can be set to the top label. + + Returns: + return_code (int): Return code of the thread's code + """ + self.top_label.setText(text) + self.close_btn.show() + self.thread_return_code = return_code + self.q_thread.exit(return_code) From 57faf21309a5271cc6845e674311abb7a2eff06d Mon Sep 17 00:00:00 2001 From: Joseff Date: Wed, 8 Mar 2023 17:18:54 +0100 Subject: [PATCH 362/898] Cleaned up the code, fixed the hanging thread --- .../unreal/hooks/pre_workfile_preparation.py | 21 +++++++++++++------ openpype/hosts/unreal/lib.py | 4 ++-- openpype/hosts/unreal/ue_workers.py | 20 +++++++----------- openpype/widgets/splash_screen.py | 15 ++++++++----- 4 files changed, 34 insertions(+), 26 deletions(-) diff --git a/openpype/hosts/unreal/hooks/pre_workfile_preparation.py b/openpype/hosts/unreal/hooks/pre_workfile_preparation.py index 8ede80f7fde..c3f9ea7e726 100644 --- a/openpype/hosts/unreal/hooks/pre_workfile_preparation.py +++ b/openpype/hosts/unreal/hooks/pre_workfile_preparation.py @@ -5,7 +5,10 @@ from pathlib import Path from openpype.widgets.splash_screen import SplashScreen from qtpy import QtCore -from openpype.hosts.unreal.ue_workers import UEProjectGenerationWorker, UEPluginInstallWorker +from openpype.hosts.unreal.ue_workers import ( + UEProjectGenerationWorker, + UEPluginInstallWorker +) from openpype import resources from openpype.lib import ( @@ -73,8 +76,10 @@ def exec_plugin_install(self, engine_path: Path, env: dict = None): ue_plugin_worker.setup(engine_path, env) ue_plugin_worker.moveToThread(q_thread) - splash_screen = SplashScreen("Installing plugin", - resources.get_resource("app_icons", "ue4.png")) + splash_screen = SplashScreen( + "Installing plugin", + resources.get_resource("app_icons", "ue4.png") + ) # set up the splash screen with necessary triggers ue_plugin_worker.installing.connect(splash_screen.update_top_label_text) @@ -111,10 +116,14 @@ def exec_ue_project_gen(self, ue_project_worker.moveToThread(q_thread) q_thread.started.connect(ue_project_worker.run) - splash_screen = SplashScreen("Initializing UE project", - resources.get_resource("app_icons", "ue4.png")) + splash_screen = SplashScreen( + "Initializing UE project", + resources.get_resource("app_icons", "ue4.png") + ) - ue_project_worker.stage_begin.connect(splash_screen.update_top_label_text) + ue_project_worker.stage_begin.connect( + splash_screen.update_top_label_text + ) ue_project_worker.progress.connect(splash_screen.update_progress) ue_project_worker.log.connect(splash_screen.append_log) ue_project_worker.finished.connect(splash_screen.quit_and_close) diff --git a/openpype/hosts/unreal/lib.py b/openpype/hosts/unreal/lib.py index 08cc57a6cdf..86ce0bb0333 100644 --- a/openpype/hosts/unreal/lib.py +++ b/openpype/hosts/unreal/lib.py @@ -252,7 +252,7 @@ def create_unreal_project(project_name: str, with open(project_file.as_posix(), mode="r+") as pf: pf_json = json.load(pf) - pf_json["EngineAssociation"] = _get_build_id(engine_path, ue_version) + pf_json["EngineAssociation"] = get_build_id(engine_path, ue_version) pf.seek(0) json.dump(pf_json, pf, indent=4) pf.truncate() @@ -338,7 +338,7 @@ def get_path_to_ubt(engine_path: Path, ue_version: str) -> Path: return Path(u_build_tool_path) -def _get_build_id(engine_path: Path, ue_version: str) -> str: +def get_build_id(engine_path: Path, ue_version: str) -> str: ue_modules = Path() if platform.system().lower() == "windows": ue_modules_path = engine_path / "Engine/Binaries/Win64" diff --git a/openpype/hosts/unreal/ue_workers.py b/openpype/hosts/unreal/ue_workers.py index 35735fcaa13..7dd08144e66 100644 --- a/openpype/hosts/unreal/ue_workers.py +++ b/openpype/hosts/unreal/ue_workers.py @@ -64,19 +64,6 @@ def setup(self, ue_version: str, self.engine_path = engine_path def run(self): - - - ue_id = ".".join(self.ue_version.split(".")[:2]) - # get unreal engine identifier - # ------------------------------------------------------------------------- - # FIXME (antirotor): As of 4.26 this is problem with UE4 built from - # sources. In that case Engine ID is calculated per machine/user and not - # from Engine files as this code then reads. This then prevents UE4 - # to directly open project as it will complain about project being - # created in different UE4 version. When user convert such project - # to his UE4 version, Engine ID is replaced in uproject file. If some - # other user tries to open it, it will present him with similar error. - # engine_path should be the location of UE_X.X folder ue_editor_exe = ue_lib.get_editor_exe_path(self.engine_path, @@ -122,10 +109,17 @@ def run(self): self.stage_begin.emit(f'Writing the Engine ID of the build UE ... 1 out' f' of {stage_count}') + if not project_file.is_file(): + msg = "Failed to write the Engine ID into .uproject file! Can " \ + "not read!" + self.failed.emit(msg) + raise RuntimeError(msg) + with open(project_file.as_posix(), mode="r+") as pf: pf_json = json.load(pf) pf_json["EngineAssociation"] = ue_lib.get_build_id(self.engine_path, self.ue_version) + print(pf_json["EngineAssociation"]) pf.seek(0) json.dump(pf_json, pf, indent=4) pf.truncate() diff --git a/openpype/widgets/splash_screen.py b/openpype/widgets/splash_screen.py index 4a7598180d8..6af19e991c1 100644 --- a/openpype/widgets/splash_screen.py +++ b/openpype/widgets/splash_screen.py @@ -64,7 +64,8 @@ def start_thread(self, q_thread: QtCore.QThread): None """ if not q_thread: - raise RuntimeError("Failed to run a worker thread! The thread is null!") + raise RuntimeError("Failed to run a worker thread! " + "The thread is null!") self.q_thread = q_thread self.q_thread.start() @@ -147,8 +148,12 @@ def init_ui(self): self.scroll_area.hide() log_widget = QtWidgets.QWidget(self.scroll_area) self.scroll_area.setWidgetResizable(True) - self.scroll_area.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) - self.scroll_area.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) + self.scroll_area.setHorizontalScrollBarPolicy( + QtCore.Qt.ScrollBarAlwaysOn + ) + self.scroll_area.setVerticalScrollBarPolicy( + QtCore.Qt.ScrollBarAlwaysOn + ) self.scroll_area.setWidget(log_widget) self.scroll_bar = self.scroll_area.verticalScrollBar() @@ -203,8 +208,8 @@ def append_log(self, text: str, end: str = ''): """A slot used for receiving log info and appending it to scroll area's content. Args: - text (str): A log text that will append to the current one in the scroll - area. + text (str): A log text that will append to the current one in the + scroll area. end (str): end string which can be appended to the end of the given line (for ex. a line break). From 78d737e4b30e1a890ff0ca6d085050d88bdedc6b Mon Sep 17 00:00:00 2001 From: Joseff Date: Wed, 8 Mar 2023 17:20:50 +0100 Subject: [PATCH 363/898] Reformatted the file --- openpype/widgets/splash_screen.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/widgets/splash_screen.py b/openpype/widgets/splash_screen.py index 6af19e991c1..fffe143ea5a 100644 --- a/openpype/widgets/splash_screen.py +++ b/openpype/widgets/splash_screen.py @@ -30,8 +30,8 @@ def __init__(self, """ Args: window_title (str): String which sets the window title - splash_icon (str | bytes | None): A resource (pic) which is used for - the splash icon + splash_icon (str | bytes | None): A resource (pic) which is used + for the splash icon window_icon (str | bytes | None: A resource (pic) which is used for the window's icon """ @@ -113,7 +113,7 @@ def init_ui(self): self.setStyleSheet(style.load_stylesheet()) # Top Section - self.top_label = QtWidgets.QLabel(self); + self.top_label = QtWidgets.QLabel(self) self.top_label.setText("Starting process ...") self.top_label.setWordWrap(True) From fc67c5a2c0b4d5a3bd4abae3ab860cc9f81a3762 Mon Sep 17 00:00:00 2001 From: Joseff Date: Wed, 8 Mar 2023 17:23:37 +0100 Subject: [PATCH 364/898] Fixed the line indentation. --- openpype/hosts/unreal/ue_workers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/unreal/ue_workers.py b/openpype/hosts/unreal/ue_workers.py index 7dd08144e66..21623579125 100644 --- a/openpype/hosts/unreal/ue_workers.py +++ b/openpype/hosts/unreal/ue_workers.py @@ -310,8 +310,8 @@ def run(self): raise RuntimeError(msg) # Create a path to the plugin in the engine - op_plugin_path = self.engine_path / \ - "Engine/Plugins/Marketplace/OpenPype" + op_plugin_path = self.engine_path / "Engine/Plugins/Marketplace" \ + "/OpenPype" if not op_plugin_path.is_dir(): self.installing.emit("Installing and building the plugin ...") From e5b7349dff710bc2577e1a9adba39cde9748e231 Mon Sep 17 00:00:00 2001 From: Joseff Date: Wed, 8 Mar 2023 17:26:27 +0100 Subject: [PATCH 365/898] Code cleanup --- openpype/hosts/unreal/ue_workers.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/unreal/ue_workers.py b/openpype/hosts/unreal/ue_workers.py index 21623579125..00f83a7d7a4 100644 --- a/openpype/hosts/unreal/ue_workers.py +++ b/openpype/hosts/unreal/ue_workers.py @@ -106,8 +106,8 @@ def run(self): raise RuntimeError(msg) print("--- Project has been generated successfully.") - self.stage_begin.emit(f'Writing the Engine ID of the build UE ... 1 out' - f' of {stage_count}') + self.stage_begin.emit(f'Writing the Engine ID of the build UE ... 1' + f' out of {stage_count}') if not project_file.is_file(): msg = "Failed to write the Engine ID into .uproject file! Can " \ @@ -117,8 +117,10 @@ def run(self): with open(project_file.as_posix(), mode="r+") as pf: pf_json = json.load(pf) - pf_json["EngineAssociation"] = ue_lib.get_build_id(self.engine_path, - self.ue_version) + pf_json["EngineAssociation"] = ue_lib.get_build_id( + self.engine_path, + self.ue_version + ) print(pf_json["EngineAssociation"]) pf.seek(0) json.dump(pf_json, pf, indent=4) @@ -132,7 +134,8 @@ def run(self): f'{stage_count}') self.progress.emit(0) - ubt_path = ue_lib.get_path_to_ubt(self.engine_path, self.ue_version) + ubt_path = ue_lib.get_path_to_ubt(self.engine_path, + self.ue_version) arch = "Win64" if platform.system().lower() == "windows": @@ -199,8 +202,8 @@ def run(self): # ensure we have PySide2 installed in engine self.progress.emit(0) - self.stage_begin.emit(f'Checking PySide2 installation... {stage_count} ' - f'out of {stage_count}') + self.stage_begin.emit(f'Checking PySide2 installation... {stage_count}' + f' out of {stage_count}') python_path = None if platform.system().lower() == "windows": python_path = self.engine_path / ("Engine/Binaries/ThirdParty/" From 7941c73f82ce7d708e7387f0db4f39df54c58f67 Mon Sep 17 00:00:00 2001 From: Joseff Date: Wed, 8 Mar 2023 17:27:25 +0100 Subject: [PATCH 366/898] Code cleanup --- openpype/hosts/unreal/hooks/pre_workfile_preparation.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/unreal/hooks/pre_workfile_preparation.py b/openpype/hosts/unreal/hooks/pre_workfile_preparation.py index c3f9ea7e726..da12bc75de8 100644 --- a/openpype/hosts/unreal/hooks/pre_workfile_preparation.py +++ b/openpype/hosts/unreal/hooks/pre_workfile_preparation.py @@ -82,7 +82,9 @@ def exec_plugin_install(self, engine_path: Path, env: dict = None): ) # set up the splash screen with necessary triggers - ue_plugin_worker.installing.connect(splash_screen.update_top_label_text) + ue_plugin_worker.installing.connect( + splash_screen.update_top_label_text + ) ue_plugin_worker.progress.connect(splash_screen.update_progress) ue_plugin_worker.log.connect(splash_screen.append_log) ue_plugin_worker.finished.connect(splash_screen.quit_and_close) From e2771abfb48d255288a708407b305241f4601737 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 10 Mar 2023 23:07:13 +0100 Subject: [PATCH 367/898] Move CustomCommentTemplate to within IntegrateKitsuNote --- .../defaults/project_settings/kitsu.json | 10 ++--- .../projects_schema/schema_project_kitsu.json | 44 +++++++++---------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/openpype/settings/defaults/project_settings/kitsu.json b/openpype/settings/defaults/project_settings/kitsu.json index 280895f1b98..f8a98d1a0b9 100644 --- a/openpype/settings/defaults/project_settings/kitsu.json +++ b/openpype/settings/defaults/project_settings/kitsu.json @@ -7,11 +7,11 @@ "publish": { "IntegrateKitsuNote": { "set_status_note": false, - "note_status_shortname": "wfa" - }, - "CustomCommentTemplate": { - "enabled": false, - "comment_template": "{comment}\n\n| | |\n|--|--|\n| version| `{version}` |\n| family | `{family}` |\n| name | `{name}` |" + "note_status_shortname": "wfa", + "CustomCommentTemplate": { + "enabled": false, + "comment_template": "{comment}\n\n| | |\n|--|--|\n| version| `{version}` |\n| family | `{family}` |\n| name | `{name}` |" + } } } } \ No newline at end of file diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index 255190c3962..25f75c8280a 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -52,30 +52,30 @@ "type": "text", "key": "note_status_shortname", "label": "Note shortname" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "checkbox_key": "enabled", - "key": "CustomCommentTemplate", - "label": "Custom Comment Template", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" }, { - "type": "label", - "label": "Kitsu supports markdown and here you can create a custom comment template.
You can use data from your instance's anatomy." - }, - { - "key": "comment_template", - "type": "text", - "multiline": true, - "label": "Custom comment" + "type": "dict", + "collapsible": true, + "checkbox_key": "enabled", + "key": "CustomCommentTemplate", + "label": "Custom Comment Template", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "label", + "label": "Kitsu supports markdown and here you can create a custom comment template.
You can use data from your instance's anatomy." + }, + { + "key": "comment_template", + "type": "text", + "multiline": true, + "label": "Custom comment" + } + ] } ] } From 7c1789faabea2380ab3001e32876d2747cf55f28 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 10 Mar 2023 23:07:41 +0100 Subject: [PATCH 368/898] Add custom message functionally --- .../plugins/publish/integrate_kitsu_note.py | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 6702cbe7aa3..b1743ca828b 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import gazu import pyblish.api +import re class IntegrateKitsuNote(pyblish.api.ContextPlugin): @@ -9,17 +10,39 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): order = pyblish.api.IntegratorOrder label = "Kitsu Note and Status" families = ["render", "kitsu"] + + # status settings set_status_note = False note_status_shortname = "wfa" + # comment settings + CustomCommentTemplate = {} + CustomCommentTemplate["enabled"] = False + CustomCommentTemplate["comment_template"] = "{comment}" + + def safe_format(self, msg, **kwargs): + def replace_missing(match): + value = kwargs.get(match.group(1), None) + if value is None: + self.log.warning( + "Key `{}` was not found in instance.data " + "and will be rendered as `` in the comment".format( + match.group(1) + ) + ) + return "" + else: + return str(value) + + pattern = r"\{([^}]*)\}" + return re.sub(pattern, replace_missing, msg) + def process(self, context): # Get comment text body publish_comment = context.data.get("comment") if not publish_comment: self.log.info("Comment is not set.") - self.log.debug("Comment is `{}`".format(publish_comment)) - for instance in context: kitsu_task = instance.data.get("kitsu_task") if kitsu_task is None: @@ -42,6 +65,15 @@ def process(self, context): "changed!".format(self.note_status_shortname) ) + # If custom comment, create it + if self.CustomCommentTemplate["enabled"]: + publish_comment = self.safe_format( + self.CustomCommentTemplate["comment_template"], + **instance.data, + ) + + self.log.debug("Comment is `{}`".format(publish_comment)) + # Add comment to kitsu task task_id = kitsu_task["id"] self.log.debug("Add new note in taks id {}".format(task_id)) From a797d78d451eb953bd5c4a2018712ade3e645c2a Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 10 Mar 2023 23:19:31 +0100 Subject: [PATCH 369/898] Added a check so only renders gets published to Kitsu --- .../modules/kitsu/plugins/publish/integrate_kitsu_note.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index b1743ca828b..44134dec6d7 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -44,6 +44,10 @@ def process(self, context): self.log.info("Comment is not set.") for instance in context: + # Check if instance is a render by checking its family + if "render" not in instance.data["family"]: + continue + kitsu_task = instance.data.get("kitsu_task") if kitsu_task is None: continue From 1093c519add9baae3276e01aa28e1a1d46cab0c8 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 10 Mar 2023 23:27:47 +0100 Subject: [PATCH 370/898] Change the label to explain more correct what it does --- .../schemas/projects_schema/schema_project_kitsu.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index 25f75c8280a..1a7747b3dca 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -46,12 +46,12 @@ { "type": "boolean", "key": "set_status_note", - "label": "Set status on note" + "label": "Set status with note" }, { "type": "text", "key": "note_status_shortname", - "label": "Note shortname" + "label": "Status shortname" }, { "type": "dict", From 3b64f515b25ebeccd4235a02722aa1e1eef26bc0 Mon Sep 17 00:00:00 2001 From: Ynbot Date: Sat, 11 Mar 2023 03:26:36 +0000 Subject: [PATCH 371/898] [Automated] Bump version --- openpype/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/version.py b/openpype/version.py index c7a5e9bea57..e8124f14663 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.15.2-nightly.5" +__version__ = "3.15.2-nightly.6" From 021454dc9bc72e9d09c0e4447f3d37647ad79669 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 11 Mar 2023 06:59:43 +0100 Subject: [PATCH 372/898] Fix #4044: Don't rely on containers, but just get ids from the nodes --- openpype/tools/mayalookassigner/commands.py | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/openpype/tools/mayalookassigner/commands.py b/openpype/tools/mayalookassigner/commands.py index 2e7a51efded..6955dda97fe 100644 --- a/openpype/tools/mayalookassigner/commands.py +++ b/openpype/tools/mayalookassigner/commands.py @@ -80,21 +80,9 @@ def get_all_asset_nodes(): Returns: list: list of dictionaries """ - - host = registered_host() - - nodes = [] - for container in host.ls(): - # We are not interested in looks but assets! - if container["loader"] == "LookLoader": - continue - - # Gather all information - container_name = container["objectName"] - nodes += lib.get_container_members(container_name) - - nodes = list(set(nodes)) - return nodes + nodes = cmds.ls(dag=True, noIntermediate=True, long=True) + items = commands.create_items_from_nodes(nodes) + return items def create_asset_id_hash(nodes): From b44b0b8fb063aeef51761a2b179cd9e074a9a5f8 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 11 Mar 2023 07:57:20 +0100 Subject: [PATCH 373/898] Remove `commands.` prefix since function is local --- openpype/tools/mayalookassigner/commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/tools/mayalookassigner/commands.py b/openpype/tools/mayalookassigner/commands.py index 6955dda97fe..0135eb4f49b 100644 --- a/openpype/tools/mayalookassigner/commands.py +++ b/openpype/tools/mayalookassigner/commands.py @@ -81,7 +81,7 @@ def get_all_asset_nodes(): list: list of dictionaries """ nodes = cmds.ls(dag=True, noIntermediate=True, long=True) - items = commands.create_items_from_nodes(nodes) + items = create_items_from_nodes(nodes) return items From c3becbffe0c5476fbac0a401bb710b9246e493e4 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 11 Mar 2023 19:42:14 +0100 Subject: [PATCH 374/898] Fix #4429: Do not reset fps or playback timeline on applying or creating render settings --- openpype/hosts/maya/api/lib.py | 43 ++++++++++++------- openpype/hosts/maya/api/lib_rendersettings.py | 2 +- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index 954576f02ec..61106c58cff 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -2099,29 +2099,40 @@ def get_frame_range(): } -def reset_frame_range(): - """Set frame range to current asset""" +def reset_frame_range(playback=True, render=True, fps=True): + """Set frame range to current asset - fps = convert_to_maya_fps( - float(legacy_io.Session.get("AVALON_FPS", 25)) - ) - set_scene_fps(fps) + Args: + playback (bool, Optional): Whether to set the maya timeline playback + frame range. Defaults to True. + render (bool, Optional): Whether to set the maya render frame range. + Defaults to True. + fps (bool, Optional): Whether to set scene FPS. Defaults to True. + """ + + if fps: + fps = convert_to_maya_fps( + float(legacy_io.Session.get("AVALON_FPS", 25)) + ) + set_scene_fps(fps) frame_range = get_frame_range() frame_start = frame_range["frameStart"] - int(frame_range["handleStart"]) frame_end = frame_range["frameEnd"] + int(frame_range["handleEnd"]) - cmds.playbackOptions(minTime=frame_start) - cmds.playbackOptions(maxTime=frame_end) - cmds.playbackOptions(animationStartTime=frame_start) - cmds.playbackOptions(animationEndTime=frame_end) - cmds.playbackOptions(minTime=frame_start) - cmds.playbackOptions(maxTime=frame_end) - cmds.currentTime(frame_start) - - cmds.setAttr("defaultRenderGlobals.startFrame", frame_start) - cmds.setAttr("defaultRenderGlobals.endFrame", frame_end) + if playback: + cmds.playbackOptions(minTime=frame_start) + cmds.playbackOptions(maxTime=frame_end) + cmds.playbackOptions(animationStartTime=frame_start) + cmds.playbackOptions(animationEndTime=frame_end) + cmds.playbackOptions(minTime=frame_start) + cmds.playbackOptions(maxTime=frame_end) + cmds.currentTime(frame_start) + + if render: + cmds.setAttr("defaultRenderGlobals.startFrame", frame_start) + cmds.setAttr("defaultRenderGlobals.endFrame", frame_end) def reset_scene_resolution(): diff --git a/openpype/hosts/maya/api/lib_rendersettings.py b/openpype/hosts/maya/api/lib_rendersettings.py index 7d44d4eaa62..eaa728a2f68 100644 --- a/openpype/hosts/maya/api/lib_rendersettings.py +++ b/openpype/hosts/maya/api/lib_rendersettings.py @@ -158,7 +158,7 @@ def _set_arnold_settings(self, width, height): cmds.setAttr( "defaultArnoldDriver.mergeAOVs", multi_exr) self._additional_attribs_setter(additional_options) - reset_frame_range() + reset_frame_range(playback=False, fps=False, render=True) def _set_redshift_settings(self, width, height): """Sets settings for Redshift.""" From e2902e86232d738433a9de45f84eb3d3b0b296e1 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 11 Mar 2023 20:49:26 +0100 Subject: [PATCH 375/898] Fix #4109: Unify menu labels for "Set Frame Range" and "Set Resolution" --- openpype/hosts/blender/api/ops.py | 4 ++-- openpype/hosts/houdini/startup/MainMenuCommon.xml | 2 +- openpype/hosts/maya/api/menu.py | 4 ++-- openpype/hosts/resolve/api/menu.py | 8 ++++---- website/docs/artist_hosts_maya.md | 8 ++++---- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/openpype/hosts/blender/api/ops.py b/openpype/hosts/blender/api/ops.py index 481c199db29..b1fa13acb9d 100644 --- a/openpype/hosts/blender/api/ops.py +++ b/openpype/hosts/blender/api/ops.py @@ -382,8 +382,8 @@ def draw(self, context): layout.operator(LaunchLibrary.bl_idname, text="Library...") layout.separator() layout.operator(LaunchWorkFiles.bl_idname, text="Work Files...") - # TODO (jasper): maybe add 'Reload Pipeline', 'Reset Frame Range' and - # 'Reset Resolution'? + # TODO (jasper): maybe add 'Reload Pipeline', 'Set Frame Range' and + # 'Set Resolution'? def draw_avalon_menu(self, context): diff --git a/openpype/hosts/houdini/startup/MainMenuCommon.xml b/openpype/hosts/houdini/startup/MainMenuCommon.xml index c08114b71bc..e12000b8553 100644 --- a/openpype/hosts/houdini/startup/MainMenuCommon.xml +++ b/openpype/hosts/houdini/startup/MainMenuCommon.xml @@ -67,7 +67,7 @@ host_tools.show_workfiles(parent) - + / ``` -Doing **OpenPype → Reset Resolution** will set correct resolution on camera. +Doing **OpenPype → Set Resolution** will set correct resolution on camera. Scene is now ready for submission and should publish without errors. From 7efb019ebc799905e4fc126883aaf9ffb86936ec Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 11 Mar 2023 20:50:30 +0100 Subject: [PATCH 376/898] Match id with label --- openpype/hosts/houdini/startup/MainMenuCommon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/houdini/startup/MainMenuCommon.xml b/openpype/hosts/houdini/startup/MainMenuCommon.xml index e12000b8553..47595ebd8c7 100644 --- a/openpype/hosts/houdini/startup/MainMenuCommon.xml +++ b/openpype/hosts/houdini/startup/MainMenuCommon.xml @@ -66,7 +66,7 @@ host_tools.show_workfiles(parent) ]]> - + Date: Mon, 13 Mar 2023 10:32:19 +0100 Subject: [PATCH 377/898] SiteSync: host dirmap is not working properly (#4563) - only editable keys are returned from Site Sync module to Local Settings Cleaner approach even if LS UI is going away in Ayon. - use remote_site only if is local_drive provider - remove unwanted import - cache mapping, update logging Mapping was called multiple times for Nuke. Logging was too verbose. --- openpype/host/dirmap.py | 63 +++++++++---------- openpype/hosts/nuke/api/lib.py | 54 +++++++++------- .../modules/sync_server/sync_server_module.py | 20 +++++- .../local_settings/projects_widget.py | 2 +- 4 files changed, 81 insertions(+), 58 deletions(-) diff --git a/openpype/host/dirmap.py b/openpype/host/dirmap.py index 347c5fbf851..1d084cccad5 100644 --- a/openpype/host/dirmap.py +++ b/openpype/host/dirmap.py @@ -39,7 +39,6 @@ def __init__( self._project_settings = project_settings self._sync_module = sync_module # to limit reinit of Modules self._log = None - self._mapping = None # cache mapping @property def sync_module(self): @@ -70,29 +69,28 @@ def dirmap_routine(self, source_path, destination_path): """Run host dependent remapping from source_path to destination_path""" pass - def process_dirmap(self): + def process_dirmap(self, mapping=None): # type: (dict) -> None """Go through all paths in Settings and set them using `dirmap`. If artists has Site Sync enabled, take dirmap mapping directly from Local Settings when artist is syncing workfile locally. - Args: - project_settings (dict): Settings for current project. """ - if not self._mapping: - self._mapping = self.get_mappings(self.project_settings) - if not self._mapping: + if not mapping: + mapping = self.get_mappings() + if not mapping: return - self.log.info("Processing directory mapping ...") self.on_enable_dirmap() - self.log.info("mapping:: {}".format(self._mapping)) - for k, sp in enumerate(self._mapping["source-path"]): - dst = self._mapping["destination-path"][k] + for k, sp in enumerate(mapping["source-path"]): + dst = mapping["destination-path"][k] try: + # add trailing slash if missing + sp = os.path.join(sp, '') + dst = os.path.join(dst, '') print("{} -> {}".format(sp, dst)) self.dirmap_routine(sp, dst) except IndexError: @@ -110,28 +108,24 @@ def process_dirmap(self): ) continue - def get_mappings(self, project_settings): + def get_mappings(self): """Get translation from source-path to destination-path. It checks if Site Sync is enabled and user chose to use local site, in that case configuration in Local Settings takes precedence """ - local_mapping = self._get_local_sync_dirmap(project_settings) dirmap_label = "{}-dirmap".format(self.host_name) - if ( - not self.project_settings[self.host_name].get(dirmap_label) - and not local_mapping - ): - return {} - mapping_settings = self.project_settings[self.host_name][dirmap_label] - mapping_enabled = mapping_settings["enabled"] or bool(local_mapping) + mapping_sett = self.project_settings[self.host_name].get(dirmap_label, + {}) + local_mapping = self._get_local_sync_dirmap() + mapping_enabled = mapping_sett.get("enabled") or bool(local_mapping) if not mapping_enabled: return {} mapping = ( local_mapping - or mapping_settings["paths"] + or mapping_sett["paths"] or {} ) @@ -141,28 +135,27 @@ def get_mappings(self, project_settings): or not mapping.get("source-path") ): return {} + self.log.info("Processing directory mapping ...") + self.log.info("mapping:: {}".format(mapping)) return mapping - def _get_local_sync_dirmap(self, project_settings): + def _get_local_sync_dirmap(self): """ Returns dirmap if synch to local project is enabled. Only valid mapping is from roots of remote site to local site set in Local Settings. - Args: - project_settings (dict) Returns: dict : { "source-path": [XXX], "destination-path": [YYYY]} """ + project_name = os.getenv("AVALON_PROJECT") mapping = {} - - if not project_settings["global"]["sync_server"]["enabled"]: + if (not self.sync_module.enabled or + project_name not in self.sync_module.get_enabled_projects()): return mapping - project_name = os.getenv("AVALON_PROJECT") - active_site = self.sync_module.get_local_normalized_site( self.sync_module.get_active_site(project_name)) remote_site = self.sync_module.get_local_normalized_site( @@ -171,11 +164,7 @@ def _get_local_sync_dirmap(self, project_settings): "active {} - remote {}".format(active_site, remote_site) ) - if ( - active_site == "local" - and project_name in self.sync_module.get_enabled_projects() - and active_site != remote_site - ): + if active_site == "local" and active_site != remote_site: sync_settings = self.sync_module.get_sync_project_setting( project_name, exclude_locals=False, @@ -188,7 +177,15 @@ def _get_local_sync_dirmap(self, project_settings): self.log.debug("local overrides {}".format(active_overrides)) self.log.debug("remote overrides {}".format(remote_overrides)) + current_platform = platform.system().lower() + remote_provider = self.sync_module.get_provider_for_site( + project_name, remote_site + ) + # dirmap has sense only with regular disk provider, in the workfile + # wont be root on cloud or sftp provider + if remote_provider != "local_drive": + remote_site = "studio" for root_name, active_site_dir in active_overrides.items(): remote_site_dir = ( remote_overrides.get(root_name) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index a5a631cc70f..2a14096f0eb 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -2861,10 +2861,10 @@ def on_enable_dirmap(self): pass def dirmap_routine(self, source_path, destination_path): - log.debug("{}: {}->{}".format(self.file_name, - source_path, destination_path)) source_path = source_path.lower().replace(os.sep, '/') destination_path = destination_path.lower().replace(os.sep, '/') + log.debug("Map: {} with: {}->{}".format(self.file_name, + source_path, destination_path)) if platform.system().lower() == "windows": self.file_name = self.file_name.lower().replace( source_path, destination_path) @@ -2878,6 +2878,7 @@ class DirmapCache: _project_name = None _project_settings = None _sync_module = None + _mapping = None @classmethod def project_name(cls): @@ -2897,6 +2898,36 @@ def sync_module(cls): cls._sync_module = ModulesManager().modules_by_name["sync_server"] return cls._sync_module + @classmethod + def mapping(cls): + return cls._mapping + + @classmethod + def set_mapping(cls, mapping): + cls._mapping = mapping + + +def dirmap_file_name_filter(file_name): + """Nuke callback function with single full path argument. + + Checks project settings for potential mapping from source to dest. + """ + + dirmap_processor = NukeDirmap( + file_name, + "nuke", + DirmapCache.project_name(), + DirmapCache.project_settings(), + DirmapCache.sync_module(), + ) + if not DirmapCache.mapping(): + DirmapCache.set_mapping(dirmap_processor.get_mappings()) + + dirmap_processor.process_dirmap(DirmapCache.mapping()) + if os.path.exists(dirmap_processor.file_name): + return dirmap_processor.file_name + return file_name + @contextlib.contextmanager def node_tempfile(): @@ -2942,25 +2973,6 @@ def duplicate_node(node): return dupli_node -def dirmap_file_name_filter(file_name): - """Nuke callback function with single full path argument. - - Checks project settings for potential mapping from source to dest. - """ - - dirmap_processor = NukeDirmap( - file_name, - "nuke", - DirmapCache.project_name(), - DirmapCache.project_settings(), - DirmapCache.sync_module(), - ) - dirmap_processor.process_dirmap() - if os.path.exists(dirmap_processor.file_name): - return dirmap_processor.file_name - return file_name - - def get_group_io_nodes(nodes): """Get the input and the output of a group of nodes.""" diff --git a/openpype/modules/sync_server/sync_server_module.py b/openpype/modules/sync_server/sync_server_module.py index 28863c091a8..5a4fa07e982 100644 --- a/openpype/modules/sync_server/sync_server_module.py +++ b/openpype/modules/sync_server/sync_server_module.py @@ -1472,13 +1472,15 @@ def _parse_sync_settings_from_settings(self, settings): return sync_settings - def get_all_site_configs(self, project_name=None): + def get_all_site_configs(self, project_name=None, + local_editable_only=False): """ Returns (dict) with all sites configured system wide. Args: project_name (str)(optional): if present, check if not disabled - + local_editable_only (bool)(opt): if True return only Local + Setting configurable (for LS UI) Returns: (dict): {'studio': {'provider':'local_drive'...}, 'MY_LOCAL': {'provider':....}} @@ -1499,9 +1501,21 @@ def get_all_site_configs(self, project_name=None): if site_settings: detail.update(site_settings) system_sites[site] = detail - system_sites.update(self._get_default_site_configs(sync_enabled, project_name)) + if local_editable_only: + local_schema = SyncServerModule.get_local_settings_schema() + editable_keys = {} + for provider_code, editables in local_schema.items(): + editable_keys[provider_code] = ["enabled", "provider"] + for editable_item in editables: + editable_keys[provider_code].append(editable_item["key"]) + + for _, site in system_sites.items(): + provider = site["provider"] + for site_config_key in list(site.keys()): + if site_config_key not in editable_keys[provider]: + site.pop(site_config_key, None) return system_sites diff --git a/openpype/tools/settings/local_settings/projects_widget.py b/openpype/tools/settings/local_settings/projects_widget.py index bdf291524c0..4a4148d7cd7 100644 --- a/openpype/tools/settings/local_settings/projects_widget.py +++ b/openpype/tools/settings/local_settings/projects_widget.py @@ -272,7 +272,7 @@ def _get_sites_inputs(self): ) site_configs = sync_server_module.get_all_site_configs( - self._project_name) + self._project_name, local_editable_only=True) roots_entity = ( self.project_settings[PROJECT_ANATOMY_KEY][LOCAL_ROOTS_KEY] From 86184a8ee0525c3f361850cae0b576aca051bdf4 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 13 Mar 2023 11:20:59 +0100 Subject: [PATCH 378/898] Tools: Fix recursive filtering (#4597) * check for 'filterRegExp' first * use recursive filtering option if is available --- openpype/tools/loader/widgets.py | 6 +++--- openpype/tools/sceneinventory/model.py | 6 +++--- openpype/tools/sceneinventory/window.py | 6 +++--- .../tools/settings/settings/search_dialog.py | 12 +++++------ .../model_filter_proxy_recursive_sort.py | 6 +++--- openpype/tools/utils/models.py | 20 ++++++++++++++----- 6 files changed, 33 insertions(+), 23 deletions(-) diff --git a/openpype/tools/loader/widgets.py b/openpype/tools/loader/widgets.py index 98ac9c871fe..b3aa381d145 100644 --- a/openpype/tools/loader/widgets.py +++ b/openpype/tools/loader/widgets.py @@ -295,10 +295,10 @@ def set_grouping(self, state): self.model.set_grouping(state) def _subset_changed(self, text): - if hasattr(self.proxy, "setFilterRegularExpression"): - self.proxy.setFilterRegularExpression(text) - else: + if hasattr(self.proxy, "setFilterRegExp"): self.proxy.setFilterRegExp(text) + else: + self.proxy.setFilterRegularExpression(text) self.view.expandAll() def set_loading_state(self, loading, empty): diff --git a/openpype/tools/sceneinventory/model.py b/openpype/tools/sceneinventory/model.py index 3398743aec5..680dfd5a510 100644 --- a/openpype/tools/sceneinventory/model.py +++ b/openpype/tools/sceneinventory/model.py @@ -482,10 +482,10 @@ def filterAcceptsRow(self, row, parent): return True # Filter by regex - if hasattr(self, "filterRegularExpression"): - regex = self.filterRegularExpression() - else: + if hasattr(self, "filterRegExp"): regex = self.filterRegExp() + else: + regex = self.filterRegularExpression() pattern = regex.pattern() if pattern: pattern = re.escape(pattern) diff --git a/openpype/tools/sceneinventory/window.py b/openpype/tools/sceneinventory/window.py index 8a6e43f796b..89424fd746d 100644 --- a/openpype/tools/sceneinventory/window.py +++ b/openpype/tools/sceneinventory/window.py @@ -160,10 +160,10 @@ def _on_hierarchy_view_change(self, enabled): self._model.set_hierarchy_view(enabled) def _on_text_filter_change(self, text_filter): - if hasattr(self._proxy, "setFilterRegularExpression"): - self._proxy.setFilterRegularExpression(text_filter) - else: + if hasattr(self._proxy, "setFilterRegExp"): self._proxy.setFilterRegExp(text_filter) + else: + self._proxy.setFilterRegularExpression(text_filter) def _on_outdated_state_change(self): self._proxy.set_filter_outdated( diff --git a/openpype/tools/settings/settings/search_dialog.py b/openpype/tools/settings/settings/search_dialog.py index 33a4d16e982..59750c02e19 100644 --- a/openpype/tools/settings/settings/search_dialog.py +++ b/openpype/tools/settings/settings/search_dialog.py @@ -27,10 +27,10 @@ def filterAcceptsRow(self, row, parent): if not parent.isValid(): return False - if hasattr(self, "filterRegularExpression"): - regex = self.filterRegularExpression() - else: + if hasattr(self, "filterRegExp"): regex = self.filterRegExp() + else: + regex = self.filterRegularExpression() pattern = regex.pattern() if pattern and regex.isValid(): @@ -111,10 +111,10 @@ def _on_filter_changed(self, txt): def _on_filter_timer(self): text = self._filter_edit.text() - if hasattr(self._proxy, "setFilterRegularExpression"): - self._proxy.setFilterRegularExpression(text) - else: + if hasattr(self._proxy, "setFilterRegExp"): self._proxy.setFilterRegExp(text) + else: + self._proxy.setFilterRegularExpression(text) # WARNING This expanding and resizing is relatively slow. self._view.expandAll() diff --git a/openpype/tools/standalonepublish/widgets/model_filter_proxy_recursive_sort.py b/openpype/tools/standalonepublish/widgets/model_filter_proxy_recursive_sort.py index 5c72e2049b9..602faaa489a 100644 --- a/openpype/tools/standalonepublish/widgets/model_filter_proxy_recursive_sort.py +++ b/openpype/tools/standalonepublish/widgets/model_filter_proxy_recursive_sort.py @@ -5,10 +5,10 @@ class RecursiveSortFilterProxyModel(QtCore.QSortFilterProxyModel): """Filters to the regex if any of the children matches allow parent""" def filterAcceptsRow(self, row, parent): - if hasattr(self, "filterRegularExpression"): - regex = self.filterRegularExpression() - else: + if hasattr(self, "filterRegExp"): regex = self.filterRegExp() + else: + regex = self.filterRegularExpression() pattern = regex.pattern() if pattern: model = self.sourceModel() diff --git a/openpype/tools/utils/models.py b/openpype/tools/utils/models.py index 270e00b2ef8..94645af110b 100644 --- a/openpype/tools/utils/models.py +++ b/openpype/tools/utils/models.py @@ -202,11 +202,20 @@ class RecursiveSortFilterProxyModel(QtCore.QSortFilterProxyModel): Use case: Filtering by string - parent won't be filtered if does not match the filter string but first checks if any children does. """ + + def __init__(self, *args, **kwargs): + super(RecursiveSortFilterProxyModel, self).__init__(*args, **kwargs) + recursive_enabled = False + if hasattr(self, "setRecursiveFilteringEnabled"): + self.setRecursiveFilteringEnabled(True) + recursive_enabled = True + self._recursive_enabled = recursive_enabled + def filterAcceptsRow(self, row, parent_index): - if hasattr(self, "filterRegularExpression"): - regex = self.filterRegularExpression() - else: + if hasattr(self, "filterRegExp"): regex = self.filterRegExp() + else: + regex = self.filterRegularExpression() pattern = regex.pattern() if pattern: @@ -219,8 +228,9 @@ def filterAcceptsRow(self, row, parent_index): # Check current index itself value = model.data(source_index, self.filterRole()) - if re.search(pattern, value, re.IGNORECASE): - return True + matched = bool(re.search(pattern, value, re.IGNORECASE)) + if matched or self._recursive_enabled: + return matched rows = model.rowCount(source_index) for idx in range(rows): From d6555321ae38ba2bb2a41d46236415d1c8ec4cdf Mon Sep 17 00:00:00 2001 From: Ynbot Date: Mon, 13 Mar 2023 14:30:56 +0000 Subject: [PATCH 379/898] [Automated] Release --- CHANGELOG.md | 848 ++++++++++++++++++++++++++++++++++++++++++++ openpype/version.py | 2 +- pyproject.toml | 2 +- 3 files changed, 850 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7ecbc83bf0..145c2e2c1ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,854 @@ # Changelog +[Full Changelog](https://github.com/ynput/OpenPype/compare/3.15.1...3.15.2) + +### **🆕 New features** + + +
+maya gltf texture convertor and validator #4261 + +Continuity of the gltf extractor implementation + +Continuity of the gltf extractor https://github.com/pypeclub/OpenPype/pull/4192UPDATE:**Validator for GLSL Shader**: Validate whether the mesh uses GLSL Shader. If not it will error out. The user can choose to perform the repair action and it will help to assign glsl shader. If the mesh with Stringray PBS, the repair action will also check to see if there is any linked texture such as Color, Occulsion, and Normal Map. If yes, it will help to relink the related textures to the glsl shader.*****If the mesh uses the PBS Shader, + + +___ + +
+ + +
+Unreal: New Publisher #4370 + +Implementation of the new publisher for Unreal. + +The implementation of the new publisher for Unreal. This PR includes the changes for all the existing creators to be compatible with the new publisher.The basic creator has been split in two distinct creators: +- `UnrealAssetCreator`, works with assets in the Content Browser. +- `UnrealActorCreator` that works with actors in the scene. + + +___ + +
+ + +
+Implementation of a new splash screen #4592 + +Implemented a new splash screen widget to reflect a process running in the background. This widget can be used for other tasks than UE. **Also fixed the compilation error of the AssetContainer.cpp when trying to build the plugin in UE 5.0** + + +___ + +
+ + +
+Deadline for 3dsMax #4439 + +Setting up deadline for 3dsmax + +Setting up deadline for 3dsmax by setting render outputs and viewport camera + + +___ + +
+ + +
+Nuke: adding nukeassist #4494 + +Adding support for NukeAssist + +For support of NukeAssist we had to limit some Nuke features since NukeAssist itself Nuke with limitations. We do not support Creator and Publisher. User can only Load versions with version control. User can also set Framerange and Colorspace. + + +___ + +
+ +### **🚀 Enhancements** + + +
+Maya: OP-2630 acescg maya #4340 + +Resolves #2712 + + +___ + +
+ + +
+Default Ftrack Family on RenderLayer #4458 + +With default settings, renderlayers in Maya were not being tagged with the Ftrack family leading to confusion when doing reviews. + + +___ + +
+ + +
+Maya: Maya Playblast Options - OP-3783 #4487 + +Replacement PR for #3912. Adds more options for playblasts to preferences/settings. + +Adds the following as options in generating playblasts, matching viewport settings. +- Use default material +- Wireframe on shaded +- X-ray +- X-ray Joints +- X-ray active component + + +___ + +
+ + +
+Maya: Passing custom attributes to alembic - OP-4111 #4516 + +Passing custom attributes to alembic + +This PR makes it possible to pass all user defined attributes along to the alembic representation. + + +___ + +
+ + +
+Maya: Options for VrayProxy output - OP-2010 #4525 + +Options for output of VrayProxy. + +Client requested more granular control of output from VrayProxy instance. Exposed options on the instance and settings for vrmesh and alembic. + + +___ + +
+ + +
+Maya: Validate missing instance attributes #4559 + +Validate missing instance attributes. + +New attributes can be introduced as new features come in. Old instances will need to be updated with these attributes for the documentation to make sense, and users do not have to recreate the instances. + + +___ + +
+ + +
+Refactored Generation of UE Projects, installation of plugins moved to the engine #4369 + +Improved the way how OpenPype works with generation of UE projects. Also the installation of the plugin has been altered to install into the engine + +OpenPype now uses the appropriate tools to generate UE projects. Unreal Build Tool (UBT) and a "Commandlet Project" is needed to properly generate a BP project, or C++ code in case that `dev_mode = True`, folders, the .uproject file and many other resources.On the plugin's side, it is built seperately with the UnrealAutomationTool (UAT) and then it's contents are moved under the `Engine/Plugins/Marketplace/OpenPype` directory. + + +___ + +
+ + +
+Unreal: Use client functions in Layout loader #4578 + +Use 'get_representations' instead of 'legacy_io' query in layout loader. + +This is removing usage of `find_one` called on `legacy_io` and use rather client functions as preparation for AYON connection. Also all representations are queried at once instead of one by one. + + +___ + +
+ + +
+General: Support for extensions filtering in loaders #4492 + +Added extensions filtering support to loader plugins. + +To avoid possible backwards compatibility break is filtering exactly the same and filtering by extensions is enabled only if class attribute 'extensions' is set. + + +___ + +
+ + +
+Nuke: multiple reformat in baking review profiles #4514 + +Added support for multiple reformat nodes in baking profiles. + +Old settings for single reformat node is supported and prioritised just in case studios are using it and backward compatibility is needed. Warnings in Nuke terminal are notifying users to switch settings to new workflow. Settings are also explaining the migration way. + + +___ + +
+ + +
+Nuke: Add option to use new creating system in workfile template builder #4545 + +Nuke workfile template builder can use new creators instead of legacy creators. + +Modified workfile template builder to have option to say if legacy creators should be used or new creators. Legacy creators are disabled by default, so Maya has changed the value. + + +___ + +
+ + +
+Global, Nuke: Workfile first version with template processing #4579 + +Supporting new template workfile builder with toggle for creation of first version of workfile in case there is none yet. + + +___ + +
+ + +
+Fusion: New Publisher #4523 + +This is an updated PR for @BigRoy 's old PR (https://github.com/ynput/OpenPype/pull/3892).I have merged it with code from OP 3.15.1-nightly.6 and made sure it works as expected.This converts the old publishing system to the new one. It implements Fusion as a new host addon. + + +- Create button removed in OpenPype menu in favor of the new Publisher +- Draft refactor validations to raise PublishValidationError +- Implement Creator for New Publisher +- Implement Fusion as Host addon + + +___ + +
+ + +
+TVPaint: Use Publisher tool #4471 + +Use Publisher tool and new creation system in TVPaint integration. + +Using new creation system makes TVPaint integration a little bit easier to maintain for artists. Removed unneeded tools Creator and Subset Manager tools. Goal is to keep the integration work as close as possible to previous integration. Some changes were made but primarilly because they were not right using previous system.All creators create instance with final family instead of changing the family during extraction. Render passes are not related to group id but to render layer instance. Render layer is still related to group. Workfile, review and scene render instances are created using autocreators instead of auto-collection during publishing. Subset names are fully filled during publishing but instance labels are filled on refresh with the last known right value. Implemented basic of legacy convertor which should convert render layers and render passes. + + +___ + +
+ + +
+TVPaint: Auto-detect render creation #4496 + +Create plugin which will create Render Layer and Render Pass instances based on information in the scene. + +Added new creator that must be triggered by artist. The create plugin will first create Render Layer instances if were not created yet. For variant is used color group name. The creator has option to rename color groups by template defined in settings -> Template may use index of group by it's usage in scene (from bottom to top). After Render Layers will create Render Passes. Render Pass is created for each individual TVPaint layer in any group that had created Render Layer. It's name is used as variant (pass). + + +___ + +
+ + +
+TVPaint: Small enhancements #4501 + +Small enhancements in TVPaint integration which did not get to https://github.com/ynput/OpenPype/pull/4471. + +It was found out that `opacity` returned from `tv_layerinfo` is always empty and is dangerous to add it to layer information. Added information about "current" layer to layers information. Disable review of Render Layer and Render Pass instances by default. In most of productions is used only "scene review". Skip usage of `"enabled"` key from settings in automated layer/pass creation. + + +___ + +
+ + +
+Global: color v3 global oiio transcoder plugin #4291 + +Implements possibility to use `oiiotool` to transcode image sequences from one color space to another(s). + +Uses collected `colorspaceData` information about source color spaces, these information needs to be collected previously in each DCC interested in color management.Uses profiles configured in Settings to create single or multiple new representations (and file extensions) with different color spaces.New representations might replace existing one, each new representation might contain different tags and custom tags to control its integration step. + + +___ + +
+ + +
+Deadline: Added support for multiple install dirs in Deadline #4451 + +SearchDirectoryList returns FIRST existing so if you would have multiple OP install dirs, it won't search for appropriate version in later ones. + + +___ + +
+ + +
+Ftrack: Upload reviewables with original name #4483 + +Ftrack can integrate reviewables with original filenames. + +As ftrack have restrictions about names of components the only way how to achieve the result was to upload the same file twice, one with required name and one with origin name. + + +___ + +
+ + +
+TVPaint: Ignore transparency in Render Pass #4499 + +It is possible to ignore layers transparency during Render Pass extraction. + +Render pass extraction does not respect opacity of TVPaint layers set in scene during extraction. It can be enabled/disabled in settings. + + +___ + +
+ + +
+Anatomy: Preparation for different root overrides #4521 + +Prepare Anatomy to handle only 'studio' site override on it's own. + +Change how Anatomy fill root overrides based on requested site name. The logic which decide what is active site was moved to sync server addon and the same for receiving root overrides of local site. The Anatomy resolve only studio site overrides anything else is handled by sync server. BaseAnatomy only expect root overrides value and does not need site name. Validation of site name happens in sync server same as resolving if site name is local or not. + + +___ + +
+ + +
+Nuke | Global: colormanaged plugin in collection #4556 + +Colormanaged extractor had changed to Mixin class so it can be added to any stage of publishing rather then just to Exctracting.Nuke is no collecting colorspaceData to representation collected on already rendered images. + +Mixin class can no be used as secondary parent in publishing plugins. + + +___ + +
+ +### **🐛 Bug fixes** + + +
+look publishing and srgb colorspace in maya #4276 + +Check the OCIO color management is enabled before doing linearize colorspace for converting the texture maps into tx files. + +Check whether the OCIO color management is enabled before the condition of converting the texture to tx extension. + + +___ + +
+ + +
+Maya: extract Thumbnail "No active model panel found" - OP-3849 #4421 + +Error when extracting playblast with no model panel. + +If `project_settings/maya/publish/ExtractPlayblast/capture_preset/Viewport Options/override_viewport_options` were off and publishing without showing any model panel, the extraction would fail. + + +___ + +
+ + +
+Maya: Fix setting scene fps with float input #4488 + +Returned value of float fps on integer values would return float. + +This PR fixes the case when switching between integer fps values for example 24 > 25. Issue was when setting the scene fps, the original float value was used which makes it unpredictable whether the value is float or integer when mapping the fps values. + + +___ + +
+ + +
+Maya: Multipart fix #4497 + +Fix multipart logic in render products. + +Each renderer has a different way of defining whether output images is multipart, so we need to define it for each renderer. Also before the `multipart` class variable was defined multiple times in several places, which made it tricky to debug where `multipart` was defined. Now its created on initialization and referenced as `self.multipart` + + +___ + +
+ + +
+Maya: Set pool on tile assembly - OP-2012 #4520 + +Set pool on tile assembly + +Pool for publishing and tiling jobs, need to use the settings (`project_settings/deadline/publish/ProcessSubmittedJobOnFarm/deadline_pool`) else fallback on primary pool (`project_settings/deadline/publish/CollectDeadlinePools/primary_pool`) + + +___ + +
+ + +
+Maya: Extract review with handles #4527 + +Review was not extracting properly with/without handles. + +Review instance was not created properly resulting in the frame range on the instance including handles. + + +___ + +
+ + +
+Maya: Fix broken lib. #4529 + +Fix broken lib. + +This commit from this PR broke the Maya lib module. + + +___ + +
+ + +
+Maya: Validate model name - OP-4983 #4539 + +Validate model name issues. + +Couple of issues with validate model name; +- missing platform extraction from settings +- map function should be list comprehension +- code cosmetics + + +___ + +
+ + +
+Maya: SkeletalMesh family loadable as reference #4573 + +In Maya, fix the SkeletalMesh family not loadable as reference. + + +___ + +
+ + +
+Unreal: fix loaders because of missing AssetContainer #4536 + +Fixing Unreal loaders, where changes in OpenPype Unreal integration plugin deleted AssetContainer. + +`AssetContainer` and `AssetContainerFactory` are still used to mark loaded instances. Because of optimizations in Integration plugin we've accidentally removed them but that broke loader. + + +___ + +
+ + +
+3dsmax unable to delete loaded asset in the scene inventory #4507 + +Fix the bug of being unable to delete loaded asset in the Scene Inventory + +Fix the bug of being unable to delete loaded asset in the Scene Inventory + + +___ + +
+ + +
+Hiero/Nuke: originalBasename editorial publishing and loading #4453 + +Publishing and loading `originalBasename` is working as expected + +Frame-ranges on version document is now correctly defined to fit original media frame range which is published. It means loading is now correctly identifying frame start and end on clip loader in Nuke. + + +___ + +
+ + +
+Nuke: Fix workfile template placeholder creation #4512 + +Template placeholder creation was erroring out in Nuke due to the Workfile template builder not being able to find any of the plugins for the Nuke host. + +Move `get_workfile_build_placeholder_plugins` function to NukeHost class as workfile template builder expects. + + +___ + +
+ + +
+Nuke: creator farm attributes from deadline submit plugin settings #4519 + +Defaults in farm attributes are sourced from settings. + +Settings for deadline nuke submitter are now used during nuke render and prerender creator plugins. + + +___ + +
+ + +
+Nuke: fix clip sequence loading #4574 + +Nuke is loading correctly clip from image sequence created without "{originalBasename}" token in anatomy template. + + +___ + +
+ + +
+Fusion: Fix files collection and small bug-fixes #4423 + +Fixed Fusion review-representation and small bug-fixes + +This fixes the problem with review-file generation that stopped the publishing on second publish before the fix.The problem was that Fusion simply looked at all the files in the render-folder instead of only gathering the needed frames for the review.Also includes a fix to get the handle start/end that before throw an error if the data didn't exist (like from a kitsu sync). + + +___ + +
+ + +
+Fusion: Updated render_local.py to not only process the first instance #4522 + +Moved the `__hasRun` to `render_once()` so the check only happens with the rendering. Currently only the first render node gets the representations added.Critical PR + + +___ + +
+ + +
+Fusion: Load sequence fix filepath resolving from representation #4580 + +Resolves issue mentioned on discord by @movalex:The loader was incorrectly trying to find the file in the publish folder which resulted in just picking 'any first file'. + +This gets the filepath from representation instead of taking the first file from listing files from publish folder. + + +___ + +
+ + +
+Fusion: Fix review burnin start and end frame #4590 + +Fix the burnin start and end frame for reviews. Without this the asset document's start and end handle would've been added to the _burnin_ frame range even though that would've been incorrect since the handles are based on the comp saver's render range instead. + + +___ + +
+ + +
+Harmony: missing set of frame range when opening scene #4485 + +Frame range gets set from DB everytime scene is opened. + +Added also check for not up-to-date loaded containers. + + +___ + +
+ + +
+Photoshop: context is not changed in publisher #4570 + +When PS is already open and artists launch new task, it should keep only opened PS open, but change context. + +Problem were occurring in Workfile app where under new task files from old task were shown. This fixes this and adds opening of last workfile for new context if workfile exists. + + +___ + +
+ + +
+hiero: fix effect item node class #4543 + +Collected effect name after renaming is saving correct class name. + + +___ + +
+ + +
+Bugfix/OP-4616 vray multipart #4297 + +This fixes a bug where multipart vray renders would not make a review in Ftrack. + + +___ + +
+ + +
+Maya: Fix changed location of reset_frame_range #4491 + +Location in commands caused cyclic import + + +___ + +
+ + +
+global: source template fixed frame duplication #4503 + +Duplication is not happening. + +Template is using `originalBasename` which already assume all necessary elements are part of the file name so there was no need for additional optional name elements. + + +___ + +
+ + +
+Deadline: Hint to use Python 3 #4518 + +Added shebank to give deadline hint which python should be used. + +Deadline has issues with Python 2 (especially with `os.scandir`). When a shebank is added to file header deadline will use python 3 mode instead of python 2 which fix the issue. + + +___ + +
+ + +
+Publisher: Prevent access to create tab after publish start #4528 + +Prevent access to create tab after publish start. + +Disable create button in instance view on publish start and enable it again on reset. Even with that make sure that it is not possible to go to create tab if the tab is disabled. + + +___ + +
+ + +
+Color Transcoding: store target_colorspace as new colorspace #4544 + +When transcoding into new colorspace, representation must carry this information instead original color space. + + +___ + +
+ + +
+Deadline: fix submit_publish_job #4552 + +Fix submit_publish_job + +Resolves #4541 + + +___ + +
+ + +
+Kitsu: Fix task itteration in update-op-with-zou #4577 + +From the last PR (https://github.com/ynput/OpenPype/pull/4425) a comment-commit last second messed up the code and resulted in two lines being the same, crashing the script. This PR fixes that. +___ + +
+ + +
+AttrDefs: Fix type for PySide6 #4584 + +Use right type in signal emit for value change of attribute definitions. + +Changed `UUID` type to `str`. This is not an issue with PySide2 but it is with PySide6. + + +___ + +
+ +### **🔀 Refactored code** + + +
+Scene Inventory: Avoid using ObjectId #4524 + +Avoid using conversion to ObjectId type in scene inventory tool. + +Preparation for AYON compatibility where ObjectId won't be used for ids. Representation ids from loaded containers are not converted to ObjectId but kept as strings which also required some changes when working with representation documents. + + +___ + +
+ +### **Merged pull requests** + + +
+SiteSync: host dirmap is not working properly #4563 + +If artists uses SiteSync with real remote (gdrive, dropbox, sftp) drive, Local Settings were throwing error `string indices must be integers`. + +Logic was reworked to provide only `local_drive` values to be overrriden by Local Settings. If remote site is `gdrive` etc. mapping to `studio` is provided as it is expected that workfiles will have imported from `studio` location and not from `gdrive` folder.Also Nuke dirmap was reworked to be less verbose and much faster. + + +___ + +
+ + +
+General: Input representation ids are not ObjectIds #4576 + +Don't use `ObjectId` as representation ids during publishing. + +Representation ids are kept as strings during publishing instead of converting them to `ObjectId`. This change is pre-requirement for AYON connection.Inputs are used for integration of links and for farm publishing (or at least it looks like). + + +___ + +
+ + +
+Shotgrid: Fixes on Deadline submissions #4498 + +A few other bug fixes for getting Nuke submission to Deadline work smoothly using Shotgrid integration. + +Continuing on the work done on this other PR this fixes a few other bugs I came across with further tests. + + +___ + +
+ + +
+Fusion: New Publisher #3892 + +This converts the old publishing system to the new one. It implements Fusion as a new host addon. + + +- Create button removed in OpenPype menu in favor of the new Publisher +- Draft refactor validations to raise `PublishValidationError` +- Implement Creator for New Publisher +- Implement Fusion as Host addon + + +___ + +
+ + +
+Make Kitsu work with Tray Publisher, added kitsureview tag, fixed sync-problems. #4425 + +Make Kitsu work with Tray Publisher, added kitsureview tag, fixed sync-problems. + +This PR updates the way the module gather info for the current publish so it now works with Tray Publisher.It fixes the data that gets synced from Kitsu to OP so all needed data gets registered even if it doesn't exist on Kitsus side.It also adds the tag "Add review to Kitsu" and adds it to Burn In so previews gets generated by default to Kitsu. + + +___ + +
+ + +
+Maya: V-Ray Set Image Format from settings #4566 + +Resolves #4565 + +Set V-Ray Image Format using settings. + + +___ + +
+ + + + ## [3.15.1](https://github.com/ynput/OpenPype/tree/3.15.1) [Full Changelog](https://github.com/ynput/OpenPype/compare/3.15.0...3.15.1) diff --git a/openpype/version.py b/openpype/version.py index e8124f14663..6ab03c2121f 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.15.2-nightly.6" +__version__ = "3.15.2" diff --git a/pyproject.toml b/pyproject.toml index 2fc4f6fe390..02370a4f10d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "OpenPype" -version = "3.15.1" # OpenPype +version = "3.15.2" # OpenPype description = "Open VFX and Animation pipeline with support." authors = ["OpenPype Team "] license = "MIT License" From ff19ae038519d1ccf85e4145c66e416609a94edf Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 13 Mar 2023 15:37:23 +0100 Subject: [PATCH 380/898] Added setup_only to tests (#4591) Allows to download test zip, unzip and restore DB in preparation for new test. --- openpype/cli.py | 8 ++++++-- openpype/pype_commands.py | 5 ++++- tests/conftest.py | 10 ++++++++++ tests/lib/testing_classes.py | 22 +++++++++++++++++++--- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/openpype/cli.py b/openpype/cli.py index 5c47088a44f..a650a9fdcc7 100644 --- a/openpype/cli.py +++ b/openpype/cli.py @@ -367,11 +367,15 @@ def run(script): "--timeout", help="Provide specific timeout value for test case", default=None) +@click.option("-so", + "--setup_only", + help="Only create dbs, do not run tests", + default=None) def runtests(folder, mark, pyargs, test_data_folder, persist, app_variant, - timeout): + timeout, setup_only): """Run all automatic tests after proper initialization via start.py""" PypeCommands().run_tests(folder, mark, pyargs, test_data_folder, - persist, app_variant, timeout) + persist, app_variant, timeout, setup_only) @main.command() diff --git a/openpype/pype_commands.py b/openpype/pype_commands.py index 932fdc9be41..dc5b3d63c32 100644 --- a/openpype/pype_commands.py +++ b/openpype/pype_commands.py @@ -270,7 +270,7 @@ def validate_jsons(self): pass def run_tests(self, folder, mark, pyargs, - test_data_folder, persist, app_variant, timeout): + test_data_folder, persist, app_variant, timeout, setup_only): """ Runs tests from 'folder' @@ -311,6 +311,9 @@ def run_tests(self, folder, mark, pyargs, if timeout: args.extend(["--timeout", timeout]) + if setup_only: + args.extend(["--setup_only", setup_only]) + print("run_tests args: {}".format(args)) import pytest pytest.main(args) diff --git a/tests/conftest.py b/tests/conftest.py index 7b58b0314dd..4f7c17244b3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -24,6 +24,11 @@ def pytest_addoption(parser): help="Overwrite default timeout" ) + parser.addoption( + "--setup_only", action="store", default=None, + help="True - only setup test, do not run any tests" + ) + @pytest.fixture(scope="module") def test_data_folder(request): @@ -45,6 +50,11 @@ def timeout(request): return request.config.getoption("--timeout") +@pytest.fixture(scope="module") +def setup_only(request): + return request.config.getoption("--setup_only") + + @pytest.hookimpl(tryfirst=True, hookwrapper=True) def pytest_runtest_makereport(item, call): # execute all other hooks to obtain the report object diff --git a/tests/lib/testing_classes.py b/tests/lib/testing_classes.py index 2bafa169714..300024dc984 100644 --- a/tests/lib/testing_classes.py +++ b/tests/lib/testing_classes.py @@ -243,6 +243,8 @@ class PublishTest(ModuleUnitTest): PERSIST = True # True - keep test_db, test_openpype, outputted test files TEST_DATA_FOLDER = None # use specific folder of unzipped test file + SETUP_ONLY = False + @pytest.fixture(scope="module") def app_name(self, app_variant): """Returns calculated value for ApplicationManager. Eg.(nuke/12-2)""" @@ -286,8 +288,13 @@ def app_args(self, download_test_data): @pytest.fixture(scope="module") def launched_app(self, dbcon, download_test_data, last_workfile_path, - startup_scripts, app_args, app_name, output_folder_url): + startup_scripts, app_args, app_name, output_folder_url, + setup_only): """Launch host app""" + if setup_only or self.SETUP_ONLY: + print("Creating only setup for test, not launching app") + yield + return # set schema - for integrate_new from openpype import PACKAGE_DIR # Path to OpenPype's schema @@ -316,8 +323,12 @@ def launched_app(self, dbcon, download_test_data, last_workfile_path, @pytest.fixture(scope="module") def publish_finished(self, dbcon, launched_app, download_test_data, - timeout): + timeout, setup_only): """Dummy fixture waiting for publish to finish""" + if setup_only or self.SETUP_ONLY: + print("Creating only setup for test, not launching app") + yield False + return import time time_start = time.time() timeout = timeout or self.TIMEOUT @@ -334,11 +345,16 @@ def publish_finished(self, dbcon, launched_app, download_test_data, def test_folder_structure_same(self, dbcon, publish_finished, download_test_data, output_folder_url, - skip_compare_folders): + skip_compare_folders, + setup_only): """Check if expected and published subfolders contain same files. Compares only presence, not size nor content! """ + if setup_only or self.SETUP_ONLY: + print("Creating only setup for test, not launching app") + return + published_dir_base = output_folder_url expected_dir_base = os.path.join(download_test_data, "expected") From 24a22e964a4de4481c9896eca2ebc5ebf75adabd Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 13 Mar 2023 16:27:33 +0100 Subject: [PATCH 381/898] Nuke: fix families mixing up with old way. --- .../deadline/plugins/publish/submit_nuke_deadline.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py index aff34c7e4a8..9abe8dec8b1 100644 --- a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py @@ -32,7 +32,7 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin, label = "Submit Nuke to Deadline" order = pyblish.api.IntegratorOrder + 0.1 hosts = ["nuke"] - families = ["render", "prerender.farm"] + families = ["render", "prerender"] optional = True targets = ["local"] @@ -80,6 +80,9 @@ def get_attribute_defs(cls): ] def process(self, instance): + if not instance.data.get("farm"): + return + instance.data["attributeValues"] = self.get_attr_values_from_data( instance.data) @@ -168,10 +171,10 @@ def process(self, instance): resp.json()["_id"]) # redefinition of families - if "render.farm" in families: + if "render" in family: instance.data['family'] = 'write' families.insert(0, "render2d") - elif "prerender.farm" in families: + elif "prerender" in family: instance.data['family'] = 'write' families.insert(0, "prerender") instance.data["families"] = families From 5d17ae2857b00bec100442957cdf1ae1164a39ca Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 11 Mar 2023 07:32:44 +0100 Subject: [PATCH 382/898] Houdini: Create button open new publisher's "create" tab Also made publish button enforce going to the "publish" tab. --- openpype/hosts/houdini/startup/MainMenuCommon.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/houdini/startup/MainMenuCommon.xml b/openpype/hosts/houdini/startup/MainMenuCommon.xml index c08114b71bc..8e24ce3b99c 100644 --- a/openpype/hosts/houdini/startup/MainMenuCommon.xml +++ b/openpype/hosts/houdini/startup/MainMenuCommon.xml @@ -10,7 +10,7 @@ import hou from openpype.tools.utils import host_tools parent = hou.qt.mainWindow() -host_tools.show_creator(parent) +host_tools.show_publisher(parent, tab="create") ]]>
@@ -30,7 +30,7 @@ host_tools.show_loader(parent=parent, use_context=True) import hou from openpype.tools.utils import host_tools parent = hou.qt.mainWindow() -host_tools.show_publisher(parent) +host_tools.show_publisher(parent, tab="publish") ]]>
From ed7a4e424368a7503eb024ceea7b35be9f8bc6d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Mar 2023 14:32:06 +0000 Subject: [PATCH 383/898] Bump @sideway/formula from 3.0.0 to 3.0.1 in /website Bumps [@sideway/formula](https://github.com/sideway/formula) from 3.0.0 to 3.0.1. - [Release notes](https://github.com/sideway/formula/releases) - [Commits](https://github.com/sideway/formula/compare/v3.0.0...v3.0.1) --- updated-dependencies: - dependency-name: "@sideway/formula" dependency-type: indirect ... Signed-off-by: dependabot[bot] --- website/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/yarn.lock b/website/yarn.lock index 559c58f9314..d250e48b9da 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -1669,9 +1669,9 @@ "@hapi/hoek" "^9.0.0" "@sideway/formula@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c" - integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg== + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" + integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== "@sideway/pinpoint@^2.0.0": version "2.0.0" From 0483714dcb55f2f7b2db5892c640ef6b673f393f Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Mon, 13 Mar 2023 17:49:44 +0100 Subject: [PATCH 384/898] Change "Maya" to Fusion in comment --- openpype/hosts/fusion/api/action.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/fusion/api/action.py b/openpype/hosts/fusion/api/action.py index 17509209504..ff5dd14caa3 100644 --- a/openpype/hosts/fusion/api/action.py +++ b/openpype/hosts/fusion/api/action.py @@ -6,12 +6,13 @@ class SelectInvalidAction(pyblish.api.Action): - """Select invalid nodes in Maya when plug-in failed. + """Select invalid nodes in Fusion when plug-in failed. To retrieve the invalid nodes this assumes a static `get_invalid()` method is available on the plugin. """ + label = "Select invalid" on = "failed" # This action is only available on a failed plug-in icon = "search" # Icon from Awesome Icon @@ -31,8 +32,10 @@ def process(self, context, plugin): if isinstance(invalid_nodes, (list, tuple)): invalid.extend(invalid_nodes) else: - self.log.warning("Plug-in returned to be invalid, " - "but has no selectable nodes.") + self.log.warning( + "Plug-in returned to be invalid, " + "but has no selectable nodes." + ) if not invalid: # Assume relevant comp is current comp and clear selection @@ -51,4 +54,6 @@ def process(self, context, plugin): for tool in invalid: flow.Select(tool, True) names.add(tool.Name) - self.log.info("Selecting invalid tools: %s" % ", ".join(sorted(names))) + self.log.info( + "Selecting invalid tools: %s" % ", ".join(sorted(names)) + ) From ea7390d1d3e91385cd7f723c3067cebabf5cca03 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Mon, 13 Mar 2023 17:50:56 +0100 Subject: [PATCH 385/898] Added create and instance attr to Create plugin Where they get it from should be moved into another folder so other plugins can get the same data. --- .../fusion/plugins/create/create_saver.py | 81 +++++++++++++------ 1 file changed, 55 insertions(+), 26 deletions(-) diff --git a/openpype/hosts/fusion/plugins/create/create_saver.py b/openpype/hosts/fusion/plugins/create/create_saver.py index e581bac20ff..56085b0a06b 100644 --- a/openpype/hosts/fusion/plugins/create/create_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_saver.py @@ -4,29 +4,34 @@ from openpype.hosts.fusion.api import ( get_current_comp, - comp_lock_and_undo_chunk + comp_lock_and_undo_chunk, ) -from openpype.lib import BoolDef +from openpype.lib import ( + BoolDef, + EnumDef, +) from openpype.pipeline import ( legacy_io, Creator, - CreatedInstance + CreatedInstance, +) +from openpype.client import ( + get_asset_by_name, ) -from openpype.client import get_asset_by_name class CreateSaver(Creator): identifier = "io.openpype.creators.fusion.saver" - name = "saver" - label = "Saver" + label = "Render (saver)" + name = "render" family = "render" - default_variants = ["Main"] - + default_variants = ["Main", "Mask"] description = "Fusion Saver to generate image sequence" - def create(self, subset_name, instance_data, pre_create_data): + instance_attributes = ["reviewable"] + def create(self, subset_name, instance_data, pre_create_data): # TODO: Add pre_create attributes to choose file format? file_format = "OpenEXRFormat" @@ -58,7 +63,8 @@ def create(self, subset_name, instance_data, pre_create_data): family=self.family, subset_name=subset_name, data=instance_data, - creator=self) + creator=self, + ) # Insert the transient data instance.transient_data["tool"] = saver @@ -68,11 +74,9 @@ def create(self, subset_name, instance_data, pre_create_data): return instance def collect_instances(self): - comp = get_current_comp() tools = comp.GetToolList(False, "Saver").values() for tool in tools: - data = self.get_managed_tool_data(tool) if not data: data = self._collect_unmanaged_saver(tool) @@ -90,7 +94,6 @@ def get_icon(self): def update_instances(self, update_list): for created_inst, _changes in update_list: - new_data = created_inst.data_to_store() tool = created_inst.transient_data["tool"] self._update_tool_with_data(tool, new_data) @@ -139,7 +142,6 @@ def _update_tool_with_data(self, tool, data): tool.SetAttrs({"TOOLS_Name": subset}) def _collect_unmanaged_saver(self, tool): - # TODO: this should not be done this way - this should actually # get the data as stored on the tool explicitly (however) # that would disallow any 'regular saver' to be collected @@ -153,8 +155,7 @@ def _collect_unmanaged_saver(self, tool): asset = legacy_io.Session["AVALON_ASSET"] task = legacy_io.Session["AVALON_TASK"] - asset_doc = get_asset_by_name(project_name=project, - asset_name=asset) + asset_doc = get_asset_by_name(project_name=project, asset_name=asset) path = tool["Clip"][comp.TIME_UNDEFINED] fname = os.path.basename(path) @@ -178,21 +179,20 @@ def _collect_unmanaged_saver(self, tool): "variant": variant, "active": not passthrough, "family": self.family, - # Unique identifier for instance and this creator "id": "pyblish.avalon.instance", - "creator_identifier": self.identifier + "creator_identifier": self.identifier, } def get_managed_tool_data(self, tool): """Return data of the tool if it matches creator identifier""" - data = tool.GetData('openpype') + data = tool.GetData("openpype") if not isinstance(data, dict): return required = { "id": "pyblish.avalon.instance", - "creator_identifier": self.identifier + "creator_identifier": self.identifier, } for key, value in required.items(): if key not in data or data[key] != value: @@ -205,11 +205,40 @@ def get_managed_tool_data(self, tool): return data + def get_pre_create_attr_defs(self): + """Settings for create page""" + attr_defs = [ + self._get_render_target_enum(), + self._get_reviewable_bool(), + ] + return attr_defs + def get_instance_attr_defs(self): - return [ - BoolDef( - "review", - default=True, - label="Review" - ) + """Settings for publish page""" + attr_defs = [ + self._get_render_target_enum(), + self._get_reviewable_bool(), ] + return attr_defs + + # These functions below should be moved to another file + # so it can be used by other plugins. plugin.py ? + + def _get_render_target_enum(self): + rendering_targets = { + "local": "Local machine rendering", + "frames": "Use existing frames", + } + if "farm_rendering" in self.instance_attributes: + rendering_targets["farm"] = "Farm rendering" + + return EnumDef( + "render_target", items=rendering_targets, label="Render target" + ) + + def _get_reviewable_bool(self): + return BoolDef( + "review", + default=("reviewable" in self.instance_attributes), + label="Review", + ) From 0414045f362bdd6c2ecfeb5851b82f129de4f710 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Mon, 13 Mar 2023 17:54:02 +0100 Subject: [PATCH 386/898] Split the render into render and review data --- .../plugins/publish/collect_render_target.py | 44 --------------- .../fusion/plugins/publish/collect_renders.py | 42 ++++++++++++++ ...ender_local.py => extract_render_local.py} | 46 ++-------------- .../plugins/publish/extract_review_data.py | 55 +++++++++++++++++++ 4 files changed, 102 insertions(+), 85 deletions(-) delete mode 100644 openpype/hosts/fusion/plugins/publish/collect_render_target.py create mode 100644 openpype/hosts/fusion/plugins/publish/collect_renders.py rename openpype/hosts/fusion/plugins/publish/{render_local.py => extract_render_local.py} (59%) create mode 100644 openpype/hosts/fusion/plugins/publish/extract_review_data.py diff --git a/openpype/hosts/fusion/plugins/publish/collect_render_target.py b/openpype/hosts/fusion/plugins/publish/collect_render_target.py deleted file mode 100644 index 39017f32e02..00000000000 --- a/openpype/hosts/fusion/plugins/publish/collect_render_target.py +++ /dev/null @@ -1,44 +0,0 @@ -import pyblish.api - - -class CollectFusionRenderMode(pyblish.api.InstancePlugin): - """Collect current comp's render Mode - - Options: - local - farm - - Note that this value is set for each comp separately. When you save the - comp this information will be stored in that file. If for some reason the - available tool does not visualize which render mode is set for the - current comp, please run the following line in the console (Py2) - - comp.GetData("openpype.rendermode") - - This will return the name of the current render mode as seen above under - Options. - - """ - - order = pyblish.api.CollectorOrder + 0.4 - label = "Collect Render Mode" - hosts = ["fusion"] - families = ["render"] - - def process(self, instance): - """Collect all image sequence tools""" - options = ["local", "farm"] - - comp = instance.context.data.get("currentComp") - if not comp: - raise RuntimeError("No comp previously collected, unable to " - "retrieve Fusion version.") - - rendermode = comp.GetData("openpype.rendermode") or "local" - assert rendermode in options, "Must be supported render mode" - - self.log.info("Render mode: {0}".format(rendermode)) - - # Append family - family = "render.{0}".format(rendermode) - instance.data["families"].append(family) diff --git a/openpype/hosts/fusion/plugins/publish/collect_renders.py b/openpype/hosts/fusion/plugins/publish/collect_renders.py new file mode 100644 index 00000000000..cdd37b3b653 --- /dev/null +++ b/openpype/hosts/fusion/plugins/publish/collect_renders.py @@ -0,0 +1,42 @@ +import pyblish.api +from pprint import pformat + + +class CollectFusionRenders(pyblish.api.InstancePlugin): + """Collect current comp's render Mode + + Options: + local + farm + + Note that this value is set for each comp separately. When you save the + comp this information will be stored in that file. If for some reason the + available tool does not visualize which render mode is set for the + current comp, please run the following line in the console (Py2) + + comp.GetData("openpype.rendermode") + + This will return the name of the current render mode as seen above under + Options. + + """ + + order = pyblish.api.CollectorOrder + 0.4 + label = "Collect Renders" + hosts = ["fusion"] + families = ["render"] + + def process(self, instance): + self.log.debug(pformat(instance.data)) + + saver_node = instance.data["transientData"]["tool"] + render_target = instance.data["render_target"] + family = instance.data["family"] + families = instance.data["families"] + + # add targeted family to families + instance.data["families"].append( + "{}.{}".format(family, render_target) + ) + + self.log.debug(pformat(instance.data)) diff --git a/openpype/hosts/fusion/plugins/publish/render_local.py b/openpype/hosts/fusion/plugins/publish/extract_render_local.py similarity index 59% rename from openpype/hosts/fusion/plugins/publish/render_local.py rename to openpype/hosts/fusion/plugins/publish/extract_render_local.py index 7d5f1a40c72..62625c899a9 100644 --- a/openpype/hosts/fusion/plugins/publish/render_local.py +++ b/openpype/hosts/fusion/plugins/publish/extract_render_local.py @@ -4,16 +4,12 @@ from openpype.hosts.fusion.api import comp_lock_and_undo_chunk -class Fusionlocal(pyblish.api.InstancePlugin, - publish.ColormanagedPyblishPluginMixin): - """Render the current Fusion composition locally. +class FusionRenderLocal( + pyblish.api.InstancePlugin, publish.ColormanagedPyblishPluginMixin +): + """Render the current Fusion composition locally.""" - Extract the result of savers by starting a comp render - This will run the local render of Fusion. - - """ - - order = pyblish.api.ExtractorOrder - 0.1 + order = pyblish.api.ExtractorOrder - 0.2 label = "Render Local" hosts = ["fusion"] families = ["render.local"] @@ -33,38 +29,6 @@ def process(self, instance): ) ) - frame_start = context.data["frameStartHandle"] - frame_end = context.data["frameEndHandle"] - path = instance.data["path"] - output_dir = instance.data["outputDir"] - - basename = os.path.basename(path) - head, ext = os.path.splitext(basename) - files = [ - f"{head}{str(frame).zfill(4)}{ext}" - for frame in range(frame_start, frame_end + 1) - ] - repre = { - "name": ext[1:], - "ext": ext[1:], - "frameStart": f"%0{len(str(frame_end))}d" % frame_start, - "files": files, - "stagingDir": output_dir, - } - - self.set_representation_colorspace( - representation=repre, - context=context, - ) - - if "representations" not in instance.data: - instance.data["representations"] = [] - instance.data["representations"].append(repre) - - # review representation - if instance.data.get("review", False): - repre["tags"] = ["review", "ftrackreview"] - def render_once(self, context): """Render context comp only once, even with more render instances""" diff --git a/openpype/hosts/fusion/plugins/publish/extract_review_data.py b/openpype/hosts/fusion/plugins/publish/extract_review_data.py new file mode 100644 index 00000000000..d9416771f63 --- /dev/null +++ b/openpype/hosts/fusion/plugins/publish/extract_review_data.py @@ -0,0 +1,55 @@ +import os +import pyblish.api +from openpype.pipeline.publish import ( + ColormanagedPyblishPluginMixin, +) + + +class FusionExtractReviewData( + pyblish.api.InstancePlugin, ColormanagedPyblishPluginMixin +): + """ + Extract the result of savers by starting a comp render + This will run the local render of Fusion. + """ + + order = pyblish.api.ExtractorOrder - 0.1 + label = "Extract Review Data" + hosts = ["fusion"] + families = ["review"] + + def process(self, instance): + context = instance.context + + frame_start = context.data["frameStartHandle"] + frame_end = context.data["frameEndHandle"] + path = instance.data["path"] + output_dir = instance.data["outputDir"] + + basename = os.path.basename(path) + head, ext = os.path.splitext(basename) + files = [ + f"{head}{str(frame).zfill(4)}{ext}" + for frame in range(frame_start, frame_end + 1) + ] + repre = { + "name": ext[1:], + "ext": ext[1:], + "frameStart": f"%0{len(str(frame_end))}d" % frame_start, + "files": files, + "stagingDir": output_dir, + } + + self.set_representation_colorspace( + representation=repre, + context=context, + ) + + # review representation + if instance.data.get("review", False): + repre["tags"] = ["review"] + + # add the repre to the instance + if "representations" not in instance.data: + instance.data["representations"] = [] + instance.data["representations"].append(repre) From ba8d03715229693745ef5df4525c6eb0fc156bf2 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Mon, 13 Mar 2023 17:54:47 +0100 Subject: [PATCH 387/898] Validate that frames for "use existing frames" do exist --- .../validate_local_frames_existence.py | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 openpype/hosts/fusion/plugins/publish/validate_local_frames_existence.py diff --git a/openpype/hosts/fusion/plugins/publish/validate_local_frames_existence.py b/openpype/hosts/fusion/plugins/publish/validate_local_frames_existence.py new file mode 100644 index 00000000000..d80e11e078d --- /dev/null +++ b/openpype/hosts/fusion/plugins/publish/validate_local_frames_existence.py @@ -0,0 +1,71 @@ +import os +import pyblish.api + +from openpype.pipeline.publish import RepairAction +from openpype.pipeline import PublishValidationError + +from openpype.hosts.fusion.api.action import SelectInvalidAction + + +class ValidateLocalFramesExistence(pyblish.api.InstancePlugin): + """Checks if files for savers that's set to publish existing frames exists""" + + order = pyblish.api.ValidatorOrder + label = "Validate Existing Frames Exists" + families = ["render"] + hosts = ["fusion"] + actions = [RepairAction, SelectInvalidAction] + + @classmethod + def get_invalid(cls, instance): + active = instance.data.get("active", instance.data.get("publish")) + if not active: + return [] + + if instance.data.get("render_target") == "frames": + tool = instance[0] + + frame_start = instance.data["frameStart"] + frame_end = instance.data["frameEnd"] + path = instance.data["path"] + output_dir = instance.data["outputDir"] + + basename = os.path.basename(path) + head, ext = os.path.splitext(basename) + files = [ + f"{head}{str(frame).zfill(4)}{ext}" + for frame in range(frame_start, frame_end + 1) + ] + + non_existing_frames = [] + + for file in files: + cls.log.error(file) + if not os.path.exists(os.path.join(output_dir, file)): + non_existing_frames.append(file) + + if len(non_existing_frames) > 0: + cls.log.error( + "Some of {}'s files does not exist".format(tool.Name) + ) + return [tool, output_dir, non_existing_frames] + + def process(self, instance): + invalid = self.get_invalid(instance) + if invalid: + raise PublishValidationError( + "{} is set to publish existing frames but " + "some frames are missing in the folder:\n\n{}" + "The missing file(s) are:\n\n{}".format( + invalid[0].Name, + invalid[1], + "\n\n".join(invalid[2]), + ), + title=self.label, + ) + + @classmethod + def repair(cls, instance): + invalid = cls.get_invalid(instance) + for tool in invalid: + tool.SetInput("CreateDir", 1.0) From a15e29afaf5ff8e78296f36cea9f06d036e1cccf Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Mon, 13 Mar 2023 17:55:04 +0100 Subject: [PATCH 388/898] Fixed repair-button to show up on review tab --- .../plugins/publish/validate_create_folder_checked.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py b/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py index ba943abacb0..53dea2af712 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py +++ b/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py @@ -14,11 +14,10 @@ class ValidateCreateFolderChecked(pyblish.api.InstancePlugin): """ order = pyblish.api.ValidatorOrder - actions = [RepairAction] label = "Validate Create Folder Checked" families = ["render"] hosts = ["fusion"] - actions = [SelectInvalidAction] + actions = [RepairAction, SelectInvalidAction] @classmethod def get_invalid(cls, instance): @@ -29,7 +28,9 @@ def get_invalid(cls, instance): tool = instance[0] create_dir = tool.GetInput("CreateDir") if create_dir == 0.0: - cls.log.error("%s has Create Folder turned off" % instance[0].Name) + cls.log.error( + "%s has Create Folder turned off" % instance[0].Name + ) return [tool] def process(self, instance): @@ -37,7 +38,8 @@ def process(self, instance): if invalid: raise PublishValidationError( "Found Saver with Create Folder During Render checked off", - title=self.label) + title=self.label, + ) @classmethod def repair(cls, instance): From 73b6ee58ae61b6ee88d6cd6bd28f78c6610220f1 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Mon, 13 Mar 2023 17:57:09 +0100 Subject: [PATCH 389/898] Remove old Render Mode menu --- openpype/hosts/fusion/api/menu.py | 12 -- .../hosts/fusion/scripts/set_rendermode.py | 112 ------------------ 2 files changed, 124 deletions(-) delete mode 100644 openpype/hosts/fusion/scripts/set_rendermode.py diff --git a/openpype/hosts/fusion/api/menu.py b/openpype/hosts/fusion/api/menu.py index 343f5f803ad..ba3ce6798d7 100644 --- a/openpype/hosts/fusion/api/menu.py +++ b/openpype/hosts/fusion/api/menu.py @@ -60,7 +60,6 @@ def __init__(self, *args, **kwargs): publish_btn = QtWidgets.QPushButton("Publish...", self) manager_btn = QtWidgets.QPushButton("Manage...", self) libload_btn = QtWidgets.QPushButton("Library...", self) - rendermode_btn = QtWidgets.QPushButton("Set render mode...", self) set_framerange_btn = QtWidgets.QPushButton("Set Frame Range", self) set_resolution_btn = QtWidgets.QPushButton("Set Resolution", self) duplicate_with_inputs_btn = QtWidgets.QPushButton( @@ -91,7 +90,6 @@ def __init__(self, *args, **kwargs): layout.addWidget(set_framerange_btn) layout.addWidget(set_resolution_btn) - layout.addWidget(rendermode_btn) layout.addSpacing(20) @@ -108,7 +106,6 @@ def __init__(self, *args, **kwargs): load_btn.clicked.connect(self.on_load_clicked) manager_btn.clicked.connect(self.on_manager_clicked) libload_btn.clicked.connect(self.on_libload_clicked) - rendermode_btn.clicked.connect(self.on_rendermode_clicked) duplicate_with_inputs_btn.clicked.connect( self.on_duplicate_with_inputs_clicked ) @@ -162,15 +159,6 @@ def on_manager_clicked(self): def on_libload_clicked(self): host_tools.show_library_loader() - def on_rendermode_clicked(self): - if self.render_mode_widget is None: - window = set_rendermode.SetRenderMode() - window.setStyleSheet(load_stylesheet()) - window.show() - self.render_mode_widget = window - else: - self.render_mode_widget.show() - def on_duplicate_with_inputs_clicked(self): duplicate_with_inputs.duplicate_with_input_connections() diff --git a/openpype/hosts/fusion/scripts/set_rendermode.py b/openpype/hosts/fusion/scripts/set_rendermode.py deleted file mode 100644 index 9d2bfef3107..00000000000 --- a/openpype/hosts/fusion/scripts/set_rendermode.py +++ /dev/null @@ -1,112 +0,0 @@ -from qtpy import QtWidgets -import qtawesome -from openpype.hosts.fusion.api import get_current_comp - - -_help = {"local": "Render the comp on your own machine and publish " - "it from that the destination folder", - "farm": "Submit a Fusion render job to a Render farm to use all other" - " computers and add a publish job"} - - -class SetRenderMode(QtWidgets.QWidget): - - def __init__(self, parent=None): - QtWidgets.QWidget.__init__(self, parent) - - self._comp = get_current_comp() - self._comp_name = self._get_comp_name() - - self.setWindowTitle("Set Render Mode") - self.setFixedSize(300, 175) - - layout = QtWidgets.QVBoxLayout() - - # region comp info - comp_info_layout = QtWidgets.QHBoxLayout() - - update_btn = QtWidgets.QPushButton(qtawesome.icon("fa.refresh", - color="white"), "") - update_btn.setFixedWidth(25) - update_btn.setFixedHeight(25) - - comp_information = QtWidgets.QLineEdit() - comp_information.setEnabled(False) - - comp_info_layout.addWidget(comp_information) - comp_info_layout.addWidget(update_btn) - # endregion comp info - - # region modes - mode_options = QtWidgets.QComboBox() - mode_options.addItems(_help.keys()) - - mode_information = QtWidgets.QTextEdit() - mode_information.setReadOnly(True) - # endregion modes - - accept_btn = QtWidgets.QPushButton("Accept") - - layout.addLayout(comp_info_layout) - layout.addWidget(mode_options) - layout.addWidget(mode_information) - layout.addWidget(accept_btn) - - self.setLayout(layout) - - self.comp_information = comp_information - self.update_btn = update_btn - - self.mode_options = mode_options - self.mode_information = mode_information - - self.accept_btn = accept_btn - - self.connections() - self.update() - - # Force updated render mode help text - self._update_rendermode_info() - - def connections(self): - """Build connections between code and buttons""" - - self.update_btn.clicked.connect(self.update) - self.accept_btn.clicked.connect(self._set_comp_rendermode) - self.mode_options.currentIndexChanged.connect( - self._update_rendermode_info) - - def update(self): - """Update all information in the UI""" - - self._comp = get_current_comp() - self._comp_name = self._get_comp_name() - self.comp_information.setText(self._comp_name) - - # Update current comp settings - mode = self._get_comp_rendermode() - index = self.mode_options.findText(mode) - self.mode_options.setCurrentIndex(index) - - def _update_rendermode_info(self): - rendermode = self.mode_options.currentText() - self.mode_information.setText(_help[rendermode]) - - def _get_comp_name(self): - return self._comp.GetAttrs("COMPS_Name") - - def _get_comp_rendermode(self): - return self._comp.GetData("openpype.rendermode") or "local" - - def _set_comp_rendermode(self): - rendermode = self.mode_options.currentText() - self._comp.SetData("openpype.rendermode", rendermode) - - self._comp.Print("Updated render mode to '%s'\n" % rendermode) - self.hide() - - def _validation(self): - ui_mode = self.mode_options.currentText() - comp_mode = self._get_comp_rendermode() - - return comp_mode == ui_mode From 075ea125894262ad87597f46e78d3f54e8997d13 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Mon, 13 Mar 2023 18:01:33 +0100 Subject: [PATCH 390/898] Remove reference to set_rendermode (forgot to delete it in last push) --- openpype/hosts/fusion/api/menu.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/fusion/api/menu.py b/openpype/hosts/fusion/api/menu.py index ba3ce6798d7..92f38a64c2a 100644 --- a/openpype/hosts/fusion/api/menu.py +++ b/openpype/hosts/fusion/api/menu.py @@ -6,7 +6,6 @@ from openpype.style import load_stylesheet from openpype.lib import register_event_callback from openpype.hosts.fusion.scripts import ( - set_rendermode, duplicate_with_inputs, ) from openpype.hosts.fusion.api.lib import ( From ee7e2f1bcd4cc7d13935482b5f3ec1f1cf41347e Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 13 Mar 2023 23:00:03 +0100 Subject: [PATCH 391/898] Update tests and documentation for `ExtractorColormanaged` refactor to `ColormanagedPyblishPluginMixin` --- .../unit/openpype/pipeline/publish/test_publish_plugins.py | 6 +++--- website/docs/dev_colorspace.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/unit/openpype/pipeline/publish/test_publish_plugins.py b/tests/unit/openpype/pipeline/publish/test_publish_plugins.py index 5c2d7b367f6..88e0095e340 100644 --- a/tests/unit/openpype/pipeline/publish/test_publish_plugins.py +++ b/tests/unit/openpype/pipeline/publish/test_publish_plugins.py @@ -135,7 +135,7 @@ def test_get_colorspace_settings(self, context, config_path_asset): } # load plugin function for testing - plugin = publish_plugins.ExtractorColormanaged() + plugin = publish_plugins.ColormanagedPyblishPluginMixin() plugin.log = log config_data, file_rules = plugin.get_colorspace_settings(context) @@ -175,14 +175,14 @@ def test_set_representation_colorspace( } # load plugin function for testing - plugin = publish_plugins.ExtractorColormanaged() + plugin = publish_plugins.ColormanagedPyblishPluginMixin() plugin.log = log plugin.set_representation_colorspace( representation_nuke, context, colorspace_settings=(config_data_nuke, file_rules_nuke) ) # load plugin function for testing - plugin = publish_plugins.ExtractorColormanaged() + plugin = publish_plugins.ColormanagedPyblishPluginMixin() plugin.log = log plugin.set_representation_colorspace( representation_hiero, context, diff --git a/website/docs/dev_colorspace.md b/website/docs/dev_colorspace.md index fe9a0ec1e38..14f19f10dba 100644 --- a/website/docs/dev_colorspace.md +++ b/website/docs/dev_colorspace.md @@ -63,7 +63,7 @@ It's up to the Loaders to read these values and apply the correct expected color - set the `OCIO` environment variable before launching the host via a prelaunch hook - or (if the host allows) to set the workfile OCIO config path using the host's API -3. Each Extractor exporting pixel data (e.g. image or video) has to use parent class `openpype.pipeline.publish.publish_plugins.ExtractorColormanaged` and use `self.set_representation_colorspace` on the representations to be integrated. +3. Each Extractor exporting pixel data (e.g. image or video) has to inherit from the mixin class `openpype.pipeline.publish.publish_plugins.ColormanagedPyblishPluginMixin` and use `self.set_representation_colorspace` on the representations to be integrated. The **set_representation_colorspace** method adds `colorspaceData` to the representation. If the `colorspace` passed is not `None` then it is added directly to the representation with resolved config path otherwise a color space is assumed using the configured file rules. If no file rule matches the `colorspaceData` is **not** added to the representation. From f55ac53c82e4b75b445bcfd99753a9ee56180ccf Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 13 Mar 2023 23:12:34 +0100 Subject: [PATCH 392/898] Fix typos --- openpype/settings/entities/schemas/README.md | 2 +- website/docs/admin_environment.md | 2 +- website/docs/admin_hosts_maya.md | 2 +- website/docs/admin_settings.md | 2 +- website/docs/admin_use.md | 2 +- website/docs/artist_hosts_3dsmax.md | 4 ++-- website/docs/artist_hosts_hiero.md | 6 +++--- website/docs/artist_hosts_photoshop.md | 2 +- website/docs/artist_tools_sync_queu.md | 2 +- website/docs/dev_colorspace.md | 4 ++-- website/docs/dev_host_implementation.md | 4 ++-- website/docs/dev_publishing.md | 2 +- website/docs/dev_settings.md | 6 +++--- website/docs/dev_testing.md | 2 +- website/docs/module_kitsu.md | 2 +- website/docs/module_site_sync.md | 2 +- website/docs/project_settings/settings_project_global.md | 6 +++--- website/docs/project_settings/settings_project_nuke.md | 2 +- .../docs/project_settings/settings_project_standalone.md | 2 +- 19 files changed, 28 insertions(+), 28 deletions(-) diff --git a/openpype/settings/entities/schemas/README.md b/openpype/settings/entities/schemas/README.md index b4c878fe0fa..cff614a4bb0 100644 --- a/openpype/settings/entities/schemas/README.md +++ b/openpype/settings/entities/schemas/README.md @@ -350,7 +350,7 @@ How output of the schema could look like on save: - number input, can be used for both integer and float - key `"decimal"` defines how many decimal places will be used, 0 is for integer input (Default: `0`) - key `"minimum"` as minimum allowed number to enter (Default: `-99999`) - - key `"maxium"` as maximum allowed number to enter (Default: `99999`) + - key `"maximum"` as maximum allowed number to enter (Default: `99999`) - key `"steps"` will change single step value of UI inputs (using arrows and wheel scroll) - for UI it is possible to show slider to enable this option set `show_slider` to `true` ``` diff --git a/website/docs/admin_environment.md b/website/docs/admin_environment.md index 1eb755b90b7..29b70a6c47a 100644 --- a/website/docs/admin_environment.md +++ b/website/docs/admin_environment.md @@ -27,4 +27,4 @@ import TabItem from '@theme/TabItem'; - for more details on how to use it go [here](admin_use#check-for-mongodb-database-connection) ## OPENPYPE_USERNAME -- if set it overides system created username +- if set it overrides system created username diff --git a/website/docs/admin_hosts_maya.md b/website/docs/admin_hosts_maya.md index 0e77f29fc20..ae0cf76f536 100644 --- a/website/docs/admin_hosts_maya.md +++ b/website/docs/admin_hosts_maya.md @@ -142,7 +142,7 @@ Fill in the necessary fields (the optional fields are regex filters) ![new place holder](assets/maya-placeholder_new.png) - - Builder type: Wether the the placeholder should load current asset representations or linked assets representations + - Builder type: Whether the the placeholder should load current asset representations or linked assets representations - Representation: Representation that will be loaded (ex: ma, abc, png, etc...) diff --git a/website/docs/admin_settings.md b/website/docs/admin_settings.md index 8626ef16ba5..dcbe740d0c0 100644 --- a/website/docs/admin_settings.md +++ b/website/docs/admin_settings.md @@ -76,7 +76,7 @@ You can also reset any settings to OpenPype default by doing `right click` and ` Many settings are useful to be adjusted on a per-project basis. To identify project overrides, they are marked with **orange edge** and **orange labels** in the settings GUI. -The process of settting project overrides is similar to setting the Studio defaults. The key difference is to select a particular project you want to be configure. Those projects can be found on the left hand side of the Project Settings tab. +The process of setting project overrides is similar to setting the Studio defaults. The key difference is to select a particular project you want to be configure. Those projects can be found on the left hand side of the Project Settings tab. In the image below you can see all three overrides at the same time. 1. Deadline has **no changes to the OpenPype defaults** at all — **grey** colour of left bar. diff --git a/website/docs/admin_use.md b/website/docs/admin_use.md index c92ac3a77a2..c1d1de0e8cd 100644 --- a/website/docs/admin_use.md +++ b/website/docs/admin_use.md @@ -68,7 +68,7 @@ Add `--headless` to run OpenPype without graphical UI (useful on server or on au `--verbose` `` - change log verbose level of OpenPype loggers. -Level value can be integer in range `0-50` or one of enum strings `"notset" (0)`, `"debug" (10)`, `"info" (20)`, `"warning" (30)`, `"error" (40)`, `"ciritcal" (50)`. Value is stored to `OPENPYPE_LOG_LEVEL` environment variable for next processes. +Level value can be integer in range `0-50` or one of enum strings `"notset" (0)`, `"debug" (10)`, `"info" (20)`, `"warning" (30)`, `"error" (40)`, `"critical" (50)`. Value is stored to `OPENPYPE_LOG_LEVEL` environment variable for next processes. ```shell openpype_console --verbose debug diff --git a/website/docs/artist_hosts_3dsmax.md b/website/docs/artist_hosts_3dsmax.md index 71ba8785dcf..12c1f401815 100644 --- a/website/docs/artist_hosts_3dsmax.md +++ b/website/docs/artist_hosts_3dsmax.md @@ -47,7 +47,7 @@ This is the core functional area for you as a user. Most of your actions will ta ![Menu OpenPype](assets/3dsmax_menu_first_OP.png) :::note OpenPype Menu -User should use this menu exclusively for **Opening/Saving** when dealing with work files not standard ```File Menu``` even though user still being able perform file operations via this menu but prefferably just performing quick saves during work session not saving actual workfile versions. +User should use this menu exclusively for **Opening/Saving** when dealing with work files not standard ```File Menu``` even though user still being able perform file operations via this menu but preferably just performing quick saves during work session not saving actual workfile versions. ::: ## Working With Scene Files @@ -73,7 +73,7 @@ OpenPype correctly names it and add version to the workfile. This basically happ etc. -Basically meaning user is free of guessing what is the correct naming and other neccessities to keep everthing in order and managed. +Basically meaning user is free of guessing what is the correct naming and other necessities to keep everything in order and managed. > Note: user still has also other options for naming like ```Subversion```, ```Artist's Note``` but we won't dive into those now. diff --git a/website/docs/artist_hosts_hiero.md b/website/docs/artist_hosts_hiero.md index 136ed6ea9c5..977c7a7baf8 100644 --- a/website/docs/artist_hosts_hiero.md +++ b/website/docs/artist_hosts_hiero.md @@ -231,14 +231,14 @@ All published instances that will replace the place holder must contain unique i ![Create menu](assets/nuke_publishedinstance.png) -The informations about these objects are given by the user by filling the extra attributes of the Place Holder +The information about these objects are given by the user by filling the extra attributes of the Place Holder ![Create menu](assets/nuke_fillingExtraAttributes.png) ### Update Place Holder -This tool alows the user to change the information provided in the extra attributes of the selected Place Holder. +This tool allows the user to change the information provided in the extra attributes of the selected Place Holder. ![Create menu](assets/nuke_updatePlaceHolder.png) @@ -250,7 +250,7 @@ This tool imports the template used and replaces the existed PlaceHolders with t ![Create menu](assets/nuke_buildWorfileFromTemplate.png) #### Result -- Replace `PLACEHOLDER` node in the template with the published instance corresponding to the informations provided in extra attributes of the Place Holder +- Replace `PLACEHOLDER` node in the template with the published instance corresponding to the information provided in extra attributes of the Place Holder ![Create menu](assets/nuke_buildworkfile.png) diff --git a/website/docs/artist_hosts_photoshop.md b/website/docs/artist_hosts_photoshop.md index 88bfb1484de..12203a5c6ed 100644 --- a/website/docs/artist_hosts_photoshop.md +++ b/website/docs/artist_hosts_photoshop.md @@ -75,7 +75,7 @@ enabled instances, you could see more information after clicking on `Details` ta ![Image instances creates](assets/photoshop_publish_validations.png) -In this dialog you could see publishable instances in left colummn, triggered plugins in the middle and logs in the right column. +In this dialog you could see publishable instances in left column, triggered plugins in the middle and logs in the right column. In left column you could see that `review` instance was created automatically. This instance flattens all publishable instances or all visible layers if no publishable instances were created into single image which could serve as a single reviewable element (for example in Ftrack). diff --git a/website/docs/artist_tools_sync_queu.md b/website/docs/artist_tools_sync_queu.md index 770c2f77ad1..7dac8638f94 100644 --- a/website/docs/artist_tools_sync_queu.md +++ b/website/docs/artist_tools_sync_queu.md @@ -2,7 +2,7 @@ id: artist_tools_sync_queue title: Sync Queue sidebar_label: Sync Queue -description: Track sites syncronization progress. +description: Track sites synchronization progress. --- # Sync Queue diff --git a/website/docs/dev_colorspace.md b/website/docs/dev_colorspace.md index fe9a0ec1e38..b46d80e1a2b 100644 --- a/website/docs/dev_colorspace.md +++ b/website/docs/dev_colorspace.md @@ -24,8 +24,8 @@ It's up to the Loaders to read these values and apply the correct expected color ### Keys - **colorspace** - string value used in other publish plugins and loaders - **config** - storing two versions of path. - - **path** - is formated and with baked platform root. It is used for posible need to find out where we were sourcing color config during publishing. - - **template** - unformated tempate resolved from settings. It is used for other plugins targeted to remote publish which could be processed at different platform. + - **path** - is formatted and with baked platform root. It is used for possible need to find out where we were sourcing color config during publishing. + - **template** - unformatted template resolved from settings. It is used for other plugins targeted to remote publish which could be processed at different platform. ### Example { diff --git a/website/docs/dev_host_implementation.md b/website/docs/dev_host_implementation.md index 3702483ad10..e62043723fc 100644 --- a/website/docs/dev_host_implementation.md +++ b/website/docs/dev_host_implementation.md @@ -45,10 +45,10 @@ openpype/hosts/{host name} ``` ### Launch Hooks -Launch hooks are not directly connected to host implementation, but they can be used to modify launch of process which may be crutial for the implementation. Launch hook are plugins called when DCC is launched. They are processed in sequence before and after launch. Pre launch hooks can change how process of DCC is launched, e.g. change subprocess flags, modify environments or modify launch arguments. If prelaunch hook crashes the application is not launched at all. Postlaunch hooks are triggered after launch of subprocess. They can be used to change statuses in your project tracker, start timer, etc. Crashed postlaunch hooks have no effect on rest of postlaunch hooks or launched process. They can be filtered by platform, host and application and order is defined by integer value. Hooks inside host are automatically loaded (one reason why folder name should match host name) or can be defined from modules. Hooks execution share same launch context where can be stored data used across multiple hooks (please be very specific in stored keys e.g. 'project' vs. 'project_name'). For more detailed information look into `openpype/lib/applications.py`. +Launch hooks are not directly connected to host implementation, but they can be used to modify launch of process which may be crucial for the implementation. Launch hook are plugins called when DCC is launched. They are processed in sequence before and after launch. Pre launch hooks can change how process of DCC is launched, e.g. change subprocess flags, modify environments or modify launch arguments. If prelaunch hook crashes the application is not launched at all. Postlaunch hooks are triggered after launch of subprocess. They can be used to change statuses in your project tracker, start timer, etc. Crashed postlaunch hooks have no effect on rest of postlaunch hooks or launched process. They can be filtered by platform, host and application and order is defined by integer value. Hooks inside host are automatically loaded (one reason why folder name should match host name) or can be defined from modules. Hooks execution share same launch context where can be stored data used across multiple hooks (please be very specific in stored keys e.g. 'project' vs. 'project_name'). For more detailed information look into `openpype/lib/applications.py`. ### Public interface -Public face is at this moment related to launching of the DCC. At this moment there there is only option to modify environment variables before launch by implementing function `add_implementation_envs` (must be available in `openpype/hosts/{host name}/__init__.py`). The function is called after pre launch hooks, as last step before subprocess launch, to be able set environment variables crutial for proper integration. It is also good place for functions that are used in prelaunch hooks and in-DCC integration. Future plans are to be able get workfiles extensions from here. Right now workfiles extensions are hardcoded in `openpype/pipeline/constants.py` under `HOST_WORKFILE_EXTENSIONS`, we would like to handle hosts as addons similar to OpenPype modules, and more improvements which are now hardcoded. +Public face is at this moment related to launching of the DCC. At this moment there there is only option to modify environment variables before launch by implementing function `add_implementation_envs` (must be available in `openpype/hosts/{host name}/__init__.py`). The function is called after pre launch hooks, as last step before subprocess launch, to be able set environment variables crucial for proper integration. It is also good place for functions that are used in prelaunch hooks and in-DCC integration. Future plans are to be able get workfiles extensions from here. Right now workfiles extensions are hardcoded in `openpype/pipeline/constants.py` under `HOST_WORKFILE_EXTENSIONS`, we would like to handle hosts as addons similar to OpenPype modules, and more improvements which are now hardcoded. ### Integration We've prepared base class `HostBase` in `openpype/host/host.py` to define minimum requirements and provide some default method implementations. The minimum requirement for a host is `name` attribute, this host would not be able to do much but is valid. To extend functionality we've prepared interfaces that helps to identify what is host capable of and if is possible to use certain tools with it. For those cases we defined interfaces for each workflow. `IWorkfileHost` interface add requirement to implement workfiles related methods which makes host usable in combination with Workfiles tool. `ILoadHost` interface add requirements to be able load, update, switch or remove referenced representations which should add support to use Loader and Scene Inventory tools. `INewPublisher` interface is required to be able use host with new OpenPype publish workflow. This is what must or can be implemented to allow certain functionality. `HostBase` will have more responsibility which will be taken from global variables in future. This process won't happen at once, but will be slow to keep backwards compatibility for some time. diff --git a/website/docs/dev_publishing.md b/website/docs/dev_publishing.md index 135f6cd9856..2c575372238 100644 --- a/website/docs/dev_publishing.md +++ b/website/docs/dev_publishing.md @@ -415,7 +415,7 @@ class CreateRender(Creator): # - 'asset' - asset name # - 'task' - task name # - 'variant' - variant - # - 'family' - instnace family + # - 'family' - instance family # Check if should use selection or not if pre_create_data.get("use_selection"): diff --git a/website/docs/dev_settings.md b/website/docs/dev_settings.md index 94590345e86..1010169a5f1 100644 --- a/website/docs/dev_settings.md +++ b/website/docs/dev_settings.md @@ -355,7 +355,7 @@ These inputs wraps another inputs into {key: value} relation { "type": "text", "key": "command", - "label": "Comand" + "label": "Command" } ] }, @@ -420,7 +420,7 @@ How output of the schema could look like on save: - number input, can be used for both integer and float - key `"decimal"` defines how many decimal places will be used, 0 is for integer input (Default: `0`) - key `"minimum"` as minimum allowed number to enter (Default: `-99999`) - - key `"maxium"` as maximum allowed number to enter (Default: `99999`) + - key `"maximum"` as maximum allowed number to enter (Default: `99999`) - key `"steps"` will change single step value of UI inputs (using arrows and wheel scroll) - for UI it is possible to show slider to enable this option set `show_slider` to `true` ```javascript @@ -602,7 +602,7 @@ How output of the schema could look like on save: - there are 2 possible ways how to set the type: 1.) dictionary with item modifiers (`number` input has `minimum`, `maximum` and `decimals`) in that case item type must be set as value of `"type"` (example below) 2.) item type name as string without modifiers (e.g. [text](#text)) - 3.) enhancement of 1.) there is also support of `template` type but be carefull about endless loop of templates + 3.) enhancement of 1.) there is also support of `template` type but be careful about endless loop of templates - goal of using `template` is to easily change same item definitions in multiple lists 1.) with item modifiers diff --git a/website/docs/dev_testing.md b/website/docs/dev_testing.md index 7136ceb4792..434c1ca9ffd 100644 --- a/website/docs/dev_testing.md +++ b/website/docs/dev_testing.md @@ -57,7 +57,7 @@ Content: Contains end to end testing in a DCC. Currently it is setup to start DCC application with prepared worfkile, run publish process and compare results in DB and file system automatically. This approach is implemented as it should work in any DCC application and should cover most common use cases. Not all hosts allow "real headless" publishing, but all hosts should allow to trigger -publish process programatically when UI of host is actually running. +publish process programmatically when UI of host is actually running. There will be eventually also possibility to build workfile and publish it programmatically, this would work only in DCCs that support it (Maya, Nuke). diff --git a/website/docs/module_kitsu.md b/website/docs/module_kitsu.md index 7738ee1ce2f..04249397863 100644 --- a/website/docs/module_kitsu.md +++ b/website/docs/module_kitsu.md @@ -41,4 +41,4 @@ openpype_console module kitsu push-to-zou -l me@domain.ext -p my_password ## Q&A ### Is it safe to rename an entity from Kitsu? Absolutely! Entities are linked by their unique IDs between the two databases. -But renaming from the OP's Project Manager won't apply the change to Kitsu, it'll be overriden during the next synchronization. +But renaming from the OP's Project Manager won't apply the change to Kitsu, it'll be overridden during the next synchronization. diff --git a/website/docs/module_site_sync.md b/website/docs/module_site_sync.md index 2e9cf011021..3e5794579c9 100644 --- a/website/docs/module_site_sync.md +++ b/website/docs/module_site_sync.md @@ -89,7 +89,7 @@ all share the same provider). Handles files stored on disk storage. -Local drive provider is the most basic one that is used for accessing all standard hard disk storage scenarios. It will work with any storage that can be mounted on your system in a standard way. This could correspond to a physical external hard drive, network mounted storage, internal drive or even VPN connected network drive. It doesn't care about how te drive is mounted, but you must be able to point to it with a simple directory path. +Local drive provider is the most basic one that is used for accessing all standard hard disk storage scenarios. It will work with any storage that can be mounted on your system in a standard way. This could correspond to a physical external hard drive, network mounted storage, internal drive or even VPN connected network drive. It doesn't care about how the drive is mounted, but you must be able to point to it with a simple directory path. Default sites `local` and `studio` both use local drive provider. diff --git a/website/docs/project_settings/settings_project_global.md b/website/docs/project_settings/settings_project_global.md index b320b5502f9..6c1a269b1f0 100644 --- a/website/docs/project_settings/settings_project_global.md +++ b/website/docs/project_settings/settings_project_global.md @@ -10,7 +10,7 @@ import TabItem from '@theme/TabItem'; Project settings can have project specific values. Each new project is using studio values defined in **default** project but these values can be modified or overridden per project. :::warning Default studio values -Projects always use default project values unless they have [project override](../admin_settings#project-overrides) (orage colour). Any changes in default project may affect all existing projects. +Projects always use default project values unless they have [project override](../admin_settings#project-overrides) (orange colour). Any changes in default project may affect all existing projects. ::: ## Color Management (ImageIO) @@ -39,14 +39,14 @@ Procedure of resolving path (from above example) will look first into path 1st a ### Using File rules File rules are inspired by [OCIO v2 configuration]((https://opencolorio.readthedocs.io/en/latest/guides/authoring/rules.html)). Each rule has a unique name which can be overridden by host-specific _File rules_ (example: `project_settings/nuke/imageio/file_rules/rules`). -The _input pattern_ matching uses REGEX expression syntax (try [regexr.com](https://regexr.com/)). Matching rules procedure's intention is to be used during publishing or loading of representation. Since the publishing procedure is run before integrator formate publish template path, make sure the pattern is working or any work render path. +The _input pattern_ matching uses REGEX expression syntax (try [regexr.com](https://regexr.com/)). Matching rules procedure's intention is to be used during publishing or loading of representation. Since the publishing procedure is run before integrator format publish template path, make sure the pattern is working or any work render path. :::warning Colorspace name input The **colorspace name** value is a raw string input and no validation is run after saving project settings. We recommend to open the specified `config.ocio` file and copy pasting the exact colorspace names. ::: ### Extract OIIO Transcode -OIIOTools transcoder plugin with configurable output presets. Any incoming representation with `colorspaceData` is convertable to single or multiple representations with different target colorspaces or display and viewer names found in linked **config.ocio** file. +OIIOTools transcoder plugin with configurable output presets. Any incoming representation with `colorspaceData` is convertible to single or multiple representations with different target colorspaces or display and viewer names found in linked **config.ocio** file. `oiiotool` is used for transcoding, eg. `oiiotool` must be present in `vendor/bin/oiio` or environment variable `OPENPYPE_OIIO_PATHS` must be provided for custom oiio installation. diff --git a/website/docs/project_settings/settings_project_nuke.md b/website/docs/project_settings/settings_project_nuke.md index b3ee5f77a63..c9c3d12df91 100644 --- a/website/docs/project_settings/settings_project_nuke.md +++ b/website/docs/project_settings/settings_project_nuke.md @@ -10,7 +10,7 @@ import TabItem from '@theme/TabItem'; Project settings can have project specific values. Each new project is using studio values defined in **default** project but these values can be modified or overridden per project. :::warning Default studio values -Projects always use default project values unless they have [project override](../admin_settings#project-overrides) (orage colour). Any changes in default project may affect all existing projects. +Projects always use default project values unless they have [project override](../admin_settings#project-overrides) (orange colour). Any changes in default project may affect all existing projects. ::: ## Workfile Builder diff --git a/website/docs/project_settings/settings_project_standalone.md b/website/docs/project_settings/settings_project_standalone.md index 778aba29426..1383bd488e2 100644 --- a/website/docs/project_settings/settings_project_standalone.md +++ b/website/docs/project_settings/settings_project_standalone.md @@ -10,7 +10,7 @@ import TabItem from '@theme/TabItem'; Project settings can have project specific values. Each new project is using studio values defined in **default** project but these values can be modified or overridden per project. :::warning Default studio values -Projects always use default project values unless they have [project override](../admin_settings#project-overrides) (orage colour). Any changes in default project may affect all existing projects. +Projects always use default project values unless they have [project override](../admin_settings#project-overrides) (orange colour). Any changes in default project may affect all existing projects. ::: ## Creator Plugins From 8f2112dd2642b02976a93cb0cabaffc1162b80ee Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 13 Mar 2023 23:13:50 +0100 Subject: [PATCH 393/898] Fix case of extension --- website/docs/artist_hosts_aftereffects.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/docs/artist_hosts_aftereffects.md b/website/docs/artist_hosts_aftereffects.md index a9c9ca49fa4..939ef4034ca 100644 --- a/website/docs/artist_hosts_aftereffects.md +++ b/website/docs/artist_hosts_aftereffects.md @@ -34,7 +34,7 @@ a correct name. You should use it instead of standard file saving dialog. In AfterEffects you'll find the tools in the `OpenPype` extension: -![Extension](assets/photoshop_extension.PNG) +![Extension](assets/photoshop_extension.png) You can show the extension panel by going to `Window` > `Extensions` > `OpenPype`. @@ -104,7 +104,7 @@ There are currently 2 options of `render` item: When you want to load existing published work, you can use the `Loader` tool. You can reach it in the extension's panel. -![Loader](assets/photoshop_loader.PNG) +![Loader](assets/photoshop_loader.png) The supported families for loading into AfterEffects are: @@ -128,7 +128,7 @@ Now that we have some content loaded, you can manage which version is loaded. Th Loaded images have to stay as smart layers in order to be updated. If you rasterize the layer, you can no longer update it to a different version using OpenPype tools. ::: -![Loader](assets/photoshop_manage.PNG) +![Loader](assets/photoshop_manage.png) You can switch to a previous version of the image or update to the latest. From c262ac3255b39c1847720b6f1d51bf993a42d865 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 13 Mar 2023 23:14:11 +0100 Subject: [PATCH 394/898] Refactor case of extension to match surrounding files --- website/docs/artist_hosts_harmony.md | 2 +- .../{harmony_creator.PNG => harmony_creator.png} | Bin 2 files changed, 1 insertion(+), 1 deletion(-) rename website/docs/assets/{harmony_creator.PNG => harmony_creator.png} (100%) diff --git a/website/docs/artist_hosts_harmony.md b/website/docs/artist_hosts_harmony.md index aa9355e2214..eaa6edc42aa 100644 --- a/website/docs/artist_hosts_harmony.md +++ b/website/docs/artist_hosts_harmony.md @@ -44,7 +44,7 @@ Because the saving to the network location happens in the background, be careful `OpenPype > Create` -![Creator](assets/harmony_creator.PNG) +![Creator](assets/harmony_creator.png) These are the families supported in Harmony: diff --git a/website/docs/assets/harmony_creator.PNG b/website/docs/assets/harmony_creator.png similarity index 100% rename from website/docs/assets/harmony_creator.PNG rename to website/docs/assets/harmony_creator.png From fbe93aae39d7950639c5fbf99aca124b5ccd9ae3 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 13 Mar 2023 23:21:05 +0100 Subject: [PATCH 395/898] Grammar tweaks --- website/docs/admin_settings.md | 2 +- website/docs/manager_ftrack.md | 2 +- website/docs/module_ftrack.md | 2 +- website/docs/module_kitsu.md | 2 +- website/docs/pype2/admin_ftrack.md | 2 +- website/docs/system_introduction.md | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/website/docs/admin_settings.md b/website/docs/admin_settings.md index dcbe740d0c0..51bfdf7c33c 100644 --- a/website/docs/admin_settings.md +++ b/website/docs/admin_settings.md @@ -7,7 +7,7 @@ sidebar_label: Working with settings import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -OpenPype stores all of it's settings and configuration in the mongo database. To make the configuration as easy as possible we provide a robust GUI where you can access and change everything that is configurable +OpenPype stores all of its settings and configuration in the mongo database. To make the configuration as easy as possible we provide a robust GUI where you can access and change everything that is configurable **Settings** GUI can be started from the tray menu *Admin -> Studio Settings*. diff --git a/website/docs/manager_ftrack.md b/website/docs/manager_ftrack.md index b5ca1678387..836d84405e7 100644 --- a/website/docs/manager_ftrack.md +++ b/website/docs/manager_ftrack.md @@ -4,7 +4,7 @@ title: Ftrack sidebar_label: Project Manager --- -Ftrack is currently the main project management option for OpenPype. This documentation assumes that you are familiar with Ftrack and it's basic principles. If you're new to Ftrack, we recommend having a thorough look at [Ftrack Official Documentation](https://help.ftrack.com/en/). +Ftrack is currently the main project management option for OpenPype. This documentation assumes that you are familiar with Ftrack and its basic principles. If you're new to Ftrack, we recommend having a thorough look at [Ftrack Official Documentation](https://help.ftrack.com/en/). ## Project management Setting project attributes is the key to properly working pipeline. diff --git a/website/docs/module_ftrack.md b/website/docs/module_ftrack.md index 6d5529b512e..9111e4658c5 100644 --- a/website/docs/module_ftrack.md +++ b/website/docs/module_ftrack.md @@ -8,7 +8,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -Ftrack is currently the main project management option for OpenPype. This documentation assumes that you are familiar with Ftrack and it's basic principles. If you're new to Ftrack, we recommend having a thorough look at [Ftrack Official Documentation](http://ftrack.rtd.ftrack.com/en/stable/). +Ftrack is currently the main project management option for OpenPype. This documentation assumes that you are familiar with Ftrack and its basic principles. If you're new to Ftrack, we recommend having a thorough look at [Ftrack Official Documentation](http://ftrack.rtd.ftrack.com/en/stable/). ## Prepare Ftrack for OpenPype diff --git a/website/docs/module_kitsu.md b/website/docs/module_kitsu.md index 04249397863..7be2a42c458 100644 --- a/website/docs/module_kitsu.md +++ b/website/docs/module_kitsu.md @@ -7,7 +7,7 @@ sidebar_label: Kitsu import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -Kitsu is a great open source production tracker and can be used for project management instead of Ftrack. This documentation assumes that you are familiar with Kitsu and it's basic principles. If you're new to Kitsu, we recommend having a thorough look at [Kitsu Official Documentation](https://kitsu.cg-wire.com/). +Kitsu is a great open source production tracker and can be used for project management instead of Ftrack. This documentation assumes that you are familiar with Kitsu and its basic principles. If you're new to Kitsu, we recommend having a thorough look at [Kitsu Official Documentation](https://kitsu.cg-wire.com/). ## Prepare Kitsu for OpenPype diff --git a/website/docs/pype2/admin_ftrack.md b/website/docs/pype2/admin_ftrack.md index a81147bece1..4ebe1a7adda 100644 --- a/website/docs/pype2/admin_ftrack.md +++ b/website/docs/pype2/admin_ftrack.md @@ -8,7 +8,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -Ftrack is currently the main project management option for Pype. This documentation assumes that you are familiar with Ftrack and it's basic principles. If you're new to Ftrack, we recommend having a thorough look at [Ftrack Official Documentation](http://ftrack.rtd.ftrack.com/en/stable/). +Ftrack is currently the main project management option for Pype. This documentation assumes that you are familiar with Ftrack and its basic principles. If you're new to Ftrack, we recommend having a thorough look at [Ftrack Official Documentation](http://ftrack.rtd.ftrack.com/en/stable/). ## Prepare Ftrack for Pype diff --git a/website/docs/system_introduction.md b/website/docs/system_introduction.md index 05627b53594..d64b0237044 100644 --- a/website/docs/system_introduction.md +++ b/website/docs/system_introduction.md @@ -15,9 +15,9 @@ various usage scenarios. ## Studio Preparation -You can find detailed breakdown of technical requirements [here](dev_requirements), but in general OpenPype should be able +You can find a detailed breakdown of technical requirements [here](dev_requirements), but in general OpenPype should be able to operate in most studios fairly quickly. The main obstacles are usually related to workflows and habits, that -might not be fully compatible with what OpenPype is expecting or enforcing. It is recommended to go through artists [key concepts](artist_concepts) to get idea about basics. +might not be fully compatible with what OpenPype is expecting or enforcing. It is recommended to go through artists [key concepts](artist_concepts) to get comfortable with the basics. Keep in mind that if you run into any workflows that are not supported, it's usually just because we haven't hit that particular case and it can most likely be added upon request. From 5aae66794b4c98d3ef2c6db7c049799f7f0d9a6b Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 13 Mar 2023 23:21:37 +0100 Subject: [PATCH 396/898] Highlight studio settings versus local settings more --- website/docs/admin_settings.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/website/docs/admin_settings.md b/website/docs/admin_settings.md index 51bfdf7c33c..1128cc00c69 100644 --- a/website/docs/admin_settings.md +++ b/website/docs/admin_settings.md @@ -11,8 +11,11 @@ OpenPype stores all of its settings and configuration in the mongo database. To **Settings** GUI can be started from the tray menu *Admin -> Studio Settings*. -Please keep in mind that these settings are set-up for the full studio and not per-individual. If you're looking for individual artist settings, you can head to -[Local Settings](admin_settings_local.md) section in the artist documentation. +:::important Studio Settings versus Local Settings +Please keep in mind that these settings are set up for the full studio and not per-individual. If you're looking for individual artist settings, you can head to +[Local Settings](admin_settings_local.md) section in the documentation. +::: + ## Categories From 5b3cc605d8be1dafdc1114372ae7e9b7e80e3ff4 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Tue, 14 Mar 2023 04:18:48 +0300 Subject: [PATCH 397/898] add some comments --- openpype/hosts/fusion/addon.py | 12 ++++++------ .../hosts/fusion/hooks/pre_fusion_profile_hook.py | 2 ++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/fusion/addon.py b/openpype/hosts/fusion/addon.py index 4b0ce59aaf2..e3464f4be43 100644 --- a/openpype/hosts/fusion/addon.py +++ b/openpype/hosts/fusion/addon.py @@ -14,6 +14,10 @@ def get_fusion_profile_number(module: str, app_data: str) -> int: already Fusion version 18, still FUSION16_PROFILE_DIR is used. The variable is added in case the version number will be updated or deleted so we could easily change the version or disable it. + + app_data derives from `launch_context.env.get("AVALON_APP_NAME")`. + For the time being we will encourage user to set a version number + set in the system settings key for the Blackmagic Fusion. """ log = Logger.get_logger(__name__) @@ -42,15 +46,11 @@ def initialize(self, module_settings): def get_launch_hook_paths(self, app): if app.host_name != self.host_name: return [] - return [ - os.path.join(FUSION_HOST_DIR, "hooks") - ] + return [os.path.join(FUSION_HOST_DIR, "hooks")] def add_implementation_envs(self, env, _app): # Set default values if are not already set via settings - defaults = { - "OPENPYPE_LOG_NO_COLORS": "Yes" - } + defaults = {"OPENPYPE_LOG_NO_COLORS": "Yes"} for key, value in defaults.items(): if not env.get(key): env[key] = value diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py index 543e90cc751..dc6a4bf85da 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -122,6 +122,8 @@ def execute(self): self.log.info(f"Setting {fu_profile_dir_variable}: {fu_profile_dir}") self.launch_context.env[fu_profile_dir_variable] = str(fu_profile_dir) + # setup masterprefs file to partially alter existing or newly generated + # Fusion profile, to add OpenPype menu, scripts and and config files. master_prefs_variable = f"FUSION{app_version}_MasterPrefs" master_prefs = Path(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") self.log.info(f"Setting {master_prefs_variable}: {master_prefs}") From 1914a0dd0212473beba1ee7e4715c3d7441be057 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 14 Mar 2023 10:07:00 +0100 Subject: [PATCH 398/898] Remove unused imports --- openpype/hosts/maya/plugins/publish/extract_look.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index efeddcfbe40..bfa26d158fd 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -1,12 +1,10 @@ # -*- coding: utf-8 -*- """Maya look extractor.""" import os -import sys import json import tempfile import platform import contextlib -import subprocess from collections import OrderedDict from maya import cmds # noqa From 3f9f9bc6d1dc13a500cbd1b7cc76f0567b0fd854 Mon Sep 17 00:00:00 2001 From: moonyuet Date: Tue, 14 Mar 2023 10:10:16 +0100 Subject: [PATCH 399/898] fix the bug of removing an instance --- openpype/hosts/max/api/plugin.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/max/api/plugin.py b/openpype/hosts/max/api/plugin.py index c16d9e61ecd..c7b9b64d295 100644 --- a/openpype/hosts/max/api/plugin.py +++ b/openpype/hosts/max/api/plugin.py @@ -101,7 +101,12 @@ def remove_instances(self, instances): instance_node = rt.getNodeByName( instance.data.get("instance_node")) if instance_node: - rt.delete(rt.getNodeByName(instance_node)) + rt.select(instance_node) + unparent_cmd = f""" + for o in selection do for c in o.children do c.parent = undefined + """ + rt.execute(unparent_cmd) + rt.delete(instance_node) self._remove_instance_from_context(instance) From e250d8935f45490ee991b9ac11bc8ec758f3c32d Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 14 Mar 2023 10:14:09 +0100 Subject: [PATCH 400/898] Don't require to `arnold` plug-in to be available, don't force load it if we don't need it. --- openpype/hosts/maya/plugins/publish/extract_look.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index bfa26d158fd..18931552916 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -21,6 +21,15 @@ HARDLINK = 2 +def _has_arnold(): + """Return whether the arnold package is available and can be imported.""" + try: + import arnold + return True + except (ImportError, ModuleNotFoundError): + return False + + def escape_space(path): """Ensure path is enclosed by quotes to allow paths with spaces""" return '"{}"'.format(path) if " " in path else path @@ -546,7 +555,7 @@ def _process_texture(self, filepath, resource, color_space = cmds.getAttr(color_space_attr) except ValueError: # node doesn't have color space attribute - if cmds.loadPlugin("mtoa", quiet=True): + if _has_arnold(): img_info = image_info(filepath) color_space = guess_colorspace(img_info) else: @@ -558,7 +567,7 @@ def _process_texture(self, filepath, resource, render_colorspace]) else: - if cmds.loadPlugin("mtoa", quiet=True): + if _has_arnold(): img_info = image_info(filepath) color_space = guess_colorspace(img_info) if color_space == "sRGB": From 8199faedc0880b21e39fd9a03c77965d5f34c436 Mon Sep 17 00:00:00 2001 From: moonyuet Date: Tue, 14 Mar 2023 10:15:46 +0100 Subject: [PATCH 401/898] cosmetic issue fix --- openpype/hosts/max/api/plugin.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/openpype/hosts/max/api/plugin.py b/openpype/hosts/max/api/plugin.py index c7b9b64d295..b54568b360c 100644 --- a/openpype/hosts/max/api/plugin.py +++ b/openpype/hosts/max/api/plugin.py @@ -102,10 +102,7 @@ def remove_instances(self, instances): instance.data.get("instance_node")) if instance_node: rt.select(instance_node) - unparent_cmd = f""" - for o in selection do for c in o.children do c.parent = undefined - """ - rt.execute(unparent_cmd) + rt.execute(f'for o in selection do for c in o.children do c.parent = undefined') # noqa rt.delete(instance_node) self._remove_instance_from_context(instance) From 5b43ce940c990592d69e360cf880aa35ce6009d5 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 14 Mar 2023 10:02:23 +0100 Subject: [PATCH 402/898] Maya: Avoid error on right click in Loader if Arnold `mtoa` is not loaded --- openpype/hosts/maya/plugins/load/load_arnold_standin.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/load/load_arnold_standin.py b/openpype/hosts/maya/plugins/load/load_arnold_standin.py index ab69d62ef58..11a2bd19669 100644 --- a/openpype/hosts/maya/plugins/load/load_arnold_standin.py +++ b/openpype/hosts/maya/plugins/load/load_arnold_standin.py @@ -2,7 +2,6 @@ import clique import maya.cmds as cmds -import mtoa.ui.arnoldmenu from openpype.settings import get_project_settings from openpype.pipeline import ( @@ -36,6 +35,11 @@ class ArnoldStandinLoader(load.LoaderPlugin): color = "orange" def load(self, context, name, namespace, options): + + # Make sure to load arnold before importing `mtoa.ui.arnoldmenu` + cmds.loadPlugin("mtoa", quiet=True) + import mtoa.ui.arnoldmenu + version = context['version'] version_data = version.get("data", {}) From f0a76b5cc56b9b6577f768f1390d06468a6cec4e Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 14 Mar 2023 11:01:45 +0100 Subject: [PATCH 403/898] Shush hound --- openpype/hosts/maya/plugins/publish/extract_look.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 18931552916..bc506b7feb1 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -24,7 +24,7 @@ def _has_arnold(): """Return whether the arnold package is available and can be imported.""" try: - import arnold + import arnold # noqa: F401 return True except (ImportError, ModuleNotFoundError): return False From be463b05dc2fae9eda44bd2ce3bd1fd47eca82d0 Mon Sep 17 00:00:00 2001 From: Oscar Domingo Date: Wed, 18 Jan 2023 15:55:40 +0000 Subject: [PATCH 404/898] documentation: Add `ARCHITECTURE.md` document This document attemps to give a quick overview of the project to help onboarding, it's not an extensive documentation but more of a elevator pitch one-line descriptions of files/directories and what the attempt to do. --- ARCHITECTURE.md | 77 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 ARCHITECTURE.md diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 00000000000..912780d803b --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,77 @@ +# Architecture + +OpenPype is a monolithic Python project that bundles several parts, this document will try to give a birds eye overview of the project and, to a certain degree, each of the sub-projects. +The current file structure looks like this: + +``` +. +├── common - Code in this folder is backend portion of Addon distribution logic for v4 server. +├── docs - Documentation of the source code. +├── igniter - The OpenPype bootstrapper, deals with running version resolution and setting up the connection to the mongodb. +├── openpype - The actual OpenPype core package. +├── schema - Collection of JSON files describing schematics of objects. This follows Avalon's convention. +├── tests - Integration and unit tests. +├── tools - Conveninece scripts to perform common actions (in both bash and ps1). +├── vendor - When using the igniter, it deploys third party tools in here, such as ffmpeg. +└── website - Source files for https://openpype.io/ which is Docusaursus (https://docusaurus.io/). +``` + +The core functionality of the pipeline can be found in `igniter` and `openpype`, which in turn rely on the `schema` files, whenever you build (or download a pre-built) version of OpenPype, these two are bundled in there, and `Igniter` is the entry point. + + +## Igniter + +It's the setup and update tool for OpenPype, unless you want to package `openpype` separately and deal with all the config manually, this will most likely be your entry point. + +``` +igniter/ +├── bootstrap_repos.py - Module that will find or install OpenPype versions in the system. +├── __init__.py - Igniter entry point. +├── install_dialog.py- Show dialog for choosing central pype repository. +├── install_thread.py - Threading helpers for the install process. +├── __main__.py - Like `__init__.py` ? +├── message_dialog.py - Qt Dialog with a message and "Ok" button. +├── nice_progress_bar.py - Fancy Qt progress bar. +├── splash.txt - ASCII art for the terminal installer. +├── stylesheet.css - Installer Qt styles. +├── terminal_splash.py - Terminal installer animation, relies in `splash.txt`. +├── tools.py - Collection of methods that don't fit in other modules. +├── update_thread.py - Threading helper to update existing OpenPype installs. +├── update_window.py - Qt UI to update OpenPype installs. +├── user_settings.py - Interface for the OpenPype user settings. +└── version.py - Igniter's version number. +``` + +## OpenPype + +This is the main package of the OpenPype logic, it could be loosely described as a combination of [Avalon](https://getavalon.github.io), [Pyblish](https://pyblish.com/) and glue around those with custom OpenPype only elements, things are in progress of being moved around to better prepare for V4, which will be released under a new name AYON. + +``` +openpype/ +├── client - Interface for the MongoDB. +├── hooks - Hooks to be executed on certain OpenPype Applications defined in `openpype.lib.applications`. +├── host - Base class for the different hosts. +├── hosts - Integration with the different DCCs (hosts) using the `host` base class. +├── lib - Libraries that stitch together the package, some have been moved into other parts. +├── modules - OpenPype modules should contain separated logic of specific kind of implementation, such as Ftrack connection and its python API. +├── pipeline - Core of the OpenPype pipeline, handles creation of data, publishing, etc. +├── plugins - Global/core plugins for loader and publisher tool. +├── resources - Icons, fonts, etc. +├── scripts - Loose scipts that get run by tools/publishers. +├── settings - OpenPype settings interface. +├── style - Qt styling. +├── tests - Unit tests. +├── tools - Core tools, check out https://openpype.io/docs/artist_tools. +├── vendor - Vendoring of needed required Python packes. +├── widgets - Common re-usable Qt Widgets. +├── action.py - LEGACY: Lives now in `openpype.pipeline.publish.action` Pyblish actions. +├── cli.py - Command line interface, leverages `click`. +├── __init__.py - Sets two constants. +├── __main__.py - Entry point, calls the `cli.py` +├── plugin.py - Pyblish plugins. +├── pype_commands.py - Implementation of OpenPype commands. +└── version.py - Current version number. +``` + + + From 182bc4b5e866a8a756f020bf79617e38e749743d Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 11 Mar 2023 20:20:18 +0100 Subject: [PATCH 405/898] Fix #4357: Move Look Assigner tool to maya since it's Maya only --- openpype/hosts/maya/api/customize.py | 3 +- openpype/hosts/maya/api/menu.py | 3 +- openpype/hosts/maya/tools/__init__.py | 26 +++++++++++++++ .../maya}/tools/mayalookassigner/LICENSE | 0 .../maya}/tools/mayalookassigner/__init__.py | 0 .../maya}/tools/mayalookassigner/app.py | 0 .../maya}/tools/mayalookassigner/commands.py | 0 .../maya}/tools/mayalookassigner/models.py | 0 .../maya}/tools/mayalookassigner/views.py | 0 .../tools/mayalookassigner/vray_proxies.py | 0 .../maya}/tools/mayalookassigner/widgets.py | 0 openpype/tools/utils/host_tools.py | 32 ------------------- 12 files changed, 30 insertions(+), 34 deletions(-) create mode 100644 openpype/hosts/maya/tools/__init__.py rename openpype/{ => hosts/maya}/tools/mayalookassigner/LICENSE (100%) rename openpype/{ => hosts/maya}/tools/mayalookassigner/__init__.py (100%) rename openpype/{ => hosts/maya}/tools/mayalookassigner/app.py (100%) rename openpype/{ => hosts/maya}/tools/mayalookassigner/commands.py (100%) rename openpype/{ => hosts/maya}/tools/mayalookassigner/models.py (100%) rename openpype/{ => hosts/maya}/tools/mayalookassigner/views.py (100%) rename openpype/{ => hosts/maya}/tools/mayalookassigner/vray_proxies.py (100%) rename openpype/{ => hosts/maya}/tools/mayalookassigner/widgets.py (100%) diff --git a/openpype/hosts/maya/api/customize.py b/openpype/hosts/maya/api/customize.py index f66858dfb6b..f4c4d6ed887 100644 --- a/openpype/hosts/maya/api/customize.py +++ b/openpype/hosts/maya/api/customize.py @@ -11,6 +11,7 @@ from openpype import resources from openpype.tools.utils import host_tools from .lib import get_main_window +from ..tools import show_look_assigner log = logging.getLogger(__name__) @@ -112,7 +113,7 @@ def override_toolbox_ui(): annotation="Look Manager", label="Look Manager", image=os.path.join(icons, "lookmanager.png"), - command=host_tools.show_look_assigner, + command=show_look_assigner, width=icon_size, height=icon_size, parent=parent diff --git a/openpype/hosts/maya/api/menu.py b/openpype/hosts/maya/api/menu.py index 0f48a133a61..efd9d414b6e 100644 --- a/openpype/hosts/maya/api/menu.py +++ b/openpype/hosts/maya/api/menu.py @@ -12,6 +12,7 @@ from openpype.tools.utils import host_tools from openpype.hosts.maya.api import lib, lib_rendersettings from .lib import get_main_window, IS_HEADLESS +from ..tools import show_look_assigner from .workfile_template_builder import ( create_placeholder, @@ -139,7 +140,7 @@ def deferred(): cmds.menuItem( "Look assigner...", - command=lambda *args: host_tools.show_look_assigner( + command=lambda *args: show_look_assigner( parent_widget ) ) diff --git a/openpype/hosts/maya/tools/__init__.py b/openpype/hosts/maya/tools/__init__.py new file mode 100644 index 00000000000..a83bb363104 --- /dev/null +++ b/openpype/hosts/maya/tools/__init__.py @@ -0,0 +1,26 @@ +from ....tools.utils.host_tools import HostToolsHelper, qt_app_context + +class MayaToolsSingleton: + _look_assigner = None + + +def get_look_assigner_tool(parent): + """Create, cache and return look assigner tool window.""" + if self._look_assigner is None: + from .mayalookassigner import MayaLookAssignerWindow + mayalookassigner_window = MayaLookAssignerWindow(parent) + MayaToolsSingleton._look_assigner = mayalookassigner_window + return MayaToolsSingleton._look_assigner + + +def show_look_assigner(parent=None): + """Look manager is Maya specific tool for look management.""" + + with qt_app_context(): + look_assigner_tool = get_look_assigner_tool(parent) + look_assigner_tool.show() + + # Pull window to the front. + look_assigner_tool.raise_() + look_assigner_tool.activateWindow() + look_assigner_tool.showNormal() \ No newline at end of file diff --git a/openpype/tools/mayalookassigner/LICENSE b/openpype/hosts/maya/tools/mayalookassigner/LICENSE similarity index 100% rename from openpype/tools/mayalookassigner/LICENSE rename to openpype/hosts/maya/tools/mayalookassigner/LICENSE diff --git a/openpype/tools/mayalookassigner/__init__.py b/openpype/hosts/maya/tools/mayalookassigner/__init__.py similarity index 100% rename from openpype/tools/mayalookassigner/__init__.py rename to openpype/hosts/maya/tools/mayalookassigner/__init__.py diff --git a/openpype/tools/mayalookassigner/app.py b/openpype/hosts/maya/tools/mayalookassigner/app.py similarity index 100% rename from openpype/tools/mayalookassigner/app.py rename to openpype/hosts/maya/tools/mayalookassigner/app.py diff --git a/openpype/tools/mayalookassigner/commands.py b/openpype/hosts/maya/tools/mayalookassigner/commands.py similarity index 100% rename from openpype/tools/mayalookassigner/commands.py rename to openpype/hosts/maya/tools/mayalookassigner/commands.py diff --git a/openpype/tools/mayalookassigner/models.py b/openpype/hosts/maya/tools/mayalookassigner/models.py similarity index 100% rename from openpype/tools/mayalookassigner/models.py rename to openpype/hosts/maya/tools/mayalookassigner/models.py diff --git a/openpype/tools/mayalookassigner/views.py b/openpype/hosts/maya/tools/mayalookassigner/views.py similarity index 100% rename from openpype/tools/mayalookassigner/views.py rename to openpype/hosts/maya/tools/mayalookassigner/views.py diff --git a/openpype/tools/mayalookassigner/vray_proxies.py b/openpype/hosts/maya/tools/mayalookassigner/vray_proxies.py similarity index 100% rename from openpype/tools/mayalookassigner/vray_proxies.py rename to openpype/hosts/maya/tools/mayalookassigner/vray_proxies.py diff --git a/openpype/tools/mayalookassigner/widgets.py b/openpype/hosts/maya/tools/mayalookassigner/widgets.py similarity index 100% rename from openpype/tools/mayalookassigner/widgets.py rename to openpype/hosts/maya/tools/mayalookassigner/widgets.py diff --git a/openpype/tools/utils/host_tools.py b/openpype/tools/utils/host_tools.py index e8593a8ae2a..ac242d24d21 100644 --- a/openpype/tools/utils/host_tools.py +++ b/openpype/tools/utils/host_tools.py @@ -38,7 +38,6 @@ def __init__(self, parent=None): self._subset_manager_tool = None self._scene_inventory_tool = None self._library_loader_tool = None - self._look_assigner_tool = None self._experimental_tools_dialog = None @property @@ -219,27 +218,6 @@ def _discover_pyblish_gui(self): raise ImportError("No Pyblish GUI found") - def get_look_assigner_tool(self, parent): - """Create, cache and return look assigner tool window.""" - if self._look_assigner_tool is None: - from openpype.tools.mayalookassigner import MayaLookAssignerWindow - - mayalookassigner_window = MayaLookAssignerWindow(parent) - self._look_assigner_tool = mayalookassigner_window - return self._look_assigner_tool - - def show_look_assigner(self, parent=None): - """Look manager is Maya specific tool for look management.""" - - with qt_app_context(): - look_assigner_tool = self.get_look_assigner_tool(parent) - look_assigner_tool.show() - - # Pull window to the front. - look_assigner_tool.raise_() - look_assigner_tool.activateWindow() - look_assigner_tool.showNormal() - def get_experimental_tools_dialog(self, parent=None): """Dialog of experimental tools. @@ -315,9 +293,6 @@ def get_tool_by_name(self, tool_name, parent=None, *args, **kwargs): elif tool_name == "sceneinventory": return self.get_scene_inventory_tool(parent, *args, **kwargs) - elif tool_name == "lookassigner": - return self.get_look_assigner_tool(parent, *args, **kwargs) - elif tool_name == "publish": self.log.info("Can't return publish tool window.") @@ -356,9 +331,6 @@ def show_tool_by_name(self, tool_name, parent=None, *args, **kwargs): elif tool_name == "sceneinventory": self.show_scene_inventory(parent, *args, **kwargs) - elif tool_name == "lookassigner": - self.show_look_assigner(parent, *args, **kwargs) - elif tool_name == "publish": self.show_publish(parent, *args, **kwargs) @@ -436,10 +408,6 @@ def show_scene_inventory(parent=None): _SingletonPoint.show_tool_by_name("sceneinventory", parent) -def show_look_assigner(parent=None): - _SingletonPoint.show_tool_by_name("lookassigner", parent) - - def show_publish(parent=None): _SingletonPoint.show_tool_by_name("publish", parent) From 1d62d15c206515669f6fb6acce6da3a98d4a9657 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 11 Mar 2023 20:24:52 +0100 Subject: [PATCH 406/898] Shush hound --- openpype/hosts/maya/tools/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/maya/tools/__init__.py b/openpype/hosts/maya/tools/__init__.py index a83bb363104..ccb014a3b91 100644 --- a/openpype/hosts/maya/tools/__init__.py +++ b/openpype/hosts/maya/tools/__init__.py @@ -1,4 +1,4 @@ -from ....tools.utils.host_tools import HostToolsHelper, qt_app_context +from ....tools.utils.host_tools import qt_app_context class MayaToolsSingleton: _look_assigner = None @@ -6,7 +6,7 @@ class MayaToolsSingleton: def get_look_assigner_tool(parent): """Create, cache and return look assigner tool window.""" - if self._look_assigner is None: + if MayaToolsSingleton._look_assigner is None: from .mayalookassigner import MayaLookAssignerWindow mayalookassigner_window = MayaLookAssignerWindow(parent) MayaToolsSingleton._look_assigner = mayalookassigner_window @@ -23,4 +23,4 @@ def show_look_assigner(parent=None): # Pull window to the front. look_assigner_tool.raise_() look_assigner_tool.activateWindow() - look_assigner_tool.showNormal() \ No newline at end of file + look_assigner_tool.showNormal() From 888dbdb569d8c9b658be578c846a7bd0727dd8c7 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 13 Mar 2023 13:38:59 +0100 Subject: [PATCH 407/898] Relative import to absolute import Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- openpype/hosts/maya/tools/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/tools/__init__.py b/openpype/hosts/maya/tools/__init__.py index ccb014a3b91..643c90bacd0 100644 --- a/openpype/hosts/maya/tools/__init__.py +++ b/openpype/hosts/maya/tools/__init__.py @@ -1,4 +1,4 @@ -from ....tools.utils.host_tools import qt_app_context +from openpype.tools.utils.host_tools import qt_app_context class MayaToolsSingleton: _look_assigner = None From 11b1b98d25f9937c49b977e5e12c4b0491669ae8 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 14 Mar 2023 09:56:42 +0100 Subject: [PATCH 408/898] Shush hound --- openpype/hosts/maya/tools/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/maya/tools/__init__.py b/openpype/hosts/maya/tools/__init__.py index 643c90bacd0..bd1e302cd2b 100644 --- a/openpype/hosts/maya/tools/__init__.py +++ b/openpype/hosts/maya/tools/__init__.py @@ -1,5 +1,6 @@ from openpype.tools.utils.host_tools import qt_app_context + class MayaToolsSingleton: _look_assigner = None From 1e458d6d1d67b2eb88c0d6e649fd80f7192f08ce Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 14 Mar 2023 14:44:29 +0100 Subject: [PATCH 409/898] global and nuke: farm publishing workflow fixes --- openpype/hosts/nuke/plugins/publish/extract_review_data.py | 2 +- .../hosts/nuke/plugins/publish/extract_review_data_lut.py | 7 ++++++- .../hosts/nuke/plugins/publish/extract_review_data_mov.py | 5 +---- openpype/hosts/nuke/plugins/publish/extract_thumbnail.py | 2 +- .../deadline/plugins/publish/submit_nuke_deadline.py | 5 +++-- .../modules/deadline/plugins/publish/submit_publish_job.py | 4 ++++ .../deadline/plugins/publish/validate_deadline_pools.py | 4 ++++ 7 files changed, 20 insertions(+), 9 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/extract_review_data.py b/openpype/hosts/nuke/plugins/publish/extract_review_data.py index dee82482957..c221af40fba 100644 --- a/openpype/hosts/nuke/plugins/publish/extract_review_data.py +++ b/openpype/hosts/nuke/plugins/publish/extract_review_data.py @@ -25,7 +25,7 @@ def process(self, instance): # review can be removed since `ProcessSubmittedJobOnFarm` will create # reviewable representation if needed if ( - "render.farm" in instance.data["families"] + instance.data.get("farm") and "review" in instance.data["families"] ): instance.data["families"].remove("review") diff --git a/openpype/hosts/nuke/plugins/publish/extract_review_data_lut.py b/openpype/hosts/nuke/plugins/publish/extract_review_data_lut.py index 67779e9599e..e4b7b155cd1 100644 --- a/openpype/hosts/nuke/plugins/publish/extract_review_data_lut.py +++ b/openpype/hosts/nuke/plugins/publish/extract_review_data_lut.py @@ -49,7 +49,12 @@ def process(self, instance): exporter.stagingDir, exporter.file).replace("\\", "/") instance.data["representations"] += data["representations"] - if "render.farm" in families: + # review can be removed since `ProcessSubmittedJobOnFarm` will create + # reviewable representation if needed + if ( + instance.data.get("farm") + and "review" in instance.data["families"] + ): instance.data["families"].remove("review") self.log.debug( diff --git a/openpype/hosts/nuke/plugins/publish/extract_review_data_mov.py b/openpype/hosts/nuke/plugins/publish/extract_review_data_mov.py index 3fcfc2a4b51..956d1a54a34 100644 --- a/openpype/hosts/nuke/plugins/publish/extract_review_data_mov.py +++ b/openpype/hosts/nuke/plugins/publish/extract_review_data_mov.py @@ -105,10 +105,7 @@ def process(self, instance): self, instance, o_name, o_data["extension"], multiple_presets) - if ( - "render.farm" in families or - "prerender.farm" in families - ): + if instance.data.get("farm"): if "review" in instance.data["families"]: instance.data["families"].remove("review") diff --git a/openpype/hosts/nuke/plugins/publish/extract_thumbnail.py b/openpype/hosts/nuke/plugins/publish/extract_thumbnail.py index a1a0e241c07..f391ca1e7c2 100644 --- a/openpype/hosts/nuke/plugins/publish/extract_thumbnail.py +++ b/openpype/hosts/nuke/plugins/publish/extract_thumbnail.py @@ -31,7 +31,7 @@ class ExtractThumbnail(publish.Extractor): def process(self, instance): - if "render.farm" in instance.data["families"]: + if instance.data.get("farm"): return with napi.maintained_selection(): diff --git a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py index 9abe8dec8b1..cc069cf51a8 100644 --- a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py @@ -81,6 +81,7 @@ def get_attribute_defs(cls): def process(self, instance): if not instance.data.get("farm"): + self.log.info("Skipping local instance.") return instance.data["attributeValues"] = self.get_attr_values_from_data( @@ -171,10 +172,10 @@ def process(self, instance): resp.json()["_id"]) # redefinition of families - if "render" in family: + if "render" in instance.data["family"]: instance.data['family'] = 'write' families.insert(0, "render2d") - elif "prerender" in family: + elif "prerender" in instance.data["family"]: instance.data['family'] = 'write' families.insert(0, "prerender") instance.data["families"] = families diff --git a/openpype/modules/deadline/plugins/publish/submit_publish_job.py b/openpype/modules/deadline/plugins/publish/submit_publish_job.py index 53c09ad22f9..0d0698c21f9 100644 --- a/openpype/modules/deadline/plugins/publish/submit_publish_job.py +++ b/openpype/modules/deadline/plugins/publish/submit_publish_job.py @@ -756,6 +756,10 @@ def process(self, instance): instance (pyblish.api.Instance): Instance data. """ + if not instance.data.get("farm"): + self.log.info("Skipping local instance.") + return + data = instance.data.copy() context = instance.context self.context = context diff --git a/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py b/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py index 78eed17c986..05afa5080d8 100644 --- a/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py +++ b/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py @@ -21,6 +21,10 @@ class ValidateDeadlinePools(OptionalPyblishPluginMixin, optional = True def process(self, instance): + if not instance.data.get("farm"): + self.log.info("Skipping local instance.") + return + # get default deadline webservice url from deadline module deadline_url = instance.context.data["defaultDeadline"] self.log.info("deadline_url::{}".format(deadline_url)) From f1b39494be1027d757b359336dda4a7869c8764c Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Tue, 14 Mar 2023 14:50:15 +0000 Subject: [PATCH 410/898] Update openpype/modules/deadline/plugins/publish/submit_maya_deadline.py Co-authored-by: Kayla Man <64118225+moonyuet@users.noreply.github.com> --- .../modules/deadline/plugins/publish/submit_maya_deadline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py index f7fc608f307..53ecb9063be 100644 --- a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py @@ -860,7 +860,7 @@ def _format_tiles( right = (tile_x * w_space) - 1 # Job info - key = "OutputFilename{}Tile{}".format(index, tile) + key = "OutputFilename{}".format(index) out["JobInfo"][key] = new_filename # Plugin Info From ecfb57913d52325323d1c2fcb8b6519e03ff201b Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 14 Mar 2023 16:05:40 +0100 Subject: [PATCH 411/898] update yarn.lock --- website/yarn.lock | 12882 ++++++++++++++++++++++---------------------- 1 file changed, 6475 insertions(+), 6407 deletions(-) diff --git a/website/yarn.lock b/website/yarn.lock index d250e48b9da..2edf57abf4e 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -3,56 +3,56 @@ "@algolia/autocomplete-core@1.5.2": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.5.2.tgz#ec0178e07b44fd74a057728ac157291b26cecf37" - integrity sha512-DY0bhyczFSS1b/CqJlTE/nQRtnTAHl6IemIkBy0nEWnhDzRDdtdx4p5Uuk3vwAFxwEEgi1WqKwgSSMx6DpNL4A== + "integrity" "sha512-DY0bhyczFSS1b/CqJlTE/nQRtnTAHl6IemIkBy0nEWnhDzRDdtdx4p5Uuk3vwAFxwEEgi1WqKwgSSMx6DpNL4A==" + "resolved" "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.5.2.tgz" + "version" "1.5.2" dependencies: "@algolia/autocomplete-shared" "1.5.2" "@algolia/autocomplete-preset-algolia@1.5.2": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.5.2.tgz#36c5638cc6dba6ea46a86e5a0314637ca40a77ca" - integrity sha512-3MRYnYQFJyovANzSX2CToS6/5cfVjbLLqFsZTKcvF3abhQzxbqwwaMBlJtt620uBUOeMzhdfasKhCc40+RHiZw== + "integrity" "sha512-3MRYnYQFJyovANzSX2CToS6/5cfVjbLLqFsZTKcvF3abhQzxbqwwaMBlJtt620uBUOeMzhdfasKhCc40+RHiZw==" + "resolved" "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.5.2.tgz" + "version" "1.5.2" dependencies: "@algolia/autocomplete-shared" "1.5.2" "@algolia/autocomplete-shared@1.5.2": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.5.2.tgz#e157f9ad624ab8fd940ff28bd2094cdf199cdd79" - integrity sha512-ylQAYv5H0YKMfHgVWX0j0NmL8XBcAeeeVQUmppnnMtzDbDnca6CzhKj3Q8eF9cHCgcdTDdb5K+3aKyGWA0obug== + "integrity" "sha512-ylQAYv5H0YKMfHgVWX0j0NmL8XBcAeeeVQUmppnnMtzDbDnca6CzhKj3Q8eF9cHCgcdTDdb5K+3aKyGWA0obug==" + "resolved" "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.5.2.tgz" + "version" "1.5.2" "@algolia/cache-browser-local-storage@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.12.1.tgz#23f4f219963b96918d0524acd09d4d646541d888" - integrity sha512-ERFFOnC9740xAkuO0iZTQqm2AzU7Dpz/s+g7o48GlZgx5p9GgNcsuK5eS0GoW/tAK+fnKlizCtlFHNuIWuvfsg== + "integrity" "sha512-ERFFOnC9740xAkuO0iZTQqm2AzU7Dpz/s+g7o48GlZgx5p9GgNcsuK5eS0GoW/tAK+fnKlizCtlFHNuIWuvfsg==" + "resolved" "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/cache-common" "4.12.1" "@algolia/cache-common@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.12.1.tgz#d3f1676ca9c404adce0f78d68f6381bedb44cd9c" - integrity sha512-UugTER3V40jT+e19Dmph5PKMeliYKxycNPwrPNADin0RcWNfT2QksK9Ff2N2W7UKraqMOzoeDb4LAJtxcK1a8Q== + "integrity" "sha512-UugTER3V40jT+e19Dmph5PKMeliYKxycNPwrPNADin0RcWNfT2QksK9Ff2N2W7UKraqMOzoeDb4LAJtxcK1a8Q==" + "resolved" "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.12.1.tgz" + "version" "4.12.1" "@algolia/cache-in-memory@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.12.1.tgz#0ef6aac2f8feab5b46fc130beb682bbd21b55244" - integrity sha512-U6iaunaxK1lHsAf02UWF58foKFEcrVLsHwN56UkCtwn32nlP9rz52WOcHsgk6TJrL8NDcO5swMjtOQ5XHESFLw== + "integrity" "sha512-U6iaunaxK1lHsAf02UWF58foKFEcrVLsHwN56UkCtwn32nlP9rz52WOcHsgk6TJrL8NDcO5swMjtOQ5XHESFLw==" + "resolved" "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/cache-common" "4.12.1" "@algolia/client-account@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.12.1.tgz#e838c9283db2fab32a425dd13c77da321d48fd8b" - integrity sha512-jGo4ConJNoMdTCR2zouO0jO/JcJmzOK6crFxMMLvdnB1JhmMbuIKluOTJVlBWeivnmcsqb7r0v7qTCPW5PAyxQ== + "integrity" "sha512-jGo4ConJNoMdTCR2zouO0jO/JcJmzOK6crFxMMLvdnB1JhmMbuIKluOTJVlBWeivnmcsqb7r0v7qTCPW5PAyxQ==" + "resolved" "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/client-common" "4.12.1" "@algolia/client-search" "4.12.1" "@algolia/transporter" "4.12.1" "@algolia/client-analytics@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.12.1.tgz#2976d658655a1590cf84cfb596aa75a204f6dec4" - integrity sha512-h1It7KXzIthlhuhfBk7LteYq72tym9maQDUsyRW0Gft8b6ZQahnRak9gcCvKwhcJ1vJoP7T7JrNYGiYSicTD9g== + "integrity" "sha512-h1It7KXzIthlhuhfBk7LteYq72tym9maQDUsyRW0Gft8b6ZQahnRak9gcCvKwhcJ1vJoP7T7JrNYGiYSicTD9g==" + "resolved" "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/client-common" "4.12.1" "@algolia/client-search" "4.12.1" @@ -60,99 +60,121 @@ "@algolia/transporter" "4.12.1" "@algolia/client-common@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.12.1.tgz#104ccefe96bda3ff926bc70c31ff6d17c41b6107" - integrity sha512-obnJ8eSbv+h94Grk83DTGQ3bqhViSWureV6oK1s21/KMGWbb3DkduHm+lcwFrMFkjSUSzosLBHV9EQUIBvueTw== + "integrity" "sha512-obnJ8eSbv+h94Grk83DTGQ3bqhViSWureV6oK1s21/KMGWbb3DkduHm+lcwFrMFkjSUSzosLBHV9EQUIBvueTw==" + "resolved" "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/requester-common" "4.12.1" "@algolia/transporter" "4.12.1" "@algolia/client-personalization@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.12.1.tgz#f63d1890f95de850e1c8e41c1d57adda521d9e7f" - integrity sha512-sMSnjjPjRgByGHYygV+5L/E8a6RgU7l2GbpJukSzJ9GRY37tHmBHuvahv8JjdCGJ2p7QDYLnQy5bN5Z02qjc7Q== + "integrity" "sha512-sMSnjjPjRgByGHYygV+5L/E8a6RgU7l2GbpJukSzJ9GRY37tHmBHuvahv8JjdCGJ2p7QDYLnQy5bN5Z02qjc7Q==" + "resolved" "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/client-common" "4.12.1" "@algolia/requester-common" "4.12.1" "@algolia/transporter" "4.12.1" -"@algolia/client-search@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.12.1.tgz#fcd7a974be5d39d5c336d7f2e89577ffa66aefdd" - integrity sha512-MwwKKprfY6X2nJ5Ki/ccXM2GDEePvVjZnnoOB2io3dLKW4fTqeSRlC5DRXeFD7UM0vOPPHr4ItV2aj19APKNVQ== +"@algolia/client-search@^4.9.1", "@algolia/client-search@4.12.1": + "integrity" "sha512-MwwKKprfY6X2nJ5Ki/ccXM2GDEePvVjZnnoOB2io3dLKW4fTqeSRlC5DRXeFD7UM0vOPPHr4ItV2aj19APKNVQ==" + "resolved" "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/client-common" "4.12.1" "@algolia/requester-common" "4.12.1" "@algolia/transporter" "4.12.1" "@algolia/events@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950" - integrity sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ== + "integrity" "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==" + "resolved" "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz" + "version" "4.0.1" "@algolia/logger-common@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.12.1.tgz#d6501b4d9d242956257ba8e10f6b4bbf6863baa4" - integrity sha512-fCgrzlXGATNqdFTxwx0GsyPXK+Uqrx1SZ3iuY2VGPPqdt1a20clAG2n2OcLHJpvaa6vMFPlJyWvbqAgzxdxBlQ== + "integrity" "sha512-fCgrzlXGATNqdFTxwx0GsyPXK+Uqrx1SZ3iuY2VGPPqdt1a20clAG2n2OcLHJpvaa6vMFPlJyWvbqAgzxdxBlQ==" + "resolved" "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.12.1.tgz" + "version" "4.12.1" "@algolia/logger-console@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.12.1.tgz#841edd39dd5c5530a69fc66084bfee3254dd0807" - integrity sha512-0owaEnq/davngQMYqxLA4KrhWHiXujQ1CU3FFnyUcMyBR7rGHI48zSOUpqnsAXrMBdSH6rH5BDkSUUFwsh8RkQ== + "integrity" "sha512-0owaEnq/davngQMYqxLA4KrhWHiXujQ1CU3FFnyUcMyBR7rGHI48zSOUpqnsAXrMBdSH6rH5BDkSUUFwsh8RkQ==" + "resolved" "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/logger-common" "4.12.1" "@algolia/requester-browser-xhr@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.12.1.tgz#2d0c18ee188d7cae0e4a930e5e89989e3c4a816b" - integrity sha512-OaMxDyG0TZG0oqz1lQh9e3woantAG1bLnuwq3fmypsrQxra4IQZiyn1x+kEb69D2TcXApI5gOgrD4oWhtEVMtw== + "integrity" "sha512-OaMxDyG0TZG0oqz1lQh9e3woantAG1bLnuwq3fmypsrQxra4IQZiyn1x+kEb69D2TcXApI5gOgrD4oWhtEVMtw==" + "resolved" "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/requester-common" "4.12.1" "@algolia/requester-common@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.12.1.tgz#95bb6539da7199da3e205341cea8f27267f7af29" - integrity sha512-XWIrWQNJ1vIrSuL/bUk3ZwNMNxl+aWz6dNboRW6+lGTcMIwc3NBFE90ogbZKhNrFRff8zI4qCF15tjW+Fyhpow== + "integrity" "sha512-XWIrWQNJ1vIrSuL/bUk3ZwNMNxl+aWz6dNboRW6+lGTcMIwc3NBFE90ogbZKhNrFRff8zI4qCF15tjW+Fyhpow==" + "resolved" "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.12.1.tgz" + "version" "4.12.1" "@algolia/requester-node-http@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.12.1.tgz#c9df97ff1daa7e58c5c2b1f28cf7163005edccb0" - integrity sha512-awBtwaD+s0hxkA1aehYn8F0t9wqGoBVWgY4JPHBmp1ChO3pK7RKnnvnv7QQa9vTlllX29oPt/BBVgMo1Z3n1Qg== + "integrity" "sha512-awBtwaD+s0hxkA1aehYn8F0t9wqGoBVWgY4JPHBmp1ChO3pK7RKnnvnv7QQa9vTlllX29oPt/BBVgMo1Z3n1Qg==" + "resolved" "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/requester-common" "4.12.1" "@algolia/transporter@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.12.1.tgz#61b9829916c474f42e2d4a6eada0d6c138379945" - integrity sha512-BGeNgdEHc6dXIk2g8kdlOoQ6fQ6OIaKQcplEj7HPoi+XZUeAvRi3Pff3QWd7YmybWkjzd9AnTzieTASDWhL+sQ== + "integrity" "sha512-BGeNgdEHc6dXIk2g8kdlOoQ6fQ6OIaKQcplEj7HPoi+XZUeAvRi3Pff3QWd7YmybWkjzd9AnTzieTASDWhL+sQ==" + "resolved" "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/cache-common" "4.12.1" "@algolia/logger-common" "4.12.1" "@algolia/requester-common" "4.12.1" -"@ampproject/remapping@^2.1.0": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" - integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== +"@ampproject/remapping@^2.2.0": + "integrity" "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==" + "resolved" "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz" + "version" "2.2.0" dependencies: - "@jridgewell/trace-mapping" "^0.3.0" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.8.3": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== - dependencies: - "@babel/highlight" "^7.16.7" - -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4", "@babel/compat-data@^7.16.8", "@babel/compat-data@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.0.tgz#86850b8597ea6962089770952075dcaabb8dba34" - integrity sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng== + "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/trace-mapping" "^0.3.9" -"@babel/core@7.12.9": - version "7.12.9" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.9.tgz#fd450c4ec10cdbb980e2928b7aa7a28484593fc8" - integrity sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.8.3": + "integrity" "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==" + "resolved" "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/highlight" "^7.18.6" + +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.8", "@babel/compat-data@^7.17.0", "@babel/compat-data@^7.20.5": + "integrity" "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==" + "resolved" "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz" + "version" "7.21.0" + +"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.12.0", "@babel/core@^7.13.0", "@babel/core@^7.15.5", "@babel/core@^7.16.0", "@babel/core@^7.4.0-0": + "integrity" "sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==" + "resolved" "https://registry.npmjs.org/@babel/core/-/core-7.21.3.tgz" + "version" "7.21.3" + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.21.3" + "@babel/helper-compilation-targets" "^7.20.7" + "@babel/helper-module-transforms" "^7.21.2" + "@babel/helpers" "^7.21.0" + "@babel/parser" "^7.21.3" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.21.3" + "@babel/types" "^7.21.3" + "convert-source-map" "^1.7.0" + "debug" "^4.1.0" + "gensync" "^1.0.0-beta.2" + "json5" "^2.2.2" + "semver" "^6.3.0" + +"@babel/core@^7.11.6", "@babel/core@7.12.9": + "integrity" "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==" + "resolved" "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz" + "version" "7.12.9" dependencies: "@babel/code-frame" "^7.10.4" "@babel/generator" "^7.12.5" @@ -162,74 +184,55 @@ "@babel/template" "^7.12.7" "@babel/traverse" "^7.12.9" "@babel/types" "^7.12.7" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.1" - json5 "^2.1.2" - lodash "^4.17.19" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - -"@babel/core@^7.15.5", "@babel/core@^7.16.0": - version "7.17.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.5.tgz#6cd2e836058c28f06a4ca8ee7ed955bbf37c8225" - integrity sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA== - dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.3" - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helpers" "^7.17.2" - "@babel/parser" "^7.17.3" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.3" - "@babel/types" "^7.17.0" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.1.2" - semver "^6.3.0" - -"@babel/generator@^7.12.5", "@babel/generator@^7.16.0", "@babel/generator@^7.17.3": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.3.tgz#a2c30b0c4f89858cb87050c3ffdfd36bdf443200" - integrity sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg== - dependencies: - "@babel/types" "^7.17.0" - jsesc "^2.5.1" - source-map "^0.5.0" + "convert-source-map" "^1.7.0" + "debug" "^4.1.0" + "gensync" "^1.0.0-beta.1" + "json5" "^2.1.2" + "lodash" "^4.17.19" + "resolve" "^1.3.2" + "semver" "^5.4.1" + "source-map" "^0.5.0" + +"@babel/generator@^7.12.5", "@babel/generator@^7.16.0", "@babel/generator@^7.21.3": + "integrity" "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==" + "resolved" "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz" + "version" "7.21.3" + dependencies: + "@babel/types" "^7.21.3" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + "jsesc" "^2.5.1" "@babel/helper-annotate-as-pure@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862" - integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw== + "integrity" "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==" + "resolved" "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/types" "^7.16.7" "@babel/helper-builder-binary-assignment-operator-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz#38d138561ea207f0f69eb1626a418e4f7e6a580b" - integrity sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA== + "integrity" "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==" + "resolved" "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-explode-assignable-expression" "^7.16.7" "@babel/types" "^7.16.7" -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b" - integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA== +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7", "@babel/helper-compilation-targets@^7.20.7": + "integrity" "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz" + "version" "7.20.7" dependencies: - "@babel/compat-data" "^7.16.4" - "@babel/helper-validator-option" "^7.16.7" - browserslist "^4.17.5" - semver "^6.3.0" + "@babel/compat-data" "^7.20.5" + "@babel/helper-validator-option" "^7.18.6" + "browserslist" "^4.21.3" + "lru-cache" "^5.1.1" + "semver" "^6.3.0" "@babel/helper-create-class-features-plugin@^7.16.10", "@babel/helper-create-class-features-plugin@^7.16.7": - version "7.17.1" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.1.tgz#9699f14a88833a7e055ce57dcd3ffdcd25186b21" - integrity sha512-JBdSr/LtyYIno/pNnJ75lBcqc3Z1XXujzPanHqjvvrhOA+DTceTFuJi8XjmWTZh4r3fsdfqaCMN0iZemdkxZHQ== + "integrity" "sha512-JBdSr/LtyYIno/pNnJ75lBcqc3Z1XXujzPanHqjvvrhOA+DTceTFuJi8XjmWTZh4r3fsdfqaCMN0iZemdkxZHQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.1.tgz" + "version" "7.17.1" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-environment-visitor" "^7.16.7" @@ -240,122 +243,112 @@ "@babel/helper-split-export-declaration" "^7.16.7" "@babel/helper-create-regexp-features-plugin@^7.16.7": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz#1dcc7d40ba0c6b6b25618997c5dbfd310f186fe1" - integrity sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA== + "integrity" "sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==" + "resolved" "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz" + "version" "7.17.0" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" - regexpu-core "^5.0.1" + "regexpu-core" "^5.0.1" "@babel/helper-define-polyfill-provider@^0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz#52411b445bdb2e676869e5a74960d2d3826d2665" - integrity sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA== + "integrity" "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==" + "resolved" "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz" + "version" "0.3.1" dependencies: "@babel/helper-compilation-targets" "^7.13.0" "@babel/helper-module-imports" "^7.12.13" "@babel/helper-plugin-utils" "^7.13.0" "@babel/traverse" "^7.13.0" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" - semver "^6.1.2" + "debug" "^4.1.1" + "lodash.debounce" "^4.0.8" + "resolve" "^1.14.2" + "semver" "^6.1.2" -"@babel/helper-environment-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" - integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== - dependencies: - "@babel/types" "^7.16.7" +"@babel/helper-environment-visitor@^7.16.7", "@babel/helper-environment-visitor@^7.18.9": + "integrity" "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==" + "resolved" "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz" + "version" "7.18.9" "@babel/helper-explode-assignable-expression@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz#12a6d8522fdd834f194e868af6354e8650242b7a" - integrity sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ== + "integrity" "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/types" "^7.16.7" -"@babel/helper-function-name@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" - integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== +"@babel/helper-function-name@^7.16.7", "@babel/helper-function-name@^7.21.0": + "integrity" "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==" + "resolved" "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz" + "version" "7.21.0" dependencies: - "@babel/helper-get-function-arity" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/types" "^7.16.7" + "@babel/template" "^7.20.7" + "@babel/types" "^7.21.0" -"@babel/helper-get-function-arity@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419" - integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== +"@babel/helper-hoist-variables@^7.16.7", "@babel/helper-hoist-variables@^7.18.6": + "integrity" "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==" + "resolved" "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz" + "version" "7.18.6" dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-hoist-variables@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" - integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== - dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.18.6" "@babel/helper-member-expression-to-functions@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz#42b9ca4b2b200123c3b7e726b0ae5153924905b0" - integrity sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q== + "integrity" "sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==" + "resolved" "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/types" "^7.16.7" -"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" - integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== +"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.18.6": + "integrity" "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==" + "resolved" "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz" + "version" "7.18.6" dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.18.6" -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz#7665faeb721a01ca5327ddc6bba15a5cb34b6a41" - integrity sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng== +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.16.7", "@babel/helper-module-transforms@^7.21.2": + "integrity" "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz" + "version" "7.21.2" dependencies: - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-simple-access" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/helper-validator-identifier" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.16.7" - "@babel/types" "^7.16.7" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.20.2" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.19.1" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.21.2" + "@babel/types" "^7.21.2" "@babel/helper-optimise-call-expression@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz#a34e3560605abbd31a18546bd2aad3e6d9a174f2" - integrity sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w== + "integrity" "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==" + "resolved" "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/types" "^7.16.7" -"@babel/helper-plugin-utils@7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" - integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== - "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" - integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== + "integrity" "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==" + "resolved" "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz" + "version" "7.16.7" + +"@babel/helper-plugin-utils@7.10.4": + "integrity" "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" + "resolved" "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz" + "version" "7.10.4" "@babel/helper-remap-async-to-generator@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz#29ffaade68a367e2ed09c90901986918d25e57e3" - integrity sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw== + "integrity" "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==" + "resolved" "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-wrap-function" "^7.16.8" "@babel/types" "^7.16.8" "@babel/helper-replace-supers@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz#e9f5f5f32ac90429c1a4bdec0f231ef0c2838ab1" - integrity sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw== + "integrity" "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==" + "resolved" "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-environment-visitor" "^7.16.7" "@babel/helper-member-expression-to-functions" "^7.16.7" @@ -363,173 +356,169 @@ "@babel/traverse" "^7.16.7" "@babel/types" "^7.16.7" -"@babel/helper-simple-access@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7" - integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g== +"@babel/helper-simple-access@^7.16.7", "@babel/helper-simple-access@^7.20.2": + "integrity" "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==" + "resolved" "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz" + "version" "7.20.2" dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.20.2" "@babel/helper-skip-transparent-expression-wrappers@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz#0ee3388070147c3ae051e487eca3ebb0e2e8bb09" - integrity sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw== + "integrity" "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==" + "resolved" "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz" + "version" "7.16.0" dependencies: "@babel/types" "^7.16.0" -"@babel/helper-split-export-declaration@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" - integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== +"@babel/helper-split-export-declaration@^7.16.7", "@babel/helper-split-export-declaration@^7.18.6": + "integrity" "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==" + "resolved" "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz" + "version" "7.18.6" dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.18.6" -"@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== +"@babel/helper-string-parser@^7.19.4": + "integrity" "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==" + "resolved" "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz" + "version" "7.19.4" -"@babel/helper-validator-option@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" - integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== +"@babel/helper-validator-identifier@^7.16.7", "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": + "integrity" "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==" + "resolved" "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz" + "version" "7.19.1" + +"@babel/helper-validator-option@^7.16.7", "@babel/helper-validator-option@^7.18.6": + "integrity" "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz" + "version" "7.21.0" "@babel/helper-wrap-function@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz#58afda087c4cd235de92f7ceedebca2c41274200" - integrity sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw== + "integrity" "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==" + "resolved" "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-function-name" "^7.16.7" "@babel/template" "^7.16.7" "@babel/traverse" "^7.16.8" "@babel/types" "^7.16.8" -"@babel/helpers@^7.12.5", "@babel/helpers@^7.17.2": - version "7.17.2" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.2.tgz#23f0a0746c8e287773ccd27c14be428891f63417" - integrity sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ== +"@babel/helpers@^7.12.5", "@babel/helpers@^7.21.0": + "integrity" "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==" + "resolved" "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz" + "version" "7.21.0" dependencies: - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.0" - "@babel/types" "^7.17.0" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.21.0" + "@babel/types" "^7.21.0" -"@babel/highlight@^7.16.7": - version "7.16.10" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" - integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== +"@babel/highlight@^7.18.6": + "integrity" "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==" + "resolved" "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz" + "version" "7.18.6" dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - chalk "^2.0.0" - js-tokens "^4.0.0" + "@babel/helper-validator-identifier" "^7.18.6" + "chalk" "^2.0.0" + "js-tokens" "^4.0.0" -"@babel/parser@^7.12.7", "@babel/parser@^7.16.4", "@babel/parser@^7.16.7", "@babel/parser@^7.17.3": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.3.tgz#b07702b982990bf6fdc1da5049a23fece4c5c3d0" - integrity sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA== +"@babel/parser@^7.12.7", "@babel/parser@^7.16.4", "@babel/parser@^7.20.7", "@babel/parser@^7.21.3": + "integrity" "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==" + "resolved" "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz" + "version" "7.21.3" "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz#4eda6d6c2a0aa79c70fa7b6da67763dfe2141050" - integrity sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg== + "integrity" "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz#cc001234dfc139ac45f6bcf801866198c8c72ff9" - integrity sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw== + "integrity" "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-proposal-optional-chaining" "^7.16.7" "@babel/plugin-proposal-async-generator-functions@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz#3bdd1ebbe620804ea9416706cd67d60787504bc8" - integrity sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ== + "integrity" "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-remap-async-to-generator" "^7.16.8" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-proposal-class-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz#925cad7b3b1a2fcea7e59ecc8eb5954f961f91b0" - integrity sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww== + "integrity" "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-create-class-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-proposal-class-static-block@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz#712357570b612106ef5426d13dc433ce0f200c2a" - integrity sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw== + "integrity" "sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-create-class-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-proposal-dynamic-import@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz#c19c897eaa46b27634a00fee9fb7d829158704b2" - integrity sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg== + "integrity" "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-proposal-export-namespace-from@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz#09de09df18445a5786a305681423ae63507a6163" - integrity sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA== + "integrity" "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" "@babel/plugin-proposal-json-strings@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz#9732cb1d17d9a2626a08c5be25186c195b6fa6e8" - integrity sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ== + "integrity" "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-proposal-logical-assignment-operators@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz#be23c0ba74deec1922e639832904be0bea73cdea" - integrity sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg== + "integrity" "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-proposal-nullish-coalescing-operator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz#141fc20b6857e59459d430c850a0011e36561d99" - integrity sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ== + "integrity" "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" "@babel/plugin-proposal-numeric-separator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz#d6b69f4af63fb38b6ca2558442a7fb191236eba9" - integrity sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw== + "integrity" "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz#def9bd03cea0f9b72283dac0ec22d289c7691069" - integrity sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.12.1" - "@babel/plugin-proposal-object-rest-spread@^7.16.7": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz#d9eb649a54628a51701aef7e0ea3d17e2b9dd390" - integrity sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw== + "integrity" "sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz" + "version" "7.17.3" dependencies: "@babel/compat-data" "^7.17.0" "@babel/helper-compilation-targets" "^7.16.7" @@ -537,35 +526,44 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-transform-parameters" "^7.16.7" +"@babel/plugin-proposal-object-rest-spread@7.12.1": + "integrity" "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz" + "version" "7.12.1" + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-transform-parameters" "^7.12.1" + "@babel/plugin-proposal-optional-catch-binding@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz#c623a430674ffc4ab732fd0a0ae7722b67cb74cf" - integrity sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA== + "integrity" "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-proposal-optional-chaining@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz#7cd629564724816c0e8a969535551f943c64c39a" - integrity sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA== + "integrity" "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-proposal-private-methods@^7.16.11": - version "7.16.11" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz#e8df108288555ff259f4527dbe84813aac3a1c50" - integrity sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw== + "integrity" "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz" + "version" "7.16.11" dependencies: "@babel/helper-create-class-features-plugin" "^7.16.10" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-proposal-private-property-in-object@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz#b0b8cef543c2c3d57e59e2c611994861d46a3fce" - integrity sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ== + "integrity" "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-create-class-features-plugin" "^7.16.7" @@ -573,166 +571,166 @@ "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-proposal-unicode-property-regex@^7.16.7", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz#635d18eb10c6214210ffc5ff4932552de08188a2" - integrity sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg== + "integrity" "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + "integrity" "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" + "version" "7.8.4" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-class-properties@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + "integrity" "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" + "version" "7.12.13" dependencies: "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-class-static-block@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" - integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + "integrity" "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz" + "version" "7.14.5" dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-dynamic-import@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" - integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + "integrity" "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-export-namespace-from@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" - integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + "integrity" "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + "integrity" "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz#9d9d357cc818aa7ae7935917c1257f67677a0926" - integrity sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-jsx@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz#50b6571d13f764266a113d77c82b4a6508bbe665" - integrity sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q== + "integrity" "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" +"@babel/plugin-syntax-jsx@7.12.1": + "integrity" "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz" + "version" "7.12.1" + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + "integrity" "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" + "version" "7.10.4" dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + "integrity" "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-numeric-separator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + "integrity" "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" + "version" "7.10.4" dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-object-rest-spread@7.8.3", "@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== +"@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3", "@babel/plugin-syntax-object-rest-spread@7.8.3": + "integrity" "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + "integrity" "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + "integrity" "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-private-property-in-object@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" - integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + "integrity" "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz" + "version" "7.14.5" dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-top-level-await@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + "integrity" "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz" + "version" "7.14.5" dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz#39c9b55ee153151990fb038651d58d3fd03f98f8" - integrity sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A== + "integrity" "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-arrow-functions@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz#44125e653d94b98db76369de9c396dc14bef4154" - integrity sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ== + "integrity" "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-async-to-generator@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz#b83dff4b970cf41f1b819f8b49cc0cfbaa53a808" - integrity sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg== + "integrity" "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-module-imports" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-remap-async-to-generator" "^7.16.8" "@babel/plugin-transform-block-scoped-functions@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz#4d0d57d9632ef6062cdf354bb717102ee042a620" - integrity sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg== + "integrity" "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-block-scoping@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz#f50664ab99ddeaee5bc681b8f3a6ea9d72ab4f87" - integrity sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ== + "integrity" "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-classes@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz#8f4b9562850cd973de3b498f1218796eb181ce00" - integrity sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ== + "integrity" "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-environment-visitor" "^7.16.7" @@ -741,174 +739,174 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-replace-supers" "^7.16.7" "@babel/helper-split-export-declaration" "^7.16.7" - globals "^11.1.0" + "globals" "^11.1.0" "@babel/plugin-transform-computed-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz#66dee12e46f61d2aae7a73710f591eb3df616470" - integrity sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw== + "integrity" "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-destructuring@^7.16.7": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz#c445f75819641788a27a0a3a759d9df911df6abc" - integrity sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg== + "integrity" "sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz" + "version" "7.17.3" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-dotall-regex@^7.16.7", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz#6b2d67686fab15fb6a7fd4bd895d5982cfc81241" - integrity sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ== + "integrity" "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-duplicate-keys@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz#2207e9ca8f82a0d36a5a67b6536e7ef8b08823c9" - integrity sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw== + "integrity" "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-exponentiation-operator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz#efa9862ef97e9e9e5f653f6ddc7b665e8536fe9b" - integrity sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA== + "integrity" "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-for-of@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz#649d639d4617dff502a9a158c479b3b556728d8c" - integrity sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg== + "integrity" "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-function-name@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz#5ab34375c64d61d083d7d2f05c38d90b97ec65cf" - integrity sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA== + "integrity" "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-compilation-targets" "^7.16.7" "@babel/helper-function-name" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz#254c9618c5ff749e87cb0c0cef1a0a050c0bdab1" - integrity sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ== + "integrity" "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-member-expression-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz#6e5dcf906ef8a098e630149d14c867dd28f92384" - integrity sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw== + "integrity" "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-modules-amd@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz#b28d323016a7daaae8609781d1f8c9da42b13186" - integrity sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g== + "integrity" "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-module-transforms" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" - babel-plugin-dynamic-import-node "^2.3.3" + "babel-plugin-dynamic-import-node" "^2.3.3" "@babel/plugin-transform-modules-commonjs@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz#cdee19aae887b16b9d331009aa9a219af7c86afe" - integrity sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA== + "integrity" "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-module-transforms" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-simple-access" "^7.16.7" - babel-plugin-dynamic-import-node "^2.3.3" + "babel-plugin-dynamic-import-node" "^2.3.3" "@babel/plugin-transform-modules-systemjs@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz#887cefaef88e684d29558c2b13ee0563e287c2d7" - integrity sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw== + "integrity" "sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-hoist-variables" "^7.16.7" "@babel/helper-module-transforms" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-validator-identifier" "^7.16.7" - babel-plugin-dynamic-import-node "^2.3.3" + "babel-plugin-dynamic-import-node" "^2.3.3" "@babel/plugin-transform-modules-umd@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz#23dad479fa585283dbd22215bff12719171e7618" - integrity sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ== + "integrity" "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-module-transforms" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-named-capturing-groups-regex@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz#7f860e0e40d844a02c9dcf9d84965e7dfd666252" - integrity sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw== + "integrity" "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/plugin-transform-new-target@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz#9967d89a5c243818e0800fdad89db22c5f514244" - integrity sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg== + "integrity" "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-object-super@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz#ac359cf8d32cf4354d27a46867999490b6c32a94" - integrity sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw== + "integrity" "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-replace-supers" "^7.16.7" "@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz#a1721f55b99b736511cb7e0152f61f17688f331f" - integrity sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw== + "integrity" "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-property-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz#2dadac85155436f22c696c4827730e0fe1057a55" - integrity sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw== + "integrity" "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-react-constant-elements@^7.14.5": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.16.7.tgz#19e9e4c2df2f6c3e6b3aea11778297d81db8df62" - integrity sha512-lF+cfsyTgwWkcw715J88JhMYJ5GpysYNLhLP1PkvkhTRN7B3e74R/1KsDxFxhRpSn0UUD3IWM4GvdBR2PEbbQQ== + "integrity" "sha512-lF+cfsyTgwWkcw715J88JhMYJ5GpysYNLhLP1PkvkhTRN7B3e74R/1KsDxFxhRpSn0UUD3IWM4GvdBR2PEbbQQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-react-display-name@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz#7b6d40d232f4c0f550ea348593db3b21e2404340" - integrity sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg== + "integrity" "sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-react-jsx-development@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz#43a00724a3ed2557ed3f276a01a929e6686ac7b8" - integrity sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A== + "integrity" "sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/plugin-transform-react-jsx" "^7.16.7" "@babel/plugin-transform-react-jsx@^7.16.7": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz#eac1565da176ccb1a715dae0b4609858808008c1" - integrity sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ== + "integrity" "sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz" + "version" "7.17.3" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-module-imports" "^7.16.7" @@ -917,103 +915,103 @@ "@babel/types" "^7.17.0" "@babel/plugin-transform-react-pure-annotations@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz#232bfd2f12eb551d6d7d01d13fe3f86b45eb9c67" - integrity sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA== + "integrity" "sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-regenerator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz#9e7576dc476cb89ccc5096fff7af659243b4adeb" - integrity sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q== + "integrity" "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz" + "version" "7.16.7" dependencies: - regenerator-transform "^0.14.2" + "regenerator-transform" "^0.14.2" "@babel/plugin-transform-reserved-words@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz#1d798e078f7c5958eec952059c460b220a63f586" - integrity sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg== + "integrity" "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-runtime@^7.16.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz#0a2e08b5e2b2d95c4b1d3b3371a2180617455b70" - integrity sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A== + "integrity" "sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz" + "version" "7.17.0" dependencies: "@babel/helper-module-imports" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" - babel-plugin-polyfill-corejs2 "^0.3.0" - babel-plugin-polyfill-corejs3 "^0.5.0" - babel-plugin-polyfill-regenerator "^0.3.0" - semver "^6.3.0" + "babel-plugin-polyfill-corejs2" "^0.3.0" + "babel-plugin-polyfill-corejs3" "^0.5.0" + "babel-plugin-polyfill-regenerator" "^0.3.0" + "semver" "^6.3.0" "@babel/plugin-transform-shorthand-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz#e8549ae4afcf8382f711794c0c7b6b934c5fbd2a" - integrity sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg== + "integrity" "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-spread@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz#a303e2122f9f12e0105daeedd0f30fb197d8ff44" - integrity sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg== + "integrity" "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-transform-sticky-regex@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz#c84741d4f4a38072b9a1e2e3fd56d359552e8660" - integrity sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw== + "integrity" "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-template-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz#f3d1c45d28967c8e80f53666fc9c3e50618217ab" - integrity sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA== + "integrity" "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-typeof-symbol@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz#9cdbe622582c21368bd482b660ba87d5545d4f7e" - integrity sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ== + "integrity" "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-typescript@^7.16.7": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz#591ce9b6b83504903fa9dd3652c357c2ba7a1ee0" - integrity sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ== + "integrity" "sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-create-class-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-typescript" "^7.16.7" "@babel/plugin-transform-unicode-escapes@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz#da8717de7b3287a2c6d659750c964f302b31ece3" - integrity sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q== + "integrity" "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-unicode-regex@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz#0f7aa4a501198976e25e82702574c34cfebe9ef2" - integrity sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q== + "integrity" "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/preset-env@^7.15.6", "@babel/preset-env@^7.16.4": - version "7.16.11" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.11.tgz#5dd88fd885fae36f88fd7c8342475c9f0abe2982" - integrity sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g== + "integrity" "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==" + "resolved" "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz" + "version" "7.16.11" dependencies: "@babel/compat-data" "^7.16.8" "@babel/helper-compilation-targets" "^7.16.7" @@ -1084,27 +1082,27 @@ "@babel/plugin-transform-unicode-regex" "^7.16.7" "@babel/preset-modules" "^0.1.5" "@babel/types" "^7.16.8" - babel-plugin-polyfill-corejs2 "^0.3.0" - babel-plugin-polyfill-corejs3 "^0.5.0" - babel-plugin-polyfill-regenerator "^0.3.0" - core-js-compat "^3.20.2" - semver "^6.3.0" + "babel-plugin-polyfill-corejs2" "^0.3.0" + "babel-plugin-polyfill-corejs3" "^0.5.0" + "babel-plugin-polyfill-regenerator" "^0.3.0" + "core-js-compat" "^3.20.2" + "semver" "^6.3.0" "@babel/preset-modules@^0.1.5": - version "0.1.5" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" - integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== + "integrity" "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==" + "resolved" "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz" + "version" "0.1.5" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" "@babel/plugin-transform-dotall-regex" "^7.4.4" "@babel/types" "^7.4.4" - esutils "^2.0.2" + "esutils" "^2.0.2" "@babel/preset-react@^7.14.5", "@babel/preset-react@^7.16.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.16.7.tgz#4c18150491edc69c183ff818f9f2aecbe5d93852" - integrity sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA== + "integrity" "sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA==" + "resolved" "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-validator-option" "^7.16.7" @@ -1114,81 +1112,82 @@ "@babel/plugin-transform-react-pure-annotations" "^7.16.7" "@babel/preset-typescript@^7.15.0", "@babel/preset-typescript@^7.16.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz#ab114d68bb2020afc069cd51b37ff98a046a70b9" - integrity sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ== + "integrity" "sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==" + "resolved" "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-validator-option" "^7.16.7" "@babel/plugin-transform-typescript" "^7.16.7" "@babel/runtime-corejs3@^7.16.3": - version "7.17.2" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.17.2.tgz#fdca2cd05fba63388babe85d349b6801b008fd13" - integrity sha512-NcKtr2epxfIrNM4VOmPKO46TvDMCBhgi2CrSHaEarrz+Plk2K5r9QemmOFTGpZaoKnWoGH5MO+CzeRsih/Fcgg== + "integrity" "sha512-NcKtr2epxfIrNM4VOmPKO46TvDMCBhgi2CrSHaEarrz+Plk2K5r9QemmOFTGpZaoKnWoGH5MO+CzeRsih/Fcgg==" + "resolved" "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.17.2.tgz" + "version" "7.17.2" dependencies: - core-js-pure "^3.20.2" - regenerator-runtime "^0.13.4" + "core-js-pure" "^3.20.2" + "regenerator-runtime" "^0.13.4" "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.16.3", "@babel/runtime@^7.8.4": - version "7.17.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941" - integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/template@^7.12.7", "@babel/template@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" - integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.16.3", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.17.0", "@babel/traverse@^7.17.3": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57" - integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.3" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.17.3" - "@babel/types" "^7.17.0" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/types@^7.12.7", "@babel/types@^7.15.6", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.4.4": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" - integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - to-fast-properties "^2.0.0" + "integrity" "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==" + "resolved" "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz" + "version" "7.17.2" + dependencies: + "regenerator-runtime" "^0.13.4" + +"@babel/template@^7.12.7", "@babel/template@^7.16.7", "@babel/template@^7.20.7": + "integrity" "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==" + "resolved" "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz" + "version" "7.20.7" + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + +"@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.16.3", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2", "@babel/traverse@^7.21.3": + "integrity" "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==" + "resolved" "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz" + "version" "7.21.3" + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.21.3" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.21.0" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.21.3" + "@babel/types" "^7.21.3" + "debug" "^4.1.0" + "globals" "^11.1.0" + +"@babel/types@^7.12.7", "@babel/types@^7.15.6", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.18.6", "@babel/types@^7.20.2", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.2", "@babel/types@^7.21.3", "@babel/types@^7.4.4": + "integrity" "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==" + "resolved" "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz" + "version" "7.21.3" + dependencies: + "@babel/helper-string-parser" "^7.19.4" + "@babel/helper-validator-identifier" "^7.19.1" + "to-fast-properties" "^2.0.0" "@docsearch/css@3.0.0-alpha.50": - version "3.0.0-alpha.50" - resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.0.0-alpha.50.tgz#794c6a8d301840a49b55f5b331c7be84b9723643" - integrity sha512-QeWFCQOtS9D+Fi20liKsPXF2j/xWKh52e+P2Z1UATIdPMqmH6zoB2lcUz+cgv6PPVgWUtECeR6VSSUm71LT94w== + "integrity" "sha512-QeWFCQOtS9D+Fi20liKsPXF2j/xWKh52e+P2Z1UATIdPMqmH6zoB2lcUz+cgv6PPVgWUtECeR6VSSUm71LT94w==" + "resolved" "https://registry.npmjs.org/@docsearch/css/-/css-3.0.0-alpha.50.tgz" + "version" "3.0.0-alpha.50" "@docsearch/react@^3.0.0-alpha.39": - version "3.0.0-alpha.50" - resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.0.0-alpha.50.tgz#a7dc547836c2b221fd3aa8eb87bfb47a579ef141" - integrity sha512-oDGV1zZCRYv7MWsh6CyQVthYTRc3b4q+6kKwNYb1/g/Wf/4nJHutpxolFLHdEUDhrJ4Xi8wxwQG+lEwAVBTHPg== + "integrity" "sha512-oDGV1zZCRYv7MWsh6CyQVthYTRc3b4q+6kKwNYb1/g/Wf/4nJHutpxolFLHdEUDhrJ4Xi8wxwQG+lEwAVBTHPg==" + "resolved" "https://registry.npmjs.org/@docsearch/react/-/react-3.0.0-alpha.50.tgz" + "version" "3.0.0-alpha.50" dependencies: "@algolia/autocomplete-core" "1.5.2" "@algolia/autocomplete-preset-algolia" "1.5.2" "@docsearch/css" "3.0.0-alpha.50" - algoliasearch "^4.0.0" + "algoliasearch" "^4.0.0" "@docusaurus/core@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.0.0-beta.15.tgz#1a3f8361803767072e56c77d60332c87e59f1ad0" - integrity sha512-zXhhD0fApMSvq/9Pkm9DQxa//hGOXVCq9yMHiXOkI5D1tLec7PxtnaC5cLfGHljkN9cKIfRDYUVcG1gHymVfpA== + "integrity" "sha512-zXhhD0fApMSvq/9Pkm9DQxa//hGOXVCq9yMHiXOkI5D1tLec7PxtnaC5cLfGHljkN9cKIfRDYUVcG1gHymVfpA==" + "resolved" "https://registry.npmjs.org/@docusaurus/core/-/core-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@babel/core" "^7.16.0" "@babel/generator" "^7.16.0" @@ -1209,103 +1208,103 @@ "@docusaurus/utils-validation" "2.0.0-beta.15" "@slorber/static-site-generator-webpack-plugin" "^4.0.0" "@svgr/webpack" "^6.0.0" - autoprefixer "^10.3.5" - babel-loader "^8.2.2" - babel-plugin-dynamic-import-node "2.3.0" - boxen "^5.0.1" - chokidar "^3.5.2" - clean-css "^5.1.5" - commander "^5.1.0" - copy-webpack-plugin "^10.2.0" - core-js "^3.18.0" - css-loader "^6.5.1" - css-minimizer-webpack-plugin "^3.3.1" - cssnano "^5.0.8" - del "^6.0.0" - detect-port "^1.3.0" - escape-html "^1.0.3" - eta "^1.12.3" - file-loader "^6.2.0" - fs-extra "^10.0.0" - html-minifier-terser "^6.0.2" - html-tags "^3.1.0" - html-webpack-plugin "^5.4.0" - import-fresh "^3.3.0" - is-root "^2.1.0" - leven "^3.1.0" - lodash "^4.17.20" - mini-css-extract-plugin "^1.6.0" - nprogress "^0.2.0" - postcss "^8.3.7" - postcss-loader "^6.1.1" - prompts "^2.4.1" - react-dev-utils "^12.0.0" - react-helmet "^6.1.0" - react-loadable "npm:@docusaurus/react-loadable@5.5.2" - react-loadable-ssr-addon-v5-slorber "^1.0.1" - react-router "^5.2.0" - react-router-config "^5.1.1" - react-router-dom "^5.2.0" - remark-admonitions "^1.2.1" - rtl-detect "^1.0.4" - semver "^7.3.4" - serve-handler "^6.1.3" - shelljs "^0.8.4" - strip-ansi "^6.0.0" - terser-webpack-plugin "^5.2.4" - tslib "^2.3.1" - update-notifier "^5.1.0" - url-loader "^4.1.1" - wait-on "^6.0.0" - webpack "^5.61.0" - webpack-bundle-analyzer "^4.4.2" - webpack-dev-server "^4.7.1" - webpack-merge "^5.8.0" - webpackbar "^5.0.2" + "autoprefixer" "^10.3.5" + "babel-loader" "^8.2.2" + "babel-plugin-dynamic-import-node" "2.3.0" + "boxen" "^5.0.1" + "chokidar" "^3.5.2" + "clean-css" "^5.1.5" + "commander" "^5.1.0" + "copy-webpack-plugin" "^10.2.0" + "core-js" "^3.18.0" + "css-loader" "^6.5.1" + "css-minimizer-webpack-plugin" "^3.3.1" + "cssnano" "^5.0.8" + "del" "^6.0.0" + "detect-port" "^1.3.0" + "escape-html" "^1.0.3" + "eta" "^1.12.3" + "file-loader" "^6.2.0" + "fs-extra" "^10.0.0" + "html-minifier-terser" "^6.0.2" + "html-tags" "^3.1.0" + "html-webpack-plugin" "^5.4.0" + "import-fresh" "^3.3.0" + "is-root" "^2.1.0" + "leven" "^3.1.0" + "lodash" "^4.17.20" + "mini-css-extract-plugin" "^1.6.0" + "nprogress" "^0.2.0" + "postcss" "^8.3.7" + "postcss-loader" "^6.1.1" + "prompts" "^2.4.1" + "react-dev-utils" "^12.0.0" + "react-helmet" "^6.1.0" + "react-loadable" "npm:@docusaurus/react-loadable@5.5.2" + "react-loadable-ssr-addon-v5-slorber" "^1.0.1" + "react-router" "^5.2.0" + "react-router-config" "^5.1.1" + "react-router-dom" "^5.2.0" + "remark-admonitions" "^1.2.1" + "rtl-detect" "^1.0.4" + "semver" "^7.3.4" + "serve-handler" "^6.1.3" + "shelljs" "^0.8.4" + "strip-ansi" "^6.0.0" + "terser-webpack-plugin" "^5.2.4" + "tslib" "^2.3.1" + "update-notifier" "^5.1.0" + "url-loader" "^4.1.1" + "wait-on" "^6.0.0" + "webpack" "^5.61.0" + "webpack-bundle-analyzer" "^4.4.2" + "webpack-dev-server" "^4.7.1" + "webpack-merge" "^5.8.0" + "webpackbar" "^5.0.2" "@docusaurus/cssnano-preset@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-beta.15.tgz#033c52815c428f0f66c87eaff93ea12554ea89df" - integrity sha512-55aYURbB5dqrx64lStNcZxDx5R6bKkAawlCB7mDKx3r+Qnp3ofGW7UExLQSCbTu3axT1vJCF5D7H6ljTRYJLtA== + "integrity" "sha512-55aYURbB5dqrx64lStNcZxDx5R6bKkAawlCB7mDKx3r+Qnp3ofGW7UExLQSCbTu3axT1vJCF5D7H6ljTRYJLtA==" + "resolved" "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: - cssnano-preset-advanced "^5.1.4" - postcss "^8.3.7" - postcss-sort-media-queries "^4.1.0" + "cssnano-preset-advanced" "^5.1.4" + "postcss" "^8.3.7" + "postcss-sort-media-queries" "^4.1.0" "@docusaurus/logger@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-2.0.0-beta.15.tgz#6d17a05fb292d15fdc43b5fa90fd2a49ad5d40ce" - integrity sha512-5bDSHCyLfMtz6QnFfICdL5mgxbGfC7DW1V+/Q17nRdpZSPZgsNKK/Esp0zdDi1oxAyEpXMXx64nLaHL7joJxIg== + "integrity" "sha512-5bDSHCyLfMtz6QnFfICdL5mgxbGfC7DW1V+/Q17nRdpZSPZgsNKK/Esp0zdDi1oxAyEpXMXx64nLaHL7joJxIg==" + "resolved" "https://registry.npmjs.org/@docusaurus/logger/-/logger-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: - chalk "^4.1.2" - tslib "^2.3.1" + "chalk" "^4.1.2" + "tslib" "^2.3.1" "@docusaurus/mdx-loader@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-beta.15.tgz#da23745bc73c93338dd330dad6bbc9d9fe325553" - integrity sha512-MVpytjDDao7hmPF1QSs9B5zoTgevZjiqjnX3FM1yjqdCv+chyUo0gnmYHjeG/4Gqu7jucp+dDdp6yQpzs4g09A== + "integrity" "sha512-MVpytjDDao7hmPF1QSs9B5zoTgevZjiqjnX3FM1yjqdCv+chyUo0gnmYHjeG/4Gqu7jucp+dDdp6yQpzs4g09A==" + "resolved" "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@babel/parser" "^7.16.4" "@babel/traverse" "^7.16.3" "@docusaurus/logger" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" "@mdx-js/mdx" "^1.6.21" - escape-html "^1.0.3" - file-loader "^6.2.0" - fs-extra "^10.0.0" - image-size "^1.0.1" - mdast-util-to-string "^2.0.0" - remark-emoji "^2.1.0" - stringify-object "^3.3.0" - tslib "^2.3.1" - unist-util-visit "^2.0.2" - url-loader "^4.1.1" - webpack "^5.61.0" + "escape-html" "^1.0.3" + "file-loader" "^6.2.0" + "fs-extra" "^10.0.0" + "image-size" "^1.0.1" + "mdast-util-to-string" "^2.0.0" + "remark-emoji" "^2.1.0" + "stringify-object" "^3.3.0" + "tslib" "^2.3.1" + "unist-util-visit" "^2.0.2" + "url-loader" "^4.1.1" + "webpack" "^5.61.0" "@docusaurus/plugin-content-blog@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.15.tgz#6d4bf532ad3dedb4f9fd6398b0fbe481af5b77a9" - integrity sha512-VtEwkgkoNIS8JFPe+huBeBuJ8HG8Lq1JNYM/ItwQg/cwGAgP8EgwbEuKDn428oZKEI2PpgAuf5Gv4AzJWIes9A== + "integrity" "sha512-VtEwkgkoNIS8JFPe+huBeBuJ8HG8Lq1JNYM/ItwQg/cwGAgP8EgwbEuKDn428oZKEI2PpgAuf5Gv4AzJWIes9A==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/logger" "2.0.0-beta.15" @@ -1313,98 +1312,98 @@ "@docusaurus/utils" "2.0.0-beta.15" "@docusaurus/utils-common" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - cheerio "^1.0.0-rc.10" - feed "^4.2.2" - fs-extra "^10.0.0" - lodash "^4.17.20" - reading-time "^1.5.0" - remark-admonitions "^1.2.1" - tslib "^2.3.1" - utility-types "^3.10.0" - webpack "^5.61.0" + "cheerio" "^1.0.0-rc.10" + "feed" "^4.2.2" + "fs-extra" "^10.0.0" + "lodash" "^4.17.20" + "reading-time" "^1.5.0" + "remark-admonitions" "^1.2.1" + "tslib" "^2.3.1" + "utility-types" "^3.10.0" + "webpack" "^5.61.0" "@docusaurus/plugin-content-docs@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-beta.15.tgz#9486bba8abd2a6284e749718bf56743d8e4446f1" - integrity sha512-HSwNZdUKz4rpJiGbFjl/OFhSleeZUSZ6E6lk98i4iL1A5u6fIm4CHsT53yp4UUOse+lFrePTFZsyqwMA4nZZYA== + "integrity" "sha512-HSwNZdUKz4rpJiGbFjl/OFhSleeZUSZ6E6lk98i4iL1A5u6fIm4CHsT53yp4UUOse+lFrePTFZsyqwMA4nZZYA==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/logger" "2.0.0-beta.15" "@docusaurus/mdx-loader" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - combine-promises "^1.1.0" - fs-extra "^10.0.0" - import-fresh "^3.2.2" - js-yaml "^4.0.0" - lodash "^4.17.20" - remark-admonitions "^1.2.1" - shelljs "^0.8.4" - tslib "^2.3.1" - utility-types "^3.10.0" - webpack "^5.61.0" + "combine-promises" "^1.1.0" + "fs-extra" "^10.0.0" + "import-fresh" "^3.2.2" + "js-yaml" "^4.0.0" + "lodash" "^4.17.20" + "remark-admonitions" "^1.2.1" + "shelljs" "^0.8.4" + "tslib" "^2.3.1" + "utility-types" "^3.10.0" + "webpack" "^5.61.0" "@docusaurus/plugin-content-pages@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-beta.15.tgz#e488f7dcdd45cd1d46e8c2c5ff5275327a6a3c65" - integrity sha512-N7YhW5RiOY6J228z4lOoP//qX0Q48cRtxDONZ/Ohd9C5OI2vS6TD8iQuDqOIYHxH+BshjNSsKvbJ+SMIQDwysg== + "integrity" "sha512-N7YhW5RiOY6J228z4lOoP//qX0Q48cRtxDONZ/Ohd9C5OI2vS6TD8iQuDqOIYHxH+BshjNSsKvbJ+SMIQDwysg==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/mdx-loader" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - fs-extra "^10.0.0" - globby "^11.0.2" - remark-admonitions "^1.2.1" - tslib "^2.3.1" - webpack "^5.61.0" + "fs-extra" "^10.0.0" + "globby" "^11.0.2" + "remark-admonitions" "^1.2.1" + "tslib" "^2.3.1" + "webpack" "^5.61.0" "@docusaurus/plugin-debug@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-beta.15.tgz#b75d706d4f9fc4146f84015097bd837d1afb7c6b" - integrity sha512-Jth11jB/rVqPwCGdkVKSUWeXZPAr/NyPn+yeknTBk2LgQKBJ3YU5dNG0uyt0Ay+UYT01TkousPJkXhLuy4Qrsw== + "integrity" "sha512-Jth11jB/rVqPwCGdkVKSUWeXZPAr/NyPn+yeknTBk2LgQKBJ3YU5dNG0uyt0Ay+UYT01TkousPJkXhLuy4Qrsw==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" - fs-extra "^10.0.0" - react-json-view "^1.21.3" - tslib "^2.3.1" + "fs-extra" "^10.0.0" + "react-json-view" "^1.21.3" + "tslib" "^2.3.1" "@docusaurus/plugin-google-analytics@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-beta.15.tgz#6ffebe76d9caac5383cfb78d2baa5883c9c2df6c" - integrity sha512-ELAnxNYiC2i7gfu/ViurNIdm1/DdnbEfVDmpffS9niQhOREM1U3jpxkz/ff1GIC6heOLyHTtini/CZBDoroVGw== + "integrity" "sha512-ELAnxNYiC2i7gfu/ViurNIdm1/DdnbEfVDmpffS9niQhOREM1U3jpxkz/ff1GIC6heOLyHTtini/CZBDoroVGw==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - tslib "^2.3.1" + "tslib" "^2.3.1" "@docusaurus/plugin-google-gtag@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-beta.15.tgz#4db3330d302653e8541dc3cb86a4dbfef0cc96f8" - integrity sha512-E5Rm3+dN7i3A9V5uq5sl9xTNA3aXsLwTZEA2SpOkY571dCpd+sfVvz1lR+KRY9Fy6ZHk8PqrNImgCWfIerRuZQ== + "integrity" "sha512-E5Rm3+dN7i3A9V5uq5sl9xTNA3aXsLwTZEA2SpOkY571dCpd+sfVvz1lR+KRY9Fy6ZHk8PqrNImgCWfIerRuZQ==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - tslib "^2.3.1" + "tslib" "^2.3.1" "@docusaurus/plugin-sitemap@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-beta.15.tgz#0cc083d9e76041897e81b4b82bcd0ccbfa65d6e5" - integrity sha512-PBjeQb2Qpe4uPdRefWL/eXCeYjrgNB/UArExYeUuP4wiY1dpw2unGNCvFUxv4hzJGmARoTLsnRkeYkUim809LQ== + "integrity" "sha512-PBjeQb2Qpe4uPdRefWL/eXCeYjrgNB/UArExYeUuP4wiY1dpw2unGNCvFUxv4hzJGmARoTLsnRkeYkUim809LQ==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" "@docusaurus/utils-common" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - fs-extra "^10.0.0" - sitemap "^7.0.0" - tslib "^2.3.1" + "fs-extra" "^10.0.0" + "sitemap" "^7.0.0" + "tslib" "^2.3.1" "@docusaurus/preset-classic@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-2.0.0-beta.15.tgz#13d2f3c4fa7c055af35541ae5e93453450efb208" - integrity sha512-3NZIXWTAzk+kOgiB8uAbD+FZv3VFR1qkU6+TW24DRenjRnXof3CkRuldhI1QI0hILm1fuJ319QRkakV8FFtXyA== + "integrity" "sha512-3NZIXWTAzk+kOgiB8uAbD+FZv3VFR1qkU6+TW24DRenjRnXof3CkRuldhI1QI0hILm1fuJ319QRkakV8FFtXyA==" + "resolved" "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/plugin-content-blog" "2.0.0-beta.15" @@ -1418,18 +1417,18 @@ "@docusaurus/theme-common" "2.0.0-beta.15" "@docusaurus/theme-search-algolia" "2.0.0-beta.15" -"@docusaurus/react-loadable@5.5.2", "react-loadable@npm:@docusaurus/react-loadable@5.5.2": - version "5.5.2" - resolved "https://registry.yarnpkg.com/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz#81aae0db81ecafbdaee3651f12804580868fa6ce" - integrity sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ== +"@docusaurus/react-loadable@5.5.2": + "integrity" "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==" + "resolved" "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz" + "version" "5.5.2" dependencies: "@types/react" "*" - prop-types "^15.6.2" + "prop-types" "^15.6.2" "@docusaurus/theme-classic@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-2.0.0-beta.15.tgz#35d04232f2d5fcb2007675339b0e6d0e8681be95" - integrity sha512-WwNRcQvMtQ7KDhOEHFKFHxXCdoZwLg66hT3vhqNIFMfGQuPzOP91MX5LUSo1QWHhlrD3H3Og+r7Ik/fy2bf5lQ== + "integrity" "sha512-WwNRcQvMtQ7KDhOEHFKFHxXCdoZwLg66hT3vhqNIFMfGQuPzOP91MX5LUSo1QWHhlrD3H3Og+r7Ik/fy2bf5lQ==" + "resolved" "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/plugin-content-blog" "2.0.0-beta.15" @@ -1441,33 +1440,33 @@ "@docusaurus/utils-common" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" "@mdx-js/react" "^1.6.21" - clsx "^1.1.1" - copy-text-to-clipboard "^3.0.1" - infima "0.2.0-alpha.37" - lodash "^4.17.20" - postcss "^8.3.7" - prism-react-renderer "^1.2.1" - prismjs "^1.23.0" - react-router-dom "^5.2.0" - rtlcss "^3.3.0" + "clsx" "^1.1.1" + "copy-text-to-clipboard" "^3.0.1" + "infima" "0.2.0-alpha.37" + "lodash" "^4.17.20" + "postcss" "^8.3.7" + "prism-react-renderer" "^1.2.1" + "prismjs" "^1.23.0" + "react-router-dom" "^5.2.0" + "rtlcss" "^3.3.0" "@docusaurus/theme-common@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-2.0.0-beta.15.tgz#5bd338d483e2c19d6d74d133572988241518398a" - integrity sha512-+pvarmzcyECE4nWxw+dCMKRIoes0NegrRuM9+nRsUrS/E5ywsF539kpupKIEqaMjq6AuM0CJtDoHxHHPNe0KaQ== + "integrity" "sha512-+pvarmzcyECE4nWxw+dCMKRIoes0NegrRuM9+nRsUrS/E5ywsF539kpupKIEqaMjq6AuM0CJtDoHxHHPNe0KaQ==" + "resolved" "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/plugin-content-blog" "2.0.0-beta.15" "@docusaurus/plugin-content-docs" "2.0.0-beta.15" "@docusaurus/plugin-content-pages" "2.0.0-beta.15" - clsx "^1.1.1" - parse-numeric-range "^1.3.0" - tslib "^2.3.1" - utility-types "^3.10.0" + "clsx" "^1.1.1" + "parse-numeric-range" "^1.3.0" + "tslib" "^2.3.1" + "utility-types" "^3.10.0" "@docusaurus/theme-search-algolia@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-beta.15.tgz#c3ad7fd8e27fcb3e072990031c08768c602cb9a4" - integrity sha512-XrrQKyjOPzmEuOcdsaAn1tzNJkNMA3PC86PwPZUaah0cYPpBGptcJYDlIW4VHIrCBfkQvhvmg/B3qKF6bMMi8g== + "integrity" "sha512-XrrQKyjOPzmEuOcdsaAn1tzNJkNMA3PC86PwPZUaah0cYPpBGptcJYDlIW4VHIrCBfkQvhvmg/B3qKF6bMMi8g==" + "resolved" "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docsearch/react" "^3.0.0-alpha.39" "@docusaurus/core" "2.0.0-beta.15" @@ -1476,268 +1475,268 @@ "@docusaurus/theme-translations" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - algoliasearch "^4.10.5" - algoliasearch-helper "^3.5.5" - clsx "^1.1.1" - eta "^1.12.3" - lodash "^4.17.20" - tslib "^2.3.1" - utility-types "^3.10.0" + "algoliasearch" "^4.10.5" + "algoliasearch-helper" "^3.5.5" + "clsx" "^1.1.1" + "eta" "^1.12.3" + "lodash" "^4.17.20" + "tslib" "^2.3.1" + "utility-types" "^3.10.0" "@docusaurus/theme-translations@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-2.0.0-beta.15.tgz#658397ab4c0d7784043e3cec52cef7ae09d2fb59" - integrity sha512-Lu2JDsnZaB2BcJe8Hpq5nrbS7+7bd09jT08b9vztQyvzR8PgzsthnzlLN4ilOeamRIuYJKo1pUGm0EsQBOP6Nw== + "integrity" "sha512-Lu2JDsnZaB2BcJe8Hpq5nrbS7+7bd09jT08b9vztQyvzR8PgzsthnzlLN4ilOeamRIuYJKo1pUGm0EsQBOP6Nw==" + "resolved" "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: - fs-extra "^10.0.0" - tslib "^2.3.1" + "fs-extra" "^10.0.0" + "tslib" "^2.3.1" "@docusaurus/utils-common@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-2.0.0-beta.15.tgz#5549b329fc750bd5e9f24952c9e3ff7cf1f63e08" - integrity sha512-kIGlSIvbE/oniUpUjI8GOkSpH8o4NXbYqAh9dqPn+TJ0KbEFY3fc80gzZQU+9SunCwJMJbIxIGevX9Ry+nackw== + "integrity" "sha512-kIGlSIvbE/oniUpUjI8GOkSpH8o4NXbYqAh9dqPn+TJ0KbEFY3fc80gzZQU+9SunCwJMJbIxIGevX9Ry+nackw==" + "resolved" "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: - tslib "^2.3.1" + "tslib" "^2.3.1" "@docusaurus/utils-validation@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.0.0-beta.15.tgz#c664bc021194db9254eb45e6b48cb7c2af269041" - integrity sha512-1oOVBCkRrsTXSYrBTsMdnj3a/R56zrx11rjF4xo0+dmm8C01Xw4msFtc3uA7VLX0HQvgHsk8xPzU5GERNdsNpg== + "integrity" "sha512-1oOVBCkRrsTXSYrBTsMdnj3a/R56zrx11rjF4xo0+dmm8C01Xw4msFtc3uA7VLX0HQvgHsk8xPzU5GERNdsNpg==" + "resolved" "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/logger" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" - joi "^17.4.2" - tslib "^2.3.1" + "joi" "^17.4.2" + "tslib" "^2.3.1" "@docusaurus/utils@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.0.0-beta.15.tgz#60868046700d5585cfa6ffc57c5f3fbed00b61fc" - integrity sha512-xkoPmFxCBkDqbZR4U3SE752OcXtWTGgZnc/pZWxItzb1IYRGNZHrzdIr7CnI7rppriuZzsyivDGiC4Ud9MWhkA== + "integrity" "sha512-xkoPmFxCBkDqbZR4U3SE752OcXtWTGgZnc/pZWxItzb1IYRGNZHrzdIr7CnI7rppriuZzsyivDGiC4Ud9MWhkA==" + "resolved" "https://registry.npmjs.org/@docusaurus/utils/-/utils-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/logger" "2.0.0-beta.15" "@mdx-js/runtime" "^1.6.22" "@svgr/webpack" "^6.0.0" - file-loader "^6.2.0" - fs-extra "^10.0.0" - github-slugger "^1.4.0" - globby "^11.0.4" - gray-matter "^4.0.3" - js-yaml "^4.0.0" - lodash "^4.17.20" - micromatch "^4.0.4" - remark-mdx-remove-exports "^1.6.22" - remark-mdx-remove-imports "^1.6.22" - resolve-pathname "^3.0.0" - tslib "^2.3.1" - url-loader "^4.1.1" + "file-loader" "^6.2.0" + "fs-extra" "^10.0.0" + "github-slugger" "^1.4.0" + "globby" "^11.0.4" + "gray-matter" "^4.0.3" + "js-yaml" "^4.0.0" + "lodash" "^4.17.20" + "micromatch" "^4.0.4" + "remark-mdx-remove-exports" "^1.6.22" + "remark-mdx-remove-imports" "^1.6.22" + "resolve-pathname" "^3.0.0" + "tslib" "^2.3.1" + "url-loader" "^4.1.1" "@hapi/hoek@^9.0.0": - version "9.2.1" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.2.1.tgz#9551142a1980503752536b5050fd99f4a7f13b17" - integrity sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw== + "integrity" "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==" + "resolved" "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz" + "version" "9.2.1" "@hapi/topo@^5.0.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" - integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== + "integrity" "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==" + "resolved" "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz" + "version" "5.1.0" dependencies: "@hapi/hoek" "^9.0.0" -"@jridgewell/gen-mapping@^0.3.0": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" - integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== +"@jridgewell/gen-mapping@^0.1.0": + "integrity" "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==" + "resolved" "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz" + "version" "0.1.1" + dependencies: + "@jridgewell/set-array" "^1.0.0" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + "integrity" "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==" + "resolved" "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz" + "version" "0.3.2" dependencies: "@jridgewell/set-array" "^1.0.1" "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/resolve-uri@^3.0.3": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== +"@jridgewell/resolve-uri@3.1.0": + "integrity" "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" + "resolved" "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz" + "version" "3.1.0" -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": + "integrity" "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + "resolved" "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz" + "version" "1.1.2" "@jridgewell/source-map@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" - integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + "integrity" "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==" + "resolved" "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz" + "version" "0.3.2" dependencies: "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== - -"@jridgewell/trace-mapping@^0.3.0": - version "0.3.4" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz#f6a0832dffd5b8a6aaa633b7d9f8e8e94c83a0c3" - integrity sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@1.4.14": + "integrity" "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + "resolved" "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" + "version" "1.4.14" -"@jridgewell/trace-mapping@^0.3.9": - version "0.3.14" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed" - integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ== +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": + "integrity" "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==" + "resolved" "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz" + "version" "0.3.17" dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" -"@mdx-js/mdx@1.6.22", "@mdx-js/mdx@^1.6.21": - version "1.6.22" - resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-1.6.22.tgz#8a723157bf90e78f17dc0f27995398e6c731f1ba" - integrity sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA== +"@mdx-js/mdx@^1.6.21", "@mdx-js/mdx@1.6.22": + "integrity" "sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==" + "resolved" "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz" + "version" "1.6.22" dependencies: "@babel/core" "7.12.9" "@babel/plugin-syntax-jsx" "7.12.1" "@babel/plugin-syntax-object-rest-spread" "7.8.3" "@mdx-js/util" "1.6.22" - babel-plugin-apply-mdx-type-prop "1.6.22" - babel-plugin-extract-import-names "1.6.22" - camelcase-css "2.0.1" - detab "2.0.4" - hast-util-raw "6.0.1" - lodash.uniq "4.5.0" - mdast-util-to-hast "10.0.1" - remark-footnotes "2.0.0" - remark-mdx "1.6.22" - remark-parse "8.0.3" - remark-squeeze-paragraphs "4.0.0" - style-to-object "0.3.0" - unified "9.2.0" - unist-builder "2.0.3" - unist-util-visit "2.0.3" - -"@mdx-js/react@1.6.22", "@mdx-js/react@^1.6.21": - version "1.6.22" - resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.6.22.tgz#ae09b4744fddc74714ee9f9d6f17a66e77c43573" - integrity sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg== + "babel-plugin-apply-mdx-type-prop" "1.6.22" + "babel-plugin-extract-import-names" "1.6.22" + "camelcase-css" "2.0.1" + "detab" "2.0.4" + "hast-util-raw" "6.0.1" + "lodash.uniq" "4.5.0" + "mdast-util-to-hast" "10.0.1" + "remark-footnotes" "2.0.0" + "remark-mdx" "1.6.22" + "remark-parse" "8.0.3" + "remark-squeeze-paragraphs" "4.0.0" + "style-to-object" "0.3.0" + "unified" "9.2.0" + "unist-builder" "2.0.3" + "unist-util-visit" "2.0.3" + +"@mdx-js/react@^1.6.21", "@mdx-js/react@1.6.22": + "integrity" "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==" + "resolved" "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz" + "version" "1.6.22" "@mdx-js/runtime@^1.6.22": - version "1.6.22" - resolved "https://registry.yarnpkg.com/@mdx-js/runtime/-/runtime-1.6.22.tgz#3edd388bf68a519ffa1aaf9c446b548165102345" - integrity sha512-p17spaO2+55VLCuxXA3LVHC4phRx60NR2XMdZ+qgVU1lKvEX4y88dmFNOzGDCPLJ03IZyKrJ/rPWWRiBrd9JrQ== + "integrity" "sha512-p17spaO2+55VLCuxXA3LVHC4phRx60NR2XMdZ+qgVU1lKvEX4y88dmFNOzGDCPLJ03IZyKrJ/rPWWRiBrd9JrQ==" + "resolved" "https://registry.npmjs.org/@mdx-js/runtime/-/runtime-1.6.22.tgz" + "version" "1.6.22" dependencies: "@mdx-js/mdx" "1.6.22" "@mdx-js/react" "1.6.22" - buble-jsx-only "^0.19.8" + "buble-jsx-only" "^0.19.8" "@mdx-js/util@1.6.22": - version "1.6.22" - resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b" - integrity sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA== + "integrity" "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==" + "resolved" "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz" + "version" "1.6.22" "@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + "integrity" "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==" + "resolved" "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" + "version" "2.1.5" dependencies: "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" + "run-parallel" "^1.1.9" -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== +"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": + "integrity" "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + "resolved" "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" + "version" "2.0.5" "@nodelib/fs.walk@^1.2.3": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + "integrity" "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==" + "resolved" "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" + "version" "1.2.8" dependencies: "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" + "fastq" "^1.6.0" "@polka/url@^1.0.0-next.20": - version "1.0.0-next.21" - resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" - integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== + "integrity" "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==" + "resolved" "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz" + "version" "1.0.0-next.21" "@sideway/address@^4.1.3": - version "4.1.3" - resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.3.tgz#d93cce5d45c5daec92ad76db492cc2ee3c64ab27" - integrity sha512-8ncEUtmnTsMmL7z1YPB47kPUq7LpKWJNFPsRzHiIajGC5uXlWGn+AmkYPcHNl8S4tcEGx+cnORnNYaw2wvL+LQ== + "integrity" "sha512-8ncEUtmnTsMmL7z1YPB47kPUq7LpKWJNFPsRzHiIajGC5uXlWGn+AmkYPcHNl8S4tcEGx+cnORnNYaw2wvL+LQ==" + "resolved" "https://registry.npmjs.org/@sideway/address/-/address-4.1.3.tgz" + "version" "4.1.3" dependencies: "@hapi/hoek" "^9.0.0" "@sideway/formula@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" - integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== + "integrity" "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + "resolved" "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz" + "version" "3.0.1" "@sideway/pinpoint@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" - integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + "integrity" "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + "resolved" "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz" + "version" "2.0.0" "@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + "integrity" "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" + "resolved" "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz" + "version" "0.14.0" "@slorber/static-site-generator-webpack-plugin@^4.0.0": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.1.tgz#0c8852146441aaa683693deaa5aee2f991d94841" - integrity sha512-PSv4RIVO1Y3kvHxjvqeVisk3E9XFoO04uwYBDWe217MFqKspplYswTuKLiJu0aLORQWzuQjfVsSlLPojwfYsLw== + "integrity" "sha512-PSv4RIVO1Y3kvHxjvqeVisk3E9XFoO04uwYBDWe217MFqKspplYswTuKLiJu0aLORQWzuQjfVsSlLPojwfYsLw==" + "resolved" "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.1.tgz" + "version" "4.0.1" dependencies: - bluebird "^3.7.1" - cheerio "^0.22.0" - eval "^0.1.4" - url "^0.11.0" - webpack-sources "^1.4.3" + "bluebird" "^3.7.1" + "cheerio" "^0.22.0" + "eval" "^0.1.4" + "url" "^0.11.0" + "webpack-sources" "^1.4.3" "@svgr/babel-plugin-add-jsx-attribute@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.0.0.tgz#bd6d1ff32a31b82b601e73672a789cc41e84fe18" - integrity sha512-MdPdhdWLtQsjd29Wa4pABdhWbaRMACdM1h31BY+c6FghTZqNGT7pEYdBoaGeKtdTOBC/XNFQaKVj+r/Ei2ryWA== + "integrity" "sha512-MdPdhdWLtQsjd29Wa4pABdhWbaRMACdM1h31BY+c6FghTZqNGT7pEYdBoaGeKtdTOBC/XNFQaKVj+r/Ei2ryWA==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-remove-jsx-attribute@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.0.0.tgz#58654908beebfa069681a83332544b17e5237e89" - integrity sha512-aVdtfx9jlaaxc3unA6l+M9YRnKIZjOhQPthLKqmTXC8UVkBLDRGwPKo+r8n3VZN8B34+yVajzPTZ+ptTSuZZCw== + "integrity" "sha512-aVdtfx9jlaaxc3unA6l+M9YRnKIZjOhQPthLKqmTXC8UVkBLDRGwPKo+r8n3VZN8B34+yVajzPTZ+ptTSuZZCw==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-remove-jsx-empty-expression@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.0.0.tgz#d06dd6e8a8f603f92f9979bb9990a1f85a4f57ba" - integrity sha512-Ccj42ApsePD451AZJJf1QzTD1B/BOU392URJTeXFxSK709i0KUsGtbwyiqsKu7vsYxpTM0IA5clAKDyf9RCZyA== + "integrity" "sha512-Ccj42ApsePD451AZJJf1QzTD1B/BOU392URJTeXFxSK709i0KUsGtbwyiqsKu7vsYxpTM0IA5clAKDyf9RCZyA==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-replace-jsx-attribute-value@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.0.0.tgz#0b85837577b02c31c09c758a12932820f5245cee" - integrity sha512-88V26WGyt1Sfd1emBYmBJRWMmgarrExpKNVmI9vVozha4kqs6FzQJ/Kp5+EYli1apgX44518/0+t9+NU36lThQ== + "integrity" "sha512-88V26WGyt1Sfd1emBYmBJRWMmgarrExpKNVmI9vVozha4kqs6FzQJ/Kp5+EYli1apgX44518/0+t9+NU36lThQ==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-svg-dynamic-title@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.0.0.tgz#28236ec26f7ab9d486a487d36ae52d58ba15676f" - integrity sha512-F7YXNLfGze+xv0KMQxrl2vkNbI9kzT9oDK55/kUuymh1ACyXkMV+VZWX1zEhSTfEKh7VkHVZGmVtHg8eTZ6PRg== + "integrity" "sha512-F7YXNLfGze+xv0KMQxrl2vkNbI9kzT9oDK55/kUuymh1ACyXkMV+VZWX1zEhSTfEKh7VkHVZGmVtHg8eTZ6PRg==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-svg-em-dimensions@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.0.0.tgz#40267c5dea1b43c4f83a0eb6169e08b43d8bafce" - integrity sha512-+rghFXxdIqJNLQK08kwPBD3Z22/0b2tEZ9lKiL/yTfuyj1wW8HUXu4bo/XkogATIYuXSghVQOOCwURXzHGKyZA== + "integrity" "sha512-+rghFXxdIqJNLQK08kwPBD3Z22/0b2tEZ9lKiL/yTfuyj1wW8HUXu4bo/XkogATIYuXSghVQOOCwURXzHGKyZA==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-transform-react-native-svg@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.0.0.tgz#eb688d0a5f539e34d268d8a516e81f5d7fede7c9" - integrity sha512-VaphyHZ+xIKv5v0K0HCzyfAaLhPGJXSk2HkpYfXIOKb7DjLBv0soHDxNv6X0vr2titsxE7klb++u7iOf7TSrFQ== + "integrity" "sha512-VaphyHZ+xIKv5v0K0HCzyfAaLhPGJXSk2HkpYfXIOKb7DjLBv0soHDxNv6X0vr2titsxE7klb++u7iOf7TSrFQ==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-transform-svg-component@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.2.0.tgz#7ba61d9fc1fb42b0ba1a04e4630019fa7e993c4f" - integrity sha512-bhYIpsORb++wpsp91fymbFkf09Z/YEKR0DnFjxvN+8JHeCUD2unnh18jIMKnDJTWtvpTaGYPXELVe4OOzFI0xg== + "integrity" "sha512-bhYIpsORb++wpsp91fymbFkf09Z/YEKR0DnFjxvN+8JHeCUD2unnh18jIMKnDJTWtvpTaGYPXELVe4OOzFI0xg==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.2.0.tgz" + "version" "6.2.0" "@svgr/babel-preset@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-6.2.0.tgz#1d3ad8c7664253a4be8e4a0f0e6872f30d8af627" - integrity sha512-4WQNY0J71JIaL03DRn0vLiz87JXx0b9dYm2aA8XHlQJQoixMl4r/soYHm8dsaJZ3jWtkCiOYy48dp9izvXhDkQ== + "integrity" "sha512-4WQNY0J71JIaL03DRn0vLiz87JXx0b9dYm2aA8XHlQJQoixMl4r/soYHm8dsaJZ3jWtkCiOYy48dp9izvXhDkQ==" + "resolved" "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.2.0.tgz" + "version" "6.2.0" dependencies: "@svgr/babel-plugin-add-jsx-attribute" "^6.0.0" "@svgr/babel-plugin-remove-jsx-attribute" "^6.0.0" @@ -1748,46 +1747,46 @@ "@svgr/babel-plugin-transform-react-native-svg" "^6.0.0" "@svgr/babel-plugin-transform-svg-component" "^6.2.0" -"@svgr/core@^6.2.1": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@svgr/core/-/core-6.2.1.tgz#195de807a9f27f9e0e0d678e01084b05c54fdf61" - integrity sha512-NWufjGI2WUyrg46mKuySfviEJ6IxHUOm/8a3Ph38VCWSp+83HBraCQrpEM3F3dB6LBs5x8OElS8h3C0oOJaJAA== +"@svgr/core@^6.0.0", "@svgr/core@^6.2.1": + "integrity" "sha512-NWufjGI2WUyrg46mKuySfviEJ6IxHUOm/8a3Ph38VCWSp+83HBraCQrpEM3F3dB6LBs5x8OElS8h3C0oOJaJAA==" + "resolved" "https://registry.npmjs.org/@svgr/core/-/core-6.2.1.tgz" + "version" "6.2.1" dependencies: "@svgr/plugin-jsx" "^6.2.1" - camelcase "^6.2.0" - cosmiconfig "^7.0.1" + "camelcase" "^6.2.0" + "cosmiconfig" "^7.0.1" "@svgr/hast-util-to-babel-ast@^6.2.1": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.2.1.tgz#ae065567b74cbe745afae617053adf9a764bea25" - integrity sha512-pt7MMkQFDlWJVy9ULJ1h+hZBDGFfSCwlBNW1HkLnVi7jUhyEXUaGYWi1x6bM2IXuAR9l265khBT4Av4lPmaNLQ== + "integrity" "sha512-pt7MMkQFDlWJVy9ULJ1h+hZBDGFfSCwlBNW1HkLnVi7jUhyEXUaGYWi1x6bM2IXuAR9l265khBT4Av4lPmaNLQ==" + "resolved" "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.2.1.tgz" + "version" "6.2.1" dependencies: "@babel/types" "^7.15.6" - entities "^3.0.1" + "entities" "^3.0.1" "@svgr/plugin-jsx@^6.2.1": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-6.2.1.tgz#5668f1d2aa18c2f1bb7a1fc9f682d3f9aed263bd" - integrity sha512-u+MpjTsLaKo6r3pHeeSVsh9hmGRag2L7VzApWIaS8imNguqoUwDq/u6U/NDmYs/KAsrmtBjOEaAAPbwNGXXp1g== + "integrity" "sha512-u+MpjTsLaKo6r3pHeeSVsh9hmGRag2L7VzApWIaS8imNguqoUwDq/u6U/NDmYs/KAsrmtBjOEaAAPbwNGXXp1g==" + "resolved" "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.2.1.tgz" + "version" "6.2.1" dependencies: "@babel/core" "^7.15.5" "@svgr/babel-preset" "^6.2.0" "@svgr/hast-util-to-babel-ast" "^6.2.1" - svg-parser "^2.0.2" + "svg-parser" "^2.0.2" "@svgr/plugin-svgo@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-6.2.0.tgz#4cbe6a33ccccdcae4e3b63ded64cc1cbe1faf48c" - integrity sha512-oDdMQONKOJEbuKwuy4Np6VdV6qoaLLvoY86hjvQEgU82Vx1MSWRyYms6Sl0f+NtqxLI/rDVufATbP/ev996k3Q== + "integrity" "sha512-oDdMQONKOJEbuKwuy4Np6VdV6qoaLLvoY86hjvQEgU82Vx1MSWRyYms6Sl0f+NtqxLI/rDVufATbP/ev996k3Q==" + "resolved" "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-6.2.0.tgz" + "version" "6.2.0" dependencies: - cosmiconfig "^7.0.1" - deepmerge "^4.2.2" - svgo "^2.5.0" + "cosmiconfig" "^7.0.1" + "deepmerge" "^4.2.2" + "svgo" "^2.5.0" "@svgr/webpack@^6.0.0": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-6.2.1.tgz#ef5d51c1b6be4e7537fb9f76b3f2b2e22b63c58d" - integrity sha512-h09ngMNd13hnePwgXa+Y5CgOjzlCvfWLHg+MBnydEedAnuLRzUHUJmGS3o2OsrhxTOOqEsPOFt5v/f6C5Qulcw== + "integrity" "sha512-h09ngMNd13hnePwgXa+Y5CgOjzlCvfWLHg+MBnydEedAnuLRzUHUJmGS3o2OsrhxTOOqEsPOFt5v/f6C5Qulcw==" + "resolved" "https://registry.npmjs.org/@svgr/webpack/-/webpack-6.2.1.tgz" + "version" "6.2.1" dependencies: "@babel/core" "^7.15.5" "@babel/plugin-transform-react-constant-elements" "^7.14.5" @@ -1799,81 +1798,81 @@ "@svgr/plugin-svgo" "^6.2.0" "@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + "integrity" "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==" + "resolved" "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz" + "version" "1.1.2" dependencies: - defer-to-connect "^1.0.1" + "defer-to-connect" "^1.0.1" "@trysound/sax@0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" - integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== + "integrity" "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==" + "resolved" "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz" + "version" "0.2.0" "@types/body-parser@*": - version "1.19.2" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" - integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + "integrity" "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==" + "resolved" "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz" + "version" "1.19.2" dependencies: "@types/connect" "*" "@types/node" "*" "@types/bonjour@^3.5.9": - version "3.5.10" - resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" - integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== + "integrity" "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==" + "resolved" "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz" + "version" "3.5.10" dependencies: "@types/node" "*" "@types/connect-history-api-fallback@^1.3.5": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" - integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== + "integrity" "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==" + "resolved" "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz" + "version" "1.3.5" dependencies: "@types/express-serve-static-core" "*" "@types/node" "*" "@types/connect@*": - version "3.4.35" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" - integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + "integrity" "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==" + "resolved" "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz" + "version" "3.4.35" dependencies: "@types/node" "*" "@types/eslint-scope@^3.7.3": - version "3.7.3" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224" - integrity sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g== + "integrity" "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==" + "resolved" "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz" + "version" "3.7.3" dependencies: "@types/eslint" "*" "@types/estree" "*" "@types/eslint@*": - version "8.4.1" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.1.tgz#c48251553e8759db9e656de3efc846954ac32304" - integrity sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA== + "integrity" "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==" + "resolved" "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz" + "version" "8.4.1" dependencies: "@types/estree" "*" "@types/json-schema" "*" "@types/estree@*", "@types/estree@^0.0.51": - version "0.0.51" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" - integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== + "integrity" "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==" + "resolved" "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz" + "version" "0.0.51" "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18": - version "4.17.28" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz#c47def9f34ec81dc6328d0b1b5303d1ec98d86b8" - integrity sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig== + "integrity" "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==" + "resolved" "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz" + "version" "4.17.28" dependencies: "@types/node" "*" "@types/qs" "*" "@types/range-parser" "*" "@types/express@*", "@types/express@^4.17.13": - version "4.17.13" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" - integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== + "integrity" "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==" + "resolved" "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz" + "version" "4.17.13" dependencies: "@types/body-parser" "*" "@types/express-serve-static-core" "^4.17.18" @@ -1881,172 +1880,172 @@ "@types/serve-static" "*" "@types/hast@^2.0.0": - version "2.3.4" - resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" - integrity sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g== + "integrity" "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==" + "resolved" "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz" + "version" "2.3.4" dependencies: "@types/unist" "*" "@types/html-minifier-terser@^6.0.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" - integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== + "integrity" "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + "resolved" "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz" + "version" "6.1.0" "@types/http-proxy@^1.17.8": - version "1.17.8" - resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.8.tgz#968c66903e7e42b483608030ee85800f22d03f55" - integrity sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA== + "integrity" "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==" + "resolved" "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz" + "version" "1.17.8" dependencies: "@types/node" "*" "@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": - version "7.0.9" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" - integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== + "integrity" "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" + "resolved" "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz" + "version" "7.0.9" "@types/mdast@^3.0.0": - version "3.0.10" - resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af" - integrity sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA== + "integrity" "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==" + "resolved" "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz" + "version" "3.0.10" dependencies: "@types/unist" "*" "@types/mime@^1": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" - integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== + "integrity" "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + "resolved" "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz" + "version" "1.3.2" "@types/node@*", "@types/node@^17.0.5": - version "17.0.18" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.18.tgz#3b4fed5cfb58010e3a2be4b6e74615e4847f1074" - integrity sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA== + "integrity" "sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==" + "resolved" "https://registry.npmjs.org/@types/node/-/node-17.0.18.tgz" + "version" "17.0.18" "@types/parse-json@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" - integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + "integrity" "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" + "resolved" "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz" + "version" "4.0.0" "@types/parse5@^5.0.0": - version "5.0.3" - resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109" - integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== + "integrity" "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==" + "resolved" "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz" + "version" "5.0.3" "@types/prop-types@*": - version "15.7.4" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" - integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ== + "integrity" "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==" + "resolved" "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz" + "version" "15.7.4" "@types/qs@*": - version "6.9.7" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" - integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + "integrity" "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + "resolved" "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz" + "version" "6.9.7" "@types/range-parser@*": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" - integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + "integrity" "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + "resolved" "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz" + "version" "1.2.4" -"@types/react@*": - version "17.0.39" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.39.tgz#d0f4cde092502a6db00a1cded6e6bf2abb7633ce" - integrity sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug== +"@types/react@*", "@types/react@>= 16.8.0 < 18.0.0": + "integrity" "sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==" + "resolved" "https://registry.npmjs.org/@types/react/-/react-17.0.39.tgz" + "version" "17.0.39" dependencies: "@types/prop-types" "*" "@types/scheduler" "*" - csstype "^3.0.2" + "csstype" "^3.0.2" "@types/retry@^0.12.0": - version "0.12.1" - resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065" - integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g== + "integrity" "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==" + "resolved" "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz" + "version" "0.12.1" "@types/sax@^1.2.1": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@types/sax/-/sax-1.2.4.tgz#8221affa7f4f3cb21abd22f244cfabfa63e6a69e" - integrity sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw== + "integrity" "sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw==" + "resolved" "https://registry.npmjs.org/@types/sax/-/sax-1.2.4.tgz" + "version" "1.2.4" dependencies: "@types/node" "*" "@types/scheduler@*": - version "0.16.2" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" - integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== + "integrity" "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" + "resolved" "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz" + "version" "0.16.2" "@types/serve-index@^1.9.1": - version "1.9.1" - resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" - integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== + "integrity" "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==" + "resolved" "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz" + "version" "1.9.1" dependencies: "@types/express" "*" "@types/serve-static@*": - version "1.13.10" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" - integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ== + "integrity" "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==" + "resolved" "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz" + "version" "1.13.10" dependencies: "@types/mime" "^1" "@types/node" "*" "@types/sockjs@^0.3.33": - version "0.3.33" - resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" - integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== + "integrity" "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==" + "resolved" "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz" + "version" "0.3.33" dependencies: "@types/node" "*" "@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" - integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== + "integrity" "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" + "resolved" "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz" + "version" "2.0.6" "@types/ws@^8.2.2": - version "8.2.2" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.2.2.tgz#7c5be4decb19500ae6b3d563043cd407bf366c21" - integrity sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg== + "integrity" "sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg==" + "resolved" "https://registry.npmjs.org/@types/ws/-/ws-8.2.2.tgz" + "version" "8.2.2" dependencies: "@types/node" "*" "@webassemblyjs/ast@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" - integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== + "integrity" "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/helper-numbers" "1.11.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.1" "@webassemblyjs/floating-point-hex-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" - integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== + "integrity" "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz" + "version" "1.11.1" "@webassemblyjs/helper-api-error@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" - integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== + "integrity" "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz" + "version" "1.11.1" "@webassemblyjs/helper-buffer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" - integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== + "integrity" "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz" + "version" "1.11.1" "@webassemblyjs/helper-numbers@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" - integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== + "integrity" "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/floating-point-hex-parser" "1.11.1" "@webassemblyjs/helper-api-error" "1.11.1" "@xtuc/long" "4.2.2" "@webassemblyjs/helper-wasm-bytecode@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" - integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== + "integrity" "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz" + "version" "1.11.1" "@webassemblyjs/helper-wasm-section@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" - integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== + "integrity" "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/helper-buffer" "1.11.1" @@ -2054,28 +2053,28 @@ "@webassemblyjs/wasm-gen" "1.11.1" "@webassemblyjs/ieee754@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" - integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== + "integrity" "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz" + "version" "1.11.1" dependencies: "@xtuc/ieee754" "^1.2.0" "@webassemblyjs/leb128@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" - integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== + "integrity" "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz" + "version" "1.11.1" dependencies: "@xtuc/long" "4.2.2" "@webassemblyjs/utf8@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" - integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== + "integrity" "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz" + "version" "1.11.1" "@webassemblyjs/wasm-edit@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" - integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== + "integrity" "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/helper-buffer" "1.11.1" @@ -2087,9 +2086,9 @@ "@webassemblyjs/wast-printer" "1.11.1" "@webassemblyjs/wasm-gen@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" - integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== + "integrity" "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.1" @@ -2098,9 +2097,9 @@ "@webassemblyjs/utf8" "1.11.1" "@webassemblyjs/wasm-opt@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" - integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== + "integrity" "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/helper-buffer" "1.11.1" @@ -2108,9 +2107,9 @@ "@webassemblyjs/wasm-parser" "1.11.1" "@webassemblyjs/wasm-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" - integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== + "integrity" "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/helper-api-error" "1.11.1" @@ -2120,124 +2119,124 @@ "@webassemblyjs/utf8" "1.11.1" "@webassemblyjs/wast-printer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" - integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== + "integrity" "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/ast" "1.11.1" "@xtuc/long" "4.2.2" "@xtuc/ieee754@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + "integrity" "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + "resolved" "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz" + "version" "1.2.0" "@xtuc/long@4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== - -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== - dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" - -acorn-dynamic-import@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948" - integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw== - -acorn-import-assertions@^1.7.6: - version "1.8.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" - integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== - -acorn-jsx@^5.0.1: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn-walk@^8.0.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== - -acorn@^6.1.1: - version "6.4.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" - integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== - -acorn@^8.0.4, acorn@^8.4.1, acorn@^8.5.0: - version "8.7.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" - integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== - -address@^1.0.1, address@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" - integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA== - -aggregate-error@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" - integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - -ajv-formats@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" - integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== - dependencies: - ajv "^8.0.0" - -ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" - integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== - -ajv-keywords@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" - integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== - dependencies: - fast-deep-equal "^3.1.3" - -ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ajv@^8.0.0, ajv@^8.8.0: - version "8.10.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.10.0.tgz#e573f719bd3af069017e3b66538ab968d040e54d" - integrity sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - -algoliasearch-helper@^3.5.5: - version "3.7.0" - resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.7.0.tgz#c0a0493df84d850360f664ad7a9d4fc78a94fd78" - integrity sha512-XJ3QfERBLfeVCyTVx80gon7r3/rgm/CE8Ha1H7cbablRe/X7SfYQ14g/eO+MhjVKIQp+gy9oC6G5ilmLwS1k6w== + "integrity" "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + "resolved" "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz" + "version" "4.2.2" + +"accepts@~1.3.4", "accepts@~1.3.5", "accepts@~1.3.8": + "integrity" "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==" + "resolved" "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz" + "version" "1.3.8" + dependencies: + "mime-types" "~2.1.34" + "negotiator" "0.6.3" + +"acorn-dynamic-import@^4.0.0": + "integrity" "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==" + "resolved" "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz" + "version" "4.0.0" + +"acorn-import-assertions@^1.7.6": + "integrity" "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==" + "resolved" "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz" + "version" "1.8.0" + +"acorn-jsx@^5.0.1": + "integrity" "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==" + "resolved" "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" + "version" "5.3.2" + +"acorn-walk@^8.0.0": + "integrity" "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" + "resolved" "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" + "version" "8.2.0" + +"acorn@^6.0.0", "acorn@^6.0.0 || ^7.0.0 || ^8.0.0", "acorn@^6.1.1": + "integrity" "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==" + "resolved" "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz" + "version" "6.4.2" + +"acorn@^8", "acorn@^8.0.4", "acorn@^8.4.1", "acorn@^8.5.0": + "integrity" "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==" + "resolved" "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz" + "version" "8.7.1" + +"address@^1.0.1", "address@^1.1.2": + "integrity" "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==" + "resolved" "https://registry.npmjs.org/address/-/address-1.1.2.tgz" + "version" "1.1.2" + +"aggregate-error@^3.0.0": + "integrity" "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==" + "resolved" "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "clean-stack" "^2.0.0" + "indent-string" "^4.0.0" + +"ajv-formats@^2.1.1": + "integrity" "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==" + "resolved" "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz" + "version" "2.1.1" + dependencies: + "ajv" "^8.0.0" + +"ajv-keywords@^3.4.1", "ajv-keywords@^3.5.2": + "integrity" "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" + "resolved" "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" + "version" "3.5.2" + +"ajv-keywords@^5.0.0": + "integrity" "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==" + "resolved" "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "fast-deep-equal" "^3.1.3" + +"ajv@^6.12.2", "ajv@^6.12.4", "ajv@^6.12.5", "ajv@^6.9.1": + "integrity" "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==" + "resolved" "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" + "version" "6.12.6" + dependencies: + "fast-deep-equal" "^3.1.1" + "fast-json-stable-stringify" "^2.0.0" + "json-schema-traverse" "^0.4.1" + "uri-js" "^4.2.2" + +"ajv@^8.0.0", "ajv@^8.8.0", "ajv@^8.8.2": + "integrity" "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==" + "resolved" "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz" + "version" "8.10.0" + dependencies: + "fast-deep-equal" "^3.1.1" + "json-schema-traverse" "^1.0.0" + "require-from-string" "^2.0.2" + "uri-js" "^4.2.2" + +"algoliasearch-helper@^3.5.5": + "integrity" "sha512-XJ3QfERBLfeVCyTVx80gon7r3/rgm/CE8Ha1H7cbablRe/X7SfYQ14g/eO+MhjVKIQp+gy9oC6G5ilmLwS1k6w==" + "resolved" "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.7.0.tgz" + "version" "3.7.0" dependencies: "@algolia/events" "^4.0.1" -algoliasearch@^4.0.0, algoliasearch@^4.10.5: - version "4.12.1" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.12.1.tgz#574a2c5424c4b6681c026928fb810be2d2ec3924" - integrity sha512-c0dM1g3zZBJrkzE5GA/Nu1y3fFxx3LCzxKzcmp2dgGS8P4CjszB/l3lsSh2MSrrK1Hn/KV4BlbBMXtYgG1Bfrw== +"algoliasearch@^4.0.0", "algoliasearch@^4.10.5", "algoliasearch@^4.9.1", "algoliasearch@>= 3.1 < 5": + "integrity" "sha512-c0dM1g3zZBJrkzE5GA/Nu1y3fFxx3LCzxKzcmp2dgGS8P4CjszB/l3lsSh2MSrrK1Hn/KV4BlbBMXtYgG1Bfrw==" + "resolved" "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/cache-browser-local-storage" "4.12.1" "@algolia/cache-common" "4.12.1" @@ -2254,2429 +2253,2448 @@ algoliasearch@^4.0.0, algoliasearch@^4.10.5: "@algolia/requester-node-http" "4.12.1" "@algolia/transporter" "4.12.1" -ansi-align@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" - integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== - dependencies: - string-width "^4.1.0" - -ansi-html-community@^0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" - integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -arg@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.1.tgz#eb0c9a8f77786cad2af8ff2b862899842d7b6adb" - integrity sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA== - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - -array-flatten@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" - integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -array-union@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-3.0.1.tgz#da52630d327f8b88cfbfb57728e2af5cd9b6b975" - integrity sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw== - -asap@~2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= - -async@^2.6.2: - version "2.6.4" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" - integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== - dependencies: - lodash "^4.17.14" - -at-least-node@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" - integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== - -autoprefixer@^10.3.5, autoprefixer@^10.3.7: - version "10.4.2" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.2.tgz#25e1df09a31a9fba5c40b578936b90d35c9d4d3b" - integrity sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ== - dependencies: - browserslist "^4.19.1" - caniuse-lite "^1.0.30001297" - fraction.js "^4.1.2" - normalize-range "^0.1.2" - picocolors "^1.0.0" - postcss-value-parser "^4.2.0" - -axios@^0.25.0: - version "0.25.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.25.0.tgz#349cfbb31331a9b4453190791760a8d35b093e0a" - integrity sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g== - dependencies: - follow-redirects "^1.14.7" - -babel-loader@^8.2.2: - version "8.2.3" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.3.tgz#8986b40f1a64cacfcb4b8429320085ef68b1342d" - integrity sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw== - dependencies: - find-cache-dir "^3.3.1" - loader-utils "^1.4.0" - make-dir "^3.1.0" - schema-utils "^2.6.5" - -babel-plugin-apply-mdx-type-prop@1.6.22: - version "1.6.22" - resolved "https://registry.yarnpkg.com/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz#d216e8fd0de91de3f1478ef3231e05446bc8705b" - integrity sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ== +"ansi-align@^3.0.0": + "integrity" "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==" + "resolved" "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "string-width" "^4.1.0" + +"ansi-html-community@^0.0.8": + "integrity" "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==" + "resolved" "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz" + "version" "0.0.8" + +"ansi-regex@^5.0.1": + "integrity" "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" + "version" "5.0.1" + +"ansi-regex@^6.0.1": + "integrity" "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz" + "version" "6.0.1" + +"ansi-styles@^3.2.1": + "integrity" "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==" + "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + "version" "3.2.1" + dependencies: + "color-convert" "^1.9.0" + +"ansi-styles@^4.0.0", "ansi-styles@^4.1.0": + "integrity" "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==" + "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + "version" "4.3.0" + dependencies: + "color-convert" "^2.0.1" + +"anymatch@~3.1.2": + "integrity" "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==" + "resolved" "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz" + "version" "3.1.2" + dependencies: + "normalize-path" "^3.0.0" + "picomatch" "^2.0.4" + +"arg@^5.0.0": + "integrity" "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==" + "resolved" "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz" + "version" "5.0.1" + +"argparse@^1.0.7": + "integrity" "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==" + "resolved" "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" + "version" "1.0.10" + dependencies: + "sprintf-js" "~1.0.2" + +"argparse@^2.0.1": + "integrity" "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "resolved" "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" + "version" "2.0.1" + +"array-flatten@^2.1.0": + "integrity" "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + "resolved" "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz" + "version" "2.1.2" + +"array-flatten@1.1.1": + "integrity" "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "resolved" "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" + "version" "1.1.1" + +"array-union@^2.1.0": + "integrity" "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + "resolved" "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" + "version" "2.1.0" + +"array-union@^3.0.1": + "integrity" "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==" + "resolved" "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz" + "version" "3.0.1" + +"asap@~2.0.3": + "integrity" "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + "resolved" "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz" + "version" "2.0.6" + +"async@^2.6.2": + "integrity" "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==" + "resolved" "https://registry.npmjs.org/async/-/async-2.6.4.tgz" + "version" "2.6.4" + dependencies: + "lodash" "^4.17.14" + +"at-least-node@^1.0.0": + "integrity" "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + "resolved" "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz" + "version" "1.0.0" + +"autoprefixer@^10.3.5", "autoprefixer@^10.3.7": + "integrity" "sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==" + "resolved" "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz" + "version" "10.4.2" + dependencies: + "browserslist" "^4.19.1" + "caniuse-lite" "^1.0.30001297" + "fraction.js" "^4.1.2" + "normalize-range" "^0.1.2" + "picocolors" "^1.0.0" + "postcss-value-parser" "^4.2.0" + +"axios@^0.25.0": + "integrity" "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==" + "resolved" "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz" + "version" "0.25.0" + dependencies: + "follow-redirects" "^1.14.7" + +"babel-loader@^8.2.2": + "integrity" "sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw==" + "resolved" "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.3.tgz" + "version" "8.2.3" + dependencies: + "find-cache-dir" "^3.3.1" + "loader-utils" "^1.4.0" + "make-dir" "^3.1.0" + "schema-utils" "^2.6.5" + +"babel-plugin-apply-mdx-type-prop@1.6.22": + "integrity" "sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ==" + "resolved" "https://registry.npmjs.org/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz" + "version" "1.6.22" dependencies: "@babel/helper-plugin-utils" "7.10.4" "@mdx-js/util" "1.6.22" -babel-plugin-dynamic-import-node@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" - integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== +"babel-plugin-dynamic-import-node@^2.3.3": + "integrity" "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==" + "resolved" "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz" + "version" "2.3.3" dependencies: - object.assign "^4.1.0" + "object.assign" "^4.1.0" -babel-plugin-dynamic-import-node@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" - integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== +"babel-plugin-dynamic-import-node@2.3.0": + "integrity" "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==" + "resolved" "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz" + "version" "2.3.0" dependencies: - object.assign "^4.1.0" + "object.assign" "^4.1.0" -babel-plugin-extract-import-names@1.6.22: - version "1.6.22" - resolved "https://registry.yarnpkg.com/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz#de5f9a28eb12f3eb2578bf74472204e66d1a13dc" - integrity sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ== +"babel-plugin-extract-import-names@1.6.22": + "integrity" "sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ==" + "resolved" "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz" + "version" "1.6.22" dependencies: "@babel/helper-plugin-utils" "7.10.4" -babel-plugin-polyfill-corejs2@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz#440f1b70ccfaabc6b676d196239b138f8a2cfba5" - integrity sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w== +"babel-plugin-polyfill-corejs2@^0.3.0": + "integrity" "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==" + "resolved" "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz" + "version" "0.3.1" dependencies: "@babel/compat-data" "^7.13.11" "@babel/helper-define-polyfill-provider" "^0.3.1" - semver "^6.1.1" + "semver" "^6.1.1" -babel-plugin-polyfill-corejs3@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz#aabe4b2fa04a6e038b688c5e55d44e78cd3a5f72" - integrity sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ== +"babel-plugin-polyfill-corejs3@^0.5.0": + "integrity" "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==" + "resolved" "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz" + "version" "0.5.2" dependencies: "@babel/helper-define-polyfill-provider" "^0.3.1" - core-js-compat "^3.21.0" + "core-js-compat" "^3.21.0" -babel-plugin-polyfill-regenerator@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz#2c0678ea47c75c8cc2fbb1852278d8fb68233990" - integrity sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A== +"babel-plugin-polyfill-regenerator@^0.3.0": + "integrity" "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==" + "resolved" "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz" + "version" "0.3.1" dependencies: "@babel/helper-define-polyfill-provider" "^0.3.1" -bail@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" - integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base16@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/base16/-/base16-1.0.0.tgz#e297f60d7ec1014a7a971a39ebc8a98c0b681e70" - integrity sha1-4pf2DX7BAUp6lxo568ipjAtoHnA= - -batch@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" - integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= - -big.js@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -bluebird@^3.7.1: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - -body-parser@1.19.2: - version "1.19.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.2.tgz#4714ccd9c157d44797b8b5607d72c0b89952f26e" - integrity sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw== - dependencies: - bytes "3.1.2" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.8.1" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.9.7" - raw-body "2.4.3" - type-is "~1.6.18" - -bonjour@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" - integrity sha1-jokKGD2O6aI5OzhExpGkK897yfU= - dependencies: - array-flatten "^2.1.0" - deep-equal "^1.0.1" - dns-equal "^1.0.0" - dns-txt "^2.0.2" - multicast-dns "^6.0.1" - multicast-dns-service-types "^1.1.0" - -boolbase@^1.0.0, boolbase@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= - -boxen@^5.0.0, boxen@^5.0.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" - integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== - dependencies: - ansi-align "^3.0.0" - camelcase "^6.2.0" - chalk "^4.1.0" - cli-boxes "^2.2.1" - string-width "^4.2.2" - type-fest "^0.20.2" - widest-line "^3.1.0" - wrap-ansi "^7.0.0" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^3.0.1, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.17.5, browserslist@^4.18.1, browserslist@^4.19.1: - version "4.19.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3" - integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A== - dependencies: - caniuse-lite "^1.0.30001286" - electron-to-chromium "^1.4.17" - escalade "^3.1.1" - node-releases "^2.0.1" - picocolors "^1.0.0" - -buble-jsx-only@^0.19.8: - version "0.19.8" - resolved "https://registry.yarnpkg.com/buble-jsx-only/-/buble-jsx-only-0.19.8.tgz#6e3524aa0f1c523de32496ac9aceb9cc2b493867" - integrity sha512-7AW19pf7PrKFnGTEDzs6u9+JZqQwM1VnLS19OlqYDhXomtFFknnoQJAPHeg84RMFWAvOhYrG7harizJNwUKJsA== - dependencies: - acorn "^6.1.1" - acorn-dynamic-import "^4.0.0" - acorn-jsx "^5.0.1" - chalk "^2.4.2" - magic-string "^0.25.3" - minimist "^1.2.0" - regexpu-core "^4.5.4" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -buffer-indexof@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" - integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== - -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^1.0.2" - -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camel-case@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" - integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== - dependencies: - pascal-case "^3.1.2" - tslib "^2.0.3" - -camelcase-css@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" - integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== - -camelcase@^6.2.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -caniuse-api@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" - integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== - dependencies: - browserslist "^4.0.0" - caniuse-lite "^1.0.0" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001297: - version "1.0.30001312" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz#e11eba4b87e24d22697dae05455d5aea28550d5f" - integrity sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ== - -ccount@^1.0.0, ccount@^1.0.3: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" - integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== - -chalk@^2.0.0, chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.1.0, chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -character-entities-legacy@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" - integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== - -character-entities@^1.0.0: - version "1.2.4" - resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" - integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== - -character-reference-invalid@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" - integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== - -cheerio-select@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-1.5.0.tgz#faf3daeb31b17c5e1a9dabcee288aaf8aafa5823" - integrity sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg== - dependencies: - css-select "^4.1.3" - css-what "^5.0.1" - domelementtype "^2.2.0" - domhandler "^4.2.0" - domutils "^2.7.0" - -cheerio@^0.22.0: - version "0.22.0" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" - integrity sha1-qbqoYKP5tZWmuBsahocxIe06Jp4= - dependencies: - css-select "~1.2.0" - dom-serializer "~0.1.0" - entities "~1.1.1" - htmlparser2 "^3.9.1" - lodash.assignin "^4.0.9" - lodash.bind "^4.1.4" - lodash.defaults "^4.0.1" - lodash.filter "^4.4.0" - lodash.flatten "^4.2.0" - lodash.foreach "^4.3.0" - lodash.map "^4.4.0" - lodash.merge "^4.4.0" - lodash.pick "^4.2.1" - lodash.reduce "^4.4.0" - lodash.reject "^4.4.0" - lodash.some "^4.4.0" - -cheerio@^1.0.0-rc.10: - version "1.0.0-rc.10" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.10.tgz#2ba3dcdfcc26e7956fc1f440e61d51c643379f3e" - integrity sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw== - dependencies: - cheerio-select "^1.5.0" - dom-serializer "^1.3.2" - domhandler "^4.2.0" - htmlparser2 "^6.1.0" - parse5 "^6.0.1" - parse5-htmlparser2-tree-adapter "^6.0.1" - tslib "^2.2.0" - -chokidar@^3.4.2, chokidar@^3.5.2, chokidar@^3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" +"bail@^1.0.0": + "integrity" "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==" + "resolved" "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz" + "version" "1.0.5" + +"balanced-match@^1.0.0": + "integrity" "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "resolved" "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + "version" "1.0.2" + +"base16@^1.0.0": + "integrity" "sha1-4pf2DX7BAUp6lxo568ipjAtoHnA=" + "resolved" "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz" + "version" "1.0.0" + +"batch@0.6.1": + "integrity" "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" + "resolved" "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz" + "version" "0.6.1" + +"big.js@^5.2.2": + "integrity" "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + "resolved" "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz" + "version" "5.2.2" + +"binary-extensions@^2.0.0": + "integrity" "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + "resolved" "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" + "version" "2.2.0" + +"bluebird@^3.7.1": + "integrity" "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + "resolved" "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz" + "version" "3.7.2" + +"body-parser@1.19.2": + "integrity" "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==" + "resolved" "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz" + "version" "1.19.2" + dependencies: + "bytes" "3.1.2" + "content-type" "~1.0.4" + "debug" "2.6.9" + "depd" "~1.1.2" + "http-errors" "1.8.1" + "iconv-lite" "0.4.24" + "on-finished" "~2.3.0" + "qs" "6.9.7" + "raw-body" "2.4.3" + "type-is" "~1.6.18" + +"bonjour@^3.5.0": + "integrity" "sha1-jokKGD2O6aI5OzhExpGkK897yfU=" + "resolved" "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz" + "version" "3.5.0" + dependencies: + "array-flatten" "^2.1.0" + "deep-equal" "^1.0.1" + "dns-equal" "^1.0.0" + "dns-txt" "^2.0.2" + "multicast-dns" "^6.0.1" + "multicast-dns-service-types" "^1.1.0" + +"boolbase@^1.0.0", "boolbase@~1.0.0": + "integrity" "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + "resolved" "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz" + "version" "1.0.0" + +"boxen@^5.0.0", "boxen@^5.0.1": + "integrity" "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==" + "resolved" "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz" + "version" "5.1.2" + dependencies: + "ansi-align" "^3.0.0" + "camelcase" "^6.2.0" + "chalk" "^4.1.0" + "cli-boxes" "^2.2.1" + "string-width" "^4.2.2" + "type-fest" "^0.20.2" + "widest-line" "^3.1.0" + "wrap-ansi" "^7.0.0" + +"brace-expansion@^1.1.7": + "integrity" "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==" + "resolved" "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + "version" "1.1.11" + dependencies: + "balanced-match" "^1.0.0" + "concat-map" "0.0.1" + +"braces@^3.0.1", "braces@~3.0.2": + "integrity" "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==" + "resolved" "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "fill-range" "^7.0.1" + +"browserslist@^4.0.0", "browserslist@^4.14.5", "browserslist@^4.16.6", "browserslist@^4.18.1", "browserslist@^4.19.1", "browserslist@^4.21.3", "browserslist@>= 4.21.0": + "integrity" "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==" + "resolved" "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz" + "version" "4.21.5" + dependencies: + "caniuse-lite" "^1.0.30001449" + "electron-to-chromium" "^1.4.284" + "node-releases" "^2.0.8" + "update-browserslist-db" "^1.0.10" + +"buble-jsx-only@^0.19.8": + "integrity" "sha512-7AW19pf7PrKFnGTEDzs6u9+JZqQwM1VnLS19OlqYDhXomtFFknnoQJAPHeg84RMFWAvOhYrG7harizJNwUKJsA==" + "resolved" "https://registry.npmjs.org/buble-jsx-only/-/buble-jsx-only-0.19.8.tgz" + "version" "0.19.8" + dependencies: + "acorn" "^6.1.1" + "acorn-dynamic-import" "^4.0.0" + "acorn-jsx" "^5.0.1" + "chalk" "^2.4.2" + "magic-string" "^0.25.3" + "minimist" "^1.2.0" + "regexpu-core" "^4.5.4" + +"buffer-from@^1.0.0": + "integrity" "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "resolved" "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" + "version" "1.1.2" + +"buffer-indexof@^1.0.0": + "integrity" "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==" + "resolved" "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz" + "version" "1.1.1" + +"bytes@3.0.0": + "integrity" "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + "resolved" "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz" + "version" "3.0.0" + +"bytes@3.1.2": + "integrity" "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + "resolved" "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" + "version" "3.1.2" + +"cacheable-request@^6.0.0": + "integrity" "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==" + "resolved" "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "clone-response" "^1.0.2" + "get-stream" "^5.1.0" + "http-cache-semantics" "^4.0.0" + "keyv" "^3.0.0" + "lowercase-keys" "^2.0.0" + "normalize-url" "^4.1.0" + "responselike" "^1.0.2" + +"call-bind@^1.0.0", "call-bind@^1.0.2": + "integrity" "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==" + "resolved" "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "function-bind" "^1.1.1" + "get-intrinsic" "^1.0.2" + +"callsites@^3.0.0": + "integrity" "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + "resolved" "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + "version" "3.1.0" + +"camel-case@^4.1.2": + "integrity" "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==" + "resolved" "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "pascal-case" "^3.1.2" + "tslib" "^2.0.3" + +"camelcase-css@2.0.1": + "integrity" "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==" + "resolved" "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz" + "version" "2.0.1" + +"camelcase@^6.2.0": + "integrity" "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + "resolved" "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + "version" "6.3.0" + +"caniuse-api@^3.0.0": + "integrity" "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==" + "resolved" "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "browserslist" "^4.0.0" + "caniuse-lite" "^1.0.0" + "lodash.memoize" "^4.1.2" + "lodash.uniq" "^4.5.0" + +"caniuse-lite@^1.0.0", "caniuse-lite@^1.0.30001297", "caniuse-lite@^1.0.30001449": + "integrity" "sha512-ewtFBSfWjEmxUgNBSZItFSmVtvk9zkwkl1OfRZlKA8slltRN+/C/tuGVrF9styXkN36Yu3+SeJ1qkXxDEyNZ5w==" + "resolved" "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001466.tgz" + "version" "1.0.30001466" + +"ccount@^1.0.0", "ccount@^1.0.3": + "integrity" "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==" + "resolved" "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz" + "version" "1.1.0" + +"chalk@^2.0.0": + "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "ansi-styles" "^3.2.1" + "escape-string-regexp" "^1.0.5" + "supports-color" "^5.3.0" + +"chalk@^2.4.2": + "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "ansi-styles" "^3.2.1" + "escape-string-regexp" "^1.0.5" + "supports-color" "^5.3.0" + +"chalk@^4.1.0", "chalk@^4.1.2": + "integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "ansi-styles" "^4.1.0" + "supports-color" "^7.1.0" + +"character-entities-legacy@^1.0.0": + "integrity" "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==" + "resolved" "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz" + "version" "1.1.4" + +"character-entities@^1.0.0": + "integrity" "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==" + "resolved" "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz" + "version" "1.2.4" + +"character-reference-invalid@^1.0.0": + "integrity" "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==" + "resolved" "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz" + "version" "1.1.4" + +"cheerio-select@^1.5.0": + "integrity" "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==" + "resolved" "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz" + "version" "1.5.0" + dependencies: + "css-select" "^4.1.3" + "css-what" "^5.0.1" + "domelementtype" "^2.2.0" + "domhandler" "^4.2.0" + "domutils" "^2.7.0" + +"cheerio@^0.22.0": + "integrity" "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=" + "resolved" "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz" + "version" "0.22.0" + dependencies: + "css-select" "~1.2.0" + "dom-serializer" "~0.1.0" + "entities" "~1.1.1" + "htmlparser2" "^3.9.1" + "lodash.assignin" "^4.0.9" + "lodash.bind" "^4.1.4" + "lodash.defaults" "^4.0.1" + "lodash.filter" "^4.4.0" + "lodash.flatten" "^4.2.0" + "lodash.foreach" "^4.3.0" + "lodash.map" "^4.4.0" + "lodash.merge" "^4.4.0" + "lodash.pick" "^4.2.1" + "lodash.reduce" "^4.4.0" + "lodash.reject" "^4.4.0" + "lodash.some" "^4.4.0" + +"cheerio@^1.0.0-rc.10": + "integrity" "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==" + "resolved" "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz" + "version" "1.0.0-rc.10" + dependencies: + "cheerio-select" "^1.5.0" + "dom-serializer" "^1.3.2" + "domhandler" "^4.2.0" + "htmlparser2" "^6.1.0" + "parse5" "^6.0.1" + "parse5-htmlparser2-tree-adapter" "^6.0.1" + "tslib" "^2.2.0" + +"chokidar@^3.4.2", "chokidar@^3.5.2", "chokidar@^3.5.3": + "integrity" "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==" + "resolved" "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" + "version" "3.5.3" + dependencies: + "anymatch" "~3.1.2" + "braces" "~3.0.2" + "glob-parent" "~5.1.2" + "is-binary-path" "~2.1.0" + "is-glob" "~4.0.1" + "normalize-path" "~3.0.0" + "readdirp" "~3.6.0" optionalDependencies: - fsevents "~2.3.2" - -chrome-trace-event@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" - integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== - -ci-info@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" - integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== - -classnames@^2.2.6: - version "2.3.1" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" - integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== - -clean-css@^5.1.5, clean-css@^5.2.2: - version "5.2.4" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.2.4.tgz#982b058f8581adb2ae062520808fb2429bd487a4" - integrity sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg== - dependencies: - source-map "~0.6.0" - -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - -cli-boxes@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" - integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== - -clone-deep@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" - integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== - dependencies: - is-plain-object "^2.0.4" - kind-of "^6.0.2" - shallow-clone "^3.0.0" - -clone-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= - dependencies: - mimic-response "^1.0.0" - -clsx@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" - integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== - -collapse-white-space@^1.0.2: - version "1.0.6" - resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287" - integrity sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -colord@^2.9.1: - version "2.9.2" - resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.2.tgz#25e2bacbbaa65991422c07ea209e2089428effb1" - integrity sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ== - -colorette@^2.0.10: - version "2.0.16" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" - integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== - -combine-promises@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/combine-promises/-/combine-promises-1.1.0.tgz#72db90743c0ca7aab7d0d8d2052fd7b0f674de71" - integrity sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg== - -comma-separated-tokens@^1.0.0: - version "1.0.8" - resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" - integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== - -commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -commander@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" - integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== - -commander@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== - -commander@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" - integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= - -compressible@~2.0.16: - version "2.0.18" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" - integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== - dependencies: - mime-db ">= 1.43.0 < 2" - -compression@^1.7.4: - version "1.7.4" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" - integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== - dependencies: - accepts "~1.3.5" - bytes "3.0.0" - compressible "~2.0.16" - debug "2.6.9" - on-headers "~1.0.2" - safe-buffer "5.1.2" - vary "~1.1.2" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -configstore@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" - integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== - dependencies: - dot-prop "^5.2.0" - graceful-fs "^4.1.2" - make-dir "^3.0.0" - unique-string "^2.0.0" - write-file-atomic "^3.0.0" - xdg-basedir "^4.0.0" - -connect-history-api-fallback@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" - integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== - -consola@^2.15.3: - version "2.15.3" - resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.3.tgz#2e11f98d6a4be71ff72e0bdf07bd23e12cb61550" - integrity sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw== - -content-disposition@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= - -content-disposition@0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" - integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== - dependencies: - safe-buffer "5.2.1" - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -convert-source-map@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" - integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== - dependencies: - safe-buffer "~5.1.1" - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" - integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== - -copy-text-to-clipboard@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz#8cbf8f90e0a47f12e4a24743736265d157bce69c" - integrity sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q== - -copy-webpack-plugin@^10.2.0: - version "10.2.4" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz#6c854be3fdaae22025da34b9112ccf81c63308fe" - integrity sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg== - dependencies: - fast-glob "^3.2.7" - glob-parent "^6.0.1" - globby "^12.0.2" - normalize-path "^3.0.0" - schema-utils "^4.0.0" - serialize-javascript "^6.0.0" - -core-js-compat@^3.20.2, core-js-compat@^3.21.0: - version "3.21.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.21.1.tgz#cac369f67c8d134ff8f9bd1623e3bc2c42068c82" - integrity sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g== - dependencies: - browserslist "^4.19.1" - semver "7.0.0" - -core-js-pure@^3.20.2: - version "3.21.1" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.21.1.tgz#8c4d1e78839f5f46208de7230cebfb72bc3bdb51" - integrity sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ== - -core-js@^3.18.0: - version "3.21.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.21.1.tgz#f2e0ddc1fc43da6f904706e8e955bc19d06a0d94" - integrity sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig== - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -cosmiconfig@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" - integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== + "fsevents" "~2.3.2" + +"chrome-trace-event@^1.0.2": + "integrity" "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==" + "resolved" "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz" + "version" "1.0.3" + +"ci-info@^2.0.0": + "integrity" "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + "resolved" "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz" + "version" "2.0.0" + +"classnames@^2.2.6": + "integrity" "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" + "resolved" "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz" + "version" "2.3.1" + +"clean-css@^5.1.5", "clean-css@^5.2.2": + "integrity" "sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg==" + "resolved" "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz" + "version" "5.2.4" + dependencies: + "source-map" "~0.6.0" + +"clean-stack@^2.0.0": + "integrity" "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + "resolved" "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz" + "version" "2.2.0" + +"cli-boxes@^2.2.1": + "integrity" "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==" + "resolved" "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz" + "version" "2.2.1" + +"clone-deep@^4.0.1": + "integrity" "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==" + "resolved" "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz" + "version" "4.0.1" + dependencies: + "is-plain-object" "^2.0.4" + "kind-of" "^6.0.2" + "shallow-clone" "^3.0.0" + +"clone-response@^1.0.2": + "integrity" "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=" + "resolved" "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "mimic-response" "^1.0.0" + +"clsx@^1.1.1": + "integrity" "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==" + "resolved" "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz" + "version" "1.1.1" + +"collapse-white-space@^1.0.2": + "integrity" "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==" + "resolved" "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz" + "version" "1.0.6" + +"color-convert@^1.9.0": + "integrity" "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==" + "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + "version" "1.9.3" + dependencies: + "color-name" "1.1.3" + +"color-convert@^2.0.1": + "integrity" "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==" + "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "color-name" "~1.1.4" + +"color-name@~1.1.4": + "integrity" "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + "version" "1.1.4" + +"color-name@1.1.3": + "integrity" "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + "version" "1.1.3" + +"colord@^2.9.1": + "integrity" "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==" + "resolved" "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz" + "version" "2.9.2" + +"colorette@^2.0.10": + "integrity" "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==" + "resolved" "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz" + "version" "2.0.16" + +"combine-promises@^1.1.0": + "integrity" "sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg==" + "resolved" "https://registry.npmjs.org/combine-promises/-/combine-promises-1.1.0.tgz" + "version" "1.1.0" + +"comma-separated-tokens@^1.0.0": + "integrity" "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==" + "resolved" "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz" + "version" "1.0.8" + +"commander@^2.20.0": + "integrity" "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "resolved" "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" + "version" "2.20.3" + +"commander@^5.1.0": + "integrity" "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" + "resolved" "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz" + "version" "5.1.0" + +"commander@^7.2.0": + "integrity" "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + "resolved" "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz" + "version" "7.2.0" + +"commander@^8.3.0": + "integrity" "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==" + "resolved" "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz" + "version" "8.3.0" + +"commondir@^1.0.1": + "integrity" "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + "resolved" "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" + "version" "1.0.1" + +"compressible@~2.0.16": + "integrity" "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==" + "resolved" "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz" + "version" "2.0.18" + dependencies: + "mime-db" ">= 1.43.0 < 2" + +"compression@^1.7.4": + "integrity" "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==" + "resolved" "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz" + "version" "1.7.4" + dependencies: + "accepts" "~1.3.5" + "bytes" "3.0.0" + "compressible" "~2.0.16" + "debug" "2.6.9" + "on-headers" "~1.0.2" + "safe-buffer" "5.1.2" + "vary" "~1.1.2" + +"concat-map@0.0.1": + "integrity" "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "resolved" "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + "version" "0.0.1" + +"configstore@^5.0.1": + "integrity" "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==" + "resolved" "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "dot-prop" "^5.2.0" + "graceful-fs" "^4.1.2" + "make-dir" "^3.0.0" + "unique-string" "^2.0.0" + "write-file-atomic" "^3.0.0" + "xdg-basedir" "^4.0.0" + +"connect-history-api-fallback@^1.6.0": + "integrity" "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==" + "resolved" "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz" + "version" "1.6.0" + +"consola@^2.15.3": + "integrity" "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" + "resolved" "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz" + "version" "2.15.3" + +"content-disposition@0.5.2": + "integrity" "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + "resolved" "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz" + "version" "0.5.2" + +"content-disposition@0.5.4": + "integrity" "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==" + "resolved" "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz" + "version" "0.5.4" + dependencies: + "safe-buffer" "5.2.1" + +"content-type@~1.0.4": + "integrity" "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + "resolved" "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz" + "version" "1.0.4" + +"convert-source-map@^1.7.0": + "integrity" "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==" + "resolved" "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz" + "version" "1.8.0" + dependencies: + "safe-buffer" "~5.1.1" + +"cookie-signature@1.0.6": + "integrity" "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "resolved" "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + "version" "1.0.6" + +"cookie@0.4.2": + "integrity" "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + "resolved" "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz" + "version" "0.4.2" + +"copy-text-to-clipboard@^3.0.1": + "integrity" "sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q==" + "resolved" "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz" + "version" "3.0.1" + +"copy-webpack-plugin@^10.2.0": + "integrity" "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==" + "resolved" "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz" + "version" "10.2.4" + dependencies: + "fast-glob" "^3.2.7" + "glob-parent" "^6.0.1" + "globby" "^12.0.2" + "normalize-path" "^3.0.0" + "schema-utils" "^4.0.0" + "serialize-javascript" "^6.0.0" + +"core-js-compat@^3.20.2", "core-js-compat@^3.21.0": + "integrity" "sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g==" + "resolved" "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.21.1.tgz" + "version" "3.21.1" + dependencies: + "browserslist" "^4.19.1" + "semver" "7.0.0" + +"core-js-pure@^3.20.2": + "integrity" "sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ==" + "resolved" "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.21.1.tgz" + "version" "3.21.1" + +"core-js@^3.18.0": + "integrity" "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==" + "resolved" "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz" + "version" "3.21.1" + +"core-util-is@~1.0.0": + "integrity" "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "resolved" "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" + "version" "1.0.3" + +"cosmiconfig@^6.0.0": + "integrity" "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==" + "resolved" "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz" + "version" "6.0.0" dependencies: "@types/parse-json" "^4.0.0" - import-fresh "^3.1.0" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.7.2" + "import-fresh" "^3.1.0" + "parse-json" "^5.0.0" + "path-type" "^4.0.0" + "yaml" "^1.7.2" -cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" - integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== +"cosmiconfig@^7.0.0", "cosmiconfig@^7.0.1": + "integrity" "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==" + "resolved" "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz" + "version" "7.0.1" dependencies: "@types/parse-json" "^4.0.0" - import-fresh "^3.2.1" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.10.0" - -cross-fetch@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" - integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== - dependencies: - node-fetch "2.6.7" - -cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -crypto-random-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" - integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== - -css-declaration-sorter@^6.0.3: - version "6.1.4" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz#b9bfb4ed9a41f8dcca9bf7184d849ea94a8294b4" - integrity sha512-lpfkqS0fctcmZotJGhnxkIyJWvBXgpyi2wsFd4J8VB7wzyrT6Ch/3Q+FMNJpjK4gu1+GN5khOnpU2ZVKrLbhCw== - dependencies: - timsort "^0.3.0" - -css-loader@^6.5.1: - version "6.6.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.6.0.tgz#c792ad5510bd1712618b49381bd0310574fafbd3" - integrity sha512-FK7H2lisOixPT406s5gZM1S3l8GrfhEBT3ZiL2UX1Ng1XWs0y2GPllz/OTyvbaHe12VgQrIXIzuEGVlbUhodqg== - dependencies: - icss-utils "^5.1.0" - postcss "^8.4.5" - postcss-modules-extract-imports "^3.0.0" - postcss-modules-local-by-default "^4.0.0" - postcss-modules-scope "^3.0.0" - postcss-modules-values "^4.0.0" - postcss-value-parser "^4.2.0" - semver "^7.3.5" - -css-minimizer-webpack-plugin@^3.3.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz#ab78f781ced9181992fe7b6e4f3422e76429878f" - integrity sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q== - dependencies: - cssnano "^5.0.6" - jest-worker "^27.0.2" - postcss "^8.3.5" - schema-utils "^4.0.0" - serialize-javascript "^6.0.0" - source-map "^0.6.1" - -css-select@^4.1.3: - version "4.2.1" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.2.1.tgz#9e665d6ae4c7f9d65dbe69d0316e3221fb274cdd" - integrity sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ== - dependencies: - boolbase "^1.0.0" - css-what "^5.1.0" - domhandler "^4.3.0" - domutils "^2.8.0" - nth-check "^2.0.1" - -css-select@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" - integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= - dependencies: - boolbase "~1.0.0" - css-what "2.1" - domutils "1.5.1" - nth-check "~1.0.1" - -css-tree@^1.1.2, css-tree@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" - integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== - dependencies: - mdn-data "2.0.14" - source-map "^0.6.1" - -css-what@2.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" - integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== - -css-what@^5.0.1, css-what@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" - integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== - -cssesc@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" - integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== - -cssnano-preset-advanced@^5.1.4: - version "5.1.12" - resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-5.1.12.tgz#11f5b0c4e3c32bcfd475465a283fa14dec8df972" - integrity sha512-5WWV9mbqVNwH4nRjs5UbhNl7eKo+16eYNzGogmz0Sa6iqWUeLdN8oo83WuTTqz5vjEKhTbRM5oX6WV1i6ees6g== - dependencies: - autoprefixer "^10.3.7" - cssnano-preset-default "^5.1.12" - postcss-discard-unused "^5.0.3" - postcss-merge-idents "^5.0.3" - postcss-reduce-idents "^5.0.3" - postcss-zindex "^5.0.2" - -cssnano-preset-default@^5.1.12: - version "5.1.12" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.1.12.tgz#64e2ad8e27a279e1413d2d2383ef89a41c909be9" - integrity sha512-rO/JZYyjW1QNkWBxMGV28DW7d98UDLaF759frhli58QFehZ+D/LSmwQ2z/ylBAe2hUlsIWTq6NYGfQPq65EF9w== - dependencies: - css-declaration-sorter "^6.0.3" - cssnano-utils "^3.0.2" - postcss-calc "^8.2.0" - postcss-colormin "^5.2.5" - postcss-convert-values "^5.0.4" - postcss-discard-comments "^5.0.3" - postcss-discard-duplicates "^5.0.3" - postcss-discard-empty "^5.0.3" - postcss-discard-overridden "^5.0.4" - postcss-merge-longhand "^5.0.6" - postcss-merge-rules "^5.0.6" - postcss-minify-font-values "^5.0.4" - postcss-minify-gradients "^5.0.6" - postcss-minify-params "^5.0.5" - postcss-minify-selectors "^5.1.3" - postcss-normalize-charset "^5.0.3" - postcss-normalize-display-values "^5.0.3" - postcss-normalize-positions "^5.0.4" - postcss-normalize-repeat-style "^5.0.4" - postcss-normalize-string "^5.0.4" - postcss-normalize-timing-functions "^5.0.3" - postcss-normalize-unicode "^5.0.4" - postcss-normalize-url "^5.0.5" - postcss-normalize-whitespace "^5.0.4" - postcss-ordered-values "^5.0.5" - postcss-reduce-initial "^5.0.3" - postcss-reduce-transforms "^5.0.4" - postcss-svgo "^5.0.4" - postcss-unique-selectors "^5.0.4" - -cssnano-utils@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.0.2.tgz#d82b4991a27ba6fec644b39bab35fe027137f516" - integrity sha512-KhprijuQv2sP4kT92sSQwhlK3SJTbDIsxcfIEySB0O+3m9esFOai7dP9bMx5enHAh2MwarVIcnwiWoOm01RIbQ== - -cssnano@^5.0.6, cssnano@^5.0.8: - version "5.0.17" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.0.17.tgz#ff45713c05cfc780a1aeb3e663b6f224d091cabf" - integrity sha512-fmjLP7k8kL18xSspeXTzRhaFtRI7DL9b8IcXR80JgtnWBpvAzHT7sCR/6qdn0tnxIaINUN6OEQu83wF57Gs3Xw== - dependencies: - cssnano-preset-default "^5.1.12" - lilconfig "^2.0.3" - yaml "^1.10.2" - -csso@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" - integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== - dependencies: - css-tree "^1.1.2" - -csstype@^3.0.2: - version "3.0.10" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.10.tgz#2ad3a7bed70f35b965707c092e5f30b327c290e5" - integrity sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA== - -debug@2.6.9, debug@^2.6.0: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^3.1.1: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -debug@^4.1.0, debug@^4.1.1: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== - dependencies: - ms "2.1.2" - -decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= - dependencies: - mimic-response "^1.0.0" - -deep-equal@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" - integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== - dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" - object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -deepmerge@^1.3.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-1.5.2.tgz#10499d868844cdad4fee0842df8c7f6f0c95a753" - integrity sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ== - -deepmerge@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" - integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== - -default-gateway@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" - integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== - dependencies: - execa "^5.0.0" - -defer-to-connect@^1.0.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" - integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== - -define-lazy-prop@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" - integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== - -define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -del@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/del/-/del-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952" - integrity sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ== - dependencies: - globby "^11.0.1" - graceful-fs "^4.2.4" - is-glob "^4.0.1" - is-path-cwd "^2.2.0" - is-path-inside "^3.0.2" - p-map "^4.0.0" - rimraf "^3.0.2" - slash "^3.0.0" - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - -detab@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/detab/-/detab-2.0.4.tgz#b927892069aff405fbb9a186fe97a44a92a94b43" - integrity sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g== - dependencies: - repeat-string "^1.5.4" - -detect-node@^2.0.4: - version "2.1.0" - resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" - integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== - -detect-port-alt@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/detect-port-alt/-/detect-port-alt-1.1.6.tgz#24707deabe932d4a3cf621302027c2b266568275" - integrity sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q== - dependencies: - address "^1.0.1" - debug "^2.6.0" - -detect-port@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.3.0.tgz#d9c40e9accadd4df5cac6a782aefd014d573d1f1" - integrity sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ== - dependencies: - address "^1.0.1" - debug "^2.6.0" - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -dns-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" - integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= - -dns-packet@^1.3.1: - version "1.3.4" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f" - integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA== - dependencies: - ip "^1.1.0" - safe-buffer "^5.0.1" - -dns-txt@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" - integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY= - dependencies: - buffer-indexof "^1.0.0" - -dom-converter@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" - integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== - dependencies: - utila "~0.4" - -dom-serializer@0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" - integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== - dependencies: - domelementtype "^2.0.1" - entities "^2.0.0" - -dom-serializer@^1.0.1, dom-serializer@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" - integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== - dependencies: - domelementtype "^2.0.1" - domhandler "^4.2.0" - entities "^2.0.0" - -dom-serializer@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" - integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== - dependencies: - domelementtype "^1.3.0" - entities "^1.1.1" - -domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== - -domelementtype@^2.0.1, domelementtype@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" - integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== - -domhandler@^2.3.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" - integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== - dependencies: - domelementtype "1" - -domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.0.tgz#16c658c626cf966967e306f966b431f77d4a5626" - integrity sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g== - dependencies: - domelementtype "^2.2.0" - -domutils@1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" - integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= - dependencies: - dom-serializer "0" - domelementtype "1" - -domutils@^1.5.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== - dependencies: - dom-serializer "0" - domelementtype "1" - -domutils@^2.5.2, domutils@^2.7.0, domutils@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" - integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== - dependencies: - dom-serializer "^1.0.1" - domelementtype "^2.2.0" - domhandler "^4.2.0" - -dot-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" - integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - -dot-prop@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" - integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== - dependencies: - is-obj "^2.0.0" - -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= - -duplexer@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" - integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -electron-to-chromium@^1.4.17: - version "1.4.71" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.71.tgz#17056914465da0890ce00351a3b946fd4cd51ff6" - integrity sha512-Hk61vXXKRb2cd3znPE9F+2pLWdIOmP7GjiTj45y6L3W/lO+hSnUSUhq+6lEaERWBdZOHbk2s3YV5c9xVl3boVw== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emojis-list@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" - integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== - -emoticon@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/emoticon/-/emoticon-3.2.0.tgz#c008ca7d7620fac742fe1bf4af8ff8fed154ae7f" - integrity sha512-SNujglcLTTg+lDAcApPNgEdudaqQFiAbJCqzjNxJkvN9vAwCGi0uu8IUVvx+f16h+V44KCY6Y2yboroc9pilHg== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -enhanced-resolve@^5.8.3: - version "5.9.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.0.tgz#49ac24953ac8452ed8fed2ef1340fc8e043667ee" - integrity sha512-weDYmzbBygL7HzGGS26M3hGQx68vehdEg6VUmqSOaFzXExFqlnKuSvsEJCVGQHScS8CQMbrAqftT+AzzHNt/YA== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -entities@^1.1.1, entities@~1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" - integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== - -entities@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" - integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== - -entities@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4" - integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-module-lexer@^0.9.0: - version "0.9.3" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" - integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-goat@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" - integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== - -escape-html@^1.0.3, escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-scope@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -eta@^1.12.3: - version "1.12.3" - resolved "https://registry.yarnpkg.com/eta/-/eta-1.12.3.tgz#2982d08adfbef39f9fa50e2fbd42d7337e7338b1" - integrity sha512-qHixwbDLtekO/d51Yr4glcaUJCIjGVJyTzuqV4GPlgZo1YpgOKG+avQynErZIYrfM6JIJdtiG2Kox8tbb+DoGg== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - -eval@^0.1.4: - version "0.1.6" - resolved "https://registry.yarnpkg.com/eval/-/eval-0.1.6.tgz#9620d7d8c85515e97e6b47c5814f46ae381cb3cc" - integrity sha512-o0XUw+5OGkXw4pJZzQoXUk+H87DHuC+7ZE//oSrRGtatTmr12oTnLfg6QOq9DyTt0c/p4TwzgmkKrBzWTSizyQ== - dependencies: - require-like ">= 0.1.1" - -eventemitter3@^4.0.0: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -events@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -execa@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - -express@^4.17.1: - version "4.17.3" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.3.tgz#f6c7302194a4fb54271b73a1fe7a06478c8f85a1" - integrity sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg== - dependencies: - accepts "~1.3.8" - array-flatten "1.1.1" - body-parser "1.19.2" - content-disposition "0.5.4" - content-type "~1.0.4" - cookie "0.4.2" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "~1.1.2" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.7" - qs "6.9.7" - range-parser "~1.2.1" - safe-buffer "5.2.1" - send "0.17.2" - serve-static "1.14.2" - setprototypeof "1.2.0" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-glob@^3.2.7, fast-glob@^3.2.9: - version "3.2.11" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" - integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== + "import-fresh" "^3.2.1" + "parse-json" "^5.0.0" + "path-type" "^4.0.0" + "yaml" "^1.10.0" + +"cross-fetch@^3.1.5": + "integrity" "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==" + "resolved" "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz" + "version" "3.1.5" + dependencies: + "node-fetch" "2.6.7" + +"cross-spawn@^7.0.3": + "integrity" "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==" + "resolved" "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" + "version" "7.0.3" + dependencies: + "path-key" "^3.1.0" + "shebang-command" "^2.0.0" + "which" "^2.0.1" + +"crypto-random-string@^2.0.0": + "integrity" "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" + "resolved" "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz" + "version" "2.0.0" + +"css-declaration-sorter@^6.0.3": + "integrity" "sha512-lpfkqS0fctcmZotJGhnxkIyJWvBXgpyi2wsFd4J8VB7wzyrT6Ch/3Q+FMNJpjK4gu1+GN5khOnpU2ZVKrLbhCw==" + "resolved" "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz" + "version" "6.1.4" + dependencies: + "timsort" "^0.3.0" + +"css-loader@^6.5.1": + "integrity" "sha512-FK7H2lisOixPT406s5gZM1S3l8GrfhEBT3ZiL2UX1Ng1XWs0y2GPllz/OTyvbaHe12VgQrIXIzuEGVlbUhodqg==" + "resolved" "https://registry.npmjs.org/css-loader/-/css-loader-6.6.0.tgz" + "version" "6.6.0" + dependencies: + "icss-utils" "^5.1.0" + "postcss" "^8.4.5" + "postcss-modules-extract-imports" "^3.0.0" + "postcss-modules-local-by-default" "^4.0.0" + "postcss-modules-scope" "^3.0.0" + "postcss-modules-values" "^4.0.0" + "postcss-value-parser" "^4.2.0" + "semver" "^7.3.5" + +"css-minimizer-webpack-plugin@^3.3.1": + "integrity" "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==" + "resolved" "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz" + "version" "3.4.1" + dependencies: + "cssnano" "^5.0.6" + "jest-worker" "^27.0.2" + "postcss" "^8.3.5" + "schema-utils" "^4.0.0" + "serialize-javascript" "^6.0.0" + "source-map" "^0.6.1" + +"css-select@^4.1.3": + "integrity" "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==" + "resolved" "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz" + "version" "4.2.1" + dependencies: + "boolbase" "^1.0.0" + "css-what" "^5.1.0" + "domhandler" "^4.3.0" + "domutils" "^2.8.0" + "nth-check" "^2.0.1" + +"css-select@~1.2.0": + "integrity" "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=" + "resolved" "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "boolbase" "~1.0.0" + "css-what" "2.1" + "domutils" "1.5.1" + "nth-check" "~1.0.1" + +"css-tree@^1.1.2", "css-tree@^1.1.3": + "integrity" "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==" + "resolved" "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz" + "version" "1.1.3" + dependencies: + "mdn-data" "2.0.14" + "source-map" "^0.6.1" + +"css-what@^5.0.1", "css-what@^5.1.0": + "integrity" "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==" + "resolved" "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz" + "version" "5.1.0" + +"css-what@2.1": + "integrity" "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" + "resolved" "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz" + "version" "2.1.3" + +"cssesc@^3.0.0": + "integrity" "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" + "resolved" "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz" + "version" "3.0.0" + +"cssnano-preset-advanced@^5.1.4": + "integrity" "sha512-5WWV9mbqVNwH4nRjs5UbhNl7eKo+16eYNzGogmz0Sa6iqWUeLdN8oo83WuTTqz5vjEKhTbRM5oX6WV1i6ees6g==" + "resolved" "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-5.1.12.tgz" + "version" "5.1.12" + dependencies: + "autoprefixer" "^10.3.7" + "cssnano-preset-default" "^5.1.12" + "postcss-discard-unused" "^5.0.3" + "postcss-merge-idents" "^5.0.3" + "postcss-reduce-idents" "^5.0.3" + "postcss-zindex" "^5.0.2" + +"cssnano-preset-default@^5.1.12": + "integrity" "sha512-rO/JZYyjW1QNkWBxMGV28DW7d98UDLaF759frhli58QFehZ+D/LSmwQ2z/ylBAe2hUlsIWTq6NYGfQPq65EF9w==" + "resolved" "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.1.12.tgz" + "version" "5.1.12" + dependencies: + "css-declaration-sorter" "^6.0.3" + "cssnano-utils" "^3.0.2" + "postcss-calc" "^8.2.0" + "postcss-colormin" "^5.2.5" + "postcss-convert-values" "^5.0.4" + "postcss-discard-comments" "^5.0.3" + "postcss-discard-duplicates" "^5.0.3" + "postcss-discard-empty" "^5.0.3" + "postcss-discard-overridden" "^5.0.4" + "postcss-merge-longhand" "^5.0.6" + "postcss-merge-rules" "^5.0.6" + "postcss-minify-font-values" "^5.0.4" + "postcss-minify-gradients" "^5.0.6" + "postcss-minify-params" "^5.0.5" + "postcss-minify-selectors" "^5.1.3" + "postcss-normalize-charset" "^5.0.3" + "postcss-normalize-display-values" "^5.0.3" + "postcss-normalize-positions" "^5.0.4" + "postcss-normalize-repeat-style" "^5.0.4" + "postcss-normalize-string" "^5.0.4" + "postcss-normalize-timing-functions" "^5.0.3" + "postcss-normalize-unicode" "^5.0.4" + "postcss-normalize-url" "^5.0.5" + "postcss-normalize-whitespace" "^5.0.4" + "postcss-ordered-values" "^5.0.5" + "postcss-reduce-initial" "^5.0.3" + "postcss-reduce-transforms" "^5.0.4" + "postcss-svgo" "^5.0.4" + "postcss-unique-selectors" "^5.0.4" + +"cssnano-utils@^3.0.2": + "integrity" "sha512-KhprijuQv2sP4kT92sSQwhlK3SJTbDIsxcfIEySB0O+3m9esFOai7dP9bMx5enHAh2MwarVIcnwiWoOm01RIbQ==" + "resolved" "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.0.2.tgz" + "version" "3.0.2" + +"cssnano@^5.0.6", "cssnano@^5.0.8": + "integrity" "sha512-fmjLP7k8kL18xSspeXTzRhaFtRI7DL9b8IcXR80JgtnWBpvAzHT7sCR/6qdn0tnxIaINUN6OEQu83wF57Gs3Xw==" + "resolved" "https://registry.npmjs.org/cssnano/-/cssnano-5.0.17.tgz" + "version" "5.0.17" + dependencies: + "cssnano-preset-default" "^5.1.12" + "lilconfig" "^2.0.3" + "yaml" "^1.10.2" + +"csso@^4.2.0": + "integrity" "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==" + "resolved" "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz" + "version" "4.2.0" + dependencies: + "css-tree" "^1.1.2" + +"csstype@^3.0.2": + "integrity" "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==" + "resolved" "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz" + "version" "3.0.10" + +"debug@^2.6.0", "debug@2.6.9": + "integrity" "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" + "resolved" "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + "version" "2.6.9" + dependencies: + "ms" "2.0.0" + +"debug@^3.1.1": + "integrity" "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==" + "resolved" "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" + "version" "3.2.7" + dependencies: + "ms" "^2.1.1" + +"debug@^4.1.0": + "integrity" "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==" + "resolved" "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz" + "version" "4.3.3" + dependencies: + "ms" "2.1.2" + +"debug@^4.1.1": + "integrity" "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==" + "resolved" "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz" + "version" "4.3.3" + dependencies: + "ms" "2.1.2" + +"decompress-response@^3.3.0": + "integrity" "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=" + "resolved" "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz" + "version" "3.3.0" + dependencies: + "mimic-response" "^1.0.0" + +"deep-equal@^1.0.1": + "integrity" "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==" + "resolved" "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "is-arguments" "^1.0.4" + "is-date-object" "^1.0.1" + "is-regex" "^1.0.4" + "object-is" "^1.0.1" + "object-keys" "^1.1.1" + "regexp.prototype.flags" "^1.2.0" + +"deep-extend@^0.6.0": + "integrity" "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + "resolved" "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz" + "version" "0.6.0" + +"deepmerge@^1.3.2": + "integrity" "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==" + "resolved" "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz" + "version" "1.5.2" + +"deepmerge@^4.2.2": + "integrity" "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" + "resolved" "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz" + "version" "4.2.2" + +"default-gateway@^6.0.3": + "integrity" "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==" + "resolved" "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz" + "version" "6.0.3" + dependencies: + "execa" "^5.0.0" + +"defer-to-connect@^1.0.1": + "integrity" "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + "resolved" "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz" + "version" "1.1.3" + +"define-lazy-prop@^2.0.0": + "integrity" "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" + "resolved" "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz" + "version" "2.0.0" + +"define-properties@^1.1.3": + "integrity" "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==" + "resolved" "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz" + "version" "1.1.3" + dependencies: + "object-keys" "^1.0.12" + +"del@^6.0.0": + "integrity" "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==" + "resolved" "https://registry.npmjs.org/del/-/del-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "globby" "^11.0.1" + "graceful-fs" "^4.2.4" + "is-glob" "^4.0.1" + "is-path-cwd" "^2.2.0" + "is-path-inside" "^3.0.2" + "p-map" "^4.0.0" + "rimraf" "^3.0.2" + "slash" "^3.0.0" + +"depd@~1.1.2": + "integrity" "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "resolved" "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" + "version" "1.1.2" + +"destroy@~1.0.4": + "integrity" "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "resolved" "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" + "version" "1.0.4" + +"detab@2.0.4": + "integrity" "sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g==" + "resolved" "https://registry.npmjs.org/detab/-/detab-2.0.4.tgz" + "version" "2.0.4" + dependencies: + "repeat-string" "^1.5.4" + +"detect-node@^2.0.4": + "integrity" "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + "resolved" "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz" + "version" "2.1.0" + +"detect-port-alt@^1.1.6": + "integrity" "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==" + "resolved" "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz" + "version" "1.1.6" + dependencies: + "address" "^1.0.1" + "debug" "^2.6.0" + +"detect-port@^1.3.0": + "integrity" "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==" + "resolved" "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz" + "version" "1.3.0" + dependencies: + "address" "^1.0.1" + "debug" "^2.6.0" + +"dir-glob@^3.0.1": + "integrity" "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==" + "resolved" "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "path-type" "^4.0.0" + +"dns-equal@^1.0.0": + "integrity" "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" + "resolved" "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz" + "version" "1.0.0" + +"dns-packet@^1.3.1": + "integrity" "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==" + "resolved" "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz" + "version" "1.3.4" + dependencies: + "ip" "^1.1.0" + "safe-buffer" "^5.0.1" + +"dns-txt@^2.0.2": + "integrity" "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=" + "resolved" "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "buffer-indexof" "^1.0.0" + +"dom-converter@^0.2.0": + "integrity" "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==" + "resolved" "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz" + "version" "0.2.0" + dependencies: + "utila" "~0.4" + +"dom-serializer@^1.0.1": + "integrity" "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==" + "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz" + "version" "1.3.2" + dependencies: + "domelementtype" "^2.0.1" + "domhandler" "^4.2.0" + "entities" "^2.0.0" + +"dom-serializer@^1.3.2": + "integrity" "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==" + "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz" + "version" "1.3.2" + dependencies: + "domelementtype" "^2.0.1" + "domhandler" "^4.2.0" + "entities" "^2.0.0" + +"dom-serializer@~0.1.0": + "integrity" "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==" + "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz" + "version" "0.1.1" + dependencies: + "domelementtype" "^1.3.0" + "entities" "^1.1.1" + +"dom-serializer@0": + "integrity" "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==" + "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz" + "version" "0.2.2" + dependencies: + "domelementtype" "^2.0.1" + "entities" "^2.0.0" + +"domelementtype@^1.3.0", "domelementtype@^1.3.1", "domelementtype@1": + "integrity" "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + "resolved" "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz" + "version" "1.3.1" + +"domelementtype@^2.0.1", "domelementtype@^2.2.0": + "integrity" "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" + "resolved" "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz" + "version" "2.2.0" + +"domhandler@^2.3.0": + "integrity" "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==" + "resolved" "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "domelementtype" "1" + +"domhandler@^4.0.0", "domhandler@^4.2.0", "domhandler@^4.3.0": + "integrity" "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==" + "resolved" "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz" + "version" "4.3.0" + dependencies: + "domelementtype" "^2.2.0" + +"domutils@^1.5.1": + "integrity" "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==" + "resolved" "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz" + "version" "1.7.0" + dependencies: + "dom-serializer" "0" + "domelementtype" "1" + +"domutils@^2.5.2", "domutils@^2.7.0", "domutils@^2.8.0": + "integrity" "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==" + "resolved" "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz" + "version" "2.8.0" + dependencies: + "dom-serializer" "^1.0.1" + "domelementtype" "^2.2.0" + "domhandler" "^4.2.0" + +"domutils@1.5.1": + "integrity" "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=" + "resolved" "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz" + "version" "1.5.1" + dependencies: + "dom-serializer" "0" + "domelementtype" "1" + +"dot-case@^3.0.4": + "integrity" "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==" + "resolved" "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "no-case" "^3.0.4" + "tslib" "^2.0.3" + +"dot-prop@^5.2.0": + "integrity" "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==" + "resolved" "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz" + "version" "5.3.0" + dependencies: + "is-obj" "^2.0.0" + +"duplexer@^0.1.2": + "integrity" "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + "resolved" "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz" + "version" "0.1.2" + +"duplexer3@^0.1.4": + "integrity" "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + "resolved" "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz" + "version" "0.1.4" + +"ee-first@1.1.1": + "integrity" "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "resolved" "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + "version" "1.1.1" + +"electron-to-chromium@^1.4.284": + "integrity" "sha512-DE9tTy2PNmy1v55AZAO542ui+MLC2cvINMK4P2LXGsJdput/ThVG9t+QGecPuAZZSgC8XoI+Jh9M1OG9IoNSCw==" + "resolved" "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.328.tgz" + "version" "1.4.328" + +"emoji-regex@^8.0.0": + "integrity" "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "resolved" "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + "version" "8.0.0" + +"emojis-list@^3.0.0": + "integrity" "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" + "resolved" "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz" + "version" "3.0.0" + +"emoticon@^3.2.0": + "integrity" "sha512-SNujglcLTTg+lDAcApPNgEdudaqQFiAbJCqzjNxJkvN9vAwCGi0uu8IUVvx+f16h+V44KCY6Y2yboroc9pilHg==" + "resolved" "https://registry.npmjs.org/emoticon/-/emoticon-3.2.0.tgz" + "version" "3.2.0" + +"encodeurl@~1.0.2": + "integrity" "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "resolved" "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" + "version" "1.0.2" + +"end-of-stream@^1.1.0": + "integrity" "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==" + "resolved" "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" + "version" "1.4.4" + dependencies: + "once" "^1.4.0" + +"enhanced-resolve@^5.8.3": + "integrity" "sha512-weDYmzbBygL7HzGGS26M3hGQx68vehdEg6VUmqSOaFzXExFqlnKuSvsEJCVGQHScS8CQMbrAqftT+AzzHNt/YA==" + "resolved" "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.0.tgz" + "version" "5.9.0" + dependencies: + "graceful-fs" "^4.2.4" + "tapable" "^2.2.0" + +"entities@^1.1.1", "entities@~1.1.1": + "integrity" "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + "resolved" "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz" + "version" "1.1.2" + +"entities@^2.0.0": + "integrity" "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + "resolved" "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz" + "version" "2.2.0" + +"entities@^3.0.1": + "integrity" "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==" + "resolved" "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz" + "version" "3.0.1" + +"error-ex@^1.3.1": + "integrity" "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==" + "resolved" "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" + "version" "1.3.2" + dependencies: + "is-arrayish" "^0.2.1" + +"es-module-lexer@^0.9.0": + "integrity" "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==" + "resolved" "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz" + "version" "0.9.3" + +"escalade@^3.1.1": + "integrity" "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + "resolved" "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" + "version" "3.1.1" + +"escape-goat@^2.0.0": + "integrity" "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==" + "resolved" "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz" + "version" "2.1.1" + +"escape-html@^1.0.3", "escape-html@~1.0.3": + "integrity" "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "resolved" "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + "version" "1.0.3" + +"escape-string-regexp@^1.0.5": + "integrity" "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + "version" "1.0.5" + +"escape-string-regexp@^4.0.0": + "integrity" "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + "version" "4.0.0" + +"eslint-scope@5.1.1": + "integrity" "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==" + "resolved" "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" + "version" "5.1.1" + dependencies: + "esrecurse" "^4.3.0" + "estraverse" "^4.1.1" + +"esprima@^4.0.0": + "integrity" "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "resolved" "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" + "version" "4.0.1" + +"esrecurse@^4.3.0": + "integrity" "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==" + "resolved" "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" + "version" "4.3.0" + dependencies: + "estraverse" "^5.2.0" + +"estraverse@^4.1.1": + "integrity" "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" + "version" "4.3.0" + +"estraverse@^5.2.0": + "integrity" "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" + "version" "5.3.0" + +"esutils@^2.0.2": + "integrity" "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + "resolved" "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" + "version" "2.0.3" + +"eta@^1.12.3": + "integrity" "sha512-qHixwbDLtekO/d51Yr4glcaUJCIjGVJyTzuqV4GPlgZo1YpgOKG+avQynErZIYrfM6JIJdtiG2Kox8tbb+DoGg==" + "resolved" "https://registry.npmjs.org/eta/-/eta-1.12.3.tgz" + "version" "1.12.3" + +"etag@~1.8.1": + "integrity" "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "resolved" "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" + "version" "1.8.1" + +"eval@^0.1.4": + "integrity" "sha512-o0XUw+5OGkXw4pJZzQoXUk+H87DHuC+7ZE//oSrRGtatTmr12oTnLfg6QOq9DyTt0c/p4TwzgmkKrBzWTSizyQ==" + "resolved" "https://registry.npmjs.org/eval/-/eval-0.1.6.tgz" + "version" "0.1.6" + dependencies: + "require-like" ">= 0.1.1" + +"eventemitter3@^4.0.0": + "integrity" "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + "resolved" "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz" + "version" "4.0.7" + +"events@^3.2.0": + "integrity" "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + "resolved" "https://registry.npmjs.org/events/-/events-3.3.0.tgz" + "version" "3.3.0" + +"execa@^5.0.0": + "integrity" "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==" + "resolved" "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" + "version" "5.1.1" + dependencies: + "cross-spawn" "^7.0.3" + "get-stream" "^6.0.0" + "human-signals" "^2.1.0" + "is-stream" "^2.0.0" + "merge-stream" "^2.0.0" + "npm-run-path" "^4.0.1" + "onetime" "^5.1.2" + "signal-exit" "^3.0.3" + "strip-final-newline" "^2.0.0" + +"express@^4.17.1": + "integrity" "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==" + "resolved" "https://registry.npmjs.org/express/-/express-4.17.3.tgz" + "version" "4.17.3" + dependencies: + "accepts" "~1.3.8" + "array-flatten" "1.1.1" + "body-parser" "1.19.2" + "content-disposition" "0.5.4" + "content-type" "~1.0.4" + "cookie" "0.4.2" + "cookie-signature" "1.0.6" + "debug" "2.6.9" + "depd" "~1.1.2" + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "etag" "~1.8.1" + "finalhandler" "~1.1.2" + "fresh" "0.5.2" + "merge-descriptors" "1.0.1" + "methods" "~1.1.2" + "on-finished" "~2.3.0" + "parseurl" "~1.3.3" + "path-to-regexp" "0.1.7" + "proxy-addr" "~2.0.7" + "qs" "6.9.7" + "range-parser" "~1.2.1" + "safe-buffer" "5.2.1" + "send" "0.17.2" + "serve-static" "1.14.2" + "setprototypeof" "1.2.0" + "statuses" "~1.5.0" + "type-is" "~1.6.18" + "utils-merge" "1.0.1" + "vary" "~1.1.2" + +"extend-shallow@^2.0.1": + "integrity" "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=" + "resolved" "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "is-extendable" "^0.1.0" + +"extend@^3.0.0": + "integrity" "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "resolved" "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz" + "version" "3.0.2" + +"fast-deep-equal@^3.1.1", "fast-deep-equal@^3.1.3": + "integrity" "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "resolved" "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" + "version" "3.1.3" + +"fast-glob@^3.2.7", "fast-glob@^3.2.9": + "integrity" "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==" + "resolved" "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz" + "version" "3.2.11" dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-url-parser@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" - integrity sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0= - dependencies: - punycode "^1.3.2" - -fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== - dependencies: - reusify "^1.0.4" - -faye-websocket@^0.11.3: - version "0.11.4" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" - integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== - dependencies: - websocket-driver ">=0.5.1" - -fbemitter@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/fbemitter/-/fbemitter-3.0.0.tgz#00b2a1af5411254aab416cd75f9e6289bee4bff3" - integrity sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw== - dependencies: - fbjs "^3.0.0" - -fbjs-css-vars@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8" - integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== - -fbjs@^3.0.0, fbjs@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.4.tgz#e1871c6bd3083bac71ff2da868ad5067d37716c6" - integrity sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ== - dependencies: - cross-fetch "^3.1.5" - fbjs-css-vars "^1.0.0" - loose-envify "^1.0.0" - object-assign "^4.1.0" - promise "^7.1.1" - setimmediate "^1.0.5" - ua-parser-js "^0.7.30" - -feed@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/feed/-/feed-4.2.2.tgz#865783ef6ed12579e2c44bbef3c9113bc4956a7e" - integrity sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ== - dependencies: - xml-js "^1.6.11" - -file-loader@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" - integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== - dependencies: - loader-utils "^2.0.0" - schema-utils "^3.0.0" - -filesize@^8.0.6: - version "8.0.7" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-8.0.7.tgz#695e70d80f4e47012c132d57a059e80c6b580bd8" - integrity sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ== - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - -find-cache-dir@^3.3.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" - integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== - dependencies: - commondir "^1.0.1" - make-dir "^3.0.2" - pkg-dir "^4.1.0" - -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -find-up@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flux@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/flux/-/flux-4.0.3.tgz#573b504a24982c4768fdfb59d8d2ea5637d72ee7" - integrity sha512-yKAbrp7JhZhj6uiT1FTuVMlIAT1J4jqEyBpFApi1kxpGZCvacMVc/t1pMQyotqHhAgvoE3bNvAykhCo2CLjnYw== - dependencies: - fbemitter "^3.0.0" - fbjs "^3.0.1" - -follow-redirects@^1.0.0, follow-redirects@^1.14.7: - version "1.14.9" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" - integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== - -fork-ts-checker-webpack-plugin@^6.5.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz#0282b335fa495a97e167f69018f566ea7d2a2b5e" - integrity sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw== + "glob-parent" "^5.1.2" + "merge2" "^1.3.0" + "micromatch" "^4.0.4" + +"fast-json-stable-stringify@^2.0.0": + "integrity" "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "resolved" "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" + "version" "2.1.0" + +"fast-url-parser@1.1.3": + "integrity" "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=" + "resolved" "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz" + "version" "1.1.3" + dependencies: + "punycode" "^1.3.2" + +"fastq@^1.6.0": + "integrity" "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==" + "resolved" "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz" + "version" "1.13.0" + dependencies: + "reusify" "^1.0.4" + +"faye-websocket@^0.11.3": + "integrity" "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==" + "resolved" "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz" + "version" "0.11.4" + dependencies: + "websocket-driver" ">=0.5.1" + +"fbemitter@^3.0.0": + "integrity" "sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==" + "resolved" "https://registry.npmjs.org/fbemitter/-/fbemitter-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "fbjs" "^3.0.0" + +"fbjs-css-vars@^1.0.0": + "integrity" "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" + "resolved" "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz" + "version" "1.0.2" + +"fbjs@^3.0.0", "fbjs@^3.0.1": + "integrity" "sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ==" + "resolved" "https://registry.npmjs.org/fbjs/-/fbjs-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "cross-fetch" "^3.1.5" + "fbjs-css-vars" "^1.0.0" + "loose-envify" "^1.0.0" + "object-assign" "^4.1.0" + "promise" "^7.1.1" + "setimmediate" "^1.0.5" + "ua-parser-js" "^0.7.30" + +"feed@^4.2.2": + "integrity" "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==" + "resolved" "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz" + "version" "4.2.2" + dependencies: + "xml-js" "^1.6.11" + +"file-loader@*", "file-loader@^6.2.0": + "integrity" "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==" + "resolved" "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz" + "version" "6.2.0" + dependencies: + "loader-utils" "^2.0.0" + "schema-utils" "^3.0.0" + +"filesize@^8.0.6": + "integrity" "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==" + "resolved" "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz" + "version" "8.0.7" + +"fill-range@^7.0.1": + "integrity" "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==" + "resolved" "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" + "version" "7.0.1" + dependencies: + "to-regex-range" "^5.0.1" + +"finalhandler@~1.1.2": + "integrity" "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==" + "resolved" "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz" + "version" "1.1.2" + dependencies: + "debug" "2.6.9" + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "on-finished" "~2.3.0" + "parseurl" "~1.3.3" + "statuses" "~1.5.0" + "unpipe" "~1.0.0" + +"find-cache-dir@^3.3.1": + "integrity" "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==" + "resolved" "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz" + "version" "3.3.2" + dependencies: + "commondir" "^1.0.1" + "make-dir" "^3.0.2" + "pkg-dir" "^4.1.0" + +"find-up@^3.0.0": + "integrity" "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==" + "resolved" "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "locate-path" "^3.0.0" + +"find-up@^4.0.0": + "integrity" "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==" + "resolved" "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "locate-path" "^5.0.0" + "path-exists" "^4.0.0" + +"find-up@^5.0.0": + "integrity" "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==" + "resolved" "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "locate-path" "^6.0.0" + "path-exists" "^4.0.0" + +"flux@^4.0.1": + "integrity" "sha512-yKAbrp7JhZhj6uiT1FTuVMlIAT1J4jqEyBpFApi1kxpGZCvacMVc/t1pMQyotqHhAgvoE3bNvAykhCo2CLjnYw==" + "resolved" "https://registry.npmjs.org/flux/-/flux-4.0.3.tgz" + "version" "4.0.3" + dependencies: + "fbemitter" "^3.0.0" + "fbjs" "^3.0.1" + +"follow-redirects@^1.0.0", "follow-redirects@^1.14.7": + "integrity" "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" + "resolved" "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz" + "version" "1.14.9" + +"fork-ts-checker-webpack-plugin@^6.5.0": + "integrity" "sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw==" + "resolved" "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz" + "version" "6.5.0" dependencies: "@babel/code-frame" "^7.8.3" "@types/json-schema" "^7.0.5" - chalk "^4.1.0" - chokidar "^3.4.2" - cosmiconfig "^6.0.0" - deepmerge "^4.2.2" - fs-extra "^9.0.0" - glob "^7.1.6" - memfs "^3.1.2" - minimatch "^3.0.4" - schema-utils "2.7.0" - semver "^7.3.2" - tapable "^1.0.0" - -forwarded@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" - integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== - -fraction.js@^4.1.2: - version "4.1.3" - resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.3.tgz#be65b0f20762ef27e1e793860bc2dfb716e99e65" - integrity sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg== - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - -fs-extra@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1" - integrity sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-extra@^9.0.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" - integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== - dependencies: - at-least-node "^1.0.0" - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-monkey@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" - integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-intrinsic@^1.0.2: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - -get-own-enumerable-property-symbols@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" - integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== - -get-stream@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -github-slugger@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.4.0.tgz#206eb96cdb22ee56fdc53a28d5a302338463444e" - integrity sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ== - -glob-parent@^5.1.2, glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob-to-regexp@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" - integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== - -glob@^7.0.0, glob@^7.1.3, glob@^7.1.6: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -global-dirs@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686" - integrity sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA== - dependencies: - ini "2.0.0" - -global-modules@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" - integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== - dependencies: - global-prefix "^3.0.0" - -global-prefix@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" - integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== - dependencies: - ini "^1.3.5" - kind-of "^6.0.2" - which "^1.3.1" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globby@^11.0.1, globby@^11.0.2, globby@^11.0.4: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -globby@^12.0.2: - version "12.2.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-12.2.0.tgz#2ab8046b4fba4ff6eede835b29f678f90e3d3c22" - integrity sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA== - dependencies: - array-union "^3.0.1" - dir-glob "^3.0.1" - fast-glob "^3.2.7" - ignore "^5.1.9" - merge2 "^1.4.1" - slash "^4.0.0" - -got@^9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + "chalk" "^4.1.0" + "chokidar" "^3.4.2" + "cosmiconfig" "^6.0.0" + "deepmerge" "^4.2.2" + "fs-extra" "^9.0.0" + "glob" "^7.1.6" + "memfs" "^3.1.2" + "minimatch" "^3.0.4" + "schema-utils" "2.7.0" + "semver" "^7.3.2" + "tapable" "^1.0.0" + +"forwarded@0.2.0": + "integrity" "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + "resolved" "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" + "version" "0.2.0" + +"fraction.js@^4.1.2": + "integrity" "sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg==" + "resolved" "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.3.tgz" + "version" "4.1.3" + +"fresh@0.5.2": + "integrity" "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "resolved" "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" + "version" "0.5.2" + +"fs-extra@^10.0.0": + "integrity" "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==" + "resolved" "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz" + "version" "10.0.0" + dependencies: + "graceful-fs" "^4.2.0" + "jsonfile" "^6.0.1" + "universalify" "^2.0.0" + +"fs-extra@^9.0.0": + "integrity" "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==" + "resolved" "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz" + "version" "9.1.0" + dependencies: + "at-least-node" "^1.0.0" + "graceful-fs" "^4.2.0" + "jsonfile" "^6.0.1" + "universalify" "^2.0.0" + +"fs-monkey@1.0.3": + "integrity" "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==" + "resolved" "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz" + "version" "1.0.3" + +"fs.realpath@^1.0.0": + "integrity" "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "resolved" "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + "version" "1.0.0" + +"function-bind@^1.1.1": + "integrity" "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "resolved" "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" + "version" "1.1.1" + +"gensync@^1.0.0-beta.1", "gensync@^1.0.0-beta.2": + "integrity" "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + "resolved" "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" + "version" "1.0.0-beta.2" + +"get-intrinsic@^1.0.2": + "integrity" "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==" + "resolved" "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "function-bind" "^1.1.1" + "has" "^1.0.3" + "has-symbols" "^1.0.1" + +"get-own-enumerable-property-symbols@^3.0.0": + "integrity" "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + "resolved" "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz" + "version" "3.0.2" + +"get-stream@^4.1.0": + "integrity" "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==" + "resolved" "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "pump" "^3.0.0" + +"get-stream@^5.1.0": + "integrity" "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==" + "resolved" "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz" + "version" "5.2.0" + dependencies: + "pump" "^3.0.0" + +"get-stream@^6.0.0": + "integrity" "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + "resolved" "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz" + "version" "6.0.1" + +"github-slugger@^1.4.0": + "integrity" "sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ==" + "resolved" "https://registry.npmjs.org/github-slugger/-/github-slugger-1.4.0.tgz" + "version" "1.4.0" + +"glob-parent@^5.1.2", "glob-parent@~5.1.2": + "integrity" "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==" + "resolved" "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + "version" "5.1.2" + dependencies: + "is-glob" "^4.0.1" + +"glob-parent@^6.0.1": + "integrity" "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==" + "resolved" "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" + "version" "6.0.2" + dependencies: + "is-glob" "^4.0.3" + +"glob-to-regexp@^0.4.1": + "integrity" "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + "resolved" "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz" + "version" "0.4.1" + +"glob@^7.0.0", "glob@^7.1.3", "glob@^7.1.6": + "integrity" "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==" + "resolved" "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz" + "version" "7.2.0" + dependencies: + "fs.realpath" "^1.0.0" + "inflight" "^1.0.4" + "inherits" "2" + "minimatch" "^3.0.4" + "once" "^1.3.0" + "path-is-absolute" "^1.0.0" + +"global-dirs@^3.0.0": + "integrity" "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==" + "resolved" "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "ini" "2.0.0" + +"global-modules@^2.0.0": + "integrity" "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==" + "resolved" "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "global-prefix" "^3.0.0" + +"global-prefix@^3.0.0": + "integrity" "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==" + "resolved" "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "ini" "^1.3.5" + "kind-of" "^6.0.2" + "which" "^1.3.1" + +"globals@^11.1.0": + "integrity" "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + "resolved" "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" + "version" "11.12.0" + +"globby@^11.0.1", "globby@^11.0.2", "globby@^11.0.4": + "integrity" "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==" + "resolved" "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" + "version" "11.1.0" + dependencies: + "array-union" "^2.1.0" + "dir-glob" "^3.0.1" + "fast-glob" "^3.2.9" + "ignore" "^5.2.0" + "merge2" "^1.4.1" + "slash" "^3.0.0" + +"globby@^12.0.2": + "integrity" "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==" + "resolved" "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz" + "version" "12.2.0" + dependencies: + "array-union" "^3.0.1" + "dir-glob" "^3.0.1" + "fast-glob" "^3.2.7" + "ignore" "^5.1.9" + "merge2" "^1.4.1" + "slash" "^4.0.0" + +"got@^9.6.0": + "integrity" "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==" + "resolved" "https://registry.npmjs.org/got/-/got-9.6.0.tgz" + "version" "9.6.0" dependencies: "@sindresorhus/is" "^0.14.0" "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" - -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: - version "4.2.9" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== - -gray-matter@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.3.tgz#e893c064825de73ea1f5f7d88c7a9f7274288798" - integrity sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q== - dependencies: - js-yaml "^3.13.1" - kind-of "^6.0.2" - section-matter "^1.0.0" - strip-bom-string "^1.0.0" - -gzip-size@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" - integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== - dependencies: - duplexer "^0.1.2" - -handle-thing@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" - integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-symbols@^1.0.1, has-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" - integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - -has-yarn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" - integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hast-to-hyperscript@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz#9b67fd188e4c81e8ad66f803855334173920218d" - integrity sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA== + "cacheable-request" "^6.0.0" + "decompress-response" "^3.3.0" + "duplexer3" "^0.1.4" + "get-stream" "^4.1.0" + "lowercase-keys" "^1.0.1" + "mimic-response" "^1.0.1" + "p-cancelable" "^1.0.0" + "to-readable-stream" "^1.0.0" + "url-parse-lax" "^3.0.0" + +"graceful-fs@^4.1.2", "graceful-fs@^4.1.6", "graceful-fs@^4.2.0", "graceful-fs@^4.2.4", "graceful-fs@^4.2.6", "graceful-fs@^4.2.9": + "integrity" "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" + "resolved" "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz" + "version" "4.2.9" + +"gray-matter@^4.0.3": + "integrity" "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==" + "resolved" "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz" + "version" "4.0.3" + dependencies: + "js-yaml" "^3.13.1" + "kind-of" "^6.0.2" + "section-matter" "^1.0.0" + "strip-bom-string" "^1.0.0" + +"gzip-size@^6.0.0": + "integrity" "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==" + "resolved" "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "duplexer" "^0.1.2" + +"handle-thing@^2.0.0": + "integrity" "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" + "resolved" "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz" + "version" "2.0.1" + +"has-flag@^3.0.0": + "integrity" "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" + "version" "3.0.0" + +"has-flag@^4.0.0": + "integrity" "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + "version" "4.0.0" + +"has-symbols@^1.0.1", "has-symbols@^1.0.2": + "integrity" "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + "resolved" "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz" + "version" "1.0.2" + +"has-tostringtag@^1.0.0": + "integrity" "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==" + "resolved" "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "has-symbols" "^1.0.2" + +"has-yarn@^2.1.0": + "integrity" "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==" + "resolved" "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz" + "version" "2.1.0" + +"has@^1.0.3": + "integrity" "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==" + "resolved" "https://registry.npmjs.org/has/-/has-1.0.3.tgz" + "version" "1.0.3" + dependencies: + "function-bind" "^1.1.1" + +"hast-to-hyperscript@^9.0.0": + "integrity" "sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA==" + "resolved" "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz" + "version" "9.0.1" dependencies: "@types/unist" "^2.0.3" - comma-separated-tokens "^1.0.0" - property-information "^5.3.0" - space-separated-tokens "^1.0.0" - style-to-object "^0.3.0" - unist-util-is "^4.0.0" - web-namespaces "^1.0.0" - -hast-util-from-parse5@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-5.0.3.tgz#3089dc0ee2ccf6ec8bc416919b51a54a589e097c" - integrity sha512-gOc8UB99F6eWVWFtM9jUikjN7QkWxB3nY0df5Z0Zq1/Nkwl5V4hAAsl0tmwlgWl/1shlTF8DnNYLO8X6wRV9pA== - dependencies: - ccount "^1.0.3" - hastscript "^5.0.0" - property-information "^5.0.0" - web-namespaces "^1.1.2" - xtend "^4.0.1" - -hast-util-from-parse5@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz#554e34abdeea25ac76f5bd950a1f0180e0b3bc2a" - integrity sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA== + "comma-separated-tokens" "^1.0.0" + "property-information" "^5.3.0" + "space-separated-tokens" "^1.0.0" + "style-to-object" "^0.3.0" + "unist-util-is" "^4.0.0" + "web-namespaces" "^1.0.0" + +"hast-util-from-parse5@^5.0.0": + "integrity" "sha512-gOc8UB99F6eWVWFtM9jUikjN7QkWxB3nY0df5Z0Zq1/Nkwl5V4hAAsl0tmwlgWl/1shlTF8DnNYLO8X6wRV9pA==" + "resolved" "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-5.0.3.tgz" + "version" "5.0.3" + dependencies: + "ccount" "^1.0.3" + "hastscript" "^5.0.0" + "property-information" "^5.0.0" + "web-namespaces" "^1.1.2" + "xtend" "^4.0.1" + +"hast-util-from-parse5@^6.0.0": + "integrity" "sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA==" + "resolved" "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz" + "version" "6.0.1" dependencies: "@types/parse5" "^5.0.0" - hastscript "^6.0.0" - property-information "^5.0.0" - vfile "^4.0.0" - vfile-location "^3.2.0" - web-namespaces "^1.0.0" - -hast-util-parse-selector@^2.0.0: - version "2.2.5" - resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz#d57c23f4da16ae3c63b3b6ca4616683313499c3a" - integrity sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ== - -hast-util-raw@6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/hast-util-raw/-/hast-util-raw-6.0.1.tgz#973b15930b7529a7b66984c98148b46526885977" - integrity sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig== + "hastscript" "^6.0.0" + "property-information" "^5.0.0" + "vfile" "^4.0.0" + "vfile-location" "^3.2.0" + "web-namespaces" "^1.0.0" + +"hast-util-parse-selector@^2.0.0": + "integrity" "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==" + "resolved" "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz" + "version" "2.2.5" + +"hast-util-raw@6.0.1": + "integrity" "sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig==" + "resolved" "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-6.0.1.tgz" + "version" "6.0.1" dependencies: "@types/hast" "^2.0.0" - hast-util-from-parse5 "^6.0.0" - hast-util-to-parse5 "^6.0.0" - html-void-elements "^1.0.0" - parse5 "^6.0.0" - unist-util-position "^3.0.0" - vfile "^4.0.0" - web-namespaces "^1.0.0" - xtend "^4.0.0" - zwitch "^1.0.0" - -hast-util-to-parse5@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz#1ec44650b631d72952066cea9b1445df699f8479" - integrity sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ== - dependencies: - hast-to-hyperscript "^9.0.0" - property-information "^5.0.0" - web-namespaces "^1.0.0" - xtend "^4.0.0" - zwitch "^1.0.0" - -hastscript@^5.0.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-5.1.2.tgz#bde2c2e56d04c62dd24e8c5df288d050a355fb8a" - integrity sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ== - dependencies: - comma-separated-tokens "^1.0.0" - hast-util-parse-selector "^2.0.0" - property-information "^5.0.0" - space-separated-tokens "^1.0.0" - -hastscript@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-6.0.0.tgz#e8768d7eac56c3fdeac8a92830d58e811e5bf640" - integrity sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w== + "hast-util-from-parse5" "^6.0.0" + "hast-util-to-parse5" "^6.0.0" + "html-void-elements" "^1.0.0" + "parse5" "^6.0.0" + "unist-util-position" "^3.0.0" + "vfile" "^4.0.0" + "web-namespaces" "^1.0.0" + "xtend" "^4.0.0" + "zwitch" "^1.0.0" + +"hast-util-to-parse5@^6.0.0": + "integrity" "sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ==" + "resolved" "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "hast-to-hyperscript" "^9.0.0" + "property-information" "^5.0.0" + "web-namespaces" "^1.0.0" + "xtend" "^4.0.0" + "zwitch" "^1.0.0" + +"hastscript@^5.0.0": + "integrity" "sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ==" + "resolved" "https://registry.npmjs.org/hastscript/-/hastscript-5.1.2.tgz" + "version" "5.1.2" + dependencies: + "comma-separated-tokens" "^1.0.0" + "hast-util-parse-selector" "^2.0.0" + "property-information" "^5.0.0" + "space-separated-tokens" "^1.0.0" + +"hastscript@^6.0.0": + "integrity" "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==" + "resolved" "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz" + "version" "6.0.0" dependencies: "@types/hast" "^2.0.0" - comma-separated-tokens "^1.0.0" - hast-util-parse-selector "^2.0.0" - property-information "^5.0.0" - space-separated-tokens "^1.0.0" + "comma-separated-tokens" "^1.0.0" + "hast-util-parse-selector" "^2.0.0" + "property-information" "^5.0.0" + "space-separated-tokens" "^1.0.0" -he@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +"he@^1.2.0": + "integrity" "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + "resolved" "https://registry.npmjs.org/he/-/he-1.2.0.tgz" + "version" "1.2.0" -history@^4.9.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" - integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew== +"history@^4.9.0": + "integrity" "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==" + "resolved" "https://registry.npmjs.org/history/-/history-4.10.1.tgz" + "version" "4.10.1" dependencies: "@babel/runtime" "^7.1.2" - loose-envify "^1.2.0" - resolve-pathname "^3.0.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - value-equal "^1.0.1" - -hoist-non-react-statics@^3.1.0: - version "3.3.2" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" - integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== - dependencies: - react-is "^16.7.0" - -hpack.js@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" - integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI= - dependencies: - inherits "^2.0.1" - obuf "^1.0.0" - readable-stream "^2.0.1" - wbuf "^1.1.0" - -html-entities@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.2.tgz#760b404685cb1d794e4f4b744332e3b00dcfe488" - integrity sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ== - -html-minifier-terser@^6.0.2: - version "6.1.0" - resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" - integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== - dependencies: - camel-case "^4.1.2" - clean-css "^5.2.2" - commander "^8.3.0" - he "^1.2.0" - param-case "^3.0.4" - relateurl "^0.2.7" - terser "^5.10.0" - -html-tags@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" - integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg== - -html-void-elements@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483" - integrity sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w== - -html-webpack-plugin@^5.4.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz#c3911936f57681c1f9f4d8b68c158cd9dfe52f50" - integrity sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw== + "loose-envify" "^1.2.0" + "resolve-pathname" "^3.0.0" + "tiny-invariant" "^1.0.2" + "tiny-warning" "^1.0.0" + "value-equal" "^1.0.1" + +"hoist-non-react-statics@^3.1.0": + "integrity" "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==" + "resolved" "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz" + "version" "3.3.2" + dependencies: + "react-is" "^16.7.0" + +"hpack.js@^2.1.6": + "integrity" "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=" + "resolved" "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz" + "version" "2.1.6" + dependencies: + "inherits" "^2.0.1" + "obuf" "^1.0.0" + "readable-stream" "^2.0.1" + "wbuf" "^1.1.0" + +"html-entities@^2.3.2": + "integrity" "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==" + "resolved" "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz" + "version" "2.3.2" + +"html-minifier-terser@^6.0.2": + "integrity" "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==" + "resolved" "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "camel-case" "^4.1.2" + "clean-css" "^5.2.2" + "commander" "^8.3.0" + "he" "^1.2.0" + "param-case" "^3.0.4" + "relateurl" "^0.2.7" + "terser" "^5.10.0" + +"html-tags@^3.1.0": + "integrity" "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==" + "resolved" "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz" + "version" "3.1.0" + +"html-void-elements@^1.0.0": + "integrity" "sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w==" + "resolved" "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz" + "version" "1.0.5" + +"html-webpack-plugin@^5.4.0": + "integrity" "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==" + "resolved" "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz" + "version" "5.5.0" dependencies: "@types/html-minifier-terser" "^6.0.0" - html-minifier-terser "^6.0.2" - lodash "^4.17.21" - pretty-error "^4.0.0" - tapable "^2.0.0" - -htmlparser2@^3.9.1: - version "3.10.1" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" - integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== - dependencies: - domelementtype "^1.3.1" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^3.1.1" - -htmlparser2@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" - integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== - dependencies: - domelementtype "^2.0.1" - domhandler "^4.0.0" - domutils "^2.5.2" - entities "^2.0.0" - -http-cache-semantics@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" - integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== - -http-deceiver@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" - integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= - -http-errors@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" - integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.1" - -http-errors@~1.6.2: - version "1.6.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - -http-parser-js@>=0.5.1: - version "0.5.5" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.5.tgz#d7c30d5d3c90d865b4a2e870181f9d6f22ac7ac5" - integrity sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA== - -http-proxy-middleware@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.3.tgz#5df04f69a89f530c2284cd71eeaa51ba52243289" - integrity sha512-1bloEwnrHMnCoO/Gcwbz7eSVvW50KPES01PecpagI+YLNLci4AcuKJrujW4Mc3sBLpFxMSlsLNHS5Nl/lvrTPA== + "html-minifier-terser" "^6.0.2" + "lodash" "^4.17.21" + "pretty-error" "^4.0.0" + "tapable" "^2.0.0" + +"htmlparser2@^3.9.1": + "integrity" "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==" + "resolved" "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz" + "version" "3.10.1" + dependencies: + "domelementtype" "^1.3.1" + "domhandler" "^2.3.0" + "domutils" "^1.5.1" + "entities" "^1.1.1" + "inherits" "^2.0.1" + "readable-stream" "^3.1.1" + +"htmlparser2@^6.1.0": + "integrity" "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==" + "resolved" "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "domelementtype" "^2.0.1" + "domhandler" "^4.0.0" + "domutils" "^2.5.2" + "entities" "^2.0.0" + +"http-cache-semantics@^4.0.0": + "integrity" "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + "resolved" "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz" + "version" "4.1.1" + +"http-deceiver@^1.2.7": + "integrity" "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" + "resolved" "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" + "version" "1.2.7" + +"http-errors@~1.6.2": + "integrity" "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=" + "resolved" "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz" + "version" "1.6.3" + dependencies: + "depd" "~1.1.2" + "inherits" "2.0.3" + "setprototypeof" "1.1.0" + "statuses" ">= 1.4.0 < 2" + +"http-errors@1.8.1": + "integrity" "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==" + "resolved" "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz" + "version" "1.8.1" + dependencies: + "depd" "~1.1.2" + "inherits" "2.0.4" + "setprototypeof" "1.2.0" + "statuses" ">= 1.5.0 < 2" + "toidentifier" "1.0.1" + +"http-parser-js@>=0.5.1": + "integrity" "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA==" + "resolved" "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz" + "version" "0.5.5" + +"http-proxy-middleware@^2.0.0": + "integrity" "sha512-1bloEwnrHMnCoO/Gcwbz7eSVvW50KPES01PecpagI+YLNLci4AcuKJrujW4Mc3sBLpFxMSlsLNHS5Nl/lvrTPA==" + "resolved" "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.3.tgz" + "version" "2.0.3" dependencies: "@types/http-proxy" "^1.17.8" - http-proxy "^1.18.1" - is-glob "^4.0.1" - is-plain-obj "^3.0.0" - micromatch "^4.0.2" - -http-proxy@^1.18.1: - version "1.18.1" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" - integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== - dependencies: - eventemitter3 "^4.0.0" - follow-redirects "^1.0.0" - requires-port "^1.0.0" - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -icss-utils@^5.0.0, icss-utils@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" - integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== - -ignore@^5.1.9, ignore@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== - -image-size@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.0.1.tgz#86d6cfc2b1d19eab5d2b368d4b9194d9e48541c5" - integrity sha512-VAwkvNSNGClRw9mDHhc5Efax8PLlsOGcUTh0T/LIriC8vPA3U5PdqXWqkz406MoYHMKW8Uf9gWr05T/rYB44kQ== - dependencies: - queue "6.0.2" - -immer@^9.0.7: - version "9.0.12" - resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.12.tgz#2d33ddf3ee1d247deab9d707ca472c8c942a0f20" - integrity sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA== - -import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.2.2, import-fresh@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-lazy@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" - integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -infima@0.2.0-alpha.37: - version "0.2.0-alpha.37" - resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.37.tgz#b87ff42d528d6d050098a560f0294fbdd12adb78" - integrity sha512-4GX7Baw+/lwS4PPW/UJNY89tWSvYG1DL6baKVdpK6mC593iRgMssxNtORMTFArLPJ/A/lzsGhRmx+z6MaMxj0Q== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -ini@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" - integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== - -ini@^1.3.5, ini@~1.3.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - -inline-style-parser@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" - integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== - -interpret@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" - integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== - -ip@^1.1.0: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= - -ipaddr.js@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -ipaddr.js@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" - integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== - -is-alphabetical@1.0.4, is-alphabetical@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" - integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== - -is-alphanumerical@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" - integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== - dependencies: - is-alphabetical "^1.0.0" - is-decimal "^1.0.0" - -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-buffer@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" - integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== - -is-ci@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" - integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== - dependencies: - ci-info "^2.0.0" - -is-core-module@^2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" - integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== - dependencies: - has "^1.0.3" - -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-decimal@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" - integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== - -is-docker@^2.0.0, is-docker@^2.1.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" - integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== - -is-extendable@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-hexadecimal@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" - integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== - -is-installed-globally@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" - integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ== - dependencies: - global-dirs "^3.0.0" - is-path-inside "^3.0.2" - -is-npm@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-5.0.0.tgz#43e8d65cc56e1b67f8d47262cf667099193f45a8" - integrity sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA== - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - -is-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" - integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== - -is-path-cwd@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" - integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== - -is-path-inside@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - -is-plain-obj@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - -is-plain-obj@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" - integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== - -is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-regex@^1.0.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" - integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= - -is-root@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" - integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg== - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-typedarray@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-whitespace-character@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7" - integrity sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w== - -is-word-character@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.4.tgz#ce0e73216f98599060592f62ff31354ddbeb0230" - integrity sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA== - -is-wsl@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== - dependencies: - is-docker "^2.0.0" - -is-yarn-global@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" - integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - -jest-worker@^27.0.2, jest-worker@^27.4.5: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" - integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + "http-proxy" "^1.18.1" + "is-glob" "^4.0.1" + "is-plain-obj" "^3.0.0" + "micromatch" "^4.0.2" + +"http-proxy@^1.18.1": + "integrity" "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==" + "resolved" "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz" + "version" "1.18.1" + dependencies: + "eventemitter3" "^4.0.0" + "follow-redirects" "^1.0.0" + "requires-port" "^1.0.0" + +"human-signals@^2.1.0": + "integrity" "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" + "resolved" "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" + "version" "2.1.0" + +"iconv-lite@0.4.24": + "integrity" "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==" + "resolved" "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" + "version" "0.4.24" + dependencies: + "safer-buffer" ">= 2.1.2 < 3" + +"icss-utils@^5.0.0", "icss-utils@^5.1.0": + "integrity" "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==" + "resolved" "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz" + "version" "5.1.0" + +"ignore@^5.1.9", "ignore@^5.2.0": + "integrity" "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==" + "resolved" "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz" + "version" "5.2.0" + +"image-size@^1.0.1": + "integrity" "sha512-VAwkvNSNGClRw9mDHhc5Efax8PLlsOGcUTh0T/LIriC8vPA3U5PdqXWqkz406MoYHMKW8Uf9gWr05T/rYB44kQ==" + "resolved" "https://registry.npmjs.org/image-size/-/image-size-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "queue" "6.0.2" + +"immer@^9.0.7": + "integrity" "sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA==" + "resolved" "https://registry.npmjs.org/immer/-/immer-9.0.12.tgz" + "version" "9.0.12" + +"import-fresh@^3.1.0", "import-fresh@^3.2.1", "import-fresh@^3.2.2", "import-fresh@^3.3.0": + "integrity" "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==" + "resolved" "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" + "version" "3.3.0" + dependencies: + "parent-module" "^1.0.0" + "resolve-from" "^4.0.0" + +"import-lazy@^2.1.0": + "integrity" "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" + "resolved" "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz" + "version" "2.1.0" + +"imurmurhash@^0.1.4": + "integrity" "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + "resolved" "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" + "version" "0.1.4" + +"indent-string@^4.0.0": + "integrity" "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + "resolved" "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" + "version" "4.0.0" + +"infima@0.2.0-alpha.37": + "integrity" "sha512-4GX7Baw+/lwS4PPW/UJNY89tWSvYG1DL6baKVdpK6mC593iRgMssxNtORMTFArLPJ/A/lzsGhRmx+z6MaMxj0Q==" + "resolved" "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.37.tgz" + "version" "0.2.0-alpha.37" + +"inflight@^1.0.4": + "integrity" "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=" + "resolved" "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + "version" "1.0.6" + dependencies: + "once" "^1.3.0" + "wrappy" "1" + +"inherits@^2.0.0", "inherits@^2.0.1", "inherits@^2.0.3", "inherits@~2.0.3", "inherits@2", "inherits@2.0.4": + "integrity" "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "resolved" "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + "version" "2.0.4" + +"inherits@2.0.3": + "integrity" "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "resolved" "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + "version" "2.0.3" + +"ini@^1.3.5", "ini@~1.3.0": + "integrity" "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + "resolved" "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" + "version" "1.3.8" + +"ini@2.0.0": + "integrity" "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==" + "resolved" "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz" + "version" "2.0.0" + +"inline-style-parser@0.1.1": + "integrity" "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" + "resolved" "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz" + "version" "0.1.1" + +"interpret@^1.0.0": + "integrity" "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + "resolved" "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz" + "version" "1.4.0" + +"ip@^1.1.0": + "integrity" "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + "resolved" "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz" + "version" "1.1.5" + +"ipaddr.js@^2.0.1": + "integrity" "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==" + "resolved" "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz" + "version" "2.0.1" + +"ipaddr.js@1.9.1": + "integrity" "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + "resolved" "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" + "version" "1.9.1" + +"is-alphabetical@^1.0.0", "is-alphabetical@1.0.4": + "integrity" "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==" + "resolved" "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz" + "version" "1.0.4" + +"is-alphanumerical@^1.0.0": + "integrity" "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==" + "resolved" "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz" + "version" "1.0.4" + dependencies: + "is-alphabetical" "^1.0.0" + "is-decimal" "^1.0.0" + +"is-arguments@^1.0.4": + "integrity" "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==" + "resolved" "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "call-bind" "^1.0.2" + "has-tostringtag" "^1.0.0" + +"is-arrayish@^0.2.1": + "integrity" "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + "resolved" "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + "version" "0.2.1" + +"is-binary-path@~2.1.0": + "integrity" "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==" + "resolved" "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "binary-extensions" "^2.0.0" + +"is-buffer@^2.0.0": + "integrity" "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" + "resolved" "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz" + "version" "2.0.5" + +"is-ci@^2.0.0": + "integrity" "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==" + "resolved" "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "ci-info" "^2.0.0" + +"is-core-module@^2.8.1": + "integrity" "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==" + "resolved" "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz" + "version" "2.8.1" + dependencies: + "has" "^1.0.3" + +"is-date-object@^1.0.1": + "integrity" "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==" + "resolved" "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz" + "version" "1.0.5" + dependencies: + "has-tostringtag" "^1.0.0" + +"is-decimal@^1.0.0": + "integrity" "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==" + "resolved" "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz" + "version" "1.0.4" + +"is-docker@^2.0.0", "is-docker@^2.1.1": + "integrity" "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" + "resolved" "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz" + "version" "2.2.1" + +"is-extendable@^0.1.0": + "integrity" "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + "resolved" "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" + "version" "0.1.1" + +"is-extglob@^2.1.1": + "integrity" "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + "resolved" "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + "version" "2.1.1" + +"is-fullwidth-code-point@^3.0.0": + "integrity" "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + "resolved" "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + "version" "3.0.0" + +"is-glob@^4.0.1", "is-glob@^4.0.3", "is-glob@~4.0.1": + "integrity" "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==" + "resolved" "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" + "version" "4.0.3" + dependencies: + "is-extglob" "^2.1.1" + +"is-hexadecimal@^1.0.0": + "integrity" "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==" + "resolved" "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz" + "version" "1.0.4" + +"is-installed-globally@^0.4.0": + "integrity" "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==" + "resolved" "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz" + "version" "0.4.0" + dependencies: + "global-dirs" "^3.0.0" + "is-path-inside" "^3.0.2" + +"is-npm@^5.0.0": + "integrity" "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==" + "resolved" "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz" + "version" "5.0.0" + +"is-number@^7.0.0": + "integrity" "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + "resolved" "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + "version" "7.0.0" + +"is-obj@^1.0.1": + "integrity" "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + "resolved" "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz" + "version" "1.0.1" + +"is-obj@^2.0.0": + "integrity" "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" + "resolved" "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz" + "version" "2.0.0" + +"is-path-cwd@^2.2.0": + "integrity" "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==" + "resolved" "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz" + "version" "2.2.0" + +"is-path-inside@^3.0.2": + "integrity" "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" + "resolved" "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" + "version" "3.0.3" + +"is-plain-obj@^2.0.0": + "integrity" "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" + "resolved" "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" + "version" "2.1.0" + +"is-plain-obj@^3.0.0": + "integrity" "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==" + "resolved" "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz" + "version" "3.0.0" + +"is-plain-object@^2.0.4": + "integrity" "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==" + "resolved" "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" + "version" "2.0.4" + dependencies: + "isobject" "^3.0.1" + +"is-regex@^1.0.4": + "integrity" "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==" + "resolved" "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz" + "version" "1.1.4" + dependencies: + "call-bind" "^1.0.2" + "has-tostringtag" "^1.0.0" + +"is-regexp@^1.0.0": + "integrity" "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=" + "resolved" "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz" + "version" "1.0.0" + +"is-root@^2.1.0": + "integrity" "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==" + "resolved" "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz" + "version" "2.1.0" + +"is-stream@^2.0.0": + "integrity" "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + "resolved" "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" + "version" "2.0.1" + +"is-typedarray@^1.0.0": + "integrity" "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "resolved" "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" + "version" "1.0.0" + +"is-whitespace-character@^1.0.0": + "integrity" "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==" + "resolved" "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz" + "version" "1.0.4" + +"is-word-character@^1.0.0": + "integrity" "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==" + "resolved" "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz" + "version" "1.0.4" + +"is-wsl@^2.2.0": + "integrity" "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==" + "resolved" "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz" + "version" "2.2.0" + dependencies: + "is-docker" "^2.0.0" + +"is-yarn-global@^0.3.0": + "integrity" "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" + "resolved" "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz" + "version" "0.3.0" + +"isarray@~1.0.0": + "integrity" "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "resolved" "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + "version" "1.0.0" + +"isarray@0.0.1": + "integrity" "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + "resolved" "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + "version" "0.0.1" + +"isexe@^2.0.0": + "integrity" "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "resolved" "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + "version" "2.0.0" + +"isobject@^3.0.1": + "integrity" "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + "resolved" "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" + "version" "3.0.1" + +"jest-worker@^27.0.2", "jest-worker@^27.4.5": + "integrity" "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==" + "resolved" "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz" + "version" "27.5.1" dependencies: "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^8.0.0" + "merge-stream" "^2.0.0" + "supports-color" "^8.0.0" -joi@^17.4.2, joi@^17.6.0: - version "17.6.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.6.0.tgz#0bb54f2f006c09a96e75ce687957bd04290054b2" - integrity sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw== +"joi@^17.4.2", "joi@^17.6.0": + "integrity" "sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw==" + "resolved" "https://registry.npmjs.org/joi/-/joi-17.6.0.tgz" + "version" "17.6.0" dependencies: "@hapi/hoek" "^9.0.0" "@hapi/topo" "^5.0.0" @@ -4684,2834 +4702,2879 @@ joi@^17.4.2, joi@^17.6.0: "@sideway/formula" "^3.0.0" "@sideway/pinpoint" "^2.0.0" -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= - -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= - -json-parse-better-errors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - -json5@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" - integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== - dependencies: - minimist "^1.2.0" - -json5@^2.1.2: - version "2.2.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" - integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== - dependencies: - minimist "^1.2.5" - -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" +"js-tokens@^3.0.0 || ^4.0.0", "js-tokens@^4.0.0": + "integrity" "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "resolved" "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + "version" "4.0.0" + +"js-yaml@^3.13.1": + "integrity" "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==" + "resolved" "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" + "version" "3.14.1" + dependencies: + "argparse" "^1.0.7" + "esprima" "^4.0.0" + +"js-yaml@^4.0.0": + "integrity" "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==" + "resolved" "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "argparse" "^2.0.1" + +"jsesc@^2.5.1": + "integrity" "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + "resolved" "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" + "version" "2.5.2" + +"jsesc@~0.5.0": + "integrity" "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + "resolved" "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" + "version" "0.5.0" + +"json-buffer@3.0.0": + "integrity" "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + "resolved" "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz" + "version" "3.0.0" + +"json-parse-better-errors@^1.0.2": + "integrity" "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + "resolved" "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz" + "version" "1.0.2" + +"json-parse-even-better-errors@^2.3.0": + "integrity" "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + "resolved" "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" + "version" "2.3.1" + +"json-schema-traverse@^0.4.1": + "integrity" "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "resolved" "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" + "version" "0.4.1" + +"json-schema-traverse@^1.0.0": + "integrity" "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "resolved" "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" + "version" "1.0.0" + +"json5@^1.0.1": + "integrity" "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==" + "resolved" "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "minimist" "^1.2.0" + +"json5@^2.1.2", "json5@^2.2.2": + "integrity" "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" + "resolved" "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" + "version" "2.2.3" + +"jsonfile@^6.0.1": + "integrity" "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==" + "resolved" "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "universalify" "^2.0.0" optionalDependencies: - graceful-fs "^4.1.6" - -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== - dependencies: - json-buffer "3.0.0" - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - -klona@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" - integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== - -latest-version@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" - integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== - dependencies: - package-json "^6.3.0" - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -lilconfig@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.4.tgz#f4507d043d7058b380b6a8f5cb7bcd4b34cee082" - integrity sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA== - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -loader-runner@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" - integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== - -loader-utils@^1.4.0: - version "1.4.2" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd3d151fec01a3" - integrity sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^1.0.1" - -loader-utils@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129" - integrity sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^2.1.2" - -loader-utils@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.0.tgz#bcecc51a7898bee7473d4bc6b845b23af8304d4f" - integrity sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ== - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.assignin@^4.0.9: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" - integrity sha1-uo31+4QesKPoBEIysOJjqNxqKKI= - -lodash.bind@^4.1.4: - version "4.2.1" - resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" - integrity sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU= - -lodash.curry@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.curry/-/lodash.curry-4.1.1.tgz#248e36072ede906501d75966200a86dab8b23170" - integrity sha1-JI42By7ekGUB11lmIAqG2riyMXA= - -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= - -lodash.defaults@^4.0.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" - integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= - -lodash.filter@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace" - integrity sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4= - -lodash.flatten@^4.2.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" - integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= - -lodash.flow@^3.3.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/lodash.flow/-/lodash.flow-3.5.0.tgz#87bf40292b8cf83e4e8ce1a3ae4209e20071675a" - integrity sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o= - -lodash.foreach@^4.3.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" - integrity sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM= - -lodash.map@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" - integrity sha1-dx7Hg540c9nEzeKLGTlMNWL09tM= - -lodash.memoize@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - -lodash.merge@^4.4.0: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.pick@^4.2.1: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" - integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM= - -lodash.reduce@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b" - integrity sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs= - -lodash.reject@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415" - integrity sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU= - -lodash.some@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" - integrity sha1-G7nzFO9ri63tE7VJFpsqlF62jk0= - -lodash.uniq@4.5.0, lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= - -lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lower-case@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" - integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== - dependencies: - tslib "^2.0.3" - -lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -magic-string@^0.25.3: - version "0.25.7" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" - integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== - dependencies: - sourcemap-codec "^1.4.4" - -make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - -markdown-escapes@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535" - integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg== - -mdast-squeeze-paragraphs@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz#7c4c114679c3bee27ef10b58e2e015be79f1ef97" - integrity sha512-zxdPn69hkQ1rm4J+2Cs2j6wDEv7O17TfXTJ33tl/+JPIoEmtV9t2ZzBM5LPHE8QlHsmVD8t3vPKCyY3oH+H8MQ== + "graceful-fs" "^4.1.6" + +"keyv@^3.0.0": + "integrity" "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==" + "resolved" "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "json-buffer" "3.0.0" + +"kind-of@^6.0.0", "kind-of@^6.0.2": + "integrity" "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + "resolved" "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" + "version" "6.0.3" + +"kleur@^3.0.3": + "integrity" "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" + "resolved" "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" + "version" "3.0.3" + +"klona@^2.0.5": + "integrity" "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==" + "resolved" "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz" + "version" "2.0.5" + +"latest-version@^5.1.0": + "integrity" "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==" + "resolved" "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "package-json" "^6.3.0" + +"leven@^3.1.0": + "integrity" "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" + "resolved" "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz" + "version" "3.1.0" + +"lilconfig@^2.0.3": + "integrity" "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==" + "resolved" "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz" + "version" "2.0.4" + +"lines-and-columns@^1.1.6": + "integrity" "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + "resolved" "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" + "version" "1.2.4" + +"loader-runner@^4.2.0": + "integrity" "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==" + "resolved" "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz" + "version" "4.2.0" + +"loader-utils@^1.4.0": + "integrity" "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==" + "resolved" "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz" + "version" "1.4.2" + dependencies: + "big.js" "^5.2.2" + "emojis-list" "^3.0.0" + "json5" "^1.0.1" + +"loader-utils@^2.0.0": + "integrity" "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==" + "resolved" "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "big.js" "^5.2.2" + "emojis-list" "^3.0.0" + "json5" "^2.1.2" + +"loader-utils@^3.2.0": + "integrity" "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==" + "resolved" "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz" + "version" "3.2.0" + +"locate-path@^3.0.0": + "integrity" "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==" + "resolved" "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "p-locate" "^3.0.0" + "path-exists" "^3.0.0" + +"locate-path@^5.0.0": + "integrity" "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==" + "resolved" "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "p-locate" "^4.1.0" + +"locate-path@^6.0.0": + "integrity" "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==" + "resolved" "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "p-locate" "^5.0.0" + +"lodash.assignin@^4.0.9": + "integrity" "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=" + "resolved" "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz" + "version" "4.2.0" + +"lodash.bind@^4.1.4": + "integrity" "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=" + "resolved" "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz" + "version" "4.2.1" + +"lodash.curry@^4.0.1": + "integrity" "sha1-JI42By7ekGUB11lmIAqG2riyMXA=" + "resolved" "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz" + "version" "4.1.1" + +"lodash.debounce@^4.0.8": + "integrity" "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + "resolved" "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" + "version" "4.0.8" + +"lodash.defaults@^4.0.1": + "integrity" "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" + "resolved" "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz" + "version" "4.2.0" + +"lodash.filter@^4.4.0": + "integrity" "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=" + "resolved" "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz" + "version" "4.6.0" + +"lodash.flatten@^4.2.0": + "integrity" "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + "resolved" "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz" + "version" "4.4.0" + +"lodash.flow@^3.3.0": + "integrity" "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o=" + "resolved" "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz" + "version" "3.5.0" + +"lodash.foreach@^4.3.0": + "integrity" "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" + "resolved" "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz" + "version" "4.5.0" + +"lodash.map@^4.4.0": + "integrity" "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=" + "resolved" "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz" + "version" "4.6.0" + +"lodash.memoize@^4.1.2": + "integrity" "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" + "resolved" "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz" + "version" "4.1.2" + +"lodash.merge@^4.4.0": + "integrity" "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "resolved" "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" + "version" "4.6.2" + +"lodash.pick@^4.2.1": + "integrity" "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" + "resolved" "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz" + "version" "4.4.0" + +"lodash.reduce@^4.4.0": + "integrity" "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" + "resolved" "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz" + "version" "4.6.0" + +"lodash.reject@^4.4.0": + "integrity" "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=" + "resolved" "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz" + "version" "4.6.0" + +"lodash.some@^4.4.0": + "integrity" "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" + "resolved" "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz" + "version" "4.6.0" + +"lodash.uniq@^4.5.0", "lodash.uniq@4.5.0": + "integrity" "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + "resolved" "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz" + "version" "4.5.0" + +"lodash@^4.17.14", "lodash@^4.17.19", "lodash@^4.17.20", "lodash@^4.17.21": + "integrity" "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "resolved" "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" + "version" "4.17.21" + +"loose-envify@^1.0.0", "loose-envify@^1.1.0", "loose-envify@^1.2.0", "loose-envify@^1.3.1", "loose-envify@^1.4.0": + "integrity" "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==" + "resolved" "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" + "version" "1.4.0" + dependencies: + "js-tokens" "^3.0.0 || ^4.0.0" + +"lower-case@^2.0.2": + "integrity" "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==" + "resolved" "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "tslib" "^2.0.3" + +"lowercase-keys@^1.0.0", "lowercase-keys@^1.0.1": + "integrity" "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + "resolved" "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz" + "version" "1.0.1" + +"lowercase-keys@^2.0.0": + "integrity" "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" + "resolved" "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz" + "version" "2.0.0" + +"lru-cache@^5.1.1": + "integrity" "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==" + "resolved" "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" + "version" "5.1.1" + dependencies: + "yallist" "^3.0.2" + +"lru-cache@^6.0.0": + "integrity" "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==" + "resolved" "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "yallist" "^4.0.0" + +"magic-string@^0.25.3": + "integrity" "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==" + "resolved" "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz" + "version" "0.25.7" + dependencies: + "sourcemap-codec" "^1.4.4" + +"make-dir@^3.0.0", "make-dir@^3.0.2", "make-dir@^3.1.0": + "integrity" "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==" + "resolved" "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "semver" "^6.0.0" + +"markdown-escapes@^1.0.0": + "integrity" "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==" + "resolved" "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz" + "version" "1.0.4" + +"mdast-squeeze-paragraphs@^4.0.0": + "integrity" "sha512-zxdPn69hkQ1rm4J+2Cs2j6wDEv7O17TfXTJ33tl/+JPIoEmtV9t2ZzBM5LPHE8QlHsmVD8t3vPKCyY3oH+H8MQ==" + "resolved" "https://registry.npmjs.org/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz" + "version" "4.0.0" dependencies: - unist-util-remove "^2.0.0" - -mdast-util-definitions@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz#c5c1a84db799173b4dcf7643cda999e440c24db2" - integrity sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ== - dependencies: - unist-util-visit "^2.0.0" + "unist-util-remove" "^2.0.0" -mdast-util-to-hast@10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz#0cfc82089494c52d46eb0e3edb7a4eb2aea021eb" - integrity sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA== +"mdast-util-definitions@^4.0.0": + "integrity" "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==" + "resolved" "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "unist-util-visit" "^2.0.0" + +"mdast-util-to-hast@10.0.1": + "integrity" "sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA==" + "resolved" "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz" + "version" "10.0.1" dependencies: "@types/mdast" "^3.0.0" "@types/unist" "^2.0.0" - mdast-util-definitions "^4.0.0" - mdurl "^1.0.0" - unist-builder "^2.0.0" - unist-util-generated "^1.0.0" - unist-util-position "^3.0.0" - unist-util-visit "^2.0.0" - -mdast-util-to-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b" - integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w== - -mdn-data@2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" - integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== - -mdurl@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" - integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - -memfs@^3.1.2, memfs@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.1.tgz#b78092f466a0dce054d63d39275b24c71d3f1305" - integrity sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw== - dependencies: - fs-monkey "1.0.3" - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - -micromatch@^4.0.2, micromatch@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== - dependencies: - braces "^3.0.1" - picomatch "^2.2.3" - -mime-db@1.51.0, "mime-db@>= 1.43.0 < 2": - version "1.51.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" - integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== - -mime-db@~1.33.0: - version "1.33.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" - integrity sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ== - -mime-types@2.1.18: - version "2.1.18" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" - integrity sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ== - dependencies: - mime-db "~1.33.0" - -mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: - version "2.1.34" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" - integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== - dependencies: - mime-db "1.51.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -mimic-response@^1.0.0, mimic-response@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - -mini-create-react-context@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz#072171561bfdc922da08a60c2197a497cc2d1d5e" - integrity sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ== + "mdast-util-definitions" "^4.0.0" + "mdurl" "^1.0.0" + "unist-builder" "^2.0.0" + "unist-util-generated" "^1.0.0" + "unist-util-position" "^3.0.0" + "unist-util-visit" "^2.0.0" + +"mdast-util-to-string@^2.0.0": + "integrity" "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==" + "resolved" "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz" + "version" "2.0.0" + +"mdn-data@2.0.14": + "integrity" "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + "resolved" "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz" + "version" "2.0.14" + +"mdurl@^1.0.0": + "integrity" "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" + "resolved" "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz" + "version" "1.0.1" + +"media-typer@0.3.0": + "integrity" "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "resolved" "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + "version" "0.3.0" + +"memfs@^3.1.2", "memfs@^3.4.1": + "integrity" "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==" + "resolved" "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz" + "version" "3.4.1" + dependencies: + "fs-monkey" "1.0.3" + +"merge-descriptors@1.0.1": + "integrity" "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "resolved" "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" + "version" "1.0.1" + +"merge-stream@^2.0.0": + "integrity" "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + "resolved" "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" + "version" "2.0.0" + +"merge2@^1.3.0", "merge2@^1.4.1": + "integrity" "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + "resolved" "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" + "version" "1.4.1" + +"methods@~1.1.2": + "integrity" "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "resolved" "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + "version" "1.1.2" + +"micromatch@^4.0.2", "micromatch@^4.0.4": + "integrity" "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==" + "resolved" "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz" + "version" "4.0.4" + dependencies: + "braces" "^3.0.1" + "picomatch" "^2.2.3" + +"mime-db@>= 1.43.0 < 2", "mime-db@1.51.0": + "integrity" "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" + "resolved" "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz" + "version" "1.51.0" + +"mime-db@~1.33.0": + "integrity" "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + "resolved" "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz" + "version" "1.33.0" + +"mime-types@^2.1.27", "mime-types@^2.1.31", "mime-types@~2.1.17", "mime-types@~2.1.24", "mime-types@~2.1.34": + "integrity" "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==" + "resolved" "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz" + "version" "2.1.34" + dependencies: + "mime-db" "1.51.0" + +"mime-types@2.1.18": + "integrity" "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==" + "resolved" "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz" + "version" "2.1.18" + dependencies: + "mime-db" "~1.33.0" + +"mime@1.6.0": + "integrity" "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + "resolved" "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" + "version" "1.6.0" + +"mimic-fn@^2.1.0": + "integrity" "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + "resolved" "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" + "version" "2.1.0" + +"mimic-response@^1.0.0", "mimic-response@^1.0.1": + "integrity" "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + "resolved" "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz" + "version" "1.0.1" + +"mini-create-react-context@^0.4.0": + "integrity" "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==" + "resolved" "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz" + "version" "0.4.1" dependencies: "@babel/runtime" "^7.12.1" - tiny-warning "^1.0.3" - -mini-css-extract-plugin@^1.6.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-1.6.2.tgz#83172b4fd812f8fc4a09d6f6d16f924f53990ca8" - integrity sha512-WhDvO3SjGm40oV5y26GjMJYjd2UMqrLAGKy5YS2/3QKJy2F7jgynuHTir/tgUUOiNQu5saXHdc8reo7YuhhT4Q== - dependencies: - loader-utils "^2.0.0" - schema-utils "^3.0.0" - webpack-sources "^1.1.0" - -minimalistic-assert@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimatch@3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^3.0.4: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.0, minimist@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" - integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== - -mkdirp@^0.5.5: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" - -mrmime@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.0.tgz#14d387f0585a5233d291baba339b063752a2398b" - integrity sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3, ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -multicast-dns-service-types@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" - integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE= - -multicast-dns@^6.0.1: - version "6.2.3" - resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" - integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== - dependencies: - dns-packet "^1.3.1" - thunky "^1.0.2" - -nanoid@^3.2.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" - integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== - -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - -neo-async@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -no-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" - integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== - dependencies: - lower-case "^2.0.2" - tslib "^2.0.3" - -node-emoji@^1.10.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c" - integrity sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A== - dependencies: - lodash "^4.17.21" - -node-fetch@2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== - dependencies: - whatwg-url "^5.0.0" - -node-forge@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.0.tgz#37a874ea723855f37db091e6c186e5b67a01d4b2" - integrity sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA== - -node-releases@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01" - integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg== - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -normalize-range@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= - -normalize-url@^4.1.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" - integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== - -normalize-url@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" - integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -nprogress@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1" - integrity sha1-y480xTIT2JVyP8urkH6UIq28r7E= - -nth-check@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2" - integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w== - dependencies: - boolbase "^1.0.0" - -nth-check@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" - integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== - dependencies: - boolbase "~1.0.0" - -object-assign@^4.1.0, object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-is@^1.0.1: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -object-keys@^1.0.12, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" - object-keys "^1.1.1" + "tiny-warning" "^1.0.3" + +"mini-css-extract-plugin@^1.6.0": + "integrity" "sha512-WhDvO3SjGm40oV5y26GjMJYjd2UMqrLAGKy5YS2/3QKJy2F7jgynuHTir/tgUUOiNQu5saXHdc8reo7YuhhT4Q==" + "resolved" "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.6.2.tgz" + "version" "1.6.2" + dependencies: + "loader-utils" "^2.0.0" + "schema-utils" "^3.0.0" + "webpack-sources" "^1.1.0" + +"minimalistic-assert@^1.0.0": + "integrity" "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + "resolved" "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" + "version" "1.0.1" + +"minimatch@^3.0.4": + "integrity" "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==" + "resolved" "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" + "version" "3.1.2" + dependencies: + "brace-expansion" "^1.1.7" + +"minimatch@3.0.4": + "integrity" "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==" + "resolved" "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "brace-expansion" "^1.1.7" + +"minimist@^1.2.0", "minimist@^1.2.5": + "integrity" "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==" + "resolved" "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz" + "version" "1.2.7" + +"mkdirp@^0.5.5": + "integrity" "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==" + "resolved" "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz" + "version" "0.5.5" + dependencies: + "minimist" "^1.2.5" + +"mrmime@^1.0.0": + "integrity" "sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ==" + "resolved" "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz" + "version" "1.0.0" + +"ms@^2.1.1", "ms@2.1.3": + "integrity" "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "resolved" "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + "version" "2.1.3" + +"ms@2.0.0": + "integrity" "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "resolved" "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + "version" "2.0.0" + +"ms@2.1.2": + "integrity" "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "resolved" "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" + "version" "2.1.2" + +"multicast-dns-service-types@^1.1.0": + "integrity" "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" + "resolved" "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz" + "version" "1.1.0" + +"multicast-dns@^6.0.1": + "integrity" "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==" + "resolved" "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz" + "version" "6.2.3" + dependencies: + "dns-packet" "^1.3.1" + "thunky" "^1.0.2" + +"nanoid@^3.2.0": + "integrity" "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==" + "resolved" "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz" + "version" "3.3.1" + +"negotiator@0.6.3": + "integrity" "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + "resolved" "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" + "version" "0.6.3" + +"neo-async@^2.6.2": + "integrity" "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + "resolved" "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" + "version" "2.6.2" + +"no-case@^3.0.4": + "integrity" "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==" + "resolved" "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "lower-case" "^2.0.2" + "tslib" "^2.0.3" + +"node-emoji@^1.10.0": + "integrity" "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==" + "resolved" "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz" + "version" "1.11.0" + dependencies: + "lodash" "^4.17.21" + +"node-fetch@2.6.7": + "integrity" "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==" + "resolved" "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz" + "version" "2.6.7" + dependencies: + "whatwg-url" "^5.0.0" + +"node-forge@^1.2.0": + "integrity" "sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA==" + "resolved" "https://registry.npmjs.org/node-forge/-/node-forge-1.3.0.tgz" + "version" "1.3.0" + +"node-releases@^2.0.8": + "integrity" "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" + "resolved" "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz" + "version" "2.0.10" + +"normalize-path@^3.0.0", "normalize-path@~3.0.0": + "integrity" "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + "resolved" "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + "version" "3.0.0" + +"normalize-range@^0.1.2": + "integrity" "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=" + "resolved" "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz" + "version" "0.1.2" + +"normalize-url@^4.1.0": + "integrity" "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==" + "resolved" "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz" + "version" "4.5.1" + +"normalize-url@^6.0.1": + "integrity" "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" + "resolved" "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz" + "version" "6.1.0" + +"npm-run-path@^4.0.1": + "integrity" "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==" + "resolved" "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz" + "version" "4.0.1" + dependencies: + "path-key" "^3.0.0" + +"nprogress@^0.2.0": + "integrity" "sha1-y480xTIT2JVyP8urkH6UIq28r7E=" + "resolved" "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz" + "version" "0.2.0" + +"nth-check@^2.0.1": + "integrity" "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==" + "resolved" "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "boolbase" "^1.0.0" + +"nth-check@~1.0.1": + "integrity" "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==" + "resolved" "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "boolbase" "~1.0.0" + +"object-assign@^4.1.0", "object-assign@^4.1.1": + "integrity" "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "resolved" "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + "version" "4.1.1" + +"object-is@^1.0.1": + "integrity" "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==" + "resolved" "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz" + "version" "1.1.5" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.3" + +"object-keys@^1.0.12", "object-keys@^1.1.1": + "integrity" "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + "resolved" "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" + "version" "1.1.1" + +"object.assign@^4.1.0": + "integrity" "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==" + "resolved" "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "call-bind" "^1.0.0" + "define-properties" "^1.1.3" + "has-symbols" "^1.0.1" + "object-keys" "^1.1.1" -obuf@^1.0.0, obuf@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" - integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== +"obuf@^1.0.0", "obuf@^1.1.2": + "integrity" "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + "resolved" "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz" + "version" "1.1.2" -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" +"on-finished@~2.3.0": + "integrity" "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=" + "resolved" "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" + "version" "2.3.0" + dependencies: + "ee-first" "1.1.1" -on-headers@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== - -once@^1.3.0, once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" +"on-headers@~1.0.2": + "integrity" "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + "resolved" "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz" + "version" "1.0.2" + +"once@^1.3.0", "once@^1.3.1", "once@^1.4.0": + "integrity" "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=" + "resolved" "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + "version" "1.4.0" + dependencies: + "wrappy" "1" -onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== +"onetime@^5.1.2": + "integrity" "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==" + "resolved" "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" + "version" "5.1.2" dependencies: - mimic-fn "^2.1.0" + "mimic-fn" "^2.1.0" -open@^8.0.9, open@^8.4.0: - version "8.4.0" - resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" - integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q== +"open@^8.0.9", "open@^8.4.0": + "integrity" "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==" + "resolved" "https://registry.npmjs.org/open/-/open-8.4.0.tgz" + "version" "8.4.0" dependencies: - define-lazy-prop "^2.0.0" - is-docker "^2.1.1" - is-wsl "^2.2.0" + "define-lazy-prop" "^2.0.0" + "is-docker" "^2.1.1" + "is-wsl" "^2.2.0" -opener@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" - integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== +"opener@^1.5.2": + "integrity" "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==" + "resolved" "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz" + "version" "1.5.2" -p-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== +"p-cancelable@^1.0.0": + "integrity" "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" + "resolved" "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz" + "version" "1.1.0" -p-limit@^2.0.0, p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== +"p-limit@^2.0.0", "p-limit@^2.2.0": + "integrity" "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==" + "resolved" "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" + "version" "2.3.0" dependencies: - p-try "^2.0.0" + "p-try" "^2.0.0" -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== +"p-limit@^3.0.2": + "integrity" "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==" + "resolved" "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" + "version" "3.1.0" dependencies: - yocto-queue "^0.1.0" + "yocto-queue" "^0.1.0" -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== +"p-locate@^3.0.0": + "integrity" "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==" + "resolved" "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz" + "version" "3.0.0" dependencies: - p-limit "^2.0.0" + "p-limit" "^2.0.0" -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== +"p-locate@^4.1.0": + "integrity" "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==" + "resolved" "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" + "version" "4.1.0" dependencies: - p-limit "^2.2.0" + "p-limit" "^2.2.0" -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== +"p-locate@^5.0.0": + "integrity" "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==" + "resolved" "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" + "version" "5.0.0" dependencies: - p-limit "^3.0.2" + "p-limit" "^3.0.2" -p-map@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" - integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== +"p-map@^4.0.0": + "integrity" "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==" + "resolved" "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz" + "version" "4.0.0" dependencies: - aggregate-error "^3.0.0" + "aggregate-error" "^3.0.0" -p-retry@^4.5.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.1.tgz#8fcddd5cdf7a67a0911a9cf2ef0e5df7f602316c" - integrity sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA== +"p-retry@^4.5.0": + "integrity" "sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==" + "resolved" "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz" + "version" "4.6.1" dependencies: "@types/retry" "^0.12.0" - retry "^0.13.1" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -package-json@^6.3.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" - integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== - dependencies: - got "^9.6.0" - registry-auth-token "^4.0.0" - registry-url "^5.0.0" - semver "^6.2.0" - -param-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" - integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== - dependencies: - dot-case "^3.0.4" - tslib "^2.0.3" - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-entities@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" - integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ== - dependencies: - character-entities "^1.0.0" - character-entities-legacy "^1.0.0" - character-reference-invalid "^1.0.0" - is-alphanumerical "^1.0.0" - is-decimal "^1.0.0" - is-hexadecimal "^1.0.0" - -parse-json@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + "retry" "^0.13.1" + +"p-try@^2.0.0": + "integrity" "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + "resolved" "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" + "version" "2.2.0" + +"package-json@^6.3.0": + "integrity" "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==" + "resolved" "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz" + "version" "6.5.0" + dependencies: + "got" "^9.6.0" + "registry-auth-token" "^4.0.0" + "registry-url" "^5.0.0" + "semver" "^6.2.0" + +"param-case@^3.0.4": + "integrity" "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==" + "resolved" "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "dot-case" "^3.0.4" + "tslib" "^2.0.3" + +"parent-module@^1.0.0": + "integrity" "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==" + "resolved" "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "callsites" "^3.0.0" + +"parse-entities@^2.0.0": + "integrity" "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==" + "resolved" "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "character-entities" "^1.0.0" + "character-entities-legacy" "^1.0.0" + "character-reference-invalid" "^1.0.0" + "is-alphanumerical" "^1.0.0" + "is-decimal" "^1.0.0" + "is-hexadecimal" "^1.0.0" + +"parse-json@^5.0.0": + "integrity" "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==" + "resolved" "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" + "version" "5.2.0" dependencies: "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -parse-numeric-range@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz#7c63b61190d61e4d53a1197f0c83c47bb670ffa3" - integrity sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ== - -parse5-htmlparser2-tree-adapter@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" - integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA== - dependencies: - parse5 "^6.0.1" - -parse5@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" - integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== - -parse5@^6.0.0, parse5@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" - integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== - -parseurl@~1.3.2, parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -pascal-case@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" - integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-is-inside@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= - -path-to-regexp@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.2.1.tgz#90b617025a16381a879bc82a38d4e8bdeb2bcf45" - integrity sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ== - -path-to-regexp@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" - integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== - dependencies: - isarray "0.0.1" - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pkg-dir@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -pkg-up@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" - integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== - dependencies: - find-up "^3.0.0" - -portfinder@^1.0.28: - version "1.0.28" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" - integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== - dependencies: - async "^2.6.2" - debug "^3.1.1" - mkdirp "^0.5.5" - -postcss-calc@^8.2.0: - version "8.2.4" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5" - integrity sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q== - dependencies: - postcss-selector-parser "^6.0.9" - postcss-value-parser "^4.2.0" - -postcss-colormin@^5.2.5: - version "5.2.5" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.2.5.tgz#d1fc269ac2ad03fe641d462b5d1dada35c69968a" - integrity sha512-+X30aDaGYq81mFqwyPpnYInsZQnNpdxMX0ajlY7AExCexEFkPVV+KrO7kXwayqEWL2xwEbNQ4nUO0ZsRWGnevg== - dependencies: - browserslist "^4.16.6" - caniuse-api "^3.0.0" - colord "^2.9.1" - postcss-value-parser "^4.2.0" - -postcss-convert-values@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.0.4.tgz#3e74dd97c581f475ae7b4500bc0a7c4fb3a6b1b6" - integrity sha512-bugzSAyjIexdObovsPZu/sBCTHccImJxLyFgeV0MmNBm/Lw5h5XnjfML6gzEmJ3A6nyfCW7hb1JXzcsA4Zfbdw== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-discard-comments@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.0.3.tgz#011acb63418d600fdbe18804e1bbecb543ad2f87" - integrity sha512-6W5BemziRoqIdAKT+1QjM4bNcJAQ7z7zk073730NHg4cUXh3/rQHHj7pmYxUB9aGhuRhBiUf0pXvIHkRwhQP0Q== - -postcss-discard-duplicates@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.3.tgz#10f202a4cfe9d407b73dfea7a477054d21ea0c1f" - integrity sha512-vPtm1Mf+kp7iAENTG7jI1MN1lk+fBqL5y+qxyi4v3H+lzsXEdfS3dwUZD45KVhgzDEgduur8ycB4hMegyMTeRw== - -postcss-discard-empty@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.0.3.tgz#ec185af4a3710b88933b0ff751aa157b6041dd6a" - integrity sha512-xGJugpaXKakwKI7sSdZjUuN4V3zSzb2Y0LOlmTajFbNinEjTfVs9PFW2lmKBaC/E64WwYppfqLD03P8l9BuueA== - -postcss-discard-overridden@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.0.4.tgz#cc999d6caf18ea16eff8b2b58f48ec3ddee35c9c" - integrity sha512-3j9QH0Qh1KkdxwiZOW82cId7zdwXVQv/gRXYDnwx5pBtR1sTkU4cXRK9lp5dSdiM0r0OICO/L8J6sV1/7m0kHg== - -postcss-discard-unused@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-5.0.3.tgz#89fd3ebdbed8320df77a4ad503bd83cff52409f5" - integrity sha512-WO6FJxL5fGnuE77ZbTcZ/nRZJ4+TOqNaqLBLWgkR4e+WdmHn77OHPyQmsRv7eOB2rLKL6tsq2bs1GwoKXD/++Q== - dependencies: - postcss-selector-parser "^6.0.5" - -postcss-loader@^6.1.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-6.2.1.tgz#0895f7346b1702103d30fdc66e4d494a93c008ef" - integrity sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q== - dependencies: - cosmiconfig "^7.0.0" - klona "^2.0.5" - semver "^7.3.5" - -postcss-merge-idents@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-5.0.3.tgz#04f333f32767bd7b7b002f0032da347ec3c8c484" - integrity sha512-Z4LCzh2WzMn69KaS2FaJcrIeDQ170V13QHq+0hnBEFKJJkD+y5qndZ/bl3AhpddrSrXWIVR+xAwjmHQIJI2Eog== - dependencies: - cssnano-utils "^3.0.2" - postcss-value-parser "^4.2.0" - -postcss-merge-longhand@^5.0.6: - version "5.0.6" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.0.6.tgz#090e60d5d3b3caad899f8774f8dccb33217d2166" - integrity sha512-rkmoPwQO6ymJSmWsX6l2hHeEBQa7C4kJb9jyi5fZB1sE8nSCv7sqchoYPixRwX/yvLoZP2y6FA5kcjiByeJqDg== - dependencies: - postcss-value-parser "^4.2.0" - stylehacks "^5.0.3" - -postcss-merge-rules@^5.0.6: - version "5.0.6" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.0.6.tgz#26b37411fe1e80202fcef61cab027265b8925f2b" - integrity sha512-nzJWJ9yXWp8AOEpn/HFAW72WKVGD2bsLiAmgw4hDchSij27bt6TF+sIK0cJUBAYT3SGcjtGGsOR89bwkkMuMgQ== + "error-ex" "^1.3.1" + "json-parse-even-better-errors" "^2.3.0" + "lines-and-columns" "^1.1.6" + +"parse-numeric-range@^1.3.0": + "integrity" "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" + "resolved" "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz" + "version" "1.3.0" + +"parse5-htmlparser2-tree-adapter@^6.0.1": + "integrity" "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==" + "resolved" "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "parse5" "^6.0.1" + +"parse5@^5.0.0": + "integrity" "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + "resolved" "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz" + "version" "5.1.1" + +"parse5@^6.0.0", "parse5@^6.0.1": + "integrity" "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + "resolved" "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz" + "version" "6.0.1" + +"parseurl@~1.3.2", "parseurl@~1.3.3": + "integrity" "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + "resolved" "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" + "version" "1.3.3" + +"pascal-case@^3.1.2": + "integrity" "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==" + "resolved" "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz" + "version" "3.1.2" + dependencies: + "no-case" "^3.0.4" + "tslib" "^2.0.3" + +"path-exists@^3.0.0": + "integrity" "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + "resolved" "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" + "version" "3.0.0" + +"path-exists@^4.0.0": + "integrity" "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + "resolved" "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" + "version" "4.0.0" + +"path-is-absolute@^1.0.0": + "integrity" "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "resolved" "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + "version" "1.0.1" + +"path-is-inside@1.0.2": + "integrity" "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + "resolved" "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz" + "version" "1.0.2" + +"path-key@^3.0.0", "path-key@^3.1.0": + "integrity" "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + "resolved" "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" + "version" "3.1.1" + +"path-parse@^1.0.7": + "integrity" "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "resolved" "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + "version" "1.0.7" + +"path-to-regexp@^1.7.0": + "integrity" "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==" + "resolved" "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz" + "version" "1.8.0" + dependencies: + "isarray" "0.0.1" + +"path-to-regexp@0.1.7": + "integrity" "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "resolved" "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" + "version" "0.1.7" + +"path-to-regexp@2.2.1": + "integrity" "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" + "resolved" "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz" + "version" "2.2.1" + +"path-type@^4.0.0": + "integrity" "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + "resolved" "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" + "version" "4.0.0" + +"picocolors@^1.0.0": + "integrity" "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "resolved" "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" + "version" "1.0.0" + +"picomatch@^2.0.4", "picomatch@^2.2.1", "picomatch@^2.2.3": + "integrity" "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + "resolved" "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + "version" "2.3.1" + +"pkg-dir@^4.1.0": + "integrity" "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==" + "resolved" "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" + "version" "4.2.0" + dependencies: + "find-up" "^4.0.0" + +"pkg-up@^3.1.0": + "integrity" "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==" + "resolved" "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "find-up" "^3.0.0" + +"portfinder@^1.0.28": + "integrity" "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==" + "resolved" "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz" + "version" "1.0.28" + dependencies: + "async" "^2.6.2" + "debug" "^3.1.1" + "mkdirp" "^0.5.5" + +"postcss-calc@^8.2.0": + "integrity" "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==" + "resolved" "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz" + "version" "8.2.4" + dependencies: + "postcss-selector-parser" "^6.0.9" + "postcss-value-parser" "^4.2.0" + +"postcss-colormin@^5.2.5": + "integrity" "sha512-+X30aDaGYq81mFqwyPpnYInsZQnNpdxMX0ajlY7AExCexEFkPVV+KrO7kXwayqEWL2xwEbNQ4nUO0ZsRWGnevg==" + "resolved" "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.2.5.tgz" + "version" "5.2.5" + dependencies: + "browserslist" "^4.16.6" + "caniuse-api" "^3.0.0" + "colord" "^2.9.1" + "postcss-value-parser" "^4.2.0" + +"postcss-convert-values@^5.0.4": + "integrity" "sha512-bugzSAyjIexdObovsPZu/sBCTHccImJxLyFgeV0MmNBm/Lw5h5XnjfML6gzEmJ3A6nyfCW7hb1JXzcsA4Zfbdw==" + "resolved" "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.0.4.tgz" + "version" "5.0.4" + dependencies: + "postcss-value-parser" "^4.2.0" + +"postcss-discard-comments@^5.0.3": + "integrity" "sha512-6W5BemziRoqIdAKT+1QjM4bNcJAQ7z7zk073730NHg4cUXh3/rQHHj7pmYxUB9aGhuRhBiUf0pXvIHkRwhQP0Q==" + "resolved" "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.0.3.tgz" + "version" "5.0.3" + +"postcss-discard-duplicates@^5.0.3": + "integrity" "sha512-vPtm1Mf+kp7iAENTG7jI1MN1lk+fBqL5y+qxyi4v3H+lzsXEdfS3dwUZD45KVhgzDEgduur8ycB4hMegyMTeRw==" + "resolved" "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.3.tgz" + "version" "5.0.3" + +"postcss-discard-empty@^5.0.3": + "integrity" "sha512-xGJugpaXKakwKI7sSdZjUuN4V3zSzb2Y0LOlmTajFbNinEjTfVs9PFW2lmKBaC/E64WwYppfqLD03P8l9BuueA==" + "resolved" "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.0.3.tgz" + "version" "5.0.3" + +"postcss-discard-overridden@^5.0.4": + "integrity" "sha512-3j9QH0Qh1KkdxwiZOW82cId7zdwXVQv/gRXYDnwx5pBtR1sTkU4cXRK9lp5dSdiM0r0OICO/L8J6sV1/7m0kHg==" + "resolved" "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.0.4.tgz" + "version" "5.0.4" + +"postcss-discard-unused@^5.0.3": + "integrity" "sha512-WO6FJxL5fGnuE77ZbTcZ/nRZJ4+TOqNaqLBLWgkR4e+WdmHn77OHPyQmsRv7eOB2rLKL6tsq2bs1GwoKXD/++Q==" + "resolved" "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-5.0.3.tgz" + "version" "5.0.3" + dependencies: + "postcss-selector-parser" "^6.0.5" + +"postcss-loader@^6.1.1": + "integrity" "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==" + "resolved" "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz" + "version" "6.2.1" + dependencies: + "cosmiconfig" "^7.0.0" + "klona" "^2.0.5" + "semver" "^7.3.5" + +"postcss-merge-idents@^5.0.3": + "integrity" "sha512-Z4LCzh2WzMn69KaS2FaJcrIeDQ170V13QHq+0hnBEFKJJkD+y5qndZ/bl3AhpddrSrXWIVR+xAwjmHQIJI2Eog==" + "resolved" "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-5.0.3.tgz" + "version" "5.0.3" + dependencies: + "cssnano-utils" "^3.0.2" + "postcss-value-parser" "^4.2.0" + +"postcss-merge-longhand@^5.0.6": + "integrity" "sha512-rkmoPwQO6ymJSmWsX6l2hHeEBQa7C4kJb9jyi5fZB1sE8nSCv7sqchoYPixRwX/yvLoZP2y6FA5kcjiByeJqDg==" + "resolved" "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.0.6.tgz" + "version" "5.0.6" + dependencies: + "postcss-value-parser" "^4.2.0" + "stylehacks" "^5.0.3" + +"postcss-merge-rules@^5.0.6": + "integrity" "sha512-nzJWJ9yXWp8AOEpn/HFAW72WKVGD2bsLiAmgw4hDchSij27bt6TF+sIK0cJUBAYT3SGcjtGGsOR89bwkkMuMgQ==" + "resolved" "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.0.6.tgz" + "version" "5.0.6" dependencies: - browserslist "^4.16.6" - caniuse-api "^3.0.0" - cssnano-utils "^3.0.2" - postcss-selector-parser "^6.0.5" + "browserslist" "^4.16.6" + "caniuse-api" "^3.0.0" + "cssnano-utils" "^3.0.2" + "postcss-selector-parser" "^6.0.5" -postcss-minify-font-values@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.0.4.tgz#627d824406b0712243221891f40a44fffe1467fd" - integrity sha512-RN6q3tyuEesvyCYYFCRGJ41J1XFvgV+dvYGHr0CeHv8F00yILlN8Slf4t8XW4IghlfZYCeyRrANO6HpJ948ieA== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-minify-gradients@^5.0.6: - version "5.0.6" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.0.6.tgz#b07cef51a93f075e94053fd972ff1cba2eaf6503" - integrity sha512-E/dT6oVxB9nLGUTiY/rG5dX9taugv9cbLNTFad3dKxOO+BQg25Q/xo2z2ddG+ZB1CbkZYaVwx5blY8VC7R/43A== - dependencies: - colord "^2.9.1" - cssnano-utils "^3.0.2" - postcss-value-parser "^4.2.0" +"postcss-minify-font-values@^5.0.4": + "integrity" "sha512-RN6q3tyuEesvyCYYFCRGJ41J1XFvgV+dvYGHr0CeHv8F00yILlN8Slf4t8XW4IghlfZYCeyRrANO6HpJ948ieA==" + "resolved" "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.0.4.tgz" + "version" "5.0.4" + dependencies: + "postcss-value-parser" "^4.2.0" + +"postcss-minify-gradients@^5.0.6": + "integrity" "sha512-E/dT6oVxB9nLGUTiY/rG5dX9taugv9cbLNTFad3dKxOO+BQg25Q/xo2z2ddG+ZB1CbkZYaVwx5blY8VC7R/43A==" + "resolved" "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.0.6.tgz" + "version" "5.0.6" + dependencies: + "colord" "^2.9.1" + "cssnano-utils" "^3.0.2" + "postcss-value-parser" "^4.2.0" -postcss-minify-params@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.0.5.tgz#86cb624358cd45c21946f8c317893f0449396646" - integrity sha512-YBNuq3Rz5LfLFNHb9wrvm6t859b8qIqfXsWeK7wROm3jSKNpO1Y5e8cOyBv6Acji15TgSrAwb3JkVNCqNyLvBg== +"postcss-minify-params@^5.0.5": + "integrity" "sha512-YBNuq3Rz5LfLFNHb9wrvm6t859b8qIqfXsWeK7wROm3jSKNpO1Y5e8cOyBv6Acji15TgSrAwb3JkVNCqNyLvBg==" + "resolved" "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.0.5.tgz" + "version" "5.0.5" dependencies: - browserslist "^4.16.6" - cssnano-utils "^3.0.2" - postcss-value-parser "^4.2.0" + "browserslist" "^4.16.6" + "cssnano-utils" "^3.0.2" + "postcss-value-parser" "^4.2.0" -postcss-minify-selectors@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.1.3.tgz#6ac12d52aa661fd509469d87ab2cebb0a1e3a1b5" - integrity sha512-9RJfTiQEKA/kZhMaEXND893nBqmYQ8qYa/G+uPdVnXF6D/FzpfI6kwBtWEcHx5FqDbA79O9n6fQJfrIj6M8jvQ== +"postcss-minify-selectors@^5.1.3": + "integrity" "sha512-9RJfTiQEKA/kZhMaEXND893nBqmYQ8qYa/G+uPdVnXF6D/FzpfI6kwBtWEcHx5FqDbA79O9n6fQJfrIj6M8jvQ==" + "resolved" "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.1.3.tgz" + "version" "5.1.3" dependencies: - postcss-selector-parser "^6.0.5" + "postcss-selector-parser" "^6.0.5" -postcss-modules-extract-imports@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" - integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== +"postcss-modules-extract-imports@^3.0.0": + "integrity" "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==" + "resolved" "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz" + "version" "3.0.0" -postcss-modules-local-by-default@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" - integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== +"postcss-modules-local-by-default@^4.0.0": + "integrity" "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==" + "resolved" "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz" + "version" "4.0.0" dependencies: - icss-utils "^5.0.0" - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.1.0" + "icss-utils" "^5.0.0" + "postcss-selector-parser" "^6.0.2" + "postcss-value-parser" "^4.1.0" -postcss-modules-scope@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" - integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== +"postcss-modules-scope@^3.0.0": + "integrity" "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==" + "resolved" "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz" + "version" "3.0.0" dependencies: - postcss-selector-parser "^6.0.4" + "postcss-selector-parser" "^6.0.4" -postcss-modules-values@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" - integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== +"postcss-modules-values@^4.0.0": + "integrity" "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==" + "resolved" "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz" + "version" "4.0.0" dependencies: - icss-utils "^5.0.0" + "icss-utils" "^5.0.0" -postcss-normalize-charset@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.0.3.tgz#719fb9f9ca9835fcbd4fed8d6e0d72a79e7b5472" - integrity sha512-iKEplDBco9EfH7sx4ut7R2r/dwTnUqyfACf62Unc9UiyFuI7uUqZZtY+u+qp7g8Qszl/U28HIfcsI3pEABWFfA== +"postcss-normalize-charset@^5.0.3": + "integrity" "sha512-iKEplDBco9EfH7sx4ut7R2r/dwTnUqyfACf62Unc9UiyFuI7uUqZZtY+u+qp7g8Qszl/U28HIfcsI3pEABWFfA==" + "resolved" "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.0.3.tgz" + "version" "5.0.3" -postcss-normalize-display-values@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.3.tgz#94cc82e20c51cc4ffba6b36e9618adc1e50db8c1" - integrity sha512-FIV5FY/qs4Ja32jiDb5mVj5iWBlS3N8tFcw2yg98+8MkRgyhtnBgSC0lxU+16AMHbjX5fbSJgw5AXLMolonuRQ== +"postcss-normalize-display-values@^5.0.3": + "integrity" "sha512-FIV5FY/qs4Ja32jiDb5mVj5iWBlS3N8tFcw2yg98+8MkRgyhtnBgSC0lxU+16AMHbjX5fbSJgw5AXLMolonuRQ==" + "resolved" "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.3.tgz" + "version" "5.0.3" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-positions@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.0.4.tgz#4001f38c99675437b83277836fb4291887fcc6cc" - integrity sha512-qynirjBX0Lc73ROomZE3lzzmXXTu48/QiEzKgMeqh28+MfuHLsuqC9po4kj84igZqqFGovz8F8hf44hA3dPYmQ== +"postcss-normalize-positions@^5.0.4": + "integrity" "sha512-qynirjBX0Lc73ROomZE3lzzmXXTu48/QiEzKgMeqh28+MfuHLsuqC9po4kj84igZqqFGovz8F8hf44hA3dPYmQ==" + "resolved" "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-repeat-style@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.4.tgz#d005adf9ee45fae78b673031a376c0c871315145" - integrity sha512-Innt+wctD7YpfeDR7r5Ik6krdyppyAg2HBRpX88fo5AYzC1Ut/l3xaxACG0KsbX49cO2n5EB13clPwuYVt8cMA== +"postcss-normalize-repeat-style@^5.0.4": + "integrity" "sha512-Innt+wctD7YpfeDR7r5Ik6krdyppyAg2HBRpX88fo5AYzC1Ut/l3xaxACG0KsbX49cO2n5EB13clPwuYVt8cMA==" + "resolved" "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-string@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.0.4.tgz#b5e00a07597e7aa8a871817bfeac2bfaa59c3333" - integrity sha512-Dfk42l0+A1CDnVpgE606ENvdmksttLynEqTQf5FL3XGQOyqxjbo25+pglCUvziicTxjtI2NLUR6KkxyUWEVubQ== +"postcss-normalize-string@^5.0.4": + "integrity" "sha512-Dfk42l0+A1CDnVpgE606ENvdmksttLynEqTQf5FL3XGQOyqxjbo25+pglCUvziicTxjtI2NLUR6KkxyUWEVubQ==" + "resolved" "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-timing-functions@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.3.tgz#47210227bfcba5e52650d7a18654337090de7072" - integrity sha512-QRfjvFh11moN4PYnJ7hia4uJXeFotyK3t2jjg8lM9mswleGsNw2Lm3I5wO+l4k1FzK96EFwEVn8X8Ojrp2gP4g== +"postcss-normalize-timing-functions@^5.0.3": + "integrity" "sha512-QRfjvFh11moN4PYnJ7hia4uJXeFotyK3t2jjg8lM9mswleGsNw2Lm3I5wO+l4k1FzK96EFwEVn8X8Ojrp2gP4g==" + "resolved" "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.3.tgz" + "version" "5.0.3" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-unicode@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.4.tgz#02866096937005cdb2c17116c690f29505a1623d" - integrity sha512-W79Regn+a+eXTzB+oV/8XJ33s3pDyFTND2yDuUCo0Xa3QSy1HtNIfRVPXNubHxjhlqmMFADr3FSCHT84ITW3ig== +"postcss-normalize-unicode@^5.0.4": + "integrity" "sha512-W79Regn+a+eXTzB+oV/8XJ33s3pDyFTND2yDuUCo0Xa3QSy1HtNIfRVPXNubHxjhlqmMFADr3FSCHT84ITW3ig==" + "resolved" "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.4.tgz" + "version" "5.0.4" dependencies: - browserslist "^4.16.6" - postcss-value-parser "^4.2.0" + "browserslist" "^4.16.6" + "postcss-value-parser" "^4.2.0" -postcss-normalize-url@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.0.5.tgz#c39efc12ff119f6f45f0b4f516902b12c8080e3a" - integrity sha512-Ws3tX+PcekYlXh+ycAt0wyzqGthkvVtZ9SZLutMVvHARxcpu4o7vvXcNoiNKyjKuWecnjS6HDI3fjBuDr5MQxQ== +"postcss-normalize-url@^5.0.5": + "integrity" "sha512-Ws3tX+PcekYlXh+ycAt0wyzqGthkvVtZ9SZLutMVvHARxcpu4o7vvXcNoiNKyjKuWecnjS6HDI3fjBuDr5MQxQ==" + "resolved" "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.0.5.tgz" + "version" "5.0.5" dependencies: - normalize-url "^6.0.1" - postcss-value-parser "^4.2.0" + "normalize-url" "^6.0.1" + "postcss-value-parser" "^4.2.0" -postcss-normalize-whitespace@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.4.tgz#1d477e7da23fecef91fc4e37d462272c7b55c5ca" - integrity sha512-wsnuHolYZjMwWZJoTC9jeI2AcjA67v4UuidDrPN9RnX8KIZfE+r2Nd6XZRwHVwUiHmRvKQtxiqo64K+h8/imaw== +"postcss-normalize-whitespace@^5.0.4": + "integrity" "sha512-wsnuHolYZjMwWZJoTC9jeI2AcjA67v4UuidDrPN9RnX8KIZfE+r2Nd6XZRwHVwUiHmRvKQtxiqo64K+h8/imaw==" + "resolved" "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-ordered-values@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.0.5.tgz#e878af822a130c3f3709737e24cb815ca7c6d040" - integrity sha512-mfY7lXpq+8bDEHfP+muqibDPhZ5eP9zgBEF9XRvoQgXcQe2Db3G1wcvjbnfjXG6wYsl+0UIjikqq4ym1V2jGMQ== +"postcss-ordered-values@^5.0.5": + "integrity" "sha512-mfY7lXpq+8bDEHfP+muqibDPhZ5eP9zgBEF9XRvoQgXcQe2Db3G1wcvjbnfjXG6wYsl+0UIjikqq4ym1V2jGMQ==" + "resolved" "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.0.5.tgz" + "version" "5.0.5" dependencies: - cssnano-utils "^3.0.2" - postcss-value-parser "^4.2.0" + "cssnano-utils" "^3.0.2" + "postcss-value-parser" "^4.2.0" -postcss-reduce-idents@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-5.0.3.tgz#b632796275b4fa1a4040799969dd17167eaf4d8b" - integrity sha512-9bj9/Xhwiti0Z35kkguJX4G6yUYVw8S1kRLU4jFSCTEuHu4yJggf4rNUoVnT45lm/vU97Wd593CxspMDbHxy4w== +"postcss-reduce-idents@^5.0.3": + "integrity" "sha512-9bj9/Xhwiti0Z35kkguJX4G6yUYVw8S1kRLU4jFSCTEuHu4yJggf4rNUoVnT45lm/vU97Wd593CxspMDbHxy4w==" + "resolved" "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-5.0.3.tgz" + "version" "5.0.3" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-reduce-initial@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.0.3.tgz#68891594defd648253703bbd8f1093162f19568d" - integrity sha512-c88TkSnQ/Dnwgb4OZbKPOBbCaauwEjbECP5uAuFPOzQ+XdjNjRH7SG0dteXrpp1LlIFEKK76iUGgmw2V0xeieA== +"postcss-reduce-initial@^5.0.3": + "integrity" "sha512-c88TkSnQ/Dnwgb4OZbKPOBbCaauwEjbECP5uAuFPOzQ+XdjNjRH7SG0dteXrpp1LlIFEKK76iUGgmw2V0xeieA==" + "resolved" "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.0.3.tgz" + "version" "5.0.3" dependencies: - browserslist "^4.16.6" - caniuse-api "^3.0.0" + "browserslist" "^4.16.6" + "caniuse-api" "^3.0.0" -postcss-reduce-transforms@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.4.tgz#717e72d30befe857f7d2784dba10eb1157863712" - integrity sha512-VIJB9SFSaL8B/B7AXb7KHL6/GNNbbCHslgdzS9UDfBZYIA2nx8NLY7iD/BXFSO/1sRUILzBTfHCoW5inP37C5g== +"postcss-reduce-transforms@^5.0.4": + "integrity" "sha512-VIJB9SFSaL8B/B7AXb7KHL6/GNNbbCHslgdzS9UDfBZYIA2nx8NLY7iD/BXFSO/1sRUILzBTfHCoW5inP37C5g==" + "resolved" "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: - version "6.0.9" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f" - integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ== +"postcss-selector-parser@^6.0.2", "postcss-selector-parser@^6.0.4", "postcss-selector-parser@^6.0.5", "postcss-selector-parser@^6.0.9": + "integrity" "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==" + "resolved" "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz" + "version" "6.0.9" dependencies: - cssesc "^3.0.0" - util-deprecate "^1.0.2" + "cssesc" "^3.0.0" + "util-deprecate" "^1.0.2" -postcss-sort-media-queries@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/postcss-sort-media-queries/-/postcss-sort-media-queries-4.2.1.tgz#a99bae69ef1098ee3b64a5fa94d258ec240d0355" - integrity sha512-9VYekQalFZ3sdgcTjXMa0dDjsfBVHXlraYJEMiOJ/2iMmI2JGCMavP16z3kWOaRu8NSaJCTgVpB/IVpH5yT9YQ== +"postcss-sort-media-queries@^4.1.0": + "integrity" "sha512-9VYekQalFZ3sdgcTjXMa0dDjsfBVHXlraYJEMiOJ/2iMmI2JGCMavP16z3kWOaRu8NSaJCTgVpB/IVpH5yT9YQ==" + "resolved" "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-4.2.1.tgz" + "version" "4.2.1" dependencies: - sort-css-media-queries "2.0.4" + "sort-css-media-queries" "2.0.4" -postcss-svgo@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.0.4.tgz#cfa8682f47b88f7cd75108ec499e133b43102abf" - integrity sha512-yDKHvULbnZtIrRqhZoA+rxreWpee28JSRH/gy9727u0UCgtpv1M/9WEWY3xySlFa0zQJcqf6oCBJPR5NwkmYpg== +"postcss-svgo@^5.0.4": + "integrity" "sha512-yDKHvULbnZtIrRqhZoA+rxreWpee28JSRH/gy9727u0UCgtpv1M/9WEWY3xySlFa0zQJcqf6oCBJPR5NwkmYpg==" + "resolved" "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-value-parser "^4.2.0" - svgo "^2.7.0" + "postcss-value-parser" "^4.2.0" + "svgo" "^2.7.0" -postcss-unique-selectors@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.0.4.tgz#08e188126b634ddfa615fb1d6c262bafdd64826e" - integrity sha512-5ampwoSDJCxDPoANBIlMgoBcYUHnhaiuLYJR5pj1DLnYQvMRVyFuTA5C3Bvt+aHtiqWpJkD/lXT50Vo1D0ZsAQ== +"postcss-unique-selectors@^5.0.4": + "integrity" "sha512-5ampwoSDJCxDPoANBIlMgoBcYUHnhaiuLYJR5pj1DLnYQvMRVyFuTA5C3Bvt+aHtiqWpJkD/lXT50Vo1D0ZsAQ==" + "resolved" "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-selector-parser "^6.0.5" + "postcss-selector-parser" "^6.0.5" -postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" - integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== +"postcss-value-parser@^4.1.0", "postcss-value-parser@^4.2.0": + "integrity" "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "resolved" "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" + "version" "4.2.0" -postcss-zindex@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-5.0.2.tgz#7e48aee54062c93418593035229ea06b92381251" - integrity sha512-KPQFjQu73H35HLHmE8Wv31ygfQoucxD52oRm4FPFv1emYhFMzUQdF8adaXCevFLIHPRp2rRYfbaDiEqZ4YjVtw== +"postcss-zindex@^5.0.2": + "integrity" "sha512-KPQFjQu73H35HLHmE8Wv31ygfQoucxD52oRm4FPFv1emYhFMzUQdF8adaXCevFLIHPRp2rRYfbaDiEqZ4YjVtw==" + "resolved" "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-5.0.2.tgz" + "version" "5.0.2" -postcss@^8.3.11, postcss@^8.3.5, postcss@^8.3.7, postcss@^8.4.5: - version "8.4.6" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.6.tgz#c5ff3c3c457a23864f32cb45ac9b741498a09ae1" - integrity sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA== +"postcss@^7.0.0 || ^8.0.1", "postcss@^8.0.9", "postcss@^8.1.0", "postcss@^8.2.15", "postcss@^8.2.2", "postcss@^8.3.11", "postcss@^8.3.5", "postcss@^8.3.7", "postcss@^8.4.4", "postcss@^8.4.5": + "integrity" "sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA==" + "resolved" "https://registry.npmjs.org/postcss/-/postcss-8.4.6.tgz" + "version" "8.4.6" dependencies: - nanoid "^3.2.0" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= - -pretty-error@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" - integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw== - dependencies: - lodash "^4.17.20" - renderkid "^3.0.0" - -pretty-time@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pretty-time/-/pretty-time-1.1.0.tgz#ffb7429afabb8535c346a34e41873adf3d74dd0e" - integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA== - -prism-react-renderer@^1.2.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.3.1.tgz#88fc9d0df6bed06ca2b9097421349f8c2f24e30d" - integrity sha512-xUeDMEz074d0zc5y6rxiMp/dlC7C+5IDDlaEUlcBOFE2wddz7hz5PNupb087mPwTt7T9BrFmewObfCBuf/LKwQ== - -prismjs@^1.23.0: - version "1.27.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057" - integrity sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA== - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -promise@^7.1.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" - integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== - dependencies: - asap "~2.0.3" - -prompts@^2.4.1, prompts@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" - integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - -prop-types@^15.6.2, prop-types@^15.7.2: - version "15.8.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" - integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.13.1" - -property-information@^5.0.0, property-information@^5.3.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.6.0.tgz#61675545fb23002f245c6540ec46077d4da3ed69" - integrity sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA== - dependencies: - xtend "^4.0.0" - -proxy-addr@~2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" - integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== - dependencies: - forwarded "0.2.0" - ipaddr.js "1.9.1" - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - -punycode@^1.3.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -pupa@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" - integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A== - dependencies: - escape-goat "^2.0.0" - -pure-color@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/pure-color/-/pure-color-1.3.0.tgz#1fe064fb0ac851f0de61320a8bf796836422f33e" - integrity sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4= - -qs@6.9.7: - version "6.9.7" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe" - integrity sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw== - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -queue@6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.2.tgz#b91525283e2315c7553d2efa18d83e76432fed65" - integrity sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA== - dependencies: - inherits "~2.0.3" - -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -range-parser@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= - -range-parser@^1.2.1, range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.3.tgz#8f80305d11c2a0a545c2d9d89d7a0286fcead43c" - integrity sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g== - dependencies: - bytes "3.1.2" - http-errors "1.8.1" - iconv-lite "0.4.24" - unpipe "1.0.0" - -rc@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -react-base16-styling@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/react-base16-styling/-/react-base16-styling-0.6.0.tgz#ef2156d66cf4139695c8a167886cb69ea660792c" - integrity sha1-7yFW1mz0E5aVyKFniGy2nqZgeSw= - dependencies: - base16 "^1.0.0" - lodash.curry "^4.0.1" - lodash.flow "^3.3.0" - pure-color "^1.2.0" - -react-dev-utils@^12.0.0: - version "12.0.0" - resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.0.tgz#4eab12cdb95692a077616770b5988f0adf806526" - integrity sha512-xBQkitdxozPxt1YZ9O1097EJiVpwHr9FoAuEVURCKV0Av8NBERovJauzP7bo1ThvuhZ4shsQ1AJiu4vQpoT1AQ== + "nanoid" "^3.2.0" + "picocolors" "^1.0.0" + "source-map-js" "^1.0.2" + +"prepend-http@^2.0.0": + "integrity" "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + "resolved" "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz" + "version" "2.0.0" + +"pretty-error@^4.0.0": + "integrity" "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==" + "resolved" "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "lodash" "^4.17.20" + "renderkid" "^3.0.0" + +"pretty-time@^1.1.0": + "integrity" "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==" + "resolved" "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz" + "version" "1.1.0" + +"prism-react-renderer@^1.2.1": + "integrity" "sha512-xUeDMEz074d0zc5y6rxiMp/dlC7C+5IDDlaEUlcBOFE2wddz7hz5PNupb087mPwTt7T9BrFmewObfCBuf/LKwQ==" + "resolved" "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-1.3.1.tgz" + "version" "1.3.1" + +"prismjs@^1.23.0": + "integrity" "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==" + "resolved" "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz" + "version" "1.27.0" + +"process-nextick-args@~2.0.0": + "integrity" "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "resolved" "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" + "version" "2.0.1" + +"promise@^7.1.1": + "integrity" "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==" + "resolved" "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz" + "version" "7.3.1" + dependencies: + "asap" "~2.0.3" + +"prompts@^2.4.1", "prompts@^2.4.2": + "integrity" "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==" + "resolved" "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "kleur" "^3.0.3" + "sisteransi" "^1.0.5" + +"prop-types@^15.0.0", "prop-types@^15.6.2", "prop-types@^15.7.2": + "integrity" "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==" + "resolved" "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" + "version" "15.8.1" + dependencies: + "loose-envify" "^1.4.0" + "object-assign" "^4.1.1" + "react-is" "^16.13.1" + +"property-information@^5.0.0", "property-information@^5.3.0": + "integrity" "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==" + "resolved" "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz" + "version" "5.6.0" + dependencies: + "xtend" "^4.0.0" + +"proxy-addr@~2.0.7": + "integrity" "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==" + "resolved" "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" + "version" "2.0.7" + dependencies: + "forwarded" "0.2.0" + "ipaddr.js" "1.9.1" + +"pump@^3.0.0": + "integrity" "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==" + "resolved" "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "end-of-stream" "^1.1.0" + "once" "^1.3.1" + +"punycode@^1.3.2": + "integrity" "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + "resolved" "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" + "version" "1.4.1" + +"punycode@^2.1.0": + "integrity" "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "resolved" "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz" + "version" "2.1.1" + +"punycode@1.3.2": + "integrity" "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + "resolved" "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" + "version" "1.3.2" + +"pupa@^2.1.1": + "integrity" "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==" + "resolved" "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz" + "version" "2.1.1" + dependencies: + "escape-goat" "^2.0.0" + +"pure-color@^1.2.0": + "integrity" "sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4=" + "resolved" "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz" + "version" "1.3.0" + +"qs@6.9.7": + "integrity" "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" + "resolved" "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz" + "version" "6.9.7" + +"querystring@0.2.0": + "integrity" "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + "resolved" "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" + "version" "0.2.0" + +"queue-microtask@^1.2.2": + "integrity" "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" + "resolved" "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + "version" "1.2.3" + +"queue@6.0.2": + "integrity" "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==" + "resolved" "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz" + "version" "6.0.2" + dependencies: + "inherits" "~2.0.3" + +"randombytes@^2.1.0": + "integrity" "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==" + "resolved" "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "safe-buffer" "^5.1.0" + +"range-parser@^1.2.1", "range-parser@~1.2.1": + "integrity" "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + "resolved" "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" + "version" "1.2.1" + +"range-parser@1.2.0": + "integrity" "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + "resolved" "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz" + "version" "1.2.0" + +"raw-body@2.4.3": + "integrity" "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==" + "resolved" "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz" + "version" "2.4.3" + dependencies: + "bytes" "3.1.2" + "http-errors" "1.8.1" + "iconv-lite" "0.4.24" + "unpipe" "1.0.0" + +"rc@^1.2.8": + "integrity" "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==" + "resolved" "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz" + "version" "1.2.8" + dependencies: + "deep-extend" "^0.6.0" + "ini" "~1.3.0" + "minimist" "^1.2.0" + "strip-json-comments" "~2.0.1" + +"react-base16-styling@^0.6.0": + "integrity" "sha1-7yFW1mz0E5aVyKFniGy2nqZgeSw=" + "resolved" "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.6.0.tgz" + "version" "0.6.0" + dependencies: + "base16" "^1.0.0" + "lodash.curry" "^4.0.1" + "lodash.flow" "^3.3.0" + "pure-color" "^1.2.0" + +"react-dev-utils@^12.0.0": + "integrity" "sha512-xBQkitdxozPxt1YZ9O1097EJiVpwHr9FoAuEVURCKV0Av8NBERovJauzP7bo1ThvuhZ4shsQ1AJiu4vQpoT1AQ==" + "resolved" "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz" + "version" "12.0.0" dependencies: "@babel/code-frame" "^7.16.0" - address "^1.1.2" - browserslist "^4.18.1" - chalk "^4.1.2" - cross-spawn "^7.0.3" - detect-port-alt "^1.1.6" - escape-string-regexp "^4.0.0" - filesize "^8.0.6" - find-up "^5.0.0" - fork-ts-checker-webpack-plugin "^6.5.0" - global-modules "^2.0.0" - globby "^11.0.4" - gzip-size "^6.0.0" - immer "^9.0.7" - is-root "^2.1.0" - loader-utils "^3.2.0" - open "^8.4.0" - pkg-up "^3.1.0" - prompts "^2.4.2" - react-error-overlay "^6.0.10" - recursive-readdir "^2.2.2" - shell-quote "^1.7.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" - -react-dom@^16.10.2: - version "16.14.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.14.0.tgz#7ad838ec29a777fb3c75c3a190f661cf92ab8b89" - integrity sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - scheduler "^0.19.1" - -react-error-overlay@^6.0.10: - version "6.0.10" - resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.10.tgz#0fe26db4fa85d9dbb8624729580e90e7159a59a6" - integrity sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA== - -react-fast-compare@^3.1.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" - integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== - -react-helmet@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-6.1.0.tgz#a750d5165cb13cf213e44747502652e794468726" - integrity sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw== - dependencies: - object-assign "^4.1.1" - prop-types "^15.7.2" - react-fast-compare "^3.1.1" - react-side-effect "^2.1.0" - -react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -react-json-view@^1.21.3: - version "1.21.3" - resolved "https://registry.yarnpkg.com/react-json-view/-/react-json-view-1.21.3.tgz#f184209ee8f1bf374fb0c41b0813cff54549c475" - integrity sha512-13p8IREj9/x/Ye4WI/JpjhoIwuzEgUAtgJZNBJckfzJt1qyh24BdTm6UQNGnyTq9dapQdrqvquZTo3dz1X6Cjw== - dependencies: - flux "^4.0.1" - react-base16-styling "^0.6.0" - react-lifecycles-compat "^3.0.4" - react-textarea-autosize "^8.3.2" - -react-lifecycles-compat@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" - integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== - -react-loadable-ssr-addon-v5-slorber@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz#2cdc91e8a744ffdf9e3556caabeb6e4278689883" - integrity sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A== + "address" "^1.1.2" + "browserslist" "^4.18.1" + "chalk" "^4.1.2" + "cross-spawn" "^7.0.3" + "detect-port-alt" "^1.1.6" + "escape-string-regexp" "^4.0.0" + "filesize" "^8.0.6" + "find-up" "^5.0.0" + "fork-ts-checker-webpack-plugin" "^6.5.0" + "global-modules" "^2.0.0" + "globby" "^11.0.4" + "gzip-size" "^6.0.0" + "immer" "^9.0.7" + "is-root" "^2.1.0" + "loader-utils" "^3.2.0" + "open" "^8.4.0" + "pkg-up" "^3.1.0" + "prompts" "^2.4.2" + "react-error-overlay" "^6.0.10" + "recursive-readdir" "^2.2.2" + "shell-quote" "^1.7.3" + "strip-ansi" "^6.0.1" + "text-table" "^0.2.0" + +"react-dom@*", "react-dom@^16.10.2", "react-dom@^16.8.4 || ^17.0.0", "react-dom@^17.0.0 || ^16.3.0 || ^15.5.4", "react-dom@>= 16.8.0 < 18.0.0": + "integrity" "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==" + "resolved" "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz" + "version" "16.14.0" + dependencies: + "loose-envify" "^1.1.0" + "object-assign" "^4.1.1" + "prop-types" "^15.6.2" + "scheduler" "^0.19.1" + +"react-error-overlay@^6.0.10": + "integrity" "sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA==" + "resolved" "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz" + "version" "6.0.10" + +"react-fast-compare@^3.1.1": + "integrity" "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" + "resolved" "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz" + "version" "3.2.0" + +"react-helmet@^6.1.0": + "integrity" "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==" + "resolved" "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "object-assign" "^4.1.1" + "prop-types" "^15.7.2" + "react-fast-compare" "^3.1.1" + "react-side-effect" "^2.1.0" + +"react-is@^16.13.1", "react-is@^16.6.0", "react-is@^16.7.0": + "integrity" "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "resolved" "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" + "version" "16.13.1" + +"react-json-view@^1.21.3": + "integrity" "sha512-13p8IREj9/x/Ye4WI/JpjhoIwuzEgUAtgJZNBJckfzJt1qyh24BdTm6UQNGnyTq9dapQdrqvquZTo3dz1X6Cjw==" + "resolved" "https://registry.npmjs.org/react-json-view/-/react-json-view-1.21.3.tgz" + "version" "1.21.3" + dependencies: + "flux" "^4.0.1" + "react-base16-styling" "^0.6.0" + "react-lifecycles-compat" "^3.0.4" + "react-textarea-autosize" "^8.3.2" + +"react-lifecycles-compat@^3.0.4": + "integrity" "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + "resolved" "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz" + "version" "3.0.4" + +"react-loadable-ssr-addon-v5-slorber@^1.0.1": + "integrity" "sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==" + "resolved" "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz" + "version" "1.0.1" dependencies: "@babel/runtime" "^7.10.3" -react-popupbox@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/react-popupbox/-/react-popupbox-2.0.8.tgz#9e0c96dcf4ddbbea8d03c28ee6c0634f0d51b791" - integrity sha512-5DT0SxLMIchKgnUkdPwTzvFhtTL5SOQd6n5dzUnnELiimjFE8eaQwL1n58NZUxs9oJsHXF3qQNvcgwEfn8VHrw== +"react-loadable@*", "react-loadable@npm:@docusaurus/react-loadable@5.5.2": + "integrity" "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==" + "resolved" "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz" + "version" "5.5.2" + dependencies: + "@types/react" "*" + "prop-types" "^15.6.2" + +"react-popupbox@^2.0.8": + "integrity" "sha512-5DT0SxLMIchKgnUkdPwTzvFhtTL5SOQd6n5dzUnnELiimjFE8eaQwL1n58NZUxs9oJsHXF3qQNvcgwEfn8VHrw==" + "resolved" "https://registry.npmjs.org/react-popupbox/-/react-popupbox-2.0.8.tgz" + "version" "2.0.8" dependencies: - deepmerge "^1.3.2" - react "^16.3.1" + "deepmerge" "^1.3.2" + "react" "^16.3.1" -react-router-config@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/react-router-config/-/react-router-config-5.1.1.tgz#0f4263d1a80c6b2dc7b9c1902c9526478194a988" - integrity sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg== +"react-router-config@^5.1.1": + "integrity" "sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==" + "resolved" "https://registry.npmjs.org/react-router-config/-/react-router-config-5.1.1.tgz" + "version" "5.1.1" dependencies: "@babel/runtime" "^7.1.2" -react-router-dom@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.0.tgz#da1bfb535a0e89a712a93b97dd76f47ad1f32363" - integrity sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ== +"react-router-dom@^5.2.0": + "integrity" "sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ==" + "resolved" "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.0.tgz" + "version" "5.3.0" dependencies: "@babel/runtime" "^7.12.13" - history "^4.9.0" - loose-envify "^1.3.1" - prop-types "^15.6.2" - react-router "5.2.1" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - -react-router@5.2.1, react-router@^5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.1.tgz#4d2e4e9d5ae9425091845b8dbc6d9d276239774d" - integrity sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ== + "history" "^4.9.0" + "loose-envify" "^1.3.1" + "prop-types" "^15.6.2" + "react-router" "5.2.1" + "tiny-invariant" "^1.0.2" + "tiny-warning" "^1.0.0" + +"react-router@^5.2.0", "react-router@>=5", "react-router@5.2.1": + "integrity" "sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==" + "resolved" "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz" + "version" "5.2.1" dependencies: "@babel/runtime" "^7.12.13" - history "^4.9.0" - hoist-non-react-statics "^3.1.0" - loose-envify "^1.3.1" - mini-create-react-context "^0.4.0" - path-to-regexp "^1.7.0" - prop-types "^15.6.2" - react-is "^16.6.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - -react-side-effect@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-2.1.1.tgz#66c5701c3e7560ab4822a4ee2742dee215d72eb3" - integrity sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ== - -react-textarea-autosize@^8.3.2: - version "8.3.3" - resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz#f70913945369da453fd554c168f6baacd1fa04d8" - integrity sha512-2XlHXK2TDxS6vbQaoPbMOfQ8GK7+irc2fVK6QFIcC8GOnH3zI/v481n+j1L0WaPVvKxwesnY93fEfH++sus2rQ== + "history" "^4.9.0" + "hoist-non-react-statics" "^3.1.0" + "loose-envify" "^1.3.1" + "mini-create-react-context" "^0.4.0" + "path-to-regexp" "^1.7.0" + "prop-types" "^15.6.2" + "react-is" "^16.6.0" + "tiny-invariant" "^1.0.2" + "tiny-warning" "^1.0.0" + +"react-side-effect@^2.1.0": + "integrity" "sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ==" + "resolved" "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.1.tgz" + "version" "2.1.1" + +"react-textarea-autosize@^8.3.2": + "integrity" "sha512-2XlHXK2TDxS6vbQaoPbMOfQ8GK7+irc2fVK6QFIcC8GOnH3zI/v481n+j1L0WaPVvKxwesnY93fEfH++sus2rQ==" + "resolved" "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz" + "version" "8.3.3" dependencies: "@babel/runtime" "^7.10.2" - use-composed-ref "^1.0.0" - use-latest "^1.0.0" - -react@^16.10.2, react@^16.3.1: - version "16.14.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d" - integrity sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - -readable-stream@^2.0.1: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.0.6, readable-stream@^3.1.1: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -reading-time@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/reading-time/-/reading-time-1.5.0.tgz#d2a7f1b6057cb2e169beaf87113cc3411b5bc5bb" - integrity sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg== - -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= - dependencies: - resolve "^1.1.6" - -recursive-readdir@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" - integrity sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg== - dependencies: - minimatch "3.0.4" - -regenerate-unicode-properties@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56" - integrity sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw== - dependencies: - regenerate "^1.4.2" - -regenerate-unicode-properties@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz#54d09c7115e1f53dc2314a974b32c1c344efe326" - integrity sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA== - dependencies: - regenerate "^1.4.2" - -regenerate@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" - integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== - -regenerator-runtime@^0.13.4: - version "0.13.9" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" - integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== - -regenerator-transform@^0.14.2: - version "0.14.5" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" - integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== + "use-composed-ref" "^1.0.0" + "use-latest" "^1.0.0" + +"react@*", "react@^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", "react@^15.0.2 || ^16.0.0 || ^17.0.0", "react@^16.10.2", "react@^16.13.1", "react@^16.13.1 || ^17.0.0", "react@^16.14.0", "react@^16.3.0 || ^17.0.0", "react@^16.3.1", "react@^16.8.0 || ^17.0.0", "react@^16.8.4 || ^17.0.0", "react@^17.0.0 || ^16.3.0 || ^15.5.4", "react@>= 16.8.0 < 18.0.0", "react@>=0.14.9", "react@>=15", "react@>=16.3.0": + "integrity" "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==" + "resolved" "https://registry.npmjs.org/react/-/react-16.14.0.tgz" + "version" "16.14.0" + dependencies: + "loose-envify" "^1.1.0" + "object-assign" "^4.1.1" + "prop-types" "^15.6.2" + +"readable-stream@^2.0.1": + "integrity" "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==" + "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz" + "version" "2.3.7" + dependencies: + "core-util-is" "~1.0.0" + "inherits" "~2.0.3" + "isarray" "~1.0.0" + "process-nextick-args" "~2.0.0" + "safe-buffer" "~5.1.1" + "string_decoder" "~1.1.1" + "util-deprecate" "~1.0.1" + +"readable-stream@^3.0.6", "readable-stream@^3.1.1": + "integrity" "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==" + "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz" + "version" "3.6.0" + dependencies: + "inherits" "^2.0.3" + "string_decoder" "^1.1.1" + "util-deprecate" "^1.0.1" + +"readdirp@~3.6.0": + "integrity" "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==" + "resolved" "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" + "version" "3.6.0" + dependencies: + "picomatch" "^2.2.1" + +"reading-time@^1.5.0": + "integrity" "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==" + "resolved" "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz" + "version" "1.5.0" + +"rechoir@^0.6.2": + "integrity" "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=" + "resolved" "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz" + "version" "0.6.2" + dependencies: + "resolve" "^1.1.6" + +"recursive-readdir@^2.2.2": + "integrity" "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==" + "resolved" "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz" + "version" "2.2.2" + dependencies: + "minimatch" "3.0.4" + +"regenerate-unicode-properties@^10.0.1": + "integrity" "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==" + "resolved" "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz" + "version" "10.0.1" + dependencies: + "regenerate" "^1.4.2" + +"regenerate-unicode-properties@^9.0.0": + "integrity" "sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==" + "resolved" "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz" + "version" "9.0.0" + dependencies: + "regenerate" "^1.4.2" + +"regenerate@^1.4.2": + "integrity" "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + "resolved" "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" + "version" "1.4.2" + +"regenerator-runtime@^0.13.4": + "integrity" "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "resolved" "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz" + "version" "0.13.9" + +"regenerator-transform@^0.14.2": + "integrity" "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==" + "resolved" "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz" + "version" "0.14.5" dependencies: "@babel/runtime" "^7.8.4" -regexp.prototype.flags@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz#b3f4c0059af9e47eca9f3f660e51d81307e72307" - integrity sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -regexpu-core@^4.5.4: - version "4.8.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.8.0.tgz#e5605ba361b67b1718478501327502f4479a98f0" - integrity sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg== - dependencies: - regenerate "^1.4.2" - regenerate-unicode-properties "^9.0.0" - regjsgen "^0.5.2" - regjsparser "^0.7.0" - unicode-match-property-ecmascript "^2.0.0" - unicode-match-property-value-ecmascript "^2.0.0" - -regexpu-core@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.0.1.tgz#c531122a7840de743dcf9c83e923b5560323ced3" - integrity sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw== - dependencies: - regenerate "^1.4.2" - regenerate-unicode-properties "^10.0.1" - regjsgen "^0.6.0" - regjsparser "^0.8.2" - unicode-match-property-ecmascript "^2.0.0" - unicode-match-property-value-ecmascript "^2.0.0" - -registry-auth-token@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" - integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== - dependencies: - rc "^1.2.8" - -registry-url@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" - integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== - dependencies: - rc "^1.2.8" - -regjsgen@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" - integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== - -regjsgen@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.6.0.tgz#83414c5354afd7d6627b16af5f10f41c4e71808d" - integrity sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA== - -regjsparser@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.7.0.tgz#a6b667b54c885e18b52554cb4960ef71187e9968" - integrity sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ== - dependencies: - jsesc "~0.5.0" - -regjsparser@^0.8.2: - version "0.8.4" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.8.4.tgz#8a14285ffcc5de78c5b95d62bbf413b6bc132d5f" - integrity sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA== - dependencies: - jsesc "~0.5.0" - -rehype-parse@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-6.0.2.tgz#aeb3fdd68085f9f796f1d3137ae2b85a98406964" - integrity sha512-0S3CpvpTAgGmnz8kiCyFLGuW5yA4OQhyNTm/nwPopZ7+PI11WnGl1TTWTGv/2hPEe/g2jRLlhVVSsoDH8waRug== - dependencies: - hast-util-from-parse5 "^5.0.0" - parse5 "^5.0.0" - xtend "^4.0.0" - -relateurl@^0.2.7: - version "0.2.7" - resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" - integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= - -remark-admonitions@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/remark-admonitions/-/remark-admonitions-1.2.1.tgz#87caa1a442aa7b4c0cafa04798ed58a342307870" - integrity sha512-Ji6p68VDvD+H1oS95Fdx9Ar5WA2wcDA4kwrrhVU7fGctC6+d3uiMICu7w7/2Xld+lnU7/gi+432+rRbup5S8ow== - dependencies: - rehype-parse "^6.0.2" - unified "^8.4.2" - unist-util-visit "^2.0.1" - -remark-emoji@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/remark-emoji/-/remark-emoji-2.2.0.tgz#1c702090a1525da5b80e15a8f963ef2c8236cac7" - integrity sha512-P3cj9s5ggsUvWw5fS2uzCHJMGuXYRb0NnZqYlNecewXt8QBU9n5vW3DUUKOhepS8F9CwdMx9B8a3i7pqFWAI5w== - dependencies: - emoticon "^3.2.0" - node-emoji "^1.10.0" - unist-util-visit "^2.0.3" - -remark-footnotes@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/remark-footnotes/-/remark-footnotes-2.0.0.tgz#9001c4c2ffebba55695d2dd80ffb8b82f7e6303f" - integrity sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ== - -remark-mdx-remove-exports@^1.6.22: - version "1.6.22" - resolved "https://registry.yarnpkg.com/remark-mdx-remove-exports/-/remark-mdx-remove-exports-1.6.22.tgz#9e34f3d02c9c54b02ca0a1fde946449338d06ecb" - integrity sha512-7g2uiTmTGfz5QyVb+toeX25frbk1Y6yd03RXGPtqx0+DVh86Gb7MkNYbk7H2X27zdZ3CQv1W/JqlFO0Oo8IxVA== - dependencies: - unist-util-remove "2.0.0" - -remark-mdx-remove-imports@^1.6.22: - version "1.6.22" - resolved "https://registry.yarnpkg.com/remark-mdx-remove-imports/-/remark-mdx-remove-imports-1.6.22.tgz#79f711c95359cff437a120d1fbdc1326ec455826" - integrity sha512-lmjAXD8Ltw0TsvBzb45S+Dxx7LTJAtDaMneMAv8LAUIPEyYoKkmGbmVsiF0/pY6mhM1Q16swCmu1TN+ie/vn/A== - dependencies: - unist-util-remove "2.0.0" - -remark-mdx@1.6.22: - version "1.6.22" - resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-1.6.22.tgz#06a8dab07dcfdd57f3373af7f86bd0e992108bbd" - integrity sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ== +"regexp.prototype.flags@^1.2.0": + "integrity" "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==" + "resolved" "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz" + "version" "1.4.1" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.3" + +"regexpu-core@^4.5.4": + "integrity" "sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg==" + "resolved" "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz" + "version" "4.8.0" + dependencies: + "regenerate" "^1.4.2" + "regenerate-unicode-properties" "^9.0.0" + "regjsgen" "^0.5.2" + "regjsparser" "^0.7.0" + "unicode-match-property-ecmascript" "^2.0.0" + "unicode-match-property-value-ecmascript" "^2.0.0" + +"regexpu-core@^5.0.1": + "integrity" "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==" + "resolved" "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "regenerate" "^1.4.2" + "regenerate-unicode-properties" "^10.0.1" + "regjsgen" "^0.6.0" + "regjsparser" "^0.8.2" + "unicode-match-property-ecmascript" "^2.0.0" + "unicode-match-property-value-ecmascript" "^2.0.0" + +"registry-auth-token@^4.0.0": + "integrity" "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==" + "resolved" "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz" + "version" "4.2.1" + dependencies: + "rc" "^1.2.8" + +"registry-url@^5.0.0": + "integrity" "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==" + "resolved" "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "rc" "^1.2.8" + +"regjsgen@^0.5.2": + "integrity" "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==" + "resolved" "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz" + "version" "0.5.2" + +"regjsgen@^0.6.0": + "integrity" "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==" + "resolved" "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz" + "version" "0.6.0" + +"regjsparser@^0.7.0": + "integrity" "sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ==" + "resolved" "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz" + "version" "0.7.0" + dependencies: + "jsesc" "~0.5.0" + +"regjsparser@^0.8.2": + "integrity" "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==" + "resolved" "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz" + "version" "0.8.4" + dependencies: + "jsesc" "~0.5.0" + +"rehype-parse@^6.0.2": + "integrity" "sha512-0S3CpvpTAgGmnz8kiCyFLGuW5yA4OQhyNTm/nwPopZ7+PI11WnGl1TTWTGv/2hPEe/g2jRLlhVVSsoDH8waRug==" + "resolved" "https://registry.npmjs.org/rehype-parse/-/rehype-parse-6.0.2.tgz" + "version" "6.0.2" + dependencies: + "hast-util-from-parse5" "^5.0.0" + "parse5" "^5.0.0" + "xtend" "^4.0.0" + +"relateurl@^0.2.7": + "integrity" "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=" + "resolved" "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz" + "version" "0.2.7" + +"remark-admonitions@^1.2.1": + "integrity" "sha512-Ji6p68VDvD+H1oS95Fdx9Ar5WA2wcDA4kwrrhVU7fGctC6+d3uiMICu7w7/2Xld+lnU7/gi+432+rRbup5S8ow==" + "resolved" "https://registry.npmjs.org/remark-admonitions/-/remark-admonitions-1.2.1.tgz" + "version" "1.2.1" + dependencies: + "rehype-parse" "^6.0.2" + "unified" "^8.4.2" + "unist-util-visit" "^2.0.1" + +"remark-emoji@^2.1.0": + "integrity" "sha512-P3cj9s5ggsUvWw5fS2uzCHJMGuXYRb0NnZqYlNecewXt8QBU9n5vW3DUUKOhepS8F9CwdMx9B8a3i7pqFWAI5w==" + "resolved" "https://registry.npmjs.org/remark-emoji/-/remark-emoji-2.2.0.tgz" + "version" "2.2.0" + dependencies: + "emoticon" "^3.2.0" + "node-emoji" "^1.10.0" + "unist-util-visit" "^2.0.3" + +"remark-footnotes@2.0.0": + "integrity" "sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ==" + "resolved" "https://registry.npmjs.org/remark-footnotes/-/remark-footnotes-2.0.0.tgz" + "version" "2.0.0" + +"remark-mdx-remove-exports@^1.6.22": + "integrity" "sha512-7g2uiTmTGfz5QyVb+toeX25frbk1Y6yd03RXGPtqx0+DVh86Gb7MkNYbk7H2X27zdZ3CQv1W/JqlFO0Oo8IxVA==" + "resolved" "https://registry.npmjs.org/remark-mdx-remove-exports/-/remark-mdx-remove-exports-1.6.22.tgz" + "version" "1.6.22" + dependencies: + "unist-util-remove" "2.0.0" + +"remark-mdx-remove-imports@^1.6.22": + "integrity" "sha512-lmjAXD8Ltw0TsvBzb45S+Dxx7LTJAtDaMneMAv8LAUIPEyYoKkmGbmVsiF0/pY6mhM1Q16swCmu1TN+ie/vn/A==" + "resolved" "https://registry.npmjs.org/remark-mdx-remove-imports/-/remark-mdx-remove-imports-1.6.22.tgz" + "version" "1.6.22" + dependencies: + "unist-util-remove" "2.0.0" + +"remark-mdx@1.6.22": + "integrity" "sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ==" + "resolved" "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz" + "version" "1.6.22" dependencies: "@babel/core" "7.12.9" "@babel/helper-plugin-utils" "7.10.4" "@babel/plugin-proposal-object-rest-spread" "7.12.1" "@babel/plugin-syntax-jsx" "7.12.1" "@mdx-js/util" "1.6.22" - is-alphabetical "1.0.4" - remark-parse "8.0.3" - unified "9.2.0" - -remark-parse@8.0.3: - version "8.0.3" - resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-8.0.3.tgz#9c62aa3b35b79a486454c690472906075f40c7e1" - integrity sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q== - dependencies: - ccount "^1.0.0" - collapse-white-space "^1.0.2" - is-alphabetical "^1.0.0" - is-decimal "^1.0.0" - is-whitespace-character "^1.0.0" - is-word-character "^1.0.0" - markdown-escapes "^1.0.0" - parse-entities "^2.0.0" - repeat-string "^1.5.4" - state-toggle "^1.0.0" - trim "0.0.1" - trim-trailing-lines "^1.0.0" - unherit "^1.0.4" - unist-util-remove-position "^2.0.0" - vfile-location "^3.0.0" - xtend "^4.0.1" - -remark-squeeze-paragraphs@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz#76eb0e085295131c84748c8e43810159c5653ead" - integrity sha512-8qRqmL9F4nuLPIgl92XUuxI3pFxize+F1H0e/W3llTk0UsjJaj01+RrirkMw7P21RKe4X6goQhYRSvNWX+70Rw== - dependencies: - mdast-squeeze-paragraphs "^4.0.0" - -remarkable-admonitions@^0.2.1: - version "0.2.2" - resolved "https://registry.yarnpkg.com/remarkable-admonitions/-/remarkable-admonitions-0.2.2.tgz#8765f9ec66be4f4c651a4e1cfb559dd7f920819c" - integrity sha512-CcMTEcLYmJLXX3IVMk4LyW4oFD2NQxh5FeLzn4k89TAPpyWIeVix/B/g/gDbZAUpCNY9l6heovR5NNIktf8X5A== - -renderkid@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" - integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg== - dependencies: - css-select "^4.1.3" - dom-converter "^0.2.0" - htmlparser2 "^6.1.0" - lodash "^4.17.21" - strip-ansi "^6.0.1" - -repeat-string@^1.5.4: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + "is-alphabetical" "1.0.4" + "remark-parse" "8.0.3" + "unified" "9.2.0" + +"remark-parse@8.0.3": + "integrity" "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==" + "resolved" "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz" + "version" "8.0.3" + dependencies: + "ccount" "^1.0.0" + "collapse-white-space" "^1.0.2" + "is-alphabetical" "^1.0.0" + "is-decimal" "^1.0.0" + "is-whitespace-character" "^1.0.0" + "is-word-character" "^1.0.0" + "markdown-escapes" "^1.0.0" + "parse-entities" "^2.0.0" + "repeat-string" "^1.5.4" + "state-toggle" "^1.0.0" + "trim" "0.0.1" + "trim-trailing-lines" "^1.0.0" + "unherit" "^1.0.4" + "unist-util-remove-position" "^2.0.0" + "vfile-location" "^3.0.0" + "xtend" "^4.0.1" + +"remark-squeeze-paragraphs@4.0.0": + "integrity" "sha512-8qRqmL9F4nuLPIgl92XUuxI3pFxize+F1H0e/W3llTk0UsjJaj01+RrirkMw7P21RKe4X6goQhYRSvNWX+70Rw==" + "resolved" "https://registry.npmjs.org/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "mdast-squeeze-paragraphs" "^4.0.0" + +"remarkable-admonitions@^0.2.1": + "integrity" "sha512-CcMTEcLYmJLXX3IVMk4LyW4oFD2NQxh5FeLzn4k89TAPpyWIeVix/B/g/gDbZAUpCNY9l6heovR5NNIktf8X5A==" + "resolved" "https://registry.npmjs.org/remarkable-admonitions/-/remarkable-admonitions-0.2.2.tgz" + "version" "0.2.2" + +"renderkid@^3.0.0": + "integrity" "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==" + "resolved" "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "css-select" "^4.1.3" + "dom-converter" "^0.2.0" + "htmlparser2" "^6.1.0" + "lodash" "^4.17.21" + "strip-ansi" "^6.0.1" + +"repeat-string@^1.5.4": + "integrity" "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + "resolved" "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" + "version" "1.6.1" + +"require-from-string@^2.0.2": + "integrity" "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + "resolved" "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" + "version" "2.0.2" "require-like@>= 0.1.1": - version "0.1.2" - resolved "https://registry.yarnpkg.com/require-like/-/require-like-0.1.2.tgz#ad6f30c13becd797010c468afa775c0c0a6b47fa" - integrity sha1-rW8wwTvs15cBDEaK+ndcDAprR/o= - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-pathname@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" - integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== - -resolve@^1.1.6, resolve@^1.14.2, resolve@^1.3.2: - version "1.22.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" - integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== - dependencies: - is-core-module "^2.8.1" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -responselike@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= - dependencies: - lowercase-keys "^1.0.0" - -retry@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" - integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -rtl-detect@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/rtl-detect/-/rtl-detect-1.0.4.tgz#40ae0ea7302a150b96bc75af7d749607392ecac6" - integrity sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ== - -rtlcss@^3.3.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-3.5.0.tgz#c9eb91269827a102bac7ae3115dd5d049de636c3" - integrity sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A== - dependencies: - find-up "^5.0.0" - picocolors "^1.0.0" - postcss "^8.3.11" - strip-json-comments "^3.1.1" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -rxjs@^7.5.4: - version "7.5.4" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.4.tgz#3d6bd407e6b7ce9a123e76b1e770dc5761aa368d" - integrity sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ== - dependencies: - tslib "^2.1.0" - -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + "integrity" "sha1-rW8wwTvs15cBDEaK+ndcDAprR/o=" + "resolved" "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz" + "version" "0.1.2" + +"requires-port@^1.0.0": + "integrity" "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + "resolved" "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" + "version" "1.0.0" + +"resolve-from@^4.0.0": + "integrity" "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + "resolved" "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" + "version" "4.0.0" + +"resolve-pathname@^3.0.0": + "integrity" "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + "resolved" "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz" + "version" "3.0.0" + +"resolve@^1.1.6", "resolve@^1.14.2", "resolve@^1.3.2": + "integrity" "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==" + "resolved" "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz" + "version" "1.22.0" + dependencies: + "is-core-module" "^2.8.1" + "path-parse" "^1.0.7" + "supports-preserve-symlinks-flag" "^1.0.0" + +"responselike@^1.0.2": + "integrity" "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=" + "resolved" "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "lowercase-keys" "^1.0.0" + +"retry@^0.13.1": + "integrity" "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" + "resolved" "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz" + "version" "0.13.1" + +"reusify@^1.0.4": + "integrity" "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + "resolved" "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" + "version" "1.0.4" + +"rimraf@^3.0.2": + "integrity" "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==" + "resolved" "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "glob" "^7.1.3" + +"rtl-detect@^1.0.4": + "integrity" "sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ==" + "resolved" "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.0.4.tgz" + "version" "1.0.4" + +"rtlcss@^3.3.0": + "integrity" "sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A==" + "resolved" "https://registry.npmjs.org/rtlcss/-/rtlcss-3.5.0.tgz" + "version" "3.5.0" + dependencies: + "find-up" "^5.0.0" + "picocolors" "^1.0.0" + "postcss" "^8.3.11" + "strip-json-comments" "^3.1.1" + +"run-parallel@^1.1.9": + "integrity" "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==" + "resolved" "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "queue-microtask" "^1.2.2" + +"rxjs@^7.5.4": + "integrity" "sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ==" + "resolved" "https://registry.npmjs.org/rxjs/-/rxjs-7.5.4.tgz" + "version" "7.5.4" + dependencies: + "tslib" "^2.1.0" + +"safe-buffer@^5.0.1", "safe-buffer@^5.1.0", "safe-buffer@>=5.1.0", "safe-buffer@~5.2.0", "safe-buffer@5.2.1": + "integrity" "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + "version" "5.2.1" + +"safe-buffer@~5.1.0", "safe-buffer@~5.1.1": + "integrity" "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + "version" "5.1.2" + +"safe-buffer@5.1.2": + "integrity" "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + "version" "5.1.2" "safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + "integrity" "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "resolved" "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" + "version" "2.1.2" -sax@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== +"sax@^1.2.4": + "integrity" "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + "resolved" "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz" + "version" "1.2.4" -scheduler@^0.19.1: - version "0.19.1" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" - integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA== +"scheduler@^0.19.1": + "integrity" "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==" + "resolved" "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz" + "version" "0.19.1" dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" + "loose-envify" "^1.1.0" + "object-assign" "^4.1.1" -schema-utils@2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" - integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== - dependencies: - "@types/json-schema" "^7.0.4" - ajv "^6.12.2" - ajv-keywords "^3.4.1" - -schema-utils@^2.6.5: - version "2.7.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" - integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== +"schema-utils@^2.6.5": + "integrity" "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==" + "resolved" "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz" + "version" "2.7.1" dependencies: "@types/json-schema" "^7.0.5" - ajv "^6.12.4" - ajv-keywords "^3.5.2" + "ajv" "^6.12.4" + "ajv-keywords" "^3.5.2" -schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" - integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== +"schema-utils@^3.0.0", "schema-utils@^3.1.0", "schema-utils@^3.1.1": + "integrity" "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==" + "resolved" "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz" + "version" "3.1.1" dependencies: "@types/json-schema" "^7.0.8" - ajv "^6.12.5" - ajv-keywords "^3.5.2" + "ajv" "^6.12.5" + "ajv-keywords" "^3.5.2" -schema-utils@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" - integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== +"schema-utils@^4.0.0": + "integrity" "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==" + "resolved" "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz" + "version" "4.0.0" dependencies: "@types/json-schema" "^7.0.9" - ajv "^8.8.0" - ajv-formats "^2.1.1" - ajv-keywords "^5.0.0" - -section-matter@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167" - integrity sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA== - dependencies: - extend-shallow "^2.0.1" - kind-of "^6.0.0" - -select-hose@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" - integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= - -selfsigned@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.0.0.tgz#e927cd5377cbb0a1075302cff8df1042cc2bce5b" - integrity sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ== - dependencies: - node-forge "^1.2.0" - -semver-diff@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" - integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg== - dependencies: - semver "^6.3.0" - -semver@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" - integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== - -semver@^5.4.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: - version "7.3.5" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== - dependencies: - lru-cache "^6.0.0" - -send@0.17.2: - version "0.17.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820" - integrity sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "1.8.1" - mime "1.6.0" - ms "2.1.3" - on-finished "~2.3.0" - range-parser "~1.2.1" - statuses "~1.5.0" - -serialize-javascript@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== - dependencies: - randombytes "^2.1.0" - -serve-handler@^6.1.3: - version "6.1.3" - resolved "https://registry.yarnpkg.com/serve-handler/-/serve-handler-6.1.3.tgz#1bf8c5ae138712af55c758477533b9117f6435e8" - integrity sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w== - dependencies: - bytes "3.0.0" - content-disposition "0.5.2" - fast-url-parser "1.1.3" - mime-types "2.1.18" - minimatch "3.0.4" - path-is-inside "1.0.2" - path-to-regexp "2.2.1" - range-parser "1.2.0" - -serve-index@^1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" - integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= - dependencies: - accepts "~1.3.4" - batch "0.6.1" - debug "2.6.9" - escape-html "~1.0.3" - http-errors "~1.6.2" - mime-types "~2.1.17" - parseurl "~1.3.2" - -serve-static@1.14.2: - version "1.14.2" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa" - integrity sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.2" - -setimmediate@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= - -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -shallow-clone@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" - integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== - dependencies: - kind-of "^6.0.2" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -shell-quote@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" - integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== - -shelljs@^0.8.4: - version "0.8.5" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" - integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - -signal-exit@^3.0.2, signal-exit@^3.0.3: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -sirv@^1.0.7: - version "1.0.19" - resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49" - integrity sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ== + "ajv" "^8.8.0" + "ajv-formats" "^2.1.1" + "ajv-keywords" "^5.0.0" + +"schema-utils@2.7.0": + "integrity" "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==" + "resolved" "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz" + "version" "2.7.0" + dependencies: + "@types/json-schema" "^7.0.4" + "ajv" "^6.12.2" + "ajv-keywords" "^3.4.1" + +"section-matter@^1.0.0": + "integrity" "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==" + "resolved" "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "extend-shallow" "^2.0.1" + "kind-of" "^6.0.0" + +"select-hose@^2.0.0": + "integrity" "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" + "resolved" "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" + "version" "2.0.0" + +"selfsigned@^2.0.0": + "integrity" "sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ==" + "resolved" "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "node-forge" "^1.2.0" + +"semver-diff@^3.1.1": + "integrity" "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==" + "resolved" "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz" + "version" "3.1.1" + dependencies: + "semver" "^6.3.0" + +"semver@^5.4.1": + "integrity" "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "resolved" "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" + "version" "5.7.1" + +"semver@^6.0.0", "semver@^6.1.1", "semver@^6.1.2", "semver@^6.2.0", "semver@^6.3.0": + "integrity" "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "resolved" "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" + "version" "6.3.0" + +"semver@^7.3.2": + "integrity" "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==" + "resolved" "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" + "version" "7.3.5" + dependencies: + "lru-cache" "^6.0.0" + +"semver@^7.3.4": + "integrity" "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==" + "resolved" "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" + "version" "7.3.5" + dependencies: + "lru-cache" "^6.0.0" + +"semver@^7.3.5": + "integrity" "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==" + "resolved" "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" + "version" "7.3.5" + dependencies: + "lru-cache" "^6.0.0" + +"semver@7.0.0": + "integrity" "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" + "resolved" "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz" + "version" "7.0.0" + +"send@0.17.2": + "integrity" "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==" + "resolved" "https://registry.npmjs.org/send/-/send-0.17.2.tgz" + "version" "0.17.2" + dependencies: + "debug" "2.6.9" + "depd" "~1.1.2" + "destroy" "~1.0.4" + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "etag" "~1.8.1" + "fresh" "0.5.2" + "http-errors" "1.8.1" + "mime" "1.6.0" + "ms" "2.1.3" + "on-finished" "~2.3.0" + "range-parser" "~1.2.1" + "statuses" "~1.5.0" + +"serialize-javascript@^6.0.0": + "integrity" "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==" + "resolved" "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "randombytes" "^2.1.0" + +"serve-handler@^6.1.3": + "integrity" "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==" + "resolved" "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz" + "version" "6.1.3" + dependencies: + "bytes" "3.0.0" + "content-disposition" "0.5.2" + "fast-url-parser" "1.1.3" + "mime-types" "2.1.18" + "minimatch" "3.0.4" + "path-is-inside" "1.0.2" + "path-to-regexp" "2.2.1" + "range-parser" "1.2.0" + +"serve-index@^1.9.1": + "integrity" "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=" + "resolved" "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz" + "version" "1.9.1" + dependencies: + "accepts" "~1.3.4" + "batch" "0.6.1" + "debug" "2.6.9" + "escape-html" "~1.0.3" + "http-errors" "~1.6.2" + "mime-types" "~2.1.17" + "parseurl" "~1.3.2" + +"serve-static@1.14.2": + "integrity" "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==" + "resolved" "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz" + "version" "1.14.2" + dependencies: + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "parseurl" "~1.3.3" + "send" "0.17.2" + +"setimmediate@^1.0.5": + "integrity" "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + "resolved" "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" + "version" "1.0.5" + +"setprototypeof@1.1.0": + "integrity" "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + "resolved" "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz" + "version" "1.1.0" + +"setprototypeof@1.2.0": + "integrity" "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "resolved" "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" + "version" "1.2.0" + +"shallow-clone@^3.0.0": + "integrity" "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==" + "resolved" "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "kind-of" "^6.0.2" + +"shebang-command@^2.0.0": + "integrity" "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==" + "resolved" "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "shebang-regex" "^3.0.0" + +"shebang-regex@^3.0.0": + "integrity" "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + "resolved" "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" + "version" "3.0.0" + +"shell-quote@^1.7.3": + "integrity" "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==" + "resolved" "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz" + "version" "1.7.3" + +"shelljs@^0.8.4": + "integrity" "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==" + "resolved" "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz" + "version" "0.8.5" + dependencies: + "glob" "^7.0.0" + "interpret" "^1.0.0" + "rechoir" "^0.6.2" + +"signal-exit@^3.0.2", "signal-exit@^3.0.3": + "integrity" "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + "resolved" "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" + "version" "3.0.7" + +"sirv@^1.0.7": + "integrity" "sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==" + "resolved" "https://registry.npmjs.org/sirv/-/sirv-1.0.19.tgz" + "version" "1.0.19" dependencies: "@polka/url" "^1.0.0-next.20" - mrmime "^1.0.0" - totalist "^1.0.0" + "mrmime" "^1.0.0" + "totalist" "^1.0.0" -sisteransi@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== +"sisteransi@^1.0.5": + "integrity" "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + "resolved" "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" + "version" "1.0.5" -sitemap@^7.0.0: - version "7.1.1" - resolved "https://registry.yarnpkg.com/sitemap/-/sitemap-7.1.1.tgz#eeed9ad6d95499161a3eadc60f8c6dce4bea2bef" - integrity sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg== +"sitemap@^7.0.0": + "integrity" "sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg==" + "resolved" "https://registry.npmjs.org/sitemap/-/sitemap-7.1.1.tgz" + "version" "7.1.1" dependencies: "@types/node" "^17.0.5" "@types/sax" "^1.2.1" - arg "^5.0.0" - sax "^1.2.4" - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slash@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" - integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== - -sockjs@^0.3.21: - version "0.3.24" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" - integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== - dependencies: - faye-websocket "^0.11.3" - uuid "^8.3.2" - websocket-driver "^0.7.4" - -sort-css-media-queries@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/sort-css-media-queries/-/sort-css-media-queries-2.0.4.tgz#b2badfa519cb4a938acbc6d3aaa913d4949dc908" - integrity sha512-PAIsEK/XupCQwitjv7XxoMvYhT7EAfyzI3hsy/MyDgTvc+Ft55ctdkctJLOy6cQejaIC+zjpUL4djFVm2ivOOw== - -source-list-map@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== - -source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== - -source-map-support@~0.5.20: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.5.0: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -sourcemap-codec@^1.4.4: - version "1.4.8" - resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" - integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== - -space-separated-tokens@^1.0.0: - version "1.1.5" - resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" - integrity sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA== - -spdy-transport@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" - integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== - dependencies: - debug "^4.1.0" - detect-node "^2.0.4" - hpack.js "^2.1.6" - obuf "^1.1.2" - readable-stream "^3.0.6" - wbuf "^1.7.3" - -spdy@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" - integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== - dependencies: - debug "^4.1.0" - handle-thing "^2.0.0" - http-deceiver "^1.2.7" - select-hose "^2.0.0" - spdy-transport "^3.0.0" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -stable@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== - -state-toggle@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe" - integrity sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ== - -"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -std-env@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.0.1.tgz#bc4cbc0e438610197e34c2d79c3df30b491f5182" - integrity sha512-mC1Ps9l77/97qeOZc+HrOL7TIaOboHqMZ24dGVQrlxFcpPpfCHpH+qfUT7Dz+6mlG8+JPA1KfBQo19iC/+Ngcw== - -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.2: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -stringify-object@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" - integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== - dependencies: - get-own-enumerable-property-symbols "^3.0.0" - is-obj "^1.0.1" - is-regexp "^1.0.0" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" - integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== - dependencies: - ansi-regex "^6.0.1" - -strip-bom-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" - integrity sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI= - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -style-to-object@0.3.0, style-to-object@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.3.0.tgz#b1b790d205991cc783801967214979ee19a76e46" - integrity sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA== - dependencies: - inline-style-parser "0.1.1" - -stylehacks@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.0.3.tgz#2ef3de567bfa2be716d29a93bf3d208c133e8d04" - integrity sha512-ENcUdpf4yO0E1rubu8rkxI+JGQk4CgjchynZ4bDBJDfqdy+uhTRSWb8/F3Jtu+Bw5MW45Po3/aQGeIyyxgQtxg== - dependencies: - browserslist "^4.16.6" - postcss-selector-parser "^6.0.4" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" + "arg" "^5.0.0" + "sax" "^1.2.4" + +"slash@^3.0.0": + "integrity" "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + "resolved" "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" + "version" "3.0.0" + +"slash@^4.0.0": + "integrity" "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==" + "resolved" "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz" + "version" "4.0.0" + +"sockjs@^0.3.21": + "integrity" "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==" + "resolved" "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz" + "version" "0.3.24" + dependencies: + "faye-websocket" "^0.11.3" + "uuid" "^8.3.2" + "websocket-driver" "^0.7.4" + +"sort-css-media-queries@2.0.4": + "integrity" "sha512-PAIsEK/XupCQwitjv7XxoMvYhT7EAfyzI3hsy/MyDgTvc+Ft55ctdkctJLOy6cQejaIC+zjpUL4djFVm2ivOOw==" + "resolved" "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.0.4.tgz" + "version" "2.0.4" + +"source-list-map@^2.0.0": + "integrity" "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + "resolved" "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz" + "version" "2.0.1" + +"source-map-js@^1.0.2": + "integrity" "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" + "resolved" "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz" + "version" "1.0.2" + +"source-map-support@~0.5.20": + "integrity" "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==" + "resolved" "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" + "version" "0.5.21" + dependencies: + "buffer-from" "^1.0.0" + "source-map" "^0.6.0" + +"source-map@^0.5.0": + "integrity" "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "resolved" "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" + "version" "0.5.7" + +"source-map@^0.6.0", "source-map@^0.6.1", "source-map@~0.6.0", "source-map@~0.6.1": + "integrity" "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "resolved" "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + "version" "0.6.1" + +"sourcemap-codec@^1.4.4": + "integrity" "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + "resolved" "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz" + "version" "1.4.8" + +"space-separated-tokens@^1.0.0": + "integrity" "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==" + "resolved" "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz" + "version" "1.1.5" + +"spdy-transport@^3.0.0": + "integrity" "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==" + "resolved" "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "debug" "^4.1.0" + "detect-node" "^2.0.4" + "hpack.js" "^2.1.6" + "obuf" "^1.1.2" + "readable-stream" "^3.0.6" + "wbuf" "^1.7.3" + +"spdy@^4.0.2": + "integrity" "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==" + "resolved" "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz" + "version" "4.0.2" + dependencies: + "debug" "^4.1.0" + "handle-thing" "^2.0.0" + "http-deceiver" "^1.2.7" + "select-hose" "^2.0.0" + "spdy-transport" "^3.0.0" + +"sprintf-js@~1.0.2": + "integrity" "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "resolved" "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" + "version" "1.0.3" + +"stable@^0.1.8": + "integrity" "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" + "resolved" "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz" + "version" "0.1.8" + +"state-toggle@^1.0.0": + "integrity" "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==" + "resolved" "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz" + "version" "1.0.3" + +"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", "statuses@~1.5.0": + "integrity" "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "resolved" "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" + "version" "1.5.0" + +"std-env@^3.0.1": + "integrity" "sha512-mC1Ps9l77/97qeOZc+HrOL7TIaOboHqMZ24dGVQrlxFcpPpfCHpH+qfUT7Dz+6mlG8+JPA1KfBQo19iC/+Ngcw==" + "resolved" "https://registry.npmjs.org/std-env/-/std-env-3.0.1.tgz" + "version" "3.0.1" + +"string_decoder@^1.1.1": + "integrity" "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==" + "resolved" "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + "version" "1.3.0" + dependencies: + "safe-buffer" "~5.2.0" + +"string_decoder@~1.1.1": + "integrity" "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==" + "resolved" "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "safe-buffer" "~5.1.0" + +"string-width@^4.0.0", "string-width@^4.1.0", "string-width@^4.2.2": + "integrity" "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==" + "resolved" "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + "version" "4.2.3" + dependencies: + "emoji-regex" "^8.0.0" + "is-fullwidth-code-point" "^3.0.0" + "strip-ansi" "^6.0.1" + +"stringify-object@^3.3.0": + "integrity" "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==" + "resolved" "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz" + "version" "3.3.0" + dependencies: + "get-own-enumerable-property-symbols" "^3.0.0" + "is-obj" "^1.0.1" + "is-regexp" "^1.0.0" + +"strip-ansi@^6.0.0", "strip-ansi@^6.0.1": + "integrity" "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==" + "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "ansi-regex" "^5.0.1" + +"strip-ansi@^7.0.0": + "integrity" "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==" + "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz" + "version" "7.0.1" + dependencies: + "ansi-regex" "^6.0.1" + +"strip-bom-string@^1.0.0": + "integrity" "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=" + "resolved" "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz" + "version" "1.0.0" + +"strip-final-newline@^2.0.0": + "integrity" "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" + "resolved" "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz" + "version" "2.0.0" + +"strip-json-comments@^3.1.1": + "integrity" "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" + "resolved" "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + "version" "3.1.1" + +"strip-json-comments@~2.0.1": + "integrity" "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + "resolved" "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" + "version" "2.0.1" + +"style-to-object@^0.3.0", "style-to-object@0.3.0": + "integrity" "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==" + "resolved" "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz" + "version" "0.3.0" + dependencies: + "inline-style-parser" "0.1.1" + +"stylehacks@^5.0.3": + "integrity" "sha512-ENcUdpf4yO0E1rubu8rkxI+JGQk4CgjchynZ4bDBJDfqdy+uhTRSWb8/F3Jtu+Bw5MW45Po3/aQGeIyyxgQtxg==" + "resolved" "https://registry.npmjs.org/stylehacks/-/stylehacks-5.0.3.tgz" + "version" "5.0.3" + dependencies: + "browserslist" "^4.16.6" + "postcss-selector-parser" "^6.0.4" + +"supports-color@^5.3.0": + "integrity" "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + "version" "5.5.0" + dependencies: + "has-flag" "^3.0.0" -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== +"supports-color@^7.1.0": + "integrity" "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + "version" "7.2.0" dependencies: - has-flag "^4.0.0" + "has-flag" "^4.0.0" -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== +"supports-color@^8.0.0": + "integrity" "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" + "version" "8.1.1" dependencies: - has-flag "^4.0.0" + "has-flag" "^4.0.0" -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +"supports-preserve-symlinks-flag@^1.0.0": + "integrity" "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + "resolved" "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" + "version" "1.0.0" -svg-parser@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" - integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== +"svg-parser@^2.0.2": + "integrity" "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + "resolved" "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz" + "version" "2.0.4" -svgo@^2.5.0, svgo@^2.7.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" - integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg== +"svgo@^2.5.0", "svgo@^2.7.0": + "integrity" "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==" + "resolved" "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz" + "version" "2.8.0" dependencies: "@trysound/sax" "0.2.0" - commander "^7.2.0" - css-select "^4.1.3" - css-tree "^1.1.3" - csso "^4.2.0" - picocolors "^1.0.0" - stable "^0.1.8" - -tapable@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" - integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== - -tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== - -terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.2.4: - version "5.3.1" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz#0320dcc270ad5372c1e8993fabbd927929773e54" - integrity sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g== - dependencies: - jest-worker "^27.4.5" - schema-utils "^3.1.1" - serialize-javascript "^6.0.0" - source-map "^0.6.1" - terser "^5.7.2" - -terser@^5.10.0, terser@^5.7.2: - version "5.14.2" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.14.2.tgz#9ac9f22b06994d736174f4091aa368db896f1c10" - integrity sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA== + "commander" "^7.2.0" + "css-select" "^4.1.3" + "css-tree" "^1.1.3" + "csso" "^4.2.0" + "picocolors" "^1.0.0" + "stable" "^0.1.8" + +"tapable@^1.0.0": + "integrity" "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" + "resolved" "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz" + "version" "1.1.3" + +"tapable@^2.0.0", "tapable@^2.1.1", "tapable@^2.2.0": + "integrity" "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" + "resolved" "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz" + "version" "2.2.1" + +"terser-webpack-plugin@^5.1.3", "terser-webpack-plugin@^5.2.4": + "integrity" "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==" + "resolved" "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz" + "version" "5.3.1" + dependencies: + "jest-worker" "^27.4.5" + "schema-utils" "^3.1.1" + "serialize-javascript" "^6.0.0" + "source-map" "^0.6.1" + "terser" "^5.7.2" + +"terser@^5.10.0", "terser@^5.7.2": + "integrity" "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==" + "resolved" "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz" + "version" "5.14.2" dependencies: "@jridgewell/source-map" "^0.3.2" - acorn "^8.5.0" - commander "^2.20.0" - source-map-support "~0.5.20" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - -thunky@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" - integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== - -timsort@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" - integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= - -tiny-invariant@^1.0.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.2.0.tgz#a1141f86b672a9148c72e978a19a73b9b94a15a9" - integrity sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg== - -tiny-warning@^1.0.0, tiny-warning@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" - integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -totalist@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" - integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= - -trim-trailing-lines@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz#bd4abbec7cc880462f10b2c8b5ce1d8d1ec7c2c0" - integrity sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ== - -trim@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" - integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= - -trough@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" - integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== - -tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - -ua-parser-js@^0.7.30: - version "0.7.33" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.33.tgz#1d04acb4ccef9293df6f70f2c3d22f3030d8b532" - integrity sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw== - -unherit@^1.0.4: - version "1.1.3" - resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.3.tgz#6c9b503f2b41b262330c80e91c8614abdaa69c22" - integrity sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ== - dependencies: - inherits "^2.0.0" - xtend "^4.0.0" - -unicode-canonical-property-names-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" - integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== - -unicode-match-property-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" - integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== - dependencies: - unicode-canonical-property-names-ecmascript "^2.0.0" - unicode-property-aliases-ecmascript "^2.0.0" - -unicode-match-property-value-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz#1a01aa57247c14c568b89775a54938788189a714" - integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw== - -unicode-property-aliases-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8" - integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ== - -unified@9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.0.tgz#67a62c627c40589edebbf60f53edfd4d822027f8" - integrity sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg== - dependencies: - bail "^1.0.0" - extend "^3.0.0" - is-buffer "^2.0.0" - is-plain-obj "^2.0.0" - trough "^1.0.0" - vfile "^4.0.0" - -unified@^8.4.2: - version "8.4.2" - resolved "https://registry.yarnpkg.com/unified/-/unified-8.4.2.tgz#13ad58b4a437faa2751a4a4c6a16f680c500fff1" - integrity sha512-JCrmN13jI4+h9UAyKEoGcDZV+i1E7BLFuG7OsaDvTXI5P0qhHX+vZO/kOhz9jn8HGENDKbwSeB0nVOg4gVStGA== - dependencies: - bail "^1.0.0" - extend "^3.0.0" - is-plain-obj "^2.0.0" - trough "^1.0.0" - vfile "^4.0.0" - -unique-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" - integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== - dependencies: - crypto-random-string "^2.0.0" - -unist-builder@2.0.3, unist-builder@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-2.0.3.tgz#77648711b5d86af0942f334397a33c5e91516436" - integrity sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw== - -unist-util-generated@^1.0.0: - version "1.1.6" - resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.6.tgz#5ab51f689e2992a472beb1b35f2ce7ff2f324d4b" - integrity sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg== - -unist-util-is@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797" - integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg== - -unist-util-position@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-3.1.0.tgz#1c42ee6301f8d52f47d14f62bbdb796571fa2d47" - integrity sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA== - -unist-util-remove-position@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz#5d19ca79fdba712301999b2b73553ca8f3b352cc" - integrity sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA== - dependencies: - unist-util-visit "^2.0.0" - -unist-util-remove@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unist-util-remove/-/unist-util-remove-2.0.0.tgz#32c2ad5578802f2ca62ab808173d505b2c898488" - integrity sha512-HwwWyNHKkeg/eXRnE11IpzY8JT55JNM1YCwwU9YNCnfzk6s8GhPXrVBBZWiwLeATJbI7euvoGSzcy9M29UeW3g== - dependencies: - unist-util-is "^4.0.0" - -unist-util-remove@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/unist-util-remove/-/unist-util-remove-2.1.0.tgz#b0b4738aa7ee445c402fda9328d604a02d010588" - integrity sha512-J8NYPyBm4baYLdCbjmf1bhPu45Cr1MWTm77qd9istEkzWpnN6O9tMsEbB2JhNnBCqGENRqEWomQ+He6au0B27Q== - dependencies: - unist-util-is "^4.0.0" - -unist-util-stringify-position@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da" - integrity sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g== + "acorn" "^8.5.0" + "commander" "^2.20.0" + "source-map-support" "~0.5.20" + +"text-table@^0.2.0": + "integrity" "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + "resolved" "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" + "version" "0.2.0" + +"thunky@^1.0.2": + "integrity" "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + "resolved" "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz" + "version" "1.1.0" + +"timsort@^0.3.0": + "integrity" "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" + "resolved" "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz" + "version" "0.3.0" + +"tiny-invariant@^1.0.2": + "integrity" "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==" + "resolved" "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz" + "version" "1.2.0" + +"tiny-warning@^1.0.0", "tiny-warning@^1.0.3": + "integrity" "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + "resolved" "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz" + "version" "1.0.3" + +"to-fast-properties@^2.0.0": + "integrity" "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + "resolved" "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" + "version" "2.0.0" + +"to-readable-stream@^1.0.0": + "integrity" "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" + "resolved" "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz" + "version" "1.0.0" + +"to-regex-range@^5.0.1": + "integrity" "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==" + "resolved" "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "is-number" "^7.0.0" + +"toidentifier@1.0.1": + "integrity" "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + "resolved" "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" + "version" "1.0.1" + +"totalist@^1.0.0": + "integrity" "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==" + "resolved" "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz" + "version" "1.1.0" + +"tr46@~0.0.3": + "integrity" "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + "resolved" "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" + "version" "0.0.3" + +"trim-trailing-lines@^1.0.0": + "integrity" "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==" + "resolved" "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz" + "version" "1.1.4" + +"trim@0.0.1": + "integrity" "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + "resolved" "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz" + "version" "0.0.1" + +"trough@^1.0.0": + "integrity" "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==" + "resolved" "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz" + "version" "1.0.5" + +"tslib@^2.0.3", "tslib@^2.1.0", "tslib@^2.2.0", "tslib@^2.3.1": + "integrity" "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "resolved" "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz" + "version" "2.3.1" + +"type-fest@^0.20.2": + "integrity" "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + "resolved" "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" + "version" "0.20.2" + +"type-is@~1.6.18": + "integrity" "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==" + "resolved" "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" + "version" "1.6.18" + dependencies: + "media-typer" "0.3.0" + "mime-types" "~2.1.24" + +"typedarray-to-buffer@^3.1.5": + "integrity" "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==" + "resolved" "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz" + "version" "3.1.5" + dependencies: + "is-typedarray" "^1.0.0" + +"typescript@>= 2.7": + "integrity" "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==" + "resolved" "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz" + "version" "4.9.5" + +"ua-parser-js@^0.7.30": + "integrity" "sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw==" + "resolved" "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.33.tgz" + "version" "0.7.33" + +"unherit@^1.0.4": + "integrity" "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==" + "resolved" "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz" + "version" "1.1.3" + dependencies: + "inherits" "^2.0.0" + "xtend" "^4.0.0" + +"unicode-canonical-property-names-ecmascript@^2.0.0": + "integrity" "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==" + "resolved" "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz" + "version" "2.0.0" + +"unicode-match-property-ecmascript@^2.0.0": + "integrity" "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==" + "resolved" "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "unicode-canonical-property-names-ecmascript" "^2.0.0" + "unicode-property-aliases-ecmascript" "^2.0.0" + +"unicode-match-property-value-ecmascript@^2.0.0": + "integrity" "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==" + "resolved" "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz" + "version" "2.0.0" + +"unicode-property-aliases-ecmascript@^2.0.0": + "integrity" "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==" + "resolved" "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz" + "version" "2.0.0" + +"unified@^8.4.2": + "integrity" "sha512-JCrmN13jI4+h9UAyKEoGcDZV+i1E7BLFuG7OsaDvTXI5P0qhHX+vZO/kOhz9jn8HGENDKbwSeB0nVOg4gVStGA==" + "resolved" "https://registry.npmjs.org/unified/-/unified-8.4.2.tgz" + "version" "8.4.2" + dependencies: + "bail" "^1.0.0" + "extend" "^3.0.0" + "is-plain-obj" "^2.0.0" + "trough" "^1.0.0" + "vfile" "^4.0.0" + +"unified@9.2.0": + "integrity" "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==" + "resolved" "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz" + "version" "9.2.0" + dependencies: + "bail" "^1.0.0" + "extend" "^3.0.0" + "is-buffer" "^2.0.0" + "is-plain-obj" "^2.0.0" + "trough" "^1.0.0" + "vfile" "^4.0.0" + +"unique-string@^2.0.0": + "integrity" "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==" + "resolved" "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "crypto-random-string" "^2.0.0" + +"unist-builder@^2.0.0", "unist-builder@2.0.3": + "integrity" "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==" + "resolved" "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz" + "version" "2.0.3" + +"unist-util-generated@^1.0.0": + "integrity" "sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==" + "resolved" "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz" + "version" "1.1.6" + +"unist-util-is@^4.0.0": + "integrity" "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==" + "resolved" "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz" + "version" "4.1.0" + +"unist-util-position@^3.0.0": + "integrity" "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA==" + "resolved" "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz" + "version" "3.1.0" + +"unist-util-remove-position@^2.0.0": + "integrity" "sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA==" + "resolved" "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "unist-util-visit" "^2.0.0" + +"unist-util-remove@^2.0.0": + "integrity" "sha512-J8NYPyBm4baYLdCbjmf1bhPu45Cr1MWTm77qd9istEkzWpnN6O9tMsEbB2JhNnBCqGENRqEWomQ+He6au0B27Q==" + "resolved" "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "unist-util-is" "^4.0.0" + +"unist-util-remove@2.0.0": + "integrity" "sha512-HwwWyNHKkeg/eXRnE11IpzY8JT55JNM1YCwwU9YNCnfzk6s8GhPXrVBBZWiwLeATJbI7euvoGSzcy9M29UeW3g==" + "resolved" "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "unist-util-is" "^4.0.0" + +"unist-util-stringify-position@^2.0.0": + "integrity" "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==" + "resolved" "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz" + "version" "2.0.3" dependencies: "@types/unist" "^2.0.2" -unist-util-visit-parents@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz#65a6ce698f78a6b0f56aa0e88f13801886cdaef6" - integrity sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg== +"unist-util-visit-parents@^3.0.0": + "integrity" "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==" + "resolved" "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz" + "version" "3.1.1" dependencies: "@types/unist" "^2.0.0" - unist-util-is "^4.0.0" + "unist-util-is" "^4.0.0" -unist-util-visit@2.0.3, unist-util-visit@^2.0.0, unist-util-visit@^2.0.1, unist-util-visit@^2.0.2, unist-util-visit@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" - integrity sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q== +"unist-util-visit@^2.0.0", "unist-util-visit@^2.0.1", "unist-util-visit@^2.0.2", "unist-util-visit@^2.0.3", "unist-util-visit@2.0.3": + "integrity" "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==" + "resolved" "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz" + "version" "2.0.3" dependencies: "@types/unist" "^2.0.0" - unist-util-is "^4.0.0" - unist-util-visit-parents "^3.0.0" - -universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - -update-notifier@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-5.1.0.tgz#4ab0d7c7f36a231dd7316cf7729313f0214d9ad9" - integrity sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw== - dependencies: - boxen "^5.0.0" - chalk "^4.1.0" - configstore "^5.0.1" - has-yarn "^2.1.0" - import-lazy "^2.1.0" - is-ci "^2.0.0" - is-installed-globally "^0.4.0" - is-npm "^5.0.0" - is-yarn-global "^0.3.0" - latest-version "^5.1.0" - pupa "^2.1.1" - semver "^7.3.4" - semver-diff "^3.1.1" - xdg-basedir "^4.0.0" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -url-loader@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2" - integrity sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA== - dependencies: - loader-utils "^2.0.0" - mime-types "^2.1.27" - schema-utils "^3.0.0" - -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= - dependencies: - prepend-http "^2.0.0" - -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -use-composed-ref@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/use-composed-ref/-/use-composed-ref-1.2.1.tgz#9bdcb5ccd894289105da2325e1210079f56bf849" - integrity sha512-6+X1FLlIcjvFMAeAD/hcxDT8tmyrWnbSPMU0EnxQuDLIxokuFzWliXBiYZuGIx+mrAMLBw0WFfCkaPw8ebzAhw== - -use-isomorphic-layout-effect@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz#7bb6589170cd2987a152042f9084f9effb75c225" - integrity sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ== - -use-latest@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/use-latest/-/use-latest-1.2.0.tgz#a44f6572b8288e0972ec411bdd0840ada366f232" - integrity sha512-d2TEuG6nSLKQLAfW3By8mKr8HurOlTkul0sOpxbClIv4SQ4iOd7BYr7VIzdbktUCnv7dua/60xzd8igMU6jmyw== - dependencies: - use-isomorphic-layout-effect "^1.0.0" - -util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -utila@~0.4: - version "0.4.0" - resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" - integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= - -utility-types@^3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.10.0.tgz#ea4148f9a741015f05ed74fd615e1d20e6bed82b" - integrity sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg== - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - -uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -value-equal@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" - integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== - -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - -vfile-location@^3.0.0, vfile-location@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-3.2.0.tgz#d8e41fbcbd406063669ebf6c33d56ae8721d0f3c" - integrity sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA== - -vfile-message@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.4.tgz#5b43b88171d409eae58477d13f23dd41d52c371a" - integrity sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ== + "unist-util-is" "^4.0.0" + "unist-util-visit-parents" "^3.0.0" + +"universalify@^2.0.0": + "integrity" "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + "resolved" "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz" + "version" "2.0.0" + +"unpipe@~1.0.0", "unpipe@1.0.0": + "integrity" "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "resolved" "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + "version" "1.0.0" + +"update-browserslist-db@^1.0.10": + "integrity" "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==" + "resolved" "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz" + "version" "1.0.10" + dependencies: + "escalade" "^3.1.1" + "picocolors" "^1.0.0" + +"update-notifier@^5.1.0": + "integrity" "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==" + "resolved" "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "boxen" "^5.0.0" + "chalk" "^4.1.0" + "configstore" "^5.0.1" + "has-yarn" "^2.1.0" + "import-lazy" "^2.1.0" + "is-ci" "^2.0.0" + "is-installed-globally" "^0.4.0" + "is-npm" "^5.0.0" + "is-yarn-global" "^0.3.0" + "latest-version" "^5.1.0" + "pupa" "^2.1.1" + "semver" "^7.3.4" + "semver-diff" "^3.1.1" + "xdg-basedir" "^4.0.0" + +"uri-js@^4.2.2": + "integrity" "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==" + "resolved" "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" + "version" "4.4.1" + dependencies: + "punycode" "^2.1.0" + +"url-loader@^4.1.1": + "integrity" "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==" + "resolved" "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz" + "version" "4.1.1" + dependencies: + "loader-utils" "^2.0.0" + "mime-types" "^2.1.27" + "schema-utils" "^3.0.0" + +"url-parse-lax@^3.0.0": + "integrity" "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=" + "resolved" "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "prepend-http" "^2.0.0" + +"url@^0.11.0": + "integrity" "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=" + "resolved" "https://registry.npmjs.org/url/-/url-0.11.0.tgz" + "version" "0.11.0" + dependencies: + "punycode" "1.3.2" + "querystring" "0.2.0" + +"use-composed-ref@^1.0.0": + "integrity" "sha512-6+X1FLlIcjvFMAeAD/hcxDT8tmyrWnbSPMU0EnxQuDLIxokuFzWliXBiYZuGIx+mrAMLBw0WFfCkaPw8ebzAhw==" + "resolved" "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.2.1.tgz" + "version" "1.2.1" + +"use-isomorphic-layout-effect@^1.0.0": + "integrity" "sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ==" + "resolved" "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz" + "version" "1.1.1" + +"use-latest@^1.0.0": + "integrity" "sha512-d2TEuG6nSLKQLAfW3By8mKr8HurOlTkul0sOpxbClIv4SQ4iOd7BYr7VIzdbktUCnv7dua/60xzd8igMU6jmyw==" + "resolved" "https://registry.npmjs.org/use-latest/-/use-latest-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "use-isomorphic-layout-effect" "^1.0.0" + +"util-deprecate@^1.0.1", "util-deprecate@^1.0.2", "util-deprecate@~1.0.1": + "integrity" "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "resolved" "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + "version" "1.0.2" + +"utila@~0.4": + "integrity" "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=" + "resolved" "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz" + "version" "0.4.0" + +"utility-types@^3.10.0": + "integrity" "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==" + "resolved" "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz" + "version" "3.10.0" + +"utils-merge@1.0.1": + "integrity" "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "resolved" "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" + "version" "1.0.1" + +"uuid@^8.3.2": + "integrity" "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + "resolved" "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" + "version" "8.3.2" + +"value-equal@^1.0.1": + "integrity" "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + "resolved" "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz" + "version" "1.0.1" + +"vary@~1.1.2": + "integrity" "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + "resolved" "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" + "version" "1.1.2" + +"vfile-location@^3.0.0", "vfile-location@^3.2.0": + "integrity" "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==" + "resolved" "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz" + "version" "3.2.0" + +"vfile-message@^2.0.0": + "integrity" "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==" + "resolved" "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz" + "version" "2.0.4" dependencies: "@types/unist" "^2.0.0" - unist-util-stringify-position "^2.0.0" + "unist-util-stringify-position" "^2.0.0" -vfile@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.2.1.tgz#03f1dce28fc625c625bc6514350fbdb00fa9e624" - integrity sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA== +"vfile@^4.0.0": + "integrity" "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==" + "resolved" "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz" + "version" "4.2.1" dependencies: "@types/unist" "^2.0.0" - is-buffer "^2.0.0" - unist-util-stringify-position "^2.0.0" - vfile-message "^2.0.0" - -wait-on@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-6.0.1.tgz#16bbc4d1e4ebdd41c5b4e63a2e16dbd1f4e5601e" - integrity sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw== - dependencies: - axios "^0.25.0" - joi "^17.6.0" - lodash "^4.17.21" - minimist "^1.2.5" - rxjs "^7.5.4" - -watchpack@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25" - integrity sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA== - dependencies: - glob-to-regexp "^0.4.1" - graceful-fs "^4.1.2" - -wbuf@^1.1.0, wbuf@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" - integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== - dependencies: - minimalistic-assert "^1.0.0" - -web-namespaces@^1.0.0, web-namespaces@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" - integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw== - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= - -webpack-bundle-analyzer@^4.4.2: - version "4.5.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz#1b0eea2947e73528754a6f9af3e91b2b6e0f79d5" - integrity sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ== - dependencies: - acorn "^8.0.4" - acorn-walk "^8.0.0" - chalk "^4.1.0" - commander "^7.2.0" - gzip-size "^6.0.0" - lodash "^4.17.20" - opener "^1.5.2" - sirv "^1.0.7" - ws "^7.3.1" - -webpack-dev-middleware@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz#aa079a8dedd7e58bfeab358a9af7dab304cee57f" - integrity sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg== - dependencies: - colorette "^2.0.10" - memfs "^3.4.1" - mime-types "^2.1.31" - range-parser "^1.2.1" - schema-utils "^4.0.0" - -webpack-dev-server@^4.7.1: - version "4.7.4" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz#d0ef7da78224578384e795ac228d8efb63d5f945" - integrity sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A== + "is-buffer" "^2.0.0" + "unist-util-stringify-position" "^2.0.0" + "vfile-message" "^2.0.0" + +"wait-on@^6.0.0": + "integrity" "sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw==" + "resolved" "https://registry.npmjs.org/wait-on/-/wait-on-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "axios" "^0.25.0" + "joi" "^17.6.0" + "lodash" "^4.17.21" + "minimist" "^1.2.5" + "rxjs" "^7.5.4" + +"watchpack@^2.3.1": + "integrity" "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==" + "resolved" "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz" + "version" "2.3.1" + dependencies: + "glob-to-regexp" "^0.4.1" + "graceful-fs" "^4.1.2" + +"wbuf@^1.1.0", "wbuf@^1.7.3": + "integrity" "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==" + "resolved" "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz" + "version" "1.7.3" + dependencies: + "minimalistic-assert" "^1.0.0" + +"web-namespaces@^1.0.0", "web-namespaces@^1.1.2": + "integrity" "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==" + "resolved" "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz" + "version" "1.1.4" + +"webidl-conversions@^3.0.0": + "integrity" "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + "resolved" "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" + "version" "3.0.1" + +"webpack-bundle-analyzer@^4.4.2": + "integrity" "sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ==" + "resolved" "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz" + "version" "4.5.0" + dependencies: + "acorn" "^8.0.4" + "acorn-walk" "^8.0.0" + "chalk" "^4.1.0" + "commander" "^7.2.0" + "gzip-size" "^6.0.0" + "lodash" "^4.17.20" + "opener" "^1.5.2" + "sirv" "^1.0.7" + "ws" "^7.3.1" + +"webpack-dev-middleware@^5.3.1": + "integrity" "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==" + "resolved" "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz" + "version" "5.3.1" + dependencies: + "colorette" "^2.0.10" + "memfs" "^3.4.1" + "mime-types" "^2.1.31" + "range-parser" "^1.2.1" + "schema-utils" "^4.0.0" + +"webpack-dev-server@^4.7.1": + "integrity" "sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A==" + "resolved" "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz" + "version" "4.7.4" dependencies: "@types/bonjour" "^3.5.9" "@types/connect-history-api-fallback" "^1.3.5" @@ -7519,212 +7582,217 @@ webpack-dev-server@^4.7.1: "@types/serve-index" "^1.9.1" "@types/sockjs" "^0.3.33" "@types/ws" "^8.2.2" - ansi-html-community "^0.0.8" - bonjour "^3.5.0" - chokidar "^3.5.3" - colorette "^2.0.10" - compression "^1.7.4" - connect-history-api-fallback "^1.6.0" - default-gateway "^6.0.3" - del "^6.0.0" - express "^4.17.1" - graceful-fs "^4.2.6" - html-entities "^2.3.2" - http-proxy-middleware "^2.0.0" - ipaddr.js "^2.0.1" - open "^8.0.9" - p-retry "^4.5.0" - portfinder "^1.0.28" - schema-utils "^4.0.0" - selfsigned "^2.0.0" - serve-index "^1.9.1" - sockjs "^0.3.21" - spdy "^4.0.2" - strip-ansi "^7.0.0" - webpack-dev-middleware "^5.3.1" - ws "^8.4.2" - -webpack-merge@^5.8.0: - version "5.8.0" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" - integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== - dependencies: - clone-deep "^4.0.1" - wildcard "^2.0.0" - -webpack-sources@^1.1.0, webpack-sources@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" - integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== - dependencies: - source-list-map "^2.0.0" - source-map "~0.6.1" - -webpack-sources@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" - integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== - -webpack@^5.61.0: - version "5.69.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.69.1.tgz#8cfd92c192c6a52c99ab00529b5a0d33aa848dc5" - integrity sha512-+VyvOSJXZMT2V5vLzOnDuMz5GxEqLk7hKWQ56YxPW/PQRUuKimPqmEIJOx8jHYeyo65pKbapbW464mvsKbaj4A== + "ansi-html-community" "^0.0.8" + "bonjour" "^3.5.0" + "chokidar" "^3.5.3" + "colorette" "^2.0.10" + "compression" "^1.7.4" + "connect-history-api-fallback" "^1.6.0" + "default-gateway" "^6.0.3" + "del" "^6.0.0" + "express" "^4.17.1" + "graceful-fs" "^4.2.6" + "html-entities" "^2.3.2" + "http-proxy-middleware" "^2.0.0" + "ipaddr.js" "^2.0.1" + "open" "^8.0.9" + "p-retry" "^4.5.0" + "portfinder" "^1.0.28" + "schema-utils" "^4.0.0" + "selfsigned" "^2.0.0" + "serve-index" "^1.9.1" + "sockjs" "^0.3.21" + "spdy" "^4.0.2" + "strip-ansi" "^7.0.0" + "webpack-dev-middleware" "^5.3.1" + "ws" "^8.4.2" + +"webpack-merge@^5.8.0": + "integrity" "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==" + "resolved" "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz" + "version" "5.8.0" + dependencies: + "clone-deep" "^4.0.1" + "wildcard" "^2.0.0" + +"webpack-sources@^1.1.0", "webpack-sources@^1.4.3": + "integrity" "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==" + "resolved" "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz" + "version" "1.4.3" + dependencies: + "source-list-map" "^2.0.0" + "source-map" "~0.6.1" + +"webpack-sources@^3.2.3": + "integrity" "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==" + "resolved" "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz" + "version" "3.2.3" + +"webpack@^4.0.0 || ^5.0.0", "webpack@^4.37.0 || ^5.0.0", "webpack@^4.4.0 || ^5.0.0", "webpack@^5.0.0", "webpack@^5.1.0", "webpack@^5.20.0", "webpack@^5.61.0", "webpack@>= 4", "webpack@>=2", "webpack@>=4.41.1 || 5.x", "webpack@3 || 4 || 5", "webpack@5.x": + "integrity" "sha512-+VyvOSJXZMT2V5vLzOnDuMz5GxEqLk7hKWQ56YxPW/PQRUuKimPqmEIJOx8jHYeyo65pKbapbW464mvsKbaj4A==" + "resolved" "https://registry.npmjs.org/webpack/-/webpack-5.69.1.tgz" + "version" "5.69.1" dependencies: "@types/eslint-scope" "^3.7.3" "@types/estree" "^0.0.51" "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/wasm-edit" "1.11.1" "@webassemblyjs/wasm-parser" "1.11.1" - acorn "^8.4.1" - acorn-import-assertions "^1.7.6" - browserslist "^4.14.5" - chrome-trace-event "^1.0.2" - enhanced-resolve "^5.8.3" - es-module-lexer "^0.9.0" - eslint-scope "5.1.1" - events "^3.2.0" - glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" - json-parse-better-errors "^1.0.2" - loader-runner "^4.2.0" - mime-types "^2.1.27" - neo-async "^2.6.2" - schema-utils "^3.1.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" - watchpack "^2.3.1" - webpack-sources "^3.2.3" - -webpackbar@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/webpackbar/-/webpackbar-5.0.2.tgz#d3dd466211c73852741dfc842b7556dcbc2b0570" - integrity sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ== - dependencies: - chalk "^4.1.0" - consola "^2.15.3" - pretty-time "^1.1.0" - std-env "^3.0.1" - -websocket-driver@>=0.5.1, websocket-driver@^0.7.4: - version "0.7.4" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" - integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== - dependencies: - http-parser-js ">=0.5.1" - safe-buffer ">=5.1.0" - websocket-extensions ">=0.1.1" - -websocket-extensions@>=0.1.1: - version "0.1.4" - resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" - integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -which@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -widest-line@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" - integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== - dependencies: - string-width "^4.0.0" - -wildcard@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" - integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write-file-atomic@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" - integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== - dependencies: - imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^3.1.5" - -ws@^7.3.1: - version "7.5.7" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" - integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== - -ws@^8.4.2: - version "8.5.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" - integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== - -xdg-basedir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" - integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== - -xml-js@^1.6.11: - version "1.6.11" - resolved "https://registry.yarnpkg.com/xml-js/-/xml-js-1.6.11.tgz#927d2f6947f7f1c19a316dd8eea3614e8b18f8e9" - integrity sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g== - dependencies: - sax "^1.2.4" - -xtend@^4.0.0, xtend@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" - integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== - -yarn@^1.17.3: - version "1.22.17" - resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.17.tgz#bf910747d22497b573131f7341c0e1d15c74036c" - integrity sha512-H0p241BXaH0UN9IeH//RT82tl5PfNraVpSpEoW+ET7lmopNC61eZ+A+IDvU8FM6Go5vx162SncDL8J1ZjRBriQ== - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -zwitch@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920" - integrity sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw== + "acorn" "^8.4.1" + "acorn-import-assertions" "^1.7.6" + "browserslist" "^4.14.5" + "chrome-trace-event" "^1.0.2" + "enhanced-resolve" "^5.8.3" + "es-module-lexer" "^0.9.0" + "eslint-scope" "5.1.1" + "events" "^3.2.0" + "glob-to-regexp" "^0.4.1" + "graceful-fs" "^4.2.9" + "json-parse-better-errors" "^1.0.2" + "loader-runner" "^4.2.0" + "mime-types" "^2.1.27" + "neo-async" "^2.6.2" + "schema-utils" "^3.1.0" + "tapable" "^2.1.1" + "terser-webpack-plugin" "^5.1.3" + "watchpack" "^2.3.1" + "webpack-sources" "^3.2.3" + +"webpackbar@^5.0.2": + "integrity" "sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ==" + "resolved" "https://registry.npmjs.org/webpackbar/-/webpackbar-5.0.2.tgz" + "version" "5.0.2" + dependencies: + "chalk" "^4.1.0" + "consola" "^2.15.3" + "pretty-time" "^1.1.0" + "std-env" "^3.0.1" + +"websocket-driver@^0.7.4", "websocket-driver@>=0.5.1": + "integrity" "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==" + "resolved" "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz" + "version" "0.7.4" + dependencies: + "http-parser-js" ">=0.5.1" + "safe-buffer" ">=5.1.0" + "websocket-extensions" ">=0.1.1" + +"websocket-extensions@>=0.1.1": + "integrity" "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" + "resolved" "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz" + "version" "0.1.4" + +"whatwg-url@^5.0.0": + "integrity" "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=" + "resolved" "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "tr46" "~0.0.3" + "webidl-conversions" "^3.0.0" + +"which@^1.3.1": + "integrity" "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==" + "resolved" "https://registry.npmjs.org/which/-/which-1.3.1.tgz" + "version" "1.3.1" + dependencies: + "isexe" "^2.0.0" + +"which@^2.0.1": + "integrity" "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==" + "resolved" "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "isexe" "^2.0.0" + +"widest-line@^3.1.0": + "integrity" "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==" + "resolved" "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "string-width" "^4.0.0" + +"wildcard@^2.0.0": + "integrity" "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==" + "resolved" "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz" + "version" "2.0.0" + +"wrap-ansi@^7.0.0": + "integrity" "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==" + "resolved" "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + "version" "7.0.0" + dependencies: + "ansi-styles" "^4.0.0" + "string-width" "^4.1.0" + "strip-ansi" "^6.0.0" + +"wrappy@1": + "integrity" "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "resolved" "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + "version" "1.0.2" + +"write-file-atomic@^3.0.0": + "integrity" "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==" + "resolved" "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz" + "version" "3.0.3" + dependencies: + "imurmurhash" "^0.1.4" + "is-typedarray" "^1.0.0" + "signal-exit" "^3.0.2" + "typedarray-to-buffer" "^3.1.5" + +"ws@^7.3.1": + "integrity" "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==" + "resolved" "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz" + "version" "7.5.7" + +"ws@^8.4.2": + "integrity" "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==" + "resolved" "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz" + "version" "8.5.0" + +"xdg-basedir@^4.0.0": + "integrity" "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" + "resolved" "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz" + "version" "4.0.0" + +"xml-js@^1.6.11": + "integrity" "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==" + "resolved" "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz" + "version" "1.6.11" + dependencies: + "sax" "^1.2.4" + +"xtend@^4.0.0", "xtend@^4.0.1": + "integrity" "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + "resolved" "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" + "version" "4.0.2" + +"yallist@^3.0.2": + "integrity" "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "resolved" "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" + "version" "3.1.1" + +"yallist@^4.0.0": + "integrity" "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "resolved" "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" + "version" "4.0.0" + +"yaml@^1.10.0", "yaml@^1.10.2", "yaml@^1.7.2": + "integrity" "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" + "resolved" "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" + "version" "1.10.2" + +"yarn@^1.17.3": + "integrity" "sha512-H0p241BXaH0UN9IeH//RT82tl5PfNraVpSpEoW+ET7lmopNC61eZ+A+IDvU8FM6Go5vx162SncDL8J1ZjRBriQ==" + "resolved" "https://registry.npmjs.org/yarn/-/yarn-1.22.17.tgz" + "version" "1.22.17" + +"yocto-queue@^0.1.0": + "integrity" "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + "resolved" "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" + "version" "0.1.0" + +"zwitch@^1.0.0": + "integrity" "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==" + "resolved" "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz" + "version" "1.0.5" From 66e05849da02a463791301a3ed6eddfe23e3341c Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 13 Mar 2023 16:22:14 +0100 Subject: [PATCH 412/898] replace last usages of Qt module --- openpype/hosts/maya/plugins/inventory/connect_geometry.py | 2 +- openpype/hosts/maya/plugins/inventory/connect_xgen.py | 2 +- openpype/hosts/maya/plugins/load/load_xgen.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/maya/plugins/inventory/connect_geometry.py b/openpype/hosts/maya/plugins/inventory/connect_geometry.py index a12487cf7ef..03154b7afe2 100644 --- a/openpype/hosts/maya/plugins/inventory/connect_geometry.py +++ b/openpype/hosts/maya/plugins/inventory/connect_geometry.py @@ -134,7 +134,7 @@ def display_warning(self, message, show_cancel=False): bool """ - from Qt import QtWidgets + from qtpy import QtWidgets accept = QtWidgets.QMessageBox.Ok if show_cancel: diff --git a/openpype/hosts/maya/plugins/inventory/connect_xgen.py b/openpype/hosts/maya/plugins/inventory/connect_xgen.py index 933a1b4025b..177971f176f 100644 --- a/openpype/hosts/maya/plugins/inventory/connect_xgen.py +++ b/openpype/hosts/maya/plugins/inventory/connect_xgen.py @@ -149,7 +149,7 @@ def display_warning(self, message, show_cancel=False): bool """ - from Qt import QtWidgets + from qtpy import QtWidgets accept = QtWidgets.QMessageBox.Ok if show_cancel: diff --git a/openpype/hosts/maya/plugins/load/load_xgen.py b/openpype/hosts/maya/plugins/load/load_xgen.py index 1600cd49bd0..7e6cabc77ce 100644 --- a/openpype/hosts/maya/plugins/load/load_xgen.py +++ b/openpype/hosts/maya/plugins/load/load_xgen.py @@ -3,7 +3,7 @@ import maya.cmds as cmds import xgenm -from Qt import QtWidgets +from qtpy import QtWidgets import openpype.hosts.maya.api.plugin from openpype.hosts.maya.api.lib import ( From 4b4adb922c6aa42f0f4989040cdf1f0e477baf82 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Mar 2023 15:23:23 +0000 Subject: [PATCH 413/898] Bump webpack from 5.69.1 to 5.76.1 in /website Bumps [webpack](https://github.com/webpack/webpack) from 5.69.1 to 5.76.1. - [Release notes](https://github.com/webpack/webpack/releases) - [Commits](https://github.com/webpack/webpack/compare/v5.69.1...v5.76.1) --- updated-dependencies: - dependency-name: webpack dependency-type: indirect ... Signed-off-by: dependabot[bot] --- website/yarn.lock | 11812 ++++++++++++++++++++------------------------ 1 file changed, 5357 insertions(+), 6455 deletions(-) diff --git a/website/yarn.lock b/website/yarn.lock index 2edf57abf4e..24a8e37e4e4 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -3,56 +3,48 @@ "@algolia/autocomplete-core@1.5.2": - "integrity" "sha512-DY0bhyczFSS1b/CqJlTE/nQRtnTAHl6IemIkBy0nEWnhDzRDdtdx4p5Uuk3vwAFxwEEgi1WqKwgSSMx6DpNL4A==" - "resolved" "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.5.2.tgz" - "version" "1.5.2" + version "1.5.2" + resolved "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.5.2.tgz" dependencies: "@algolia/autocomplete-shared" "1.5.2" "@algolia/autocomplete-preset-algolia@1.5.2": - "integrity" "sha512-3MRYnYQFJyovANzSX2CToS6/5cfVjbLLqFsZTKcvF3abhQzxbqwwaMBlJtt620uBUOeMzhdfasKhCc40+RHiZw==" - "resolved" "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.5.2.tgz" - "version" "1.5.2" + version "1.5.2" + resolved "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.5.2.tgz" dependencies: "@algolia/autocomplete-shared" "1.5.2" "@algolia/autocomplete-shared@1.5.2": - "integrity" "sha512-ylQAYv5H0YKMfHgVWX0j0NmL8XBcAeeeVQUmppnnMtzDbDnca6CzhKj3Q8eF9cHCgcdTDdb5K+3aKyGWA0obug==" - "resolved" "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.5.2.tgz" - "version" "1.5.2" + version "1.5.2" + resolved "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.5.2.tgz" "@algolia/cache-browser-local-storage@4.12.1": - "integrity" "sha512-ERFFOnC9740xAkuO0iZTQqm2AzU7Dpz/s+g7o48GlZgx5p9GgNcsuK5eS0GoW/tAK+fnKlizCtlFHNuIWuvfsg==" - "resolved" "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.12.1.tgz" - "version" "4.12.1" + version "4.12.1" + resolved "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.12.1.tgz" dependencies: "@algolia/cache-common" "4.12.1" "@algolia/cache-common@4.12.1": - "integrity" "sha512-UugTER3V40jT+e19Dmph5PKMeliYKxycNPwrPNADin0RcWNfT2QksK9Ff2N2W7UKraqMOzoeDb4LAJtxcK1a8Q==" - "resolved" "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.12.1.tgz" - "version" "4.12.1" + version "4.12.1" + resolved "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.12.1.tgz" "@algolia/cache-in-memory@4.12.1": - "integrity" "sha512-U6iaunaxK1lHsAf02UWF58foKFEcrVLsHwN56UkCtwn32nlP9rz52WOcHsgk6TJrL8NDcO5swMjtOQ5XHESFLw==" - "resolved" "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.12.1.tgz" - "version" "4.12.1" + version "4.12.1" + resolved "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.12.1.tgz" dependencies: "@algolia/cache-common" "4.12.1" "@algolia/client-account@4.12.1": - "integrity" "sha512-jGo4ConJNoMdTCR2zouO0jO/JcJmzOK6crFxMMLvdnB1JhmMbuIKluOTJVlBWeivnmcsqb7r0v7qTCPW5PAyxQ==" - "resolved" "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.12.1.tgz" - "version" "4.12.1" + version "4.12.1" + resolved "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.12.1.tgz" dependencies: "@algolia/client-common" "4.12.1" "@algolia/client-search" "4.12.1" "@algolia/transporter" "4.12.1" "@algolia/client-analytics@4.12.1": - "integrity" "sha512-h1It7KXzIthlhuhfBk7LteYq72tym9maQDUsyRW0Gft8b6ZQahnRak9gcCvKwhcJ1vJoP7T7JrNYGiYSicTD9g==" - "resolved" "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.12.1.tgz" - "version" "4.12.1" + version "4.12.1" + resolved "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.12.1.tgz" dependencies: "@algolia/client-common" "4.12.1" "@algolia/client-search" "4.12.1" @@ -60,100 +52,107 @@ "@algolia/transporter" "4.12.1" "@algolia/client-common@4.12.1": - "integrity" "sha512-obnJ8eSbv+h94Grk83DTGQ3bqhViSWureV6oK1s21/KMGWbb3DkduHm+lcwFrMFkjSUSzosLBHV9EQUIBvueTw==" - "resolved" "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.12.1.tgz" - "version" "4.12.1" + version "4.12.1" + resolved "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.12.1.tgz" dependencies: "@algolia/requester-common" "4.12.1" "@algolia/transporter" "4.12.1" "@algolia/client-personalization@4.12.1": - "integrity" "sha512-sMSnjjPjRgByGHYygV+5L/E8a6RgU7l2GbpJukSzJ9GRY37tHmBHuvahv8JjdCGJ2p7QDYLnQy5bN5Z02qjc7Q==" - "resolved" "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.12.1.tgz" - "version" "4.12.1" + version "4.12.1" + resolved "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.12.1.tgz" dependencies: "@algolia/client-common" "4.12.1" "@algolia/requester-common" "4.12.1" "@algolia/transporter" "4.12.1" -"@algolia/client-search@^4.9.1", "@algolia/client-search@4.12.1": - "integrity" "sha512-MwwKKprfY6X2nJ5Ki/ccXM2GDEePvVjZnnoOB2io3dLKW4fTqeSRlC5DRXeFD7UM0vOPPHr4ItV2aj19APKNVQ==" - "resolved" "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.12.1.tgz" - "version" "4.12.1" +"@algolia/client-search@4.12.1": + version "4.12.1" + resolved "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.12.1.tgz" dependencies: "@algolia/client-common" "4.12.1" "@algolia/requester-common" "4.12.1" "@algolia/transporter" "4.12.1" "@algolia/events@^4.0.1": - "integrity" "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==" - "resolved" "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz" - "version" "4.0.1" + version "4.0.1" + resolved "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz" "@algolia/logger-common@4.12.1": - "integrity" "sha512-fCgrzlXGATNqdFTxwx0GsyPXK+Uqrx1SZ3iuY2VGPPqdt1a20clAG2n2OcLHJpvaa6vMFPlJyWvbqAgzxdxBlQ==" - "resolved" "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.12.1.tgz" - "version" "4.12.1" + version "4.12.1" + resolved "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.12.1.tgz" "@algolia/logger-console@4.12.1": - "integrity" "sha512-0owaEnq/davngQMYqxLA4KrhWHiXujQ1CU3FFnyUcMyBR7rGHI48zSOUpqnsAXrMBdSH6rH5BDkSUUFwsh8RkQ==" - "resolved" "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.12.1.tgz" - "version" "4.12.1" + version "4.12.1" + resolved "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.12.1.tgz" dependencies: "@algolia/logger-common" "4.12.1" "@algolia/requester-browser-xhr@4.12.1": - "integrity" "sha512-OaMxDyG0TZG0oqz1lQh9e3woantAG1bLnuwq3fmypsrQxra4IQZiyn1x+kEb69D2TcXApI5gOgrD4oWhtEVMtw==" - "resolved" "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.12.1.tgz" - "version" "4.12.1" + version "4.12.1" + resolved "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.12.1.tgz" dependencies: "@algolia/requester-common" "4.12.1" "@algolia/requester-common@4.12.1": - "integrity" "sha512-XWIrWQNJ1vIrSuL/bUk3ZwNMNxl+aWz6dNboRW6+lGTcMIwc3NBFE90ogbZKhNrFRff8zI4qCF15tjW+Fyhpow==" - "resolved" "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.12.1.tgz" - "version" "4.12.1" + version "4.12.1" + resolved "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.12.1.tgz" "@algolia/requester-node-http@4.12.1": - "integrity" "sha512-awBtwaD+s0hxkA1aehYn8F0t9wqGoBVWgY4JPHBmp1ChO3pK7RKnnvnv7QQa9vTlllX29oPt/BBVgMo1Z3n1Qg==" - "resolved" "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.12.1.tgz" - "version" "4.12.1" + version "4.12.1" + resolved "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.12.1.tgz" dependencies: "@algolia/requester-common" "4.12.1" "@algolia/transporter@4.12.1": - "integrity" "sha512-BGeNgdEHc6dXIk2g8kdlOoQ6fQ6OIaKQcplEj7HPoi+XZUeAvRi3Pff3QWd7YmybWkjzd9AnTzieTASDWhL+sQ==" - "resolved" "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.12.1.tgz" - "version" "4.12.1" + version "4.12.1" + resolved "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.12.1.tgz" dependencies: "@algolia/cache-common" "4.12.1" "@algolia/logger-common" "4.12.1" "@algolia/requester-common" "4.12.1" "@ampproject/remapping@^2.2.0": - "integrity" "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==" - "resolved" "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz" - "version" "2.2.0" + version "2.2.0" + resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz" dependencies: "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.8.3": - "integrity" "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==" - "resolved" "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz" - "version" "7.18.6" + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz" dependencies: "@babel/highlight" "^7.18.6" "@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.8", "@babel/compat-data@^7.17.0", "@babel/compat-data@^7.20.5": - "integrity" "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==" - "resolved" "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz" - "version" "7.21.0" + version "7.21.0" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz" -"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.12.0", "@babel/core@^7.13.0", "@babel/core@^7.15.5", "@babel/core@^7.16.0", "@babel/core@^7.4.0-0": - "integrity" "sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==" - "resolved" "https://registry.npmjs.org/@babel/core/-/core-7.21.3.tgz" - "version" "7.21.3" +"@babel/core@7.12.9": + version "7.12.9" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz" + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.12.5" + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helpers" "^7.12.5" + "@babel/parser" "^7.12.7" + "@babel/template" "^7.12.7" + "@babel/traverse" "^7.12.9" + "@babel/types" "^7.12.7" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.19" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/core@^7.15.5", "@babel/core@^7.16.0": + version "7.21.3" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.21.3.tgz" dependencies: "@ampproject/remapping" "^2.2.0" "@babel/code-frame" "^7.18.6" @@ -165,74 +164,47 @@ "@babel/template" "^7.20.7" "@babel/traverse" "^7.21.3" "@babel/types" "^7.21.3" - "convert-source-map" "^1.7.0" - "debug" "^4.1.0" - "gensync" "^1.0.0-beta.2" - "json5" "^2.2.2" - "semver" "^6.3.0" - -"@babel/core@^7.11.6", "@babel/core@7.12.9": - "integrity" "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==" - "resolved" "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz" - "version" "7.12.9" - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.12.5" - "@babel/helper-module-transforms" "^7.12.1" - "@babel/helpers" "^7.12.5" - "@babel/parser" "^7.12.7" - "@babel/template" "^7.12.7" - "@babel/traverse" "^7.12.9" - "@babel/types" "^7.12.7" - "convert-source-map" "^1.7.0" - "debug" "^4.1.0" - "gensync" "^1.0.0-beta.1" - "json5" "^2.1.2" - "lodash" "^4.17.19" - "resolve" "^1.3.2" - "semver" "^5.4.1" - "source-map" "^0.5.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.2" + semver "^6.3.0" "@babel/generator@^7.12.5", "@babel/generator@^7.16.0", "@babel/generator@^7.21.3": - "integrity" "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==" - "resolved" "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz" - "version" "7.21.3" + version "7.21.3" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz" dependencies: "@babel/types" "^7.21.3" "@jridgewell/gen-mapping" "^0.3.2" "@jridgewell/trace-mapping" "^0.3.17" - "jsesc" "^2.5.1" + jsesc "^2.5.1" "@babel/helper-annotate-as-pure@^7.16.7": - "integrity" "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==" - "resolved" "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz" dependencies: "@babel/types" "^7.16.7" "@babel/helper-builder-binary-assignment-operator-visitor@^7.16.7": - "integrity" "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==" - "resolved" "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz" dependencies: "@babel/helper-explode-assignable-expression" "^7.16.7" "@babel/types" "^7.16.7" "@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7", "@babel/helper-compilation-targets@^7.20.7": - "integrity" "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==" - "resolved" "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz" - "version" "7.20.7" + version "7.20.7" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz" dependencies: "@babel/compat-data" "^7.20.5" "@babel/helper-validator-option" "^7.18.6" - "browserslist" "^4.21.3" - "lru-cache" "^5.1.1" - "semver" "^6.3.0" + browserslist "^4.21.3" + lru-cache "^5.1.1" + semver "^6.3.0" "@babel/helper-create-class-features-plugin@^7.16.10", "@babel/helper-create-class-features-plugin@^7.16.7": - "integrity" "sha512-JBdSr/LtyYIno/pNnJ75lBcqc3Z1XXujzPanHqjvvrhOA+DTceTFuJi8XjmWTZh4r3fsdfqaCMN0iZemdkxZHQ==" - "resolved" "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.1.tgz" - "version" "7.17.1" + version "7.17.1" + resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.1.tgz" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-environment-visitor" "^7.16.7" @@ -243,72 +215,63 @@ "@babel/helper-split-export-declaration" "^7.16.7" "@babel/helper-create-regexp-features-plugin@^7.16.7": - "integrity" "sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==" - "resolved" "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz" - "version" "7.17.0" + version "7.17.0" + resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" - "regexpu-core" "^5.0.1" + regexpu-core "^5.0.1" "@babel/helper-define-polyfill-provider@^0.3.1": - "integrity" "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==" - "resolved" "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz" - "version" "0.3.1" + version "0.3.1" + resolved "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz" dependencies: "@babel/helper-compilation-targets" "^7.13.0" "@babel/helper-module-imports" "^7.12.13" "@babel/helper-plugin-utils" "^7.13.0" "@babel/traverse" "^7.13.0" - "debug" "^4.1.1" - "lodash.debounce" "^4.0.8" - "resolve" "^1.14.2" - "semver" "^6.1.2" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + semver "^6.1.2" "@babel/helper-environment-visitor@^7.16.7", "@babel/helper-environment-visitor@^7.18.9": - "integrity" "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==" - "resolved" "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz" - "version" "7.18.9" + version "7.18.9" + resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz" "@babel/helper-explode-assignable-expression@^7.16.7": - "integrity" "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==" - "resolved" "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz" dependencies: "@babel/types" "^7.16.7" "@babel/helper-function-name@^7.16.7", "@babel/helper-function-name@^7.21.0": - "integrity" "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==" - "resolved" "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz" - "version" "7.21.0" + version "7.21.0" + resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz" dependencies: "@babel/template" "^7.20.7" "@babel/types" "^7.21.0" "@babel/helper-hoist-variables@^7.16.7", "@babel/helper-hoist-variables@^7.18.6": - "integrity" "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==" - "resolved" "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz" - "version" "7.18.6" + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz" dependencies: "@babel/types" "^7.18.6" "@babel/helper-member-expression-to-functions@^7.16.7": - "integrity" "sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==" - "resolved" "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz" dependencies: "@babel/types" "^7.16.7" "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.18.6": - "integrity" "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==" - "resolved" "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz" - "version" "7.18.6" + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz" dependencies: "@babel/types" "^7.18.6" "@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.16.7", "@babel/helper-module-transforms@^7.21.2": - "integrity" "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==" - "resolved" "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz" - "version" "7.21.2" + version "7.21.2" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz" dependencies: "@babel/helper-environment-visitor" "^7.18.9" "@babel/helper-module-imports" "^7.18.6" @@ -320,35 +283,30 @@ "@babel/types" "^7.21.2" "@babel/helper-optimise-call-expression@^7.16.7": - "integrity" "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==" - "resolved" "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz" dependencies: "@babel/types" "^7.16.7" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - "integrity" "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==" - "resolved" "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz" - "version" "7.16.7" - "@babel/helper-plugin-utils@7.10.4": - "integrity" "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" - "resolved" "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz" - "version" "7.10.4" + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz" "@babel/helper-remap-async-to-generator@^7.16.8": - "integrity" "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==" - "resolved" "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz" - "version" "7.16.8" + version "7.16.8" + resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-wrap-function" "^7.16.8" "@babel/types" "^7.16.8" "@babel/helper-replace-supers@^7.16.7": - "integrity" "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==" - "resolved" "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz" dependencies: "@babel/helper-environment-visitor" "^7.16.7" "@babel/helper-member-expression-to-functions" "^7.16.7" @@ -357,45 +315,38 @@ "@babel/types" "^7.16.7" "@babel/helper-simple-access@^7.16.7", "@babel/helper-simple-access@^7.20.2": - "integrity" "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==" - "resolved" "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz" - "version" "7.20.2" + version "7.20.2" + resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz" dependencies: "@babel/types" "^7.20.2" "@babel/helper-skip-transparent-expression-wrappers@^7.16.0": - "integrity" "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==" - "resolved" "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz" - "version" "7.16.0" + version "7.16.0" + resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz" dependencies: "@babel/types" "^7.16.0" "@babel/helper-split-export-declaration@^7.16.7", "@babel/helper-split-export-declaration@^7.18.6": - "integrity" "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==" - "resolved" "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz" - "version" "7.18.6" + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz" dependencies: "@babel/types" "^7.18.6" "@babel/helper-string-parser@^7.19.4": - "integrity" "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==" - "resolved" "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz" - "version" "7.19.4" + version "7.19.4" + resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz" "@babel/helper-validator-identifier@^7.16.7", "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": - "integrity" "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==" - "resolved" "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz" - "version" "7.19.1" + version "7.19.1" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz" "@babel/helper-validator-option@^7.16.7", "@babel/helper-validator-option@^7.18.6": - "integrity" "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==" - "resolved" "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz" - "version" "7.21.0" + version "7.21.0" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz" "@babel/helper-wrap-function@^7.16.8": - "integrity" "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==" - "resolved" "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz" - "version" "7.16.8" + version "7.16.8" + resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz" dependencies: "@babel/helper-function-name" "^7.16.7" "@babel/template" "^7.16.7" @@ -403,122 +354,115 @@ "@babel/types" "^7.16.8" "@babel/helpers@^7.12.5", "@babel/helpers@^7.21.0": - "integrity" "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==" - "resolved" "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz" - "version" "7.21.0" + version "7.21.0" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz" dependencies: "@babel/template" "^7.20.7" "@babel/traverse" "^7.21.0" "@babel/types" "^7.21.0" "@babel/highlight@^7.18.6": - "integrity" "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==" - "resolved" "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz" - "version" "7.18.6" + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz" dependencies: "@babel/helper-validator-identifier" "^7.18.6" - "chalk" "^2.0.0" - "js-tokens" "^4.0.0" + chalk "^2.0.0" + js-tokens "^4.0.0" "@babel/parser@^7.12.7", "@babel/parser@^7.16.4", "@babel/parser@^7.20.7", "@babel/parser@^7.21.3": - "integrity" "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==" - "resolved" "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz" - "version" "7.21.3" + version "7.21.3" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz" "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": - "integrity" "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==" - "resolved" "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.16.7": - "integrity" "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==" - "resolved" "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-proposal-optional-chaining" "^7.16.7" "@babel/plugin-proposal-async-generator-functions@^7.16.8": - "integrity" "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==" - "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz" - "version" "7.16.8" + version "7.16.8" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-remap-async-to-generator" "^7.16.8" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-proposal-class-properties@^7.16.7": - "integrity" "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==" - "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz" dependencies: "@babel/helper-create-class-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-proposal-class-static-block@^7.16.7": - "integrity" "sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw==" - "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz" dependencies: "@babel/helper-create-class-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-proposal-dynamic-import@^7.16.7": - "integrity" "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==" - "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-proposal-export-namespace-from@^7.16.7": - "integrity" "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==" - "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" "@babel/plugin-proposal-json-strings@^7.16.7": - "integrity" "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==" - "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-proposal-logical-assignment-operators@^7.16.7": - "integrity" "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==" - "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-proposal-nullish-coalescing-operator@^7.16.7": - "integrity" "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==" - "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" "@babel/plugin-proposal-numeric-separator@^7.16.7": - "integrity" "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==" - "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-numeric-separator" "^7.10.4" +"@babel/plugin-proposal-object-rest-spread@7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz" + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-transform-parameters" "^7.12.1" + "@babel/plugin-proposal-object-rest-spread@^7.16.7": - "integrity" "sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==" - "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz" - "version" "7.17.3" + version "7.17.3" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz" dependencies: "@babel/compat-data" "^7.17.0" "@babel/helper-compilation-targets" "^7.16.7" @@ -526,44 +470,31 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-transform-parameters" "^7.16.7" -"@babel/plugin-proposal-object-rest-spread@7.12.1": - "integrity" "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==" - "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz" - "version" "7.12.1" - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.12.1" - "@babel/plugin-proposal-optional-catch-binding@^7.16.7": - "integrity" "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==" - "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-proposal-optional-chaining@^7.16.7": - "integrity" "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==" - "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-proposal-private-methods@^7.16.11": - "integrity" "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==" - "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz" - "version" "7.16.11" + version "7.16.11" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz" dependencies: "@babel/helper-create-class-features-plugin" "^7.16.10" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-proposal-private-property-in-object@^7.16.7": - "integrity" "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==" - "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-create-class-features-plugin" "^7.16.7" @@ -571,166 +502,143 @@ "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-proposal-unicode-property-regex@^7.16.7", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - "integrity" "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==" - "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-async-generators@^7.8.4": - "integrity" "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==" - "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" - "version" "7.8.4" + version "7.8.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-class-properties@^7.12.13": - "integrity" "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==" - "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" - "version" "7.12.13" + version "7.12.13" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" dependencies: "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-class-static-block@^7.14.5": - "integrity" "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==" - "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz" - "version" "7.14.5" + version "7.14.5" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz" dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-dynamic-import@^7.8.3": - "integrity" "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==" - "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz" - "version" "7.8.3" + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-export-namespace-from@^7.8.3": - "integrity" "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==" - "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz" - "version" "7.8.3" + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz" dependencies: "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-json-strings@^7.8.3": - "integrity" "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==" - "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" - "version" "7.8.3" + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.16.7": - "integrity" "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==" - "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz" - "version" "7.16.7" - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-jsx@7.12.1": - "integrity" "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==" - "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz" - "version" "7.12.1" + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz" dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-syntax-jsx@^7.16.7": + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": - "integrity" "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==" - "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" - "version" "7.10.4" + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - "integrity" "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==" - "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" - "version" "7.8.3" + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-numeric-separator@^7.10.4": - "integrity" "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==" - "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" - "version" "7.10.4" + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3", "@babel/plugin-syntax-object-rest-spread@7.8.3": - "integrity" "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==" - "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" - "version" "7.8.3" +"@babel/plugin-syntax-object-rest-spread@7.8.3", "@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding@^7.8.3": - "integrity" "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==" - "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" - "version" "7.8.3" + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-chaining@^7.8.3": - "integrity" "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==" - "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" - "version" "7.8.3" + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-private-property-in-object@^7.14.5": - "integrity" "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==" - "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz" - "version" "7.14.5" + version "7.14.5" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz" dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-top-level-await@^7.14.5": - "integrity" "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==" - "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz" - "version" "7.14.5" + version "7.14.5" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz" dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.16.7": - "integrity" "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==" - "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-arrow-functions@^7.16.7": - "integrity" "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-async-to-generator@^7.16.8": - "integrity" "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz" - "version" "7.16.8" + version "7.16.8" + resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz" dependencies: "@babel/helper-module-imports" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-remap-async-to-generator" "^7.16.8" "@babel/plugin-transform-block-scoped-functions@^7.16.7": - "integrity" "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-block-scoping@^7.16.7": - "integrity" "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-classes@^7.16.7": - "integrity" "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-environment-visitor" "^7.16.7" @@ -739,174 +647,152 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-replace-supers" "^7.16.7" "@babel/helper-split-export-declaration" "^7.16.7" - "globals" "^11.1.0" + globals "^11.1.0" "@babel/plugin-transform-computed-properties@^7.16.7": - "integrity" "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-destructuring@^7.16.7": - "integrity" "sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz" - "version" "7.17.3" + version "7.17.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-dotall-regex@^7.16.7", "@babel/plugin-transform-dotall-regex@^7.4.4": - "integrity" "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-duplicate-keys@^7.16.7": - "integrity" "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-exponentiation-operator@^7.16.7": - "integrity" "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz" dependencies: "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-for-of@^7.16.7": - "integrity" "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-function-name@^7.16.7": - "integrity" "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz" dependencies: "@babel/helper-compilation-targets" "^7.16.7" "@babel/helper-function-name" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-literals@^7.16.7": - "integrity" "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-member-expression-literals@^7.16.7": - "integrity" "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-modules-amd@^7.16.7": - "integrity" "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz" dependencies: "@babel/helper-module-transforms" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" - "babel-plugin-dynamic-import-node" "^2.3.3" + babel-plugin-dynamic-import-node "^2.3.3" "@babel/plugin-transform-modules-commonjs@^7.16.8": - "integrity" "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz" - "version" "7.16.8" + version "7.16.8" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz" dependencies: "@babel/helper-module-transforms" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-simple-access" "^7.16.7" - "babel-plugin-dynamic-import-node" "^2.3.3" + babel-plugin-dynamic-import-node "^2.3.3" "@babel/plugin-transform-modules-systemjs@^7.16.7": - "integrity" "sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz" dependencies: "@babel/helper-hoist-variables" "^7.16.7" "@babel/helper-module-transforms" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-validator-identifier" "^7.16.7" - "babel-plugin-dynamic-import-node" "^2.3.3" + babel-plugin-dynamic-import-node "^2.3.3" "@babel/plugin-transform-modules-umd@^7.16.7": - "integrity" "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz" dependencies: "@babel/helper-module-transforms" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-named-capturing-groups-regex@^7.16.8": - "integrity" "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz" - "version" "7.16.8" + version "7.16.8" + resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/plugin-transform-new-target@^7.16.7": - "integrity" "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-object-super@^7.16.7": - "integrity" "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-replace-supers" "^7.16.7" "@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.16.7": - "integrity" "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-property-literals@^7.16.7": - "integrity" "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-react-constant-elements@^7.14.5": - "integrity" "sha512-lF+cfsyTgwWkcw715J88JhMYJ5GpysYNLhLP1PkvkhTRN7B3e74R/1KsDxFxhRpSn0UUD3IWM4GvdBR2PEbbQQ==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-react-display-name@^7.16.7": - "integrity" "sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-react-jsx-development@^7.16.7": - "integrity" "sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz" dependencies: "@babel/plugin-transform-react-jsx" "^7.16.7" "@babel/plugin-transform-react-jsx@^7.16.7": - "integrity" "sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz" - "version" "7.17.3" + version "7.17.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-module-imports" "^7.16.7" @@ -915,103 +801,90 @@ "@babel/types" "^7.17.0" "@babel/plugin-transform-react-pure-annotations@^7.16.7": - "integrity" "sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-regenerator@^7.16.7": - "integrity" "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz" dependencies: - "regenerator-transform" "^0.14.2" + regenerator-transform "^0.14.2" "@babel/plugin-transform-reserved-words@^7.16.7": - "integrity" "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-runtime@^7.16.0": - "integrity" "sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz" - "version" "7.17.0" + version "7.17.0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz" dependencies: "@babel/helper-module-imports" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" - "babel-plugin-polyfill-corejs2" "^0.3.0" - "babel-plugin-polyfill-corejs3" "^0.5.0" - "babel-plugin-polyfill-regenerator" "^0.3.0" - "semver" "^6.3.0" + babel-plugin-polyfill-corejs2 "^0.3.0" + babel-plugin-polyfill-corejs3 "^0.5.0" + babel-plugin-polyfill-regenerator "^0.3.0" + semver "^6.3.0" "@babel/plugin-transform-shorthand-properties@^7.16.7": - "integrity" "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-spread@^7.16.7": - "integrity" "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-transform-sticky-regex@^7.16.7": - "integrity" "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-template-literals@^7.16.7": - "integrity" "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-typeof-symbol@^7.16.7": - "integrity" "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-typescript@^7.16.7": - "integrity" "sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz" - "version" "7.16.8" + version "7.16.8" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz" dependencies: "@babel/helper-create-class-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-typescript" "^7.16.7" "@babel/plugin-transform-unicode-escapes@^7.16.7": - "integrity" "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-unicode-regex@^7.16.7": - "integrity" "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==" - "resolved" "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/preset-env@^7.15.6", "@babel/preset-env@^7.16.4": - "integrity" "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==" - "resolved" "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz" - "version" "7.16.11" + version "7.16.11" + resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz" dependencies: "@babel/compat-data" "^7.16.8" "@babel/helper-compilation-targets" "^7.16.7" @@ -1082,27 +955,25 @@ "@babel/plugin-transform-unicode-regex" "^7.16.7" "@babel/preset-modules" "^0.1.5" "@babel/types" "^7.16.8" - "babel-plugin-polyfill-corejs2" "^0.3.0" - "babel-plugin-polyfill-corejs3" "^0.5.0" - "babel-plugin-polyfill-regenerator" "^0.3.0" - "core-js-compat" "^3.20.2" - "semver" "^6.3.0" + babel-plugin-polyfill-corejs2 "^0.3.0" + babel-plugin-polyfill-corejs3 "^0.5.0" + babel-plugin-polyfill-regenerator "^0.3.0" + core-js-compat "^3.20.2" + semver "^6.3.0" "@babel/preset-modules@^0.1.5": - "integrity" "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==" - "resolved" "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz" - "version" "0.1.5" + version "0.1.5" + resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" "@babel/plugin-transform-dotall-regex" "^7.4.4" "@babel/types" "^7.4.4" - "esutils" "^2.0.2" + esutils "^2.0.2" "@babel/preset-react@^7.14.5", "@babel/preset-react@^7.16.0": - "integrity" "sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA==" - "resolved" "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-validator-option" "^7.16.7" @@ -1112,42 +983,37 @@ "@babel/plugin-transform-react-pure-annotations" "^7.16.7" "@babel/preset-typescript@^7.15.0", "@babel/preset-typescript@^7.16.0": - "integrity" "sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==" - "resolved" "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz" - "version" "7.16.7" + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-validator-option" "^7.16.7" "@babel/plugin-transform-typescript" "^7.16.7" "@babel/runtime-corejs3@^7.16.3": - "integrity" "sha512-NcKtr2epxfIrNM4VOmPKO46TvDMCBhgi2CrSHaEarrz+Plk2K5r9QemmOFTGpZaoKnWoGH5MO+CzeRsih/Fcgg==" - "resolved" "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.17.2.tgz" - "version" "7.17.2" + version "7.17.2" + resolved "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.17.2.tgz" dependencies: - "core-js-pure" "^3.20.2" - "regenerator-runtime" "^0.13.4" + core-js-pure "^3.20.2" + regenerator-runtime "^0.13.4" "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.16.3", "@babel/runtime@^7.8.4": - "integrity" "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==" - "resolved" "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz" - "version" "7.17.2" + version "7.17.2" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz" dependencies: - "regenerator-runtime" "^0.13.4" + regenerator-runtime "^0.13.4" "@babel/template@^7.12.7", "@babel/template@^7.16.7", "@babel/template@^7.20.7": - "integrity" "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==" - "resolved" "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz" - "version" "7.20.7" + version "7.20.7" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz" dependencies: "@babel/code-frame" "^7.18.6" "@babel/parser" "^7.20.7" "@babel/types" "^7.20.7" "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.16.3", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2", "@babel/traverse@^7.21.3": - "integrity" "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==" - "resolved" "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz" - "version" "7.21.3" + version "7.21.3" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz" dependencies: "@babel/code-frame" "^7.18.6" "@babel/generator" "^7.21.3" @@ -1157,37 +1023,33 @@ "@babel/helper-split-export-declaration" "^7.18.6" "@babel/parser" "^7.21.3" "@babel/types" "^7.21.3" - "debug" "^4.1.0" - "globals" "^11.1.0" + debug "^4.1.0" + globals "^11.1.0" "@babel/types@^7.12.7", "@babel/types@^7.15.6", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.18.6", "@babel/types@^7.20.2", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.2", "@babel/types@^7.21.3", "@babel/types@^7.4.4": - "integrity" "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==" - "resolved" "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz" - "version" "7.21.3" + version "7.21.3" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz" dependencies: "@babel/helper-string-parser" "^7.19.4" "@babel/helper-validator-identifier" "^7.19.1" - "to-fast-properties" "^2.0.0" + to-fast-properties "^2.0.0" "@docsearch/css@3.0.0-alpha.50": - "integrity" "sha512-QeWFCQOtS9D+Fi20liKsPXF2j/xWKh52e+P2Z1UATIdPMqmH6zoB2lcUz+cgv6PPVgWUtECeR6VSSUm71LT94w==" - "resolved" "https://registry.npmjs.org/@docsearch/css/-/css-3.0.0-alpha.50.tgz" - "version" "3.0.0-alpha.50" + version "3.0.0-alpha.50" + resolved "https://registry.npmjs.org/@docsearch/css/-/css-3.0.0-alpha.50.tgz" "@docsearch/react@^3.0.0-alpha.39": - "integrity" "sha512-oDGV1zZCRYv7MWsh6CyQVthYTRc3b4q+6kKwNYb1/g/Wf/4nJHutpxolFLHdEUDhrJ4Xi8wxwQG+lEwAVBTHPg==" - "resolved" "https://registry.npmjs.org/@docsearch/react/-/react-3.0.0-alpha.50.tgz" - "version" "3.0.0-alpha.50" + version "3.0.0-alpha.50" + resolved "https://registry.npmjs.org/@docsearch/react/-/react-3.0.0-alpha.50.tgz" dependencies: "@algolia/autocomplete-core" "1.5.2" "@algolia/autocomplete-preset-algolia" "1.5.2" "@docsearch/css" "3.0.0-alpha.50" - "algoliasearch" "^4.0.0" + algoliasearch "^4.0.0" "@docusaurus/core@2.0.0-beta.15": - "integrity" "sha512-zXhhD0fApMSvq/9Pkm9DQxa//hGOXVCq9yMHiXOkI5D1tLec7PxtnaC5cLfGHljkN9cKIfRDYUVcG1gHymVfpA==" - "resolved" "https://registry.npmjs.org/@docusaurus/core/-/core-2.0.0-beta.15.tgz" - "version" "2.0.0-beta.15" + version "2.0.0-beta.15" + resolved "https://registry.npmjs.org/@docusaurus/core/-/core-2.0.0-beta.15.tgz" dependencies: "@babel/core" "^7.16.0" "@babel/generator" "^7.16.0" @@ -1208,103 +1070,99 @@ "@docusaurus/utils-validation" "2.0.0-beta.15" "@slorber/static-site-generator-webpack-plugin" "^4.0.0" "@svgr/webpack" "^6.0.0" - "autoprefixer" "^10.3.5" - "babel-loader" "^8.2.2" - "babel-plugin-dynamic-import-node" "2.3.0" - "boxen" "^5.0.1" - "chokidar" "^3.5.2" - "clean-css" "^5.1.5" - "commander" "^5.1.0" - "copy-webpack-plugin" "^10.2.0" - "core-js" "^3.18.0" - "css-loader" "^6.5.1" - "css-minimizer-webpack-plugin" "^3.3.1" - "cssnano" "^5.0.8" - "del" "^6.0.0" - "detect-port" "^1.3.0" - "escape-html" "^1.0.3" - "eta" "^1.12.3" - "file-loader" "^6.2.0" - "fs-extra" "^10.0.0" - "html-minifier-terser" "^6.0.2" - "html-tags" "^3.1.0" - "html-webpack-plugin" "^5.4.0" - "import-fresh" "^3.3.0" - "is-root" "^2.1.0" - "leven" "^3.1.0" - "lodash" "^4.17.20" - "mini-css-extract-plugin" "^1.6.0" - "nprogress" "^0.2.0" - "postcss" "^8.3.7" - "postcss-loader" "^6.1.1" - "prompts" "^2.4.1" - "react-dev-utils" "^12.0.0" - "react-helmet" "^6.1.0" - "react-loadable" "npm:@docusaurus/react-loadable@5.5.2" - "react-loadable-ssr-addon-v5-slorber" "^1.0.1" - "react-router" "^5.2.0" - "react-router-config" "^5.1.1" - "react-router-dom" "^5.2.0" - "remark-admonitions" "^1.2.1" - "rtl-detect" "^1.0.4" - "semver" "^7.3.4" - "serve-handler" "^6.1.3" - "shelljs" "^0.8.4" - "strip-ansi" "^6.0.0" - "terser-webpack-plugin" "^5.2.4" - "tslib" "^2.3.1" - "update-notifier" "^5.1.0" - "url-loader" "^4.1.1" - "wait-on" "^6.0.0" - "webpack" "^5.61.0" - "webpack-bundle-analyzer" "^4.4.2" - "webpack-dev-server" "^4.7.1" - "webpack-merge" "^5.8.0" - "webpackbar" "^5.0.2" + autoprefixer "^10.3.5" + babel-loader "^8.2.2" + babel-plugin-dynamic-import-node "2.3.0" + boxen "^5.0.1" + chokidar "^3.5.2" + clean-css "^5.1.5" + commander "^5.1.0" + copy-webpack-plugin "^10.2.0" + core-js "^3.18.0" + css-loader "^6.5.1" + css-minimizer-webpack-plugin "^3.3.1" + cssnano "^5.0.8" + del "^6.0.0" + detect-port "^1.3.0" + escape-html "^1.0.3" + eta "^1.12.3" + file-loader "^6.2.0" + fs-extra "^10.0.0" + html-minifier-terser "^6.0.2" + html-tags "^3.1.0" + html-webpack-plugin "^5.4.0" + import-fresh "^3.3.0" + is-root "^2.1.0" + leven "^3.1.0" + lodash "^4.17.20" + mini-css-extract-plugin "^1.6.0" + nprogress "^0.2.0" + postcss "^8.3.7" + postcss-loader "^6.1.1" + prompts "^2.4.1" + react-dev-utils "^12.0.0" + react-helmet "^6.1.0" + react-loadable "npm:@docusaurus/react-loadable@5.5.2" + react-loadable-ssr-addon-v5-slorber "^1.0.1" + react-router "^5.2.0" + react-router-config "^5.1.1" + react-router-dom "^5.2.0" + remark-admonitions "^1.2.1" + rtl-detect "^1.0.4" + semver "^7.3.4" + serve-handler "^6.1.3" + shelljs "^0.8.4" + strip-ansi "^6.0.0" + terser-webpack-plugin "^5.2.4" + tslib "^2.3.1" + update-notifier "^5.1.0" + url-loader "^4.1.1" + wait-on "^6.0.0" + webpack "^5.61.0" + webpack-bundle-analyzer "^4.4.2" + webpack-dev-server "^4.7.1" + webpack-merge "^5.8.0" + webpackbar "^5.0.2" "@docusaurus/cssnano-preset@2.0.0-beta.15": - "integrity" "sha512-55aYURbB5dqrx64lStNcZxDx5R6bKkAawlCB7mDKx3r+Qnp3ofGW7UExLQSCbTu3axT1vJCF5D7H6ljTRYJLtA==" - "resolved" "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-beta.15.tgz" - "version" "2.0.0-beta.15" + version "2.0.0-beta.15" + resolved "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-beta.15.tgz" dependencies: - "cssnano-preset-advanced" "^5.1.4" - "postcss" "^8.3.7" - "postcss-sort-media-queries" "^4.1.0" + cssnano-preset-advanced "^5.1.4" + postcss "^8.3.7" + postcss-sort-media-queries "^4.1.0" "@docusaurus/logger@2.0.0-beta.15": - "integrity" "sha512-5bDSHCyLfMtz6QnFfICdL5mgxbGfC7DW1V+/Q17nRdpZSPZgsNKK/Esp0zdDi1oxAyEpXMXx64nLaHL7joJxIg==" - "resolved" "https://registry.npmjs.org/@docusaurus/logger/-/logger-2.0.0-beta.15.tgz" - "version" "2.0.0-beta.15" + version "2.0.0-beta.15" + resolved "https://registry.npmjs.org/@docusaurus/logger/-/logger-2.0.0-beta.15.tgz" dependencies: - "chalk" "^4.1.2" - "tslib" "^2.3.1" + chalk "^4.1.2" + tslib "^2.3.1" "@docusaurus/mdx-loader@2.0.0-beta.15": - "integrity" "sha512-MVpytjDDao7hmPF1QSs9B5zoTgevZjiqjnX3FM1yjqdCv+chyUo0gnmYHjeG/4Gqu7jucp+dDdp6yQpzs4g09A==" - "resolved" "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-beta.15.tgz" - "version" "2.0.0-beta.15" + version "2.0.0-beta.15" + resolved "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-beta.15.tgz" dependencies: "@babel/parser" "^7.16.4" "@babel/traverse" "^7.16.3" "@docusaurus/logger" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" "@mdx-js/mdx" "^1.6.21" - "escape-html" "^1.0.3" - "file-loader" "^6.2.0" - "fs-extra" "^10.0.0" - "image-size" "^1.0.1" - "mdast-util-to-string" "^2.0.0" - "remark-emoji" "^2.1.0" - "stringify-object" "^3.3.0" - "tslib" "^2.3.1" - "unist-util-visit" "^2.0.2" - "url-loader" "^4.1.1" - "webpack" "^5.61.0" + escape-html "^1.0.3" + file-loader "^6.2.0" + fs-extra "^10.0.0" + image-size "^1.0.1" + mdast-util-to-string "^2.0.0" + remark-emoji "^2.1.0" + stringify-object "^3.3.0" + tslib "^2.3.1" + unist-util-visit "^2.0.2" + url-loader "^4.1.1" + webpack "^5.61.0" "@docusaurus/plugin-content-blog@2.0.0-beta.15": - "integrity" "sha512-VtEwkgkoNIS8JFPe+huBeBuJ8HG8Lq1JNYM/ItwQg/cwGAgP8EgwbEuKDn428oZKEI2PpgAuf5Gv4AzJWIes9A==" - "resolved" "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.15.tgz" - "version" "2.0.0-beta.15" + version "2.0.0-beta.15" + resolved "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.15.tgz" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/logger" "2.0.0-beta.15" @@ -1312,98 +1170,91 @@ "@docusaurus/utils" "2.0.0-beta.15" "@docusaurus/utils-common" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - "cheerio" "^1.0.0-rc.10" - "feed" "^4.2.2" - "fs-extra" "^10.0.0" - "lodash" "^4.17.20" - "reading-time" "^1.5.0" - "remark-admonitions" "^1.2.1" - "tslib" "^2.3.1" - "utility-types" "^3.10.0" - "webpack" "^5.61.0" + cheerio "^1.0.0-rc.10" + feed "^4.2.2" + fs-extra "^10.0.0" + lodash "^4.17.20" + reading-time "^1.5.0" + remark-admonitions "^1.2.1" + tslib "^2.3.1" + utility-types "^3.10.0" + webpack "^5.61.0" "@docusaurus/plugin-content-docs@2.0.0-beta.15": - "integrity" "sha512-HSwNZdUKz4rpJiGbFjl/OFhSleeZUSZ6E6lk98i4iL1A5u6fIm4CHsT53yp4UUOse+lFrePTFZsyqwMA4nZZYA==" - "resolved" "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-beta.15.tgz" - "version" "2.0.0-beta.15" + version "2.0.0-beta.15" + resolved "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-beta.15.tgz" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/logger" "2.0.0-beta.15" "@docusaurus/mdx-loader" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - "combine-promises" "^1.1.0" - "fs-extra" "^10.0.0" - "import-fresh" "^3.2.2" - "js-yaml" "^4.0.0" - "lodash" "^4.17.20" - "remark-admonitions" "^1.2.1" - "shelljs" "^0.8.4" - "tslib" "^2.3.1" - "utility-types" "^3.10.0" - "webpack" "^5.61.0" + combine-promises "^1.1.0" + fs-extra "^10.0.0" + import-fresh "^3.2.2" + js-yaml "^4.0.0" + lodash "^4.17.20" + remark-admonitions "^1.2.1" + shelljs "^0.8.4" + tslib "^2.3.1" + utility-types "^3.10.0" + webpack "^5.61.0" "@docusaurus/plugin-content-pages@2.0.0-beta.15": - "integrity" "sha512-N7YhW5RiOY6J228z4lOoP//qX0Q48cRtxDONZ/Ohd9C5OI2vS6TD8iQuDqOIYHxH+BshjNSsKvbJ+SMIQDwysg==" - "resolved" "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-beta.15.tgz" - "version" "2.0.0-beta.15" + version "2.0.0-beta.15" + resolved "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-beta.15.tgz" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/mdx-loader" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - "fs-extra" "^10.0.0" - "globby" "^11.0.2" - "remark-admonitions" "^1.2.1" - "tslib" "^2.3.1" - "webpack" "^5.61.0" + fs-extra "^10.0.0" + globby "^11.0.2" + remark-admonitions "^1.2.1" + tslib "^2.3.1" + webpack "^5.61.0" "@docusaurus/plugin-debug@2.0.0-beta.15": - "integrity" "sha512-Jth11jB/rVqPwCGdkVKSUWeXZPAr/NyPn+yeknTBk2LgQKBJ3YU5dNG0uyt0Ay+UYT01TkousPJkXhLuy4Qrsw==" - "resolved" "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-beta.15.tgz" - "version" "2.0.0-beta.15" + version "2.0.0-beta.15" + resolved "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-beta.15.tgz" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" - "fs-extra" "^10.0.0" - "react-json-view" "^1.21.3" - "tslib" "^2.3.1" + fs-extra "^10.0.0" + react-json-view "^1.21.3" + tslib "^2.3.1" "@docusaurus/plugin-google-analytics@2.0.0-beta.15": - "integrity" "sha512-ELAnxNYiC2i7gfu/ViurNIdm1/DdnbEfVDmpffS9niQhOREM1U3jpxkz/ff1GIC6heOLyHTtini/CZBDoroVGw==" - "resolved" "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-beta.15.tgz" - "version" "2.0.0-beta.15" + version "2.0.0-beta.15" + resolved "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-beta.15.tgz" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - "tslib" "^2.3.1" + tslib "^2.3.1" "@docusaurus/plugin-google-gtag@2.0.0-beta.15": - "integrity" "sha512-E5Rm3+dN7i3A9V5uq5sl9xTNA3aXsLwTZEA2SpOkY571dCpd+sfVvz1lR+KRY9Fy6ZHk8PqrNImgCWfIerRuZQ==" - "resolved" "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-beta.15.tgz" - "version" "2.0.0-beta.15" + version "2.0.0-beta.15" + resolved "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-beta.15.tgz" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - "tslib" "^2.3.1" + tslib "^2.3.1" "@docusaurus/plugin-sitemap@2.0.0-beta.15": - "integrity" "sha512-PBjeQb2Qpe4uPdRefWL/eXCeYjrgNB/UArExYeUuP4wiY1dpw2unGNCvFUxv4hzJGmARoTLsnRkeYkUim809LQ==" - "resolved" "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-beta.15.tgz" - "version" "2.0.0-beta.15" + version "2.0.0-beta.15" + resolved "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-beta.15.tgz" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" "@docusaurus/utils-common" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - "fs-extra" "^10.0.0" - "sitemap" "^7.0.0" - "tslib" "^2.3.1" + fs-extra "^10.0.0" + sitemap "^7.0.0" + tslib "^2.3.1" "@docusaurus/preset-classic@2.0.0-beta.15": - "integrity" "sha512-3NZIXWTAzk+kOgiB8uAbD+FZv3VFR1qkU6+TW24DRenjRnXof3CkRuldhI1QI0hILm1fuJ319QRkakV8FFtXyA==" - "resolved" "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-2.0.0-beta.15.tgz" - "version" "2.0.0-beta.15" + version "2.0.0-beta.15" + resolved "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-2.0.0-beta.15.tgz" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/plugin-content-blog" "2.0.0-beta.15" @@ -1417,18 +1268,16 @@ "@docusaurus/theme-common" "2.0.0-beta.15" "@docusaurus/theme-search-algolia" "2.0.0-beta.15" -"@docusaurus/react-loadable@5.5.2": - "integrity" "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==" - "resolved" "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz" - "version" "5.5.2" +"@docusaurus/react-loadable@5.5.2", "react-loadable@npm:@docusaurus/react-loadable@5.5.2": + version "5.5.2" + resolved "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz" dependencies: "@types/react" "*" - "prop-types" "^15.6.2" + prop-types "^15.6.2" "@docusaurus/theme-classic@2.0.0-beta.15": - "integrity" "sha512-WwNRcQvMtQ7KDhOEHFKFHxXCdoZwLg66hT3vhqNIFMfGQuPzOP91MX5LUSo1QWHhlrD3H3Og+r7Ik/fy2bf5lQ==" - "resolved" "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.0.0-beta.15.tgz" - "version" "2.0.0-beta.15" + version "2.0.0-beta.15" + resolved "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.0.0-beta.15.tgz" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/plugin-content-blog" "2.0.0-beta.15" @@ -1440,33 +1289,31 @@ "@docusaurus/utils-common" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" "@mdx-js/react" "^1.6.21" - "clsx" "^1.1.1" - "copy-text-to-clipboard" "^3.0.1" - "infima" "0.2.0-alpha.37" - "lodash" "^4.17.20" - "postcss" "^8.3.7" - "prism-react-renderer" "^1.2.1" - "prismjs" "^1.23.0" - "react-router-dom" "^5.2.0" - "rtlcss" "^3.3.0" + clsx "^1.1.1" + copy-text-to-clipboard "^3.0.1" + infima "0.2.0-alpha.37" + lodash "^4.17.20" + postcss "^8.3.7" + prism-react-renderer "^1.2.1" + prismjs "^1.23.0" + react-router-dom "^5.2.0" + rtlcss "^3.3.0" "@docusaurus/theme-common@2.0.0-beta.15": - "integrity" "sha512-+pvarmzcyECE4nWxw+dCMKRIoes0NegrRuM9+nRsUrS/E5ywsF539kpupKIEqaMjq6AuM0CJtDoHxHHPNe0KaQ==" - "resolved" "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-2.0.0-beta.15.tgz" - "version" "2.0.0-beta.15" + version "2.0.0-beta.15" + resolved "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-2.0.0-beta.15.tgz" dependencies: "@docusaurus/plugin-content-blog" "2.0.0-beta.15" "@docusaurus/plugin-content-docs" "2.0.0-beta.15" "@docusaurus/plugin-content-pages" "2.0.0-beta.15" - "clsx" "^1.1.1" - "parse-numeric-range" "^1.3.0" - "tslib" "^2.3.1" - "utility-types" "^3.10.0" + clsx "^1.1.1" + parse-numeric-range "^1.3.0" + tslib "^2.3.1" + utility-types "^3.10.0" "@docusaurus/theme-search-algolia@2.0.0-beta.15": - "integrity" "sha512-XrrQKyjOPzmEuOcdsaAn1tzNJkNMA3PC86PwPZUaah0cYPpBGptcJYDlIW4VHIrCBfkQvhvmg/B3qKF6bMMi8g==" - "resolved" "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-beta.15.tgz" - "version" "2.0.0-beta.15" + version "2.0.0-beta.15" + resolved "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-beta.15.tgz" dependencies: "@docsearch/react" "^3.0.0-alpha.39" "@docusaurus/core" "2.0.0-beta.15" @@ -1475,268 +1322,233 @@ "@docusaurus/theme-translations" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - "algoliasearch" "^4.10.5" - "algoliasearch-helper" "^3.5.5" - "clsx" "^1.1.1" - "eta" "^1.12.3" - "lodash" "^4.17.20" - "tslib" "^2.3.1" - "utility-types" "^3.10.0" + algoliasearch "^4.10.5" + algoliasearch-helper "^3.5.5" + clsx "^1.1.1" + eta "^1.12.3" + lodash "^4.17.20" + tslib "^2.3.1" + utility-types "^3.10.0" "@docusaurus/theme-translations@2.0.0-beta.15": - "integrity" "sha512-Lu2JDsnZaB2BcJe8Hpq5nrbS7+7bd09jT08b9vztQyvzR8PgzsthnzlLN4ilOeamRIuYJKo1pUGm0EsQBOP6Nw==" - "resolved" "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-2.0.0-beta.15.tgz" - "version" "2.0.0-beta.15" + version "2.0.0-beta.15" + resolved "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-2.0.0-beta.15.tgz" dependencies: - "fs-extra" "^10.0.0" - "tslib" "^2.3.1" + fs-extra "^10.0.0" + tslib "^2.3.1" "@docusaurus/utils-common@2.0.0-beta.15": - "integrity" "sha512-kIGlSIvbE/oniUpUjI8GOkSpH8o4NXbYqAh9dqPn+TJ0KbEFY3fc80gzZQU+9SunCwJMJbIxIGevX9Ry+nackw==" - "resolved" "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-2.0.0-beta.15.tgz" - "version" "2.0.0-beta.15" + version "2.0.0-beta.15" + resolved "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-2.0.0-beta.15.tgz" dependencies: - "tslib" "^2.3.1" + tslib "^2.3.1" "@docusaurus/utils-validation@2.0.0-beta.15": - "integrity" "sha512-1oOVBCkRrsTXSYrBTsMdnj3a/R56zrx11rjF4xo0+dmm8C01Xw4msFtc3uA7VLX0HQvgHsk8xPzU5GERNdsNpg==" - "resolved" "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-2.0.0-beta.15.tgz" - "version" "2.0.0-beta.15" + version "2.0.0-beta.15" + resolved "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-2.0.0-beta.15.tgz" dependencies: "@docusaurus/logger" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" - "joi" "^17.4.2" - "tslib" "^2.3.1" + joi "^17.4.2" + tslib "^2.3.1" "@docusaurus/utils@2.0.0-beta.15": - "integrity" "sha512-xkoPmFxCBkDqbZR4U3SE752OcXtWTGgZnc/pZWxItzb1IYRGNZHrzdIr7CnI7rppriuZzsyivDGiC4Ud9MWhkA==" - "resolved" "https://registry.npmjs.org/@docusaurus/utils/-/utils-2.0.0-beta.15.tgz" - "version" "2.0.0-beta.15" + version "2.0.0-beta.15" + resolved "https://registry.npmjs.org/@docusaurus/utils/-/utils-2.0.0-beta.15.tgz" dependencies: "@docusaurus/logger" "2.0.0-beta.15" "@mdx-js/runtime" "^1.6.22" "@svgr/webpack" "^6.0.0" - "file-loader" "^6.2.0" - "fs-extra" "^10.0.0" - "github-slugger" "^1.4.0" - "globby" "^11.0.4" - "gray-matter" "^4.0.3" - "js-yaml" "^4.0.0" - "lodash" "^4.17.20" - "micromatch" "^4.0.4" - "remark-mdx-remove-exports" "^1.6.22" - "remark-mdx-remove-imports" "^1.6.22" - "resolve-pathname" "^3.0.0" - "tslib" "^2.3.1" - "url-loader" "^4.1.1" + file-loader "^6.2.0" + fs-extra "^10.0.0" + github-slugger "^1.4.0" + globby "^11.0.4" + gray-matter "^4.0.3" + js-yaml "^4.0.0" + lodash "^4.17.20" + micromatch "^4.0.4" + remark-mdx-remove-exports "^1.6.22" + remark-mdx-remove-imports "^1.6.22" + resolve-pathname "^3.0.0" + tslib "^2.3.1" + url-loader "^4.1.1" "@hapi/hoek@^9.0.0": - "integrity" "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==" - "resolved" "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz" - "version" "9.2.1" + version "9.2.1" + resolved "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz" "@hapi/topo@^5.0.0": - "integrity" "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==" - "resolved" "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz" - "version" "5.1.0" + version "5.1.0" + resolved "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz" dependencies: "@hapi/hoek" "^9.0.0" "@jridgewell/gen-mapping@^0.1.0": - "integrity" "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==" - "resolved" "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz" - "version" "0.1.1" + version "0.1.1" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz" dependencies: "@jridgewell/set-array" "^1.0.0" "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": - "integrity" "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==" - "resolved" "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz" - "version" "0.3.2" + version "0.3.2" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz" dependencies: "@jridgewell/set-array" "^1.0.1" "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" "@jridgewell/resolve-uri@3.1.0": - "integrity" "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" - "resolved" "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz" - "version" "3.1.0" + version "3.1.0" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz" "@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": - "integrity" "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" - "resolved" "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz" - "version" "1.1.2" + version "1.1.2" + resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz" "@jridgewell/source-map@^0.3.2": - "integrity" "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==" - "resolved" "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz" - "version" "0.3.2" + version "0.3.2" + resolved "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz" dependencies: "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@1.4.14": - "integrity" "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" - "resolved" "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" - "version" "1.4.14" +"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": - "integrity" "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==" - "resolved" "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz" - "version" "0.3.17" + version "0.3.17" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz" dependencies: "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" -"@mdx-js/mdx@^1.6.21", "@mdx-js/mdx@1.6.22": - "integrity" "sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==" - "resolved" "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz" - "version" "1.6.22" +"@mdx-js/mdx@1.6.22", "@mdx-js/mdx@^1.6.21": + version "1.6.22" + resolved "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz" dependencies: "@babel/core" "7.12.9" "@babel/plugin-syntax-jsx" "7.12.1" "@babel/plugin-syntax-object-rest-spread" "7.8.3" "@mdx-js/util" "1.6.22" - "babel-plugin-apply-mdx-type-prop" "1.6.22" - "babel-plugin-extract-import-names" "1.6.22" - "camelcase-css" "2.0.1" - "detab" "2.0.4" - "hast-util-raw" "6.0.1" - "lodash.uniq" "4.5.0" - "mdast-util-to-hast" "10.0.1" - "remark-footnotes" "2.0.0" - "remark-mdx" "1.6.22" - "remark-parse" "8.0.3" - "remark-squeeze-paragraphs" "4.0.0" - "style-to-object" "0.3.0" - "unified" "9.2.0" - "unist-builder" "2.0.3" - "unist-util-visit" "2.0.3" - -"@mdx-js/react@^1.6.21", "@mdx-js/react@1.6.22": - "integrity" "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==" - "resolved" "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz" - "version" "1.6.22" + babel-plugin-apply-mdx-type-prop "1.6.22" + babel-plugin-extract-import-names "1.6.22" + camelcase-css "2.0.1" + detab "2.0.4" + hast-util-raw "6.0.1" + lodash.uniq "4.5.0" + mdast-util-to-hast "10.0.1" + remark-footnotes "2.0.0" + remark-mdx "1.6.22" + remark-parse "8.0.3" + remark-squeeze-paragraphs "4.0.0" + style-to-object "0.3.0" + unified "9.2.0" + unist-builder "2.0.3" + unist-util-visit "2.0.3" + +"@mdx-js/react@1.6.22", "@mdx-js/react@^1.6.21": + version "1.6.22" + resolved "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz" "@mdx-js/runtime@^1.6.22": - "integrity" "sha512-p17spaO2+55VLCuxXA3LVHC4phRx60NR2XMdZ+qgVU1lKvEX4y88dmFNOzGDCPLJ03IZyKrJ/rPWWRiBrd9JrQ==" - "resolved" "https://registry.npmjs.org/@mdx-js/runtime/-/runtime-1.6.22.tgz" - "version" "1.6.22" + version "1.6.22" + resolved "https://registry.npmjs.org/@mdx-js/runtime/-/runtime-1.6.22.tgz" dependencies: "@mdx-js/mdx" "1.6.22" "@mdx-js/react" "1.6.22" - "buble-jsx-only" "^0.19.8" + buble-jsx-only "^0.19.8" "@mdx-js/util@1.6.22": - "integrity" "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==" - "resolved" "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz" - "version" "1.6.22" + version "1.6.22" + resolved "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz" "@nodelib/fs.scandir@2.1.5": - "integrity" "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==" - "resolved" "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" - "version" "2.1.5" + version "2.1.5" + resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" dependencies: "@nodelib/fs.stat" "2.0.5" - "run-parallel" "^1.1.9" + run-parallel "^1.1.9" -"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": - "integrity" "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" - "resolved" "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" - "version" "2.0.5" +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" "@nodelib/fs.walk@^1.2.3": - "integrity" "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==" - "resolved" "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" - "version" "1.2.8" + version "1.2.8" + resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" dependencies: "@nodelib/fs.scandir" "2.1.5" - "fastq" "^1.6.0" + fastq "^1.6.0" "@polka/url@^1.0.0-next.20": - "integrity" "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==" - "resolved" "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz" - "version" "1.0.0-next.21" + version "1.0.0-next.21" + resolved "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz" "@sideway/address@^4.1.3": - "integrity" "sha512-8ncEUtmnTsMmL7z1YPB47kPUq7LpKWJNFPsRzHiIajGC5uXlWGn+AmkYPcHNl8S4tcEGx+cnORnNYaw2wvL+LQ==" - "resolved" "https://registry.npmjs.org/@sideway/address/-/address-4.1.3.tgz" - "version" "4.1.3" + version "4.1.3" + resolved "https://registry.npmjs.org/@sideway/address/-/address-4.1.3.tgz" dependencies: "@hapi/hoek" "^9.0.0" "@sideway/formula@^3.0.0": - "integrity" "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" - "resolved" "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz" - "version" "3.0.1" + version "3.0.1" + resolved "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz" "@sideway/pinpoint@^2.0.0": - "integrity" "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" - "resolved" "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz" - "version" "2.0.0" + version "2.0.0" + resolved "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz" "@sindresorhus/is@^0.14.0": - "integrity" "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" - "resolved" "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz" - "version" "0.14.0" + version "0.14.0" + resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz" "@slorber/static-site-generator-webpack-plugin@^4.0.0": - "integrity" "sha512-PSv4RIVO1Y3kvHxjvqeVisk3E9XFoO04uwYBDWe217MFqKspplYswTuKLiJu0aLORQWzuQjfVsSlLPojwfYsLw==" - "resolved" "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.1.tgz" - "version" "4.0.1" + version "4.0.1" + resolved "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.1.tgz" dependencies: - "bluebird" "^3.7.1" - "cheerio" "^0.22.0" - "eval" "^0.1.4" - "url" "^0.11.0" - "webpack-sources" "^1.4.3" + bluebird "^3.7.1" + cheerio "^0.22.0" + eval "^0.1.4" + url "^0.11.0" + webpack-sources "^1.4.3" "@svgr/babel-plugin-add-jsx-attribute@^6.0.0": - "integrity" "sha512-MdPdhdWLtQsjd29Wa4pABdhWbaRMACdM1h31BY+c6FghTZqNGT7pEYdBoaGeKtdTOBC/XNFQaKVj+r/Ei2ryWA==" - "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.0.0.tgz" - "version" "6.0.0" + version "6.0.0" + resolved "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.0.0.tgz" "@svgr/babel-plugin-remove-jsx-attribute@^6.0.0": - "integrity" "sha512-aVdtfx9jlaaxc3unA6l+M9YRnKIZjOhQPthLKqmTXC8UVkBLDRGwPKo+r8n3VZN8B34+yVajzPTZ+ptTSuZZCw==" - "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.0.0.tgz" - "version" "6.0.0" + version "6.0.0" + resolved "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.0.0.tgz" "@svgr/babel-plugin-remove-jsx-empty-expression@^6.0.0": - "integrity" "sha512-Ccj42ApsePD451AZJJf1QzTD1B/BOU392URJTeXFxSK709i0KUsGtbwyiqsKu7vsYxpTM0IA5clAKDyf9RCZyA==" - "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.0.0.tgz" - "version" "6.0.0" + version "6.0.0" + resolved "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.0.0.tgz" "@svgr/babel-plugin-replace-jsx-attribute-value@^6.0.0": - "integrity" "sha512-88V26WGyt1Sfd1emBYmBJRWMmgarrExpKNVmI9vVozha4kqs6FzQJ/Kp5+EYli1apgX44518/0+t9+NU36lThQ==" - "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.0.0.tgz" - "version" "6.0.0" + version "6.0.0" + resolved "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.0.0.tgz" "@svgr/babel-plugin-svg-dynamic-title@^6.0.0": - "integrity" "sha512-F7YXNLfGze+xv0KMQxrl2vkNbI9kzT9oDK55/kUuymh1ACyXkMV+VZWX1zEhSTfEKh7VkHVZGmVtHg8eTZ6PRg==" - "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.0.0.tgz" - "version" "6.0.0" + version "6.0.0" + resolved "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.0.0.tgz" "@svgr/babel-plugin-svg-em-dimensions@^6.0.0": - "integrity" "sha512-+rghFXxdIqJNLQK08kwPBD3Z22/0b2tEZ9lKiL/yTfuyj1wW8HUXu4bo/XkogATIYuXSghVQOOCwURXzHGKyZA==" - "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.0.0.tgz" - "version" "6.0.0" + version "6.0.0" + resolved "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.0.0.tgz" "@svgr/babel-plugin-transform-react-native-svg@^6.0.0": - "integrity" "sha512-VaphyHZ+xIKv5v0K0HCzyfAaLhPGJXSk2HkpYfXIOKb7DjLBv0soHDxNv6X0vr2titsxE7klb++u7iOf7TSrFQ==" - "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.0.0.tgz" - "version" "6.0.0" + version "6.0.0" + resolved "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.0.0.tgz" "@svgr/babel-plugin-transform-svg-component@^6.2.0": - "integrity" "sha512-bhYIpsORb++wpsp91fymbFkf09Z/YEKR0DnFjxvN+8JHeCUD2unnh18jIMKnDJTWtvpTaGYPXELVe4OOzFI0xg==" - "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.2.0.tgz" - "version" "6.2.0" + version "6.2.0" + resolved "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.2.0.tgz" "@svgr/babel-preset@^6.2.0": - "integrity" "sha512-4WQNY0J71JIaL03DRn0vLiz87JXx0b9dYm2aA8XHlQJQoixMl4r/soYHm8dsaJZ3jWtkCiOYy48dp9izvXhDkQ==" - "resolved" "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.2.0.tgz" - "version" "6.2.0" + version "6.2.0" + resolved "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.2.0.tgz" dependencies: "@svgr/babel-plugin-add-jsx-attribute" "^6.0.0" "@svgr/babel-plugin-remove-jsx-attribute" "^6.0.0" @@ -1747,46 +1559,41 @@ "@svgr/babel-plugin-transform-react-native-svg" "^6.0.0" "@svgr/babel-plugin-transform-svg-component" "^6.2.0" -"@svgr/core@^6.0.0", "@svgr/core@^6.2.1": - "integrity" "sha512-NWufjGI2WUyrg46mKuySfviEJ6IxHUOm/8a3Ph38VCWSp+83HBraCQrpEM3F3dB6LBs5x8OElS8h3C0oOJaJAA==" - "resolved" "https://registry.npmjs.org/@svgr/core/-/core-6.2.1.tgz" - "version" "6.2.1" +"@svgr/core@^6.2.1": + version "6.2.1" + resolved "https://registry.npmjs.org/@svgr/core/-/core-6.2.1.tgz" dependencies: "@svgr/plugin-jsx" "^6.2.1" - "camelcase" "^6.2.0" - "cosmiconfig" "^7.0.1" + camelcase "^6.2.0" + cosmiconfig "^7.0.1" "@svgr/hast-util-to-babel-ast@^6.2.1": - "integrity" "sha512-pt7MMkQFDlWJVy9ULJ1h+hZBDGFfSCwlBNW1HkLnVi7jUhyEXUaGYWi1x6bM2IXuAR9l265khBT4Av4lPmaNLQ==" - "resolved" "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.2.1.tgz" - "version" "6.2.1" + version "6.2.1" + resolved "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.2.1.tgz" dependencies: "@babel/types" "^7.15.6" - "entities" "^3.0.1" + entities "^3.0.1" "@svgr/plugin-jsx@^6.2.1": - "integrity" "sha512-u+MpjTsLaKo6r3pHeeSVsh9hmGRag2L7VzApWIaS8imNguqoUwDq/u6U/NDmYs/KAsrmtBjOEaAAPbwNGXXp1g==" - "resolved" "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.2.1.tgz" - "version" "6.2.1" + version "6.2.1" + resolved "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.2.1.tgz" dependencies: "@babel/core" "^7.15.5" "@svgr/babel-preset" "^6.2.0" "@svgr/hast-util-to-babel-ast" "^6.2.1" - "svg-parser" "^2.0.2" + svg-parser "^2.0.2" "@svgr/plugin-svgo@^6.2.0": - "integrity" "sha512-oDdMQONKOJEbuKwuy4Np6VdV6qoaLLvoY86hjvQEgU82Vx1MSWRyYms6Sl0f+NtqxLI/rDVufATbP/ev996k3Q==" - "resolved" "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-6.2.0.tgz" - "version" "6.2.0" + version "6.2.0" + resolved "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-6.2.0.tgz" dependencies: - "cosmiconfig" "^7.0.1" - "deepmerge" "^4.2.2" - "svgo" "^2.5.0" + cosmiconfig "^7.0.1" + deepmerge "^4.2.2" + svgo "^2.5.0" "@svgr/webpack@^6.0.0": - "integrity" "sha512-h09ngMNd13hnePwgXa+Y5CgOjzlCvfWLHg+MBnydEedAnuLRzUHUJmGS3o2OsrhxTOOqEsPOFt5v/f6C5Qulcw==" - "resolved" "https://registry.npmjs.org/@svgr/webpack/-/webpack-6.2.1.tgz" - "version" "6.2.1" + version "6.2.1" + resolved "https://registry.npmjs.org/@svgr/webpack/-/webpack-6.2.1.tgz" dependencies: "@babel/core" "^7.15.5" "@babel/plugin-transform-react-constant-elements" "^7.14.5" @@ -1798,81 +1605,70 @@ "@svgr/plugin-svgo" "^6.2.0" "@szmarczak/http-timer@^1.1.2": - "integrity" "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==" - "resolved" "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz" - "version" "1.1.2" + version "1.1.2" + resolved "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz" dependencies: - "defer-to-connect" "^1.0.1" + defer-to-connect "^1.0.1" "@trysound/sax@0.2.0": - "integrity" "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==" - "resolved" "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz" - "version" "0.2.0" + version "0.2.0" + resolved "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz" "@types/body-parser@*": - "integrity" "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==" - "resolved" "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz" - "version" "1.19.2" + version "1.19.2" + resolved "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz" dependencies: "@types/connect" "*" "@types/node" "*" "@types/bonjour@^3.5.9": - "integrity" "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==" - "resolved" "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz" - "version" "3.5.10" + version "3.5.10" + resolved "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz" dependencies: "@types/node" "*" "@types/connect-history-api-fallback@^1.3.5": - "integrity" "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==" - "resolved" "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz" - "version" "1.3.5" + version "1.3.5" + resolved "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz" dependencies: "@types/express-serve-static-core" "*" "@types/node" "*" "@types/connect@*": - "integrity" "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==" - "resolved" "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz" - "version" "3.4.35" + version "3.4.35" + resolved "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz" dependencies: "@types/node" "*" "@types/eslint-scope@^3.7.3": - "integrity" "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==" - "resolved" "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz" - "version" "3.7.3" + version "3.7.3" + resolved "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz" dependencies: "@types/eslint" "*" "@types/estree" "*" "@types/eslint@*": - "integrity" "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==" - "resolved" "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz" - "version" "8.4.1" + version "8.4.1" + resolved "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz" dependencies: "@types/estree" "*" "@types/json-schema" "*" "@types/estree@*", "@types/estree@^0.0.51": - "integrity" "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==" - "resolved" "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz" - "version" "0.0.51" + version "0.0.51" + resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz" "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18": - "integrity" "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==" - "resolved" "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz" - "version" "4.17.28" + version "4.17.28" + resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz" dependencies: "@types/node" "*" "@types/qs" "*" "@types/range-parser" "*" "@types/express@*", "@types/express@^4.17.13": - "integrity" "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==" - "resolved" "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz" - "version" "4.17.13" + version "4.17.13" + resolved "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz" dependencies: "@types/body-parser" "*" "@types/express-serve-static-core" "^4.17.18" @@ -1880,172 +1676,144 @@ "@types/serve-static" "*" "@types/hast@^2.0.0": - "integrity" "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==" - "resolved" "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz" - "version" "2.3.4" + version "2.3.4" + resolved "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz" dependencies: "@types/unist" "*" "@types/html-minifier-terser@^6.0.0": - "integrity" "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" - "resolved" "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz" - "version" "6.1.0" + version "6.1.0" + resolved "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz" "@types/http-proxy@^1.17.8": - "integrity" "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==" - "resolved" "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz" - "version" "1.17.8" + version "1.17.8" + resolved "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz" dependencies: "@types/node" "*" "@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": - "integrity" "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" - "resolved" "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz" - "version" "7.0.9" + version "7.0.9" + resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz" "@types/mdast@^3.0.0": - "integrity" "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==" - "resolved" "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz" - "version" "3.0.10" + version "3.0.10" + resolved "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz" dependencies: "@types/unist" "*" "@types/mime@^1": - "integrity" "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" - "resolved" "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz" - "version" "1.3.2" + version "1.3.2" + resolved "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz" "@types/node@*", "@types/node@^17.0.5": - "integrity" "sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==" - "resolved" "https://registry.npmjs.org/@types/node/-/node-17.0.18.tgz" - "version" "17.0.18" + version "17.0.18" + resolved "https://registry.npmjs.org/@types/node/-/node-17.0.18.tgz" "@types/parse-json@^4.0.0": - "integrity" "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" - "resolved" "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz" - "version" "4.0.0" + version "4.0.0" + resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz" "@types/parse5@^5.0.0": - "integrity" "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==" - "resolved" "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz" - "version" "5.0.3" + version "5.0.3" + resolved "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz" "@types/prop-types@*": - "integrity" "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==" - "resolved" "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz" - "version" "15.7.4" + version "15.7.4" + resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz" "@types/qs@*": - "integrity" "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" - "resolved" "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz" - "version" "6.9.7" + version "6.9.7" + resolved "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz" "@types/range-parser@*": - "integrity" "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" - "resolved" "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz" - "version" "1.2.4" + version "1.2.4" + resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz" -"@types/react@*", "@types/react@>= 16.8.0 < 18.0.0": - "integrity" "sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==" - "resolved" "https://registry.npmjs.org/@types/react/-/react-17.0.39.tgz" - "version" "17.0.39" +"@types/react@*": + version "17.0.39" + resolved "https://registry.npmjs.org/@types/react/-/react-17.0.39.tgz" dependencies: "@types/prop-types" "*" "@types/scheduler" "*" - "csstype" "^3.0.2" + csstype "^3.0.2" "@types/retry@^0.12.0": - "integrity" "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==" - "resolved" "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz" - "version" "0.12.1" + version "0.12.1" + resolved "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz" "@types/sax@^1.2.1": - "integrity" "sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw==" - "resolved" "https://registry.npmjs.org/@types/sax/-/sax-1.2.4.tgz" - "version" "1.2.4" + version "1.2.4" + resolved "https://registry.npmjs.org/@types/sax/-/sax-1.2.4.tgz" dependencies: "@types/node" "*" "@types/scheduler@*": - "integrity" "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" - "resolved" "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz" - "version" "0.16.2" + version "0.16.2" + resolved "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz" "@types/serve-index@^1.9.1": - "integrity" "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==" - "resolved" "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz" - "version" "1.9.1" + version "1.9.1" + resolved "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz" dependencies: "@types/express" "*" "@types/serve-static@*": - "integrity" "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==" - "resolved" "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz" - "version" "1.13.10" + version "1.13.10" + resolved "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz" dependencies: "@types/mime" "^1" "@types/node" "*" "@types/sockjs@^0.3.33": - "integrity" "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==" - "resolved" "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz" - "version" "0.3.33" + version "0.3.33" + resolved "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz" dependencies: "@types/node" "*" "@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": - "integrity" "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" - "resolved" "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz" - "version" "2.0.6" + version "2.0.6" + resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz" "@types/ws@^8.2.2": - "integrity" "sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg==" - "resolved" "https://registry.npmjs.org/@types/ws/-/ws-8.2.2.tgz" - "version" "8.2.2" + version "8.2.2" + resolved "https://registry.npmjs.org/@types/ws/-/ws-8.2.2.tgz" dependencies: "@types/node" "*" "@webassemblyjs/ast@1.11.1": - "integrity" "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==" - "resolved" "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz" - "version" "1.11.1" + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz" dependencies: "@webassemblyjs/helper-numbers" "1.11.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.1" "@webassemblyjs/floating-point-hex-parser@1.11.1": - "integrity" "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==" - "resolved" "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz" - "version" "1.11.1" + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz" "@webassemblyjs/helper-api-error@1.11.1": - "integrity" "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==" - "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz" - "version" "1.11.1" + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz" "@webassemblyjs/helper-buffer@1.11.1": - "integrity" "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==" - "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz" - "version" "1.11.1" + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz" "@webassemblyjs/helper-numbers@1.11.1": - "integrity" "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==" - "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz" - "version" "1.11.1" + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz" dependencies: "@webassemblyjs/floating-point-hex-parser" "1.11.1" "@webassemblyjs/helper-api-error" "1.11.1" "@xtuc/long" "4.2.2" "@webassemblyjs/helper-wasm-bytecode@1.11.1": - "integrity" "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==" - "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz" - "version" "1.11.1" + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz" "@webassemblyjs/helper-wasm-section@1.11.1": - "integrity" "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==" - "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz" - "version" "1.11.1" + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz" dependencies: "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/helper-buffer" "1.11.1" @@ -2053,28 +1821,24 @@ "@webassemblyjs/wasm-gen" "1.11.1" "@webassemblyjs/ieee754@1.11.1": - "integrity" "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==" - "resolved" "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz" - "version" "1.11.1" + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz" dependencies: "@xtuc/ieee754" "^1.2.0" "@webassemblyjs/leb128@1.11.1": - "integrity" "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==" - "resolved" "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz" - "version" "1.11.1" + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz" dependencies: "@xtuc/long" "4.2.2" "@webassemblyjs/utf8@1.11.1": - "integrity" "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==" - "resolved" "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz" - "version" "1.11.1" + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz" "@webassemblyjs/wasm-edit@1.11.1": - "integrity" "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==" - "resolved" "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz" - "version" "1.11.1" + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz" dependencies: "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/helper-buffer" "1.11.1" @@ -2086,9 +1850,8 @@ "@webassemblyjs/wast-printer" "1.11.1" "@webassemblyjs/wasm-gen@1.11.1": - "integrity" "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==" - "resolved" "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz" - "version" "1.11.1" + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz" dependencies: "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.1" @@ -2097,9 +1860,8 @@ "@webassemblyjs/utf8" "1.11.1" "@webassemblyjs/wasm-opt@1.11.1": - "integrity" "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==" - "resolved" "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz" - "version" "1.11.1" + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz" dependencies: "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/helper-buffer" "1.11.1" @@ -2107,9 +1869,8 @@ "@webassemblyjs/wasm-parser" "1.11.1" "@webassemblyjs/wasm-parser@1.11.1": - "integrity" "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==" - "resolved" "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz" - "version" "1.11.1" + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz" dependencies: "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/helper-api-error" "1.11.1" @@ -2119,124 +1880,109 @@ "@webassemblyjs/utf8" "1.11.1" "@webassemblyjs/wast-printer@1.11.1": - "integrity" "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==" - "resolved" "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz" - "version" "1.11.1" + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz" dependencies: "@webassemblyjs/ast" "1.11.1" "@xtuc/long" "4.2.2" "@xtuc/ieee754@^1.2.0": - "integrity" "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" - "resolved" "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz" - "version" "1.2.0" + version "1.2.0" + resolved "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz" "@xtuc/long@4.2.2": - "integrity" "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" - "resolved" "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz" - "version" "4.2.2" - -"accepts@~1.3.4", "accepts@~1.3.5", "accepts@~1.3.8": - "integrity" "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==" - "resolved" "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz" - "version" "1.3.8" - dependencies: - "mime-types" "~2.1.34" - "negotiator" "0.6.3" - -"acorn-dynamic-import@^4.0.0": - "integrity" "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==" - "resolved" "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz" - "version" "4.0.0" - -"acorn-import-assertions@^1.7.6": - "integrity" "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==" - "resolved" "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz" - "version" "1.8.0" - -"acorn-jsx@^5.0.1": - "integrity" "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==" - "resolved" "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" - "version" "5.3.2" - -"acorn-walk@^8.0.0": - "integrity" "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" - "resolved" "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" - "version" "8.2.0" - -"acorn@^6.0.0", "acorn@^6.0.0 || ^7.0.0 || ^8.0.0", "acorn@^6.1.1": - "integrity" "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==" - "resolved" "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz" - "version" "6.4.2" - -"acorn@^8", "acorn@^8.0.4", "acorn@^8.4.1", "acorn@^8.5.0": - "integrity" "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==" - "resolved" "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz" - "version" "8.7.1" - -"address@^1.0.1", "address@^1.1.2": - "integrity" "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==" - "resolved" "https://registry.npmjs.org/address/-/address-1.1.2.tgz" - "version" "1.1.2" - -"aggregate-error@^3.0.0": - "integrity" "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==" - "resolved" "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz" - "version" "3.1.0" - dependencies: - "clean-stack" "^2.0.0" - "indent-string" "^4.0.0" - -"ajv-formats@^2.1.1": - "integrity" "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==" - "resolved" "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz" - "version" "2.1.1" - dependencies: - "ajv" "^8.0.0" - -"ajv-keywords@^3.4.1", "ajv-keywords@^3.5.2": - "integrity" "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" - "resolved" "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" - "version" "3.5.2" - -"ajv-keywords@^5.0.0": - "integrity" "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==" - "resolved" "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz" - "version" "5.1.0" - dependencies: - "fast-deep-equal" "^3.1.3" - -"ajv@^6.12.2", "ajv@^6.12.4", "ajv@^6.12.5", "ajv@^6.9.1": - "integrity" "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==" - "resolved" "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" - "version" "6.12.6" - dependencies: - "fast-deep-equal" "^3.1.1" - "fast-json-stable-stringify" "^2.0.0" - "json-schema-traverse" "^0.4.1" - "uri-js" "^4.2.2" - -"ajv@^8.0.0", "ajv@^8.8.0", "ajv@^8.8.2": - "integrity" "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==" - "resolved" "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz" - "version" "8.10.0" - dependencies: - "fast-deep-equal" "^3.1.1" - "json-schema-traverse" "^1.0.0" - "require-from-string" "^2.0.2" - "uri-js" "^4.2.2" - -"algoliasearch-helper@^3.5.5": - "integrity" "sha512-XJ3QfERBLfeVCyTVx80gon7r3/rgm/CE8Ha1H7cbablRe/X7SfYQ14g/eO+MhjVKIQp+gy9oC6G5ilmLwS1k6w==" - "resolved" "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.7.0.tgz" - "version" "3.7.0" + version "4.2.2" + resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz" + +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz" + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn-dynamic-import@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz" + +acorn-import-assertions@^1.7.6: + version "1.8.0" + resolved "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz" + +acorn-jsx@^5.0.1: + version "5.3.2" + resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" + +acorn-walk@^8.0.0: + version "8.2.0" + resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" + +acorn@^6.1.1: + version "6.4.2" + resolved "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz" + +acorn@^8.0.4, acorn@^8.5.0: + version "8.7.1" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz" + +acorn@^8.7.1: + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + +address@^1.0.1, address@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/address/-/address-1.1.2.tgz" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz" + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz" + dependencies: + ajv "^8.0.0" + +ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" + +ajv-keywords@^5.0.0: + version "5.1.0" + resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz" + dependencies: + fast-deep-equal "^3.1.3" + +ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.0, ajv@^8.8.0: + version "8.10.0" + resolved "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz" + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +algoliasearch-helper@^3.5.5: + version "3.7.0" + resolved "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.7.0.tgz" dependencies: "@algolia/events" "^4.0.1" -"algoliasearch@^4.0.0", "algoliasearch@^4.10.5", "algoliasearch@^4.9.1", "algoliasearch@>= 3.1 < 5": - "integrity" "sha512-c0dM1g3zZBJrkzE5GA/Nu1y3fFxx3LCzxKzcmp2dgGS8P4CjszB/l3lsSh2MSrrK1Hn/KV4BlbBMXtYgG1Bfrw==" - "resolved" "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.12.1.tgz" - "version" "4.12.1" +algoliasearch@^4.0.0, algoliasearch@^4.10.5: + version "4.12.1" + resolved "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.12.1.tgz" dependencies: "@algolia/cache-browser-local-storage" "4.12.1" "@algolia/cache-common" "4.12.1" @@ -2253,5546 +1999,4702 @@ "@algolia/requester-node-http" "4.12.1" "@algolia/transporter" "4.12.1" -"ansi-align@^3.0.0": - "integrity" "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==" - "resolved" "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz" - "version" "3.0.1" - dependencies: - "string-width" "^4.1.0" - -"ansi-html-community@^0.0.8": - "integrity" "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==" - "resolved" "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz" - "version" "0.0.8" - -"ansi-regex@^5.0.1": - "integrity" "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" - "version" "5.0.1" - -"ansi-regex@^6.0.1": - "integrity" "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" - "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz" - "version" "6.0.1" - -"ansi-styles@^3.2.1": - "integrity" "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==" - "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" - "version" "3.2.1" - dependencies: - "color-convert" "^1.9.0" - -"ansi-styles@^4.0.0", "ansi-styles@^4.1.0": - "integrity" "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==" - "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" - "version" "4.3.0" - dependencies: - "color-convert" "^2.0.1" - -"anymatch@~3.1.2": - "integrity" "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==" - "resolved" "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz" - "version" "3.1.2" - dependencies: - "normalize-path" "^3.0.0" - "picomatch" "^2.0.4" - -"arg@^5.0.0": - "integrity" "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==" - "resolved" "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz" - "version" "5.0.1" - -"argparse@^1.0.7": - "integrity" "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==" - "resolved" "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" - "version" "1.0.10" - dependencies: - "sprintf-js" "~1.0.2" - -"argparse@^2.0.1": - "integrity" "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - "resolved" "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" - "version" "2.0.1" - -"array-flatten@^2.1.0": - "integrity" "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" - "resolved" "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz" - "version" "2.1.2" - -"array-flatten@1.1.1": - "integrity" "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - "resolved" "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" - "version" "1.1.1" - -"array-union@^2.1.0": - "integrity" "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" - "resolved" "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" - "version" "2.1.0" - -"array-union@^3.0.1": - "integrity" "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==" - "resolved" "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz" - "version" "3.0.1" - -"asap@~2.0.3": - "integrity" "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" - "resolved" "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz" - "version" "2.0.6" - -"async@^2.6.2": - "integrity" "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==" - "resolved" "https://registry.npmjs.org/async/-/async-2.6.4.tgz" - "version" "2.6.4" - dependencies: - "lodash" "^4.17.14" - -"at-least-node@^1.0.0": - "integrity" "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" - "resolved" "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz" - "version" "1.0.0" - -"autoprefixer@^10.3.5", "autoprefixer@^10.3.7": - "integrity" "sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==" - "resolved" "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz" - "version" "10.4.2" - dependencies: - "browserslist" "^4.19.1" - "caniuse-lite" "^1.0.30001297" - "fraction.js" "^4.1.2" - "normalize-range" "^0.1.2" - "picocolors" "^1.0.0" - "postcss-value-parser" "^4.2.0" - -"axios@^0.25.0": - "integrity" "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==" - "resolved" "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz" - "version" "0.25.0" - dependencies: - "follow-redirects" "^1.14.7" - -"babel-loader@^8.2.2": - "integrity" "sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw==" - "resolved" "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.3.tgz" - "version" "8.2.3" - dependencies: - "find-cache-dir" "^3.3.1" - "loader-utils" "^1.4.0" - "make-dir" "^3.1.0" - "schema-utils" "^2.6.5" - -"babel-plugin-apply-mdx-type-prop@1.6.22": - "integrity" "sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ==" - "resolved" "https://registry.npmjs.org/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz" - "version" "1.6.22" +ansi-align@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz" dependencies: - "@babel/helper-plugin-utils" "7.10.4" - "@mdx-js/util" "1.6.22" + string-width "^4.1.0" + +ansi-html-community@^0.0.8: + version "0.0.8" + resolved "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz" -"babel-plugin-dynamic-import-node@^2.3.3": - "integrity" "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==" - "resolved" "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz" - "version" "2.3.3" +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" + +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz" + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" dependencies: - "object.assign" "^4.1.0" + color-convert "^1.9.0" -"babel-plugin-dynamic-import-node@2.3.0": - "integrity" "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==" - "resolved" "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz" - "version" "2.3.0" +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" dependencies: - "object.assign" "^4.1.0" + color-convert "^2.0.1" -"babel-plugin-extract-import-names@1.6.22": - "integrity" "sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ==" - "resolved" "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz" - "version" "1.6.22" +anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz" dependencies: - "@babel/helper-plugin-utils" "7.10.4" + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^5.0.0: + version "5.0.1" + resolved "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz" -"babel-plugin-polyfill-corejs2@^0.3.0": - "integrity" "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==" - "resolved" "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz" - "version" "0.3.1" +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" dependencies: - "@babel/compat-data" "^7.13.11" - "@babel/helper-define-polyfill-provider" "^0.3.1" - "semver" "^6.1.1" + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" + +array-flatten@^2.1.0: + version "2.1.2" + resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" + +array-union@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz" + +asap@~2.0.3: + version "2.0.6" + resolved "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz" -"babel-plugin-polyfill-corejs3@^0.5.0": - "integrity" "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==" - "resolved" "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz" - "version" "0.5.2" +async@^2.6.2: + version "2.6.4" + resolved "https://registry.npmjs.org/async/-/async-2.6.4.tgz" dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.1" - "core-js-compat" "^3.21.0" + lodash "^4.17.14" + +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz" -"babel-plugin-polyfill-regenerator@^0.3.0": - "integrity" "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==" - "resolved" "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz" - "version" "0.3.1" +autoprefixer@^10.3.5, autoprefixer@^10.3.7: + version "10.4.2" + resolved "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz" dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.1" + browserslist "^4.19.1" + caniuse-lite "^1.0.30001297" + fraction.js "^4.1.2" + normalize-range "^0.1.2" + picocolors "^1.0.0" + postcss-value-parser "^4.2.0" -"bail@^1.0.0": - "integrity" "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==" - "resolved" "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz" - "version" "1.0.5" - -"balanced-match@^1.0.0": - "integrity" "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - "resolved" "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" - "version" "1.0.2" - -"base16@^1.0.0": - "integrity" "sha1-4pf2DX7BAUp6lxo568ipjAtoHnA=" - "resolved" "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz" - "version" "1.0.0" - -"batch@0.6.1": - "integrity" "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" - "resolved" "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz" - "version" "0.6.1" - -"big.js@^5.2.2": - "integrity" "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" - "resolved" "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz" - "version" "5.2.2" - -"binary-extensions@^2.0.0": - "integrity" "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" - "resolved" "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" - "version" "2.2.0" - -"bluebird@^3.7.1": - "integrity" "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - "resolved" "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz" - "version" "3.7.2" - -"body-parser@1.19.2": - "integrity" "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==" - "resolved" "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz" - "version" "1.19.2" - dependencies: - "bytes" "3.1.2" - "content-type" "~1.0.4" - "debug" "2.6.9" - "depd" "~1.1.2" - "http-errors" "1.8.1" - "iconv-lite" "0.4.24" - "on-finished" "~2.3.0" - "qs" "6.9.7" - "raw-body" "2.4.3" - "type-is" "~1.6.18" - -"bonjour@^3.5.0": - "integrity" "sha1-jokKGD2O6aI5OzhExpGkK897yfU=" - "resolved" "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz" - "version" "3.5.0" - dependencies: - "array-flatten" "^2.1.0" - "deep-equal" "^1.0.1" - "dns-equal" "^1.0.0" - "dns-txt" "^2.0.2" - "multicast-dns" "^6.0.1" - "multicast-dns-service-types" "^1.1.0" - -"boolbase@^1.0.0", "boolbase@~1.0.0": - "integrity" "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" - "resolved" "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz" - "version" "1.0.0" - -"boxen@^5.0.0", "boxen@^5.0.1": - "integrity" "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==" - "resolved" "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz" - "version" "5.1.2" - dependencies: - "ansi-align" "^3.0.0" - "camelcase" "^6.2.0" - "chalk" "^4.1.0" - "cli-boxes" "^2.2.1" - "string-width" "^4.2.2" - "type-fest" "^0.20.2" - "widest-line" "^3.1.0" - "wrap-ansi" "^7.0.0" - -"brace-expansion@^1.1.7": - "integrity" "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==" - "resolved" "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" - "version" "1.1.11" - dependencies: - "balanced-match" "^1.0.0" - "concat-map" "0.0.1" - -"braces@^3.0.1", "braces@~3.0.2": - "integrity" "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==" - "resolved" "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" - "version" "3.0.2" - dependencies: - "fill-range" "^7.0.1" - -"browserslist@^4.0.0", "browserslist@^4.14.5", "browserslist@^4.16.6", "browserslist@^4.18.1", "browserslist@^4.19.1", "browserslist@^4.21.3", "browserslist@>= 4.21.0": - "integrity" "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==" - "resolved" "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz" - "version" "4.21.5" - dependencies: - "caniuse-lite" "^1.0.30001449" - "electron-to-chromium" "^1.4.284" - "node-releases" "^2.0.8" - "update-browserslist-db" "^1.0.10" - -"buble-jsx-only@^0.19.8": - "integrity" "sha512-7AW19pf7PrKFnGTEDzs6u9+JZqQwM1VnLS19OlqYDhXomtFFknnoQJAPHeg84RMFWAvOhYrG7harizJNwUKJsA==" - "resolved" "https://registry.npmjs.org/buble-jsx-only/-/buble-jsx-only-0.19.8.tgz" - "version" "0.19.8" - dependencies: - "acorn" "^6.1.1" - "acorn-dynamic-import" "^4.0.0" - "acorn-jsx" "^5.0.1" - "chalk" "^2.4.2" - "magic-string" "^0.25.3" - "minimist" "^1.2.0" - "regexpu-core" "^4.5.4" - -"buffer-from@^1.0.0": - "integrity" "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - "resolved" "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" - "version" "1.1.2" - -"buffer-indexof@^1.0.0": - "integrity" "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==" - "resolved" "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz" - "version" "1.1.1" - -"bytes@3.0.0": - "integrity" "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" - "resolved" "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz" - "version" "3.0.0" - -"bytes@3.1.2": - "integrity" "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - "resolved" "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" - "version" "3.1.2" - -"cacheable-request@^6.0.0": - "integrity" "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==" - "resolved" "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz" - "version" "6.1.0" - dependencies: - "clone-response" "^1.0.2" - "get-stream" "^5.1.0" - "http-cache-semantics" "^4.0.0" - "keyv" "^3.0.0" - "lowercase-keys" "^2.0.0" - "normalize-url" "^4.1.0" - "responselike" "^1.0.2" - -"call-bind@^1.0.0", "call-bind@^1.0.2": - "integrity" "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==" - "resolved" "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" - "version" "1.0.2" - dependencies: - "function-bind" "^1.1.1" - "get-intrinsic" "^1.0.2" - -"callsites@^3.0.0": - "integrity" "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" - "resolved" "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" - "version" "3.1.0" - -"camel-case@^4.1.2": - "integrity" "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==" - "resolved" "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz" - "version" "4.1.2" - dependencies: - "pascal-case" "^3.1.2" - "tslib" "^2.0.3" - -"camelcase-css@2.0.1": - "integrity" "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==" - "resolved" "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz" - "version" "2.0.1" - -"camelcase@^6.2.0": - "integrity" "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" - "resolved" "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" - "version" "6.3.0" - -"caniuse-api@^3.0.0": - "integrity" "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==" - "resolved" "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz" - "version" "3.0.0" - dependencies: - "browserslist" "^4.0.0" - "caniuse-lite" "^1.0.0" - "lodash.memoize" "^4.1.2" - "lodash.uniq" "^4.5.0" - -"caniuse-lite@^1.0.0", "caniuse-lite@^1.0.30001297", "caniuse-lite@^1.0.30001449": - "integrity" "sha512-ewtFBSfWjEmxUgNBSZItFSmVtvk9zkwkl1OfRZlKA8slltRN+/C/tuGVrF9styXkN36Yu3+SeJ1qkXxDEyNZ5w==" - "resolved" "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001466.tgz" - "version" "1.0.30001466" - -"ccount@^1.0.0", "ccount@^1.0.3": - "integrity" "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==" - "resolved" "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz" - "version" "1.1.0" - -"chalk@^2.0.0": - "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==" - "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" - "version" "2.4.2" - dependencies: - "ansi-styles" "^3.2.1" - "escape-string-regexp" "^1.0.5" - "supports-color" "^5.3.0" - -"chalk@^2.4.2": - "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==" - "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" - "version" "2.4.2" - dependencies: - "ansi-styles" "^3.2.1" - "escape-string-regexp" "^1.0.5" - "supports-color" "^5.3.0" - -"chalk@^4.1.0", "chalk@^4.1.2": - "integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==" - "resolved" "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" - "version" "4.1.2" - dependencies: - "ansi-styles" "^4.1.0" - "supports-color" "^7.1.0" - -"character-entities-legacy@^1.0.0": - "integrity" "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==" - "resolved" "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz" - "version" "1.1.4" - -"character-entities@^1.0.0": - "integrity" "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==" - "resolved" "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz" - "version" "1.2.4" - -"character-reference-invalid@^1.0.0": - "integrity" "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==" - "resolved" "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz" - "version" "1.1.4" - -"cheerio-select@^1.5.0": - "integrity" "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==" - "resolved" "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz" - "version" "1.5.0" - dependencies: - "css-select" "^4.1.3" - "css-what" "^5.0.1" - "domelementtype" "^2.2.0" - "domhandler" "^4.2.0" - "domutils" "^2.7.0" - -"cheerio@^0.22.0": - "integrity" "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=" - "resolved" "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz" - "version" "0.22.0" - dependencies: - "css-select" "~1.2.0" - "dom-serializer" "~0.1.0" - "entities" "~1.1.1" - "htmlparser2" "^3.9.1" - "lodash.assignin" "^4.0.9" - "lodash.bind" "^4.1.4" - "lodash.defaults" "^4.0.1" - "lodash.filter" "^4.4.0" - "lodash.flatten" "^4.2.0" - "lodash.foreach" "^4.3.0" - "lodash.map" "^4.4.0" - "lodash.merge" "^4.4.0" - "lodash.pick" "^4.2.1" - "lodash.reduce" "^4.4.0" - "lodash.reject" "^4.4.0" - "lodash.some" "^4.4.0" - -"cheerio@^1.0.0-rc.10": - "integrity" "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==" - "resolved" "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz" - "version" "1.0.0-rc.10" - dependencies: - "cheerio-select" "^1.5.0" - "dom-serializer" "^1.3.2" - "domhandler" "^4.2.0" - "htmlparser2" "^6.1.0" - "parse5" "^6.0.1" - "parse5-htmlparser2-tree-adapter" "^6.0.1" - "tslib" "^2.2.0" - -"chokidar@^3.4.2", "chokidar@^3.5.2", "chokidar@^3.5.3": - "integrity" "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==" - "resolved" "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" - "version" "3.5.3" - dependencies: - "anymatch" "~3.1.2" - "braces" "~3.0.2" - "glob-parent" "~5.1.2" - "is-binary-path" "~2.1.0" - "is-glob" "~4.0.1" - "normalize-path" "~3.0.0" - "readdirp" "~3.6.0" - optionalDependencies: - "fsevents" "~2.3.2" - -"chrome-trace-event@^1.0.2": - "integrity" "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==" - "resolved" "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz" - "version" "1.0.3" - -"ci-info@^2.0.0": - "integrity" "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" - "resolved" "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz" - "version" "2.0.0" - -"classnames@^2.2.6": - "integrity" "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" - "resolved" "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz" - "version" "2.3.1" - -"clean-css@^5.1.5", "clean-css@^5.2.2": - "integrity" "sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg==" - "resolved" "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz" - "version" "5.2.4" - dependencies: - "source-map" "~0.6.0" - -"clean-stack@^2.0.0": - "integrity" "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" - "resolved" "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz" - "version" "2.2.0" - -"cli-boxes@^2.2.1": - "integrity" "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==" - "resolved" "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz" - "version" "2.2.1" - -"clone-deep@^4.0.1": - "integrity" "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==" - "resolved" "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz" - "version" "4.0.1" - dependencies: - "is-plain-object" "^2.0.4" - "kind-of" "^6.0.2" - "shallow-clone" "^3.0.0" - -"clone-response@^1.0.2": - "integrity" "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=" - "resolved" "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz" - "version" "1.0.2" - dependencies: - "mimic-response" "^1.0.0" - -"clsx@^1.1.1": - "integrity" "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==" - "resolved" "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz" - "version" "1.1.1" - -"collapse-white-space@^1.0.2": - "integrity" "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==" - "resolved" "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz" - "version" "1.0.6" - -"color-convert@^1.9.0": - "integrity" "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==" - "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" - "version" "1.9.3" - dependencies: - "color-name" "1.1.3" - -"color-convert@^2.0.1": - "integrity" "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==" - "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" - "version" "2.0.1" - dependencies: - "color-name" "~1.1.4" - -"color-name@~1.1.4": - "integrity" "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" - "version" "1.1.4" - -"color-name@1.1.3": - "integrity" "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" - "version" "1.1.3" - -"colord@^2.9.1": - "integrity" "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==" - "resolved" "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz" - "version" "2.9.2" - -"colorette@^2.0.10": - "integrity" "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==" - "resolved" "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz" - "version" "2.0.16" - -"combine-promises@^1.1.0": - "integrity" "sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg==" - "resolved" "https://registry.npmjs.org/combine-promises/-/combine-promises-1.1.0.tgz" - "version" "1.1.0" - -"comma-separated-tokens@^1.0.0": - "integrity" "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==" - "resolved" "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz" - "version" "1.0.8" - -"commander@^2.20.0": - "integrity" "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - "resolved" "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" - "version" "2.20.3" - -"commander@^5.1.0": - "integrity" "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" - "resolved" "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz" - "version" "5.1.0" - -"commander@^7.2.0": - "integrity" "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" - "resolved" "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz" - "version" "7.2.0" - -"commander@^8.3.0": - "integrity" "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==" - "resolved" "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz" - "version" "8.3.0" - -"commondir@^1.0.1": - "integrity" "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" - "resolved" "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" - "version" "1.0.1" - -"compressible@~2.0.16": - "integrity" "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==" - "resolved" "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz" - "version" "2.0.18" - dependencies: - "mime-db" ">= 1.43.0 < 2" - -"compression@^1.7.4": - "integrity" "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==" - "resolved" "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz" - "version" "1.7.4" - dependencies: - "accepts" "~1.3.5" - "bytes" "3.0.0" - "compressible" "~2.0.16" - "debug" "2.6.9" - "on-headers" "~1.0.2" - "safe-buffer" "5.1.2" - "vary" "~1.1.2" - -"concat-map@0.0.1": - "integrity" "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - "resolved" "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" - "version" "0.0.1" - -"configstore@^5.0.1": - "integrity" "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==" - "resolved" "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz" - "version" "5.0.1" - dependencies: - "dot-prop" "^5.2.0" - "graceful-fs" "^4.1.2" - "make-dir" "^3.0.0" - "unique-string" "^2.0.0" - "write-file-atomic" "^3.0.0" - "xdg-basedir" "^4.0.0" - -"connect-history-api-fallback@^1.6.0": - "integrity" "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==" - "resolved" "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz" - "version" "1.6.0" - -"consola@^2.15.3": - "integrity" "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" - "resolved" "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz" - "version" "2.15.3" - -"content-disposition@0.5.2": - "integrity" "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" - "resolved" "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz" - "version" "0.5.2" - -"content-disposition@0.5.4": - "integrity" "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==" - "resolved" "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz" - "version" "0.5.4" - dependencies: - "safe-buffer" "5.2.1" - -"content-type@~1.0.4": - "integrity" "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - "resolved" "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz" - "version" "1.0.4" - -"convert-source-map@^1.7.0": - "integrity" "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==" - "resolved" "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz" - "version" "1.8.0" - dependencies: - "safe-buffer" "~5.1.1" - -"cookie-signature@1.0.6": - "integrity" "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - "resolved" "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" - "version" "1.0.6" - -"cookie@0.4.2": - "integrity" "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" - "resolved" "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz" - "version" "0.4.2" - -"copy-text-to-clipboard@^3.0.1": - "integrity" "sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q==" - "resolved" "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz" - "version" "3.0.1" - -"copy-webpack-plugin@^10.2.0": - "integrity" "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==" - "resolved" "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz" - "version" "10.2.4" - dependencies: - "fast-glob" "^3.2.7" - "glob-parent" "^6.0.1" - "globby" "^12.0.2" - "normalize-path" "^3.0.0" - "schema-utils" "^4.0.0" - "serialize-javascript" "^6.0.0" - -"core-js-compat@^3.20.2", "core-js-compat@^3.21.0": - "integrity" "sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g==" - "resolved" "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.21.1.tgz" - "version" "3.21.1" - dependencies: - "browserslist" "^4.19.1" - "semver" "7.0.0" - -"core-js-pure@^3.20.2": - "integrity" "sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ==" - "resolved" "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.21.1.tgz" - "version" "3.21.1" - -"core-js@^3.18.0": - "integrity" "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==" - "resolved" "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz" - "version" "3.21.1" - -"core-util-is@~1.0.0": - "integrity" "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - "resolved" "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" - "version" "1.0.3" - -"cosmiconfig@^6.0.0": - "integrity" "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==" - "resolved" "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz" - "version" "6.0.0" +axios@^0.25.0: + version "0.25.0" + resolved "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz" dependencies: - "@types/parse-json" "^4.0.0" - "import-fresh" "^3.1.0" - "parse-json" "^5.0.0" - "path-type" "^4.0.0" - "yaml" "^1.7.2" + follow-redirects "^1.14.7" -"cosmiconfig@^7.0.0", "cosmiconfig@^7.0.1": - "integrity" "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==" - "resolved" "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz" - "version" "7.0.1" +babel-loader@^8.2.2: + version "8.2.3" + resolved "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.3.tgz" dependencies: - "@types/parse-json" "^4.0.0" - "import-fresh" "^3.2.1" - "parse-json" "^5.0.0" - "path-type" "^4.0.0" - "yaml" "^1.10.0" - -"cross-fetch@^3.1.5": - "integrity" "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==" - "resolved" "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz" - "version" "3.1.5" - dependencies: - "node-fetch" "2.6.7" - -"cross-spawn@^7.0.3": - "integrity" "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==" - "resolved" "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" - "version" "7.0.3" - dependencies: - "path-key" "^3.1.0" - "shebang-command" "^2.0.0" - "which" "^2.0.1" - -"crypto-random-string@^2.0.0": - "integrity" "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" - "resolved" "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz" - "version" "2.0.0" - -"css-declaration-sorter@^6.0.3": - "integrity" "sha512-lpfkqS0fctcmZotJGhnxkIyJWvBXgpyi2wsFd4J8VB7wzyrT6Ch/3Q+FMNJpjK4gu1+GN5khOnpU2ZVKrLbhCw==" - "resolved" "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz" - "version" "6.1.4" - dependencies: - "timsort" "^0.3.0" - -"css-loader@^6.5.1": - "integrity" "sha512-FK7H2lisOixPT406s5gZM1S3l8GrfhEBT3ZiL2UX1Ng1XWs0y2GPllz/OTyvbaHe12VgQrIXIzuEGVlbUhodqg==" - "resolved" "https://registry.npmjs.org/css-loader/-/css-loader-6.6.0.tgz" - "version" "6.6.0" - dependencies: - "icss-utils" "^5.1.0" - "postcss" "^8.4.5" - "postcss-modules-extract-imports" "^3.0.0" - "postcss-modules-local-by-default" "^4.0.0" - "postcss-modules-scope" "^3.0.0" - "postcss-modules-values" "^4.0.0" - "postcss-value-parser" "^4.2.0" - "semver" "^7.3.5" - -"css-minimizer-webpack-plugin@^3.3.1": - "integrity" "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==" - "resolved" "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz" - "version" "3.4.1" - dependencies: - "cssnano" "^5.0.6" - "jest-worker" "^27.0.2" - "postcss" "^8.3.5" - "schema-utils" "^4.0.0" - "serialize-javascript" "^6.0.0" - "source-map" "^0.6.1" - -"css-select@^4.1.3": - "integrity" "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==" - "resolved" "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz" - "version" "4.2.1" - dependencies: - "boolbase" "^1.0.0" - "css-what" "^5.1.0" - "domhandler" "^4.3.0" - "domutils" "^2.8.0" - "nth-check" "^2.0.1" - -"css-select@~1.2.0": - "integrity" "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=" - "resolved" "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz" - "version" "1.2.0" - dependencies: - "boolbase" "~1.0.0" - "css-what" "2.1" - "domutils" "1.5.1" - "nth-check" "~1.0.1" - -"css-tree@^1.1.2", "css-tree@^1.1.3": - "integrity" "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==" - "resolved" "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz" - "version" "1.1.3" - dependencies: - "mdn-data" "2.0.14" - "source-map" "^0.6.1" - -"css-what@^5.0.1", "css-what@^5.1.0": - "integrity" "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==" - "resolved" "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz" - "version" "5.1.0" - -"css-what@2.1": - "integrity" "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" - "resolved" "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz" - "version" "2.1.3" - -"cssesc@^3.0.0": - "integrity" "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" - "resolved" "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz" - "version" "3.0.0" - -"cssnano-preset-advanced@^5.1.4": - "integrity" "sha512-5WWV9mbqVNwH4nRjs5UbhNl7eKo+16eYNzGogmz0Sa6iqWUeLdN8oo83WuTTqz5vjEKhTbRM5oX6WV1i6ees6g==" - "resolved" "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-5.1.12.tgz" - "version" "5.1.12" - dependencies: - "autoprefixer" "^10.3.7" - "cssnano-preset-default" "^5.1.12" - "postcss-discard-unused" "^5.0.3" - "postcss-merge-idents" "^5.0.3" - "postcss-reduce-idents" "^5.0.3" - "postcss-zindex" "^5.0.2" - -"cssnano-preset-default@^5.1.12": - "integrity" "sha512-rO/JZYyjW1QNkWBxMGV28DW7d98UDLaF759frhli58QFehZ+D/LSmwQ2z/ylBAe2hUlsIWTq6NYGfQPq65EF9w==" - "resolved" "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.1.12.tgz" - "version" "5.1.12" - dependencies: - "css-declaration-sorter" "^6.0.3" - "cssnano-utils" "^3.0.2" - "postcss-calc" "^8.2.0" - "postcss-colormin" "^5.2.5" - "postcss-convert-values" "^5.0.4" - "postcss-discard-comments" "^5.0.3" - "postcss-discard-duplicates" "^5.0.3" - "postcss-discard-empty" "^5.0.3" - "postcss-discard-overridden" "^5.0.4" - "postcss-merge-longhand" "^5.0.6" - "postcss-merge-rules" "^5.0.6" - "postcss-minify-font-values" "^5.0.4" - "postcss-minify-gradients" "^5.0.6" - "postcss-minify-params" "^5.0.5" - "postcss-minify-selectors" "^5.1.3" - "postcss-normalize-charset" "^5.0.3" - "postcss-normalize-display-values" "^5.0.3" - "postcss-normalize-positions" "^5.0.4" - "postcss-normalize-repeat-style" "^5.0.4" - "postcss-normalize-string" "^5.0.4" - "postcss-normalize-timing-functions" "^5.0.3" - "postcss-normalize-unicode" "^5.0.4" - "postcss-normalize-url" "^5.0.5" - "postcss-normalize-whitespace" "^5.0.4" - "postcss-ordered-values" "^5.0.5" - "postcss-reduce-initial" "^5.0.3" - "postcss-reduce-transforms" "^5.0.4" - "postcss-svgo" "^5.0.4" - "postcss-unique-selectors" "^5.0.4" - -"cssnano-utils@^3.0.2": - "integrity" "sha512-KhprijuQv2sP4kT92sSQwhlK3SJTbDIsxcfIEySB0O+3m9esFOai7dP9bMx5enHAh2MwarVIcnwiWoOm01RIbQ==" - "resolved" "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.0.2.tgz" - "version" "3.0.2" - -"cssnano@^5.0.6", "cssnano@^5.0.8": - "integrity" "sha512-fmjLP7k8kL18xSspeXTzRhaFtRI7DL9b8IcXR80JgtnWBpvAzHT7sCR/6qdn0tnxIaINUN6OEQu83wF57Gs3Xw==" - "resolved" "https://registry.npmjs.org/cssnano/-/cssnano-5.0.17.tgz" - "version" "5.0.17" - dependencies: - "cssnano-preset-default" "^5.1.12" - "lilconfig" "^2.0.3" - "yaml" "^1.10.2" - -"csso@^4.2.0": - "integrity" "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==" - "resolved" "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz" - "version" "4.2.0" - dependencies: - "css-tree" "^1.1.2" - -"csstype@^3.0.2": - "integrity" "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==" - "resolved" "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz" - "version" "3.0.10" - -"debug@^2.6.0", "debug@2.6.9": - "integrity" "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" - "resolved" "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" - "version" "2.6.9" - dependencies: - "ms" "2.0.0" - -"debug@^3.1.1": - "integrity" "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==" - "resolved" "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" - "version" "3.2.7" - dependencies: - "ms" "^2.1.1" - -"debug@^4.1.0": - "integrity" "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==" - "resolved" "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz" - "version" "4.3.3" - dependencies: - "ms" "2.1.2" - -"debug@^4.1.1": - "integrity" "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==" - "resolved" "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz" - "version" "4.3.3" - dependencies: - "ms" "2.1.2" - -"decompress-response@^3.3.0": - "integrity" "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=" - "resolved" "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz" - "version" "3.3.0" - dependencies: - "mimic-response" "^1.0.0" - -"deep-equal@^1.0.1": - "integrity" "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==" - "resolved" "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz" - "version" "1.1.1" - dependencies: - "is-arguments" "^1.0.4" - "is-date-object" "^1.0.1" - "is-regex" "^1.0.4" - "object-is" "^1.0.1" - "object-keys" "^1.1.1" - "regexp.prototype.flags" "^1.2.0" - -"deep-extend@^0.6.0": - "integrity" "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" - "resolved" "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz" - "version" "0.6.0" - -"deepmerge@^1.3.2": - "integrity" "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==" - "resolved" "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz" - "version" "1.5.2" - -"deepmerge@^4.2.2": - "integrity" "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" - "resolved" "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz" - "version" "4.2.2" - -"default-gateway@^6.0.3": - "integrity" "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==" - "resolved" "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz" - "version" "6.0.3" - dependencies: - "execa" "^5.0.0" - -"defer-to-connect@^1.0.1": - "integrity" "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" - "resolved" "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz" - "version" "1.1.3" - -"define-lazy-prop@^2.0.0": - "integrity" "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" - "resolved" "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz" - "version" "2.0.0" - -"define-properties@^1.1.3": - "integrity" "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==" - "resolved" "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz" - "version" "1.1.3" - dependencies: - "object-keys" "^1.0.12" - -"del@^6.0.0": - "integrity" "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==" - "resolved" "https://registry.npmjs.org/del/-/del-6.0.0.tgz" - "version" "6.0.0" - dependencies: - "globby" "^11.0.1" - "graceful-fs" "^4.2.4" - "is-glob" "^4.0.1" - "is-path-cwd" "^2.2.0" - "is-path-inside" "^3.0.2" - "p-map" "^4.0.0" - "rimraf" "^3.0.2" - "slash" "^3.0.0" - -"depd@~1.1.2": - "integrity" "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - "resolved" "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" - "version" "1.1.2" - -"destroy@~1.0.4": - "integrity" "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - "resolved" "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" - "version" "1.0.4" - -"detab@2.0.4": - "integrity" "sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g==" - "resolved" "https://registry.npmjs.org/detab/-/detab-2.0.4.tgz" - "version" "2.0.4" - dependencies: - "repeat-string" "^1.5.4" - -"detect-node@^2.0.4": - "integrity" "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" - "resolved" "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz" - "version" "2.1.0" - -"detect-port-alt@^1.1.6": - "integrity" "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==" - "resolved" "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz" - "version" "1.1.6" - dependencies: - "address" "^1.0.1" - "debug" "^2.6.0" - -"detect-port@^1.3.0": - "integrity" "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==" - "resolved" "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz" - "version" "1.3.0" - dependencies: - "address" "^1.0.1" - "debug" "^2.6.0" - -"dir-glob@^3.0.1": - "integrity" "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==" - "resolved" "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" - "version" "3.0.1" - dependencies: - "path-type" "^4.0.0" - -"dns-equal@^1.0.0": - "integrity" "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" - "resolved" "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz" - "version" "1.0.0" - -"dns-packet@^1.3.1": - "integrity" "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==" - "resolved" "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz" - "version" "1.3.4" - dependencies: - "ip" "^1.1.0" - "safe-buffer" "^5.0.1" - -"dns-txt@^2.0.2": - "integrity" "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=" - "resolved" "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz" - "version" "2.0.2" - dependencies: - "buffer-indexof" "^1.0.0" - -"dom-converter@^0.2.0": - "integrity" "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==" - "resolved" "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz" - "version" "0.2.0" - dependencies: - "utila" "~0.4" - -"dom-serializer@^1.0.1": - "integrity" "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==" - "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz" - "version" "1.3.2" - dependencies: - "domelementtype" "^2.0.1" - "domhandler" "^4.2.0" - "entities" "^2.0.0" - -"dom-serializer@^1.3.2": - "integrity" "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==" - "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz" - "version" "1.3.2" - dependencies: - "domelementtype" "^2.0.1" - "domhandler" "^4.2.0" - "entities" "^2.0.0" - -"dom-serializer@~0.1.0": - "integrity" "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==" - "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz" - "version" "0.1.1" - dependencies: - "domelementtype" "^1.3.0" - "entities" "^1.1.1" - -"dom-serializer@0": - "integrity" "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==" - "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz" - "version" "0.2.2" - dependencies: - "domelementtype" "^2.0.1" - "entities" "^2.0.0" - -"domelementtype@^1.3.0", "domelementtype@^1.3.1", "domelementtype@1": - "integrity" "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - "resolved" "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz" - "version" "1.3.1" - -"domelementtype@^2.0.1", "domelementtype@^2.2.0": - "integrity" "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" - "resolved" "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz" - "version" "2.2.0" - -"domhandler@^2.3.0": - "integrity" "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==" - "resolved" "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz" - "version" "2.4.2" - dependencies: - "domelementtype" "1" - -"domhandler@^4.0.0", "domhandler@^4.2.0", "domhandler@^4.3.0": - "integrity" "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==" - "resolved" "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz" - "version" "4.3.0" - dependencies: - "domelementtype" "^2.2.0" - -"domutils@^1.5.1": - "integrity" "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==" - "resolved" "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz" - "version" "1.7.0" - dependencies: - "dom-serializer" "0" - "domelementtype" "1" - -"domutils@^2.5.2", "domutils@^2.7.0", "domutils@^2.8.0": - "integrity" "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==" - "resolved" "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz" - "version" "2.8.0" - dependencies: - "dom-serializer" "^1.0.1" - "domelementtype" "^2.2.0" - "domhandler" "^4.2.0" - -"domutils@1.5.1": - "integrity" "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=" - "resolved" "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz" - "version" "1.5.1" - dependencies: - "dom-serializer" "0" - "domelementtype" "1" - -"dot-case@^3.0.4": - "integrity" "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==" - "resolved" "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz" - "version" "3.0.4" - dependencies: - "no-case" "^3.0.4" - "tslib" "^2.0.3" - -"dot-prop@^5.2.0": - "integrity" "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==" - "resolved" "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz" - "version" "5.3.0" - dependencies: - "is-obj" "^2.0.0" - -"duplexer@^0.1.2": - "integrity" "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" - "resolved" "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz" - "version" "0.1.2" - -"duplexer3@^0.1.4": - "integrity" "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" - "resolved" "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz" - "version" "0.1.4" - -"ee-first@1.1.1": - "integrity" "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - "resolved" "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" - "version" "1.1.1" - -"electron-to-chromium@^1.4.284": - "integrity" "sha512-DE9tTy2PNmy1v55AZAO542ui+MLC2cvINMK4P2LXGsJdput/ThVG9t+QGecPuAZZSgC8XoI+Jh9M1OG9IoNSCw==" - "resolved" "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.328.tgz" - "version" "1.4.328" - -"emoji-regex@^8.0.0": - "integrity" "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - "resolved" "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" - "version" "8.0.0" - -"emojis-list@^3.0.0": - "integrity" "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" - "resolved" "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz" - "version" "3.0.0" - -"emoticon@^3.2.0": - "integrity" "sha512-SNujglcLTTg+lDAcApPNgEdudaqQFiAbJCqzjNxJkvN9vAwCGi0uu8IUVvx+f16h+V44KCY6Y2yboroc9pilHg==" - "resolved" "https://registry.npmjs.org/emoticon/-/emoticon-3.2.0.tgz" - "version" "3.2.0" - -"encodeurl@~1.0.2": - "integrity" "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - "resolved" "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" - "version" "1.0.2" - -"end-of-stream@^1.1.0": - "integrity" "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==" - "resolved" "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" - "version" "1.4.4" - dependencies: - "once" "^1.4.0" - -"enhanced-resolve@^5.8.3": - "integrity" "sha512-weDYmzbBygL7HzGGS26M3hGQx68vehdEg6VUmqSOaFzXExFqlnKuSvsEJCVGQHScS8CQMbrAqftT+AzzHNt/YA==" - "resolved" "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.0.tgz" - "version" "5.9.0" - dependencies: - "graceful-fs" "^4.2.4" - "tapable" "^2.2.0" - -"entities@^1.1.1", "entities@~1.1.1": - "integrity" "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" - "resolved" "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz" - "version" "1.1.2" - -"entities@^2.0.0": - "integrity" "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" - "resolved" "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz" - "version" "2.2.0" - -"entities@^3.0.1": - "integrity" "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==" - "resolved" "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz" - "version" "3.0.1" - -"error-ex@^1.3.1": - "integrity" "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==" - "resolved" "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" - "version" "1.3.2" - dependencies: - "is-arrayish" "^0.2.1" - -"es-module-lexer@^0.9.0": - "integrity" "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==" - "resolved" "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz" - "version" "0.9.3" - -"escalade@^3.1.1": - "integrity" "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" - "resolved" "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" - "version" "3.1.1" - -"escape-goat@^2.0.0": - "integrity" "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==" - "resolved" "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz" - "version" "2.1.1" - -"escape-html@^1.0.3", "escape-html@~1.0.3": - "integrity" "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - "resolved" "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" - "version" "1.0.3" - -"escape-string-regexp@^1.0.5": - "integrity" "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" - "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" - "version" "1.0.5" - -"escape-string-regexp@^4.0.0": - "integrity" "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" - "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" - "version" "4.0.0" - -"eslint-scope@5.1.1": - "integrity" "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==" - "resolved" "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" - "version" "5.1.1" - dependencies: - "esrecurse" "^4.3.0" - "estraverse" "^4.1.1" - -"esprima@^4.0.0": - "integrity" "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - "resolved" "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" - "version" "4.0.1" - -"esrecurse@^4.3.0": - "integrity" "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==" - "resolved" "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" - "version" "4.3.0" - dependencies: - "estraverse" "^5.2.0" - -"estraverse@^4.1.1": - "integrity" "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" - "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" - "version" "4.3.0" - -"estraverse@^5.2.0": - "integrity" "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" - "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" - "version" "5.3.0" - -"esutils@^2.0.2": - "integrity" "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" - "resolved" "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" - "version" "2.0.3" - -"eta@^1.12.3": - "integrity" "sha512-qHixwbDLtekO/d51Yr4glcaUJCIjGVJyTzuqV4GPlgZo1YpgOKG+avQynErZIYrfM6JIJdtiG2Kox8tbb+DoGg==" - "resolved" "https://registry.npmjs.org/eta/-/eta-1.12.3.tgz" - "version" "1.12.3" - -"etag@~1.8.1": - "integrity" "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - "resolved" "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" - "version" "1.8.1" - -"eval@^0.1.4": - "integrity" "sha512-o0XUw+5OGkXw4pJZzQoXUk+H87DHuC+7ZE//oSrRGtatTmr12oTnLfg6QOq9DyTt0c/p4TwzgmkKrBzWTSizyQ==" - "resolved" "https://registry.npmjs.org/eval/-/eval-0.1.6.tgz" - "version" "0.1.6" - dependencies: - "require-like" ">= 0.1.1" - -"eventemitter3@^4.0.0": - "integrity" "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" - "resolved" "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz" - "version" "4.0.7" - -"events@^3.2.0": - "integrity" "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" - "resolved" "https://registry.npmjs.org/events/-/events-3.3.0.tgz" - "version" "3.3.0" - -"execa@^5.0.0": - "integrity" "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==" - "resolved" "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" - "version" "5.1.1" - dependencies: - "cross-spawn" "^7.0.3" - "get-stream" "^6.0.0" - "human-signals" "^2.1.0" - "is-stream" "^2.0.0" - "merge-stream" "^2.0.0" - "npm-run-path" "^4.0.1" - "onetime" "^5.1.2" - "signal-exit" "^3.0.3" - "strip-final-newline" "^2.0.0" - -"express@^4.17.1": - "integrity" "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==" - "resolved" "https://registry.npmjs.org/express/-/express-4.17.3.tgz" - "version" "4.17.3" - dependencies: - "accepts" "~1.3.8" - "array-flatten" "1.1.1" - "body-parser" "1.19.2" - "content-disposition" "0.5.4" - "content-type" "~1.0.4" - "cookie" "0.4.2" - "cookie-signature" "1.0.6" - "debug" "2.6.9" - "depd" "~1.1.2" - "encodeurl" "~1.0.2" - "escape-html" "~1.0.3" - "etag" "~1.8.1" - "finalhandler" "~1.1.2" - "fresh" "0.5.2" - "merge-descriptors" "1.0.1" - "methods" "~1.1.2" - "on-finished" "~2.3.0" - "parseurl" "~1.3.3" - "path-to-regexp" "0.1.7" - "proxy-addr" "~2.0.7" - "qs" "6.9.7" - "range-parser" "~1.2.1" - "safe-buffer" "5.2.1" - "send" "0.17.2" - "serve-static" "1.14.2" - "setprototypeof" "1.2.0" - "statuses" "~1.5.0" - "type-is" "~1.6.18" - "utils-merge" "1.0.1" - "vary" "~1.1.2" - -"extend-shallow@^2.0.1": - "integrity" "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=" - "resolved" "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" - "version" "2.0.1" - dependencies: - "is-extendable" "^0.1.0" - -"extend@^3.0.0": - "integrity" "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - "resolved" "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz" - "version" "3.0.2" - -"fast-deep-equal@^3.1.1", "fast-deep-equal@^3.1.3": - "integrity" "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - "resolved" "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" - "version" "3.1.3" - -"fast-glob@^3.2.7", "fast-glob@^3.2.9": - "integrity" "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==" - "resolved" "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz" - "version" "3.2.11" + find-cache-dir "^3.3.1" + loader-utils "^1.4.0" + make-dir "^3.1.0" + schema-utils "^2.6.5" + +babel-plugin-apply-mdx-type-prop@1.6.22: + version "1.6.22" + resolved "https://registry.npmjs.org/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz" dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - "glob-parent" "^5.1.2" - "merge2" "^1.3.0" - "micromatch" "^4.0.4" - -"fast-json-stable-stringify@^2.0.0": - "integrity" "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - "resolved" "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" - "version" "2.1.0" - -"fast-url-parser@1.1.3": - "integrity" "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=" - "resolved" "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz" - "version" "1.1.3" - dependencies: - "punycode" "^1.3.2" - -"fastq@^1.6.0": - "integrity" "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==" - "resolved" "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz" - "version" "1.13.0" - dependencies: - "reusify" "^1.0.4" - -"faye-websocket@^0.11.3": - "integrity" "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==" - "resolved" "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz" - "version" "0.11.4" - dependencies: - "websocket-driver" ">=0.5.1" - -"fbemitter@^3.0.0": - "integrity" "sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==" - "resolved" "https://registry.npmjs.org/fbemitter/-/fbemitter-3.0.0.tgz" - "version" "3.0.0" - dependencies: - "fbjs" "^3.0.0" - -"fbjs-css-vars@^1.0.0": - "integrity" "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" - "resolved" "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz" - "version" "1.0.2" - -"fbjs@^3.0.0", "fbjs@^3.0.1": - "integrity" "sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ==" - "resolved" "https://registry.npmjs.org/fbjs/-/fbjs-3.0.4.tgz" - "version" "3.0.4" - dependencies: - "cross-fetch" "^3.1.5" - "fbjs-css-vars" "^1.0.0" - "loose-envify" "^1.0.0" - "object-assign" "^4.1.0" - "promise" "^7.1.1" - "setimmediate" "^1.0.5" - "ua-parser-js" "^0.7.30" - -"feed@^4.2.2": - "integrity" "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==" - "resolved" "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz" - "version" "4.2.2" - dependencies: - "xml-js" "^1.6.11" - -"file-loader@*", "file-loader@^6.2.0": - "integrity" "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==" - "resolved" "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz" - "version" "6.2.0" - dependencies: - "loader-utils" "^2.0.0" - "schema-utils" "^3.0.0" - -"filesize@^8.0.6": - "integrity" "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==" - "resolved" "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz" - "version" "8.0.7" - -"fill-range@^7.0.1": - "integrity" "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==" - "resolved" "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" - "version" "7.0.1" - dependencies: - "to-regex-range" "^5.0.1" - -"finalhandler@~1.1.2": - "integrity" "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==" - "resolved" "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz" - "version" "1.1.2" - dependencies: - "debug" "2.6.9" - "encodeurl" "~1.0.2" - "escape-html" "~1.0.3" - "on-finished" "~2.3.0" - "parseurl" "~1.3.3" - "statuses" "~1.5.0" - "unpipe" "~1.0.0" - -"find-cache-dir@^3.3.1": - "integrity" "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==" - "resolved" "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz" - "version" "3.3.2" - dependencies: - "commondir" "^1.0.1" - "make-dir" "^3.0.2" - "pkg-dir" "^4.1.0" - -"find-up@^3.0.0": - "integrity" "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==" - "resolved" "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz" - "version" "3.0.0" - dependencies: - "locate-path" "^3.0.0" - -"find-up@^4.0.0": - "integrity" "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==" - "resolved" "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" - "version" "4.1.0" - dependencies: - "locate-path" "^5.0.0" - "path-exists" "^4.0.0" - -"find-up@^5.0.0": - "integrity" "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==" - "resolved" "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" - "version" "5.0.0" - dependencies: - "locate-path" "^6.0.0" - "path-exists" "^4.0.0" - -"flux@^4.0.1": - "integrity" "sha512-yKAbrp7JhZhj6uiT1FTuVMlIAT1J4jqEyBpFApi1kxpGZCvacMVc/t1pMQyotqHhAgvoE3bNvAykhCo2CLjnYw==" - "resolved" "https://registry.npmjs.org/flux/-/flux-4.0.3.tgz" - "version" "4.0.3" - dependencies: - "fbemitter" "^3.0.0" - "fbjs" "^3.0.1" - -"follow-redirects@^1.0.0", "follow-redirects@^1.14.7": - "integrity" "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" - "resolved" "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz" - "version" "1.14.9" - -"fork-ts-checker-webpack-plugin@^6.5.0": - "integrity" "sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw==" - "resolved" "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz" - "version" "6.5.0" + "@babel/helper-plugin-utils" "7.10.4" + "@mdx-js/util" "1.6.22" + +babel-plugin-dynamic-import-node@2.3.0: + version "2.3.0" + resolved "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz" dependencies: - "@babel/code-frame" "^7.8.3" - "@types/json-schema" "^7.0.5" - "chalk" "^4.1.0" - "chokidar" "^3.4.2" - "cosmiconfig" "^6.0.0" - "deepmerge" "^4.2.2" - "fs-extra" "^9.0.0" - "glob" "^7.1.6" - "memfs" "^3.1.2" - "minimatch" "^3.0.4" - "schema-utils" "2.7.0" - "semver" "^7.3.2" - "tapable" "^1.0.0" - -"forwarded@0.2.0": - "integrity" "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - "resolved" "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" - "version" "0.2.0" - -"fraction.js@^4.1.2": - "integrity" "sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg==" - "resolved" "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.3.tgz" - "version" "4.1.3" - -"fresh@0.5.2": - "integrity" "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - "resolved" "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" - "version" "0.5.2" - -"fs-extra@^10.0.0": - "integrity" "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==" - "resolved" "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz" - "version" "10.0.0" - dependencies: - "graceful-fs" "^4.2.0" - "jsonfile" "^6.0.1" - "universalify" "^2.0.0" - -"fs-extra@^9.0.0": - "integrity" "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==" - "resolved" "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz" - "version" "9.1.0" - dependencies: - "at-least-node" "^1.0.0" - "graceful-fs" "^4.2.0" - "jsonfile" "^6.0.1" - "universalify" "^2.0.0" - -"fs-monkey@1.0.3": - "integrity" "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==" - "resolved" "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz" - "version" "1.0.3" - -"fs.realpath@^1.0.0": - "integrity" "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - "resolved" "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" - "version" "1.0.0" - -"function-bind@^1.1.1": - "integrity" "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - "resolved" "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" - "version" "1.1.1" - -"gensync@^1.0.0-beta.1", "gensync@^1.0.0-beta.2": - "integrity" "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" - "resolved" "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" - "version" "1.0.0-beta.2" - -"get-intrinsic@^1.0.2": - "integrity" "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==" - "resolved" "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz" - "version" "1.1.1" - dependencies: - "function-bind" "^1.1.1" - "has" "^1.0.3" - "has-symbols" "^1.0.1" - -"get-own-enumerable-property-symbols@^3.0.0": - "integrity" "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" - "resolved" "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz" - "version" "3.0.2" - -"get-stream@^4.1.0": - "integrity" "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==" - "resolved" "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz" - "version" "4.1.0" - dependencies: - "pump" "^3.0.0" - -"get-stream@^5.1.0": - "integrity" "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==" - "resolved" "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz" - "version" "5.2.0" - dependencies: - "pump" "^3.0.0" - -"get-stream@^6.0.0": - "integrity" "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" - "resolved" "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz" - "version" "6.0.1" - -"github-slugger@^1.4.0": - "integrity" "sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ==" - "resolved" "https://registry.npmjs.org/github-slugger/-/github-slugger-1.4.0.tgz" - "version" "1.4.0" - -"glob-parent@^5.1.2", "glob-parent@~5.1.2": - "integrity" "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==" - "resolved" "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" - "version" "5.1.2" - dependencies: - "is-glob" "^4.0.1" - -"glob-parent@^6.0.1": - "integrity" "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==" - "resolved" "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" - "version" "6.0.2" - dependencies: - "is-glob" "^4.0.3" - -"glob-to-regexp@^0.4.1": - "integrity" "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" - "resolved" "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz" - "version" "0.4.1" - -"glob@^7.0.0", "glob@^7.1.3", "glob@^7.1.6": - "integrity" "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==" - "resolved" "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz" - "version" "7.2.0" - dependencies: - "fs.realpath" "^1.0.0" - "inflight" "^1.0.4" - "inherits" "2" - "minimatch" "^3.0.4" - "once" "^1.3.0" - "path-is-absolute" "^1.0.0" - -"global-dirs@^3.0.0": - "integrity" "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==" - "resolved" "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz" - "version" "3.0.0" - dependencies: - "ini" "2.0.0" - -"global-modules@^2.0.0": - "integrity" "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==" - "resolved" "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "global-prefix" "^3.0.0" - -"global-prefix@^3.0.0": - "integrity" "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==" - "resolved" "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz" - "version" "3.0.0" - dependencies: - "ini" "^1.3.5" - "kind-of" "^6.0.2" - "which" "^1.3.1" - -"globals@^11.1.0": - "integrity" "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" - "resolved" "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" - "version" "11.12.0" - -"globby@^11.0.1", "globby@^11.0.2", "globby@^11.0.4": - "integrity" "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==" - "resolved" "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" - "version" "11.1.0" - dependencies: - "array-union" "^2.1.0" - "dir-glob" "^3.0.1" - "fast-glob" "^3.2.9" - "ignore" "^5.2.0" - "merge2" "^1.4.1" - "slash" "^3.0.0" - -"globby@^12.0.2": - "integrity" "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==" - "resolved" "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz" - "version" "12.2.0" - dependencies: - "array-union" "^3.0.1" - "dir-glob" "^3.0.1" - "fast-glob" "^3.2.7" - "ignore" "^5.1.9" - "merge2" "^1.4.1" - "slash" "^4.0.0" - -"got@^9.6.0": - "integrity" "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==" - "resolved" "https://registry.npmjs.org/got/-/got-9.6.0.tgz" - "version" "9.6.0" + object.assign "^4.1.0" + +babel-plugin-dynamic-import-node@^2.3.3: + version "2.3.3" + resolved "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz" dependencies: - "@sindresorhus/is" "^0.14.0" - "@szmarczak/http-timer" "^1.1.2" - "cacheable-request" "^6.0.0" - "decompress-response" "^3.3.0" - "duplexer3" "^0.1.4" - "get-stream" "^4.1.0" - "lowercase-keys" "^1.0.1" - "mimic-response" "^1.0.1" - "p-cancelable" "^1.0.0" - "to-readable-stream" "^1.0.0" - "url-parse-lax" "^3.0.0" - -"graceful-fs@^4.1.2", "graceful-fs@^4.1.6", "graceful-fs@^4.2.0", "graceful-fs@^4.2.4", "graceful-fs@^4.2.6", "graceful-fs@^4.2.9": - "integrity" "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" - "resolved" "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz" - "version" "4.2.9" - -"gray-matter@^4.0.3": - "integrity" "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==" - "resolved" "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz" - "version" "4.0.3" - dependencies: - "js-yaml" "^3.13.1" - "kind-of" "^6.0.2" - "section-matter" "^1.0.0" - "strip-bom-string" "^1.0.0" - -"gzip-size@^6.0.0": - "integrity" "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==" - "resolved" "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz" - "version" "6.0.0" - dependencies: - "duplexer" "^0.1.2" - -"handle-thing@^2.0.0": - "integrity" "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" - "resolved" "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz" - "version" "2.0.1" - -"has-flag@^3.0.0": - "integrity" "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" - "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" - "version" "3.0.0" - -"has-flag@^4.0.0": - "integrity" "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" - "version" "4.0.0" - -"has-symbols@^1.0.1", "has-symbols@^1.0.2": - "integrity" "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - "resolved" "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz" - "version" "1.0.2" - -"has-tostringtag@^1.0.0": - "integrity" "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==" - "resolved" "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz" - "version" "1.0.0" - dependencies: - "has-symbols" "^1.0.2" - -"has-yarn@^2.1.0": - "integrity" "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==" - "resolved" "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz" - "version" "2.1.0" - -"has@^1.0.3": - "integrity" "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==" - "resolved" "https://registry.npmjs.org/has/-/has-1.0.3.tgz" - "version" "1.0.3" - dependencies: - "function-bind" "^1.1.1" - -"hast-to-hyperscript@^9.0.0": - "integrity" "sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA==" - "resolved" "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz" - "version" "9.0.1" + object.assign "^4.1.0" + +babel-plugin-extract-import-names@1.6.22: + version "1.6.22" + resolved "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz" dependencies: - "@types/unist" "^2.0.3" - "comma-separated-tokens" "^1.0.0" - "property-information" "^5.3.0" - "space-separated-tokens" "^1.0.0" - "style-to-object" "^0.3.0" - "unist-util-is" "^4.0.0" - "web-namespaces" "^1.0.0" - -"hast-util-from-parse5@^5.0.0": - "integrity" "sha512-gOc8UB99F6eWVWFtM9jUikjN7QkWxB3nY0df5Z0Zq1/Nkwl5V4hAAsl0tmwlgWl/1shlTF8DnNYLO8X6wRV9pA==" - "resolved" "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-5.0.3.tgz" - "version" "5.0.3" - dependencies: - "ccount" "^1.0.3" - "hastscript" "^5.0.0" - "property-information" "^5.0.0" - "web-namespaces" "^1.1.2" - "xtend" "^4.0.1" - -"hast-util-from-parse5@^6.0.0": - "integrity" "sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA==" - "resolved" "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz" - "version" "6.0.1" + "@babel/helper-plugin-utils" "7.10.4" + +babel-plugin-polyfill-corejs2@^0.3.0: + version "0.3.1" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz" dependencies: - "@types/parse5" "^5.0.0" - "hastscript" "^6.0.0" - "property-information" "^5.0.0" - "vfile" "^4.0.0" - "vfile-location" "^3.2.0" - "web-namespaces" "^1.0.0" - -"hast-util-parse-selector@^2.0.0": - "integrity" "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==" - "resolved" "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz" - "version" "2.2.5" - -"hast-util-raw@6.0.1": - "integrity" "sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig==" - "resolved" "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-6.0.1.tgz" - "version" "6.0.1" + "@babel/compat-data" "^7.13.11" + "@babel/helper-define-polyfill-provider" "^0.3.1" + semver "^6.1.1" + +babel-plugin-polyfill-corejs3@^0.5.0: + version "0.5.2" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz" dependencies: - "@types/hast" "^2.0.0" - "hast-util-from-parse5" "^6.0.0" - "hast-util-to-parse5" "^6.0.0" - "html-void-elements" "^1.0.0" - "parse5" "^6.0.0" - "unist-util-position" "^3.0.0" - "vfile" "^4.0.0" - "web-namespaces" "^1.0.0" - "xtend" "^4.0.0" - "zwitch" "^1.0.0" - -"hast-util-to-parse5@^6.0.0": - "integrity" "sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ==" - "resolved" "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz" - "version" "6.0.0" - dependencies: - "hast-to-hyperscript" "^9.0.0" - "property-information" "^5.0.0" - "web-namespaces" "^1.0.0" - "xtend" "^4.0.0" - "zwitch" "^1.0.0" - -"hastscript@^5.0.0": - "integrity" "sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ==" - "resolved" "https://registry.npmjs.org/hastscript/-/hastscript-5.1.2.tgz" - "version" "5.1.2" - dependencies: - "comma-separated-tokens" "^1.0.0" - "hast-util-parse-selector" "^2.0.0" - "property-information" "^5.0.0" - "space-separated-tokens" "^1.0.0" - -"hastscript@^6.0.0": - "integrity" "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==" - "resolved" "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz" - "version" "6.0.0" + "@babel/helper-define-polyfill-provider" "^0.3.1" + core-js-compat "^3.21.0" + +babel-plugin-polyfill-regenerator@^0.3.0: + version "0.3.1" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz" dependencies: - "@types/hast" "^2.0.0" - "comma-separated-tokens" "^1.0.0" - "hast-util-parse-selector" "^2.0.0" - "property-information" "^5.0.0" - "space-separated-tokens" "^1.0.0" + "@babel/helper-define-polyfill-provider" "^0.3.1" + +bail@^1.0.0: + version "1.0.5" + resolved "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + +base16@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz" + +batch@0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz" + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz" + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" + +bluebird@^3.7.1: + version "3.7.2" + resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz" + +body-parser@1.19.2: + version "1.19.2" + resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz" + dependencies: + bytes "3.1.2" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "1.8.1" + iconv-lite "0.4.24" + on-finished "~2.3.0" + qs "6.9.7" + raw-body "2.4.3" + type-is "~1.6.18" + +bonjour@^3.5.0: + version "3.5.0" + resolved "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz" + dependencies: + array-flatten "^2.1.0" + deep-equal "^1.0.1" + dns-equal "^1.0.0" + dns-txt "^2.0.2" + multicast-dns "^6.0.1" + multicast-dns-service-types "^1.1.0" + +boolbase@^1.0.0, boolbase@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz" + +boxen@^5.0.0, boxen@^5.0.1: + version "5.1.2" + resolved "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz" + dependencies: + ansi-align "^3.0.0" + camelcase "^6.2.0" + chalk "^4.1.0" + cli-boxes "^2.2.1" + string-width "^4.2.2" + type-fest "^0.20.2" + widest-line "^3.1.0" + wrap-ansi "^7.0.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^3.0.1, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" + dependencies: + fill-range "^7.0.1" + +browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.18.1, browserslist@^4.19.1, browserslist@^4.21.3: + version "4.21.5" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz" + dependencies: + caniuse-lite "^1.0.30001449" + electron-to-chromium "^1.4.284" + node-releases "^2.0.8" + update-browserslist-db "^1.0.10" + +buble-jsx-only@^0.19.8: + version "0.19.8" + resolved "https://registry.npmjs.org/buble-jsx-only/-/buble-jsx-only-0.19.8.tgz" + dependencies: + acorn "^6.1.1" + acorn-dynamic-import "^4.0.0" + acorn-jsx "^5.0.1" + chalk "^2.4.2" + magic-string "^0.25.3" + minimist "^1.2.0" + regexpu-core "^4.5.4" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" + +buffer-indexof@^1.0.0: + version "1.1.1" + resolved "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz" + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz" + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" + +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz" + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + +camel-case@^4.1.2: + version "4.1.2" + resolved "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz" + dependencies: + pascal-case "^3.1.2" + tslib "^2.0.3" + +camelcase-css@2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz" + +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + +caniuse-api@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz" + dependencies: + browserslist "^4.0.0" + caniuse-lite "^1.0.0" + lodash.memoize "^4.1.2" + lodash.uniq "^4.5.0" + +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001297, caniuse-lite@^1.0.30001449: + version "1.0.30001466" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001466.tgz" + +ccount@^1.0.0, ccount@^1.0.3: + version "1.1.0" + resolved "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz" + +chalk@^2.0.0, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.1.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +character-entities-legacy@^1.0.0: + version "1.1.4" + resolved "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz" + +character-entities@^1.0.0: + version "1.2.4" + resolved "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz" + +character-reference-invalid@^1.0.0: + version "1.1.4" + resolved "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz" + +cheerio-select@^1.5.0: + version "1.5.0" + resolved "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz" + dependencies: + css-select "^4.1.3" + css-what "^5.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" + domutils "^2.7.0" + +cheerio@^0.22.0: + version "0.22.0" + resolved "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz" + dependencies: + css-select "~1.2.0" + dom-serializer "~0.1.0" + entities "~1.1.1" + htmlparser2 "^3.9.1" + lodash.assignin "^4.0.9" + lodash.bind "^4.1.4" + lodash.defaults "^4.0.1" + lodash.filter "^4.4.0" + lodash.flatten "^4.2.0" + lodash.foreach "^4.3.0" + lodash.map "^4.4.0" + lodash.merge "^4.4.0" + lodash.pick "^4.2.1" + lodash.reduce "^4.4.0" + lodash.reject "^4.4.0" + lodash.some "^4.4.0" + +cheerio@^1.0.0-rc.10: + version "1.0.0-rc.10" + resolved "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz" + dependencies: + cheerio-select "^1.5.0" + dom-serializer "^1.3.2" + domhandler "^4.2.0" + htmlparser2 "^6.1.0" + parse5 "^6.0.1" + parse5-htmlparser2-tree-adapter "^6.0.1" + tslib "^2.2.0" + +chokidar@^3.4.2, chokidar@^3.5.2, chokidar@^3.5.3: + version "3.5.3" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" -"he@^1.2.0": - "integrity" "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" - "resolved" "https://registry.npmjs.org/he/-/he-1.2.0.tgz" - "version" "1.2.0" +chrome-trace-event@^1.0.2: + version "1.0.3" + resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz" -"history@^4.9.0": - "integrity" "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==" - "resolved" "https://registry.npmjs.org/history/-/history-4.10.1.tgz" - "version" "4.10.1" +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz" + +classnames@^2.2.6: + version "2.3.1" + resolved "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz" + +clean-css@^5.1.5, clean-css@^5.2.2: + version "5.2.4" + resolved "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz" dependencies: - "@babel/runtime" "^7.1.2" - "loose-envify" "^1.2.0" - "resolve-pathname" "^3.0.0" - "tiny-invariant" "^1.0.2" - "tiny-warning" "^1.0.0" - "value-equal" "^1.0.1" - -"hoist-non-react-statics@^3.1.0": - "integrity" "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==" - "resolved" "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz" - "version" "3.3.2" - dependencies: - "react-is" "^16.7.0" - -"hpack.js@^2.1.6": - "integrity" "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=" - "resolved" "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz" - "version" "2.1.6" - dependencies: - "inherits" "^2.0.1" - "obuf" "^1.0.0" - "readable-stream" "^2.0.1" - "wbuf" "^1.1.0" - -"html-entities@^2.3.2": - "integrity" "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==" - "resolved" "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz" - "version" "2.3.2" - -"html-minifier-terser@^6.0.2": - "integrity" "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==" - "resolved" "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz" - "version" "6.1.0" - dependencies: - "camel-case" "^4.1.2" - "clean-css" "^5.2.2" - "commander" "^8.3.0" - "he" "^1.2.0" - "param-case" "^3.0.4" - "relateurl" "^0.2.7" - "terser" "^5.10.0" - -"html-tags@^3.1.0": - "integrity" "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==" - "resolved" "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz" - "version" "3.1.0" - -"html-void-elements@^1.0.0": - "integrity" "sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w==" - "resolved" "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz" - "version" "1.0.5" - -"html-webpack-plugin@^5.4.0": - "integrity" "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==" - "resolved" "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz" - "version" "5.5.0" + source-map "~0.6.0" + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz" + +cli-boxes@^2.2.1: + version "2.2.1" + resolved "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz" + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz" dependencies: - "@types/html-minifier-terser" "^6.0.0" - "html-minifier-terser" "^6.0.2" - "lodash" "^4.17.21" - "pretty-error" "^4.0.0" - "tapable" "^2.0.0" - -"htmlparser2@^3.9.1": - "integrity" "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==" - "resolved" "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz" - "version" "3.10.1" - dependencies: - "domelementtype" "^1.3.1" - "domhandler" "^2.3.0" - "domutils" "^1.5.1" - "entities" "^1.1.1" - "inherits" "^2.0.1" - "readable-stream" "^3.1.1" - -"htmlparser2@^6.1.0": - "integrity" "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==" - "resolved" "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz" - "version" "6.1.0" - dependencies: - "domelementtype" "^2.0.1" - "domhandler" "^4.0.0" - "domutils" "^2.5.2" - "entities" "^2.0.0" - -"http-cache-semantics@^4.0.0": - "integrity" "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" - "resolved" "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz" - "version" "4.1.1" - -"http-deceiver@^1.2.7": - "integrity" "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" - "resolved" "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" - "version" "1.2.7" - -"http-errors@~1.6.2": - "integrity" "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=" - "resolved" "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz" - "version" "1.6.3" - dependencies: - "depd" "~1.1.2" - "inherits" "2.0.3" - "setprototypeof" "1.1.0" - "statuses" ">= 1.4.0 < 2" - -"http-errors@1.8.1": - "integrity" "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==" - "resolved" "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz" - "version" "1.8.1" - dependencies: - "depd" "~1.1.2" - "inherits" "2.0.4" - "setprototypeof" "1.2.0" - "statuses" ">= 1.5.0 < 2" - "toidentifier" "1.0.1" - -"http-parser-js@>=0.5.1": - "integrity" "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA==" - "resolved" "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz" - "version" "0.5.5" - -"http-proxy-middleware@^2.0.0": - "integrity" "sha512-1bloEwnrHMnCoO/Gcwbz7eSVvW50KPES01PecpagI+YLNLci4AcuKJrujW4Mc3sBLpFxMSlsLNHS5Nl/lvrTPA==" - "resolved" "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.3.tgz" - "version" "2.0.3" + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz" dependencies: - "@types/http-proxy" "^1.17.8" - "http-proxy" "^1.18.1" - "is-glob" "^4.0.1" - "is-plain-obj" "^3.0.0" - "micromatch" "^4.0.2" - -"http-proxy@^1.18.1": - "integrity" "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==" - "resolved" "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz" - "version" "1.18.1" - dependencies: - "eventemitter3" "^4.0.0" - "follow-redirects" "^1.0.0" - "requires-port" "^1.0.0" - -"human-signals@^2.1.0": - "integrity" "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" - "resolved" "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" - "version" "2.1.0" - -"iconv-lite@0.4.24": - "integrity" "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==" - "resolved" "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" - "version" "0.4.24" - dependencies: - "safer-buffer" ">= 2.1.2 < 3" - -"icss-utils@^5.0.0", "icss-utils@^5.1.0": - "integrity" "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==" - "resolved" "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz" - "version" "5.1.0" - -"ignore@^5.1.9", "ignore@^5.2.0": - "integrity" "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==" - "resolved" "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz" - "version" "5.2.0" - -"image-size@^1.0.1": - "integrity" "sha512-VAwkvNSNGClRw9mDHhc5Efax8PLlsOGcUTh0T/LIriC8vPA3U5PdqXWqkz406MoYHMKW8Uf9gWr05T/rYB44kQ==" - "resolved" "https://registry.npmjs.org/image-size/-/image-size-1.0.1.tgz" - "version" "1.0.1" - dependencies: - "queue" "6.0.2" - -"immer@^9.0.7": - "integrity" "sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA==" - "resolved" "https://registry.npmjs.org/immer/-/immer-9.0.12.tgz" - "version" "9.0.12" - -"import-fresh@^3.1.0", "import-fresh@^3.2.1", "import-fresh@^3.2.2", "import-fresh@^3.3.0": - "integrity" "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==" - "resolved" "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" - "version" "3.3.0" - dependencies: - "parent-module" "^1.0.0" - "resolve-from" "^4.0.0" - -"import-lazy@^2.1.0": - "integrity" "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" - "resolved" "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz" - "version" "2.1.0" - -"imurmurhash@^0.1.4": - "integrity" "sha1-khi5srkoojixPcT7a21XbyMUU+o=" - "resolved" "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" - "version" "0.1.4" - -"indent-string@^4.0.0": - "integrity" "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" - "resolved" "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" - "version" "4.0.0" - -"infima@0.2.0-alpha.37": - "integrity" "sha512-4GX7Baw+/lwS4PPW/UJNY89tWSvYG1DL6baKVdpK6mC593iRgMssxNtORMTFArLPJ/A/lzsGhRmx+z6MaMxj0Q==" - "resolved" "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.37.tgz" - "version" "0.2.0-alpha.37" - -"inflight@^1.0.4": - "integrity" "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=" - "resolved" "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" - "version" "1.0.6" - dependencies: - "once" "^1.3.0" - "wrappy" "1" - -"inherits@^2.0.0", "inherits@^2.0.1", "inherits@^2.0.3", "inherits@~2.0.3", "inherits@2", "inherits@2.0.4": - "integrity" "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - "resolved" "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" - "version" "2.0.4" - -"inherits@2.0.3": - "integrity" "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - "resolved" "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - "version" "2.0.3" - -"ini@^1.3.5", "ini@~1.3.0": - "integrity" "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - "resolved" "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" - "version" "1.3.8" - -"ini@2.0.0": - "integrity" "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==" - "resolved" "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz" - "version" "2.0.0" - -"inline-style-parser@0.1.1": - "integrity" "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" - "resolved" "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz" - "version" "0.1.1" - -"interpret@^1.0.0": - "integrity" "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" - "resolved" "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz" - "version" "1.4.0" - -"ip@^1.1.0": - "integrity" "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" - "resolved" "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz" - "version" "1.1.5" - -"ipaddr.js@^2.0.1": - "integrity" "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==" - "resolved" "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz" - "version" "2.0.1" - -"ipaddr.js@1.9.1": - "integrity" "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - "resolved" "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" - "version" "1.9.1" - -"is-alphabetical@^1.0.0", "is-alphabetical@1.0.4": - "integrity" "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==" - "resolved" "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz" - "version" "1.0.4" - -"is-alphanumerical@^1.0.0": - "integrity" "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==" - "resolved" "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz" - "version" "1.0.4" - dependencies: - "is-alphabetical" "^1.0.0" - "is-decimal" "^1.0.0" - -"is-arguments@^1.0.4": - "integrity" "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==" - "resolved" "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz" - "version" "1.1.1" - dependencies: - "call-bind" "^1.0.2" - "has-tostringtag" "^1.0.0" - -"is-arrayish@^0.2.1": - "integrity" "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - "resolved" "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" - "version" "0.2.1" - -"is-binary-path@~2.1.0": - "integrity" "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==" - "resolved" "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" - "version" "2.1.0" - dependencies: - "binary-extensions" "^2.0.0" - -"is-buffer@^2.0.0": - "integrity" "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" - "resolved" "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz" - "version" "2.0.5" - -"is-ci@^2.0.0": - "integrity" "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==" - "resolved" "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "ci-info" "^2.0.0" - -"is-core-module@^2.8.1": - "integrity" "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==" - "resolved" "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz" - "version" "2.8.1" - dependencies: - "has" "^1.0.3" - -"is-date-object@^1.0.1": - "integrity" "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==" - "resolved" "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz" - "version" "1.0.5" - dependencies: - "has-tostringtag" "^1.0.0" - -"is-decimal@^1.0.0": - "integrity" "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==" - "resolved" "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz" - "version" "1.0.4" - -"is-docker@^2.0.0", "is-docker@^2.1.1": - "integrity" "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" - "resolved" "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz" - "version" "2.2.1" - -"is-extendable@^0.1.0": - "integrity" "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - "resolved" "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" - "version" "0.1.1" - -"is-extglob@^2.1.1": - "integrity" "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - "resolved" "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" - "version" "2.1.1" - -"is-fullwidth-code-point@^3.0.0": - "integrity" "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - "resolved" "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" - "version" "3.0.0" - -"is-glob@^4.0.1", "is-glob@^4.0.3", "is-glob@~4.0.1": - "integrity" "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==" - "resolved" "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" - "version" "4.0.3" - dependencies: - "is-extglob" "^2.1.1" - -"is-hexadecimal@^1.0.0": - "integrity" "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==" - "resolved" "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz" - "version" "1.0.4" - -"is-installed-globally@^0.4.0": - "integrity" "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==" - "resolved" "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz" - "version" "0.4.0" - dependencies: - "global-dirs" "^3.0.0" - "is-path-inside" "^3.0.2" - -"is-npm@^5.0.0": - "integrity" "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==" - "resolved" "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz" - "version" "5.0.0" - -"is-number@^7.0.0": - "integrity" "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - "resolved" "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" - "version" "7.0.0" - -"is-obj@^1.0.1": - "integrity" "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" - "resolved" "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz" - "version" "1.0.1" - -"is-obj@^2.0.0": - "integrity" "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" - "resolved" "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz" - "version" "2.0.0" - -"is-path-cwd@^2.2.0": - "integrity" "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==" - "resolved" "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz" - "version" "2.2.0" - -"is-path-inside@^3.0.2": - "integrity" "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" - "resolved" "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" - "version" "3.0.3" - -"is-plain-obj@^2.0.0": - "integrity" "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" - "resolved" "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" - "version" "2.1.0" - -"is-plain-obj@^3.0.0": - "integrity" "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==" - "resolved" "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz" - "version" "3.0.0" - -"is-plain-object@^2.0.4": - "integrity" "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==" - "resolved" "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" - "version" "2.0.4" - dependencies: - "isobject" "^3.0.1" - -"is-regex@^1.0.4": - "integrity" "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==" - "resolved" "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz" - "version" "1.1.4" - dependencies: - "call-bind" "^1.0.2" - "has-tostringtag" "^1.0.0" - -"is-regexp@^1.0.0": - "integrity" "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=" - "resolved" "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz" - "version" "1.0.0" - -"is-root@^2.1.0": - "integrity" "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==" - "resolved" "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz" - "version" "2.1.0" - -"is-stream@^2.0.0": - "integrity" "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" - "resolved" "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" - "version" "2.0.1" - -"is-typedarray@^1.0.0": - "integrity" "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - "resolved" "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" - "version" "1.0.0" - -"is-whitespace-character@^1.0.0": - "integrity" "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==" - "resolved" "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz" - "version" "1.0.4" - -"is-word-character@^1.0.0": - "integrity" "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==" - "resolved" "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz" - "version" "1.0.4" - -"is-wsl@^2.2.0": - "integrity" "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==" - "resolved" "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz" - "version" "2.2.0" - dependencies: - "is-docker" "^2.0.0" - -"is-yarn-global@^0.3.0": - "integrity" "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" - "resolved" "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz" - "version" "0.3.0" - -"isarray@~1.0.0": - "integrity" "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - "resolved" "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - "version" "1.0.0" - -"isarray@0.0.1": - "integrity" "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - "resolved" "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" - "version" "0.0.1" - -"isexe@^2.0.0": - "integrity" "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - "resolved" "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" - "version" "2.0.0" - -"isobject@^3.0.1": - "integrity" "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - "resolved" "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" - "version" "3.0.1" - -"jest-worker@^27.0.2", "jest-worker@^27.4.5": - "integrity" "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==" - "resolved" "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz" - "version" "27.5.1" + mimic-response "^1.0.0" + +clsx@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz" + +collapse-white-space@^1.0.2: + version "1.0.6" + resolved "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" dependencies: - "@types/node" "*" - "merge-stream" "^2.0.0" - "supports-color" "^8.0.0" + color-name "1.1.3" -"joi@^17.4.2", "joi@^17.6.0": - "integrity" "sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw==" - "resolved" "https://registry.npmjs.org/joi/-/joi-17.6.0.tgz" - "version" "17.6.0" +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" dependencies: - "@hapi/hoek" "^9.0.0" - "@hapi/topo" "^5.0.0" - "@sideway/address" "^4.1.3" - "@sideway/formula" "^3.0.0" - "@sideway/pinpoint" "^2.0.0" + color-name "~1.1.4" -"js-tokens@^3.0.0 || ^4.0.0", "js-tokens@^4.0.0": - "integrity" "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - "resolved" "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" - "version" "4.0.0" - -"js-yaml@^3.13.1": - "integrity" "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==" - "resolved" "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" - "version" "3.14.1" - dependencies: - "argparse" "^1.0.7" - "esprima" "^4.0.0" - -"js-yaml@^4.0.0": - "integrity" "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==" - "resolved" "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" - "version" "4.1.0" - dependencies: - "argparse" "^2.0.1" - -"jsesc@^2.5.1": - "integrity" "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" - "resolved" "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" - "version" "2.5.2" - -"jsesc@~0.5.0": - "integrity" "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" - "resolved" "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" - "version" "0.5.0" - -"json-buffer@3.0.0": - "integrity" "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" - "resolved" "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz" - "version" "3.0.0" - -"json-parse-better-errors@^1.0.2": - "integrity" "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" - "resolved" "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz" - "version" "1.0.2" - -"json-parse-even-better-errors@^2.3.0": - "integrity" "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" - "resolved" "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" - "version" "2.3.1" - -"json-schema-traverse@^0.4.1": - "integrity" "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - "resolved" "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" - "version" "0.4.1" - -"json-schema-traverse@^1.0.0": - "integrity" "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - "resolved" "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" - "version" "1.0.0" - -"json5@^1.0.1": - "integrity" "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==" - "resolved" "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz" - "version" "1.0.2" - dependencies: - "minimist" "^1.2.0" - -"json5@^2.1.2", "json5@^2.2.2": - "integrity" "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" - "resolved" "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" - "version" "2.2.3" - -"jsonfile@^6.0.1": - "integrity" "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==" - "resolved" "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz" - "version" "6.1.0" - dependencies: - "universalify" "^2.0.0" - optionalDependencies: - "graceful-fs" "^4.1.6" - -"keyv@^3.0.0": - "integrity" "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==" - "resolved" "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz" - "version" "3.1.0" - dependencies: - "json-buffer" "3.0.0" - -"kind-of@^6.0.0", "kind-of@^6.0.2": - "integrity" "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" - "resolved" "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" - "version" "6.0.3" - -"kleur@^3.0.3": - "integrity" "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" - "resolved" "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" - "version" "3.0.3" - -"klona@^2.0.5": - "integrity" "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==" - "resolved" "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz" - "version" "2.0.5" - -"latest-version@^5.1.0": - "integrity" "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==" - "resolved" "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz" - "version" "5.1.0" - dependencies: - "package-json" "^6.3.0" - -"leven@^3.1.0": - "integrity" "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" - "resolved" "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz" - "version" "3.1.0" - -"lilconfig@^2.0.3": - "integrity" "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==" - "resolved" "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz" - "version" "2.0.4" - -"lines-and-columns@^1.1.6": - "integrity" "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" - "resolved" "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" - "version" "1.2.4" - -"loader-runner@^4.2.0": - "integrity" "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==" - "resolved" "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz" - "version" "4.2.0" - -"loader-utils@^1.4.0": - "integrity" "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==" - "resolved" "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz" - "version" "1.4.2" - dependencies: - "big.js" "^5.2.2" - "emojis-list" "^3.0.0" - "json5" "^1.0.1" - -"loader-utils@^2.0.0": - "integrity" "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==" - "resolved" "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz" - "version" "2.0.2" - dependencies: - "big.js" "^5.2.2" - "emojis-list" "^3.0.0" - "json5" "^2.1.2" - -"loader-utils@^3.2.0": - "integrity" "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==" - "resolved" "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz" - "version" "3.2.0" - -"locate-path@^3.0.0": - "integrity" "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==" - "resolved" "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz" - "version" "3.0.0" - dependencies: - "p-locate" "^3.0.0" - "path-exists" "^3.0.0" - -"locate-path@^5.0.0": - "integrity" "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==" - "resolved" "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" - "version" "5.0.0" - dependencies: - "p-locate" "^4.1.0" - -"locate-path@^6.0.0": - "integrity" "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==" - "resolved" "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" - "version" "6.0.0" - dependencies: - "p-locate" "^5.0.0" - -"lodash.assignin@^4.0.9": - "integrity" "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=" - "resolved" "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz" - "version" "4.2.0" - -"lodash.bind@^4.1.4": - "integrity" "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=" - "resolved" "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz" - "version" "4.2.1" - -"lodash.curry@^4.0.1": - "integrity" "sha1-JI42By7ekGUB11lmIAqG2riyMXA=" - "resolved" "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz" - "version" "4.1.1" - -"lodash.debounce@^4.0.8": - "integrity" "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" - "resolved" "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" - "version" "4.0.8" - -"lodash.defaults@^4.0.1": - "integrity" "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" - "resolved" "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz" - "version" "4.2.0" - -"lodash.filter@^4.4.0": - "integrity" "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=" - "resolved" "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz" - "version" "4.6.0" - -"lodash.flatten@^4.2.0": - "integrity" "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" - "resolved" "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz" - "version" "4.4.0" - -"lodash.flow@^3.3.0": - "integrity" "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o=" - "resolved" "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz" - "version" "3.5.0" - -"lodash.foreach@^4.3.0": - "integrity" "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" - "resolved" "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz" - "version" "4.5.0" - -"lodash.map@^4.4.0": - "integrity" "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=" - "resolved" "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz" - "version" "4.6.0" - -"lodash.memoize@^4.1.2": - "integrity" "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" - "resolved" "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz" - "version" "4.1.2" - -"lodash.merge@^4.4.0": - "integrity" "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - "resolved" "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" - "version" "4.6.2" - -"lodash.pick@^4.2.1": - "integrity" "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" - "resolved" "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz" - "version" "4.4.0" - -"lodash.reduce@^4.4.0": - "integrity" "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" - "resolved" "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz" - "version" "4.6.0" - -"lodash.reject@^4.4.0": - "integrity" "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=" - "resolved" "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz" - "version" "4.6.0" - -"lodash.some@^4.4.0": - "integrity" "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" - "resolved" "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz" - "version" "4.6.0" - -"lodash.uniq@^4.5.0", "lodash.uniq@4.5.0": - "integrity" "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" - "resolved" "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz" - "version" "4.5.0" - -"lodash@^4.17.14", "lodash@^4.17.19", "lodash@^4.17.20", "lodash@^4.17.21": - "integrity" "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - "resolved" "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" - "version" "4.17.21" - -"loose-envify@^1.0.0", "loose-envify@^1.1.0", "loose-envify@^1.2.0", "loose-envify@^1.3.1", "loose-envify@^1.4.0": - "integrity" "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==" - "resolved" "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" - "version" "1.4.0" - dependencies: - "js-tokens" "^3.0.0 || ^4.0.0" - -"lower-case@^2.0.2": - "integrity" "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==" - "resolved" "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz" - "version" "2.0.2" - dependencies: - "tslib" "^2.0.3" - -"lowercase-keys@^1.0.0", "lowercase-keys@^1.0.1": - "integrity" "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" - "resolved" "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz" - "version" "1.0.1" - -"lowercase-keys@^2.0.0": - "integrity" "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" - "resolved" "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz" - "version" "2.0.0" - -"lru-cache@^5.1.1": - "integrity" "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==" - "resolved" "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" - "version" "5.1.1" - dependencies: - "yallist" "^3.0.2" - -"lru-cache@^6.0.0": - "integrity" "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==" - "resolved" "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" - "version" "6.0.0" - dependencies: - "yallist" "^4.0.0" - -"magic-string@^0.25.3": - "integrity" "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==" - "resolved" "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz" - "version" "0.25.7" - dependencies: - "sourcemap-codec" "^1.4.4" - -"make-dir@^3.0.0", "make-dir@^3.0.2", "make-dir@^3.1.0": - "integrity" "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==" - "resolved" "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" - "version" "3.1.0" +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + +colord@^2.9.1: + version "2.9.2" + resolved "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz" + +colorette@^2.0.10: + version "2.0.16" + resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz" + +combine-promises@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/combine-promises/-/combine-promises-1.1.0.tgz" + +comma-separated-tokens@^1.0.0: + version "1.0.8" + resolved "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz" + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" + +commander@^5.1.0: + version "5.1.0" + resolved "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz" + +commander@^7.2.0: + version "7.2.0" + resolved "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz" + +commander@^8.3.0: + version "8.3.0" + resolved "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz" + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" + +compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz" dependencies: - "semver" "^6.0.0" - -"markdown-escapes@^1.0.0": - "integrity" "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==" - "resolved" "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz" - "version" "1.0.4" - -"mdast-squeeze-paragraphs@^4.0.0": - "integrity" "sha512-zxdPn69hkQ1rm4J+2Cs2j6wDEv7O17TfXTJ33tl/+JPIoEmtV9t2ZzBM5LPHE8QlHsmVD8t3vPKCyY3oH+H8MQ==" - "resolved" "https://registry.npmjs.org/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz" - "version" "4.0.0" + mime-db ">= 1.43.0 < 2" + +compression@^1.7.4: + version "1.7.4" + resolved "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz" dependencies: - "unist-util-remove" "^2.0.0" + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" -"mdast-util-definitions@^4.0.0": - "integrity" "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==" - "resolved" "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz" - "version" "4.0.0" +configstore@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz" dependencies: - "unist-util-visit" "^2.0.0" + dot-prop "^5.2.0" + graceful-fs "^4.1.2" + make-dir "^3.0.0" + unique-string "^2.0.0" + write-file-atomic "^3.0.0" + xdg-basedir "^4.0.0" -"mdast-util-to-hast@10.0.1": - "integrity" "sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA==" - "resolved" "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz" - "version" "10.0.1" +connect-history-api-fallback@^1.6.0: + version "1.6.0" + resolved "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz" + +consola@^2.15.3: + version "2.15.3" + resolved "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz" + +content-disposition@0.5.2: + version "0.5.2" + resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz" + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz" dependencies: - "@types/mdast" "^3.0.0" - "@types/unist" "^2.0.0" - "mdast-util-definitions" "^4.0.0" - "mdurl" "^1.0.0" - "unist-builder" "^2.0.0" - "unist-util-generated" "^1.0.0" - "unist-util-position" "^3.0.0" - "unist-util-visit" "^2.0.0" - -"mdast-util-to-string@^2.0.0": - "integrity" "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==" - "resolved" "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz" - "version" "2.0.0" - -"mdn-data@2.0.14": - "integrity" "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" - "resolved" "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz" - "version" "2.0.14" - -"mdurl@^1.0.0": - "integrity" "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" - "resolved" "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz" - "version" "1.0.1" - -"media-typer@0.3.0": - "integrity" "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - "resolved" "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" - "version" "0.3.0" - -"memfs@^3.1.2", "memfs@^3.4.1": - "integrity" "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==" - "resolved" "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz" - "version" "3.4.1" - dependencies: - "fs-monkey" "1.0.3" - -"merge-descriptors@1.0.1": - "integrity" "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - "resolved" "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" - "version" "1.0.1" - -"merge-stream@^2.0.0": - "integrity" "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" - "resolved" "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" - "version" "2.0.0" - -"merge2@^1.3.0", "merge2@^1.4.1": - "integrity" "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" - "resolved" "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" - "version" "1.4.1" - -"methods@~1.1.2": - "integrity" "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - "resolved" "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" - "version" "1.1.2" - -"micromatch@^4.0.2", "micromatch@^4.0.4": - "integrity" "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==" - "resolved" "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz" - "version" "4.0.4" - dependencies: - "braces" "^3.0.1" - "picomatch" "^2.2.3" - -"mime-db@>= 1.43.0 < 2", "mime-db@1.51.0": - "integrity" "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" - "resolved" "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz" - "version" "1.51.0" - -"mime-db@~1.33.0": - "integrity" "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" - "resolved" "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz" - "version" "1.33.0" - -"mime-types@^2.1.27", "mime-types@^2.1.31", "mime-types@~2.1.17", "mime-types@~2.1.24", "mime-types@~2.1.34": - "integrity" "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==" - "resolved" "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz" - "version" "2.1.34" - dependencies: - "mime-db" "1.51.0" - -"mime-types@2.1.18": - "integrity" "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==" - "resolved" "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz" - "version" "2.1.18" - dependencies: - "mime-db" "~1.33.0" - -"mime@1.6.0": - "integrity" "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - "resolved" "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" - "version" "1.6.0" - -"mimic-fn@^2.1.0": - "integrity" "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" - "resolved" "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" - "version" "2.1.0" - -"mimic-response@^1.0.0", "mimic-response@^1.0.1": - "integrity" "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" - "resolved" "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz" - "version" "1.0.1" - -"mini-create-react-context@^0.4.0": - "integrity" "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==" - "resolved" "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz" - "version" "0.4.1" + safe-buffer "5.2.1" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz" + +convert-source-map@^1.7.0: + version "1.8.0" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz" dependencies: - "@babel/runtime" "^7.12.1" - "tiny-warning" "^1.0.3" - -"mini-css-extract-plugin@^1.6.0": - "integrity" "sha512-WhDvO3SjGm40oV5y26GjMJYjd2UMqrLAGKy5YS2/3QKJy2F7jgynuHTir/tgUUOiNQu5saXHdc8reo7YuhhT4Q==" - "resolved" "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.6.2.tgz" - "version" "1.6.2" - dependencies: - "loader-utils" "^2.0.0" - "schema-utils" "^3.0.0" - "webpack-sources" "^1.1.0" - -"minimalistic-assert@^1.0.0": - "integrity" "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - "resolved" "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" - "version" "1.0.1" - -"minimatch@^3.0.4": - "integrity" "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==" - "resolved" "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" - "version" "3.1.2" - dependencies: - "brace-expansion" "^1.1.7" - -"minimatch@3.0.4": - "integrity" "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==" - "resolved" "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" - "version" "3.0.4" - dependencies: - "brace-expansion" "^1.1.7" - -"minimist@^1.2.0", "minimist@^1.2.5": - "integrity" "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==" - "resolved" "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz" - "version" "1.2.7" - -"mkdirp@^0.5.5": - "integrity" "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==" - "resolved" "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz" - "version" "0.5.5" - dependencies: - "minimist" "^1.2.5" - -"mrmime@^1.0.0": - "integrity" "sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ==" - "resolved" "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz" - "version" "1.0.0" - -"ms@^2.1.1", "ms@2.1.3": - "integrity" "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - "resolved" "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" - "version" "2.1.3" - -"ms@2.0.0": - "integrity" "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - "resolved" "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - "version" "2.0.0" - -"ms@2.1.2": - "integrity" "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - "resolved" "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" - "version" "2.1.2" - -"multicast-dns-service-types@^1.1.0": - "integrity" "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" - "resolved" "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz" - "version" "1.1.0" - -"multicast-dns@^6.0.1": - "integrity" "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==" - "resolved" "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz" - "version" "6.2.3" - dependencies: - "dns-packet" "^1.3.1" - "thunky" "^1.0.2" - -"nanoid@^3.2.0": - "integrity" "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==" - "resolved" "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz" - "version" "3.3.1" - -"negotiator@0.6.3": - "integrity" "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" - "resolved" "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" - "version" "0.6.3" - -"neo-async@^2.6.2": - "integrity" "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" - "resolved" "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" - "version" "2.6.2" - -"no-case@^3.0.4": - "integrity" "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==" - "resolved" "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz" - "version" "3.0.4" - dependencies: - "lower-case" "^2.0.2" - "tslib" "^2.0.3" - -"node-emoji@^1.10.0": - "integrity" "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==" - "resolved" "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz" - "version" "1.11.0" - dependencies: - "lodash" "^4.17.21" - -"node-fetch@2.6.7": - "integrity" "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==" - "resolved" "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz" - "version" "2.6.7" - dependencies: - "whatwg-url" "^5.0.0" - -"node-forge@^1.2.0": - "integrity" "sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA==" - "resolved" "https://registry.npmjs.org/node-forge/-/node-forge-1.3.0.tgz" - "version" "1.3.0" - -"node-releases@^2.0.8": - "integrity" "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" - "resolved" "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz" - "version" "2.0.10" - -"normalize-path@^3.0.0", "normalize-path@~3.0.0": - "integrity" "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - "resolved" "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" - "version" "3.0.0" - -"normalize-range@^0.1.2": - "integrity" "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=" - "resolved" "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz" - "version" "0.1.2" - -"normalize-url@^4.1.0": - "integrity" "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==" - "resolved" "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz" - "version" "4.5.1" - -"normalize-url@^6.0.1": - "integrity" "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" - "resolved" "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz" - "version" "6.1.0" - -"npm-run-path@^4.0.1": - "integrity" "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==" - "resolved" "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz" - "version" "4.0.1" - dependencies: - "path-key" "^3.0.0" - -"nprogress@^0.2.0": - "integrity" "sha1-y480xTIT2JVyP8urkH6UIq28r7E=" - "resolved" "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz" - "version" "0.2.0" - -"nth-check@^2.0.1": - "integrity" "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==" - "resolved" "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz" - "version" "2.0.1" - dependencies: - "boolbase" "^1.0.0" - -"nth-check@~1.0.1": - "integrity" "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==" - "resolved" "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz" - "version" "1.0.2" - dependencies: - "boolbase" "~1.0.0" - -"object-assign@^4.1.0", "object-assign@^4.1.1": - "integrity" "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - "resolved" "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" - "version" "4.1.1" - -"object-is@^1.0.1": - "integrity" "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==" - "resolved" "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz" - "version" "1.1.5" - dependencies: - "call-bind" "^1.0.2" - "define-properties" "^1.1.3" - -"object-keys@^1.0.12", "object-keys@^1.1.1": - "integrity" "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - "resolved" "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" - "version" "1.1.1" - -"object.assign@^4.1.0": - "integrity" "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==" - "resolved" "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz" - "version" "4.1.2" - dependencies: - "call-bind" "^1.0.0" - "define-properties" "^1.1.3" - "has-symbols" "^1.0.1" - "object-keys" "^1.1.1" + safe-buffer "~5.1.1" -"obuf@^1.0.0", "obuf@^1.1.2": - "integrity" "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" - "resolved" "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz" - "version" "1.1.2" +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" -"on-finished@~2.3.0": - "integrity" "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=" - "resolved" "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" - "version" "2.3.0" - dependencies: - "ee-first" "1.1.1" +cookie@0.4.2: + version "0.4.2" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz" -"on-headers@~1.0.2": - "integrity" "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" - "resolved" "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz" - "version" "1.0.2" - -"once@^1.3.0", "once@^1.3.1", "once@^1.4.0": - "integrity" "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=" - "resolved" "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - "version" "1.4.0" - dependencies: - "wrappy" "1" +copy-text-to-clipboard@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz" -"onetime@^5.1.2": - "integrity" "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==" - "resolved" "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" - "version" "5.1.2" +copy-webpack-plugin@^10.2.0: + version "10.2.4" + resolved "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz" dependencies: - "mimic-fn" "^2.1.0" + fast-glob "^3.2.7" + glob-parent "^6.0.1" + globby "^12.0.2" + normalize-path "^3.0.0" + schema-utils "^4.0.0" + serialize-javascript "^6.0.0" -"open@^8.0.9", "open@^8.4.0": - "integrity" "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==" - "resolved" "https://registry.npmjs.org/open/-/open-8.4.0.tgz" - "version" "8.4.0" +core-js-compat@^3.20.2, core-js-compat@^3.21.0: + version "3.21.1" + resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.21.1.tgz" dependencies: - "define-lazy-prop" "^2.0.0" - "is-docker" "^2.1.1" - "is-wsl" "^2.2.0" + browserslist "^4.19.1" + semver "7.0.0" -"opener@^1.5.2": - "integrity" "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==" - "resolved" "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz" - "version" "1.5.2" +core-js-pure@^3.20.2: + version "3.21.1" + resolved "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.21.1.tgz" -"p-cancelable@^1.0.0": - "integrity" "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" - "resolved" "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz" - "version" "1.1.0" +core-js@^3.18.0: + version "3.21.1" + resolved "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz" -"p-limit@^2.0.0", "p-limit@^2.2.0": - "integrity" "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==" - "resolved" "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" - "version" "2.3.0" - dependencies: - "p-try" "^2.0.0" +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" -"p-limit@^3.0.2": - "integrity" "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==" - "resolved" "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" - "version" "3.1.0" +cosmiconfig@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz" dependencies: - "yocto-queue" "^0.1.0" + "@types/parse-json" "^4.0.0" + import-fresh "^3.1.0" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.7.2" -"p-locate@^3.0.0": - "integrity" "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==" - "resolved" "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz" - "version" "3.0.0" +cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: + version "7.0.1" + resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz" dependencies: - "p-limit" "^2.0.0" + "@types/parse-json" "^4.0.0" + import-fresh "^3.2.1" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.10.0" + +cross-fetch@^3.1.5: + version "3.1.5" + resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz" + dependencies: + node-fetch "2.6.7" + +cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +crypto-random-string@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz" + +css-declaration-sorter@^6.0.3: + version "6.1.4" + resolved "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz" + dependencies: + timsort "^0.3.0" + +css-loader@^6.5.1: + version "6.6.0" + resolved "https://registry.npmjs.org/css-loader/-/css-loader-6.6.0.tgz" + dependencies: + icss-utils "^5.1.0" + postcss "^8.4.5" + postcss-modules-extract-imports "^3.0.0" + postcss-modules-local-by-default "^4.0.0" + postcss-modules-scope "^3.0.0" + postcss-modules-values "^4.0.0" + postcss-value-parser "^4.2.0" + semver "^7.3.5" + +css-minimizer-webpack-plugin@^3.3.1: + version "3.4.1" + resolved "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz" + dependencies: + cssnano "^5.0.6" + jest-worker "^27.0.2" + postcss "^8.3.5" + schema-utils "^4.0.0" + serialize-javascript "^6.0.0" + source-map "^0.6.1" + +css-select@^4.1.3: + version "4.2.1" + resolved "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz" + dependencies: + boolbase "^1.0.0" + css-what "^5.1.0" + domhandler "^4.3.0" + domutils "^2.8.0" + nth-check "^2.0.1" + +css-select@~1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz" + dependencies: + boolbase "~1.0.0" + css-what "2.1" + domutils "1.5.1" + nth-check "~1.0.1" + +css-tree@^1.1.2, css-tree@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz" + dependencies: + mdn-data "2.0.14" + source-map "^0.6.1" + +css-what@2.1: + version "2.1.3" + resolved "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz" + +css-what@^5.0.1, css-what@^5.1.0: + version "5.1.0" + resolved "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz" + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz" + +cssnano-preset-advanced@^5.1.4: + version "5.1.12" + resolved "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-5.1.12.tgz" + dependencies: + autoprefixer "^10.3.7" + cssnano-preset-default "^5.1.12" + postcss-discard-unused "^5.0.3" + postcss-merge-idents "^5.0.3" + postcss-reduce-idents "^5.0.3" + postcss-zindex "^5.0.2" + +cssnano-preset-default@^5.1.12: + version "5.1.12" + resolved "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.1.12.tgz" + dependencies: + css-declaration-sorter "^6.0.3" + cssnano-utils "^3.0.2" + postcss-calc "^8.2.0" + postcss-colormin "^5.2.5" + postcss-convert-values "^5.0.4" + postcss-discard-comments "^5.0.3" + postcss-discard-duplicates "^5.0.3" + postcss-discard-empty "^5.0.3" + postcss-discard-overridden "^5.0.4" + postcss-merge-longhand "^5.0.6" + postcss-merge-rules "^5.0.6" + postcss-minify-font-values "^5.0.4" + postcss-minify-gradients "^5.0.6" + postcss-minify-params "^5.0.5" + postcss-minify-selectors "^5.1.3" + postcss-normalize-charset "^5.0.3" + postcss-normalize-display-values "^5.0.3" + postcss-normalize-positions "^5.0.4" + postcss-normalize-repeat-style "^5.0.4" + postcss-normalize-string "^5.0.4" + postcss-normalize-timing-functions "^5.0.3" + postcss-normalize-unicode "^5.0.4" + postcss-normalize-url "^5.0.5" + postcss-normalize-whitespace "^5.0.4" + postcss-ordered-values "^5.0.5" + postcss-reduce-initial "^5.0.3" + postcss-reduce-transforms "^5.0.4" + postcss-svgo "^5.0.4" + postcss-unique-selectors "^5.0.4" + +cssnano-utils@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.0.2.tgz" + +cssnano@^5.0.6, cssnano@^5.0.8: + version "5.0.17" + resolved "https://registry.npmjs.org/cssnano/-/cssnano-5.0.17.tgz" + dependencies: + cssnano-preset-default "^5.1.12" + lilconfig "^2.0.3" + yaml "^1.10.2" + +csso@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz" + dependencies: + css-tree "^1.1.2" + +csstype@^3.0.2: + version "3.0.10" + resolved "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz" + +debug@2.6.9, debug@^2.6.0: + version "2.6.9" + resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + dependencies: + ms "2.0.0" + +debug@^3.1.1: + version "3.2.7" + resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" + dependencies: + ms "^2.1.1" + +debug@^4.1.0, debug@^4.1.1: + version "4.3.3" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz" + dependencies: + ms "2.1.2" + +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz" + dependencies: + mimic-response "^1.0.0" + +deep-equal@^1.0.1: + version "1.1.1" + resolved "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz" + dependencies: + is-arguments "^1.0.4" + is-date-object "^1.0.1" + is-regex "^1.0.4" + object-is "^1.0.1" + object-keys "^1.1.1" + regexp.prototype.flags "^1.2.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz" + +deepmerge@^1.3.2: + version "1.5.2" + resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz" + +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz" + +default-gateway@^6.0.3: + version "6.0.3" + resolved "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz" + dependencies: + execa "^5.0.0" + +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz" + +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz" -"p-locate@^4.1.0": - "integrity" "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==" - "resolved" "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" - "version" "4.1.0" +define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz" dependencies: - "p-limit" "^2.2.0" + object-keys "^1.0.12" -"p-locate@^5.0.0": - "integrity" "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==" - "resolved" "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" - "version" "5.0.0" +del@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/del/-/del-6.0.0.tgz" dependencies: - "p-limit" "^3.0.2" + globby "^11.0.1" + graceful-fs "^4.2.4" + is-glob "^4.0.1" + is-path-cwd "^2.2.0" + is-path-inside "^3.0.2" + p-map "^4.0.0" + rimraf "^3.0.2" + slash "^3.0.0" -"p-map@^4.0.0": - "integrity" "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==" - "resolved" "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz" - "version" "4.0.0" +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" + +detab@2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/detab/-/detab-2.0.4.tgz" dependencies: - "aggregate-error" "^3.0.0" + repeat-string "^1.5.4" -"p-retry@^4.5.0": - "integrity" "sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==" - "resolved" "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz" - "version" "4.6.1" +detect-node@^2.0.4: + version "2.1.0" + resolved "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz" + +detect-port-alt@^1.1.6: + version "1.1.6" + resolved "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz" dependencies: - "@types/retry" "^0.12.0" - "retry" "^0.13.1" - -"p-try@^2.0.0": - "integrity" "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" - "resolved" "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" - "version" "2.2.0" - -"package-json@^6.3.0": - "integrity" "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==" - "resolved" "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz" - "version" "6.5.0" - dependencies: - "got" "^9.6.0" - "registry-auth-token" "^4.0.0" - "registry-url" "^5.0.0" - "semver" "^6.2.0" - -"param-case@^3.0.4": - "integrity" "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==" - "resolved" "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz" - "version" "3.0.4" - dependencies: - "dot-case" "^3.0.4" - "tslib" "^2.0.3" - -"parent-module@^1.0.0": - "integrity" "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==" - "resolved" "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" - "version" "1.0.1" - dependencies: - "callsites" "^3.0.0" - -"parse-entities@^2.0.0": - "integrity" "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==" - "resolved" "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "character-entities" "^1.0.0" - "character-entities-legacy" "^1.0.0" - "character-reference-invalid" "^1.0.0" - "is-alphanumerical" "^1.0.0" - "is-decimal" "^1.0.0" - "is-hexadecimal" "^1.0.0" - -"parse-json@^5.0.0": - "integrity" "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==" - "resolved" "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" - "version" "5.2.0" + address "^1.0.1" + debug "^2.6.0" + +detect-port@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz" dependencies: - "@babel/code-frame" "^7.0.0" - "error-ex" "^1.3.1" - "json-parse-even-better-errors" "^2.3.0" - "lines-and-columns" "^1.1.6" - -"parse-numeric-range@^1.3.0": - "integrity" "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" - "resolved" "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz" - "version" "1.3.0" - -"parse5-htmlparser2-tree-adapter@^6.0.1": - "integrity" "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==" - "resolved" "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz" - "version" "6.0.1" - dependencies: - "parse5" "^6.0.1" - -"parse5@^5.0.0": - "integrity" "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" - "resolved" "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz" - "version" "5.1.1" - -"parse5@^6.0.0", "parse5@^6.0.1": - "integrity" "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" - "resolved" "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz" - "version" "6.0.1" - -"parseurl@~1.3.2", "parseurl@~1.3.3": - "integrity" "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - "resolved" "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" - "version" "1.3.3" - -"pascal-case@^3.1.2": - "integrity" "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==" - "resolved" "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz" - "version" "3.1.2" - dependencies: - "no-case" "^3.0.4" - "tslib" "^2.0.3" - -"path-exists@^3.0.0": - "integrity" "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - "resolved" "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" - "version" "3.0.0" - -"path-exists@^4.0.0": - "integrity" "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" - "resolved" "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" - "version" "4.0.0" - -"path-is-absolute@^1.0.0": - "integrity" "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - "resolved" "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - "version" "1.0.1" - -"path-is-inside@1.0.2": - "integrity" "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" - "resolved" "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz" - "version" "1.0.2" - -"path-key@^3.0.0", "path-key@^3.1.0": - "integrity" "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - "resolved" "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" - "version" "3.1.1" - -"path-parse@^1.0.7": - "integrity" "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - "resolved" "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" - "version" "1.0.7" - -"path-to-regexp@^1.7.0": - "integrity" "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==" - "resolved" "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz" - "version" "1.8.0" - dependencies: - "isarray" "0.0.1" - -"path-to-regexp@0.1.7": - "integrity" "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - "resolved" "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" - "version" "0.1.7" - -"path-to-regexp@2.2.1": - "integrity" "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" - "resolved" "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz" - "version" "2.2.1" - -"path-type@^4.0.0": - "integrity" "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" - "resolved" "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" - "version" "4.0.0" - -"picocolors@^1.0.0": - "integrity" "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - "resolved" "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" - "version" "1.0.0" - -"picomatch@^2.0.4", "picomatch@^2.2.1", "picomatch@^2.2.3": - "integrity" "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - "resolved" "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" - "version" "2.3.1" - -"pkg-dir@^4.1.0": - "integrity" "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==" - "resolved" "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" - "version" "4.2.0" - dependencies: - "find-up" "^4.0.0" - -"pkg-up@^3.1.0": - "integrity" "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==" - "resolved" "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz" - "version" "3.1.0" - dependencies: - "find-up" "^3.0.0" - -"portfinder@^1.0.28": - "integrity" "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==" - "resolved" "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz" - "version" "1.0.28" - dependencies: - "async" "^2.6.2" - "debug" "^3.1.1" - "mkdirp" "^0.5.5" - -"postcss-calc@^8.2.0": - "integrity" "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==" - "resolved" "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz" - "version" "8.2.4" - dependencies: - "postcss-selector-parser" "^6.0.9" - "postcss-value-parser" "^4.2.0" - -"postcss-colormin@^5.2.5": - "integrity" "sha512-+X30aDaGYq81mFqwyPpnYInsZQnNpdxMX0ajlY7AExCexEFkPVV+KrO7kXwayqEWL2xwEbNQ4nUO0ZsRWGnevg==" - "resolved" "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.2.5.tgz" - "version" "5.2.5" - dependencies: - "browserslist" "^4.16.6" - "caniuse-api" "^3.0.0" - "colord" "^2.9.1" - "postcss-value-parser" "^4.2.0" - -"postcss-convert-values@^5.0.4": - "integrity" "sha512-bugzSAyjIexdObovsPZu/sBCTHccImJxLyFgeV0MmNBm/Lw5h5XnjfML6gzEmJ3A6nyfCW7hb1JXzcsA4Zfbdw==" - "resolved" "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.0.4.tgz" - "version" "5.0.4" - dependencies: - "postcss-value-parser" "^4.2.0" - -"postcss-discard-comments@^5.0.3": - "integrity" "sha512-6W5BemziRoqIdAKT+1QjM4bNcJAQ7z7zk073730NHg4cUXh3/rQHHj7pmYxUB9aGhuRhBiUf0pXvIHkRwhQP0Q==" - "resolved" "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.0.3.tgz" - "version" "5.0.3" - -"postcss-discard-duplicates@^5.0.3": - "integrity" "sha512-vPtm1Mf+kp7iAENTG7jI1MN1lk+fBqL5y+qxyi4v3H+lzsXEdfS3dwUZD45KVhgzDEgduur8ycB4hMegyMTeRw==" - "resolved" "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.3.tgz" - "version" "5.0.3" - -"postcss-discard-empty@^5.0.3": - "integrity" "sha512-xGJugpaXKakwKI7sSdZjUuN4V3zSzb2Y0LOlmTajFbNinEjTfVs9PFW2lmKBaC/E64WwYppfqLD03P8l9BuueA==" - "resolved" "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.0.3.tgz" - "version" "5.0.3" - -"postcss-discard-overridden@^5.0.4": - "integrity" "sha512-3j9QH0Qh1KkdxwiZOW82cId7zdwXVQv/gRXYDnwx5pBtR1sTkU4cXRK9lp5dSdiM0r0OICO/L8J6sV1/7m0kHg==" - "resolved" "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.0.4.tgz" - "version" "5.0.4" - -"postcss-discard-unused@^5.0.3": - "integrity" "sha512-WO6FJxL5fGnuE77ZbTcZ/nRZJ4+TOqNaqLBLWgkR4e+WdmHn77OHPyQmsRv7eOB2rLKL6tsq2bs1GwoKXD/++Q==" - "resolved" "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-5.0.3.tgz" - "version" "5.0.3" - dependencies: - "postcss-selector-parser" "^6.0.5" - -"postcss-loader@^6.1.1": - "integrity" "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==" - "resolved" "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz" - "version" "6.2.1" - dependencies: - "cosmiconfig" "^7.0.0" - "klona" "^2.0.5" - "semver" "^7.3.5" - -"postcss-merge-idents@^5.0.3": - "integrity" "sha512-Z4LCzh2WzMn69KaS2FaJcrIeDQ170V13QHq+0hnBEFKJJkD+y5qndZ/bl3AhpddrSrXWIVR+xAwjmHQIJI2Eog==" - "resolved" "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-5.0.3.tgz" - "version" "5.0.3" - dependencies: - "cssnano-utils" "^3.0.2" - "postcss-value-parser" "^4.2.0" - -"postcss-merge-longhand@^5.0.6": - "integrity" "sha512-rkmoPwQO6ymJSmWsX6l2hHeEBQa7C4kJb9jyi5fZB1sE8nSCv7sqchoYPixRwX/yvLoZP2y6FA5kcjiByeJqDg==" - "resolved" "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.0.6.tgz" - "version" "5.0.6" - dependencies: - "postcss-value-parser" "^4.2.0" - "stylehacks" "^5.0.3" - -"postcss-merge-rules@^5.0.6": - "integrity" "sha512-nzJWJ9yXWp8AOEpn/HFAW72WKVGD2bsLiAmgw4hDchSij27bt6TF+sIK0cJUBAYT3SGcjtGGsOR89bwkkMuMgQ==" - "resolved" "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.0.6.tgz" - "version" "5.0.6" + address "^1.0.1" + debug "^2.6.0" + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" dependencies: - "browserslist" "^4.16.6" - "caniuse-api" "^3.0.0" - "cssnano-utils" "^3.0.2" - "postcss-selector-parser" "^6.0.5" + path-type "^4.0.0" -"postcss-minify-font-values@^5.0.4": - "integrity" "sha512-RN6q3tyuEesvyCYYFCRGJ41J1XFvgV+dvYGHr0CeHv8F00yILlN8Slf4t8XW4IghlfZYCeyRrANO6HpJ948ieA==" - "resolved" "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.0.4.tgz" - "version" "5.0.4" - dependencies: - "postcss-value-parser" "^4.2.0" - -"postcss-minify-gradients@^5.0.6": - "integrity" "sha512-E/dT6oVxB9nLGUTiY/rG5dX9taugv9cbLNTFad3dKxOO+BQg25Q/xo2z2ddG+ZB1CbkZYaVwx5blY8VC7R/43A==" - "resolved" "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.0.6.tgz" - "version" "5.0.6" - dependencies: - "colord" "^2.9.1" - "cssnano-utils" "^3.0.2" - "postcss-value-parser" "^4.2.0" +dns-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz" -"postcss-minify-params@^5.0.5": - "integrity" "sha512-YBNuq3Rz5LfLFNHb9wrvm6t859b8qIqfXsWeK7wROm3jSKNpO1Y5e8cOyBv6Acji15TgSrAwb3JkVNCqNyLvBg==" - "resolved" "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.0.5.tgz" - "version" "5.0.5" +dns-packet@^1.3.1: + version "1.3.4" + resolved "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz" dependencies: - "browserslist" "^4.16.6" - "cssnano-utils" "^3.0.2" - "postcss-value-parser" "^4.2.0" + ip "^1.1.0" + safe-buffer "^5.0.1" -"postcss-minify-selectors@^5.1.3": - "integrity" "sha512-9RJfTiQEKA/kZhMaEXND893nBqmYQ8qYa/G+uPdVnXF6D/FzpfI6kwBtWEcHx5FqDbA79O9n6fQJfrIj6M8jvQ==" - "resolved" "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.1.3.tgz" - "version" "5.1.3" +dns-txt@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz" dependencies: - "postcss-selector-parser" "^6.0.5" + buffer-indexof "^1.0.0" -"postcss-modules-extract-imports@^3.0.0": - "integrity" "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==" - "resolved" "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz" - "version" "3.0.0" +dom-converter@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz" + dependencies: + utila "~0.4" -"postcss-modules-local-by-default@^4.0.0": - "integrity" "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==" - "resolved" "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz" - "version" "4.0.0" +dom-serializer@0: + version "0.2.2" + resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz" dependencies: - "icss-utils" "^5.0.0" - "postcss-selector-parser" "^6.0.2" - "postcss-value-parser" "^4.1.0" + domelementtype "^2.0.1" + entities "^2.0.0" -"postcss-modules-scope@^3.0.0": - "integrity" "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==" - "resolved" "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz" - "version" "3.0.0" +dom-serializer@^1.0.1, dom-serializer@^1.3.2: + version "1.3.2" + resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz" dependencies: - "postcss-selector-parser" "^6.0.4" + domelementtype "^2.0.1" + domhandler "^4.2.0" + entities "^2.0.0" -"postcss-modules-values@^4.0.0": - "integrity" "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==" - "resolved" "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz" - "version" "4.0.0" +dom-serializer@~0.1.0: + version "0.1.1" + resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz" dependencies: - "icss-utils" "^5.0.0" + domelementtype "^1.3.0" + entities "^1.1.1" -"postcss-normalize-charset@^5.0.3": - "integrity" "sha512-iKEplDBco9EfH7sx4ut7R2r/dwTnUqyfACf62Unc9UiyFuI7uUqZZtY+u+qp7g8Qszl/U28HIfcsI3pEABWFfA==" - "resolved" "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.0.3.tgz" - "version" "5.0.3" +domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: + version "1.3.1" + resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz" -"postcss-normalize-display-values@^5.0.3": - "integrity" "sha512-FIV5FY/qs4Ja32jiDb5mVj5iWBlS3N8tFcw2yg98+8MkRgyhtnBgSC0lxU+16AMHbjX5fbSJgw5AXLMolonuRQ==" - "resolved" "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.3.tgz" - "version" "5.0.3" - dependencies: - "postcss-value-parser" "^4.2.0" +domelementtype@^2.0.1, domelementtype@^2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz" -"postcss-normalize-positions@^5.0.4": - "integrity" "sha512-qynirjBX0Lc73ROomZE3lzzmXXTu48/QiEzKgMeqh28+MfuHLsuqC9po4kj84igZqqFGovz8F8hf44hA3dPYmQ==" - "resolved" "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.0.4.tgz" - "version" "5.0.4" +domhandler@^2.3.0: + version "2.4.2" + resolved "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz" dependencies: - "postcss-value-parser" "^4.2.0" + domelementtype "1" -"postcss-normalize-repeat-style@^5.0.4": - "integrity" "sha512-Innt+wctD7YpfeDR7r5Ik6krdyppyAg2HBRpX88fo5AYzC1Ut/l3xaxACG0KsbX49cO2n5EB13clPwuYVt8cMA==" - "resolved" "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.4.tgz" - "version" "5.0.4" +domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.0: + version "4.3.0" + resolved "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz" dependencies: - "postcss-value-parser" "^4.2.0" + domelementtype "^2.2.0" -"postcss-normalize-string@^5.0.4": - "integrity" "sha512-Dfk42l0+A1CDnVpgE606ENvdmksttLynEqTQf5FL3XGQOyqxjbo25+pglCUvziicTxjtI2NLUR6KkxyUWEVubQ==" - "resolved" "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.0.4.tgz" - "version" "5.0.4" +domutils@1.5.1: + version "1.5.1" + resolved "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz" dependencies: - "postcss-value-parser" "^4.2.0" + dom-serializer "0" + domelementtype "1" -"postcss-normalize-timing-functions@^5.0.3": - "integrity" "sha512-QRfjvFh11moN4PYnJ7hia4uJXeFotyK3t2jjg8lM9mswleGsNw2Lm3I5wO+l4k1FzK96EFwEVn8X8Ojrp2gP4g==" - "resolved" "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.3.tgz" - "version" "5.0.3" +domutils@^1.5.1: + version "1.7.0" + resolved "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz" dependencies: - "postcss-value-parser" "^4.2.0" + dom-serializer "0" + domelementtype "1" -"postcss-normalize-unicode@^5.0.4": - "integrity" "sha512-W79Regn+a+eXTzB+oV/8XJ33s3pDyFTND2yDuUCo0Xa3QSy1HtNIfRVPXNubHxjhlqmMFADr3FSCHT84ITW3ig==" - "resolved" "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.4.tgz" - "version" "5.0.4" +domutils@^2.5.2, domutils@^2.7.0, domutils@^2.8.0: + version "2.8.0" + resolved "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz" dependencies: - "browserslist" "^4.16.6" - "postcss-value-parser" "^4.2.0" + dom-serializer "^1.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" -"postcss-normalize-url@^5.0.5": - "integrity" "sha512-Ws3tX+PcekYlXh+ycAt0wyzqGthkvVtZ9SZLutMVvHARxcpu4o7vvXcNoiNKyjKuWecnjS6HDI3fjBuDr5MQxQ==" - "resolved" "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.0.5.tgz" - "version" "5.0.5" +dot-case@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz" dependencies: - "normalize-url" "^6.0.1" - "postcss-value-parser" "^4.2.0" + no-case "^3.0.4" + tslib "^2.0.3" -"postcss-normalize-whitespace@^5.0.4": - "integrity" "sha512-wsnuHolYZjMwWZJoTC9jeI2AcjA67v4UuidDrPN9RnX8KIZfE+r2Nd6XZRwHVwUiHmRvKQtxiqo64K+h8/imaw==" - "resolved" "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.4.tgz" - "version" "5.0.4" +dot-prop@^5.2.0: + version "5.3.0" + resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz" dependencies: - "postcss-value-parser" "^4.2.0" + is-obj "^2.0.0" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz" + +duplexer@^0.1.2: + version "0.1.2" + resolved "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" -"postcss-ordered-values@^5.0.5": - "integrity" "sha512-mfY7lXpq+8bDEHfP+muqibDPhZ5eP9zgBEF9XRvoQgXcQe2Db3G1wcvjbnfjXG6wYsl+0UIjikqq4ym1V2jGMQ==" - "resolved" "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.0.5.tgz" - "version" "5.0.5" +electron-to-chromium@^1.4.284: + version "1.4.328" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.328.tgz" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz" + +emoticon@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/emoticon/-/emoticon-3.2.0.tgz" + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" dependencies: - "cssnano-utils" "^3.0.2" - "postcss-value-parser" "^4.2.0" + once "^1.4.0" -"postcss-reduce-idents@^5.0.3": - "integrity" "sha512-9bj9/Xhwiti0Z35kkguJX4G6yUYVw8S1kRLU4jFSCTEuHu4yJggf4rNUoVnT45lm/vU97Wd593CxspMDbHxy4w==" - "resolved" "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-5.0.3.tgz" - "version" "5.0.3" +enhanced-resolve@^5.10.0: + version "5.12.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634" dependencies: - "postcss-value-parser" "^4.2.0" + graceful-fs "^4.2.4" + tapable "^2.2.0" + +entities@^1.1.1, entities@~1.1.1: + version "1.1.2" + resolved "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz" + +entities@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz" + +entities@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz" -"postcss-reduce-initial@^5.0.3": - "integrity" "sha512-c88TkSnQ/Dnwgb4OZbKPOBbCaauwEjbECP5uAuFPOzQ+XdjNjRH7SG0dteXrpp1LlIFEKK76iUGgmw2V0xeieA==" - "resolved" "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.0.3.tgz" - "version" "5.0.3" +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" dependencies: - "browserslist" "^4.16.6" - "caniuse-api" "^3.0.0" + is-arrayish "^0.2.1" -"postcss-reduce-transforms@^5.0.4": - "integrity" "sha512-VIJB9SFSaL8B/B7AXb7KHL6/GNNbbCHslgdzS9UDfBZYIA2nx8NLY7iD/BXFSO/1sRUILzBTfHCoW5inP37C5g==" - "resolved" "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.4.tgz" - "version" "5.0.4" +es-module-lexer@^0.9.0: + version "0.9.3" + resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" + +escape-goat@^2.0.0: + version "2.1.1" + resolved "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz" + +escape-html@^1.0.3, escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + +eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" + +estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" + +eta@^1.12.3: + version "1.12.3" + resolved "https://registry.npmjs.org/eta/-/eta-1.12.3.tgz" + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" + +eval@^0.1.4: + version "0.1.6" + resolved "https://registry.npmjs.org/eval/-/eval-0.1.6.tgz" + dependencies: + require-like ">= 0.1.1" + +eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz" + +events@^3.2.0: + version "3.3.0" + resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz" + +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +express@^4.17.1: + version "4.17.3" + resolved "https://registry.npmjs.org/express/-/express-4.17.3.tgz" + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.19.2" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.4.2" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~1.1.2" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "~1.1.2" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.9.7" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.17.2" + serve-static "1.14.2" + setprototypeof "1.2.0" + statuses "~1.5.0" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" + dependencies: + is-extendable "^0.1.0" + +extend@^3.0.0: + version "3.0.2" + resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" + +fast-glob@^3.2.7, fast-glob@^3.2.9: + version "3.2.11" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz" dependencies: - "postcss-value-parser" "^4.2.0" + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" -"postcss-selector-parser@^6.0.2", "postcss-selector-parser@^6.0.4", "postcss-selector-parser@^6.0.5", "postcss-selector-parser@^6.0.9": - "integrity" "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==" - "resolved" "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz" - "version" "6.0.9" +fast-url-parser@1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz" dependencies: - "cssesc" "^3.0.0" - "util-deprecate" "^1.0.2" + punycode "^1.3.2" -"postcss-sort-media-queries@^4.1.0": - "integrity" "sha512-9VYekQalFZ3sdgcTjXMa0dDjsfBVHXlraYJEMiOJ/2iMmI2JGCMavP16z3kWOaRu8NSaJCTgVpB/IVpH5yT9YQ==" - "resolved" "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-4.2.1.tgz" - "version" "4.2.1" +fastq@^1.6.0: + version "1.13.0" + resolved "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz" dependencies: - "sort-css-media-queries" "2.0.4" + reusify "^1.0.4" -"postcss-svgo@^5.0.4": - "integrity" "sha512-yDKHvULbnZtIrRqhZoA+rxreWpee28JSRH/gy9727u0UCgtpv1M/9WEWY3xySlFa0zQJcqf6oCBJPR5NwkmYpg==" - "resolved" "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.0.4.tgz" - "version" "5.0.4" +faye-websocket@^0.11.3: + version "0.11.4" + resolved "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz" dependencies: - "postcss-value-parser" "^4.2.0" - "svgo" "^2.7.0" + websocket-driver ">=0.5.1" -"postcss-unique-selectors@^5.0.4": - "integrity" "sha512-5ampwoSDJCxDPoANBIlMgoBcYUHnhaiuLYJR5pj1DLnYQvMRVyFuTA5C3Bvt+aHtiqWpJkD/lXT50Vo1D0ZsAQ==" - "resolved" "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.0.4.tgz" - "version" "5.0.4" +fbemitter@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/fbemitter/-/fbemitter-3.0.0.tgz" dependencies: - "postcss-selector-parser" "^6.0.5" + fbjs "^3.0.0" -"postcss-value-parser@^4.1.0", "postcss-value-parser@^4.2.0": - "integrity" "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" - "resolved" "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" - "version" "4.2.0" +fbjs-css-vars@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz" -"postcss-zindex@^5.0.2": - "integrity" "sha512-KPQFjQu73H35HLHmE8Wv31ygfQoucxD52oRm4FPFv1emYhFMzUQdF8adaXCevFLIHPRp2rRYfbaDiEqZ4YjVtw==" - "resolved" "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-5.0.2.tgz" - "version" "5.0.2" +fbjs@^3.0.0, fbjs@^3.0.1: + version "3.0.4" + resolved "https://registry.npmjs.org/fbjs/-/fbjs-3.0.4.tgz" + dependencies: + cross-fetch "^3.1.5" + fbjs-css-vars "^1.0.0" + loose-envify "^1.0.0" + object-assign "^4.1.0" + promise "^7.1.1" + setimmediate "^1.0.5" + ua-parser-js "^0.7.30" -"postcss@^7.0.0 || ^8.0.1", "postcss@^8.0.9", "postcss@^8.1.0", "postcss@^8.2.15", "postcss@^8.2.2", "postcss@^8.3.11", "postcss@^8.3.5", "postcss@^8.3.7", "postcss@^8.4.4", "postcss@^8.4.5": - "integrity" "sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA==" - "resolved" "https://registry.npmjs.org/postcss/-/postcss-8.4.6.tgz" - "version" "8.4.6" +feed@^4.2.2: + version "4.2.2" + resolved "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz" dependencies: - "nanoid" "^3.2.0" - "picocolors" "^1.0.0" - "source-map-js" "^1.0.2" - -"prepend-http@^2.0.0": - "integrity" "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" - "resolved" "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz" - "version" "2.0.0" - -"pretty-error@^4.0.0": - "integrity" "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==" - "resolved" "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz" - "version" "4.0.0" - dependencies: - "lodash" "^4.17.20" - "renderkid" "^3.0.0" - -"pretty-time@^1.1.0": - "integrity" "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==" - "resolved" "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz" - "version" "1.1.0" - -"prism-react-renderer@^1.2.1": - "integrity" "sha512-xUeDMEz074d0zc5y6rxiMp/dlC7C+5IDDlaEUlcBOFE2wddz7hz5PNupb087mPwTt7T9BrFmewObfCBuf/LKwQ==" - "resolved" "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-1.3.1.tgz" - "version" "1.3.1" - -"prismjs@^1.23.0": - "integrity" "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==" - "resolved" "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz" - "version" "1.27.0" - -"process-nextick-args@~2.0.0": - "integrity" "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - "resolved" "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" - "version" "2.0.1" - -"promise@^7.1.1": - "integrity" "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==" - "resolved" "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz" - "version" "7.3.1" - dependencies: - "asap" "~2.0.3" - -"prompts@^2.4.1", "prompts@^2.4.2": - "integrity" "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==" - "resolved" "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz" - "version" "2.4.2" - dependencies: - "kleur" "^3.0.3" - "sisteransi" "^1.0.5" - -"prop-types@^15.0.0", "prop-types@^15.6.2", "prop-types@^15.7.2": - "integrity" "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==" - "resolved" "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" - "version" "15.8.1" - dependencies: - "loose-envify" "^1.4.0" - "object-assign" "^4.1.1" - "react-is" "^16.13.1" - -"property-information@^5.0.0", "property-information@^5.3.0": - "integrity" "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==" - "resolved" "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz" - "version" "5.6.0" - dependencies: - "xtend" "^4.0.0" - -"proxy-addr@~2.0.7": - "integrity" "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==" - "resolved" "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" - "version" "2.0.7" - dependencies: - "forwarded" "0.2.0" - "ipaddr.js" "1.9.1" - -"pump@^3.0.0": - "integrity" "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==" - "resolved" "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz" - "version" "3.0.0" - dependencies: - "end-of-stream" "^1.1.0" - "once" "^1.3.1" - -"punycode@^1.3.2": - "integrity" "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - "resolved" "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" - "version" "1.4.1" - -"punycode@^2.1.0": - "integrity" "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - "resolved" "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz" - "version" "2.1.1" - -"punycode@1.3.2": - "integrity" "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" - "resolved" "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" - "version" "1.3.2" - -"pupa@^2.1.1": - "integrity" "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==" - "resolved" "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz" - "version" "2.1.1" - dependencies: - "escape-goat" "^2.0.0" - -"pure-color@^1.2.0": - "integrity" "sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4=" - "resolved" "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz" - "version" "1.3.0" - -"qs@6.9.7": - "integrity" "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" - "resolved" "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz" - "version" "6.9.7" - -"querystring@0.2.0": - "integrity" "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" - "resolved" "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" - "version" "0.2.0" - -"queue-microtask@^1.2.2": - "integrity" "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" - "resolved" "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" - "version" "1.2.3" - -"queue@6.0.2": - "integrity" "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==" - "resolved" "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz" - "version" "6.0.2" - dependencies: - "inherits" "~2.0.3" - -"randombytes@^2.1.0": - "integrity" "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==" - "resolved" "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" - "version" "2.1.0" - dependencies: - "safe-buffer" "^5.1.0" - -"range-parser@^1.2.1", "range-parser@~1.2.1": - "integrity" "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - "resolved" "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" - "version" "1.2.1" - -"range-parser@1.2.0": - "integrity" "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" - "resolved" "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz" - "version" "1.2.0" - -"raw-body@2.4.3": - "integrity" "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==" - "resolved" "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz" - "version" "2.4.3" - dependencies: - "bytes" "3.1.2" - "http-errors" "1.8.1" - "iconv-lite" "0.4.24" - "unpipe" "1.0.0" - -"rc@^1.2.8": - "integrity" "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==" - "resolved" "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz" - "version" "1.2.8" - dependencies: - "deep-extend" "^0.6.0" - "ini" "~1.3.0" - "minimist" "^1.2.0" - "strip-json-comments" "~2.0.1" - -"react-base16-styling@^0.6.0": - "integrity" "sha1-7yFW1mz0E5aVyKFniGy2nqZgeSw=" - "resolved" "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.6.0.tgz" - "version" "0.6.0" - dependencies: - "base16" "^1.0.0" - "lodash.curry" "^4.0.1" - "lodash.flow" "^3.3.0" - "pure-color" "^1.2.0" - -"react-dev-utils@^12.0.0": - "integrity" "sha512-xBQkitdxozPxt1YZ9O1097EJiVpwHr9FoAuEVURCKV0Av8NBERovJauzP7bo1ThvuhZ4shsQ1AJiu4vQpoT1AQ==" - "resolved" "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz" - "version" "12.0.0" + xml-js "^1.6.11" + +file-loader@^6.2.0: + version "6.2.0" + resolved "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz" dependencies: - "@babel/code-frame" "^7.16.0" - "address" "^1.1.2" - "browserslist" "^4.18.1" - "chalk" "^4.1.2" - "cross-spawn" "^7.0.3" - "detect-port-alt" "^1.1.6" - "escape-string-regexp" "^4.0.0" - "filesize" "^8.0.6" - "find-up" "^5.0.0" - "fork-ts-checker-webpack-plugin" "^6.5.0" - "global-modules" "^2.0.0" - "globby" "^11.0.4" - "gzip-size" "^6.0.0" - "immer" "^9.0.7" - "is-root" "^2.1.0" - "loader-utils" "^3.2.0" - "open" "^8.4.0" - "pkg-up" "^3.1.0" - "prompts" "^2.4.2" - "react-error-overlay" "^6.0.10" - "recursive-readdir" "^2.2.2" - "shell-quote" "^1.7.3" - "strip-ansi" "^6.0.1" - "text-table" "^0.2.0" - -"react-dom@*", "react-dom@^16.10.2", "react-dom@^16.8.4 || ^17.0.0", "react-dom@^17.0.0 || ^16.3.0 || ^15.5.4", "react-dom@>= 16.8.0 < 18.0.0": - "integrity" "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==" - "resolved" "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz" - "version" "16.14.0" - dependencies: - "loose-envify" "^1.1.0" - "object-assign" "^4.1.1" - "prop-types" "^15.6.2" - "scheduler" "^0.19.1" - -"react-error-overlay@^6.0.10": - "integrity" "sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA==" - "resolved" "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz" - "version" "6.0.10" - -"react-fast-compare@^3.1.1": - "integrity" "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" - "resolved" "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz" - "version" "3.2.0" - -"react-helmet@^6.1.0": - "integrity" "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==" - "resolved" "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz" - "version" "6.1.0" - dependencies: - "object-assign" "^4.1.1" - "prop-types" "^15.7.2" - "react-fast-compare" "^3.1.1" - "react-side-effect" "^2.1.0" - -"react-is@^16.13.1", "react-is@^16.6.0", "react-is@^16.7.0": - "integrity" "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - "resolved" "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" - "version" "16.13.1" - -"react-json-view@^1.21.3": - "integrity" "sha512-13p8IREj9/x/Ye4WI/JpjhoIwuzEgUAtgJZNBJckfzJt1qyh24BdTm6UQNGnyTq9dapQdrqvquZTo3dz1X6Cjw==" - "resolved" "https://registry.npmjs.org/react-json-view/-/react-json-view-1.21.3.tgz" - "version" "1.21.3" - dependencies: - "flux" "^4.0.1" - "react-base16-styling" "^0.6.0" - "react-lifecycles-compat" "^3.0.4" - "react-textarea-autosize" "^8.3.2" - -"react-lifecycles-compat@^3.0.4": - "integrity" "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" - "resolved" "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz" - "version" "3.0.4" - -"react-loadable-ssr-addon-v5-slorber@^1.0.1": - "integrity" "sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==" - "resolved" "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz" - "version" "1.0.1" + loader-utils "^2.0.0" + schema-utils "^3.0.0" + +filesize@^8.0.6: + version "8.0.7" + resolved "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" dependencies: - "@babel/runtime" "^7.10.3" + to-regex-range "^5.0.1" -"react-loadable@*", "react-loadable@npm:@docusaurus/react-loadable@5.5.2": - "integrity" "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==" - "resolved" "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz" - "version" "5.5.2" +finalhandler@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz" dependencies: - "@types/react" "*" - "prop-types" "^15.6.2" + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" -"react-popupbox@^2.0.8": - "integrity" "sha512-5DT0SxLMIchKgnUkdPwTzvFhtTL5SOQd6n5dzUnnELiimjFE8eaQwL1n58NZUxs9oJsHXF3qQNvcgwEfn8VHrw==" - "resolved" "https://registry.npmjs.org/react-popupbox/-/react-popupbox-2.0.8.tgz" - "version" "2.0.8" +find-cache-dir@^3.3.1: + version "3.3.2" + resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz" dependencies: - "deepmerge" "^1.3.2" - "react" "^16.3.1" + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" -"react-router-config@^5.1.1": - "integrity" "sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==" - "resolved" "https://registry.npmjs.org/react-router-config/-/react-router-config-5.1.1.tgz" - "version" "5.1.1" +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz" dependencies: - "@babel/runtime" "^7.1.2" + locate-path "^3.0.0" -"react-router-dom@^5.2.0": - "integrity" "sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ==" - "resolved" "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.0.tgz" - "version" "5.3.0" +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" dependencies: - "@babel/runtime" "^7.12.13" - "history" "^4.9.0" - "loose-envify" "^1.3.1" - "prop-types" "^15.6.2" - "react-router" "5.2.1" - "tiny-invariant" "^1.0.2" - "tiny-warning" "^1.0.0" - -"react-router@^5.2.0", "react-router@>=5", "react-router@5.2.1": - "integrity" "sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==" - "resolved" "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz" - "version" "5.2.1" + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" dependencies: - "@babel/runtime" "^7.12.13" - "history" "^4.9.0" - "hoist-non-react-statics" "^3.1.0" - "loose-envify" "^1.3.1" - "mini-create-react-context" "^0.4.0" - "path-to-regexp" "^1.7.0" - "prop-types" "^15.6.2" - "react-is" "^16.6.0" - "tiny-invariant" "^1.0.2" - "tiny-warning" "^1.0.0" - -"react-side-effect@^2.1.0": - "integrity" "sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ==" - "resolved" "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.1.tgz" - "version" "2.1.1" - -"react-textarea-autosize@^8.3.2": - "integrity" "sha512-2XlHXK2TDxS6vbQaoPbMOfQ8GK7+irc2fVK6QFIcC8GOnH3zI/v481n+j1L0WaPVvKxwesnY93fEfH++sus2rQ==" - "resolved" "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz" - "version" "8.3.3" + locate-path "^6.0.0" + path-exists "^4.0.0" + +flux@^4.0.1: + version "4.0.3" + resolved "https://registry.npmjs.org/flux/-/flux-4.0.3.tgz" dependencies: - "@babel/runtime" "^7.10.2" - "use-composed-ref" "^1.0.0" - "use-latest" "^1.0.0" - -"react@*", "react@^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", "react@^15.0.2 || ^16.0.0 || ^17.0.0", "react@^16.10.2", "react@^16.13.1", "react@^16.13.1 || ^17.0.0", "react@^16.14.0", "react@^16.3.0 || ^17.0.0", "react@^16.3.1", "react@^16.8.0 || ^17.0.0", "react@^16.8.4 || ^17.0.0", "react@^17.0.0 || ^16.3.0 || ^15.5.4", "react@>= 16.8.0 < 18.0.0", "react@>=0.14.9", "react@>=15", "react@>=16.3.0": - "integrity" "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==" - "resolved" "https://registry.npmjs.org/react/-/react-16.14.0.tgz" - "version" "16.14.0" - dependencies: - "loose-envify" "^1.1.0" - "object-assign" "^4.1.1" - "prop-types" "^15.6.2" - -"readable-stream@^2.0.1": - "integrity" "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==" - "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz" - "version" "2.3.7" - dependencies: - "core-util-is" "~1.0.0" - "inherits" "~2.0.3" - "isarray" "~1.0.0" - "process-nextick-args" "~2.0.0" - "safe-buffer" "~5.1.1" - "string_decoder" "~1.1.1" - "util-deprecate" "~1.0.1" - -"readable-stream@^3.0.6", "readable-stream@^3.1.1": - "integrity" "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==" - "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz" - "version" "3.6.0" - dependencies: - "inherits" "^2.0.3" - "string_decoder" "^1.1.1" - "util-deprecate" "^1.0.1" - -"readdirp@~3.6.0": - "integrity" "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==" - "resolved" "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" - "version" "3.6.0" - dependencies: - "picomatch" "^2.2.1" - -"reading-time@^1.5.0": - "integrity" "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==" - "resolved" "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz" - "version" "1.5.0" - -"rechoir@^0.6.2": - "integrity" "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=" - "resolved" "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz" - "version" "0.6.2" - dependencies: - "resolve" "^1.1.6" - -"recursive-readdir@^2.2.2": - "integrity" "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==" - "resolved" "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz" - "version" "2.2.2" - dependencies: - "minimatch" "3.0.4" - -"regenerate-unicode-properties@^10.0.1": - "integrity" "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==" - "resolved" "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz" - "version" "10.0.1" - dependencies: - "regenerate" "^1.4.2" - -"regenerate-unicode-properties@^9.0.0": - "integrity" "sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==" - "resolved" "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz" - "version" "9.0.0" - dependencies: - "regenerate" "^1.4.2" - -"regenerate@^1.4.2": - "integrity" "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" - "resolved" "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" - "version" "1.4.2" - -"regenerator-runtime@^0.13.4": - "integrity" "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" - "resolved" "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz" - "version" "0.13.9" - -"regenerator-transform@^0.14.2": - "integrity" "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==" - "resolved" "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz" - "version" "0.14.5" + fbemitter "^3.0.0" + fbjs "^3.0.1" + +follow-redirects@^1.0.0, follow-redirects@^1.14.7: + version "1.14.9" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz" + +fork-ts-checker-webpack-plugin@^6.5.0: + version "6.5.0" + resolved "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz" dependencies: - "@babel/runtime" "^7.8.4" + "@babel/code-frame" "^7.8.3" + "@types/json-schema" "^7.0.5" + chalk "^4.1.0" + chokidar "^3.4.2" + cosmiconfig "^6.0.0" + deepmerge "^4.2.2" + fs-extra "^9.0.0" + glob "^7.1.6" + memfs "^3.1.2" + minimatch "^3.0.4" + schema-utils "2.7.0" + semver "^7.3.2" + tapable "^1.0.0" + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" + +fraction.js@^4.1.2: + version "4.1.3" + resolved "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.3.tgz" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" + +fs-extra@^10.0.0: + version "10.0.0" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz" + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" -"regexp.prototype.flags@^1.2.0": - "integrity" "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==" - "resolved" "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz" - "version" "1.4.1" - dependencies: - "call-bind" "^1.0.2" - "define-properties" "^1.1.3" - -"regexpu-core@^4.5.4": - "integrity" "sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg==" - "resolved" "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz" - "version" "4.8.0" - dependencies: - "regenerate" "^1.4.2" - "regenerate-unicode-properties" "^9.0.0" - "regjsgen" "^0.5.2" - "regjsparser" "^0.7.0" - "unicode-match-property-ecmascript" "^2.0.0" - "unicode-match-property-value-ecmascript" "^2.0.0" - -"regexpu-core@^5.0.1": - "integrity" "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==" - "resolved" "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz" - "version" "5.0.1" - dependencies: - "regenerate" "^1.4.2" - "regenerate-unicode-properties" "^10.0.1" - "regjsgen" "^0.6.0" - "regjsparser" "^0.8.2" - "unicode-match-property-ecmascript" "^2.0.0" - "unicode-match-property-value-ecmascript" "^2.0.0" - -"registry-auth-token@^4.0.0": - "integrity" "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==" - "resolved" "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz" - "version" "4.2.1" - dependencies: - "rc" "^1.2.8" - -"registry-url@^5.0.0": - "integrity" "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==" - "resolved" "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz" - "version" "5.1.0" - dependencies: - "rc" "^1.2.8" - -"regjsgen@^0.5.2": - "integrity" "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==" - "resolved" "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz" - "version" "0.5.2" - -"regjsgen@^0.6.0": - "integrity" "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==" - "resolved" "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz" - "version" "0.6.0" - -"regjsparser@^0.7.0": - "integrity" "sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ==" - "resolved" "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz" - "version" "0.7.0" - dependencies: - "jsesc" "~0.5.0" - -"regjsparser@^0.8.2": - "integrity" "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==" - "resolved" "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz" - "version" "0.8.4" - dependencies: - "jsesc" "~0.5.0" - -"rehype-parse@^6.0.2": - "integrity" "sha512-0S3CpvpTAgGmnz8kiCyFLGuW5yA4OQhyNTm/nwPopZ7+PI11WnGl1TTWTGv/2hPEe/g2jRLlhVVSsoDH8waRug==" - "resolved" "https://registry.npmjs.org/rehype-parse/-/rehype-parse-6.0.2.tgz" - "version" "6.0.2" - dependencies: - "hast-util-from-parse5" "^5.0.0" - "parse5" "^5.0.0" - "xtend" "^4.0.0" - -"relateurl@^0.2.7": - "integrity" "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=" - "resolved" "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz" - "version" "0.2.7" - -"remark-admonitions@^1.2.1": - "integrity" "sha512-Ji6p68VDvD+H1oS95Fdx9Ar5WA2wcDA4kwrrhVU7fGctC6+d3uiMICu7w7/2Xld+lnU7/gi+432+rRbup5S8ow==" - "resolved" "https://registry.npmjs.org/remark-admonitions/-/remark-admonitions-1.2.1.tgz" - "version" "1.2.1" - dependencies: - "rehype-parse" "^6.0.2" - "unified" "^8.4.2" - "unist-util-visit" "^2.0.1" - -"remark-emoji@^2.1.0": - "integrity" "sha512-P3cj9s5ggsUvWw5fS2uzCHJMGuXYRb0NnZqYlNecewXt8QBU9n5vW3DUUKOhepS8F9CwdMx9B8a3i7pqFWAI5w==" - "resolved" "https://registry.npmjs.org/remark-emoji/-/remark-emoji-2.2.0.tgz" - "version" "2.2.0" - dependencies: - "emoticon" "^3.2.0" - "node-emoji" "^1.10.0" - "unist-util-visit" "^2.0.3" - -"remark-footnotes@2.0.0": - "integrity" "sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ==" - "resolved" "https://registry.npmjs.org/remark-footnotes/-/remark-footnotes-2.0.0.tgz" - "version" "2.0.0" - -"remark-mdx-remove-exports@^1.6.22": - "integrity" "sha512-7g2uiTmTGfz5QyVb+toeX25frbk1Y6yd03RXGPtqx0+DVh86Gb7MkNYbk7H2X27zdZ3CQv1W/JqlFO0Oo8IxVA==" - "resolved" "https://registry.npmjs.org/remark-mdx-remove-exports/-/remark-mdx-remove-exports-1.6.22.tgz" - "version" "1.6.22" - dependencies: - "unist-util-remove" "2.0.0" - -"remark-mdx-remove-imports@^1.6.22": - "integrity" "sha512-lmjAXD8Ltw0TsvBzb45S+Dxx7LTJAtDaMneMAv8LAUIPEyYoKkmGbmVsiF0/pY6mhM1Q16swCmu1TN+ie/vn/A==" - "resolved" "https://registry.npmjs.org/remark-mdx-remove-imports/-/remark-mdx-remove-imports-1.6.22.tgz" - "version" "1.6.22" - dependencies: - "unist-util-remove" "2.0.0" - -"remark-mdx@1.6.22": - "integrity" "sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ==" - "resolved" "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz" - "version" "1.6.22" +fs-extra@^9.0.0: + version "9.1.0" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz" dependencies: - "@babel/core" "7.12.9" - "@babel/helper-plugin-utils" "7.10.4" - "@babel/plugin-proposal-object-rest-spread" "7.12.1" - "@babel/plugin-syntax-jsx" "7.12.1" - "@mdx-js/util" "1.6.22" - "is-alphabetical" "1.0.4" - "remark-parse" "8.0.3" - "unified" "9.2.0" - -"remark-parse@8.0.3": - "integrity" "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==" - "resolved" "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz" - "version" "8.0.3" - dependencies: - "ccount" "^1.0.0" - "collapse-white-space" "^1.0.2" - "is-alphabetical" "^1.0.0" - "is-decimal" "^1.0.0" - "is-whitespace-character" "^1.0.0" - "is-word-character" "^1.0.0" - "markdown-escapes" "^1.0.0" - "parse-entities" "^2.0.0" - "repeat-string" "^1.5.4" - "state-toggle" "^1.0.0" - "trim" "0.0.1" - "trim-trailing-lines" "^1.0.0" - "unherit" "^1.0.4" - "unist-util-remove-position" "^2.0.0" - "vfile-location" "^3.0.0" - "xtend" "^4.0.1" - -"remark-squeeze-paragraphs@4.0.0": - "integrity" "sha512-8qRqmL9F4nuLPIgl92XUuxI3pFxize+F1H0e/W3llTk0UsjJaj01+RrirkMw7P21RKe4X6goQhYRSvNWX+70Rw==" - "resolved" "https://registry.npmjs.org/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz" - "version" "4.0.0" - dependencies: - "mdast-squeeze-paragraphs" "^4.0.0" - -"remarkable-admonitions@^0.2.1": - "integrity" "sha512-CcMTEcLYmJLXX3IVMk4LyW4oFD2NQxh5FeLzn4k89TAPpyWIeVix/B/g/gDbZAUpCNY9l6heovR5NNIktf8X5A==" - "resolved" "https://registry.npmjs.org/remarkable-admonitions/-/remarkable-admonitions-0.2.2.tgz" - "version" "0.2.2" - -"renderkid@^3.0.0": - "integrity" "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==" - "resolved" "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz" - "version" "3.0.0" - dependencies: - "css-select" "^4.1.3" - "dom-converter" "^0.2.0" - "htmlparser2" "^6.1.0" - "lodash" "^4.17.21" - "strip-ansi" "^6.0.1" - -"repeat-string@^1.5.4": - "integrity" "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" - "resolved" "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" - "version" "1.6.1" - -"require-from-string@^2.0.2": - "integrity" "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" - "resolved" "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" - "version" "2.0.2" + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" -"require-like@>= 0.1.1": - "integrity" "sha1-rW8wwTvs15cBDEaK+ndcDAprR/o=" - "resolved" "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz" - "version" "0.1.2" - -"requires-port@^1.0.0": - "integrity" "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" - "resolved" "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" - "version" "1.0.0" - -"resolve-from@^4.0.0": - "integrity" "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" - "resolved" "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" - "version" "4.0.0" - -"resolve-pathname@^3.0.0": - "integrity" "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" - "resolved" "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz" - "version" "3.0.0" - -"resolve@^1.1.6", "resolve@^1.14.2", "resolve@^1.3.2": - "integrity" "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==" - "resolved" "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz" - "version" "1.22.0" - dependencies: - "is-core-module" "^2.8.1" - "path-parse" "^1.0.7" - "supports-preserve-symlinks-flag" "^1.0.0" - -"responselike@^1.0.2": - "integrity" "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=" - "resolved" "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz" - "version" "1.0.2" - dependencies: - "lowercase-keys" "^1.0.0" - -"retry@^0.13.1": - "integrity" "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" - "resolved" "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz" - "version" "0.13.1" - -"reusify@^1.0.4": - "integrity" "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" - "resolved" "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" - "version" "1.0.4" - -"rimraf@^3.0.2": - "integrity" "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==" - "resolved" "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" - "version" "3.0.2" - dependencies: - "glob" "^7.1.3" - -"rtl-detect@^1.0.4": - "integrity" "sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ==" - "resolved" "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.0.4.tgz" - "version" "1.0.4" - -"rtlcss@^3.3.0": - "integrity" "sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A==" - "resolved" "https://registry.npmjs.org/rtlcss/-/rtlcss-3.5.0.tgz" - "version" "3.5.0" - dependencies: - "find-up" "^5.0.0" - "picocolors" "^1.0.0" - "postcss" "^8.3.11" - "strip-json-comments" "^3.1.1" - -"run-parallel@^1.1.9": - "integrity" "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==" - "resolved" "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" - "version" "1.2.0" - dependencies: - "queue-microtask" "^1.2.2" - -"rxjs@^7.5.4": - "integrity" "sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ==" - "resolved" "https://registry.npmjs.org/rxjs/-/rxjs-7.5.4.tgz" - "version" "7.5.4" - dependencies: - "tslib" "^2.1.0" - -"safe-buffer@^5.0.1", "safe-buffer@^5.1.0", "safe-buffer@>=5.1.0", "safe-buffer@~5.2.0", "safe-buffer@5.2.1": - "integrity" "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" - "version" "5.2.1" - -"safe-buffer@~5.1.0", "safe-buffer@~5.1.1": - "integrity" "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" - "version" "5.1.2" - -"safe-buffer@5.1.2": - "integrity" "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" - "version" "5.1.2" +fs-monkey@1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz" -"safer-buffer@>= 2.1.2 < 3": - "integrity" "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - "resolved" "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" - "version" "2.1.2" +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" -"sax@^1.2.4": - "integrity" "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - "resolved" "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz" - "version" "1.2.4" +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" + +gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" + +get-intrinsic@^1.0.2: + version "1.1.1" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz" + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + +get-own-enumerable-property-symbols@^3.0.0: + version "3.0.2" + resolved "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz" + +get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz" + dependencies: + pump "^3.0.0" + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz" + dependencies: + pump "^3.0.0" + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz" + +github-slugger@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/github-slugger/-/github-slugger-1.4.0.tgz" + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.1: + version "6.0.2" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" + dependencies: + is-glob "^4.0.3" -"scheduler@^0.19.1": - "integrity" "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==" - "resolved" "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz" - "version" "0.19.1" - dependencies: - "loose-envify" "^1.1.0" - "object-assign" "^4.1.1" +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz" -"schema-utils@^2.6.5": - "integrity" "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==" - "resolved" "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz" - "version" "2.7.1" +glob@^7.0.0, glob@^7.1.3, glob@^7.1.6: + version "7.2.0" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz" dependencies: - "@types/json-schema" "^7.0.5" - "ajv" "^6.12.4" - "ajv-keywords" "^3.5.2" + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" -"schema-utils@^3.0.0", "schema-utils@^3.1.0", "schema-utils@^3.1.1": - "integrity" "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==" - "resolved" "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz" - "version" "3.1.1" +global-dirs@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz" dependencies: - "@types/json-schema" "^7.0.8" - "ajv" "^6.12.5" - "ajv-keywords" "^3.5.2" + ini "2.0.0" -"schema-utils@^4.0.0": - "integrity" "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==" - "resolved" "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz" - "version" "4.0.0" +global-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz" dependencies: - "@types/json-schema" "^7.0.9" - "ajv" "^8.8.0" - "ajv-formats" "^2.1.1" - "ajv-keywords" "^5.0.0" + global-prefix "^3.0.0" -"schema-utils@2.7.0": - "integrity" "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==" - "resolved" "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz" - "version" "2.7.0" +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz" dependencies: - "@types/json-schema" "^7.0.4" - "ajv" "^6.12.2" - "ajv-keywords" "^3.4.1" - -"section-matter@^1.0.0": - "integrity" "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==" - "resolved" "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz" - "version" "1.0.0" - dependencies: - "extend-shallow" "^2.0.1" - "kind-of" "^6.0.0" - -"select-hose@^2.0.0": - "integrity" "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" - "resolved" "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" - "version" "2.0.0" - -"selfsigned@^2.0.0": - "integrity" "sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ==" - "resolved" "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "node-forge" "^1.2.0" - -"semver-diff@^3.1.1": - "integrity" "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==" - "resolved" "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz" - "version" "3.1.1" - dependencies: - "semver" "^6.3.0" - -"semver@^5.4.1": - "integrity" "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - "resolved" "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" - "version" "5.7.1" - -"semver@^6.0.0", "semver@^6.1.1", "semver@^6.1.2", "semver@^6.2.0", "semver@^6.3.0": - "integrity" "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - "resolved" "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" - "version" "6.3.0" - -"semver@^7.3.2": - "integrity" "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==" - "resolved" "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" - "version" "7.3.5" - dependencies: - "lru-cache" "^6.0.0" - -"semver@^7.3.4": - "integrity" "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==" - "resolved" "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" - "version" "7.3.5" - dependencies: - "lru-cache" "^6.0.0" - -"semver@^7.3.5": - "integrity" "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==" - "resolved" "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" - "version" "7.3.5" - dependencies: - "lru-cache" "^6.0.0" - -"semver@7.0.0": - "integrity" "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" - "resolved" "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz" - "version" "7.0.0" - -"send@0.17.2": - "integrity" "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==" - "resolved" "https://registry.npmjs.org/send/-/send-0.17.2.tgz" - "version" "0.17.2" - dependencies: - "debug" "2.6.9" - "depd" "~1.1.2" - "destroy" "~1.0.4" - "encodeurl" "~1.0.2" - "escape-html" "~1.0.3" - "etag" "~1.8.1" - "fresh" "0.5.2" - "http-errors" "1.8.1" - "mime" "1.6.0" - "ms" "2.1.3" - "on-finished" "~2.3.0" - "range-parser" "~1.2.1" - "statuses" "~1.5.0" - -"serialize-javascript@^6.0.0": - "integrity" "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==" - "resolved" "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz" - "version" "6.0.0" - dependencies: - "randombytes" "^2.1.0" - -"serve-handler@^6.1.3": - "integrity" "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==" - "resolved" "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz" - "version" "6.1.3" - dependencies: - "bytes" "3.0.0" - "content-disposition" "0.5.2" - "fast-url-parser" "1.1.3" - "mime-types" "2.1.18" - "minimatch" "3.0.4" - "path-is-inside" "1.0.2" - "path-to-regexp" "2.2.1" - "range-parser" "1.2.0" - -"serve-index@^1.9.1": - "integrity" "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=" - "resolved" "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz" - "version" "1.9.1" - dependencies: - "accepts" "~1.3.4" - "batch" "0.6.1" - "debug" "2.6.9" - "escape-html" "~1.0.3" - "http-errors" "~1.6.2" - "mime-types" "~2.1.17" - "parseurl" "~1.3.2" - -"serve-static@1.14.2": - "integrity" "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==" - "resolved" "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz" - "version" "1.14.2" - dependencies: - "encodeurl" "~1.0.2" - "escape-html" "~1.0.3" - "parseurl" "~1.3.3" - "send" "0.17.2" - -"setimmediate@^1.0.5": - "integrity" "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" - "resolved" "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" - "version" "1.0.5" - -"setprototypeof@1.1.0": - "integrity" "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" - "resolved" "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz" - "version" "1.1.0" - -"setprototypeof@1.2.0": - "integrity" "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - "resolved" "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" - "version" "1.2.0" - -"shallow-clone@^3.0.0": - "integrity" "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==" - "resolved" "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz" - "version" "3.0.1" - dependencies: - "kind-of" "^6.0.2" - -"shebang-command@^2.0.0": - "integrity" "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==" - "resolved" "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "shebang-regex" "^3.0.0" - -"shebang-regex@^3.0.0": - "integrity" "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - "resolved" "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" - "version" "3.0.0" - -"shell-quote@^1.7.3": - "integrity" "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==" - "resolved" "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz" - "version" "1.7.3" - -"shelljs@^0.8.4": - "integrity" "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==" - "resolved" "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz" - "version" "0.8.5" - dependencies: - "glob" "^7.0.0" - "interpret" "^1.0.0" - "rechoir" "^0.6.2" - -"signal-exit@^3.0.2", "signal-exit@^3.0.3": - "integrity" "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - "resolved" "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" - "version" "3.0.7" - -"sirv@^1.0.7": - "integrity" "sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==" - "resolved" "https://registry.npmjs.org/sirv/-/sirv-1.0.19.tgz" - "version" "1.0.19" + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" + +globby@^11.0.1, globby@^11.0.2, globby@^11.0.4: + version "11.1.0" + resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" dependencies: - "@polka/url" "^1.0.0-next.20" - "mrmime" "^1.0.0" - "totalist" "^1.0.0" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" -"sisteransi@^1.0.5": - "integrity" "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" - "resolved" "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" - "version" "1.0.5" +globby@^12.0.2: + version "12.2.0" + resolved "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz" + dependencies: + array-union "^3.0.1" + dir-glob "^3.0.1" + fast-glob "^3.2.7" + ignore "^5.1.9" + merge2 "^1.4.1" + slash "^4.0.0" -"sitemap@^7.0.0": - "integrity" "sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg==" - "resolved" "https://registry.npmjs.org/sitemap/-/sitemap-7.1.1.tgz" - "version" "7.1.1" +got@^9.6.0: + version "9.6.0" + resolved "https://registry.npmjs.org/got/-/got-9.6.0.tgz" dependencies: - "@types/node" "^17.0.5" - "@types/sax" "^1.2.1" - "arg" "^5.0.0" - "sax" "^1.2.4" - -"slash@^3.0.0": - "integrity" "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" - "resolved" "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" - "version" "3.0.0" - -"slash@^4.0.0": - "integrity" "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==" - "resolved" "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz" - "version" "4.0.0" - -"sockjs@^0.3.21": - "integrity" "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==" - "resolved" "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz" - "version" "0.3.24" - dependencies: - "faye-websocket" "^0.11.3" - "uuid" "^8.3.2" - "websocket-driver" "^0.7.4" - -"sort-css-media-queries@2.0.4": - "integrity" "sha512-PAIsEK/XupCQwitjv7XxoMvYhT7EAfyzI3hsy/MyDgTvc+Ft55ctdkctJLOy6cQejaIC+zjpUL4djFVm2ivOOw==" - "resolved" "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.0.4.tgz" - "version" "2.0.4" - -"source-list-map@^2.0.0": - "integrity" "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" - "resolved" "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz" - "version" "2.0.1" - -"source-map-js@^1.0.2": - "integrity" "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" - "resolved" "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz" - "version" "1.0.2" - -"source-map-support@~0.5.20": - "integrity" "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==" - "resolved" "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" - "version" "0.5.21" - dependencies: - "buffer-from" "^1.0.0" - "source-map" "^0.6.0" - -"source-map@^0.5.0": - "integrity" "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - "resolved" "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" - "version" "0.5.7" - -"source-map@^0.6.0", "source-map@^0.6.1", "source-map@~0.6.0", "source-map@~0.6.1": - "integrity" "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - "resolved" "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" - "version" "0.6.1" - -"sourcemap-codec@^1.4.4": - "integrity" "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" - "resolved" "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz" - "version" "1.4.8" - -"space-separated-tokens@^1.0.0": - "integrity" "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==" - "resolved" "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz" - "version" "1.1.5" - -"spdy-transport@^3.0.0": - "integrity" "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==" - "resolved" "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz" - "version" "3.0.0" - dependencies: - "debug" "^4.1.0" - "detect-node" "^2.0.4" - "hpack.js" "^2.1.6" - "obuf" "^1.1.2" - "readable-stream" "^3.0.6" - "wbuf" "^1.7.3" - -"spdy@^4.0.2": - "integrity" "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==" - "resolved" "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz" - "version" "4.0.2" - dependencies: - "debug" "^4.1.0" - "handle-thing" "^2.0.0" - "http-deceiver" "^1.2.7" - "select-hose" "^2.0.0" - "spdy-transport" "^3.0.0" - -"sprintf-js@~1.0.2": - "integrity" "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - "resolved" "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" - "version" "1.0.3" - -"stable@^0.1.8": - "integrity" "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" - "resolved" "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz" - "version" "0.1.8" - -"state-toggle@^1.0.0": - "integrity" "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==" - "resolved" "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz" - "version" "1.0.3" - -"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", "statuses@~1.5.0": - "integrity" "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - "resolved" "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" - "version" "1.5.0" - -"std-env@^3.0.1": - "integrity" "sha512-mC1Ps9l77/97qeOZc+HrOL7TIaOboHqMZ24dGVQrlxFcpPpfCHpH+qfUT7Dz+6mlG8+JPA1KfBQo19iC/+Ngcw==" - "resolved" "https://registry.npmjs.org/std-env/-/std-env-3.0.1.tgz" - "version" "3.0.1" - -"string_decoder@^1.1.1": - "integrity" "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==" - "resolved" "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" - "version" "1.3.0" - dependencies: - "safe-buffer" "~5.2.0" - -"string_decoder@~1.1.1": - "integrity" "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==" - "resolved" "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" - "version" "1.1.1" - dependencies: - "safe-buffer" "~5.1.0" - -"string-width@^4.0.0", "string-width@^4.1.0", "string-width@^4.2.2": - "integrity" "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==" - "resolved" "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" - "version" "4.2.3" - dependencies: - "emoji-regex" "^8.0.0" - "is-fullwidth-code-point" "^3.0.0" - "strip-ansi" "^6.0.1" - -"stringify-object@^3.3.0": - "integrity" "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==" - "resolved" "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz" - "version" "3.3.0" - dependencies: - "get-own-enumerable-property-symbols" "^3.0.0" - "is-obj" "^1.0.1" - "is-regexp" "^1.0.0" - -"strip-ansi@^6.0.0", "strip-ansi@^6.0.1": - "integrity" "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==" - "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" - "version" "6.0.1" - dependencies: - "ansi-regex" "^5.0.1" - -"strip-ansi@^7.0.0": - "integrity" "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==" - "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz" - "version" "7.0.1" - dependencies: - "ansi-regex" "^6.0.1" - -"strip-bom-string@^1.0.0": - "integrity" "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=" - "resolved" "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz" - "version" "1.0.0" - -"strip-final-newline@^2.0.0": - "integrity" "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" - "resolved" "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz" - "version" "2.0.0" - -"strip-json-comments@^3.1.1": - "integrity" "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" - "resolved" "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" - "version" "3.1.1" - -"strip-json-comments@~2.0.1": - "integrity" "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - "resolved" "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" - "version" "2.0.1" - -"style-to-object@^0.3.0", "style-to-object@0.3.0": - "integrity" "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==" - "resolved" "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz" - "version" "0.3.0" - dependencies: - "inline-style-parser" "0.1.1" - -"stylehacks@^5.0.3": - "integrity" "sha512-ENcUdpf4yO0E1rubu8rkxI+JGQk4CgjchynZ4bDBJDfqdy+uhTRSWb8/F3Jtu+Bw5MW45Po3/aQGeIyyxgQtxg==" - "resolved" "https://registry.npmjs.org/stylehacks/-/stylehacks-5.0.3.tgz" - "version" "5.0.3" - dependencies: - "browserslist" "^4.16.6" - "postcss-selector-parser" "^6.0.4" - -"supports-color@^5.3.0": - "integrity" "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==" - "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" - "version" "5.5.0" - dependencies: - "has-flag" "^3.0.0" + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" -"supports-color@^7.1.0": - "integrity" "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==" - "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" - "version" "7.2.0" +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: + version "4.2.9" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz" + +gray-matter@^4.0.3: + version "4.0.3" + resolved "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz" dependencies: - "has-flag" "^4.0.0" + js-yaml "^3.13.1" + kind-of "^6.0.2" + section-matter "^1.0.0" + strip-bom-string "^1.0.0" -"supports-color@^8.0.0": - "integrity" "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==" - "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" - "version" "8.1.1" +gzip-size@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz" dependencies: - "has-flag" "^4.0.0" + duplexer "^0.1.2" + +handle-thing@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz" -"supports-preserve-symlinks-flag@^1.0.0": - "integrity" "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" - "resolved" "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" - "version" "1.0.0" +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" -"svg-parser@^2.0.2": - "integrity" "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" - "resolved" "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz" - "version" "2.0.4" +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" -"svgo@^2.5.0", "svgo@^2.7.0": - "integrity" "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==" - "resolved" "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz" - "version" "2.8.0" +has-symbols@^1.0.1, has-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz" + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz" dependencies: - "@trysound/sax" "0.2.0" - "commander" "^7.2.0" - "css-select" "^4.1.3" - "css-tree" "^1.1.3" - "csso" "^4.2.0" - "picocolors" "^1.0.0" - "stable" "^0.1.8" - -"tapable@^1.0.0": - "integrity" "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" - "resolved" "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz" - "version" "1.1.3" - -"tapable@^2.0.0", "tapable@^2.1.1", "tapable@^2.2.0": - "integrity" "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" - "resolved" "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz" - "version" "2.2.1" - -"terser-webpack-plugin@^5.1.3", "terser-webpack-plugin@^5.2.4": - "integrity" "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==" - "resolved" "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz" - "version" "5.3.1" - dependencies: - "jest-worker" "^27.4.5" - "schema-utils" "^3.1.1" - "serialize-javascript" "^6.0.0" - "source-map" "^0.6.1" - "terser" "^5.7.2" - -"terser@^5.10.0", "terser@^5.7.2": - "integrity" "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==" - "resolved" "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz" - "version" "5.14.2" + has-symbols "^1.0.2" + +has-yarn@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz" + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" dependencies: - "@jridgewell/source-map" "^0.3.2" - "acorn" "^8.5.0" - "commander" "^2.20.0" - "source-map-support" "~0.5.20" - -"text-table@^0.2.0": - "integrity" "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" - "resolved" "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" - "version" "0.2.0" - -"thunky@^1.0.2": - "integrity" "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" - "resolved" "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz" - "version" "1.1.0" - -"timsort@^0.3.0": - "integrity" "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" - "resolved" "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz" - "version" "0.3.0" - -"tiny-invariant@^1.0.2": - "integrity" "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==" - "resolved" "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz" - "version" "1.2.0" - -"tiny-warning@^1.0.0", "tiny-warning@^1.0.3": - "integrity" "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" - "resolved" "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz" - "version" "1.0.3" - -"to-fast-properties@^2.0.0": - "integrity" "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" - "resolved" "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" - "version" "2.0.0" - -"to-readable-stream@^1.0.0": - "integrity" "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" - "resolved" "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz" - "version" "1.0.0" - -"to-regex-range@^5.0.1": - "integrity" "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==" - "resolved" "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" - "version" "5.0.1" - dependencies: - "is-number" "^7.0.0" - -"toidentifier@1.0.1": - "integrity" "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" - "resolved" "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" - "version" "1.0.1" - -"totalist@^1.0.0": - "integrity" "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==" - "resolved" "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz" - "version" "1.1.0" - -"tr46@~0.0.3": - "integrity" "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" - "resolved" "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" - "version" "0.0.3" - -"trim-trailing-lines@^1.0.0": - "integrity" "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==" - "resolved" "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz" - "version" "1.1.4" - -"trim@0.0.1": - "integrity" "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" - "resolved" "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz" - "version" "0.0.1" - -"trough@^1.0.0": - "integrity" "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==" - "resolved" "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz" - "version" "1.0.5" - -"tslib@^2.0.3", "tslib@^2.1.0", "tslib@^2.2.0", "tslib@^2.3.1": - "integrity" "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - "resolved" "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz" - "version" "2.3.1" - -"type-fest@^0.20.2": - "integrity" "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" - "resolved" "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" - "version" "0.20.2" - -"type-is@~1.6.18": - "integrity" "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==" - "resolved" "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" - "version" "1.6.18" - dependencies: - "media-typer" "0.3.0" - "mime-types" "~2.1.24" - -"typedarray-to-buffer@^3.1.5": - "integrity" "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==" - "resolved" "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz" - "version" "3.1.5" - dependencies: - "is-typedarray" "^1.0.0" - -"typescript@>= 2.7": - "integrity" "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==" - "resolved" "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz" - "version" "4.9.5" - -"ua-parser-js@^0.7.30": - "integrity" "sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw==" - "resolved" "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.33.tgz" - "version" "0.7.33" - -"unherit@^1.0.4": - "integrity" "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==" - "resolved" "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz" - "version" "1.1.3" - dependencies: - "inherits" "^2.0.0" - "xtend" "^4.0.0" - -"unicode-canonical-property-names-ecmascript@^2.0.0": - "integrity" "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==" - "resolved" "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz" - "version" "2.0.0" - -"unicode-match-property-ecmascript@^2.0.0": - "integrity" "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==" - "resolved" "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "unicode-canonical-property-names-ecmascript" "^2.0.0" - "unicode-property-aliases-ecmascript" "^2.0.0" - -"unicode-match-property-value-ecmascript@^2.0.0": - "integrity" "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==" - "resolved" "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz" - "version" "2.0.0" - -"unicode-property-aliases-ecmascript@^2.0.0": - "integrity" "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==" - "resolved" "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz" - "version" "2.0.0" - -"unified@^8.4.2": - "integrity" "sha512-JCrmN13jI4+h9UAyKEoGcDZV+i1E7BLFuG7OsaDvTXI5P0qhHX+vZO/kOhz9jn8HGENDKbwSeB0nVOg4gVStGA==" - "resolved" "https://registry.npmjs.org/unified/-/unified-8.4.2.tgz" - "version" "8.4.2" - dependencies: - "bail" "^1.0.0" - "extend" "^3.0.0" - "is-plain-obj" "^2.0.0" - "trough" "^1.0.0" - "vfile" "^4.0.0" - -"unified@9.2.0": - "integrity" "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==" - "resolved" "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz" - "version" "9.2.0" - dependencies: - "bail" "^1.0.0" - "extend" "^3.0.0" - "is-buffer" "^2.0.0" - "is-plain-obj" "^2.0.0" - "trough" "^1.0.0" - "vfile" "^4.0.0" - -"unique-string@^2.0.0": - "integrity" "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==" - "resolved" "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "crypto-random-string" "^2.0.0" - -"unist-builder@^2.0.0", "unist-builder@2.0.3": - "integrity" "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==" - "resolved" "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz" - "version" "2.0.3" - -"unist-util-generated@^1.0.0": - "integrity" "sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==" - "resolved" "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz" - "version" "1.1.6" - -"unist-util-is@^4.0.0": - "integrity" "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==" - "resolved" "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz" - "version" "4.1.0" - -"unist-util-position@^3.0.0": - "integrity" "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA==" - "resolved" "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz" - "version" "3.1.0" - -"unist-util-remove-position@^2.0.0": - "integrity" "sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA==" - "resolved" "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz" - "version" "2.0.1" - dependencies: - "unist-util-visit" "^2.0.0" - -"unist-util-remove@^2.0.0": - "integrity" "sha512-J8NYPyBm4baYLdCbjmf1bhPu45Cr1MWTm77qd9istEkzWpnN6O9tMsEbB2JhNnBCqGENRqEWomQ+He6au0B27Q==" - "resolved" "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.1.0.tgz" - "version" "2.1.0" - dependencies: - "unist-util-is" "^4.0.0" - -"unist-util-remove@2.0.0": - "integrity" "sha512-HwwWyNHKkeg/eXRnE11IpzY8JT55JNM1YCwwU9YNCnfzk6s8GhPXrVBBZWiwLeATJbI7euvoGSzcy9M29UeW3g==" - "resolved" "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "unist-util-is" "^4.0.0" - -"unist-util-stringify-position@^2.0.0": - "integrity" "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==" - "resolved" "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz" - "version" "2.0.3" + function-bind "^1.1.1" + +hast-to-hyperscript@^9.0.0: + version "9.0.1" + resolved "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz" dependencies: - "@types/unist" "^2.0.2" + "@types/unist" "^2.0.3" + comma-separated-tokens "^1.0.0" + property-information "^5.3.0" + space-separated-tokens "^1.0.0" + style-to-object "^0.3.0" + unist-util-is "^4.0.0" + web-namespaces "^1.0.0" + +hast-util-from-parse5@^5.0.0: + version "5.0.3" + resolved "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-5.0.3.tgz" + dependencies: + ccount "^1.0.3" + hastscript "^5.0.0" + property-information "^5.0.0" + web-namespaces "^1.1.2" + xtend "^4.0.1" + +hast-util-from-parse5@^6.0.0: + version "6.0.1" + resolved "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz" + dependencies: + "@types/parse5" "^5.0.0" + hastscript "^6.0.0" + property-information "^5.0.0" + vfile "^4.0.0" + vfile-location "^3.2.0" + web-namespaces "^1.0.0" -"unist-util-visit-parents@^3.0.0": - "integrity" "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==" - "resolved" "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz" - "version" "3.1.1" +hast-util-parse-selector@^2.0.0: + version "2.2.5" + resolved "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz" + +hast-util-raw@6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-6.0.1.tgz" dependencies: - "@types/unist" "^2.0.0" - "unist-util-is" "^4.0.0" + "@types/hast" "^2.0.0" + hast-util-from-parse5 "^6.0.0" + hast-util-to-parse5 "^6.0.0" + html-void-elements "^1.0.0" + parse5 "^6.0.0" + unist-util-position "^3.0.0" + vfile "^4.0.0" + web-namespaces "^1.0.0" + xtend "^4.0.0" + zwitch "^1.0.0" + +hast-util-to-parse5@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz" + dependencies: + hast-to-hyperscript "^9.0.0" + property-information "^5.0.0" + web-namespaces "^1.0.0" + xtend "^4.0.0" + zwitch "^1.0.0" + +hastscript@^5.0.0: + version "5.1.2" + resolved "https://registry.npmjs.org/hastscript/-/hastscript-5.1.2.tgz" + dependencies: + comma-separated-tokens "^1.0.0" + hast-util-parse-selector "^2.0.0" + property-information "^5.0.0" + space-separated-tokens "^1.0.0" + +hastscript@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz" + dependencies: + "@types/hast" "^2.0.0" + comma-separated-tokens "^1.0.0" + hast-util-parse-selector "^2.0.0" + property-information "^5.0.0" + space-separated-tokens "^1.0.0" + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz" -"unist-util-visit@^2.0.0", "unist-util-visit@^2.0.1", "unist-util-visit@^2.0.2", "unist-util-visit@^2.0.3", "unist-util-visit@2.0.3": - "integrity" "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==" - "resolved" "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz" - "version" "2.0.3" +history@^4.9.0: + version "4.10.1" + resolved "https://registry.npmjs.org/history/-/history-4.10.1.tgz" dependencies: - "@types/unist" "^2.0.0" - "unist-util-is" "^4.0.0" - "unist-util-visit-parents" "^3.0.0" - -"universalify@^2.0.0": - "integrity" "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" - "resolved" "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz" - "version" "2.0.0" - -"unpipe@~1.0.0", "unpipe@1.0.0": - "integrity" "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - "resolved" "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" - "version" "1.0.0" - -"update-browserslist-db@^1.0.10": - "integrity" "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==" - "resolved" "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz" - "version" "1.0.10" - dependencies: - "escalade" "^3.1.1" - "picocolors" "^1.0.0" - -"update-notifier@^5.1.0": - "integrity" "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==" - "resolved" "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz" - "version" "5.1.0" - dependencies: - "boxen" "^5.0.0" - "chalk" "^4.1.0" - "configstore" "^5.0.1" - "has-yarn" "^2.1.0" - "import-lazy" "^2.1.0" - "is-ci" "^2.0.0" - "is-installed-globally" "^0.4.0" - "is-npm" "^5.0.0" - "is-yarn-global" "^0.3.0" - "latest-version" "^5.1.0" - "pupa" "^2.1.1" - "semver" "^7.3.4" - "semver-diff" "^3.1.1" - "xdg-basedir" "^4.0.0" - -"uri-js@^4.2.2": - "integrity" "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==" - "resolved" "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" - "version" "4.4.1" - dependencies: - "punycode" "^2.1.0" - -"url-loader@^4.1.1": - "integrity" "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==" - "resolved" "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz" - "version" "4.1.1" - dependencies: - "loader-utils" "^2.0.0" - "mime-types" "^2.1.27" - "schema-utils" "^3.0.0" - -"url-parse-lax@^3.0.0": - "integrity" "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=" - "resolved" "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz" - "version" "3.0.0" - dependencies: - "prepend-http" "^2.0.0" - -"url@^0.11.0": - "integrity" "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=" - "resolved" "https://registry.npmjs.org/url/-/url-0.11.0.tgz" - "version" "0.11.0" - dependencies: - "punycode" "1.3.2" - "querystring" "0.2.0" - -"use-composed-ref@^1.0.0": - "integrity" "sha512-6+X1FLlIcjvFMAeAD/hcxDT8tmyrWnbSPMU0EnxQuDLIxokuFzWliXBiYZuGIx+mrAMLBw0WFfCkaPw8ebzAhw==" - "resolved" "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.2.1.tgz" - "version" "1.2.1" - -"use-isomorphic-layout-effect@^1.0.0": - "integrity" "sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ==" - "resolved" "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz" - "version" "1.1.1" - -"use-latest@^1.0.0": - "integrity" "sha512-d2TEuG6nSLKQLAfW3By8mKr8HurOlTkul0sOpxbClIv4SQ4iOd7BYr7VIzdbktUCnv7dua/60xzd8igMU6jmyw==" - "resolved" "https://registry.npmjs.org/use-latest/-/use-latest-1.2.0.tgz" - "version" "1.2.0" - dependencies: - "use-isomorphic-layout-effect" "^1.0.0" - -"util-deprecate@^1.0.1", "util-deprecate@^1.0.2", "util-deprecate@~1.0.1": - "integrity" "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - "resolved" "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - "version" "1.0.2" - -"utila@~0.4": - "integrity" "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=" - "resolved" "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz" - "version" "0.4.0" - -"utility-types@^3.10.0": - "integrity" "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==" - "resolved" "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz" - "version" "3.10.0" - -"utils-merge@1.0.1": - "integrity" "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - "resolved" "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" - "version" "1.0.1" - -"uuid@^8.3.2": - "integrity" "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - "resolved" "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" - "version" "8.3.2" - -"value-equal@^1.0.1": - "integrity" "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" - "resolved" "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz" - "version" "1.0.1" - -"vary@~1.1.2": - "integrity" "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - "resolved" "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" - "version" "1.1.2" - -"vfile-location@^3.0.0", "vfile-location@^3.2.0": - "integrity" "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==" - "resolved" "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz" - "version" "3.2.0" - -"vfile-message@^2.0.0": - "integrity" "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==" - "resolved" "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz" - "version" "2.0.4" + "@babel/runtime" "^7.1.2" + loose-envify "^1.2.0" + resolve-pathname "^3.0.0" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + value-equal "^1.0.1" + +hoist-non-react-statics@^3.1.0: + version "3.3.2" + resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz" + dependencies: + react-is "^16.7.0" + +hpack.js@^2.1.6: + version "2.1.6" + resolved "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz" + dependencies: + inherits "^2.0.1" + obuf "^1.0.0" + readable-stream "^2.0.1" + wbuf "^1.1.0" + +html-entities@^2.3.2: + version "2.3.2" + resolved "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz" + +html-minifier-terser@^6.0.2: + version "6.1.0" + resolved "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz" + dependencies: + camel-case "^4.1.2" + clean-css "^5.2.2" + commander "^8.3.0" + he "^1.2.0" + param-case "^3.0.4" + relateurl "^0.2.7" + terser "^5.10.0" + +html-tags@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz" + +html-void-elements@^1.0.0: + version "1.0.5" + resolved "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz" + +html-webpack-plugin@^5.4.0: + version "5.5.0" + resolved "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz" dependencies: - "@types/unist" "^2.0.0" - "unist-util-stringify-position" "^2.0.0" + "@types/html-minifier-terser" "^6.0.0" + html-minifier-terser "^6.0.2" + lodash "^4.17.21" + pretty-error "^4.0.0" + tapable "^2.0.0" + +htmlparser2@^3.9.1: + version "3.10.1" + resolved "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz" + dependencies: + domelementtype "^1.3.1" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^3.1.1" + +htmlparser2@^6.1.0: + version "6.1.0" + resolved "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz" + dependencies: + domelementtype "^2.0.1" + domhandler "^4.0.0" + domutils "^2.5.2" + entities "^2.0.0" + +http-cache-semantics@^4.0.0: + version "4.1.1" + resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz" + +http-deceiver@^1.2.7: + version "1.2.7" + resolved "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" + +http-errors@1.8.1: + version "1.8.1" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz" + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.1" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz" + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-parser-js@>=0.5.1: + version "0.5.5" + resolved "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz" + +http-proxy-middleware@^2.0.0: + version "2.0.3" + resolved "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.3.tgz" + dependencies: + "@types/http-proxy" "^1.17.8" + http-proxy "^1.18.1" + is-glob "^4.0.1" + is-plain-obj "^3.0.0" + micromatch "^4.0.2" -"vfile@^4.0.0": - "integrity" "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==" - "resolved" "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz" - "version" "4.2.1" +http-proxy@^1.18.1: + version "1.18.1" + resolved "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz" dependencies: - "@types/unist" "^2.0.0" - "is-buffer" "^2.0.0" - "unist-util-stringify-position" "^2.0.0" - "vfile-message" "^2.0.0" - -"wait-on@^6.0.0": - "integrity" "sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw==" - "resolved" "https://registry.npmjs.org/wait-on/-/wait-on-6.0.1.tgz" - "version" "6.0.1" - dependencies: - "axios" "^0.25.0" - "joi" "^17.6.0" - "lodash" "^4.17.21" - "minimist" "^1.2.5" - "rxjs" "^7.5.4" - -"watchpack@^2.3.1": - "integrity" "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==" - "resolved" "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz" - "version" "2.3.1" - dependencies: - "glob-to-regexp" "^0.4.1" - "graceful-fs" "^4.1.2" - -"wbuf@^1.1.0", "wbuf@^1.7.3": - "integrity" "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==" - "resolved" "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz" - "version" "1.7.3" - dependencies: - "minimalistic-assert" "^1.0.0" - -"web-namespaces@^1.0.0", "web-namespaces@^1.1.2": - "integrity" "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==" - "resolved" "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz" - "version" "1.1.4" - -"webidl-conversions@^3.0.0": - "integrity" "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" - "resolved" "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" - "version" "3.0.1" - -"webpack-bundle-analyzer@^4.4.2": - "integrity" "sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ==" - "resolved" "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz" - "version" "4.5.0" - dependencies: - "acorn" "^8.0.4" - "acorn-walk" "^8.0.0" - "chalk" "^4.1.0" - "commander" "^7.2.0" - "gzip-size" "^6.0.0" - "lodash" "^4.17.20" - "opener" "^1.5.2" - "sirv" "^1.0.7" - "ws" "^7.3.1" - -"webpack-dev-middleware@^5.3.1": - "integrity" "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==" - "resolved" "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz" - "version" "5.3.1" - dependencies: - "colorette" "^2.0.10" - "memfs" "^3.4.1" - "mime-types" "^2.1.31" - "range-parser" "^1.2.1" - "schema-utils" "^4.0.0" - -"webpack-dev-server@^4.7.1": - "integrity" "sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A==" - "resolved" "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz" - "version" "4.7.4" + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" dependencies: - "@types/bonjour" "^3.5.9" - "@types/connect-history-api-fallback" "^1.3.5" - "@types/express" "^4.17.13" - "@types/serve-index" "^1.9.1" - "@types/sockjs" "^0.3.33" - "@types/ws" "^8.2.2" - "ansi-html-community" "^0.0.8" - "bonjour" "^3.5.0" - "chokidar" "^3.5.3" - "colorette" "^2.0.10" - "compression" "^1.7.4" - "connect-history-api-fallback" "^1.6.0" - "default-gateway" "^6.0.3" - "del" "^6.0.0" - "express" "^4.17.1" - "graceful-fs" "^4.2.6" - "html-entities" "^2.3.2" - "http-proxy-middleware" "^2.0.0" - "ipaddr.js" "^2.0.1" - "open" "^8.0.9" - "p-retry" "^4.5.0" - "portfinder" "^1.0.28" - "schema-utils" "^4.0.0" - "selfsigned" "^2.0.0" - "serve-index" "^1.9.1" - "sockjs" "^0.3.21" - "spdy" "^4.0.2" - "strip-ansi" "^7.0.0" - "webpack-dev-middleware" "^5.3.1" - "ws" "^8.4.2" - -"webpack-merge@^5.8.0": - "integrity" "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==" - "resolved" "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz" - "version" "5.8.0" - dependencies: - "clone-deep" "^4.0.1" - "wildcard" "^2.0.0" - -"webpack-sources@^1.1.0", "webpack-sources@^1.4.3": - "integrity" "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==" - "resolved" "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz" - "version" "1.4.3" - dependencies: - "source-list-map" "^2.0.0" - "source-map" "~0.6.1" - -"webpack-sources@^3.2.3": - "integrity" "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==" - "resolved" "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz" - "version" "3.2.3" - -"webpack@^4.0.0 || ^5.0.0", "webpack@^4.37.0 || ^5.0.0", "webpack@^4.4.0 || ^5.0.0", "webpack@^5.0.0", "webpack@^5.1.0", "webpack@^5.20.0", "webpack@^5.61.0", "webpack@>= 4", "webpack@>=2", "webpack@>=4.41.1 || 5.x", "webpack@3 || 4 || 5", "webpack@5.x": - "integrity" "sha512-+VyvOSJXZMT2V5vLzOnDuMz5GxEqLk7hKWQ56YxPW/PQRUuKimPqmEIJOx8jHYeyo65pKbapbW464mvsKbaj4A==" - "resolved" "https://registry.npmjs.org/webpack/-/webpack-5.69.1.tgz" - "version" "5.69.1" + safer-buffer ">= 2.1.2 < 3" + +icss-utils@^5.0.0, icss-utils@^5.1.0: + version "5.1.0" + resolved "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz" + +ignore@^5.1.9, ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz" + +image-size@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/image-size/-/image-size-1.0.1.tgz" dependencies: - "@types/eslint-scope" "^3.7.3" - "@types/estree" "^0.0.51" + queue "6.0.2" + +immer@^9.0.7: + version "9.0.12" + resolved "https://registry.npmjs.org/immer/-/immer-9.0.12.tgz" + +import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.2.2, import-fresh@^3.3.0: + version "3.3.0" + resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" + +infima@0.2.0-alpha.37: + version "0.2.0-alpha.37" + resolved "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.37.tgz" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + +ini@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz" + +ini@^1.3.5, ini@~1.3.0: + version "1.3.8" + resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" + +inline-style-parser@0.1.1: + version "0.1.1" + resolved "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz" + +interpret@^1.0.0: + version "1.4.0" + resolved "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz" + +ip@^1.1.0: + version "1.1.5" + resolved "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz" + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" + +ipaddr.js@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz" + +is-alphabetical@1.0.4, is-alphabetical@^1.0.0: + version "1.0.4" + resolved "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz" + +is-alphanumerical@^1.0.0: + version "1.0.4" + resolved "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz" + dependencies: + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + +is-arguments@^1.0.4: + version "1.1.1" + resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz" + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" + dependencies: + binary-extensions "^2.0.0" + +is-buffer@^2.0.0: + version "2.0.5" + resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz" + +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz" + dependencies: + ci-info "^2.0.0" + +is-core-module@^2.8.1: + version "2.8.1" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz" + dependencies: + has "^1.0.3" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz" + dependencies: + has-tostringtag "^1.0.0" + +is-decimal@^1.0.0: + version "1.0.4" + resolved "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz" + +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz" + +is-extendable@^0.1.0: + version "0.1.1" + resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + +is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" + dependencies: + is-extglob "^2.1.1" + +is-hexadecimal@^1.0.0: + version "1.0.4" + resolved "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz" + +is-installed-globally@^0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz" + dependencies: + global-dirs "^3.0.0" + is-path-inside "^3.0.2" + +is-npm@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + +is-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz" + +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz" + +is-path-cwd@^2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz" + +is-path-inside@^3.0.2: + version "3.0.3" + resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" + +is-plain-obj@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" + +is-plain-obj@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz" + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" + dependencies: + isobject "^3.0.1" + +is-regex@^1.0.4: + version "1.1.4" + resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz" + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz" + +is-root@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz" + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" + +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" + +is-whitespace-character@^1.0.0: + version "1.0.4" + resolved "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz" + +is-word-character@^1.0.0: + version "1.0.4" + resolved "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz" + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz" + dependencies: + is-docker "^2.0.0" + +is-yarn-global@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" + +jest-worker@^27.0.2, jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz" + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +joi@^17.4.2, joi@^17.6.0: + version "17.6.0" + resolved "https://registry.npmjs.org/joi/-/joi-17.6.0.tgz" + dependencies: + "@hapi/hoek" "^9.0.0" + "@hapi/topo" "^5.0.0" + "@sideway/address" "^4.1.3" + "@sideway/formula" "^3.0.0" + "@sideway/pinpoint" "^2.0.0" + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^4.0.0: + version "4.1.0" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" + dependencies: + argparse "^2.0.1" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" + +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz" + +json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: + version "2.3.1" + resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" + +json5@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz" + dependencies: + minimist "^1.2.0" + +json5@^2.1.2, json5@^2.2.2: + version "2.2.3" + resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz" + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz" + dependencies: + json-buffer "3.0.0" + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" + +klona@^2.0.5: + version "2.0.5" + resolved "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz" + +latest-version@^5.1.0: + version "5.1.0" + resolved "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz" + dependencies: + package-json "^6.3.0" + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz" + +lilconfig@^2.0.3: + version "2.0.4" + resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz" + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" + +loader-runner@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz" + +loader-utils@^1.4.0: + version "1.4.2" + resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz" + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^1.0.1" + +loader-utils@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz" + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + +loader-utils@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz" + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" + dependencies: + p-locate "^5.0.0" + +lodash.assignin@^4.0.9: + version "4.2.0" + resolved "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz" + +lodash.bind@^4.1.4: + version "4.2.1" + resolved "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz" + +lodash.curry@^4.0.1: + version "4.1.1" + resolved "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz" + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" + +lodash.defaults@^4.0.1: + version "4.2.0" + resolved "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz" + +lodash.filter@^4.4.0: + version "4.6.0" + resolved "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz" + +lodash.flatten@^4.2.0: + version "4.4.0" + resolved "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz" + +lodash.flow@^3.3.0: + version "3.5.0" + resolved "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz" + +lodash.foreach@^4.3.0: + version "4.5.0" + resolved "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz" + +lodash.map@^4.4.0: + version "4.6.0" + resolved "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz" + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz" + +lodash.merge@^4.4.0: + version "4.6.2" + resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" + +lodash.pick@^4.2.1: + version "4.4.0" + resolved "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz" + +lodash.reduce@^4.4.0: + version "4.6.0" + resolved "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz" + +lodash.reject@^4.4.0: + version "4.6.0" + resolved "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz" + +lodash.some@^4.4.0: + version "4.6.0" + resolved "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz" + +lodash.uniq@4.5.0, lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz" + +lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" + +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz" + dependencies: + tslib "^2.0.3" + +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz" + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz" + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" + dependencies: + yallist "^3.0.2" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" + dependencies: + yallist "^4.0.0" + +magic-string@^0.25.3: + version "0.25.7" + resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz" + dependencies: + sourcemap-codec "^1.4.4" + +make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" + dependencies: + semver "^6.0.0" + +markdown-escapes@^1.0.0: + version "1.0.4" + resolved "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz" + +mdast-squeeze-paragraphs@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz" + dependencies: + unist-util-remove "^2.0.0" + +mdast-util-definitions@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz" + dependencies: + unist-util-visit "^2.0.0" + +mdast-util-to-hast@10.0.1: + version "10.0.1" + resolved "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz" + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + mdast-util-definitions "^4.0.0" + mdurl "^1.0.0" + unist-builder "^2.0.0" + unist-util-generated "^1.0.0" + unist-util-position "^3.0.0" + unist-util-visit "^2.0.0" + +mdast-util-to-string@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz" + +mdn-data@2.0.14: + version "2.0.14" + resolved "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz" + +mdurl@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + +memfs@^3.1.2, memfs@^3.4.1: + version "3.4.1" + resolved "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz" + dependencies: + fs-monkey "1.0.3" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + +micromatch@^4.0.2, micromatch@^4.0.4: + version "4.0.4" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz" + dependencies: + braces "^3.0.1" + picomatch "^2.2.3" + +mime-db@1.51.0, "mime-db@>= 1.43.0 < 2": + version "1.51.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz" + +mime-db@~1.33.0: + version "1.33.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz" + +mime-types@2.1.18: + version "2.1.18" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz" + dependencies: + mime-db "~1.33.0" + +mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.34" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz" + dependencies: + mime-db "1.51.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" + +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz" + +mini-create-react-context@^0.4.0: + version "0.4.1" + resolved "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz" + dependencies: + "@babel/runtime" "^7.12.1" + tiny-warning "^1.0.3" + +mini-css-extract-plugin@^1.6.0: + version "1.6.2" + resolved "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.6.2.tgz" + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + webpack-sources "^1.1.0" + +minimalistic-assert@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" + +minimatch@3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" + dependencies: + brace-expansion "^1.1.7" + +minimatch@^3.0.4: + version "3.1.2" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0, minimist@^1.2.5: + version "1.2.7" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz" + +mkdirp@^0.5.5: + version "0.5.5" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz" + dependencies: + minimist "^1.2.5" + +mrmime@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" + +ms@2.1.3, ms@^2.1.1: + version "2.1.3" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + +multicast-dns-service-types@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz" + +multicast-dns@^6.0.1: + version "6.2.3" + resolved "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz" + dependencies: + dns-packet "^1.3.1" + thunky "^1.0.2" + +nanoid@^3.2.0: + version "3.3.1" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz" + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" + +no-case@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz" + dependencies: + lower-case "^2.0.2" + tslib "^2.0.3" + +node-emoji@^1.10.0: + version "1.11.0" + resolved "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz" + dependencies: + lodash "^4.17.21" + +node-fetch@2.6.7: + version "2.6.7" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz" + dependencies: + whatwg-url "^5.0.0" + +node-forge@^1.2.0: + version "1.3.0" + resolved "https://registry.npmjs.org/node-forge/-/node-forge-1.3.0.tgz" + +node-releases@^2.0.8: + version "2.0.10" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz" + +normalize-url@^4.1.0: + version "4.5.1" + resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz" + +normalize-url@^6.0.1: + version "6.1.0" + resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz" + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz" + dependencies: + path-key "^3.0.0" + +nprogress@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz" + +nth-check@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz" + dependencies: + boolbase "^1.0.0" + +nth-check@~1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz" + dependencies: + boolbase "~1.0.0" + +object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + +object-is@^1.0.1: + version "1.1.5" + resolved "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz" + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" + +object.assign@^4.1.0: + version "4.1.2" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz" + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + +obuf@^1.0.0, obuf@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz" + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + dependencies: + wrappy "1" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" + dependencies: + mimic-fn "^2.1.0" + +open@^8.0.9, open@^8.4.0: + version "8.4.0" + resolved "https://registry.npmjs.org/open/-/open-8.4.0.tgz" + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + +opener@^1.5.2: + version "1.5.2" + resolved "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz" + +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz" + +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" + dependencies: + yocto-queue "^0.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz" + dependencies: + p-limit "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" + dependencies: + p-limit "^3.0.2" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz" + dependencies: + aggregate-error "^3.0.0" + +p-retry@^4.5.0: + version "4.6.1" + resolved "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz" + dependencies: + "@types/retry" "^0.12.0" + retry "^0.13.1" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" + +package-json@^6.3.0: + version "6.5.0" + resolved "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz" + dependencies: + got "^9.6.0" + registry-auth-token "^4.0.0" + registry-url "^5.0.0" + semver "^6.2.0" + +param-case@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz" + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" + dependencies: + callsites "^3.0.0" + +parse-entities@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz" + dependencies: + character-entities "^1.0.0" + character-entities-legacy "^1.0.0" + character-reference-invalid "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + is-hexadecimal "^1.0.0" + +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parse-numeric-range@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz" + +parse5-htmlparser2-tree-adapter@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz" + dependencies: + parse5 "^6.0.1" + +parse5@^5.0.0: + version "5.1.1" + resolved "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz" + +parse5@^6.0.0, parse5@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz" + +parseurl@~1.3.2, parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" + +pascal-case@^3.1.2: + version "3.1.2" + resolved "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz" + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + +path-is-inside@1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz" + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" + +path-to-regexp@2.2.1: + version "2.2.1" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz" + +path-to-regexp@^1.7.0: + version "1.8.0" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz" + dependencies: + isarray "0.0.1" + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: + version "2.3.1" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + +pkg-dir@^4.1.0: + version "4.2.0" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" + dependencies: + find-up "^4.0.0" + +pkg-up@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz" + dependencies: + find-up "^3.0.0" + +portfinder@^1.0.28: + version "1.0.28" + resolved "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz" + dependencies: + async "^2.6.2" + debug "^3.1.1" + mkdirp "^0.5.5" + +postcss-calc@^8.2.0: + version "8.2.4" + resolved "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz" + dependencies: + postcss-selector-parser "^6.0.9" + postcss-value-parser "^4.2.0" + +postcss-colormin@^5.2.5: + version "5.2.5" + resolved "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.2.5.tgz" + dependencies: + browserslist "^4.16.6" + caniuse-api "^3.0.0" + colord "^2.9.1" + postcss-value-parser "^4.2.0" + +postcss-convert-values@^5.0.4: + version "5.0.4" + resolved "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.0.4.tgz" + dependencies: + postcss-value-parser "^4.2.0" + +postcss-discard-comments@^5.0.3: + version "5.0.3" + resolved "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.0.3.tgz" + +postcss-discard-duplicates@^5.0.3: + version "5.0.3" + resolved "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.3.tgz" + +postcss-discard-empty@^5.0.3: + version "5.0.3" + resolved "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.0.3.tgz" + +postcss-discard-overridden@^5.0.4: + version "5.0.4" + resolved "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.0.4.tgz" + +postcss-discard-unused@^5.0.3: + version "5.0.3" + resolved "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-5.0.3.tgz" + dependencies: + postcss-selector-parser "^6.0.5" + +postcss-loader@^6.1.1: + version "6.2.1" + resolved "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz" + dependencies: + cosmiconfig "^7.0.0" + klona "^2.0.5" + semver "^7.3.5" + +postcss-merge-idents@^5.0.3: + version "5.0.3" + resolved "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-5.0.3.tgz" + dependencies: + cssnano-utils "^3.0.2" + postcss-value-parser "^4.2.0" + +postcss-merge-longhand@^5.0.6: + version "5.0.6" + resolved "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.0.6.tgz" + dependencies: + postcss-value-parser "^4.2.0" + stylehacks "^5.0.3" + +postcss-merge-rules@^5.0.6: + version "5.0.6" + resolved "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.0.6.tgz" + dependencies: + browserslist "^4.16.6" + caniuse-api "^3.0.0" + cssnano-utils "^3.0.2" + postcss-selector-parser "^6.0.5" + +postcss-minify-font-values@^5.0.4: + version "5.0.4" + resolved "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.0.4.tgz" + dependencies: + postcss-value-parser "^4.2.0" + +postcss-minify-gradients@^5.0.6: + version "5.0.6" + resolved "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.0.6.tgz" + dependencies: + colord "^2.9.1" + cssnano-utils "^3.0.2" + postcss-value-parser "^4.2.0" + +postcss-minify-params@^5.0.5: + version "5.0.5" + resolved "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.0.5.tgz" + dependencies: + browserslist "^4.16.6" + cssnano-utils "^3.0.2" + postcss-value-parser "^4.2.0" + +postcss-minify-selectors@^5.1.3: + version "5.1.3" + resolved "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.1.3.tgz" + dependencies: + postcss-selector-parser "^6.0.5" + +postcss-modules-extract-imports@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz" + +postcss-modules-local-by-default@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz" + dependencies: + icss-utils "^5.0.0" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + +postcss-modules-scope@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz" + dependencies: + postcss-selector-parser "^6.0.4" + +postcss-modules-values@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz" + dependencies: + icss-utils "^5.0.0" + +postcss-normalize-charset@^5.0.3: + version "5.0.3" + resolved "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.0.3.tgz" + +postcss-normalize-display-values@^5.0.3: + version "5.0.3" + resolved "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.3.tgz" + dependencies: + postcss-value-parser "^4.2.0" + +postcss-normalize-positions@^5.0.4: + version "5.0.4" + resolved "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.0.4.tgz" + dependencies: + postcss-value-parser "^4.2.0" + +postcss-normalize-repeat-style@^5.0.4: + version "5.0.4" + resolved "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.4.tgz" + dependencies: + postcss-value-parser "^4.2.0" + +postcss-normalize-string@^5.0.4: + version "5.0.4" + resolved "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.0.4.tgz" + dependencies: + postcss-value-parser "^4.2.0" + +postcss-normalize-timing-functions@^5.0.3: + version "5.0.3" + resolved "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.3.tgz" + dependencies: + postcss-value-parser "^4.2.0" + +postcss-normalize-unicode@^5.0.4: + version "5.0.4" + resolved "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.4.tgz" + dependencies: + browserslist "^4.16.6" + postcss-value-parser "^4.2.0" + +postcss-normalize-url@^5.0.5: + version "5.0.5" + resolved "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.0.5.tgz" + dependencies: + normalize-url "^6.0.1" + postcss-value-parser "^4.2.0" + +postcss-normalize-whitespace@^5.0.4: + version "5.0.4" + resolved "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.4.tgz" + dependencies: + postcss-value-parser "^4.2.0" + +postcss-ordered-values@^5.0.5: + version "5.0.5" + resolved "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.0.5.tgz" + dependencies: + cssnano-utils "^3.0.2" + postcss-value-parser "^4.2.0" + +postcss-reduce-idents@^5.0.3: + version "5.0.3" + resolved "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-5.0.3.tgz" + dependencies: + postcss-value-parser "^4.2.0" + +postcss-reduce-initial@^5.0.3: + version "5.0.3" + resolved "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.0.3.tgz" + dependencies: + browserslist "^4.16.6" + caniuse-api "^3.0.0" + +postcss-reduce-transforms@^5.0.4: + version "5.0.4" + resolved "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.4.tgz" + dependencies: + postcss-value-parser "^4.2.0" + +postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: + version "6.0.9" + resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz" + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-sort-media-queries@^4.1.0: + version "4.2.1" + resolved "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-4.2.1.tgz" + dependencies: + sort-css-media-queries "2.0.4" + +postcss-svgo@^5.0.4: + version "5.0.4" + resolved "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.0.4.tgz" + dependencies: + postcss-value-parser "^4.2.0" + svgo "^2.7.0" + +postcss-unique-selectors@^5.0.4: + version "5.0.4" + resolved "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.0.4.tgz" + dependencies: + postcss-selector-parser "^6.0.5" + +postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" + +postcss-zindex@^5.0.2: + version "5.0.2" + resolved "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-5.0.2.tgz" + +postcss@^8.3.11, postcss@^8.3.5, postcss@^8.3.7, postcss@^8.4.5: + version "8.4.6" + resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.6.tgz" + dependencies: + nanoid "^3.2.0" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz" + +pretty-error@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz" + dependencies: + lodash "^4.17.20" + renderkid "^3.0.0" + +pretty-time@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz" + +prism-react-renderer@^1.2.1: + version "1.3.1" + resolved "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-1.3.1.tgz" + +prismjs@^1.23.0: + version "1.27.0" + resolved "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz" + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" + +promise@^7.1.1: + version "7.3.1" + resolved "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz" + dependencies: + asap "~2.0.3" + +prompts@^2.4.1, prompts@^2.4.2: + version "2.4.2" + resolved "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz" + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +prop-types@^15.6.2, prop-types@^15.7.2: + version "15.8.1" + resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + +property-information@^5.0.0, property-information@^5.3.0: + version "5.6.0" + resolved "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz" + dependencies: + xtend "^4.0.0" + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" + +punycode@^1.3.2: + version "1.4.1" + resolved "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz" + +pupa@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz" + dependencies: + escape-goat "^2.0.0" + +pure-color@^1.2.0: + version "1.3.0" + resolved "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz" + +qs@6.9.7: + version "6.9.7" + resolved "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz" + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + +queue@6.0.2: + version "6.0.2" + resolved "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz" + dependencies: + inherits "~2.0.3" + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" + dependencies: + safe-buffer "^5.1.0" + +range-parser@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz" + +range-parser@^1.2.1, range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" + +raw-body@2.4.3: + version "2.4.3" + resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz" + dependencies: + bytes "3.1.2" + http-errors "1.8.1" + iconv-lite "0.4.24" + unpipe "1.0.0" + +rc@^1.2.8: + version "1.2.8" + resolved "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz" + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +react-base16-styling@^0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.6.0.tgz" + dependencies: + base16 "^1.0.0" + lodash.curry "^4.0.1" + lodash.flow "^3.3.0" + pure-color "^1.2.0" + +react-dev-utils@^12.0.0: + version "12.0.0" + resolved "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz" + dependencies: + "@babel/code-frame" "^7.16.0" + address "^1.1.2" + browserslist "^4.18.1" + chalk "^4.1.2" + cross-spawn "^7.0.3" + detect-port-alt "^1.1.6" + escape-string-regexp "^4.0.0" + filesize "^8.0.6" + find-up "^5.0.0" + fork-ts-checker-webpack-plugin "^6.5.0" + global-modules "^2.0.0" + globby "^11.0.4" + gzip-size "^6.0.0" + immer "^9.0.7" + is-root "^2.1.0" + loader-utils "^3.2.0" + open "^8.4.0" + pkg-up "^3.1.0" + prompts "^2.4.2" + react-error-overlay "^6.0.10" + recursive-readdir "^2.2.2" + shell-quote "^1.7.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + +react-dom@^16.10.2: + version "16.14.0" + resolved "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz" + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + scheduler "^0.19.1" + +react-error-overlay@^6.0.10: + version "6.0.10" + resolved "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz" + +react-fast-compare@^3.1.1: + version "3.2.0" + resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz" + +react-helmet@^6.1.0: + version "6.1.0" + resolved "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz" + dependencies: + object-assign "^4.1.1" + prop-types "^15.7.2" + react-fast-compare "^3.1.1" + react-side-effect "^2.1.0" + +react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: + version "16.13.1" + resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" + +react-json-view@^1.21.3: + version "1.21.3" + resolved "https://registry.npmjs.org/react-json-view/-/react-json-view-1.21.3.tgz" + dependencies: + flux "^4.0.1" + react-base16-styling "^0.6.0" + react-lifecycles-compat "^3.0.4" + react-textarea-autosize "^8.3.2" + +react-lifecycles-compat@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz" + +react-loadable-ssr-addon-v5-slorber@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz" + dependencies: + "@babel/runtime" "^7.10.3" + +react-popupbox@^2.0.8: + version "2.0.8" + resolved "https://registry.npmjs.org/react-popupbox/-/react-popupbox-2.0.8.tgz" + dependencies: + deepmerge "^1.3.2" + react "^16.3.1" + +react-router-config@^5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/react-router-config/-/react-router-config-5.1.1.tgz" + dependencies: + "@babel/runtime" "^7.1.2" + +react-router-dom@^5.2.0: + version "5.3.0" + resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.0.tgz" + dependencies: + "@babel/runtime" "^7.12.13" + history "^4.9.0" + loose-envify "^1.3.1" + prop-types "^15.6.2" + react-router "5.2.1" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + +react-router@5.2.1, react-router@^5.2.0: + version "5.2.1" + resolved "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz" + dependencies: + "@babel/runtime" "^7.12.13" + history "^4.9.0" + hoist-non-react-statics "^3.1.0" + loose-envify "^1.3.1" + mini-create-react-context "^0.4.0" + path-to-regexp "^1.7.0" + prop-types "^15.6.2" + react-is "^16.6.0" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + +react-side-effect@^2.1.0: + version "2.1.1" + resolved "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.1.tgz" + +react-textarea-autosize@^8.3.2: + version "8.3.3" + resolved "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz" + dependencies: + "@babel/runtime" "^7.10.2" + use-composed-ref "^1.0.0" + use-latest "^1.0.0" + +react@^16.10.2, react@^16.3.1: + version "16.14.0" + resolved "https://registry.npmjs.org/react/-/react-16.14.0.tgz" + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + +readable-stream@^2.0.1: + version "2.3.7" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.6, readable-stream@^3.1.1: + version "3.6.0" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz" + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" + dependencies: + picomatch "^2.2.1" + +reading-time@^1.5.0: + version "1.5.0" + resolved "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz" + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz" + dependencies: + resolve "^1.1.6" + +recursive-readdir@^2.2.2: + version "2.2.2" + resolved "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz" + dependencies: + minimatch "3.0.4" + +regenerate-unicode-properties@^10.0.1: + version "10.0.1" + resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz" + dependencies: + regenerate "^1.4.2" + +regenerate-unicode-properties@^9.0.0: + version "9.0.0" + resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz" + dependencies: + regenerate "^1.4.2" + +regenerate@^1.4.2: + version "1.4.2" + resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" + +regenerator-runtime@^0.13.4: + version "0.13.9" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz" + +regenerator-transform@^0.14.2: + version "0.14.5" + resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz" + dependencies: + "@babel/runtime" "^7.8.4" + +regexp.prototype.flags@^1.2.0: + version "1.4.1" + resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz" + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +regexpu-core@^4.5.4: + version "4.8.0" + resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz" + dependencies: + regenerate "^1.4.2" + regenerate-unicode-properties "^9.0.0" + regjsgen "^0.5.2" + regjsparser "^0.7.0" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.0.0" + +regexpu-core@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz" + dependencies: + regenerate "^1.4.2" + regenerate-unicode-properties "^10.0.1" + regjsgen "^0.6.0" + regjsparser "^0.8.2" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.0.0" + +registry-auth-token@^4.0.0: + version "4.2.1" + resolved "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz" + dependencies: + rc "^1.2.8" + +registry-url@^5.0.0: + version "5.1.0" + resolved "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz" + dependencies: + rc "^1.2.8" + +regjsgen@^0.5.2: + version "0.5.2" + resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz" + +regjsgen@^0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz" + +regjsparser@^0.7.0: + version "0.7.0" + resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz" + dependencies: + jsesc "~0.5.0" + +regjsparser@^0.8.2: + version "0.8.4" + resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz" + dependencies: + jsesc "~0.5.0" + +rehype-parse@^6.0.2: + version "6.0.2" + resolved "https://registry.npmjs.org/rehype-parse/-/rehype-parse-6.0.2.tgz" + dependencies: + hast-util-from-parse5 "^5.0.0" + parse5 "^5.0.0" + xtend "^4.0.0" + +relateurl@^0.2.7: + version "0.2.7" + resolved "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz" + +remark-admonitions@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/remark-admonitions/-/remark-admonitions-1.2.1.tgz" + dependencies: + rehype-parse "^6.0.2" + unified "^8.4.2" + unist-util-visit "^2.0.1" + +remark-emoji@^2.1.0: + version "2.2.0" + resolved "https://registry.npmjs.org/remark-emoji/-/remark-emoji-2.2.0.tgz" + dependencies: + emoticon "^3.2.0" + node-emoji "^1.10.0" + unist-util-visit "^2.0.3" + +remark-footnotes@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/remark-footnotes/-/remark-footnotes-2.0.0.tgz" + +remark-mdx-remove-exports@^1.6.22: + version "1.6.22" + resolved "https://registry.npmjs.org/remark-mdx-remove-exports/-/remark-mdx-remove-exports-1.6.22.tgz" + dependencies: + unist-util-remove "2.0.0" + +remark-mdx-remove-imports@^1.6.22: + version "1.6.22" + resolved "https://registry.npmjs.org/remark-mdx-remove-imports/-/remark-mdx-remove-imports-1.6.22.tgz" + dependencies: + unist-util-remove "2.0.0" + +remark-mdx@1.6.22: + version "1.6.22" + resolved "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz" + dependencies: + "@babel/core" "7.12.9" + "@babel/helper-plugin-utils" "7.10.4" + "@babel/plugin-proposal-object-rest-spread" "7.12.1" + "@babel/plugin-syntax-jsx" "7.12.1" + "@mdx-js/util" "1.6.22" + is-alphabetical "1.0.4" + remark-parse "8.0.3" + unified "9.2.0" + +remark-parse@8.0.3: + version "8.0.3" + resolved "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz" + dependencies: + ccount "^1.0.0" + collapse-white-space "^1.0.2" + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + is-whitespace-character "^1.0.0" + is-word-character "^1.0.0" + markdown-escapes "^1.0.0" + parse-entities "^2.0.0" + repeat-string "^1.5.4" + state-toggle "^1.0.0" + trim "0.0.1" + trim-trailing-lines "^1.0.0" + unherit "^1.0.4" + unist-util-remove-position "^2.0.0" + vfile-location "^3.0.0" + xtend "^4.0.1" + +remark-squeeze-paragraphs@4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz" + dependencies: + mdast-squeeze-paragraphs "^4.0.0" + +remarkable-admonitions@^0.2.1: + version "0.2.2" + resolved "https://registry.npmjs.org/remarkable-admonitions/-/remarkable-admonitions-0.2.2.tgz" + +renderkid@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz" + dependencies: + css-select "^4.1.3" + dom-converter "^0.2.0" + htmlparser2 "^6.1.0" + lodash "^4.17.21" + strip-ansi "^6.0.1" + +repeat-string@^1.5.4: + version "1.6.1" + resolved "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" + +"require-like@>= 0.1.1": + version "0.1.2" + resolved "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz" + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" + +resolve-pathname@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz" + +resolve@^1.1.6, resolve@^1.14.2, resolve@^1.3.2: + version "1.22.0" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz" + dependencies: + is-core-module "^2.8.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz" + dependencies: + lowercase-keys "^1.0.0" + +retry@^0.13.1: + version "0.13.1" + resolved "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" + dependencies: + glob "^7.1.3" + +rtl-detect@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.0.4.tgz" + +rtlcss@^3.3.0: + version "3.5.0" + resolved "https://registry.npmjs.org/rtlcss/-/rtlcss-3.5.0.tgz" + dependencies: + find-up "^5.0.0" + picocolors "^1.0.0" + postcss "^8.3.11" + strip-json-comments "^3.1.1" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" + dependencies: + queue-microtask "^1.2.2" + +rxjs@^7.5.4: + version "7.5.4" + resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.5.4.tgz" + dependencies: + tslib "^2.1.0" + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" + +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz" + +scheduler@^0.19.1: + version "0.19.1" + resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz" + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + +schema-utils@2.7.0: + version "2.7.0" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz" + dependencies: + "@types/json-schema" "^7.0.4" + ajv "^6.12.2" + ajv-keywords "^3.4.1" + +schema-utils@^2.6.5: + version "2.7.1" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz" + dependencies: + "@types/json-schema" "^7.0.5" + ajv "^6.12.4" + ajv-keywords "^3.5.2" + +schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz" + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +schema-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz" + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.8.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.0.0" + +section-matter@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz" + dependencies: + extend-shallow "^2.0.1" + kind-of "^6.0.0" + +select-hose@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" + +selfsigned@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.0.tgz" + dependencies: + node-forge "^1.2.0" + +semver-diff@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz" + dependencies: + semver "^6.3.0" + +semver@7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz" + +semver@^5.4.1: + version "5.7.1" + resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" + +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" + +semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: + version "7.3.5" + resolved "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" + dependencies: + lru-cache "^6.0.0" + +send@0.17.2: + version "0.17.2" + resolved "https://registry.npmjs.org/send/-/send-0.17.2.tgz" + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "1.8.1" + mime "1.6.0" + ms "2.1.3" + on-finished "~2.3.0" + range-parser "~1.2.1" + statuses "~1.5.0" + +serialize-javascript@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz" + dependencies: + randombytes "^2.1.0" + +serve-handler@^6.1.3: + version "6.1.3" + resolved "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz" + dependencies: + bytes "3.0.0" + content-disposition "0.5.2" + fast-url-parser "1.1.3" + mime-types "2.1.18" + minimatch "3.0.4" + path-is-inside "1.0.2" + path-to-regexp "2.2.1" + range-parser "1.2.0" + +serve-index@^1.9.1: + version "1.9.1" + resolved "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz" + dependencies: + accepts "~1.3.4" + batch "0.6.1" + debug "2.6.9" + escape-html "~1.0.3" + http-errors "~1.6.2" + mime-types "~2.1.17" + parseurl "~1.3.2" + +serve-static@1.14.2: + version "1.14.2" + resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz" + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.17.2" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz" + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz" + dependencies: + kind-of "^6.0.2" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" + +shell-quote@^1.7.3: + version "1.7.3" + resolved "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz" + +shelljs@^0.8.4: + version "0.8.5" + resolved "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz" + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +signal-exit@^3.0.2, signal-exit@^3.0.3: + version "3.0.7" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" + +sirv@^1.0.7: + version "1.0.19" + resolved "https://registry.npmjs.org/sirv/-/sirv-1.0.19.tgz" + dependencies: + "@polka/url" "^1.0.0-next.20" + mrmime "^1.0.0" + totalist "^1.0.0" + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" + +sitemap@^7.0.0: + version "7.1.1" + resolved "https://registry.npmjs.org/sitemap/-/sitemap-7.1.1.tgz" + dependencies: + "@types/node" "^17.0.5" + "@types/sax" "^1.2.1" + arg "^5.0.0" + sax "^1.2.4" + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" + +slash@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz" + +sockjs@^0.3.21: + version "0.3.24" + resolved "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz" + dependencies: + faye-websocket "^0.11.3" + uuid "^8.3.2" + websocket-driver "^0.7.4" + +sort-css-media-queries@2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.0.4.tgz" + +source-list-map@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz" + +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz" + +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.5.0: + version "0.5.7" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + +sourcemap-codec@^1.4.4: + version "1.4.8" + resolved "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz" + +space-separated-tokens@^1.0.0: + version "1.1.5" + resolved "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz" + +spdy-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz" + dependencies: + debug "^4.1.0" + detect-node "^2.0.4" + hpack.js "^2.1.6" + obuf "^1.1.2" + readable-stream "^3.0.6" + wbuf "^1.7.3" + +spdy@^4.0.2: + version "4.0.2" + resolved "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz" + dependencies: + debug "^4.1.0" + handle-thing "^2.0.0" + http-deceiver "^1.2.7" + select-hose "^2.0.0" + spdy-transport "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" + +stable@^0.1.8: + version "0.1.8" + resolved "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz" + +state-toggle@^1.0.0: + version "1.0.3" + resolved "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz" + +"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" + +std-env@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/std-env/-/std-env-3.0.1.tgz" + +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.2: + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" + dependencies: + safe-buffer "~5.1.0" + +stringify-object@^3.3.0: + version "3.3.0" + resolved "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz" + dependencies: + get-own-enumerable-property-symbols "^3.0.0" + is-obj "^1.0.1" + is-regexp "^1.0.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.0: + version "7.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz" + dependencies: + ansi-regex "^6.0.1" + +strip-bom-string@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz" + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz" + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" + +style-to-object@0.3.0, style-to-object@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz" + dependencies: + inline-style-parser "0.1.1" + +stylehacks@^5.0.3: + version "5.0.3" + resolved "https://registry.npmjs.org/stylehacks/-/stylehacks-5.0.3.tgz" + dependencies: + browserslist "^4.16.6" + postcss-selector-parser "^6.0.4" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" + +svg-parser@^2.0.2: + version "2.0.4" + resolved "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz" + +svgo@^2.5.0, svgo@^2.7.0: + version "2.8.0" + resolved "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz" + dependencies: + "@trysound/sax" "0.2.0" + commander "^7.2.0" + css-select "^4.1.3" + css-tree "^1.1.3" + csso "^4.2.0" + picocolors "^1.0.0" + stable "^0.1.8" + +tapable@^1.0.0: + version "1.1.3" + resolved "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz" + +tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz" + +terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.2.4: + version "5.3.1" + resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz" + dependencies: + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.0" + source-map "^0.6.1" + terser "^5.7.2" + +terser@^5.10.0, terser@^5.7.2: + version "5.14.2" + resolved "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz" + dependencies: + "@jridgewell/source-map" "^0.3.2" + acorn "^8.5.0" + commander "^2.20.0" + source-map-support "~0.5.20" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" + +thunky@^1.0.2: + version "1.1.0" + resolved "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz" + +timsort@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz" + +tiny-invariant@^1.0.2: + version "1.2.0" + resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz" + +tiny-warning@^1.0.0, tiny-warning@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz" + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" + +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" + +totalist@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" + +trim-trailing-lines@^1.0.0: + version "1.1.4" + resolved "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz" + +trim@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz" + +trough@^1.0.0: + version "1.0.5" + resolved "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz" + +tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.1: + version "2.3.1" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz" + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz" + dependencies: + is-typedarray "^1.0.0" + +ua-parser-js@^0.7.30: + version "0.7.33" + resolved "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.33.tgz" + +unherit@^1.0.4: + version "1.1.3" + resolved "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz" + dependencies: + inherits "^2.0.0" + xtend "^4.0.0" + +unicode-canonical-property-names-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz" + +unicode-match-property-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz" + dependencies: + unicode-canonical-property-names-ecmascript "^2.0.0" + unicode-property-aliases-ecmascript "^2.0.0" + +unicode-match-property-value-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz" + +unicode-property-aliases-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz" + +unified@9.2.0: + version "9.2.0" + resolved "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz" + dependencies: + bail "^1.0.0" + extend "^3.0.0" + is-buffer "^2.0.0" + is-plain-obj "^2.0.0" + trough "^1.0.0" + vfile "^4.0.0" + +unified@^8.4.2: + version "8.4.2" + resolved "https://registry.npmjs.org/unified/-/unified-8.4.2.tgz" + dependencies: + bail "^1.0.0" + extend "^3.0.0" + is-plain-obj "^2.0.0" + trough "^1.0.0" + vfile "^4.0.0" + +unique-string@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz" + dependencies: + crypto-random-string "^2.0.0" + +unist-builder@2.0.3, unist-builder@^2.0.0: + version "2.0.3" + resolved "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz" + +unist-util-generated@^1.0.0: + version "1.1.6" + resolved "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz" + +unist-util-is@^4.0.0: + version "4.1.0" + resolved "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz" + +unist-util-position@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz" + +unist-util-remove-position@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz" + dependencies: + unist-util-visit "^2.0.0" + +unist-util-remove@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.0.0.tgz" + dependencies: + unist-util-is "^4.0.0" + +unist-util-remove@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.1.0.tgz" + dependencies: + unist-util-is "^4.0.0" + +unist-util-stringify-position@^2.0.0: + version "2.0.3" + resolved "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz" + dependencies: + "@types/unist" "^2.0.2" + +unist-util-visit-parents@^3.0.0: + version "3.1.1" + resolved "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz" + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" + +unist-util-visit@2.0.3, unist-util-visit@^2.0.0, unist-util-visit@^2.0.1, unist-util-visit@^2.0.2, unist-util-visit@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz" + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" + unist-util-visit-parents "^3.0.0" + +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz" + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + +update-browserslist-db@^1.0.10: + version "1.0.10" + resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz" + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +update-notifier@^5.1.0: + version "5.1.0" + resolved "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz" + dependencies: + boxen "^5.0.0" + chalk "^4.1.0" + configstore "^5.0.1" + has-yarn "^2.1.0" + import-lazy "^2.1.0" + is-ci "^2.0.0" + is-installed-globally "^0.4.0" + is-npm "^5.0.0" + is-yarn-global "^0.3.0" + latest-version "^5.1.0" + pupa "^2.1.1" + semver "^7.3.4" + semver-diff "^3.1.1" + xdg-basedir "^4.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" + dependencies: + punycode "^2.1.0" + +url-loader@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz" + dependencies: + loader-utils "^2.0.0" + mime-types "^2.1.27" + schema-utils "^3.0.0" + +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz" + dependencies: + prepend-http "^2.0.0" + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.npmjs.org/url/-/url-0.11.0.tgz" + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use-composed-ref@^1.0.0: + version "1.2.1" + resolved "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.2.1.tgz" + +use-isomorphic-layout-effect@^1.0.0: + version "1.1.1" + resolved "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz" + +use-latest@^1.0.0: + version "1.2.0" + resolved "https://registry.npmjs.org/use-latest/-/use-latest-1.2.0.tgz" + dependencies: + use-isomorphic-layout-effect "^1.0.0" + +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + +utila@~0.4: + version "0.4.0" + resolved "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz" + +utility-types@^3.10.0: + version "3.10.0" + resolved "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" + +value-equal@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz" + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" + +vfile-location@^3.0.0, vfile-location@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz" + +vfile-message@^2.0.0: + version "2.0.4" + resolved "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz" + dependencies: + "@types/unist" "^2.0.0" + unist-util-stringify-position "^2.0.0" + +vfile@^4.0.0: + version "4.2.1" + resolved "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz" + dependencies: + "@types/unist" "^2.0.0" + is-buffer "^2.0.0" + unist-util-stringify-position "^2.0.0" + vfile-message "^2.0.0" + +wait-on@^6.0.0: + version "6.0.1" + resolved "https://registry.npmjs.org/wait-on/-/wait-on-6.0.1.tgz" + dependencies: + axios "^0.25.0" + joi "^17.6.0" + lodash "^4.17.21" + minimist "^1.2.5" + rxjs "^7.5.4" + +watchpack@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +wbuf@^1.1.0, wbuf@^1.7.3: + version "1.7.3" + resolved "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz" + dependencies: + minimalistic-assert "^1.0.0" + +web-namespaces@^1.0.0, web-namespaces@^1.1.2: + version "1.1.4" + resolved "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" + +webpack-bundle-analyzer@^4.4.2: + version "4.5.0" + resolved "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz" + dependencies: + acorn "^8.0.4" + acorn-walk "^8.0.0" + chalk "^4.1.0" + commander "^7.2.0" + gzip-size "^6.0.0" + lodash "^4.17.20" + opener "^1.5.2" + sirv "^1.0.7" + ws "^7.3.1" + +webpack-dev-middleware@^5.3.1: + version "5.3.1" + resolved "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz" + dependencies: + colorette "^2.0.10" + memfs "^3.4.1" + mime-types "^2.1.31" + range-parser "^1.2.1" + schema-utils "^4.0.0" + +webpack-dev-server@^4.7.1: + version "4.7.4" + resolved "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz" + dependencies: + "@types/bonjour" "^3.5.9" + "@types/connect-history-api-fallback" "^1.3.5" + "@types/express" "^4.17.13" + "@types/serve-index" "^1.9.1" + "@types/sockjs" "^0.3.33" + "@types/ws" "^8.2.2" + ansi-html-community "^0.0.8" + bonjour "^3.5.0" + chokidar "^3.5.3" + colorette "^2.0.10" + compression "^1.7.4" + connect-history-api-fallback "^1.6.0" + default-gateway "^6.0.3" + del "^6.0.0" + express "^4.17.1" + graceful-fs "^4.2.6" + html-entities "^2.3.2" + http-proxy-middleware "^2.0.0" + ipaddr.js "^2.0.1" + open "^8.0.9" + p-retry "^4.5.0" + portfinder "^1.0.28" + schema-utils "^4.0.0" + selfsigned "^2.0.0" + serve-index "^1.9.1" + sockjs "^0.3.21" + spdy "^4.0.2" + strip-ansi "^7.0.0" + webpack-dev-middleware "^5.3.1" + ws "^8.4.2" + +webpack-merge@^5.8.0: + version "5.8.0" + resolved "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz" + dependencies: + clone-deep "^4.0.1" + wildcard "^2.0.0" + +webpack-sources@^1.1.0, webpack-sources@^1.4.3: + version "1.4.3" + resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz" + dependencies: + source-list-map "^2.0.0" + source-map "~0.6.1" + +webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz" + +webpack@^5.61.0: + version "5.76.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.76.1.tgz#7773de017e988bccb0f13c7d75ec245f377d295c" + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^0.0.51" "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/wasm-edit" "1.11.1" "@webassemblyjs/wasm-parser" "1.11.1" - "acorn" "^8.4.1" - "acorn-import-assertions" "^1.7.6" - "browserslist" "^4.14.5" - "chrome-trace-event" "^1.0.2" - "enhanced-resolve" "^5.8.3" - "es-module-lexer" "^0.9.0" - "eslint-scope" "5.1.1" - "events" "^3.2.0" - "glob-to-regexp" "^0.4.1" - "graceful-fs" "^4.2.9" - "json-parse-better-errors" "^1.0.2" - "loader-runner" "^4.2.0" - "mime-types" "^2.1.27" - "neo-async" "^2.6.2" - "schema-utils" "^3.1.0" - "tapable" "^2.1.1" - "terser-webpack-plugin" "^5.1.3" - "watchpack" "^2.3.1" - "webpack-sources" "^3.2.3" - -"webpackbar@^5.0.2": - "integrity" "sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ==" - "resolved" "https://registry.npmjs.org/webpackbar/-/webpackbar-5.0.2.tgz" - "version" "5.0.2" - dependencies: - "chalk" "^4.1.0" - "consola" "^2.15.3" - "pretty-time" "^1.1.0" - "std-env" "^3.0.1" - -"websocket-driver@^0.7.4", "websocket-driver@>=0.5.1": - "integrity" "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==" - "resolved" "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz" - "version" "0.7.4" - dependencies: - "http-parser-js" ">=0.5.1" - "safe-buffer" ">=5.1.0" - "websocket-extensions" ">=0.1.1" - -"websocket-extensions@>=0.1.1": - "integrity" "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" - "resolved" "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz" - "version" "0.1.4" - -"whatwg-url@^5.0.0": - "integrity" "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=" - "resolved" "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" - "version" "5.0.0" - dependencies: - "tr46" "~0.0.3" - "webidl-conversions" "^3.0.0" - -"which@^1.3.1": - "integrity" "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==" - "resolved" "https://registry.npmjs.org/which/-/which-1.3.1.tgz" - "version" "1.3.1" - dependencies: - "isexe" "^2.0.0" - -"which@^2.0.1": - "integrity" "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==" - "resolved" "https://registry.npmjs.org/which/-/which-2.0.2.tgz" - "version" "2.0.2" - dependencies: - "isexe" "^2.0.0" - -"widest-line@^3.1.0": - "integrity" "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==" - "resolved" "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz" - "version" "3.1.0" - dependencies: - "string-width" "^4.0.0" - -"wildcard@^2.0.0": - "integrity" "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==" - "resolved" "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz" - "version" "2.0.0" - -"wrap-ansi@^7.0.0": - "integrity" "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==" - "resolved" "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" - "version" "7.0.0" - dependencies: - "ansi-styles" "^4.0.0" - "string-width" "^4.1.0" - "strip-ansi" "^6.0.0" - -"wrappy@1": - "integrity" "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - "resolved" "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - "version" "1.0.2" - -"write-file-atomic@^3.0.0": - "integrity" "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==" - "resolved" "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz" - "version" "3.0.3" - dependencies: - "imurmurhash" "^0.1.4" - "is-typedarray" "^1.0.0" - "signal-exit" "^3.0.2" - "typedarray-to-buffer" "^3.1.5" - -"ws@^7.3.1": - "integrity" "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==" - "resolved" "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz" - "version" "7.5.7" - -"ws@^8.4.2": - "integrity" "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==" - "resolved" "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz" - "version" "8.5.0" - -"xdg-basedir@^4.0.0": - "integrity" "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" - "resolved" "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz" - "version" "4.0.0" - -"xml-js@^1.6.11": - "integrity" "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==" - "resolved" "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz" - "version" "1.6.11" - dependencies: - "sax" "^1.2.4" - -"xtend@^4.0.0", "xtend@^4.0.1": - "integrity" "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - "resolved" "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" - "version" "4.0.2" - -"yallist@^3.0.2": - "integrity" "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - "resolved" "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" - "version" "3.1.1" - -"yallist@^4.0.0": - "integrity" "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - "resolved" "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" - "version" "4.0.0" - -"yaml@^1.10.0", "yaml@^1.10.2", "yaml@^1.7.2": - "integrity" "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" - "resolved" "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" - "version" "1.10.2" - -"yarn@^1.17.3": - "integrity" "sha512-H0p241BXaH0UN9IeH//RT82tl5PfNraVpSpEoW+ET7lmopNC61eZ+A+IDvU8FM6Go5vx162SncDL8J1ZjRBriQ==" - "resolved" "https://registry.npmjs.org/yarn/-/yarn-1.22.17.tgz" - "version" "1.22.17" - -"yocto-queue@^0.1.0": - "integrity" "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" - "resolved" "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" - "version" "0.1.0" - -"zwitch@^1.0.0": - "integrity" "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==" - "resolved" "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz" - "version" "1.0.5" + acorn "^8.7.1" + acorn-import-assertions "^1.7.6" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.10.0" + es-module-lexer "^0.9.0" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.9" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.1.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.1.3" + watchpack "^2.4.0" + webpack-sources "^3.2.3" + +webpackbar@^5.0.2: + version "5.0.2" + resolved "https://registry.npmjs.org/webpackbar/-/webpackbar-5.0.2.tgz" + dependencies: + chalk "^4.1.0" + consola "^2.15.3" + pretty-time "^1.1.0" + std-env "^3.0.1" + +websocket-driver@>=0.5.1, websocket-driver@^0.7.4: + version "0.7.4" + resolved "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz" + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz" + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which@^1.3.1: + version "1.3.1" + resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz" + dependencies: + isexe "^2.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + dependencies: + isexe "^2.0.0" + +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz" + dependencies: + string-width "^4.0.0" + +wildcard@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz" + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + +ws@^7.3.1: + version "7.5.7" + resolved "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz" + +ws@^8.4.2: + version "8.5.0" + resolved "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz" + +xdg-basedir@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz" + +xml-js@^1.6.11: + version "1.6.11" + resolved "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz" + dependencies: + sax "^1.2.4" + +xtend@^4.0.0, xtend@^4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" + +yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: + version "1.10.2" + resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" + +yarn@^1.17.3: + version "1.22.17" + resolved "https://registry.npmjs.org/yarn/-/yarn-1.22.17.tgz" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" + +zwitch@^1.0.0: + version "1.0.5" + resolved "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz" From efc9c794748c38daac60d3e2e14e39eea16b6ec3 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 14 Mar 2023 16:23:55 +0100 Subject: [PATCH 414/898] updating website yarn.lock --- website/yarn.lock | 12882 ++++++++++++++++++++++---------------------- 1 file changed, 6475 insertions(+), 6407 deletions(-) diff --git a/website/yarn.lock b/website/yarn.lock index 559c58f9314..2edf57abf4e 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -3,56 +3,56 @@ "@algolia/autocomplete-core@1.5.2": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.5.2.tgz#ec0178e07b44fd74a057728ac157291b26cecf37" - integrity sha512-DY0bhyczFSS1b/CqJlTE/nQRtnTAHl6IemIkBy0nEWnhDzRDdtdx4p5Uuk3vwAFxwEEgi1WqKwgSSMx6DpNL4A== + "integrity" "sha512-DY0bhyczFSS1b/CqJlTE/nQRtnTAHl6IemIkBy0nEWnhDzRDdtdx4p5Uuk3vwAFxwEEgi1WqKwgSSMx6DpNL4A==" + "resolved" "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.5.2.tgz" + "version" "1.5.2" dependencies: "@algolia/autocomplete-shared" "1.5.2" "@algolia/autocomplete-preset-algolia@1.5.2": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.5.2.tgz#36c5638cc6dba6ea46a86e5a0314637ca40a77ca" - integrity sha512-3MRYnYQFJyovANzSX2CToS6/5cfVjbLLqFsZTKcvF3abhQzxbqwwaMBlJtt620uBUOeMzhdfasKhCc40+RHiZw== + "integrity" "sha512-3MRYnYQFJyovANzSX2CToS6/5cfVjbLLqFsZTKcvF3abhQzxbqwwaMBlJtt620uBUOeMzhdfasKhCc40+RHiZw==" + "resolved" "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.5.2.tgz" + "version" "1.5.2" dependencies: "@algolia/autocomplete-shared" "1.5.2" "@algolia/autocomplete-shared@1.5.2": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.5.2.tgz#e157f9ad624ab8fd940ff28bd2094cdf199cdd79" - integrity sha512-ylQAYv5H0YKMfHgVWX0j0NmL8XBcAeeeVQUmppnnMtzDbDnca6CzhKj3Q8eF9cHCgcdTDdb5K+3aKyGWA0obug== + "integrity" "sha512-ylQAYv5H0YKMfHgVWX0j0NmL8XBcAeeeVQUmppnnMtzDbDnca6CzhKj3Q8eF9cHCgcdTDdb5K+3aKyGWA0obug==" + "resolved" "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.5.2.tgz" + "version" "1.5.2" "@algolia/cache-browser-local-storage@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.12.1.tgz#23f4f219963b96918d0524acd09d4d646541d888" - integrity sha512-ERFFOnC9740xAkuO0iZTQqm2AzU7Dpz/s+g7o48GlZgx5p9GgNcsuK5eS0GoW/tAK+fnKlizCtlFHNuIWuvfsg== + "integrity" "sha512-ERFFOnC9740xAkuO0iZTQqm2AzU7Dpz/s+g7o48GlZgx5p9GgNcsuK5eS0GoW/tAK+fnKlizCtlFHNuIWuvfsg==" + "resolved" "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/cache-common" "4.12.1" "@algolia/cache-common@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.12.1.tgz#d3f1676ca9c404adce0f78d68f6381bedb44cd9c" - integrity sha512-UugTER3V40jT+e19Dmph5PKMeliYKxycNPwrPNADin0RcWNfT2QksK9Ff2N2W7UKraqMOzoeDb4LAJtxcK1a8Q== + "integrity" "sha512-UugTER3V40jT+e19Dmph5PKMeliYKxycNPwrPNADin0RcWNfT2QksK9Ff2N2W7UKraqMOzoeDb4LAJtxcK1a8Q==" + "resolved" "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.12.1.tgz" + "version" "4.12.1" "@algolia/cache-in-memory@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.12.1.tgz#0ef6aac2f8feab5b46fc130beb682bbd21b55244" - integrity sha512-U6iaunaxK1lHsAf02UWF58foKFEcrVLsHwN56UkCtwn32nlP9rz52WOcHsgk6TJrL8NDcO5swMjtOQ5XHESFLw== + "integrity" "sha512-U6iaunaxK1lHsAf02UWF58foKFEcrVLsHwN56UkCtwn32nlP9rz52WOcHsgk6TJrL8NDcO5swMjtOQ5XHESFLw==" + "resolved" "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/cache-common" "4.12.1" "@algolia/client-account@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.12.1.tgz#e838c9283db2fab32a425dd13c77da321d48fd8b" - integrity sha512-jGo4ConJNoMdTCR2zouO0jO/JcJmzOK6crFxMMLvdnB1JhmMbuIKluOTJVlBWeivnmcsqb7r0v7qTCPW5PAyxQ== + "integrity" "sha512-jGo4ConJNoMdTCR2zouO0jO/JcJmzOK6crFxMMLvdnB1JhmMbuIKluOTJVlBWeivnmcsqb7r0v7qTCPW5PAyxQ==" + "resolved" "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/client-common" "4.12.1" "@algolia/client-search" "4.12.1" "@algolia/transporter" "4.12.1" "@algolia/client-analytics@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.12.1.tgz#2976d658655a1590cf84cfb596aa75a204f6dec4" - integrity sha512-h1It7KXzIthlhuhfBk7LteYq72tym9maQDUsyRW0Gft8b6ZQahnRak9gcCvKwhcJ1vJoP7T7JrNYGiYSicTD9g== + "integrity" "sha512-h1It7KXzIthlhuhfBk7LteYq72tym9maQDUsyRW0Gft8b6ZQahnRak9gcCvKwhcJ1vJoP7T7JrNYGiYSicTD9g==" + "resolved" "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/client-common" "4.12.1" "@algolia/client-search" "4.12.1" @@ -60,99 +60,121 @@ "@algolia/transporter" "4.12.1" "@algolia/client-common@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.12.1.tgz#104ccefe96bda3ff926bc70c31ff6d17c41b6107" - integrity sha512-obnJ8eSbv+h94Grk83DTGQ3bqhViSWureV6oK1s21/KMGWbb3DkduHm+lcwFrMFkjSUSzosLBHV9EQUIBvueTw== + "integrity" "sha512-obnJ8eSbv+h94Grk83DTGQ3bqhViSWureV6oK1s21/KMGWbb3DkduHm+lcwFrMFkjSUSzosLBHV9EQUIBvueTw==" + "resolved" "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/requester-common" "4.12.1" "@algolia/transporter" "4.12.1" "@algolia/client-personalization@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.12.1.tgz#f63d1890f95de850e1c8e41c1d57adda521d9e7f" - integrity sha512-sMSnjjPjRgByGHYygV+5L/E8a6RgU7l2GbpJukSzJ9GRY37tHmBHuvahv8JjdCGJ2p7QDYLnQy5bN5Z02qjc7Q== + "integrity" "sha512-sMSnjjPjRgByGHYygV+5L/E8a6RgU7l2GbpJukSzJ9GRY37tHmBHuvahv8JjdCGJ2p7QDYLnQy5bN5Z02qjc7Q==" + "resolved" "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/client-common" "4.12.1" "@algolia/requester-common" "4.12.1" "@algolia/transporter" "4.12.1" -"@algolia/client-search@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.12.1.tgz#fcd7a974be5d39d5c336d7f2e89577ffa66aefdd" - integrity sha512-MwwKKprfY6X2nJ5Ki/ccXM2GDEePvVjZnnoOB2io3dLKW4fTqeSRlC5DRXeFD7UM0vOPPHr4ItV2aj19APKNVQ== +"@algolia/client-search@^4.9.1", "@algolia/client-search@4.12.1": + "integrity" "sha512-MwwKKprfY6X2nJ5Ki/ccXM2GDEePvVjZnnoOB2io3dLKW4fTqeSRlC5DRXeFD7UM0vOPPHr4ItV2aj19APKNVQ==" + "resolved" "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/client-common" "4.12.1" "@algolia/requester-common" "4.12.1" "@algolia/transporter" "4.12.1" "@algolia/events@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950" - integrity sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ== + "integrity" "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==" + "resolved" "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz" + "version" "4.0.1" "@algolia/logger-common@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.12.1.tgz#d6501b4d9d242956257ba8e10f6b4bbf6863baa4" - integrity sha512-fCgrzlXGATNqdFTxwx0GsyPXK+Uqrx1SZ3iuY2VGPPqdt1a20clAG2n2OcLHJpvaa6vMFPlJyWvbqAgzxdxBlQ== + "integrity" "sha512-fCgrzlXGATNqdFTxwx0GsyPXK+Uqrx1SZ3iuY2VGPPqdt1a20clAG2n2OcLHJpvaa6vMFPlJyWvbqAgzxdxBlQ==" + "resolved" "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.12.1.tgz" + "version" "4.12.1" "@algolia/logger-console@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.12.1.tgz#841edd39dd5c5530a69fc66084bfee3254dd0807" - integrity sha512-0owaEnq/davngQMYqxLA4KrhWHiXujQ1CU3FFnyUcMyBR7rGHI48zSOUpqnsAXrMBdSH6rH5BDkSUUFwsh8RkQ== + "integrity" "sha512-0owaEnq/davngQMYqxLA4KrhWHiXujQ1CU3FFnyUcMyBR7rGHI48zSOUpqnsAXrMBdSH6rH5BDkSUUFwsh8RkQ==" + "resolved" "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/logger-common" "4.12.1" "@algolia/requester-browser-xhr@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.12.1.tgz#2d0c18ee188d7cae0e4a930e5e89989e3c4a816b" - integrity sha512-OaMxDyG0TZG0oqz1lQh9e3woantAG1bLnuwq3fmypsrQxra4IQZiyn1x+kEb69D2TcXApI5gOgrD4oWhtEVMtw== + "integrity" "sha512-OaMxDyG0TZG0oqz1lQh9e3woantAG1bLnuwq3fmypsrQxra4IQZiyn1x+kEb69D2TcXApI5gOgrD4oWhtEVMtw==" + "resolved" "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/requester-common" "4.12.1" "@algolia/requester-common@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.12.1.tgz#95bb6539da7199da3e205341cea8f27267f7af29" - integrity sha512-XWIrWQNJ1vIrSuL/bUk3ZwNMNxl+aWz6dNboRW6+lGTcMIwc3NBFE90ogbZKhNrFRff8zI4qCF15tjW+Fyhpow== + "integrity" "sha512-XWIrWQNJ1vIrSuL/bUk3ZwNMNxl+aWz6dNboRW6+lGTcMIwc3NBFE90ogbZKhNrFRff8zI4qCF15tjW+Fyhpow==" + "resolved" "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.12.1.tgz" + "version" "4.12.1" "@algolia/requester-node-http@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.12.1.tgz#c9df97ff1daa7e58c5c2b1f28cf7163005edccb0" - integrity sha512-awBtwaD+s0hxkA1aehYn8F0t9wqGoBVWgY4JPHBmp1ChO3pK7RKnnvnv7QQa9vTlllX29oPt/BBVgMo1Z3n1Qg== + "integrity" "sha512-awBtwaD+s0hxkA1aehYn8F0t9wqGoBVWgY4JPHBmp1ChO3pK7RKnnvnv7QQa9vTlllX29oPt/BBVgMo1Z3n1Qg==" + "resolved" "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/requester-common" "4.12.1" "@algolia/transporter@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.12.1.tgz#61b9829916c474f42e2d4a6eada0d6c138379945" - integrity sha512-BGeNgdEHc6dXIk2g8kdlOoQ6fQ6OIaKQcplEj7HPoi+XZUeAvRi3Pff3QWd7YmybWkjzd9AnTzieTASDWhL+sQ== + "integrity" "sha512-BGeNgdEHc6dXIk2g8kdlOoQ6fQ6OIaKQcplEj7HPoi+XZUeAvRi3Pff3QWd7YmybWkjzd9AnTzieTASDWhL+sQ==" + "resolved" "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/cache-common" "4.12.1" "@algolia/logger-common" "4.12.1" "@algolia/requester-common" "4.12.1" -"@ampproject/remapping@^2.1.0": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" - integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== +"@ampproject/remapping@^2.2.0": + "integrity" "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==" + "resolved" "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz" + "version" "2.2.0" dependencies: - "@jridgewell/trace-mapping" "^0.3.0" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.8.3": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== - dependencies: - "@babel/highlight" "^7.16.7" - -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4", "@babel/compat-data@^7.16.8", "@babel/compat-data@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.0.tgz#86850b8597ea6962089770952075dcaabb8dba34" - integrity sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng== + "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/trace-mapping" "^0.3.9" -"@babel/core@7.12.9": - version "7.12.9" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.9.tgz#fd450c4ec10cdbb980e2928b7aa7a28484593fc8" - integrity sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.8.3": + "integrity" "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==" + "resolved" "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/highlight" "^7.18.6" + +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.8", "@babel/compat-data@^7.17.0", "@babel/compat-data@^7.20.5": + "integrity" "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==" + "resolved" "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz" + "version" "7.21.0" + +"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.12.0", "@babel/core@^7.13.0", "@babel/core@^7.15.5", "@babel/core@^7.16.0", "@babel/core@^7.4.0-0": + "integrity" "sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==" + "resolved" "https://registry.npmjs.org/@babel/core/-/core-7.21.3.tgz" + "version" "7.21.3" + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.21.3" + "@babel/helper-compilation-targets" "^7.20.7" + "@babel/helper-module-transforms" "^7.21.2" + "@babel/helpers" "^7.21.0" + "@babel/parser" "^7.21.3" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.21.3" + "@babel/types" "^7.21.3" + "convert-source-map" "^1.7.0" + "debug" "^4.1.0" + "gensync" "^1.0.0-beta.2" + "json5" "^2.2.2" + "semver" "^6.3.0" + +"@babel/core@^7.11.6", "@babel/core@7.12.9": + "integrity" "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==" + "resolved" "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz" + "version" "7.12.9" dependencies: "@babel/code-frame" "^7.10.4" "@babel/generator" "^7.12.5" @@ -162,74 +184,55 @@ "@babel/template" "^7.12.7" "@babel/traverse" "^7.12.9" "@babel/types" "^7.12.7" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.1" - json5 "^2.1.2" - lodash "^4.17.19" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - -"@babel/core@^7.15.5", "@babel/core@^7.16.0": - version "7.17.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.5.tgz#6cd2e836058c28f06a4ca8ee7ed955bbf37c8225" - integrity sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA== - dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.3" - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helpers" "^7.17.2" - "@babel/parser" "^7.17.3" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.3" - "@babel/types" "^7.17.0" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.1.2" - semver "^6.3.0" - -"@babel/generator@^7.12.5", "@babel/generator@^7.16.0", "@babel/generator@^7.17.3": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.3.tgz#a2c30b0c4f89858cb87050c3ffdfd36bdf443200" - integrity sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg== - dependencies: - "@babel/types" "^7.17.0" - jsesc "^2.5.1" - source-map "^0.5.0" + "convert-source-map" "^1.7.0" + "debug" "^4.1.0" + "gensync" "^1.0.0-beta.1" + "json5" "^2.1.2" + "lodash" "^4.17.19" + "resolve" "^1.3.2" + "semver" "^5.4.1" + "source-map" "^0.5.0" + +"@babel/generator@^7.12.5", "@babel/generator@^7.16.0", "@babel/generator@^7.21.3": + "integrity" "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==" + "resolved" "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz" + "version" "7.21.3" + dependencies: + "@babel/types" "^7.21.3" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + "jsesc" "^2.5.1" "@babel/helper-annotate-as-pure@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862" - integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw== + "integrity" "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==" + "resolved" "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/types" "^7.16.7" "@babel/helper-builder-binary-assignment-operator-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz#38d138561ea207f0f69eb1626a418e4f7e6a580b" - integrity sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA== + "integrity" "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==" + "resolved" "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-explode-assignable-expression" "^7.16.7" "@babel/types" "^7.16.7" -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b" - integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA== +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7", "@babel/helper-compilation-targets@^7.20.7": + "integrity" "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz" + "version" "7.20.7" dependencies: - "@babel/compat-data" "^7.16.4" - "@babel/helper-validator-option" "^7.16.7" - browserslist "^4.17.5" - semver "^6.3.0" + "@babel/compat-data" "^7.20.5" + "@babel/helper-validator-option" "^7.18.6" + "browserslist" "^4.21.3" + "lru-cache" "^5.1.1" + "semver" "^6.3.0" "@babel/helper-create-class-features-plugin@^7.16.10", "@babel/helper-create-class-features-plugin@^7.16.7": - version "7.17.1" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.1.tgz#9699f14a88833a7e055ce57dcd3ffdcd25186b21" - integrity sha512-JBdSr/LtyYIno/pNnJ75lBcqc3Z1XXujzPanHqjvvrhOA+DTceTFuJi8XjmWTZh4r3fsdfqaCMN0iZemdkxZHQ== + "integrity" "sha512-JBdSr/LtyYIno/pNnJ75lBcqc3Z1XXujzPanHqjvvrhOA+DTceTFuJi8XjmWTZh4r3fsdfqaCMN0iZemdkxZHQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.1.tgz" + "version" "7.17.1" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-environment-visitor" "^7.16.7" @@ -240,122 +243,112 @@ "@babel/helper-split-export-declaration" "^7.16.7" "@babel/helper-create-regexp-features-plugin@^7.16.7": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz#1dcc7d40ba0c6b6b25618997c5dbfd310f186fe1" - integrity sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA== + "integrity" "sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==" + "resolved" "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz" + "version" "7.17.0" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" - regexpu-core "^5.0.1" + "regexpu-core" "^5.0.1" "@babel/helper-define-polyfill-provider@^0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz#52411b445bdb2e676869e5a74960d2d3826d2665" - integrity sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA== + "integrity" "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==" + "resolved" "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz" + "version" "0.3.1" dependencies: "@babel/helper-compilation-targets" "^7.13.0" "@babel/helper-module-imports" "^7.12.13" "@babel/helper-plugin-utils" "^7.13.0" "@babel/traverse" "^7.13.0" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" - semver "^6.1.2" + "debug" "^4.1.1" + "lodash.debounce" "^4.0.8" + "resolve" "^1.14.2" + "semver" "^6.1.2" -"@babel/helper-environment-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" - integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== - dependencies: - "@babel/types" "^7.16.7" +"@babel/helper-environment-visitor@^7.16.7", "@babel/helper-environment-visitor@^7.18.9": + "integrity" "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==" + "resolved" "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz" + "version" "7.18.9" "@babel/helper-explode-assignable-expression@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz#12a6d8522fdd834f194e868af6354e8650242b7a" - integrity sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ== + "integrity" "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/types" "^7.16.7" -"@babel/helper-function-name@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" - integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== +"@babel/helper-function-name@^7.16.7", "@babel/helper-function-name@^7.21.0": + "integrity" "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==" + "resolved" "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz" + "version" "7.21.0" dependencies: - "@babel/helper-get-function-arity" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/types" "^7.16.7" + "@babel/template" "^7.20.7" + "@babel/types" "^7.21.0" -"@babel/helper-get-function-arity@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419" - integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== +"@babel/helper-hoist-variables@^7.16.7", "@babel/helper-hoist-variables@^7.18.6": + "integrity" "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==" + "resolved" "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz" + "version" "7.18.6" dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-hoist-variables@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" - integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== - dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.18.6" "@babel/helper-member-expression-to-functions@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz#42b9ca4b2b200123c3b7e726b0ae5153924905b0" - integrity sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q== + "integrity" "sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==" + "resolved" "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/types" "^7.16.7" -"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" - integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== +"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.18.6": + "integrity" "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==" + "resolved" "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz" + "version" "7.18.6" dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.18.6" -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz#7665faeb721a01ca5327ddc6bba15a5cb34b6a41" - integrity sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng== +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.16.7", "@babel/helper-module-transforms@^7.21.2": + "integrity" "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz" + "version" "7.21.2" dependencies: - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-simple-access" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/helper-validator-identifier" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.16.7" - "@babel/types" "^7.16.7" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.20.2" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.19.1" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.21.2" + "@babel/types" "^7.21.2" "@babel/helper-optimise-call-expression@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz#a34e3560605abbd31a18546bd2aad3e6d9a174f2" - integrity sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w== + "integrity" "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==" + "resolved" "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/types" "^7.16.7" -"@babel/helper-plugin-utils@7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" - integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== - "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" - integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== + "integrity" "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==" + "resolved" "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz" + "version" "7.16.7" + +"@babel/helper-plugin-utils@7.10.4": + "integrity" "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" + "resolved" "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz" + "version" "7.10.4" "@babel/helper-remap-async-to-generator@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz#29ffaade68a367e2ed09c90901986918d25e57e3" - integrity sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw== + "integrity" "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==" + "resolved" "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-wrap-function" "^7.16.8" "@babel/types" "^7.16.8" "@babel/helper-replace-supers@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz#e9f5f5f32ac90429c1a4bdec0f231ef0c2838ab1" - integrity sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw== + "integrity" "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==" + "resolved" "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-environment-visitor" "^7.16.7" "@babel/helper-member-expression-to-functions" "^7.16.7" @@ -363,173 +356,169 @@ "@babel/traverse" "^7.16.7" "@babel/types" "^7.16.7" -"@babel/helper-simple-access@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7" - integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g== +"@babel/helper-simple-access@^7.16.7", "@babel/helper-simple-access@^7.20.2": + "integrity" "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==" + "resolved" "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz" + "version" "7.20.2" dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.20.2" "@babel/helper-skip-transparent-expression-wrappers@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz#0ee3388070147c3ae051e487eca3ebb0e2e8bb09" - integrity sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw== + "integrity" "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==" + "resolved" "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz" + "version" "7.16.0" dependencies: "@babel/types" "^7.16.0" -"@babel/helper-split-export-declaration@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" - integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== +"@babel/helper-split-export-declaration@^7.16.7", "@babel/helper-split-export-declaration@^7.18.6": + "integrity" "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==" + "resolved" "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz" + "version" "7.18.6" dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.18.6" -"@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== +"@babel/helper-string-parser@^7.19.4": + "integrity" "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==" + "resolved" "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz" + "version" "7.19.4" -"@babel/helper-validator-option@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" - integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== +"@babel/helper-validator-identifier@^7.16.7", "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": + "integrity" "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==" + "resolved" "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz" + "version" "7.19.1" + +"@babel/helper-validator-option@^7.16.7", "@babel/helper-validator-option@^7.18.6": + "integrity" "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz" + "version" "7.21.0" "@babel/helper-wrap-function@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz#58afda087c4cd235de92f7ceedebca2c41274200" - integrity sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw== + "integrity" "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==" + "resolved" "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-function-name" "^7.16.7" "@babel/template" "^7.16.7" "@babel/traverse" "^7.16.8" "@babel/types" "^7.16.8" -"@babel/helpers@^7.12.5", "@babel/helpers@^7.17.2": - version "7.17.2" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.2.tgz#23f0a0746c8e287773ccd27c14be428891f63417" - integrity sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ== +"@babel/helpers@^7.12.5", "@babel/helpers@^7.21.0": + "integrity" "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==" + "resolved" "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz" + "version" "7.21.0" dependencies: - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.0" - "@babel/types" "^7.17.0" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.21.0" + "@babel/types" "^7.21.0" -"@babel/highlight@^7.16.7": - version "7.16.10" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" - integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== +"@babel/highlight@^7.18.6": + "integrity" "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==" + "resolved" "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz" + "version" "7.18.6" dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - chalk "^2.0.0" - js-tokens "^4.0.0" + "@babel/helper-validator-identifier" "^7.18.6" + "chalk" "^2.0.0" + "js-tokens" "^4.0.0" -"@babel/parser@^7.12.7", "@babel/parser@^7.16.4", "@babel/parser@^7.16.7", "@babel/parser@^7.17.3": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.3.tgz#b07702b982990bf6fdc1da5049a23fece4c5c3d0" - integrity sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA== +"@babel/parser@^7.12.7", "@babel/parser@^7.16.4", "@babel/parser@^7.20.7", "@babel/parser@^7.21.3": + "integrity" "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==" + "resolved" "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz" + "version" "7.21.3" "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz#4eda6d6c2a0aa79c70fa7b6da67763dfe2141050" - integrity sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg== + "integrity" "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz#cc001234dfc139ac45f6bcf801866198c8c72ff9" - integrity sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw== + "integrity" "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-proposal-optional-chaining" "^7.16.7" "@babel/plugin-proposal-async-generator-functions@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz#3bdd1ebbe620804ea9416706cd67d60787504bc8" - integrity sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ== + "integrity" "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-remap-async-to-generator" "^7.16.8" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-proposal-class-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz#925cad7b3b1a2fcea7e59ecc8eb5954f961f91b0" - integrity sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww== + "integrity" "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-create-class-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-proposal-class-static-block@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz#712357570b612106ef5426d13dc433ce0f200c2a" - integrity sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw== + "integrity" "sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-create-class-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-proposal-dynamic-import@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz#c19c897eaa46b27634a00fee9fb7d829158704b2" - integrity sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg== + "integrity" "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-proposal-export-namespace-from@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz#09de09df18445a5786a305681423ae63507a6163" - integrity sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA== + "integrity" "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" "@babel/plugin-proposal-json-strings@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz#9732cb1d17d9a2626a08c5be25186c195b6fa6e8" - integrity sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ== + "integrity" "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-proposal-logical-assignment-operators@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz#be23c0ba74deec1922e639832904be0bea73cdea" - integrity sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg== + "integrity" "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-proposal-nullish-coalescing-operator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz#141fc20b6857e59459d430c850a0011e36561d99" - integrity sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ== + "integrity" "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" "@babel/plugin-proposal-numeric-separator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz#d6b69f4af63fb38b6ca2558442a7fb191236eba9" - integrity sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw== + "integrity" "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz#def9bd03cea0f9b72283dac0ec22d289c7691069" - integrity sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.12.1" - "@babel/plugin-proposal-object-rest-spread@^7.16.7": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz#d9eb649a54628a51701aef7e0ea3d17e2b9dd390" - integrity sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw== + "integrity" "sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz" + "version" "7.17.3" dependencies: "@babel/compat-data" "^7.17.0" "@babel/helper-compilation-targets" "^7.16.7" @@ -537,35 +526,44 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-transform-parameters" "^7.16.7" +"@babel/plugin-proposal-object-rest-spread@7.12.1": + "integrity" "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz" + "version" "7.12.1" + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-transform-parameters" "^7.12.1" + "@babel/plugin-proposal-optional-catch-binding@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz#c623a430674ffc4ab732fd0a0ae7722b67cb74cf" - integrity sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA== + "integrity" "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-proposal-optional-chaining@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz#7cd629564724816c0e8a969535551f943c64c39a" - integrity sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA== + "integrity" "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-proposal-private-methods@^7.16.11": - version "7.16.11" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz#e8df108288555ff259f4527dbe84813aac3a1c50" - integrity sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw== + "integrity" "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz" + "version" "7.16.11" dependencies: "@babel/helper-create-class-features-plugin" "^7.16.10" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-proposal-private-property-in-object@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz#b0b8cef543c2c3d57e59e2c611994861d46a3fce" - integrity sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ== + "integrity" "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-create-class-features-plugin" "^7.16.7" @@ -573,166 +571,166 @@ "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-proposal-unicode-property-regex@^7.16.7", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz#635d18eb10c6214210ffc5ff4932552de08188a2" - integrity sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg== + "integrity" "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + "integrity" "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" + "version" "7.8.4" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-class-properties@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + "integrity" "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" + "version" "7.12.13" dependencies: "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-class-static-block@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" - integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + "integrity" "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz" + "version" "7.14.5" dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-dynamic-import@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" - integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + "integrity" "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-export-namespace-from@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" - integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + "integrity" "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + "integrity" "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz#9d9d357cc818aa7ae7935917c1257f67677a0926" - integrity sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-jsx@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz#50b6571d13f764266a113d77c82b4a6508bbe665" - integrity sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q== + "integrity" "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" +"@babel/plugin-syntax-jsx@7.12.1": + "integrity" "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz" + "version" "7.12.1" + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + "integrity" "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" + "version" "7.10.4" dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + "integrity" "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-numeric-separator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + "integrity" "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" + "version" "7.10.4" dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-object-rest-spread@7.8.3", "@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== +"@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3", "@babel/plugin-syntax-object-rest-spread@7.8.3": + "integrity" "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + "integrity" "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + "integrity" "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-private-property-in-object@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" - integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + "integrity" "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz" + "version" "7.14.5" dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-top-level-await@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + "integrity" "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz" + "version" "7.14.5" dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz#39c9b55ee153151990fb038651d58d3fd03f98f8" - integrity sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A== + "integrity" "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-arrow-functions@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz#44125e653d94b98db76369de9c396dc14bef4154" - integrity sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ== + "integrity" "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-async-to-generator@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz#b83dff4b970cf41f1b819f8b49cc0cfbaa53a808" - integrity sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg== + "integrity" "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-module-imports" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-remap-async-to-generator" "^7.16.8" "@babel/plugin-transform-block-scoped-functions@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz#4d0d57d9632ef6062cdf354bb717102ee042a620" - integrity sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg== + "integrity" "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-block-scoping@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz#f50664ab99ddeaee5bc681b8f3a6ea9d72ab4f87" - integrity sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ== + "integrity" "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-classes@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz#8f4b9562850cd973de3b498f1218796eb181ce00" - integrity sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ== + "integrity" "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-environment-visitor" "^7.16.7" @@ -741,174 +739,174 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-replace-supers" "^7.16.7" "@babel/helper-split-export-declaration" "^7.16.7" - globals "^11.1.0" + "globals" "^11.1.0" "@babel/plugin-transform-computed-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz#66dee12e46f61d2aae7a73710f591eb3df616470" - integrity sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw== + "integrity" "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-destructuring@^7.16.7": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz#c445f75819641788a27a0a3a759d9df911df6abc" - integrity sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg== + "integrity" "sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz" + "version" "7.17.3" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-dotall-regex@^7.16.7", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz#6b2d67686fab15fb6a7fd4bd895d5982cfc81241" - integrity sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ== + "integrity" "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-duplicate-keys@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz#2207e9ca8f82a0d36a5a67b6536e7ef8b08823c9" - integrity sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw== + "integrity" "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-exponentiation-operator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz#efa9862ef97e9e9e5f653f6ddc7b665e8536fe9b" - integrity sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA== + "integrity" "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-for-of@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz#649d639d4617dff502a9a158c479b3b556728d8c" - integrity sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg== + "integrity" "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-function-name@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz#5ab34375c64d61d083d7d2f05c38d90b97ec65cf" - integrity sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA== + "integrity" "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-compilation-targets" "^7.16.7" "@babel/helper-function-name" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz#254c9618c5ff749e87cb0c0cef1a0a050c0bdab1" - integrity sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ== + "integrity" "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-member-expression-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz#6e5dcf906ef8a098e630149d14c867dd28f92384" - integrity sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw== + "integrity" "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-modules-amd@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz#b28d323016a7daaae8609781d1f8c9da42b13186" - integrity sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g== + "integrity" "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-module-transforms" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" - babel-plugin-dynamic-import-node "^2.3.3" + "babel-plugin-dynamic-import-node" "^2.3.3" "@babel/plugin-transform-modules-commonjs@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz#cdee19aae887b16b9d331009aa9a219af7c86afe" - integrity sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA== + "integrity" "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-module-transforms" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-simple-access" "^7.16.7" - babel-plugin-dynamic-import-node "^2.3.3" + "babel-plugin-dynamic-import-node" "^2.3.3" "@babel/plugin-transform-modules-systemjs@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz#887cefaef88e684d29558c2b13ee0563e287c2d7" - integrity sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw== + "integrity" "sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-hoist-variables" "^7.16.7" "@babel/helper-module-transforms" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-validator-identifier" "^7.16.7" - babel-plugin-dynamic-import-node "^2.3.3" + "babel-plugin-dynamic-import-node" "^2.3.3" "@babel/plugin-transform-modules-umd@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz#23dad479fa585283dbd22215bff12719171e7618" - integrity sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ== + "integrity" "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-module-transforms" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-named-capturing-groups-regex@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz#7f860e0e40d844a02c9dcf9d84965e7dfd666252" - integrity sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw== + "integrity" "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/plugin-transform-new-target@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz#9967d89a5c243818e0800fdad89db22c5f514244" - integrity sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg== + "integrity" "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-object-super@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz#ac359cf8d32cf4354d27a46867999490b6c32a94" - integrity sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw== + "integrity" "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-replace-supers" "^7.16.7" "@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz#a1721f55b99b736511cb7e0152f61f17688f331f" - integrity sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw== + "integrity" "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-property-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz#2dadac85155436f22c696c4827730e0fe1057a55" - integrity sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw== + "integrity" "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-react-constant-elements@^7.14.5": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.16.7.tgz#19e9e4c2df2f6c3e6b3aea11778297d81db8df62" - integrity sha512-lF+cfsyTgwWkcw715J88JhMYJ5GpysYNLhLP1PkvkhTRN7B3e74R/1KsDxFxhRpSn0UUD3IWM4GvdBR2PEbbQQ== + "integrity" "sha512-lF+cfsyTgwWkcw715J88JhMYJ5GpysYNLhLP1PkvkhTRN7B3e74R/1KsDxFxhRpSn0UUD3IWM4GvdBR2PEbbQQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-react-display-name@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz#7b6d40d232f4c0f550ea348593db3b21e2404340" - integrity sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg== + "integrity" "sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-react-jsx-development@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz#43a00724a3ed2557ed3f276a01a929e6686ac7b8" - integrity sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A== + "integrity" "sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/plugin-transform-react-jsx" "^7.16.7" "@babel/plugin-transform-react-jsx@^7.16.7": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz#eac1565da176ccb1a715dae0b4609858808008c1" - integrity sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ== + "integrity" "sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz" + "version" "7.17.3" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-module-imports" "^7.16.7" @@ -917,103 +915,103 @@ "@babel/types" "^7.17.0" "@babel/plugin-transform-react-pure-annotations@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz#232bfd2f12eb551d6d7d01d13fe3f86b45eb9c67" - integrity sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA== + "integrity" "sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-regenerator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz#9e7576dc476cb89ccc5096fff7af659243b4adeb" - integrity sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q== + "integrity" "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz" + "version" "7.16.7" dependencies: - regenerator-transform "^0.14.2" + "regenerator-transform" "^0.14.2" "@babel/plugin-transform-reserved-words@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz#1d798e078f7c5958eec952059c460b220a63f586" - integrity sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg== + "integrity" "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-runtime@^7.16.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz#0a2e08b5e2b2d95c4b1d3b3371a2180617455b70" - integrity sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A== + "integrity" "sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz" + "version" "7.17.0" dependencies: "@babel/helper-module-imports" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" - babel-plugin-polyfill-corejs2 "^0.3.0" - babel-plugin-polyfill-corejs3 "^0.5.0" - babel-plugin-polyfill-regenerator "^0.3.0" - semver "^6.3.0" + "babel-plugin-polyfill-corejs2" "^0.3.0" + "babel-plugin-polyfill-corejs3" "^0.5.0" + "babel-plugin-polyfill-regenerator" "^0.3.0" + "semver" "^6.3.0" "@babel/plugin-transform-shorthand-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz#e8549ae4afcf8382f711794c0c7b6b934c5fbd2a" - integrity sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg== + "integrity" "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-spread@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz#a303e2122f9f12e0105daeedd0f30fb197d8ff44" - integrity sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg== + "integrity" "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-transform-sticky-regex@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz#c84741d4f4a38072b9a1e2e3fd56d359552e8660" - integrity sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw== + "integrity" "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-template-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz#f3d1c45d28967c8e80f53666fc9c3e50618217ab" - integrity sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA== + "integrity" "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-typeof-symbol@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz#9cdbe622582c21368bd482b660ba87d5545d4f7e" - integrity sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ== + "integrity" "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-typescript@^7.16.7": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz#591ce9b6b83504903fa9dd3652c357c2ba7a1ee0" - integrity sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ== + "integrity" "sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-create-class-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-typescript" "^7.16.7" "@babel/plugin-transform-unicode-escapes@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz#da8717de7b3287a2c6d659750c964f302b31ece3" - integrity sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q== + "integrity" "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-unicode-regex@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz#0f7aa4a501198976e25e82702574c34cfebe9ef2" - integrity sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q== + "integrity" "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/preset-env@^7.15.6", "@babel/preset-env@^7.16.4": - version "7.16.11" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.11.tgz#5dd88fd885fae36f88fd7c8342475c9f0abe2982" - integrity sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g== + "integrity" "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==" + "resolved" "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz" + "version" "7.16.11" dependencies: "@babel/compat-data" "^7.16.8" "@babel/helper-compilation-targets" "^7.16.7" @@ -1084,27 +1082,27 @@ "@babel/plugin-transform-unicode-regex" "^7.16.7" "@babel/preset-modules" "^0.1.5" "@babel/types" "^7.16.8" - babel-plugin-polyfill-corejs2 "^0.3.0" - babel-plugin-polyfill-corejs3 "^0.5.0" - babel-plugin-polyfill-regenerator "^0.3.0" - core-js-compat "^3.20.2" - semver "^6.3.0" + "babel-plugin-polyfill-corejs2" "^0.3.0" + "babel-plugin-polyfill-corejs3" "^0.5.0" + "babel-plugin-polyfill-regenerator" "^0.3.0" + "core-js-compat" "^3.20.2" + "semver" "^6.3.0" "@babel/preset-modules@^0.1.5": - version "0.1.5" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" - integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== + "integrity" "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==" + "resolved" "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz" + "version" "0.1.5" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" "@babel/plugin-transform-dotall-regex" "^7.4.4" "@babel/types" "^7.4.4" - esutils "^2.0.2" + "esutils" "^2.0.2" "@babel/preset-react@^7.14.5", "@babel/preset-react@^7.16.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.16.7.tgz#4c18150491edc69c183ff818f9f2aecbe5d93852" - integrity sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA== + "integrity" "sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA==" + "resolved" "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-validator-option" "^7.16.7" @@ -1114,81 +1112,82 @@ "@babel/plugin-transform-react-pure-annotations" "^7.16.7" "@babel/preset-typescript@^7.15.0", "@babel/preset-typescript@^7.16.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz#ab114d68bb2020afc069cd51b37ff98a046a70b9" - integrity sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ== + "integrity" "sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==" + "resolved" "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-validator-option" "^7.16.7" "@babel/plugin-transform-typescript" "^7.16.7" "@babel/runtime-corejs3@^7.16.3": - version "7.17.2" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.17.2.tgz#fdca2cd05fba63388babe85d349b6801b008fd13" - integrity sha512-NcKtr2epxfIrNM4VOmPKO46TvDMCBhgi2CrSHaEarrz+Plk2K5r9QemmOFTGpZaoKnWoGH5MO+CzeRsih/Fcgg== + "integrity" "sha512-NcKtr2epxfIrNM4VOmPKO46TvDMCBhgi2CrSHaEarrz+Plk2K5r9QemmOFTGpZaoKnWoGH5MO+CzeRsih/Fcgg==" + "resolved" "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.17.2.tgz" + "version" "7.17.2" dependencies: - core-js-pure "^3.20.2" - regenerator-runtime "^0.13.4" + "core-js-pure" "^3.20.2" + "regenerator-runtime" "^0.13.4" "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.16.3", "@babel/runtime@^7.8.4": - version "7.17.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941" - integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/template@^7.12.7", "@babel/template@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" - integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.16.3", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.17.0", "@babel/traverse@^7.17.3": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57" - integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.3" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.17.3" - "@babel/types" "^7.17.0" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/types@^7.12.7", "@babel/types@^7.15.6", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.4.4": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" - integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - to-fast-properties "^2.0.0" + "integrity" "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==" + "resolved" "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz" + "version" "7.17.2" + dependencies: + "regenerator-runtime" "^0.13.4" + +"@babel/template@^7.12.7", "@babel/template@^7.16.7", "@babel/template@^7.20.7": + "integrity" "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==" + "resolved" "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz" + "version" "7.20.7" + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + +"@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.16.3", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2", "@babel/traverse@^7.21.3": + "integrity" "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==" + "resolved" "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz" + "version" "7.21.3" + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.21.3" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.21.0" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.21.3" + "@babel/types" "^7.21.3" + "debug" "^4.1.0" + "globals" "^11.1.0" + +"@babel/types@^7.12.7", "@babel/types@^7.15.6", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.18.6", "@babel/types@^7.20.2", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.2", "@babel/types@^7.21.3", "@babel/types@^7.4.4": + "integrity" "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==" + "resolved" "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz" + "version" "7.21.3" + dependencies: + "@babel/helper-string-parser" "^7.19.4" + "@babel/helper-validator-identifier" "^7.19.1" + "to-fast-properties" "^2.0.0" "@docsearch/css@3.0.0-alpha.50": - version "3.0.0-alpha.50" - resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.0.0-alpha.50.tgz#794c6a8d301840a49b55f5b331c7be84b9723643" - integrity sha512-QeWFCQOtS9D+Fi20liKsPXF2j/xWKh52e+P2Z1UATIdPMqmH6zoB2lcUz+cgv6PPVgWUtECeR6VSSUm71LT94w== + "integrity" "sha512-QeWFCQOtS9D+Fi20liKsPXF2j/xWKh52e+P2Z1UATIdPMqmH6zoB2lcUz+cgv6PPVgWUtECeR6VSSUm71LT94w==" + "resolved" "https://registry.npmjs.org/@docsearch/css/-/css-3.0.0-alpha.50.tgz" + "version" "3.0.0-alpha.50" "@docsearch/react@^3.0.0-alpha.39": - version "3.0.0-alpha.50" - resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.0.0-alpha.50.tgz#a7dc547836c2b221fd3aa8eb87bfb47a579ef141" - integrity sha512-oDGV1zZCRYv7MWsh6CyQVthYTRc3b4q+6kKwNYb1/g/Wf/4nJHutpxolFLHdEUDhrJ4Xi8wxwQG+lEwAVBTHPg== + "integrity" "sha512-oDGV1zZCRYv7MWsh6CyQVthYTRc3b4q+6kKwNYb1/g/Wf/4nJHutpxolFLHdEUDhrJ4Xi8wxwQG+lEwAVBTHPg==" + "resolved" "https://registry.npmjs.org/@docsearch/react/-/react-3.0.0-alpha.50.tgz" + "version" "3.0.0-alpha.50" dependencies: "@algolia/autocomplete-core" "1.5.2" "@algolia/autocomplete-preset-algolia" "1.5.2" "@docsearch/css" "3.0.0-alpha.50" - algoliasearch "^4.0.0" + "algoliasearch" "^4.0.0" "@docusaurus/core@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.0.0-beta.15.tgz#1a3f8361803767072e56c77d60332c87e59f1ad0" - integrity sha512-zXhhD0fApMSvq/9Pkm9DQxa//hGOXVCq9yMHiXOkI5D1tLec7PxtnaC5cLfGHljkN9cKIfRDYUVcG1gHymVfpA== + "integrity" "sha512-zXhhD0fApMSvq/9Pkm9DQxa//hGOXVCq9yMHiXOkI5D1tLec7PxtnaC5cLfGHljkN9cKIfRDYUVcG1gHymVfpA==" + "resolved" "https://registry.npmjs.org/@docusaurus/core/-/core-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@babel/core" "^7.16.0" "@babel/generator" "^7.16.0" @@ -1209,103 +1208,103 @@ "@docusaurus/utils-validation" "2.0.0-beta.15" "@slorber/static-site-generator-webpack-plugin" "^4.0.0" "@svgr/webpack" "^6.0.0" - autoprefixer "^10.3.5" - babel-loader "^8.2.2" - babel-plugin-dynamic-import-node "2.3.0" - boxen "^5.0.1" - chokidar "^3.5.2" - clean-css "^5.1.5" - commander "^5.1.0" - copy-webpack-plugin "^10.2.0" - core-js "^3.18.0" - css-loader "^6.5.1" - css-minimizer-webpack-plugin "^3.3.1" - cssnano "^5.0.8" - del "^6.0.0" - detect-port "^1.3.0" - escape-html "^1.0.3" - eta "^1.12.3" - file-loader "^6.2.0" - fs-extra "^10.0.0" - html-minifier-terser "^6.0.2" - html-tags "^3.1.0" - html-webpack-plugin "^5.4.0" - import-fresh "^3.3.0" - is-root "^2.1.0" - leven "^3.1.0" - lodash "^4.17.20" - mini-css-extract-plugin "^1.6.0" - nprogress "^0.2.0" - postcss "^8.3.7" - postcss-loader "^6.1.1" - prompts "^2.4.1" - react-dev-utils "^12.0.0" - react-helmet "^6.1.0" - react-loadable "npm:@docusaurus/react-loadable@5.5.2" - react-loadable-ssr-addon-v5-slorber "^1.0.1" - react-router "^5.2.0" - react-router-config "^5.1.1" - react-router-dom "^5.2.0" - remark-admonitions "^1.2.1" - rtl-detect "^1.0.4" - semver "^7.3.4" - serve-handler "^6.1.3" - shelljs "^0.8.4" - strip-ansi "^6.0.0" - terser-webpack-plugin "^5.2.4" - tslib "^2.3.1" - update-notifier "^5.1.0" - url-loader "^4.1.1" - wait-on "^6.0.0" - webpack "^5.61.0" - webpack-bundle-analyzer "^4.4.2" - webpack-dev-server "^4.7.1" - webpack-merge "^5.8.0" - webpackbar "^5.0.2" + "autoprefixer" "^10.3.5" + "babel-loader" "^8.2.2" + "babel-plugin-dynamic-import-node" "2.3.0" + "boxen" "^5.0.1" + "chokidar" "^3.5.2" + "clean-css" "^5.1.5" + "commander" "^5.1.0" + "copy-webpack-plugin" "^10.2.0" + "core-js" "^3.18.0" + "css-loader" "^6.5.1" + "css-minimizer-webpack-plugin" "^3.3.1" + "cssnano" "^5.0.8" + "del" "^6.0.0" + "detect-port" "^1.3.0" + "escape-html" "^1.0.3" + "eta" "^1.12.3" + "file-loader" "^6.2.0" + "fs-extra" "^10.0.0" + "html-minifier-terser" "^6.0.2" + "html-tags" "^3.1.0" + "html-webpack-plugin" "^5.4.0" + "import-fresh" "^3.3.0" + "is-root" "^2.1.0" + "leven" "^3.1.0" + "lodash" "^4.17.20" + "mini-css-extract-plugin" "^1.6.0" + "nprogress" "^0.2.0" + "postcss" "^8.3.7" + "postcss-loader" "^6.1.1" + "prompts" "^2.4.1" + "react-dev-utils" "^12.0.0" + "react-helmet" "^6.1.0" + "react-loadable" "npm:@docusaurus/react-loadable@5.5.2" + "react-loadable-ssr-addon-v5-slorber" "^1.0.1" + "react-router" "^5.2.0" + "react-router-config" "^5.1.1" + "react-router-dom" "^5.2.0" + "remark-admonitions" "^1.2.1" + "rtl-detect" "^1.0.4" + "semver" "^7.3.4" + "serve-handler" "^6.1.3" + "shelljs" "^0.8.4" + "strip-ansi" "^6.0.0" + "terser-webpack-plugin" "^5.2.4" + "tslib" "^2.3.1" + "update-notifier" "^5.1.0" + "url-loader" "^4.1.1" + "wait-on" "^6.0.0" + "webpack" "^5.61.0" + "webpack-bundle-analyzer" "^4.4.2" + "webpack-dev-server" "^4.7.1" + "webpack-merge" "^5.8.0" + "webpackbar" "^5.0.2" "@docusaurus/cssnano-preset@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-beta.15.tgz#033c52815c428f0f66c87eaff93ea12554ea89df" - integrity sha512-55aYURbB5dqrx64lStNcZxDx5R6bKkAawlCB7mDKx3r+Qnp3ofGW7UExLQSCbTu3axT1vJCF5D7H6ljTRYJLtA== + "integrity" "sha512-55aYURbB5dqrx64lStNcZxDx5R6bKkAawlCB7mDKx3r+Qnp3ofGW7UExLQSCbTu3axT1vJCF5D7H6ljTRYJLtA==" + "resolved" "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: - cssnano-preset-advanced "^5.1.4" - postcss "^8.3.7" - postcss-sort-media-queries "^4.1.0" + "cssnano-preset-advanced" "^5.1.4" + "postcss" "^8.3.7" + "postcss-sort-media-queries" "^4.1.0" "@docusaurus/logger@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-2.0.0-beta.15.tgz#6d17a05fb292d15fdc43b5fa90fd2a49ad5d40ce" - integrity sha512-5bDSHCyLfMtz6QnFfICdL5mgxbGfC7DW1V+/Q17nRdpZSPZgsNKK/Esp0zdDi1oxAyEpXMXx64nLaHL7joJxIg== + "integrity" "sha512-5bDSHCyLfMtz6QnFfICdL5mgxbGfC7DW1V+/Q17nRdpZSPZgsNKK/Esp0zdDi1oxAyEpXMXx64nLaHL7joJxIg==" + "resolved" "https://registry.npmjs.org/@docusaurus/logger/-/logger-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: - chalk "^4.1.2" - tslib "^2.3.1" + "chalk" "^4.1.2" + "tslib" "^2.3.1" "@docusaurus/mdx-loader@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-beta.15.tgz#da23745bc73c93338dd330dad6bbc9d9fe325553" - integrity sha512-MVpytjDDao7hmPF1QSs9B5zoTgevZjiqjnX3FM1yjqdCv+chyUo0gnmYHjeG/4Gqu7jucp+dDdp6yQpzs4g09A== + "integrity" "sha512-MVpytjDDao7hmPF1QSs9B5zoTgevZjiqjnX3FM1yjqdCv+chyUo0gnmYHjeG/4Gqu7jucp+dDdp6yQpzs4g09A==" + "resolved" "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@babel/parser" "^7.16.4" "@babel/traverse" "^7.16.3" "@docusaurus/logger" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" "@mdx-js/mdx" "^1.6.21" - escape-html "^1.0.3" - file-loader "^6.2.0" - fs-extra "^10.0.0" - image-size "^1.0.1" - mdast-util-to-string "^2.0.0" - remark-emoji "^2.1.0" - stringify-object "^3.3.0" - tslib "^2.3.1" - unist-util-visit "^2.0.2" - url-loader "^4.1.1" - webpack "^5.61.0" + "escape-html" "^1.0.3" + "file-loader" "^6.2.0" + "fs-extra" "^10.0.0" + "image-size" "^1.0.1" + "mdast-util-to-string" "^2.0.0" + "remark-emoji" "^2.1.0" + "stringify-object" "^3.3.0" + "tslib" "^2.3.1" + "unist-util-visit" "^2.0.2" + "url-loader" "^4.1.1" + "webpack" "^5.61.0" "@docusaurus/plugin-content-blog@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.15.tgz#6d4bf532ad3dedb4f9fd6398b0fbe481af5b77a9" - integrity sha512-VtEwkgkoNIS8JFPe+huBeBuJ8HG8Lq1JNYM/ItwQg/cwGAgP8EgwbEuKDn428oZKEI2PpgAuf5Gv4AzJWIes9A== + "integrity" "sha512-VtEwkgkoNIS8JFPe+huBeBuJ8HG8Lq1JNYM/ItwQg/cwGAgP8EgwbEuKDn428oZKEI2PpgAuf5Gv4AzJWIes9A==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/logger" "2.0.0-beta.15" @@ -1313,98 +1312,98 @@ "@docusaurus/utils" "2.0.0-beta.15" "@docusaurus/utils-common" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - cheerio "^1.0.0-rc.10" - feed "^4.2.2" - fs-extra "^10.0.0" - lodash "^4.17.20" - reading-time "^1.5.0" - remark-admonitions "^1.2.1" - tslib "^2.3.1" - utility-types "^3.10.0" - webpack "^5.61.0" + "cheerio" "^1.0.0-rc.10" + "feed" "^4.2.2" + "fs-extra" "^10.0.0" + "lodash" "^4.17.20" + "reading-time" "^1.5.0" + "remark-admonitions" "^1.2.1" + "tslib" "^2.3.1" + "utility-types" "^3.10.0" + "webpack" "^5.61.0" "@docusaurus/plugin-content-docs@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-beta.15.tgz#9486bba8abd2a6284e749718bf56743d8e4446f1" - integrity sha512-HSwNZdUKz4rpJiGbFjl/OFhSleeZUSZ6E6lk98i4iL1A5u6fIm4CHsT53yp4UUOse+lFrePTFZsyqwMA4nZZYA== + "integrity" "sha512-HSwNZdUKz4rpJiGbFjl/OFhSleeZUSZ6E6lk98i4iL1A5u6fIm4CHsT53yp4UUOse+lFrePTFZsyqwMA4nZZYA==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/logger" "2.0.0-beta.15" "@docusaurus/mdx-loader" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - combine-promises "^1.1.0" - fs-extra "^10.0.0" - import-fresh "^3.2.2" - js-yaml "^4.0.0" - lodash "^4.17.20" - remark-admonitions "^1.2.1" - shelljs "^0.8.4" - tslib "^2.3.1" - utility-types "^3.10.0" - webpack "^5.61.0" + "combine-promises" "^1.1.0" + "fs-extra" "^10.0.0" + "import-fresh" "^3.2.2" + "js-yaml" "^4.0.0" + "lodash" "^4.17.20" + "remark-admonitions" "^1.2.1" + "shelljs" "^0.8.4" + "tslib" "^2.3.1" + "utility-types" "^3.10.0" + "webpack" "^5.61.0" "@docusaurus/plugin-content-pages@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-beta.15.tgz#e488f7dcdd45cd1d46e8c2c5ff5275327a6a3c65" - integrity sha512-N7YhW5RiOY6J228z4lOoP//qX0Q48cRtxDONZ/Ohd9C5OI2vS6TD8iQuDqOIYHxH+BshjNSsKvbJ+SMIQDwysg== + "integrity" "sha512-N7YhW5RiOY6J228z4lOoP//qX0Q48cRtxDONZ/Ohd9C5OI2vS6TD8iQuDqOIYHxH+BshjNSsKvbJ+SMIQDwysg==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/mdx-loader" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - fs-extra "^10.0.0" - globby "^11.0.2" - remark-admonitions "^1.2.1" - tslib "^2.3.1" - webpack "^5.61.0" + "fs-extra" "^10.0.0" + "globby" "^11.0.2" + "remark-admonitions" "^1.2.1" + "tslib" "^2.3.1" + "webpack" "^5.61.0" "@docusaurus/plugin-debug@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-beta.15.tgz#b75d706d4f9fc4146f84015097bd837d1afb7c6b" - integrity sha512-Jth11jB/rVqPwCGdkVKSUWeXZPAr/NyPn+yeknTBk2LgQKBJ3YU5dNG0uyt0Ay+UYT01TkousPJkXhLuy4Qrsw== + "integrity" "sha512-Jth11jB/rVqPwCGdkVKSUWeXZPAr/NyPn+yeknTBk2LgQKBJ3YU5dNG0uyt0Ay+UYT01TkousPJkXhLuy4Qrsw==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" - fs-extra "^10.0.0" - react-json-view "^1.21.3" - tslib "^2.3.1" + "fs-extra" "^10.0.0" + "react-json-view" "^1.21.3" + "tslib" "^2.3.1" "@docusaurus/plugin-google-analytics@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-beta.15.tgz#6ffebe76d9caac5383cfb78d2baa5883c9c2df6c" - integrity sha512-ELAnxNYiC2i7gfu/ViurNIdm1/DdnbEfVDmpffS9niQhOREM1U3jpxkz/ff1GIC6heOLyHTtini/CZBDoroVGw== + "integrity" "sha512-ELAnxNYiC2i7gfu/ViurNIdm1/DdnbEfVDmpffS9niQhOREM1U3jpxkz/ff1GIC6heOLyHTtini/CZBDoroVGw==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - tslib "^2.3.1" + "tslib" "^2.3.1" "@docusaurus/plugin-google-gtag@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-beta.15.tgz#4db3330d302653e8541dc3cb86a4dbfef0cc96f8" - integrity sha512-E5Rm3+dN7i3A9V5uq5sl9xTNA3aXsLwTZEA2SpOkY571dCpd+sfVvz1lR+KRY9Fy6ZHk8PqrNImgCWfIerRuZQ== + "integrity" "sha512-E5Rm3+dN7i3A9V5uq5sl9xTNA3aXsLwTZEA2SpOkY571dCpd+sfVvz1lR+KRY9Fy6ZHk8PqrNImgCWfIerRuZQ==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - tslib "^2.3.1" + "tslib" "^2.3.1" "@docusaurus/plugin-sitemap@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-beta.15.tgz#0cc083d9e76041897e81b4b82bcd0ccbfa65d6e5" - integrity sha512-PBjeQb2Qpe4uPdRefWL/eXCeYjrgNB/UArExYeUuP4wiY1dpw2unGNCvFUxv4hzJGmARoTLsnRkeYkUim809LQ== + "integrity" "sha512-PBjeQb2Qpe4uPdRefWL/eXCeYjrgNB/UArExYeUuP4wiY1dpw2unGNCvFUxv4hzJGmARoTLsnRkeYkUim809LQ==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" "@docusaurus/utils-common" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - fs-extra "^10.0.0" - sitemap "^7.0.0" - tslib "^2.3.1" + "fs-extra" "^10.0.0" + "sitemap" "^7.0.0" + "tslib" "^2.3.1" "@docusaurus/preset-classic@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-2.0.0-beta.15.tgz#13d2f3c4fa7c055af35541ae5e93453450efb208" - integrity sha512-3NZIXWTAzk+kOgiB8uAbD+FZv3VFR1qkU6+TW24DRenjRnXof3CkRuldhI1QI0hILm1fuJ319QRkakV8FFtXyA== + "integrity" "sha512-3NZIXWTAzk+kOgiB8uAbD+FZv3VFR1qkU6+TW24DRenjRnXof3CkRuldhI1QI0hILm1fuJ319QRkakV8FFtXyA==" + "resolved" "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/plugin-content-blog" "2.0.0-beta.15" @@ -1418,18 +1417,18 @@ "@docusaurus/theme-common" "2.0.0-beta.15" "@docusaurus/theme-search-algolia" "2.0.0-beta.15" -"@docusaurus/react-loadable@5.5.2", "react-loadable@npm:@docusaurus/react-loadable@5.5.2": - version "5.5.2" - resolved "https://registry.yarnpkg.com/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz#81aae0db81ecafbdaee3651f12804580868fa6ce" - integrity sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ== +"@docusaurus/react-loadable@5.5.2": + "integrity" "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==" + "resolved" "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz" + "version" "5.5.2" dependencies: "@types/react" "*" - prop-types "^15.6.2" + "prop-types" "^15.6.2" "@docusaurus/theme-classic@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-2.0.0-beta.15.tgz#35d04232f2d5fcb2007675339b0e6d0e8681be95" - integrity sha512-WwNRcQvMtQ7KDhOEHFKFHxXCdoZwLg66hT3vhqNIFMfGQuPzOP91MX5LUSo1QWHhlrD3H3Og+r7Ik/fy2bf5lQ== + "integrity" "sha512-WwNRcQvMtQ7KDhOEHFKFHxXCdoZwLg66hT3vhqNIFMfGQuPzOP91MX5LUSo1QWHhlrD3H3Og+r7Ik/fy2bf5lQ==" + "resolved" "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/plugin-content-blog" "2.0.0-beta.15" @@ -1441,33 +1440,33 @@ "@docusaurus/utils-common" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" "@mdx-js/react" "^1.6.21" - clsx "^1.1.1" - copy-text-to-clipboard "^3.0.1" - infima "0.2.0-alpha.37" - lodash "^4.17.20" - postcss "^8.3.7" - prism-react-renderer "^1.2.1" - prismjs "^1.23.0" - react-router-dom "^5.2.0" - rtlcss "^3.3.0" + "clsx" "^1.1.1" + "copy-text-to-clipboard" "^3.0.1" + "infima" "0.2.0-alpha.37" + "lodash" "^4.17.20" + "postcss" "^8.3.7" + "prism-react-renderer" "^1.2.1" + "prismjs" "^1.23.0" + "react-router-dom" "^5.2.0" + "rtlcss" "^3.3.0" "@docusaurus/theme-common@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-2.0.0-beta.15.tgz#5bd338d483e2c19d6d74d133572988241518398a" - integrity sha512-+pvarmzcyECE4nWxw+dCMKRIoes0NegrRuM9+nRsUrS/E5ywsF539kpupKIEqaMjq6AuM0CJtDoHxHHPNe0KaQ== + "integrity" "sha512-+pvarmzcyECE4nWxw+dCMKRIoes0NegrRuM9+nRsUrS/E5ywsF539kpupKIEqaMjq6AuM0CJtDoHxHHPNe0KaQ==" + "resolved" "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/plugin-content-blog" "2.0.0-beta.15" "@docusaurus/plugin-content-docs" "2.0.0-beta.15" "@docusaurus/plugin-content-pages" "2.0.0-beta.15" - clsx "^1.1.1" - parse-numeric-range "^1.3.0" - tslib "^2.3.1" - utility-types "^3.10.0" + "clsx" "^1.1.1" + "parse-numeric-range" "^1.3.0" + "tslib" "^2.3.1" + "utility-types" "^3.10.0" "@docusaurus/theme-search-algolia@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-beta.15.tgz#c3ad7fd8e27fcb3e072990031c08768c602cb9a4" - integrity sha512-XrrQKyjOPzmEuOcdsaAn1tzNJkNMA3PC86PwPZUaah0cYPpBGptcJYDlIW4VHIrCBfkQvhvmg/B3qKF6bMMi8g== + "integrity" "sha512-XrrQKyjOPzmEuOcdsaAn1tzNJkNMA3PC86PwPZUaah0cYPpBGptcJYDlIW4VHIrCBfkQvhvmg/B3qKF6bMMi8g==" + "resolved" "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docsearch/react" "^3.0.0-alpha.39" "@docusaurus/core" "2.0.0-beta.15" @@ -1476,268 +1475,268 @@ "@docusaurus/theme-translations" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - algoliasearch "^4.10.5" - algoliasearch-helper "^3.5.5" - clsx "^1.1.1" - eta "^1.12.3" - lodash "^4.17.20" - tslib "^2.3.1" - utility-types "^3.10.0" + "algoliasearch" "^4.10.5" + "algoliasearch-helper" "^3.5.5" + "clsx" "^1.1.1" + "eta" "^1.12.3" + "lodash" "^4.17.20" + "tslib" "^2.3.1" + "utility-types" "^3.10.0" "@docusaurus/theme-translations@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-2.0.0-beta.15.tgz#658397ab4c0d7784043e3cec52cef7ae09d2fb59" - integrity sha512-Lu2JDsnZaB2BcJe8Hpq5nrbS7+7bd09jT08b9vztQyvzR8PgzsthnzlLN4ilOeamRIuYJKo1pUGm0EsQBOP6Nw== + "integrity" "sha512-Lu2JDsnZaB2BcJe8Hpq5nrbS7+7bd09jT08b9vztQyvzR8PgzsthnzlLN4ilOeamRIuYJKo1pUGm0EsQBOP6Nw==" + "resolved" "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: - fs-extra "^10.0.0" - tslib "^2.3.1" + "fs-extra" "^10.0.0" + "tslib" "^2.3.1" "@docusaurus/utils-common@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-2.0.0-beta.15.tgz#5549b329fc750bd5e9f24952c9e3ff7cf1f63e08" - integrity sha512-kIGlSIvbE/oniUpUjI8GOkSpH8o4NXbYqAh9dqPn+TJ0KbEFY3fc80gzZQU+9SunCwJMJbIxIGevX9Ry+nackw== + "integrity" "sha512-kIGlSIvbE/oniUpUjI8GOkSpH8o4NXbYqAh9dqPn+TJ0KbEFY3fc80gzZQU+9SunCwJMJbIxIGevX9Ry+nackw==" + "resolved" "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: - tslib "^2.3.1" + "tslib" "^2.3.1" "@docusaurus/utils-validation@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.0.0-beta.15.tgz#c664bc021194db9254eb45e6b48cb7c2af269041" - integrity sha512-1oOVBCkRrsTXSYrBTsMdnj3a/R56zrx11rjF4xo0+dmm8C01Xw4msFtc3uA7VLX0HQvgHsk8xPzU5GERNdsNpg== + "integrity" "sha512-1oOVBCkRrsTXSYrBTsMdnj3a/R56zrx11rjF4xo0+dmm8C01Xw4msFtc3uA7VLX0HQvgHsk8xPzU5GERNdsNpg==" + "resolved" "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/logger" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" - joi "^17.4.2" - tslib "^2.3.1" + "joi" "^17.4.2" + "tslib" "^2.3.1" "@docusaurus/utils@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.0.0-beta.15.tgz#60868046700d5585cfa6ffc57c5f3fbed00b61fc" - integrity sha512-xkoPmFxCBkDqbZR4U3SE752OcXtWTGgZnc/pZWxItzb1IYRGNZHrzdIr7CnI7rppriuZzsyivDGiC4Ud9MWhkA== + "integrity" "sha512-xkoPmFxCBkDqbZR4U3SE752OcXtWTGgZnc/pZWxItzb1IYRGNZHrzdIr7CnI7rppriuZzsyivDGiC4Ud9MWhkA==" + "resolved" "https://registry.npmjs.org/@docusaurus/utils/-/utils-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/logger" "2.0.0-beta.15" "@mdx-js/runtime" "^1.6.22" "@svgr/webpack" "^6.0.0" - file-loader "^6.2.0" - fs-extra "^10.0.0" - github-slugger "^1.4.0" - globby "^11.0.4" - gray-matter "^4.0.3" - js-yaml "^4.0.0" - lodash "^4.17.20" - micromatch "^4.0.4" - remark-mdx-remove-exports "^1.6.22" - remark-mdx-remove-imports "^1.6.22" - resolve-pathname "^3.0.0" - tslib "^2.3.1" - url-loader "^4.1.1" + "file-loader" "^6.2.0" + "fs-extra" "^10.0.0" + "github-slugger" "^1.4.0" + "globby" "^11.0.4" + "gray-matter" "^4.0.3" + "js-yaml" "^4.0.0" + "lodash" "^4.17.20" + "micromatch" "^4.0.4" + "remark-mdx-remove-exports" "^1.6.22" + "remark-mdx-remove-imports" "^1.6.22" + "resolve-pathname" "^3.0.0" + "tslib" "^2.3.1" + "url-loader" "^4.1.1" "@hapi/hoek@^9.0.0": - version "9.2.1" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.2.1.tgz#9551142a1980503752536b5050fd99f4a7f13b17" - integrity sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw== + "integrity" "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==" + "resolved" "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz" + "version" "9.2.1" "@hapi/topo@^5.0.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" - integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== + "integrity" "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==" + "resolved" "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz" + "version" "5.1.0" dependencies: "@hapi/hoek" "^9.0.0" -"@jridgewell/gen-mapping@^0.3.0": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" - integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== +"@jridgewell/gen-mapping@^0.1.0": + "integrity" "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==" + "resolved" "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz" + "version" "0.1.1" + dependencies: + "@jridgewell/set-array" "^1.0.0" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + "integrity" "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==" + "resolved" "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz" + "version" "0.3.2" dependencies: "@jridgewell/set-array" "^1.0.1" "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/resolve-uri@^3.0.3": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== +"@jridgewell/resolve-uri@3.1.0": + "integrity" "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" + "resolved" "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz" + "version" "3.1.0" -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": + "integrity" "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + "resolved" "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz" + "version" "1.1.2" "@jridgewell/source-map@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" - integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + "integrity" "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==" + "resolved" "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz" + "version" "0.3.2" dependencies: "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== - -"@jridgewell/trace-mapping@^0.3.0": - version "0.3.4" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz#f6a0832dffd5b8a6aaa633b7d9f8e8e94c83a0c3" - integrity sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@1.4.14": + "integrity" "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + "resolved" "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" + "version" "1.4.14" -"@jridgewell/trace-mapping@^0.3.9": - version "0.3.14" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed" - integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ== +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": + "integrity" "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==" + "resolved" "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz" + "version" "0.3.17" dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" -"@mdx-js/mdx@1.6.22", "@mdx-js/mdx@^1.6.21": - version "1.6.22" - resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-1.6.22.tgz#8a723157bf90e78f17dc0f27995398e6c731f1ba" - integrity sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA== +"@mdx-js/mdx@^1.6.21", "@mdx-js/mdx@1.6.22": + "integrity" "sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==" + "resolved" "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz" + "version" "1.6.22" dependencies: "@babel/core" "7.12.9" "@babel/plugin-syntax-jsx" "7.12.1" "@babel/plugin-syntax-object-rest-spread" "7.8.3" "@mdx-js/util" "1.6.22" - babel-plugin-apply-mdx-type-prop "1.6.22" - babel-plugin-extract-import-names "1.6.22" - camelcase-css "2.0.1" - detab "2.0.4" - hast-util-raw "6.0.1" - lodash.uniq "4.5.0" - mdast-util-to-hast "10.0.1" - remark-footnotes "2.0.0" - remark-mdx "1.6.22" - remark-parse "8.0.3" - remark-squeeze-paragraphs "4.0.0" - style-to-object "0.3.0" - unified "9.2.0" - unist-builder "2.0.3" - unist-util-visit "2.0.3" - -"@mdx-js/react@1.6.22", "@mdx-js/react@^1.6.21": - version "1.6.22" - resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.6.22.tgz#ae09b4744fddc74714ee9f9d6f17a66e77c43573" - integrity sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg== + "babel-plugin-apply-mdx-type-prop" "1.6.22" + "babel-plugin-extract-import-names" "1.6.22" + "camelcase-css" "2.0.1" + "detab" "2.0.4" + "hast-util-raw" "6.0.1" + "lodash.uniq" "4.5.0" + "mdast-util-to-hast" "10.0.1" + "remark-footnotes" "2.0.0" + "remark-mdx" "1.6.22" + "remark-parse" "8.0.3" + "remark-squeeze-paragraphs" "4.0.0" + "style-to-object" "0.3.0" + "unified" "9.2.0" + "unist-builder" "2.0.3" + "unist-util-visit" "2.0.3" + +"@mdx-js/react@^1.6.21", "@mdx-js/react@1.6.22": + "integrity" "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==" + "resolved" "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz" + "version" "1.6.22" "@mdx-js/runtime@^1.6.22": - version "1.6.22" - resolved "https://registry.yarnpkg.com/@mdx-js/runtime/-/runtime-1.6.22.tgz#3edd388bf68a519ffa1aaf9c446b548165102345" - integrity sha512-p17spaO2+55VLCuxXA3LVHC4phRx60NR2XMdZ+qgVU1lKvEX4y88dmFNOzGDCPLJ03IZyKrJ/rPWWRiBrd9JrQ== + "integrity" "sha512-p17spaO2+55VLCuxXA3LVHC4phRx60NR2XMdZ+qgVU1lKvEX4y88dmFNOzGDCPLJ03IZyKrJ/rPWWRiBrd9JrQ==" + "resolved" "https://registry.npmjs.org/@mdx-js/runtime/-/runtime-1.6.22.tgz" + "version" "1.6.22" dependencies: "@mdx-js/mdx" "1.6.22" "@mdx-js/react" "1.6.22" - buble-jsx-only "^0.19.8" + "buble-jsx-only" "^0.19.8" "@mdx-js/util@1.6.22": - version "1.6.22" - resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b" - integrity sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA== + "integrity" "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==" + "resolved" "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz" + "version" "1.6.22" "@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + "integrity" "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==" + "resolved" "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" + "version" "2.1.5" dependencies: "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" + "run-parallel" "^1.1.9" -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== +"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": + "integrity" "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + "resolved" "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" + "version" "2.0.5" "@nodelib/fs.walk@^1.2.3": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + "integrity" "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==" + "resolved" "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" + "version" "1.2.8" dependencies: "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" + "fastq" "^1.6.0" "@polka/url@^1.0.0-next.20": - version "1.0.0-next.21" - resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" - integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== + "integrity" "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==" + "resolved" "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz" + "version" "1.0.0-next.21" "@sideway/address@^4.1.3": - version "4.1.3" - resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.3.tgz#d93cce5d45c5daec92ad76db492cc2ee3c64ab27" - integrity sha512-8ncEUtmnTsMmL7z1YPB47kPUq7LpKWJNFPsRzHiIajGC5uXlWGn+AmkYPcHNl8S4tcEGx+cnORnNYaw2wvL+LQ== + "integrity" "sha512-8ncEUtmnTsMmL7z1YPB47kPUq7LpKWJNFPsRzHiIajGC5uXlWGn+AmkYPcHNl8S4tcEGx+cnORnNYaw2wvL+LQ==" + "resolved" "https://registry.npmjs.org/@sideway/address/-/address-4.1.3.tgz" + "version" "4.1.3" dependencies: "@hapi/hoek" "^9.0.0" "@sideway/formula@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c" - integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg== + "integrity" "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + "resolved" "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz" + "version" "3.0.1" "@sideway/pinpoint@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" - integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + "integrity" "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + "resolved" "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz" + "version" "2.0.0" "@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + "integrity" "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" + "resolved" "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz" + "version" "0.14.0" "@slorber/static-site-generator-webpack-plugin@^4.0.0": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.1.tgz#0c8852146441aaa683693deaa5aee2f991d94841" - integrity sha512-PSv4RIVO1Y3kvHxjvqeVisk3E9XFoO04uwYBDWe217MFqKspplYswTuKLiJu0aLORQWzuQjfVsSlLPojwfYsLw== + "integrity" "sha512-PSv4RIVO1Y3kvHxjvqeVisk3E9XFoO04uwYBDWe217MFqKspplYswTuKLiJu0aLORQWzuQjfVsSlLPojwfYsLw==" + "resolved" "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.1.tgz" + "version" "4.0.1" dependencies: - bluebird "^3.7.1" - cheerio "^0.22.0" - eval "^0.1.4" - url "^0.11.0" - webpack-sources "^1.4.3" + "bluebird" "^3.7.1" + "cheerio" "^0.22.0" + "eval" "^0.1.4" + "url" "^0.11.0" + "webpack-sources" "^1.4.3" "@svgr/babel-plugin-add-jsx-attribute@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.0.0.tgz#bd6d1ff32a31b82b601e73672a789cc41e84fe18" - integrity sha512-MdPdhdWLtQsjd29Wa4pABdhWbaRMACdM1h31BY+c6FghTZqNGT7pEYdBoaGeKtdTOBC/XNFQaKVj+r/Ei2ryWA== + "integrity" "sha512-MdPdhdWLtQsjd29Wa4pABdhWbaRMACdM1h31BY+c6FghTZqNGT7pEYdBoaGeKtdTOBC/XNFQaKVj+r/Ei2ryWA==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-remove-jsx-attribute@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.0.0.tgz#58654908beebfa069681a83332544b17e5237e89" - integrity sha512-aVdtfx9jlaaxc3unA6l+M9YRnKIZjOhQPthLKqmTXC8UVkBLDRGwPKo+r8n3VZN8B34+yVajzPTZ+ptTSuZZCw== + "integrity" "sha512-aVdtfx9jlaaxc3unA6l+M9YRnKIZjOhQPthLKqmTXC8UVkBLDRGwPKo+r8n3VZN8B34+yVajzPTZ+ptTSuZZCw==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-remove-jsx-empty-expression@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.0.0.tgz#d06dd6e8a8f603f92f9979bb9990a1f85a4f57ba" - integrity sha512-Ccj42ApsePD451AZJJf1QzTD1B/BOU392URJTeXFxSK709i0KUsGtbwyiqsKu7vsYxpTM0IA5clAKDyf9RCZyA== + "integrity" "sha512-Ccj42ApsePD451AZJJf1QzTD1B/BOU392URJTeXFxSK709i0KUsGtbwyiqsKu7vsYxpTM0IA5clAKDyf9RCZyA==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-replace-jsx-attribute-value@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.0.0.tgz#0b85837577b02c31c09c758a12932820f5245cee" - integrity sha512-88V26WGyt1Sfd1emBYmBJRWMmgarrExpKNVmI9vVozha4kqs6FzQJ/Kp5+EYli1apgX44518/0+t9+NU36lThQ== + "integrity" "sha512-88V26WGyt1Sfd1emBYmBJRWMmgarrExpKNVmI9vVozha4kqs6FzQJ/Kp5+EYli1apgX44518/0+t9+NU36lThQ==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-svg-dynamic-title@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.0.0.tgz#28236ec26f7ab9d486a487d36ae52d58ba15676f" - integrity sha512-F7YXNLfGze+xv0KMQxrl2vkNbI9kzT9oDK55/kUuymh1ACyXkMV+VZWX1zEhSTfEKh7VkHVZGmVtHg8eTZ6PRg== + "integrity" "sha512-F7YXNLfGze+xv0KMQxrl2vkNbI9kzT9oDK55/kUuymh1ACyXkMV+VZWX1zEhSTfEKh7VkHVZGmVtHg8eTZ6PRg==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-svg-em-dimensions@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.0.0.tgz#40267c5dea1b43c4f83a0eb6169e08b43d8bafce" - integrity sha512-+rghFXxdIqJNLQK08kwPBD3Z22/0b2tEZ9lKiL/yTfuyj1wW8HUXu4bo/XkogATIYuXSghVQOOCwURXzHGKyZA== + "integrity" "sha512-+rghFXxdIqJNLQK08kwPBD3Z22/0b2tEZ9lKiL/yTfuyj1wW8HUXu4bo/XkogATIYuXSghVQOOCwURXzHGKyZA==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-transform-react-native-svg@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.0.0.tgz#eb688d0a5f539e34d268d8a516e81f5d7fede7c9" - integrity sha512-VaphyHZ+xIKv5v0K0HCzyfAaLhPGJXSk2HkpYfXIOKb7DjLBv0soHDxNv6X0vr2titsxE7klb++u7iOf7TSrFQ== + "integrity" "sha512-VaphyHZ+xIKv5v0K0HCzyfAaLhPGJXSk2HkpYfXIOKb7DjLBv0soHDxNv6X0vr2titsxE7klb++u7iOf7TSrFQ==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-transform-svg-component@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.2.0.tgz#7ba61d9fc1fb42b0ba1a04e4630019fa7e993c4f" - integrity sha512-bhYIpsORb++wpsp91fymbFkf09Z/YEKR0DnFjxvN+8JHeCUD2unnh18jIMKnDJTWtvpTaGYPXELVe4OOzFI0xg== + "integrity" "sha512-bhYIpsORb++wpsp91fymbFkf09Z/YEKR0DnFjxvN+8JHeCUD2unnh18jIMKnDJTWtvpTaGYPXELVe4OOzFI0xg==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.2.0.tgz" + "version" "6.2.0" "@svgr/babel-preset@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-6.2.0.tgz#1d3ad8c7664253a4be8e4a0f0e6872f30d8af627" - integrity sha512-4WQNY0J71JIaL03DRn0vLiz87JXx0b9dYm2aA8XHlQJQoixMl4r/soYHm8dsaJZ3jWtkCiOYy48dp9izvXhDkQ== + "integrity" "sha512-4WQNY0J71JIaL03DRn0vLiz87JXx0b9dYm2aA8XHlQJQoixMl4r/soYHm8dsaJZ3jWtkCiOYy48dp9izvXhDkQ==" + "resolved" "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.2.0.tgz" + "version" "6.2.0" dependencies: "@svgr/babel-plugin-add-jsx-attribute" "^6.0.0" "@svgr/babel-plugin-remove-jsx-attribute" "^6.0.0" @@ -1748,46 +1747,46 @@ "@svgr/babel-plugin-transform-react-native-svg" "^6.0.0" "@svgr/babel-plugin-transform-svg-component" "^6.2.0" -"@svgr/core@^6.2.1": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@svgr/core/-/core-6.2.1.tgz#195de807a9f27f9e0e0d678e01084b05c54fdf61" - integrity sha512-NWufjGI2WUyrg46mKuySfviEJ6IxHUOm/8a3Ph38VCWSp+83HBraCQrpEM3F3dB6LBs5x8OElS8h3C0oOJaJAA== +"@svgr/core@^6.0.0", "@svgr/core@^6.2.1": + "integrity" "sha512-NWufjGI2WUyrg46mKuySfviEJ6IxHUOm/8a3Ph38VCWSp+83HBraCQrpEM3F3dB6LBs5x8OElS8h3C0oOJaJAA==" + "resolved" "https://registry.npmjs.org/@svgr/core/-/core-6.2.1.tgz" + "version" "6.2.1" dependencies: "@svgr/plugin-jsx" "^6.2.1" - camelcase "^6.2.0" - cosmiconfig "^7.0.1" + "camelcase" "^6.2.0" + "cosmiconfig" "^7.0.1" "@svgr/hast-util-to-babel-ast@^6.2.1": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.2.1.tgz#ae065567b74cbe745afae617053adf9a764bea25" - integrity sha512-pt7MMkQFDlWJVy9ULJ1h+hZBDGFfSCwlBNW1HkLnVi7jUhyEXUaGYWi1x6bM2IXuAR9l265khBT4Av4lPmaNLQ== + "integrity" "sha512-pt7MMkQFDlWJVy9ULJ1h+hZBDGFfSCwlBNW1HkLnVi7jUhyEXUaGYWi1x6bM2IXuAR9l265khBT4Av4lPmaNLQ==" + "resolved" "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.2.1.tgz" + "version" "6.2.1" dependencies: "@babel/types" "^7.15.6" - entities "^3.0.1" + "entities" "^3.0.1" "@svgr/plugin-jsx@^6.2.1": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-6.2.1.tgz#5668f1d2aa18c2f1bb7a1fc9f682d3f9aed263bd" - integrity sha512-u+MpjTsLaKo6r3pHeeSVsh9hmGRag2L7VzApWIaS8imNguqoUwDq/u6U/NDmYs/KAsrmtBjOEaAAPbwNGXXp1g== + "integrity" "sha512-u+MpjTsLaKo6r3pHeeSVsh9hmGRag2L7VzApWIaS8imNguqoUwDq/u6U/NDmYs/KAsrmtBjOEaAAPbwNGXXp1g==" + "resolved" "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.2.1.tgz" + "version" "6.2.1" dependencies: "@babel/core" "^7.15.5" "@svgr/babel-preset" "^6.2.0" "@svgr/hast-util-to-babel-ast" "^6.2.1" - svg-parser "^2.0.2" + "svg-parser" "^2.0.2" "@svgr/plugin-svgo@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-6.2.0.tgz#4cbe6a33ccccdcae4e3b63ded64cc1cbe1faf48c" - integrity sha512-oDdMQONKOJEbuKwuy4Np6VdV6qoaLLvoY86hjvQEgU82Vx1MSWRyYms6Sl0f+NtqxLI/rDVufATbP/ev996k3Q== + "integrity" "sha512-oDdMQONKOJEbuKwuy4Np6VdV6qoaLLvoY86hjvQEgU82Vx1MSWRyYms6Sl0f+NtqxLI/rDVufATbP/ev996k3Q==" + "resolved" "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-6.2.0.tgz" + "version" "6.2.0" dependencies: - cosmiconfig "^7.0.1" - deepmerge "^4.2.2" - svgo "^2.5.0" + "cosmiconfig" "^7.0.1" + "deepmerge" "^4.2.2" + "svgo" "^2.5.0" "@svgr/webpack@^6.0.0": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-6.2.1.tgz#ef5d51c1b6be4e7537fb9f76b3f2b2e22b63c58d" - integrity sha512-h09ngMNd13hnePwgXa+Y5CgOjzlCvfWLHg+MBnydEedAnuLRzUHUJmGS3o2OsrhxTOOqEsPOFt5v/f6C5Qulcw== + "integrity" "sha512-h09ngMNd13hnePwgXa+Y5CgOjzlCvfWLHg+MBnydEedAnuLRzUHUJmGS3o2OsrhxTOOqEsPOFt5v/f6C5Qulcw==" + "resolved" "https://registry.npmjs.org/@svgr/webpack/-/webpack-6.2.1.tgz" + "version" "6.2.1" dependencies: "@babel/core" "^7.15.5" "@babel/plugin-transform-react-constant-elements" "^7.14.5" @@ -1799,81 +1798,81 @@ "@svgr/plugin-svgo" "^6.2.0" "@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + "integrity" "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==" + "resolved" "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz" + "version" "1.1.2" dependencies: - defer-to-connect "^1.0.1" + "defer-to-connect" "^1.0.1" "@trysound/sax@0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" - integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== + "integrity" "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==" + "resolved" "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz" + "version" "0.2.0" "@types/body-parser@*": - version "1.19.2" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" - integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + "integrity" "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==" + "resolved" "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz" + "version" "1.19.2" dependencies: "@types/connect" "*" "@types/node" "*" "@types/bonjour@^3.5.9": - version "3.5.10" - resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" - integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== + "integrity" "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==" + "resolved" "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz" + "version" "3.5.10" dependencies: "@types/node" "*" "@types/connect-history-api-fallback@^1.3.5": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" - integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== + "integrity" "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==" + "resolved" "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz" + "version" "1.3.5" dependencies: "@types/express-serve-static-core" "*" "@types/node" "*" "@types/connect@*": - version "3.4.35" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" - integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + "integrity" "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==" + "resolved" "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz" + "version" "3.4.35" dependencies: "@types/node" "*" "@types/eslint-scope@^3.7.3": - version "3.7.3" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224" - integrity sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g== + "integrity" "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==" + "resolved" "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz" + "version" "3.7.3" dependencies: "@types/eslint" "*" "@types/estree" "*" "@types/eslint@*": - version "8.4.1" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.1.tgz#c48251553e8759db9e656de3efc846954ac32304" - integrity sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA== + "integrity" "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==" + "resolved" "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz" + "version" "8.4.1" dependencies: "@types/estree" "*" "@types/json-schema" "*" "@types/estree@*", "@types/estree@^0.0.51": - version "0.0.51" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" - integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== + "integrity" "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==" + "resolved" "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz" + "version" "0.0.51" "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18": - version "4.17.28" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz#c47def9f34ec81dc6328d0b1b5303d1ec98d86b8" - integrity sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig== + "integrity" "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==" + "resolved" "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz" + "version" "4.17.28" dependencies: "@types/node" "*" "@types/qs" "*" "@types/range-parser" "*" "@types/express@*", "@types/express@^4.17.13": - version "4.17.13" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" - integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== + "integrity" "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==" + "resolved" "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz" + "version" "4.17.13" dependencies: "@types/body-parser" "*" "@types/express-serve-static-core" "^4.17.18" @@ -1881,172 +1880,172 @@ "@types/serve-static" "*" "@types/hast@^2.0.0": - version "2.3.4" - resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" - integrity sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g== + "integrity" "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==" + "resolved" "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz" + "version" "2.3.4" dependencies: "@types/unist" "*" "@types/html-minifier-terser@^6.0.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" - integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== + "integrity" "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + "resolved" "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz" + "version" "6.1.0" "@types/http-proxy@^1.17.8": - version "1.17.8" - resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.8.tgz#968c66903e7e42b483608030ee85800f22d03f55" - integrity sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA== + "integrity" "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==" + "resolved" "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz" + "version" "1.17.8" dependencies: "@types/node" "*" "@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": - version "7.0.9" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" - integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== + "integrity" "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" + "resolved" "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz" + "version" "7.0.9" "@types/mdast@^3.0.0": - version "3.0.10" - resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af" - integrity sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA== + "integrity" "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==" + "resolved" "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz" + "version" "3.0.10" dependencies: "@types/unist" "*" "@types/mime@^1": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" - integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== + "integrity" "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + "resolved" "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz" + "version" "1.3.2" "@types/node@*", "@types/node@^17.0.5": - version "17.0.18" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.18.tgz#3b4fed5cfb58010e3a2be4b6e74615e4847f1074" - integrity sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA== + "integrity" "sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==" + "resolved" "https://registry.npmjs.org/@types/node/-/node-17.0.18.tgz" + "version" "17.0.18" "@types/parse-json@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" - integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + "integrity" "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" + "resolved" "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz" + "version" "4.0.0" "@types/parse5@^5.0.0": - version "5.0.3" - resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109" - integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== + "integrity" "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==" + "resolved" "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz" + "version" "5.0.3" "@types/prop-types@*": - version "15.7.4" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" - integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ== + "integrity" "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==" + "resolved" "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz" + "version" "15.7.4" "@types/qs@*": - version "6.9.7" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" - integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + "integrity" "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + "resolved" "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz" + "version" "6.9.7" "@types/range-parser@*": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" - integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + "integrity" "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + "resolved" "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz" + "version" "1.2.4" -"@types/react@*": - version "17.0.39" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.39.tgz#d0f4cde092502a6db00a1cded6e6bf2abb7633ce" - integrity sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug== +"@types/react@*", "@types/react@>= 16.8.0 < 18.0.0": + "integrity" "sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==" + "resolved" "https://registry.npmjs.org/@types/react/-/react-17.0.39.tgz" + "version" "17.0.39" dependencies: "@types/prop-types" "*" "@types/scheduler" "*" - csstype "^3.0.2" + "csstype" "^3.0.2" "@types/retry@^0.12.0": - version "0.12.1" - resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065" - integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g== + "integrity" "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==" + "resolved" "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz" + "version" "0.12.1" "@types/sax@^1.2.1": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@types/sax/-/sax-1.2.4.tgz#8221affa7f4f3cb21abd22f244cfabfa63e6a69e" - integrity sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw== + "integrity" "sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw==" + "resolved" "https://registry.npmjs.org/@types/sax/-/sax-1.2.4.tgz" + "version" "1.2.4" dependencies: "@types/node" "*" "@types/scheduler@*": - version "0.16.2" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" - integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== + "integrity" "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" + "resolved" "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz" + "version" "0.16.2" "@types/serve-index@^1.9.1": - version "1.9.1" - resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" - integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== + "integrity" "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==" + "resolved" "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz" + "version" "1.9.1" dependencies: "@types/express" "*" "@types/serve-static@*": - version "1.13.10" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" - integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ== + "integrity" "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==" + "resolved" "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz" + "version" "1.13.10" dependencies: "@types/mime" "^1" "@types/node" "*" "@types/sockjs@^0.3.33": - version "0.3.33" - resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" - integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== + "integrity" "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==" + "resolved" "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz" + "version" "0.3.33" dependencies: "@types/node" "*" "@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" - integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== + "integrity" "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" + "resolved" "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz" + "version" "2.0.6" "@types/ws@^8.2.2": - version "8.2.2" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.2.2.tgz#7c5be4decb19500ae6b3d563043cd407bf366c21" - integrity sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg== + "integrity" "sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg==" + "resolved" "https://registry.npmjs.org/@types/ws/-/ws-8.2.2.tgz" + "version" "8.2.2" dependencies: "@types/node" "*" "@webassemblyjs/ast@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" - integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== + "integrity" "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/helper-numbers" "1.11.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.1" "@webassemblyjs/floating-point-hex-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" - integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== + "integrity" "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz" + "version" "1.11.1" "@webassemblyjs/helper-api-error@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" - integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== + "integrity" "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz" + "version" "1.11.1" "@webassemblyjs/helper-buffer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" - integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== + "integrity" "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz" + "version" "1.11.1" "@webassemblyjs/helper-numbers@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" - integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== + "integrity" "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/floating-point-hex-parser" "1.11.1" "@webassemblyjs/helper-api-error" "1.11.1" "@xtuc/long" "4.2.2" "@webassemblyjs/helper-wasm-bytecode@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" - integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== + "integrity" "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz" + "version" "1.11.1" "@webassemblyjs/helper-wasm-section@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" - integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== + "integrity" "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/helper-buffer" "1.11.1" @@ -2054,28 +2053,28 @@ "@webassemblyjs/wasm-gen" "1.11.1" "@webassemblyjs/ieee754@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" - integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== + "integrity" "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz" + "version" "1.11.1" dependencies: "@xtuc/ieee754" "^1.2.0" "@webassemblyjs/leb128@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" - integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== + "integrity" "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz" + "version" "1.11.1" dependencies: "@xtuc/long" "4.2.2" "@webassemblyjs/utf8@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" - integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== + "integrity" "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz" + "version" "1.11.1" "@webassemblyjs/wasm-edit@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" - integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== + "integrity" "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/helper-buffer" "1.11.1" @@ -2087,9 +2086,9 @@ "@webassemblyjs/wast-printer" "1.11.1" "@webassemblyjs/wasm-gen@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" - integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== + "integrity" "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.1" @@ -2098,9 +2097,9 @@ "@webassemblyjs/utf8" "1.11.1" "@webassemblyjs/wasm-opt@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" - integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== + "integrity" "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/helper-buffer" "1.11.1" @@ -2108,9 +2107,9 @@ "@webassemblyjs/wasm-parser" "1.11.1" "@webassemblyjs/wasm-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" - integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== + "integrity" "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/helper-api-error" "1.11.1" @@ -2120,124 +2119,124 @@ "@webassemblyjs/utf8" "1.11.1" "@webassemblyjs/wast-printer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" - integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== + "integrity" "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/ast" "1.11.1" "@xtuc/long" "4.2.2" "@xtuc/ieee754@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + "integrity" "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + "resolved" "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz" + "version" "1.2.0" "@xtuc/long@4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== - -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== - dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" - -acorn-dynamic-import@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948" - integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw== - -acorn-import-assertions@^1.7.6: - version "1.8.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" - integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== - -acorn-jsx@^5.0.1: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn-walk@^8.0.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== - -acorn@^6.1.1: - version "6.4.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" - integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== - -acorn@^8.0.4, acorn@^8.4.1, acorn@^8.5.0: - version "8.7.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" - integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== - -address@^1.0.1, address@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" - integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA== - -aggregate-error@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" - integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - -ajv-formats@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" - integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== - dependencies: - ajv "^8.0.0" - -ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" - integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== - -ajv-keywords@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" - integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== - dependencies: - fast-deep-equal "^3.1.3" - -ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ajv@^8.0.0, ajv@^8.8.0: - version "8.10.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.10.0.tgz#e573f719bd3af069017e3b66538ab968d040e54d" - integrity sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - -algoliasearch-helper@^3.5.5: - version "3.7.0" - resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.7.0.tgz#c0a0493df84d850360f664ad7a9d4fc78a94fd78" - integrity sha512-XJ3QfERBLfeVCyTVx80gon7r3/rgm/CE8Ha1H7cbablRe/X7SfYQ14g/eO+MhjVKIQp+gy9oC6G5ilmLwS1k6w== + "integrity" "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + "resolved" "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz" + "version" "4.2.2" + +"accepts@~1.3.4", "accepts@~1.3.5", "accepts@~1.3.8": + "integrity" "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==" + "resolved" "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz" + "version" "1.3.8" + dependencies: + "mime-types" "~2.1.34" + "negotiator" "0.6.3" + +"acorn-dynamic-import@^4.0.0": + "integrity" "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==" + "resolved" "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz" + "version" "4.0.0" + +"acorn-import-assertions@^1.7.6": + "integrity" "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==" + "resolved" "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz" + "version" "1.8.0" + +"acorn-jsx@^5.0.1": + "integrity" "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==" + "resolved" "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" + "version" "5.3.2" + +"acorn-walk@^8.0.0": + "integrity" "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" + "resolved" "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" + "version" "8.2.0" + +"acorn@^6.0.0", "acorn@^6.0.0 || ^7.0.0 || ^8.0.0", "acorn@^6.1.1": + "integrity" "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==" + "resolved" "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz" + "version" "6.4.2" + +"acorn@^8", "acorn@^8.0.4", "acorn@^8.4.1", "acorn@^8.5.0": + "integrity" "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==" + "resolved" "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz" + "version" "8.7.1" + +"address@^1.0.1", "address@^1.1.2": + "integrity" "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==" + "resolved" "https://registry.npmjs.org/address/-/address-1.1.2.tgz" + "version" "1.1.2" + +"aggregate-error@^3.0.0": + "integrity" "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==" + "resolved" "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "clean-stack" "^2.0.0" + "indent-string" "^4.0.0" + +"ajv-formats@^2.1.1": + "integrity" "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==" + "resolved" "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz" + "version" "2.1.1" + dependencies: + "ajv" "^8.0.0" + +"ajv-keywords@^3.4.1", "ajv-keywords@^3.5.2": + "integrity" "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" + "resolved" "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" + "version" "3.5.2" + +"ajv-keywords@^5.0.0": + "integrity" "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==" + "resolved" "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "fast-deep-equal" "^3.1.3" + +"ajv@^6.12.2", "ajv@^6.12.4", "ajv@^6.12.5", "ajv@^6.9.1": + "integrity" "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==" + "resolved" "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" + "version" "6.12.6" + dependencies: + "fast-deep-equal" "^3.1.1" + "fast-json-stable-stringify" "^2.0.0" + "json-schema-traverse" "^0.4.1" + "uri-js" "^4.2.2" + +"ajv@^8.0.0", "ajv@^8.8.0", "ajv@^8.8.2": + "integrity" "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==" + "resolved" "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz" + "version" "8.10.0" + dependencies: + "fast-deep-equal" "^3.1.1" + "json-schema-traverse" "^1.0.0" + "require-from-string" "^2.0.2" + "uri-js" "^4.2.2" + +"algoliasearch-helper@^3.5.5": + "integrity" "sha512-XJ3QfERBLfeVCyTVx80gon7r3/rgm/CE8Ha1H7cbablRe/X7SfYQ14g/eO+MhjVKIQp+gy9oC6G5ilmLwS1k6w==" + "resolved" "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.7.0.tgz" + "version" "3.7.0" dependencies: "@algolia/events" "^4.0.1" -algoliasearch@^4.0.0, algoliasearch@^4.10.5: - version "4.12.1" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.12.1.tgz#574a2c5424c4b6681c026928fb810be2d2ec3924" - integrity sha512-c0dM1g3zZBJrkzE5GA/Nu1y3fFxx3LCzxKzcmp2dgGS8P4CjszB/l3lsSh2MSrrK1Hn/KV4BlbBMXtYgG1Bfrw== +"algoliasearch@^4.0.0", "algoliasearch@^4.10.5", "algoliasearch@^4.9.1", "algoliasearch@>= 3.1 < 5": + "integrity" "sha512-c0dM1g3zZBJrkzE5GA/Nu1y3fFxx3LCzxKzcmp2dgGS8P4CjszB/l3lsSh2MSrrK1Hn/KV4BlbBMXtYgG1Bfrw==" + "resolved" "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/cache-browser-local-storage" "4.12.1" "@algolia/cache-common" "4.12.1" @@ -2254,2429 +2253,2448 @@ algoliasearch@^4.0.0, algoliasearch@^4.10.5: "@algolia/requester-node-http" "4.12.1" "@algolia/transporter" "4.12.1" -ansi-align@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" - integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== - dependencies: - string-width "^4.1.0" - -ansi-html-community@^0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" - integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -arg@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.1.tgz#eb0c9a8f77786cad2af8ff2b862899842d7b6adb" - integrity sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA== - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - -array-flatten@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" - integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -array-union@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-3.0.1.tgz#da52630d327f8b88cfbfb57728e2af5cd9b6b975" - integrity sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw== - -asap@~2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= - -async@^2.6.2: - version "2.6.4" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" - integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== - dependencies: - lodash "^4.17.14" - -at-least-node@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" - integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== - -autoprefixer@^10.3.5, autoprefixer@^10.3.7: - version "10.4.2" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.2.tgz#25e1df09a31a9fba5c40b578936b90d35c9d4d3b" - integrity sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ== - dependencies: - browserslist "^4.19.1" - caniuse-lite "^1.0.30001297" - fraction.js "^4.1.2" - normalize-range "^0.1.2" - picocolors "^1.0.0" - postcss-value-parser "^4.2.0" - -axios@^0.25.0: - version "0.25.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.25.0.tgz#349cfbb31331a9b4453190791760a8d35b093e0a" - integrity sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g== - dependencies: - follow-redirects "^1.14.7" - -babel-loader@^8.2.2: - version "8.2.3" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.3.tgz#8986b40f1a64cacfcb4b8429320085ef68b1342d" - integrity sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw== - dependencies: - find-cache-dir "^3.3.1" - loader-utils "^1.4.0" - make-dir "^3.1.0" - schema-utils "^2.6.5" - -babel-plugin-apply-mdx-type-prop@1.6.22: - version "1.6.22" - resolved "https://registry.yarnpkg.com/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz#d216e8fd0de91de3f1478ef3231e05446bc8705b" - integrity sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ== +"ansi-align@^3.0.0": + "integrity" "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==" + "resolved" "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "string-width" "^4.1.0" + +"ansi-html-community@^0.0.8": + "integrity" "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==" + "resolved" "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz" + "version" "0.0.8" + +"ansi-regex@^5.0.1": + "integrity" "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" + "version" "5.0.1" + +"ansi-regex@^6.0.1": + "integrity" "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz" + "version" "6.0.1" + +"ansi-styles@^3.2.1": + "integrity" "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==" + "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + "version" "3.2.1" + dependencies: + "color-convert" "^1.9.0" + +"ansi-styles@^4.0.0", "ansi-styles@^4.1.0": + "integrity" "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==" + "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + "version" "4.3.0" + dependencies: + "color-convert" "^2.0.1" + +"anymatch@~3.1.2": + "integrity" "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==" + "resolved" "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz" + "version" "3.1.2" + dependencies: + "normalize-path" "^3.0.0" + "picomatch" "^2.0.4" + +"arg@^5.0.0": + "integrity" "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==" + "resolved" "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz" + "version" "5.0.1" + +"argparse@^1.0.7": + "integrity" "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==" + "resolved" "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" + "version" "1.0.10" + dependencies: + "sprintf-js" "~1.0.2" + +"argparse@^2.0.1": + "integrity" "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "resolved" "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" + "version" "2.0.1" + +"array-flatten@^2.1.0": + "integrity" "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + "resolved" "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz" + "version" "2.1.2" + +"array-flatten@1.1.1": + "integrity" "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "resolved" "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" + "version" "1.1.1" + +"array-union@^2.1.0": + "integrity" "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + "resolved" "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" + "version" "2.1.0" + +"array-union@^3.0.1": + "integrity" "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==" + "resolved" "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz" + "version" "3.0.1" + +"asap@~2.0.3": + "integrity" "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + "resolved" "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz" + "version" "2.0.6" + +"async@^2.6.2": + "integrity" "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==" + "resolved" "https://registry.npmjs.org/async/-/async-2.6.4.tgz" + "version" "2.6.4" + dependencies: + "lodash" "^4.17.14" + +"at-least-node@^1.0.0": + "integrity" "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + "resolved" "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz" + "version" "1.0.0" + +"autoprefixer@^10.3.5", "autoprefixer@^10.3.7": + "integrity" "sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==" + "resolved" "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz" + "version" "10.4.2" + dependencies: + "browserslist" "^4.19.1" + "caniuse-lite" "^1.0.30001297" + "fraction.js" "^4.1.2" + "normalize-range" "^0.1.2" + "picocolors" "^1.0.0" + "postcss-value-parser" "^4.2.0" + +"axios@^0.25.0": + "integrity" "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==" + "resolved" "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz" + "version" "0.25.0" + dependencies: + "follow-redirects" "^1.14.7" + +"babel-loader@^8.2.2": + "integrity" "sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw==" + "resolved" "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.3.tgz" + "version" "8.2.3" + dependencies: + "find-cache-dir" "^3.3.1" + "loader-utils" "^1.4.0" + "make-dir" "^3.1.0" + "schema-utils" "^2.6.5" + +"babel-plugin-apply-mdx-type-prop@1.6.22": + "integrity" "sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ==" + "resolved" "https://registry.npmjs.org/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz" + "version" "1.6.22" dependencies: "@babel/helper-plugin-utils" "7.10.4" "@mdx-js/util" "1.6.22" -babel-plugin-dynamic-import-node@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" - integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== +"babel-plugin-dynamic-import-node@^2.3.3": + "integrity" "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==" + "resolved" "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz" + "version" "2.3.3" dependencies: - object.assign "^4.1.0" + "object.assign" "^4.1.0" -babel-plugin-dynamic-import-node@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" - integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== +"babel-plugin-dynamic-import-node@2.3.0": + "integrity" "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==" + "resolved" "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz" + "version" "2.3.0" dependencies: - object.assign "^4.1.0" + "object.assign" "^4.1.0" -babel-plugin-extract-import-names@1.6.22: - version "1.6.22" - resolved "https://registry.yarnpkg.com/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz#de5f9a28eb12f3eb2578bf74472204e66d1a13dc" - integrity sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ== +"babel-plugin-extract-import-names@1.6.22": + "integrity" "sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ==" + "resolved" "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz" + "version" "1.6.22" dependencies: "@babel/helper-plugin-utils" "7.10.4" -babel-plugin-polyfill-corejs2@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz#440f1b70ccfaabc6b676d196239b138f8a2cfba5" - integrity sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w== +"babel-plugin-polyfill-corejs2@^0.3.0": + "integrity" "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==" + "resolved" "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz" + "version" "0.3.1" dependencies: "@babel/compat-data" "^7.13.11" "@babel/helper-define-polyfill-provider" "^0.3.1" - semver "^6.1.1" + "semver" "^6.1.1" -babel-plugin-polyfill-corejs3@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz#aabe4b2fa04a6e038b688c5e55d44e78cd3a5f72" - integrity sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ== +"babel-plugin-polyfill-corejs3@^0.5.0": + "integrity" "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==" + "resolved" "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz" + "version" "0.5.2" dependencies: "@babel/helper-define-polyfill-provider" "^0.3.1" - core-js-compat "^3.21.0" + "core-js-compat" "^3.21.0" -babel-plugin-polyfill-regenerator@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz#2c0678ea47c75c8cc2fbb1852278d8fb68233990" - integrity sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A== +"babel-plugin-polyfill-regenerator@^0.3.0": + "integrity" "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==" + "resolved" "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz" + "version" "0.3.1" dependencies: "@babel/helper-define-polyfill-provider" "^0.3.1" -bail@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" - integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base16@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/base16/-/base16-1.0.0.tgz#e297f60d7ec1014a7a971a39ebc8a98c0b681e70" - integrity sha1-4pf2DX7BAUp6lxo568ipjAtoHnA= - -batch@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" - integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= - -big.js@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -bluebird@^3.7.1: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - -body-parser@1.19.2: - version "1.19.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.2.tgz#4714ccd9c157d44797b8b5607d72c0b89952f26e" - integrity sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw== - dependencies: - bytes "3.1.2" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.8.1" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.9.7" - raw-body "2.4.3" - type-is "~1.6.18" - -bonjour@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" - integrity sha1-jokKGD2O6aI5OzhExpGkK897yfU= - dependencies: - array-flatten "^2.1.0" - deep-equal "^1.0.1" - dns-equal "^1.0.0" - dns-txt "^2.0.2" - multicast-dns "^6.0.1" - multicast-dns-service-types "^1.1.0" - -boolbase@^1.0.0, boolbase@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= - -boxen@^5.0.0, boxen@^5.0.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" - integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== - dependencies: - ansi-align "^3.0.0" - camelcase "^6.2.0" - chalk "^4.1.0" - cli-boxes "^2.2.1" - string-width "^4.2.2" - type-fest "^0.20.2" - widest-line "^3.1.0" - wrap-ansi "^7.0.0" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^3.0.1, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.17.5, browserslist@^4.18.1, browserslist@^4.19.1: - version "4.19.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3" - integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A== - dependencies: - caniuse-lite "^1.0.30001286" - electron-to-chromium "^1.4.17" - escalade "^3.1.1" - node-releases "^2.0.1" - picocolors "^1.0.0" - -buble-jsx-only@^0.19.8: - version "0.19.8" - resolved "https://registry.yarnpkg.com/buble-jsx-only/-/buble-jsx-only-0.19.8.tgz#6e3524aa0f1c523de32496ac9aceb9cc2b493867" - integrity sha512-7AW19pf7PrKFnGTEDzs6u9+JZqQwM1VnLS19OlqYDhXomtFFknnoQJAPHeg84RMFWAvOhYrG7harizJNwUKJsA== - dependencies: - acorn "^6.1.1" - acorn-dynamic-import "^4.0.0" - acorn-jsx "^5.0.1" - chalk "^2.4.2" - magic-string "^0.25.3" - minimist "^1.2.0" - regexpu-core "^4.5.4" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -buffer-indexof@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" - integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== - -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^1.0.2" - -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camel-case@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" - integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== - dependencies: - pascal-case "^3.1.2" - tslib "^2.0.3" - -camelcase-css@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" - integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== - -camelcase@^6.2.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -caniuse-api@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" - integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== - dependencies: - browserslist "^4.0.0" - caniuse-lite "^1.0.0" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001297: - version "1.0.30001312" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz#e11eba4b87e24d22697dae05455d5aea28550d5f" - integrity sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ== - -ccount@^1.0.0, ccount@^1.0.3: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" - integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== - -chalk@^2.0.0, chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.1.0, chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -character-entities-legacy@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" - integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== - -character-entities@^1.0.0: - version "1.2.4" - resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" - integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== - -character-reference-invalid@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" - integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== - -cheerio-select@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-1.5.0.tgz#faf3daeb31b17c5e1a9dabcee288aaf8aafa5823" - integrity sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg== - dependencies: - css-select "^4.1.3" - css-what "^5.0.1" - domelementtype "^2.2.0" - domhandler "^4.2.0" - domutils "^2.7.0" - -cheerio@^0.22.0: - version "0.22.0" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" - integrity sha1-qbqoYKP5tZWmuBsahocxIe06Jp4= - dependencies: - css-select "~1.2.0" - dom-serializer "~0.1.0" - entities "~1.1.1" - htmlparser2 "^3.9.1" - lodash.assignin "^4.0.9" - lodash.bind "^4.1.4" - lodash.defaults "^4.0.1" - lodash.filter "^4.4.0" - lodash.flatten "^4.2.0" - lodash.foreach "^4.3.0" - lodash.map "^4.4.0" - lodash.merge "^4.4.0" - lodash.pick "^4.2.1" - lodash.reduce "^4.4.0" - lodash.reject "^4.4.0" - lodash.some "^4.4.0" - -cheerio@^1.0.0-rc.10: - version "1.0.0-rc.10" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.10.tgz#2ba3dcdfcc26e7956fc1f440e61d51c643379f3e" - integrity sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw== - dependencies: - cheerio-select "^1.5.0" - dom-serializer "^1.3.2" - domhandler "^4.2.0" - htmlparser2 "^6.1.0" - parse5 "^6.0.1" - parse5-htmlparser2-tree-adapter "^6.0.1" - tslib "^2.2.0" - -chokidar@^3.4.2, chokidar@^3.5.2, chokidar@^3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" +"bail@^1.0.0": + "integrity" "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==" + "resolved" "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz" + "version" "1.0.5" + +"balanced-match@^1.0.0": + "integrity" "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "resolved" "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + "version" "1.0.2" + +"base16@^1.0.0": + "integrity" "sha1-4pf2DX7BAUp6lxo568ipjAtoHnA=" + "resolved" "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz" + "version" "1.0.0" + +"batch@0.6.1": + "integrity" "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" + "resolved" "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz" + "version" "0.6.1" + +"big.js@^5.2.2": + "integrity" "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + "resolved" "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz" + "version" "5.2.2" + +"binary-extensions@^2.0.0": + "integrity" "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + "resolved" "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" + "version" "2.2.0" + +"bluebird@^3.7.1": + "integrity" "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + "resolved" "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz" + "version" "3.7.2" + +"body-parser@1.19.2": + "integrity" "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==" + "resolved" "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz" + "version" "1.19.2" + dependencies: + "bytes" "3.1.2" + "content-type" "~1.0.4" + "debug" "2.6.9" + "depd" "~1.1.2" + "http-errors" "1.8.1" + "iconv-lite" "0.4.24" + "on-finished" "~2.3.0" + "qs" "6.9.7" + "raw-body" "2.4.3" + "type-is" "~1.6.18" + +"bonjour@^3.5.0": + "integrity" "sha1-jokKGD2O6aI5OzhExpGkK897yfU=" + "resolved" "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz" + "version" "3.5.0" + dependencies: + "array-flatten" "^2.1.0" + "deep-equal" "^1.0.1" + "dns-equal" "^1.0.0" + "dns-txt" "^2.0.2" + "multicast-dns" "^6.0.1" + "multicast-dns-service-types" "^1.1.0" + +"boolbase@^1.0.0", "boolbase@~1.0.0": + "integrity" "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + "resolved" "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz" + "version" "1.0.0" + +"boxen@^5.0.0", "boxen@^5.0.1": + "integrity" "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==" + "resolved" "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz" + "version" "5.1.2" + dependencies: + "ansi-align" "^3.0.0" + "camelcase" "^6.2.0" + "chalk" "^4.1.0" + "cli-boxes" "^2.2.1" + "string-width" "^4.2.2" + "type-fest" "^0.20.2" + "widest-line" "^3.1.0" + "wrap-ansi" "^7.0.0" + +"brace-expansion@^1.1.7": + "integrity" "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==" + "resolved" "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + "version" "1.1.11" + dependencies: + "balanced-match" "^1.0.0" + "concat-map" "0.0.1" + +"braces@^3.0.1", "braces@~3.0.2": + "integrity" "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==" + "resolved" "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "fill-range" "^7.0.1" + +"browserslist@^4.0.0", "browserslist@^4.14.5", "browserslist@^4.16.6", "browserslist@^4.18.1", "browserslist@^4.19.1", "browserslist@^4.21.3", "browserslist@>= 4.21.0": + "integrity" "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==" + "resolved" "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz" + "version" "4.21.5" + dependencies: + "caniuse-lite" "^1.0.30001449" + "electron-to-chromium" "^1.4.284" + "node-releases" "^2.0.8" + "update-browserslist-db" "^1.0.10" + +"buble-jsx-only@^0.19.8": + "integrity" "sha512-7AW19pf7PrKFnGTEDzs6u9+JZqQwM1VnLS19OlqYDhXomtFFknnoQJAPHeg84RMFWAvOhYrG7harizJNwUKJsA==" + "resolved" "https://registry.npmjs.org/buble-jsx-only/-/buble-jsx-only-0.19.8.tgz" + "version" "0.19.8" + dependencies: + "acorn" "^6.1.1" + "acorn-dynamic-import" "^4.0.0" + "acorn-jsx" "^5.0.1" + "chalk" "^2.4.2" + "magic-string" "^0.25.3" + "minimist" "^1.2.0" + "regexpu-core" "^4.5.4" + +"buffer-from@^1.0.0": + "integrity" "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "resolved" "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" + "version" "1.1.2" + +"buffer-indexof@^1.0.0": + "integrity" "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==" + "resolved" "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz" + "version" "1.1.1" + +"bytes@3.0.0": + "integrity" "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + "resolved" "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz" + "version" "3.0.0" + +"bytes@3.1.2": + "integrity" "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + "resolved" "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" + "version" "3.1.2" + +"cacheable-request@^6.0.0": + "integrity" "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==" + "resolved" "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "clone-response" "^1.0.2" + "get-stream" "^5.1.0" + "http-cache-semantics" "^4.0.0" + "keyv" "^3.0.0" + "lowercase-keys" "^2.0.0" + "normalize-url" "^4.1.0" + "responselike" "^1.0.2" + +"call-bind@^1.0.0", "call-bind@^1.0.2": + "integrity" "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==" + "resolved" "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "function-bind" "^1.1.1" + "get-intrinsic" "^1.0.2" + +"callsites@^3.0.0": + "integrity" "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + "resolved" "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + "version" "3.1.0" + +"camel-case@^4.1.2": + "integrity" "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==" + "resolved" "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "pascal-case" "^3.1.2" + "tslib" "^2.0.3" + +"camelcase-css@2.0.1": + "integrity" "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==" + "resolved" "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz" + "version" "2.0.1" + +"camelcase@^6.2.0": + "integrity" "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + "resolved" "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + "version" "6.3.0" + +"caniuse-api@^3.0.0": + "integrity" "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==" + "resolved" "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "browserslist" "^4.0.0" + "caniuse-lite" "^1.0.0" + "lodash.memoize" "^4.1.2" + "lodash.uniq" "^4.5.0" + +"caniuse-lite@^1.0.0", "caniuse-lite@^1.0.30001297", "caniuse-lite@^1.0.30001449": + "integrity" "sha512-ewtFBSfWjEmxUgNBSZItFSmVtvk9zkwkl1OfRZlKA8slltRN+/C/tuGVrF9styXkN36Yu3+SeJ1qkXxDEyNZ5w==" + "resolved" "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001466.tgz" + "version" "1.0.30001466" + +"ccount@^1.0.0", "ccount@^1.0.3": + "integrity" "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==" + "resolved" "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz" + "version" "1.1.0" + +"chalk@^2.0.0": + "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "ansi-styles" "^3.2.1" + "escape-string-regexp" "^1.0.5" + "supports-color" "^5.3.0" + +"chalk@^2.4.2": + "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "ansi-styles" "^3.2.1" + "escape-string-regexp" "^1.0.5" + "supports-color" "^5.3.0" + +"chalk@^4.1.0", "chalk@^4.1.2": + "integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "ansi-styles" "^4.1.0" + "supports-color" "^7.1.0" + +"character-entities-legacy@^1.0.0": + "integrity" "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==" + "resolved" "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz" + "version" "1.1.4" + +"character-entities@^1.0.0": + "integrity" "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==" + "resolved" "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz" + "version" "1.2.4" + +"character-reference-invalid@^1.0.0": + "integrity" "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==" + "resolved" "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz" + "version" "1.1.4" + +"cheerio-select@^1.5.0": + "integrity" "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==" + "resolved" "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz" + "version" "1.5.0" + dependencies: + "css-select" "^4.1.3" + "css-what" "^5.0.1" + "domelementtype" "^2.2.0" + "domhandler" "^4.2.0" + "domutils" "^2.7.0" + +"cheerio@^0.22.0": + "integrity" "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=" + "resolved" "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz" + "version" "0.22.0" + dependencies: + "css-select" "~1.2.0" + "dom-serializer" "~0.1.0" + "entities" "~1.1.1" + "htmlparser2" "^3.9.1" + "lodash.assignin" "^4.0.9" + "lodash.bind" "^4.1.4" + "lodash.defaults" "^4.0.1" + "lodash.filter" "^4.4.0" + "lodash.flatten" "^4.2.0" + "lodash.foreach" "^4.3.0" + "lodash.map" "^4.4.0" + "lodash.merge" "^4.4.0" + "lodash.pick" "^4.2.1" + "lodash.reduce" "^4.4.0" + "lodash.reject" "^4.4.0" + "lodash.some" "^4.4.0" + +"cheerio@^1.0.0-rc.10": + "integrity" "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==" + "resolved" "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz" + "version" "1.0.0-rc.10" + dependencies: + "cheerio-select" "^1.5.0" + "dom-serializer" "^1.3.2" + "domhandler" "^4.2.0" + "htmlparser2" "^6.1.0" + "parse5" "^6.0.1" + "parse5-htmlparser2-tree-adapter" "^6.0.1" + "tslib" "^2.2.0" + +"chokidar@^3.4.2", "chokidar@^3.5.2", "chokidar@^3.5.3": + "integrity" "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==" + "resolved" "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" + "version" "3.5.3" + dependencies: + "anymatch" "~3.1.2" + "braces" "~3.0.2" + "glob-parent" "~5.1.2" + "is-binary-path" "~2.1.0" + "is-glob" "~4.0.1" + "normalize-path" "~3.0.0" + "readdirp" "~3.6.0" optionalDependencies: - fsevents "~2.3.2" - -chrome-trace-event@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" - integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== - -ci-info@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" - integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== - -classnames@^2.2.6: - version "2.3.1" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" - integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== - -clean-css@^5.1.5, clean-css@^5.2.2: - version "5.2.4" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.2.4.tgz#982b058f8581adb2ae062520808fb2429bd487a4" - integrity sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg== - dependencies: - source-map "~0.6.0" - -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - -cli-boxes@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" - integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== - -clone-deep@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" - integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== - dependencies: - is-plain-object "^2.0.4" - kind-of "^6.0.2" - shallow-clone "^3.0.0" - -clone-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= - dependencies: - mimic-response "^1.0.0" - -clsx@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" - integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== - -collapse-white-space@^1.0.2: - version "1.0.6" - resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287" - integrity sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -colord@^2.9.1: - version "2.9.2" - resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.2.tgz#25e2bacbbaa65991422c07ea209e2089428effb1" - integrity sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ== - -colorette@^2.0.10: - version "2.0.16" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" - integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== - -combine-promises@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/combine-promises/-/combine-promises-1.1.0.tgz#72db90743c0ca7aab7d0d8d2052fd7b0f674de71" - integrity sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg== - -comma-separated-tokens@^1.0.0: - version "1.0.8" - resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" - integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== - -commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -commander@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" - integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== - -commander@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== - -commander@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" - integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= - -compressible@~2.0.16: - version "2.0.18" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" - integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== - dependencies: - mime-db ">= 1.43.0 < 2" - -compression@^1.7.4: - version "1.7.4" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" - integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== - dependencies: - accepts "~1.3.5" - bytes "3.0.0" - compressible "~2.0.16" - debug "2.6.9" - on-headers "~1.0.2" - safe-buffer "5.1.2" - vary "~1.1.2" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -configstore@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" - integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== - dependencies: - dot-prop "^5.2.0" - graceful-fs "^4.1.2" - make-dir "^3.0.0" - unique-string "^2.0.0" - write-file-atomic "^3.0.0" - xdg-basedir "^4.0.0" - -connect-history-api-fallback@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" - integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== - -consola@^2.15.3: - version "2.15.3" - resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.3.tgz#2e11f98d6a4be71ff72e0bdf07bd23e12cb61550" - integrity sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw== - -content-disposition@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= - -content-disposition@0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" - integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== - dependencies: - safe-buffer "5.2.1" - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -convert-source-map@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" - integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== - dependencies: - safe-buffer "~5.1.1" - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" - integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== - -copy-text-to-clipboard@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz#8cbf8f90e0a47f12e4a24743736265d157bce69c" - integrity sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q== - -copy-webpack-plugin@^10.2.0: - version "10.2.4" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz#6c854be3fdaae22025da34b9112ccf81c63308fe" - integrity sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg== - dependencies: - fast-glob "^3.2.7" - glob-parent "^6.0.1" - globby "^12.0.2" - normalize-path "^3.0.0" - schema-utils "^4.0.0" - serialize-javascript "^6.0.0" - -core-js-compat@^3.20.2, core-js-compat@^3.21.0: - version "3.21.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.21.1.tgz#cac369f67c8d134ff8f9bd1623e3bc2c42068c82" - integrity sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g== - dependencies: - browserslist "^4.19.1" - semver "7.0.0" - -core-js-pure@^3.20.2: - version "3.21.1" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.21.1.tgz#8c4d1e78839f5f46208de7230cebfb72bc3bdb51" - integrity sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ== - -core-js@^3.18.0: - version "3.21.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.21.1.tgz#f2e0ddc1fc43da6f904706e8e955bc19d06a0d94" - integrity sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig== - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -cosmiconfig@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" - integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== + "fsevents" "~2.3.2" + +"chrome-trace-event@^1.0.2": + "integrity" "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==" + "resolved" "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz" + "version" "1.0.3" + +"ci-info@^2.0.0": + "integrity" "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + "resolved" "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz" + "version" "2.0.0" + +"classnames@^2.2.6": + "integrity" "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" + "resolved" "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz" + "version" "2.3.1" + +"clean-css@^5.1.5", "clean-css@^5.2.2": + "integrity" "sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg==" + "resolved" "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz" + "version" "5.2.4" + dependencies: + "source-map" "~0.6.0" + +"clean-stack@^2.0.0": + "integrity" "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + "resolved" "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz" + "version" "2.2.0" + +"cli-boxes@^2.2.1": + "integrity" "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==" + "resolved" "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz" + "version" "2.2.1" + +"clone-deep@^4.0.1": + "integrity" "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==" + "resolved" "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz" + "version" "4.0.1" + dependencies: + "is-plain-object" "^2.0.4" + "kind-of" "^6.0.2" + "shallow-clone" "^3.0.0" + +"clone-response@^1.0.2": + "integrity" "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=" + "resolved" "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "mimic-response" "^1.0.0" + +"clsx@^1.1.1": + "integrity" "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==" + "resolved" "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz" + "version" "1.1.1" + +"collapse-white-space@^1.0.2": + "integrity" "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==" + "resolved" "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz" + "version" "1.0.6" + +"color-convert@^1.9.0": + "integrity" "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==" + "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + "version" "1.9.3" + dependencies: + "color-name" "1.1.3" + +"color-convert@^2.0.1": + "integrity" "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==" + "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "color-name" "~1.1.4" + +"color-name@~1.1.4": + "integrity" "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + "version" "1.1.4" + +"color-name@1.1.3": + "integrity" "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + "version" "1.1.3" + +"colord@^2.9.1": + "integrity" "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==" + "resolved" "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz" + "version" "2.9.2" + +"colorette@^2.0.10": + "integrity" "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==" + "resolved" "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz" + "version" "2.0.16" + +"combine-promises@^1.1.0": + "integrity" "sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg==" + "resolved" "https://registry.npmjs.org/combine-promises/-/combine-promises-1.1.0.tgz" + "version" "1.1.0" + +"comma-separated-tokens@^1.0.0": + "integrity" "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==" + "resolved" "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz" + "version" "1.0.8" + +"commander@^2.20.0": + "integrity" "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "resolved" "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" + "version" "2.20.3" + +"commander@^5.1.0": + "integrity" "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" + "resolved" "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz" + "version" "5.1.0" + +"commander@^7.2.0": + "integrity" "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + "resolved" "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz" + "version" "7.2.0" + +"commander@^8.3.0": + "integrity" "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==" + "resolved" "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz" + "version" "8.3.0" + +"commondir@^1.0.1": + "integrity" "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + "resolved" "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" + "version" "1.0.1" + +"compressible@~2.0.16": + "integrity" "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==" + "resolved" "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz" + "version" "2.0.18" + dependencies: + "mime-db" ">= 1.43.0 < 2" + +"compression@^1.7.4": + "integrity" "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==" + "resolved" "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz" + "version" "1.7.4" + dependencies: + "accepts" "~1.3.5" + "bytes" "3.0.0" + "compressible" "~2.0.16" + "debug" "2.6.9" + "on-headers" "~1.0.2" + "safe-buffer" "5.1.2" + "vary" "~1.1.2" + +"concat-map@0.0.1": + "integrity" "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "resolved" "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + "version" "0.0.1" + +"configstore@^5.0.1": + "integrity" "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==" + "resolved" "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "dot-prop" "^5.2.0" + "graceful-fs" "^4.1.2" + "make-dir" "^3.0.0" + "unique-string" "^2.0.0" + "write-file-atomic" "^3.0.0" + "xdg-basedir" "^4.0.0" + +"connect-history-api-fallback@^1.6.0": + "integrity" "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==" + "resolved" "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz" + "version" "1.6.0" + +"consola@^2.15.3": + "integrity" "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" + "resolved" "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz" + "version" "2.15.3" + +"content-disposition@0.5.2": + "integrity" "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + "resolved" "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz" + "version" "0.5.2" + +"content-disposition@0.5.4": + "integrity" "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==" + "resolved" "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz" + "version" "0.5.4" + dependencies: + "safe-buffer" "5.2.1" + +"content-type@~1.0.4": + "integrity" "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + "resolved" "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz" + "version" "1.0.4" + +"convert-source-map@^1.7.0": + "integrity" "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==" + "resolved" "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz" + "version" "1.8.0" + dependencies: + "safe-buffer" "~5.1.1" + +"cookie-signature@1.0.6": + "integrity" "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "resolved" "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + "version" "1.0.6" + +"cookie@0.4.2": + "integrity" "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + "resolved" "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz" + "version" "0.4.2" + +"copy-text-to-clipboard@^3.0.1": + "integrity" "sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q==" + "resolved" "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz" + "version" "3.0.1" + +"copy-webpack-plugin@^10.2.0": + "integrity" "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==" + "resolved" "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz" + "version" "10.2.4" + dependencies: + "fast-glob" "^3.2.7" + "glob-parent" "^6.0.1" + "globby" "^12.0.2" + "normalize-path" "^3.0.0" + "schema-utils" "^4.0.0" + "serialize-javascript" "^6.0.0" + +"core-js-compat@^3.20.2", "core-js-compat@^3.21.0": + "integrity" "sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g==" + "resolved" "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.21.1.tgz" + "version" "3.21.1" + dependencies: + "browserslist" "^4.19.1" + "semver" "7.0.0" + +"core-js-pure@^3.20.2": + "integrity" "sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ==" + "resolved" "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.21.1.tgz" + "version" "3.21.1" + +"core-js@^3.18.0": + "integrity" "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==" + "resolved" "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz" + "version" "3.21.1" + +"core-util-is@~1.0.0": + "integrity" "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "resolved" "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" + "version" "1.0.3" + +"cosmiconfig@^6.0.0": + "integrity" "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==" + "resolved" "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz" + "version" "6.0.0" dependencies: "@types/parse-json" "^4.0.0" - import-fresh "^3.1.0" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.7.2" + "import-fresh" "^3.1.0" + "parse-json" "^5.0.0" + "path-type" "^4.0.0" + "yaml" "^1.7.2" -cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" - integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== +"cosmiconfig@^7.0.0", "cosmiconfig@^7.0.1": + "integrity" "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==" + "resolved" "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz" + "version" "7.0.1" dependencies: "@types/parse-json" "^4.0.0" - import-fresh "^3.2.1" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.10.0" - -cross-fetch@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" - integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== - dependencies: - node-fetch "2.6.7" - -cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -crypto-random-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" - integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== - -css-declaration-sorter@^6.0.3: - version "6.1.4" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz#b9bfb4ed9a41f8dcca9bf7184d849ea94a8294b4" - integrity sha512-lpfkqS0fctcmZotJGhnxkIyJWvBXgpyi2wsFd4J8VB7wzyrT6Ch/3Q+FMNJpjK4gu1+GN5khOnpU2ZVKrLbhCw== - dependencies: - timsort "^0.3.0" - -css-loader@^6.5.1: - version "6.6.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.6.0.tgz#c792ad5510bd1712618b49381bd0310574fafbd3" - integrity sha512-FK7H2lisOixPT406s5gZM1S3l8GrfhEBT3ZiL2UX1Ng1XWs0y2GPllz/OTyvbaHe12VgQrIXIzuEGVlbUhodqg== - dependencies: - icss-utils "^5.1.0" - postcss "^8.4.5" - postcss-modules-extract-imports "^3.0.0" - postcss-modules-local-by-default "^4.0.0" - postcss-modules-scope "^3.0.0" - postcss-modules-values "^4.0.0" - postcss-value-parser "^4.2.0" - semver "^7.3.5" - -css-minimizer-webpack-plugin@^3.3.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz#ab78f781ced9181992fe7b6e4f3422e76429878f" - integrity sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q== - dependencies: - cssnano "^5.0.6" - jest-worker "^27.0.2" - postcss "^8.3.5" - schema-utils "^4.0.0" - serialize-javascript "^6.0.0" - source-map "^0.6.1" - -css-select@^4.1.3: - version "4.2.1" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.2.1.tgz#9e665d6ae4c7f9d65dbe69d0316e3221fb274cdd" - integrity sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ== - dependencies: - boolbase "^1.0.0" - css-what "^5.1.0" - domhandler "^4.3.0" - domutils "^2.8.0" - nth-check "^2.0.1" - -css-select@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" - integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= - dependencies: - boolbase "~1.0.0" - css-what "2.1" - domutils "1.5.1" - nth-check "~1.0.1" - -css-tree@^1.1.2, css-tree@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" - integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== - dependencies: - mdn-data "2.0.14" - source-map "^0.6.1" - -css-what@2.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" - integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== - -css-what@^5.0.1, css-what@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" - integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== - -cssesc@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" - integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== - -cssnano-preset-advanced@^5.1.4: - version "5.1.12" - resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-5.1.12.tgz#11f5b0c4e3c32bcfd475465a283fa14dec8df972" - integrity sha512-5WWV9mbqVNwH4nRjs5UbhNl7eKo+16eYNzGogmz0Sa6iqWUeLdN8oo83WuTTqz5vjEKhTbRM5oX6WV1i6ees6g== - dependencies: - autoprefixer "^10.3.7" - cssnano-preset-default "^5.1.12" - postcss-discard-unused "^5.0.3" - postcss-merge-idents "^5.0.3" - postcss-reduce-idents "^5.0.3" - postcss-zindex "^5.0.2" - -cssnano-preset-default@^5.1.12: - version "5.1.12" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.1.12.tgz#64e2ad8e27a279e1413d2d2383ef89a41c909be9" - integrity sha512-rO/JZYyjW1QNkWBxMGV28DW7d98UDLaF759frhli58QFehZ+D/LSmwQ2z/ylBAe2hUlsIWTq6NYGfQPq65EF9w== - dependencies: - css-declaration-sorter "^6.0.3" - cssnano-utils "^3.0.2" - postcss-calc "^8.2.0" - postcss-colormin "^5.2.5" - postcss-convert-values "^5.0.4" - postcss-discard-comments "^5.0.3" - postcss-discard-duplicates "^5.0.3" - postcss-discard-empty "^5.0.3" - postcss-discard-overridden "^5.0.4" - postcss-merge-longhand "^5.0.6" - postcss-merge-rules "^5.0.6" - postcss-minify-font-values "^5.0.4" - postcss-minify-gradients "^5.0.6" - postcss-minify-params "^5.0.5" - postcss-minify-selectors "^5.1.3" - postcss-normalize-charset "^5.0.3" - postcss-normalize-display-values "^5.0.3" - postcss-normalize-positions "^5.0.4" - postcss-normalize-repeat-style "^5.0.4" - postcss-normalize-string "^5.0.4" - postcss-normalize-timing-functions "^5.0.3" - postcss-normalize-unicode "^5.0.4" - postcss-normalize-url "^5.0.5" - postcss-normalize-whitespace "^5.0.4" - postcss-ordered-values "^5.0.5" - postcss-reduce-initial "^5.0.3" - postcss-reduce-transforms "^5.0.4" - postcss-svgo "^5.0.4" - postcss-unique-selectors "^5.0.4" - -cssnano-utils@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.0.2.tgz#d82b4991a27ba6fec644b39bab35fe027137f516" - integrity sha512-KhprijuQv2sP4kT92sSQwhlK3SJTbDIsxcfIEySB0O+3m9esFOai7dP9bMx5enHAh2MwarVIcnwiWoOm01RIbQ== - -cssnano@^5.0.6, cssnano@^5.0.8: - version "5.0.17" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.0.17.tgz#ff45713c05cfc780a1aeb3e663b6f224d091cabf" - integrity sha512-fmjLP7k8kL18xSspeXTzRhaFtRI7DL9b8IcXR80JgtnWBpvAzHT7sCR/6qdn0tnxIaINUN6OEQu83wF57Gs3Xw== - dependencies: - cssnano-preset-default "^5.1.12" - lilconfig "^2.0.3" - yaml "^1.10.2" - -csso@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" - integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== - dependencies: - css-tree "^1.1.2" - -csstype@^3.0.2: - version "3.0.10" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.10.tgz#2ad3a7bed70f35b965707c092e5f30b327c290e5" - integrity sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA== - -debug@2.6.9, debug@^2.6.0: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^3.1.1: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -debug@^4.1.0, debug@^4.1.1: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== - dependencies: - ms "2.1.2" - -decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= - dependencies: - mimic-response "^1.0.0" - -deep-equal@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" - integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== - dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" - object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -deepmerge@^1.3.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-1.5.2.tgz#10499d868844cdad4fee0842df8c7f6f0c95a753" - integrity sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ== - -deepmerge@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" - integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== - -default-gateway@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" - integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== - dependencies: - execa "^5.0.0" - -defer-to-connect@^1.0.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" - integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== - -define-lazy-prop@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" - integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== - -define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -del@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/del/-/del-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952" - integrity sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ== - dependencies: - globby "^11.0.1" - graceful-fs "^4.2.4" - is-glob "^4.0.1" - is-path-cwd "^2.2.0" - is-path-inside "^3.0.2" - p-map "^4.0.0" - rimraf "^3.0.2" - slash "^3.0.0" - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - -detab@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/detab/-/detab-2.0.4.tgz#b927892069aff405fbb9a186fe97a44a92a94b43" - integrity sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g== - dependencies: - repeat-string "^1.5.4" - -detect-node@^2.0.4: - version "2.1.0" - resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" - integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== - -detect-port-alt@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/detect-port-alt/-/detect-port-alt-1.1.6.tgz#24707deabe932d4a3cf621302027c2b266568275" - integrity sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q== - dependencies: - address "^1.0.1" - debug "^2.6.0" - -detect-port@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.3.0.tgz#d9c40e9accadd4df5cac6a782aefd014d573d1f1" - integrity sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ== - dependencies: - address "^1.0.1" - debug "^2.6.0" - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -dns-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" - integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= - -dns-packet@^1.3.1: - version "1.3.4" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f" - integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA== - dependencies: - ip "^1.1.0" - safe-buffer "^5.0.1" - -dns-txt@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" - integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY= - dependencies: - buffer-indexof "^1.0.0" - -dom-converter@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" - integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== - dependencies: - utila "~0.4" - -dom-serializer@0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" - integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== - dependencies: - domelementtype "^2.0.1" - entities "^2.0.0" - -dom-serializer@^1.0.1, dom-serializer@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" - integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== - dependencies: - domelementtype "^2.0.1" - domhandler "^4.2.0" - entities "^2.0.0" - -dom-serializer@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" - integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== - dependencies: - domelementtype "^1.3.0" - entities "^1.1.1" - -domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== - -domelementtype@^2.0.1, domelementtype@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" - integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== - -domhandler@^2.3.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" - integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== - dependencies: - domelementtype "1" - -domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.0.tgz#16c658c626cf966967e306f966b431f77d4a5626" - integrity sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g== - dependencies: - domelementtype "^2.2.0" - -domutils@1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" - integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= - dependencies: - dom-serializer "0" - domelementtype "1" - -domutils@^1.5.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== - dependencies: - dom-serializer "0" - domelementtype "1" - -domutils@^2.5.2, domutils@^2.7.0, domutils@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" - integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== - dependencies: - dom-serializer "^1.0.1" - domelementtype "^2.2.0" - domhandler "^4.2.0" - -dot-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" - integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - -dot-prop@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" - integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== - dependencies: - is-obj "^2.0.0" - -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= - -duplexer@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" - integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -electron-to-chromium@^1.4.17: - version "1.4.71" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.71.tgz#17056914465da0890ce00351a3b946fd4cd51ff6" - integrity sha512-Hk61vXXKRb2cd3znPE9F+2pLWdIOmP7GjiTj45y6L3W/lO+hSnUSUhq+6lEaERWBdZOHbk2s3YV5c9xVl3boVw== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emojis-list@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" - integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== - -emoticon@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/emoticon/-/emoticon-3.2.0.tgz#c008ca7d7620fac742fe1bf4af8ff8fed154ae7f" - integrity sha512-SNujglcLTTg+lDAcApPNgEdudaqQFiAbJCqzjNxJkvN9vAwCGi0uu8IUVvx+f16h+V44KCY6Y2yboroc9pilHg== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -enhanced-resolve@^5.8.3: - version "5.9.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.0.tgz#49ac24953ac8452ed8fed2ef1340fc8e043667ee" - integrity sha512-weDYmzbBygL7HzGGS26M3hGQx68vehdEg6VUmqSOaFzXExFqlnKuSvsEJCVGQHScS8CQMbrAqftT+AzzHNt/YA== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -entities@^1.1.1, entities@~1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" - integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== - -entities@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" - integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== - -entities@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4" - integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-module-lexer@^0.9.0: - version "0.9.3" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" - integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-goat@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" - integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== - -escape-html@^1.0.3, escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-scope@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -eta@^1.12.3: - version "1.12.3" - resolved "https://registry.yarnpkg.com/eta/-/eta-1.12.3.tgz#2982d08adfbef39f9fa50e2fbd42d7337e7338b1" - integrity sha512-qHixwbDLtekO/d51Yr4glcaUJCIjGVJyTzuqV4GPlgZo1YpgOKG+avQynErZIYrfM6JIJdtiG2Kox8tbb+DoGg== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - -eval@^0.1.4: - version "0.1.6" - resolved "https://registry.yarnpkg.com/eval/-/eval-0.1.6.tgz#9620d7d8c85515e97e6b47c5814f46ae381cb3cc" - integrity sha512-o0XUw+5OGkXw4pJZzQoXUk+H87DHuC+7ZE//oSrRGtatTmr12oTnLfg6QOq9DyTt0c/p4TwzgmkKrBzWTSizyQ== - dependencies: - require-like ">= 0.1.1" - -eventemitter3@^4.0.0: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -events@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -execa@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - -express@^4.17.1: - version "4.17.3" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.3.tgz#f6c7302194a4fb54271b73a1fe7a06478c8f85a1" - integrity sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg== - dependencies: - accepts "~1.3.8" - array-flatten "1.1.1" - body-parser "1.19.2" - content-disposition "0.5.4" - content-type "~1.0.4" - cookie "0.4.2" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "~1.1.2" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.7" - qs "6.9.7" - range-parser "~1.2.1" - safe-buffer "5.2.1" - send "0.17.2" - serve-static "1.14.2" - setprototypeof "1.2.0" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-glob@^3.2.7, fast-glob@^3.2.9: - version "3.2.11" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" - integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== + "import-fresh" "^3.2.1" + "parse-json" "^5.0.0" + "path-type" "^4.0.0" + "yaml" "^1.10.0" + +"cross-fetch@^3.1.5": + "integrity" "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==" + "resolved" "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz" + "version" "3.1.5" + dependencies: + "node-fetch" "2.6.7" + +"cross-spawn@^7.0.3": + "integrity" "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==" + "resolved" "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" + "version" "7.0.3" + dependencies: + "path-key" "^3.1.0" + "shebang-command" "^2.0.0" + "which" "^2.0.1" + +"crypto-random-string@^2.0.0": + "integrity" "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" + "resolved" "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz" + "version" "2.0.0" + +"css-declaration-sorter@^6.0.3": + "integrity" "sha512-lpfkqS0fctcmZotJGhnxkIyJWvBXgpyi2wsFd4J8VB7wzyrT6Ch/3Q+FMNJpjK4gu1+GN5khOnpU2ZVKrLbhCw==" + "resolved" "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz" + "version" "6.1.4" + dependencies: + "timsort" "^0.3.0" + +"css-loader@^6.5.1": + "integrity" "sha512-FK7H2lisOixPT406s5gZM1S3l8GrfhEBT3ZiL2UX1Ng1XWs0y2GPllz/OTyvbaHe12VgQrIXIzuEGVlbUhodqg==" + "resolved" "https://registry.npmjs.org/css-loader/-/css-loader-6.6.0.tgz" + "version" "6.6.0" + dependencies: + "icss-utils" "^5.1.0" + "postcss" "^8.4.5" + "postcss-modules-extract-imports" "^3.0.0" + "postcss-modules-local-by-default" "^4.0.0" + "postcss-modules-scope" "^3.0.0" + "postcss-modules-values" "^4.0.0" + "postcss-value-parser" "^4.2.0" + "semver" "^7.3.5" + +"css-minimizer-webpack-plugin@^3.3.1": + "integrity" "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==" + "resolved" "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz" + "version" "3.4.1" + dependencies: + "cssnano" "^5.0.6" + "jest-worker" "^27.0.2" + "postcss" "^8.3.5" + "schema-utils" "^4.0.0" + "serialize-javascript" "^6.0.0" + "source-map" "^0.6.1" + +"css-select@^4.1.3": + "integrity" "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==" + "resolved" "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz" + "version" "4.2.1" + dependencies: + "boolbase" "^1.0.0" + "css-what" "^5.1.0" + "domhandler" "^4.3.0" + "domutils" "^2.8.0" + "nth-check" "^2.0.1" + +"css-select@~1.2.0": + "integrity" "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=" + "resolved" "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "boolbase" "~1.0.0" + "css-what" "2.1" + "domutils" "1.5.1" + "nth-check" "~1.0.1" + +"css-tree@^1.1.2", "css-tree@^1.1.3": + "integrity" "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==" + "resolved" "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz" + "version" "1.1.3" + dependencies: + "mdn-data" "2.0.14" + "source-map" "^0.6.1" + +"css-what@^5.0.1", "css-what@^5.1.0": + "integrity" "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==" + "resolved" "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz" + "version" "5.1.0" + +"css-what@2.1": + "integrity" "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" + "resolved" "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz" + "version" "2.1.3" + +"cssesc@^3.0.0": + "integrity" "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" + "resolved" "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz" + "version" "3.0.0" + +"cssnano-preset-advanced@^5.1.4": + "integrity" "sha512-5WWV9mbqVNwH4nRjs5UbhNl7eKo+16eYNzGogmz0Sa6iqWUeLdN8oo83WuTTqz5vjEKhTbRM5oX6WV1i6ees6g==" + "resolved" "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-5.1.12.tgz" + "version" "5.1.12" + dependencies: + "autoprefixer" "^10.3.7" + "cssnano-preset-default" "^5.1.12" + "postcss-discard-unused" "^5.0.3" + "postcss-merge-idents" "^5.0.3" + "postcss-reduce-idents" "^5.0.3" + "postcss-zindex" "^5.0.2" + +"cssnano-preset-default@^5.1.12": + "integrity" "sha512-rO/JZYyjW1QNkWBxMGV28DW7d98UDLaF759frhli58QFehZ+D/LSmwQ2z/ylBAe2hUlsIWTq6NYGfQPq65EF9w==" + "resolved" "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.1.12.tgz" + "version" "5.1.12" + dependencies: + "css-declaration-sorter" "^6.0.3" + "cssnano-utils" "^3.0.2" + "postcss-calc" "^8.2.0" + "postcss-colormin" "^5.2.5" + "postcss-convert-values" "^5.0.4" + "postcss-discard-comments" "^5.0.3" + "postcss-discard-duplicates" "^5.0.3" + "postcss-discard-empty" "^5.0.3" + "postcss-discard-overridden" "^5.0.4" + "postcss-merge-longhand" "^5.0.6" + "postcss-merge-rules" "^5.0.6" + "postcss-minify-font-values" "^5.0.4" + "postcss-minify-gradients" "^5.0.6" + "postcss-minify-params" "^5.0.5" + "postcss-minify-selectors" "^5.1.3" + "postcss-normalize-charset" "^5.0.3" + "postcss-normalize-display-values" "^5.0.3" + "postcss-normalize-positions" "^5.0.4" + "postcss-normalize-repeat-style" "^5.0.4" + "postcss-normalize-string" "^5.0.4" + "postcss-normalize-timing-functions" "^5.0.3" + "postcss-normalize-unicode" "^5.0.4" + "postcss-normalize-url" "^5.0.5" + "postcss-normalize-whitespace" "^5.0.4" + "postcss-ordered-values" "^5.0.5" + "postcss-reduce-initial" "^5.0.3" + "postcss-reduce-transforms" "^5.0.4" + "postcss-svgo" "^5.0.4" + "postcss-unique-selectors" "^5.0.4" + +"cssnano-utils@^3.0.2": + "integrity" "sha512-KhprijuQv2sP4kT92sSQwhlK3SJTbDIsxcfIEySB0O+3m9esFOai7dP9bMx5enHAh2MwarVIcnwiWoOm01RIbQ==" + "resolved" "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.0.2.tgz" + "version" "3.0.2" + +"cssnano@^5.0.6", "cssnano@^5.0.8": + "integrity" "sha512-fmjLP7k8kL18xSspeXTzRhaFtRI7DL9b8IcXR80JgtnWBpvAzHT7sCR/6qdn0tnxIaINUN6OEQu83wF57Gs3Xw==" + "resolved" "https://registry.npmjs.org/cssnano/-/cssnano-5.0.17.tgz" + "version" "5.0.17" + dependencies: + "cssnano-preset-default" "^5.1.12" + "lilconfig" "^2.0.3" + "yaml" "^1.10.2" + +"csso@^4.2.0": + "integrity" "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==" + "resolved" "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz" + "version" "4.2.0" + dependencies: + "css-tree" "^1.1.2" + +"csstype@^3.0.2": + "integrity" "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==" + "resolved" "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz" + "version" "3.0.10" + +"debug@^2.6.0", "debug@2.6.9": + "integrity" "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" + "resolved" "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + "version" "2.6.9" + dependencies: + "ms" "2.0.0" + +"debug@^3.1.1": + "integrity" "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==" + "resolved" "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" + "version" "3.2.7" + dependencies: + "ms" "^2.1.1" + +"debug@^4.1.0": + "integrity" "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==" + "resolved" "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz" + "version" "4.3.3" + dependencies: + "ms" "2.1.2" + +"debug@^4.1.1": + "integrity" "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==" + "resolved" "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz" + "version" "4.3.3" + dependencies: + "ms" "2.1.2" + +"decompress-response@^3.3.0": + "integrity" "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=" + "resolved" "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz" + "version" "3.3.0" + dependencies: + "mimic-response" "^1.0.0" + +"deep-equal@^1.0.1": + "integrity" "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==" + "resolved" "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "is-arguments" "^1.0.4" + "is-date-object" "^1.0.1" + "is-regex" "^1.0.4" + "object-is" "^1.0.1" + "object-keys" "^1.1.1" + "regexp.prototype.flags" "^1.2.0" + +"deep-extend@^0.6.0": + "integrity" "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + "resolved" "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz" + "version" "0.6.0" + +"deepmerge@^1.3.2": + "integrity" "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==" + "resolved" "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz" + "version" "1.5.2" + +"deepmerge@^4.2.2": + "integrity" "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" + "resolved" "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz" + "version" "4.2.2" + +"default-gateway@^6.0.3": + "integrity" "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==" + "resolved" "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz" + "version" "6.0.3" + dependencies: + "execa" "^5.0.0" + +"defer-to-connect@^1.0.1": + "integrity" "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + "resolved" "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz" + "version" "1.1.3" + +"define-lazy-prop@^2.0.0": + "integrity" "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" + "resolved" "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz" + "version" "2.0.0" + +"define-properties@^1.1.3": + "integrity" "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==" + "resolved" "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz" + "version" "1.1.3" + dependencies: + "object-keys" "^1.0.12" + +"del@^6.0.0": + "integrity" "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==" + "resolved" "https://registry.npmjs.org/del/-/del-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "globby" "^11.0.1" + "graceful-fs" "^4.2.4" + "is-glob" "^4.0.1" + "is-path-cwd" "^2.2.0" + "is-path-inside" "^3.0.2" + "p-map" "^4.0.0" + "rimraf" "^3.0.2" + "slash" "^3.0.0" + +"depd@~1.1.2": + "integrity" "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "resolved" "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" + "version" "1.1.2" + +"destroy@~1.0.4": + "integrity" "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "resolved" "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" + "version" "1.0.4" + +"detab@2.0.4": + "integrity" "sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g==" + "resolved" "https://registry.npmjs.org/detab/-/detab-2.0.4.tgz" + "version" "2.0.4" + dependencies: + "repeat-string" "^1.5.4" + +"detect-node@^2.0.4": + "integrity" "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + "resolved" "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz" + "version" "2.1.0" + +"detect-port-alt@^1.1.6": + "integrity" "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==" + "resolved" "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz" + "version" "1.1.6" + dependencies: + "address" "^1.0.1" + "debug" "^2.6.0" + +"detect-port@^1.3.0": + "integrity" "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==" + "resolved" "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz" + "version" "1.3.0" + dependencies: + "address" "^1.0.1" + "debug" "^2.6.0" + +"dir-glob@^3.0.1": + "integrity" "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==" + "resolved" "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "path-type" "^4.0.0" + +"dns-equal@^1.0.0": + "integrity" "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" + "resolved" "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz" + "version" "1.0.0" + +"dns-packet@^1.3.1": + "integrity" "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==" + "resolved" "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz" + "version" "1.3.4" + dependencies: + "ip" "^1.1.0" + "safe-buffer" "^5.0.1" + +"dns-txt@^2.0.2": + "integrity" "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=" + "resolved" "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "buffer-indexof" "^1.0.0" + +"dom-converter@^0.2.0": + "integrity" "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==" + "resolved" "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz" + "version" "0.2.0" + dependencies: + "utila" "~0.4" + +"dom-serializer@^1.0.1": + "integrity" "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==" + "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz" + "version" "1.3.2" + dependencies: + "domelementtype" "^2.0.1" + "domhandler" "^4.2.0" + "entities" "^2.0.0" + +"dom-serializer@^1.3.2": + "integrity" "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==" + "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz" + "version" "1.3.2" + dependencies: + "domelementtype" "^2.0.1" + "domhandler" "^4.2.0" + "entities" "^2.0.0" + +"dom-serializer@~0.1.0": + "integrity" "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==" + "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz" + "version" "0.1.1" + dependencies: + "domelementtype" "^1.3.0" + "entities" "^1.1.1" + +"dom-serializer@0": + "integrity" "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==" + "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz" + "version" "0.2.2" + dependencies: + "domelementtype" "^2.0.1" + "entities" "^2.0.0" + +"domelementtype@^1.3.0", "domelementtype@^1.3.1", "domelementtype@1": + "integrity" "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + "resolved" "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz" + "version" "1.3.1" + +"domelementtype@^2.0.1", "domelementtype@^2.2.0": + "integrity" "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" + "resolved" "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz" + "version" "2.2.0" + +"domhandler@^2.3.0": + "integrity" "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==" + "resolved" "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "domelementtype" "1" + +"domhandler@^4.0.0", "domhandler@^4.2.0", "domhandler@^4.3.0": + "integrity" "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==" + "resolved" "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz" + "version" "4.3.0" + dependencies: + "domelementtype" "^2.2.0" + +"domutils@^1.5.1": + "integrity" "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==" + "resolved" "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz" + "version" "1.7.0" + dependencies: + "dom-serializer" "0" + "domelementtype" "1" + +"domutils@^2.5.2", "domutils@^2.7.0", "domutils@^2.8.0": + "integrity" "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==" + "resolved" "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz" + "version" "2.8.0" + dependencies: + "dom-serializer" "^1.0.1" + "domelementtype" "^2.2.0" + "domhandler" "^4.2.0" + +"domutils@1.5.1": + "integrity" "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=" + "resolved" "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz" + "version" "1.5.1" + dependencies: + "dom-serializer" "0" + "domelementtype" "1" + +"dot-case@^3.0.4": + "integrity" "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==" + "resolved" "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "no-case" "^3.0.4" + "tslib" "^2.0.3" + +"dot-prop@^5.2.0": + "integrity" "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==" + "resolved" "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz" + "version" "5.3.0" + dependencies: + "is-obj" "^2.0.0" + +"duplexer@^0.1.2": + "integrity" "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + "resolved" "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz" + "version" "0.1.2" + +"duplexer3@^0.1.4": + "integrity" "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + "resolved" "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz" + "version" "0.1.4" + +"ee-first@1.1.1": + "integrity" "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "resolved" "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + "version" "1.1.1" + +"electron-to-chromium@^1.4.284": + "integrity" "sha512-DE9tTy2PNmy1v55AZAO542ui+MLC2cvINMK4P2LXGsJdput/ThVG9t+QGecPuAZZSgC8XoI+Jh9M1OG9IoNSCw==" + "resolved" "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.328.tgz" + "version" "1.4.328" + +"emoji-regex@^8.0.0": + "integrity" "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "resolved" "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + "version" "8.0.0" + +"emojis-list@^3.0.0": + "integrity" "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" + "resolved" "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz" + "version" "3.0.0" + +"emoticon@^3.2.0": + "integrity" "sha512-SNujglcLTTg+lDAcApPNgEdudaqQFiAbJCqzjNxJkvN9vAwCGi0uu8IUVvx+f16h+V44KCY6Y2yboroc9pilHg==" + "resolved" "https://registry.npmjs.org/emoticon/-/emoticon-3.2.0.tgz" + "version" "3.2.0" + +"encodeurl@~1.0.2": + "integrity" "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "resolved" "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" + "version" "1.0.2" + +"end-of-stream@^1.1.0": + "integrity" "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==" + "resolved" "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" + "version" "1.4.4" + dependencies: + "once" "^1.4.0" + +"enhanced-resolve@^5.8.3": + "integrity" "sha512-weDYmzbBygL7HzGGS26M3hGQx68vehdEg6VUmqSOaFzXExFqlnKuSvsEJCVGQHScS8CQMbrAqftT+AzzHNt/YA==" + "resolved" "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.0.tgz" + "version" "5.9.0" + dependencies: + "graceful-fs" "^4.2.4" + "tapable" "^2.2.0" + +"entities@^1.1.1", "entities@~1.1.1": + "integrity" "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + "resolved" "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz" + "version" "1.1.2" + +"entities@^2.0.0": + "integrity" "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + "resolved" "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz" + "version" "2.2.0" + +"entities@^3.0.1": + "integrity" "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==" + "resolved" "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz" + "version" "3.0.1" + +"error-ex@^1.3.1": + "integrity" "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==" + "resolved" "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" + "version" "1.3.2" + dependencies: + "is-arrayish" "^0.2.1" + +"es-module-lexer@^0.9.0": + "integrity" "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==" + "resolved" "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz" + "version" "0.9.3" + +"escalade@^3.1.1": + "integrity" "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + "resolved" "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" + "version" "3.1.1" + +"escape-goat@^2.0.0": + "integrity" "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==" + "resolved" "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz" + "version" "2.1.1" + +"escape-html@^1.0.3", "escape-html@~1.0.3": + "integrity" "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "resolved" "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + "version" "1.0.3" + +"escape-string-regexp@^1.0.5": + "integrity" "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + "version" "1.0.5" + +"escape-string-regexp@^4.0.0": + "integrity" "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + "version" "4.0.0" + +"eslint-scope@5.1.1": + "integrity" "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==" + "resolved" "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" + "version" "5.1.1" + dependencies: + "esrecurse" "^4.3.0" + "estraverse" "^4.1.1" + +"esprima@^4.0.0": + "integrity" "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "resolved" "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" + "version" "4.0.1" + +"esrecurse@^4.3.0": + "integrity" "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==" + "resolved" "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" + "version" "4.3.0" + dependencies: + "estraverse" "^5.2.0" + +"estraverse@^4.1.1": + "integrity" "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" + "version" "4.3.0" + +"estraverse@^5.2.0": + "integrity" "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" + "version" "5.3.0" + +"esutils@^2.0.2": + "integrity" "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + "resolved" "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" + "version" "2.0.3" + +"eta@^1.12.3": + "integrity" "sha512-qHixwbDLtekO/d51Yr4glcaUJCIjGVJyTzuqV4GPlgZo1YpgOKG+avQynErZIYrfM6JIJdtiG2Kox8tbb+DoGg==" + "resolved" "https://registry.npmjs.org/eta/-/eta-1.12.3.tgz" + "version" "1.12.3" + +"etag@~1.8.1": + "integrity" "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "resolved" "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" + "version" "1.8.1" + +"eval@^0.1.4": + "integrity" "sha512-o0XUw+5OGkXw4pJZzQoXUk+H87DHuC+7ZE//oSrRGtatTmr12oTnLfg6QOq9DyTt0c/p4TwzgmkKrBzWTSizyQ==" + "resolved" "https://registry.npmjs.org/eval/-/eval-0.1.6.tgz" + "version" "0.1.6" + dependencies: + "require-like" ">= 0.1.1" + +"eventemitter3@^4.0.0": + "integrity" "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + "resolved" "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz" + "version" "4.0.7" + +"events@^3.2.0": + "integrity" "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + "resolved" "https://registry.npmjs.org/events/-/events-3.3.0.tgz" + "version" "3.3.0" + +"execa@^5.0.0": + "integrity" "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==" + "resolved" "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" + "version" "5.1.1" + dependencies: + "cross-spawn" "^7.0.3" + "get-stream" "^6.0.0" + "human-signals" "^2.1.0" + "is-stream" "^2.0.0" + "merge-stream" "^2.0.0" + "npm-run-path" "^4.0.1" + "onetime" "^5.1.2" + "signal-exit" "^3.0.3" + "strip-final-newline" "^2.0.0" + +"express@^4.17.1": + "integrity" "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==" + "resolved" "https://registry.npmjs.org/express/-/express-4.17.3.tgz" + "version" "4.17.3" + dependencies: + "accepts" "~1.3.8" + "array-flatten" "1.1.1" + "body-parser" "1.19.2" + "content-disposition" "0.5.4" + "content-type" "~1.0.4" + "cookie" "0.4.2" + "cookie-signature" "1.0.6" + "debug" "2.6.9" + "depd" "~1.1.2" + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "etag" "~1.8.1" + "finalhandler" "~1.1.2" + "fresh" "0.5.2" + "merge-descriptors" "1.0.1" + "methods" "~1.1.2" + "on-finished" "~2.3.0" + "parseurl" "~1.3.3" + "path-to-regexp" "0.1.7" + "proxy-addr" "~2.0.7" + "qs" "6.9.7" + "range-parser" "~1.2.1" + "safe-buffer" "5.2.1" + "send" "0.17.2" + "serve-static" "1.14.2" + "setprototypeof" "1.2.0" + "statuses" "~1.5.0" + "type-is" "~1.6.18" + "utils-merge" "1.0.1" + "vary" "~1.1.2" + +"extend-shallow@^2.0.1": + "integrity" "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=" + "resolved" "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "is-extendable" "^0.1.0" + +"extend@^3.0.0": + "integrity" "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "resolved" "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz" + "version" "3.0.2" + +"fast-deep-equal@^3.1.1", "fast-deep-equal@^3.1.3": + "integrity" "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "resolved" "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" + "version" "3.1.3" + +"fast-glob@^3.2.7", "fast-glob@^3.2.9": + "integrity" "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==" + "resolved" "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz" + "version" "3.2.11" dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-url-parser@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" - integrity sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0= - dependencies: - punycode "^1.3.2" - -fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== - dependencies: - reusify "^1.0.4" - -faye-websocket@^0.11.3: - version "0.11.4" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" - integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== - dependencies: - websocket-driver ">=0.5.1" - -fbemitter@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/fbemitter/-/fbemitter-3.0.0.tgz#00b2a1af5411254aab416cd75f9e6289bee4bff3" - integrity sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw== - dependencies: - fbjs "^3.0.0" - -fbjs-css-vars@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8" - integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== - -fbjs@^3.0.0, fbjs@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.4.tgz#e1871c6bd3083bac71ff2da868ad5067d37716c6" - integrity sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ== - dependencies: - cross-fetch "^3.1.5" - fbjs-css-vars "^1.0.0" - loose-envify "^1.0.0" - object-assign "^4.1.0" - promise "^7.1.1" - setimmediate "^1.0.5" - ua-parser-js "^0.7.30" - -feed@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/feed/-/feed-4.2.2.tgz#865783ef6ed12579e2c44bbef3c9113bc4956a7e" - integrity sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ== - dependencies: - xml-js "^1.6.11" - -file-loader@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" - integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== - dependencies: - loader-utils "^2.0.0" - schema-utils "^3.0.0" - -filesize@^8.0.6: - version "8.0.7" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-8.0.7.tgz#695e70d80f4e47012c132d57a059e80c6b580bd8" - integrity sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ== - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - -find-cache-dir@^3.3.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" - integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== - dependencies: - commondir "^1.0.1" - make-dir "^3.0.2" - pkg-dir "^4.1.0" - -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -find-up@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flux@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/flux/-/flux-4.0.3.tgz#573b504a24982c4768fdfb59d8d2ea5637d72ee7" - integrity sha512-yKAbrp7JhZhj6uiT1FTuVMlIAT1J4jqEyBpFApi1kxpGZCvacMVc/t1pMQyotqHhAgvoE3bNvAykhCo2CLjnYw== - dependencies: - fbemitter "^3.0.0" - fbjs "^3.0.1" - -follow-redirects@^1.0.0, follow-redirects@^1.14.7: - version "1.14.9" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" - integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== - -fork-ts-checker-webpack-plugin@^6.5.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz#0282b335fa495a97e167f69018f566ea7d2a2b5e" - integrity sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw== + "glob-parent" "^5.1.2" + "merge2" "^1.3.0" + "micromatch" "^4.0.4" + +"fast-json-stable-stringify@^2.0.0": + "integrity" "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "resolved" "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" + "version" "2.1.0" + +"fast-url-parser@1.1.3": + "integrity" "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=" + "resolved" "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz" + "version" "1.1.3" + dependencies: + "punycode" "^1.3.2" + +"fastq@^1.6.0": + "integrity" "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==" + "resolved" "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz" + "version" "1.13.0" + dependencies: + "reusify" "^1.0.4" + +"faye-websocket@^0.11.3": + "integrity" "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==" + "resolved" "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz" + "version" "0.11.4" + dependencies: + "websocket-driver" ">=0.5.1" + +"fbemitter@^3.0.0": + "integrity" "sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==" + "resolved" "https://registry.npmjs.org/fbemitter/-/fbemitter-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "fbjs" "^3.0.0" + +"fbjs-css-vars@^1.0.0": + "integrity" "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" + "resolved" "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz" + "version" "1.0.2" + +"fbjs@^3.0.0", "fbjs@^3.0.1": + "integrity" "sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ==" + "resolved" "https://registry.npmjs.org/fbjs/-/fbjs-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "cross-fetch" "^3.1.5" + "fbjs-css-vars" "^1.0.0" + "loose-envify" "^1.0.0" + "object-assign" "^4.1.0" + "promise" "^7.1.1" + "setimmediate" "^1.0.5" + "ua-parser-js" "^0.7.30" + +"feed@^4.2.2": + "integrity" "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==" + "resolved" "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz" + "version" "4.2.2" + dependencies: + "xml-js" "^1.6.11" + +"file-loader@*", "file-loader@^6.2.0": + "integrity" "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==" + "resolved" "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz" + "version" "6.2.0" + dependencies: + "loader-utils" "^2.0.0" + "schema-utils" "^3.0.0" + +"filesize@^8.0.6": + "integrity" "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==" + "resolved" "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz" + "version" "8.0.7" + +"fill-range@^7.0.1": + "integrity" "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==" + "resolved" "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" + "version" "7.0.1" + dependencies: + "to-regex-range" "^5.0.1" + +"finalhandler@~1.1.2": + "integrity" "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==" + "resolved" "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz" + "version" "1.1.2" + dependencies: + "debug" "2.6.9" + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "on-finished" "~2.3.0" + "parseurl" "~1.3.3" + "statuses" "~1.5.0" + "unpipe" "~1.0.0" + +"find-cache-dir@^3.3.1": + "integrity" "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==" + "resolved" "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz" + "version" "3.3.2" + dependencies: + "commondir" "^1.0.1" + "make-dir" "^3.0.2" + "pkg-dir" "^4.1.0" + +"find-up@^3.0.0": + "integrity" "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==" + "resolved" "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "locate-path" "^3.0.0" + +"find-up@^4.0.0": + "integrity" "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==" + "resolved" "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "locate-path" "^5.0.0" + "path-exists" "^4.0.0" + +"find-up@^5.0.0": + "integrity" "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==" + "resolved" "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "locate-path" "^6.0.0" + "path-exists" "^4.0.0" + +"flux@^4.0.1": + "integrity" "sha512-yKAbrp7JhZhj6uiT1FTuVMlIAT1J4jqEyBpFApi1kxpGZCvacMVc/t1pMQyotqHhAgvoE3bNvAykhCo2CLjnYw==" + "resolved" "https://registry.npmjs.org/flux/-/flux-4.0.3.tgz" + "version" "4.0.3" + dependencies: + "fbemitter" "^3.0.0" + "fbjs" "^3.0.1" + +"follow-redirects@^1.0.0", "follow-redirects@^1.14.7": + "integrity" "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" + "resolved" "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz" + "version" "1.14.9" + +"fork-ts-checker-webpack-plugin@^6.5.0": + "integrity" "sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw==" + "resolved" "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz" + "version" "6.5.0" dependencies: "@babel/code-frame" "^7.8.3" "@types/json-schema" "^7.0.5" - chalk "^4.1.0" - chokidar "^3.4.2" - cosmiconfig "^6.0.0" - deepmerge "^4.2.2" - fs-extra "^9.0.0" - glob "^7.1.6" - memfs "^3.1.2" - minimatch "^3.0.4" - schema-utils "2.7.0" - semver "^7.3.2" - tapable "^1.0.0" - -forwarded@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" - integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== - -fraction.js@^4.1.2: - version "4.1.3" - resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.3.tgz#be65b0f20762ef27e1e793860bc2dfb716e99e65" - integrity sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg== - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - -fs-extra@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1" - integrity sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-extra@^9.0.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" - integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== - dependencies: - at-least-node "^1.0.0" - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-monkey@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" - integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-intrinsic@^1.0.2: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - -get-own-enumerable-property-symbols@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" - integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== - -get-stream@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -github-slugger@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.4.0.tgz#206eb96cdb22ee56fdc53a28d5a302338463444e" - integrity sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ== - -glob-parent@^5.1.2, glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob-to-regexp@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" - integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== - -glob@^7.0.0, glob@^7.1.3, glob@^7.1.6: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -global-dirs@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686" - integrity sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA== - dependencies: - ini "2.0.0" - -global-modules@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" - integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== - dependencies: - global-prefix "^3.0.0" - -global-prefix@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" - integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== - dependencies: - ini "^1.3.5" - kind-of "^6.0.2" - which "^1.3.1" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globby@^11.0.1, globby@^11.0.2, globby@^11.0.4: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -globby@^12.0.2: - version "12.2.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-12.2.0.tgz#2ab8046b4fba4ff6eede835b29f678f90e3d3c22" - integrity sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA== - dependencies: - array-union "^3.0.1" - dir-glob "^3.0.1" - fast-glob "^3.2.7" - ignore "^5.1.9" - merge2 "^1.4.1" - slash "^4.0.0" - -got@^9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + "chalk" "^4.1.0" + "chokidar" "^3.4.2" + "cosmiconfig" "^6.0.0" + "deepmerge" "^4.2.2" + "fs-extra" "^9.0.0" + "glob" "^7.1.6" + "memfs" "^3.1.2" + "minimatch" "^3.0.4" + "schema-utils" "2.7.0" + "semver" "^7.3.2" + "tapable" "^1.0.0" + +"forwarded@0.2.0": + "integrity" "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + "resolved" "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" + "version" "0.2.0" + +"fraction.js@^4.1.2": + "integrity" "sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg==" + "resolved" "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.3.tgz" + "version" "4.1.3" + +"fresh@0.5.2": + "integrity" "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "resolved" "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" + "version" "0.5.2" + +"fs-extra@^10.0.0": + "integrity" "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==" + "resolved" "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz" + "version" "10.0.0" + dependencies: + "graceful-fs" "^4.2.0" + "jsonfile" "^6.0.1" + "universalify" "^2.0.0" + +"fs-extra@^9.0.0": + "integrity" "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==" + "resolved" "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz" + "version" "9.1.0" + dependencies: + "at-least-node" "^1.0.0" + "graceful-fs" "^4.2.0" + "jsonfile" "^6.0.1" + "universalify" "^2.0.0" + +"fs-monkey@1.0.3": + "integrity" "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==" + "resolved" "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz" + "version" "1.0.3" + +"fs.realpath@^1.0.0": + "integrity" "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "resolved" "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + "version" "1.0.0" + +"function-bind@^1.1.1": + "integrity" "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "resolved" "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" + "version" "1.1.1" + +"gensync@^1.0.0-beta.1", "gensync@^1.0.0-beta.2": + "integrity" "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + "resolved" "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" + "version" "1.0.0-beta.2" + +"get-intrinsic@^1.0.2": + "integrity" "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==" + "resolved" "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "function-bind" "^1.1.1" + "has" "^1.0.3" + "has-symbols" "^1.0.1" + +"get-own-enumerable-property-symbols@^3.0.0": + "integrity" "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + "resolved" "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz" + "version" "3.0.2" + +"get-stream@^4.1.0": + "integrity" "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==" + "resolved" "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "pump" "^3.0.0" + +"get-stream@^5.1.0": + "integrity" "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==" + "resolved" "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz" + "version" "5.2.0" + dependencies: + "pump" "^3.0.0" + +"get-stream@^6.0.0": + "integrity" "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + "resolved" "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz" + "version" "6.0.1" + +"github-slugger@^1.4.0": + "integrity" "sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ==" + "resolved" "https://registry.npmjs.org/github-slugger/-/github-slugger-1.4.0.tgz" + "version" "1.4.0" + +"glob-parent@^5.1.2", "glob-parent@~5.1.2": + "integrity" "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==" + "resolved" "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + "version" "5.1.2" + dependencies: + "is-glob" "^4.0.1" + +"glob-parent@^6.0.1": + "integrity" "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==" + "resolved" "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" + "version" "6.0.2" + dependencies: + "is-glob" "^4.0.3" + +"glob-to-regexp@^0.4.1": + "integrity" "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + "resolved" "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz" + "version" "0.4.1" + +"glob@^7.0.0", "glob@^7.1.3", "glob@^7.1.6": + "integrity" "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==" + "resolved" "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz" + "version" "7.2.0" + dependencies: + "fs.realpath" "^1.0.0" + "inflight" "^1.0.4" + "inherits" "2" + "minimatch" "^3.0.4" + "once" "^1.3.0" + "path-is-absolute" "^1.0.0" + +"global-dirs@^3.0.0": + "integrity" "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==" + "resolved" "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "ini" "2.0.0" + +"global-modules@^2.0.0": + "integrity" "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==" + "resolved" "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "global-prefix" "^3.0.0" + +"global-prefix@^3.0.0": + "integrity" "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==" + "resolved" "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "ini" "^1.3.5" + "kind-of" "^6.0.2" + "which" "^1.3.1" + +"globals@^11.1.0": + "integrity" "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + "resolved" "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" + "version" "11.12.0" + +"globby@^11.0.1", "globby@^11.0.2", "globby@^11.0.4": + "integrity" "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==" + "resolved" "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" + "version" "11.1.0" + dependencies: + "array-union" "^2.1.0" + "dir-glob" "^3.0.1" + "fast-glob" "^3.2.9" + "ignore" "^5.2.0" + "merge2" "^1.4.1" + "slash" "^3.0.0" + +"globby@^12.0.2": + "integrity" "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==" + "resolved" "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz" + "version" "12.2.0" + dependencies: + "array-union" "^3.0.1" + "dir-glob" "^3.0.1" + "fast-glob" "^3.2.7" + "ignore" "^5.1.9" + "merge2" "^1.4.1" + "slash" "^4.0.0" + +"got@^9.6.0": + "integrity" "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==" + "resolved" "https://registry.npmjs.org/got/-/got-9.6.0.tgz" + "version" "9.6.0" dependencies: "@sindresorhus/is" "^0.14.0" "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" - -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: - version "4.2.9" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== - -gray-matter@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.3.tgz#e893c064825de73ea1f5f7d88c7a9f7274288798" - integrity sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q== - dependencies: - js-yaml "^3.13.1" - kind-of "^6.0.2" - section-matter "^1.0.0" - strip-bom-string "^1.0.0" - -gzip-size@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" - integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== - dependencies: - duplexer "^0.1.2" - -handle-thing@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" - integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-symbols@^1.0.1, has-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" - integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - -has-yarn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" - integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hast-to-hyperscript@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz#9b67fd188e4c81e8ad66f803855334173920218d" - integrity sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA== + "cacheable-request" "^6.0.0" + "decompress-response" "^3.3.0" + "duplexer3" "^0.1.4" + "get-stream" "^4.1.0" + "lowercase-keys" "^1.0.1" + "mimic-response" "^1.0.1" + "p-cancelable" "^1.0.0" + "to-readable-stream" "^1.0.0" + "url-parse-lax" "^3.0.0" + +"graceful-fs@^4.1.2", "graceful-fs@^4.1.6", "graceful-fs@^4.2.0", "graceful-fs@^4.2.4", "graceful-fs@^4.2.6", "graceful-fs@^4.2.9": + "integrity" "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" + "resolved" "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz" + "version" "4.2.9" + +"gray-matter@^4.0.3": + "integrity" "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==" + "resolved" "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz" + "version" "4.0.3" + dependencies: + "js-yaml" "^3.13.1" + "kind-of" "^6.0.2" + "section-matter" "^1.0.0" + "strip-bom-string" "^1.0.0" + +"gzip-size@^6.0.0": + "integrity" "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==" + "resolved" "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "duplexer" "^0.1.2" + +"handle-thing@^2.0.0": + "integrity" "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" + "resolved" "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz" + "version" "2.0.1" + +"has-flag@^3.0.0": + "integrity" "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" + "version" "3.0.0" + +"has-flag@^4.0.0": + "integrity" "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + "version" "4.0.0" + +"has-symbols@^1.0.1", "has-symbols@^1.0.2": + "integrity" "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + "resolved" "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz" + "version" "1.0.2" + +"has-tostringtag@^1.0.0": + "integrity" "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==" + "resolved" "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "has-symbols" "^1.0.2" + +"has-yarn@^2.1.0": + "integrity" "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==" + "resolved" "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz" + "version" "2.1.0" + +"has@^1.0.3": + "integrity" "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==" + "resolved" "https://registry.npmjs.org/has/-/has-1.0.3.tgz" + "version" "1.0.3" + dependencies: + "function-bind" "^1.1.1" + +"hast-to-hyperscript@^9.0.0": + "integrity" "sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA==" + "resolved" "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz" + "version" "9.0.1" dependencies: "@types/unist" "^2.0.3" - comma-separated-tokens "^1.0.0" - property-information "^5.3.0" - space-separated-tokens "^1.0.0" - style-to-object "^0.3.0" - unist-util-is "^4.0.0" - web-namespaces "^1.0.0" - -hast-util-from-parse5@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-5.0.3.tgz#3089dc0ee2ccf6ec8bc416919b51a54a589e097c" - integrity sha512-gOc8UB99F6eWVWFtM9jUikjN7QkWxB3nY0df5Z0Zq1/Nkwl5V4hAAsl0tmwlgWl/1shlTF8DnNYLO8X6wRV9pA== - dependencies: - ccount "^1.0.3" - hastscript "^5.0.0" - property-information "^5.0.0" - web-namespaces "^1.1.2" - xtend "^4.0.1" - -hast-util-from-parse5@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz#554e34abdeea25ac76f5bd950a1f0180e0b3bc2a" - integrity sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA== + "comma-separated-tokens" "^1.0.0" + "property-information" "^5.3.0" + "space-separated-tokens" "^1.0.0" + "style-to-object" "^0.3.0" + "unist-util-is" "^4.0.0" + "web-namespaces" "^1.0.0" + +"hast-util-from-parse5@^5.0.0": + "integrity" "sha512-gOc8UB99F6eWVWFtM9jUikjN7QkWxB3nY0df5Z0Zq1/Nkwl5V4hAAsl0tmwlgWl/1shlTF8DnNYLO8X6wRV9pA==" + "resolved" "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-5.0.3.tgz" + "version" "5.0.3" + dependencies: + "ccount" "^1.0.3" + "hastscript" "^5.0.0" + "property-information" "^5.0.0" + "web-namespaces" "^1.1.2" + "xtend" "^4.0.1" + +"hast-util-from-parse5@^6.0.0": + "integrity" "sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA==" + "resolved" "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz" + "version" "6.0.1" dependencies: "@types/parse5" "^5.0.0" - hastscript "^6.0.0" - property-information "^5.0.0" - vfile "^4.0.0" - vfile-location "^3.2.0" - web-namespaces "^1.0.0" - -hast-util-parse-selector@^2.0.0: - version "2.2.5" - resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz#d57c23f4da16ae3c63b3b6ca4616683313499c3a" - integrity sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ== - -hast-util-raw@6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/hast-util-raw/-/hast-util-raw-6.0.1.tgz#973b15930b7529a7b66984c98148b46526885977" - integrity sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig== + "hastscript" "^6.0.0" + "property-information" "^5.0.0" + "vfile" "^4.0.0" + "vfile-location" "^3.2.0" + "web-namespaces" "^1.0.0" + +"hast-util-parse-selector@^2.0.0": + "integrity" "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==" + "resolved" "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz" + "version" "2.2.5" + +"hast-util-raw@6.0.1": + "integrity" "sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig==" + "resolved" "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-6.0.1.tgz" + "version" "6.0.1" dependencies: "@types/hast" "^2.0.0" - hast-util-from-parse5 "^6.0.0" - hast-util-to-parse5 "^6.0.0" - html-void-elements "^1.0.0" - parse5 "^6.0.0" - unist-util-position "^3.0.0" - vfile "^4.0.0" - web-namespaces "^1.0.0" - xtend "^4.0.0" - zwitch "^1.0.0" - -hast-util-to-parse5@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz#1ec44650b631d72952066cea9b1445df699f8479" - integrity sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ== - dependencies: - hast-to-hyperscript "^9.0.0" - property-information "^5.0.0" - web-namespaces "^1.0.0" - xtend "^4.0.0" - zwitch "^1.0.0" - -hastscript@^5.0.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-5.1.2.tgz#bde2c2e56d04c62dd24e8c5df288d050a355fb8a" - integrity sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ== - dependencies: - comma-separated-tokens "^1.0.0" - hast-util-parse-selector "^2.0.0" - property-information "^5.0.0" - space-separated-tokens "^1.0.0" - -hastscript@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-6.0.0.tgz#e8768d7eac56c3fdeac8a92830d58e811e5bf640" - integrity sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w== + "hast-util-from-parse5" "^6.0.0" + "hast-util-to-parse5" "^6.0.0" + "html-void-elements" "^1.0.0" + "parse5" "^6.0.0" + "unist-util-position" "^3.0.0" + "vfile" "^4.0.0" + "web-namespaces" "^1.0.0" + "xtend" "^4.0.0" + "zwitch" "^1.0.0" + +"hast-util-to-parse5@^6.0.0": + "integrity" "sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ==" + "resolved" "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "hast-to-hyperscript" "^9.0.0" + "property-information" "^5.0.0" + "web-namespaces" "^1.0.0" + "xtend" "^4.0.0" + "zwitch" "^1.0.0" + +"hastscript@^5.0.0": + "integrity" "sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ==" + "resolved" "https://registry.npmjs.org/hastscript/-/hastscript-5.1.2.tgz" + "version" "5.1.2" + dependencies: + "comma-separated-tokens" "^1.0.0" + "hast-util-parse-selector" "^2.0.0" + "property-information" "^5.0.0" + "space-separated-tokens" "^1.0.0" + +"hastscript@^6.0.0": + "integrity" "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==" + "resolved" "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz" + "version" "6.0.0" dependencies: "@types/hast" "^2.0.0" - comma-separated-tokens "^1.0.0" - hast-util-parse-selector "^2.0.0" - property-information "^5.0.0" - space-separated-tokens "^1.0.0" + "comma-separated-tokens" "^1.0.0" + "hast-util-parse-selector" "^2.0.0" + "property-information" "^5.0.0" + "space-separated-tokens" "^1.0.0" -he@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +"he@^1.2.0": + "integrity" "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + "resolved" "https://registry.npmjs.org/he/-/he-1.2.0.tgz" + "version" "1.2.0" -history@^4.9.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" - integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew== +"history@^4.9.0": + "integrity" "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==" + "resolved" "https://registry.npmjs.org/history/-/history-4.10.1.tgz" + "version" "4.10.1" dependencies: "@babel/runtime" "^7.1.2" - loose-envify "^1.2.0" - resolve-pathname "^3.0.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - value-equal "^1.0.1" - -hoist-non-react-statics@^3.1.0: - version "3.3.2" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" - integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== - dependencies: - react-is "^16.7.0" - -hpack.js@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" - integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI= - dependencies: - inherits "^2.0.1" - obuf "^1.0.0" - readable-stream "^2.0.1" - wbuf "^1.1.0" - -html-entities@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.2.tgz#760b404685cb1d794e4f4b744332e3b00dcfe488" - integrity sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ== - -html-minifier-terser@^6.0.2: - version "6.1.0" - resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" - integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== - dependencies: - camel-case "^4.1.2" - clean-css "^5.2.2" - commander "^8.3.0" - he "^1.2.0" - param-case "^3.0.4" - relateurl "^0.2.7" - terser "^5.10.0" - -html-tags@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" - integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg== - -html-void-elements@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483" - integrity sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w== - -html-webpack-plugin@^5.4.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz#c3911936f57681c1f9f4d8b68c158cd9dfe52f50" - integrity sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw== + "loose-envify" "^1.2.0" + "resolve-pathname" "^3.0.0" + "tiny-invariant" "^1.0.2" + "tiny-warning" "^1.0.0" + "value-equal" "^1.0.1" + +"hoist-non-react-statics@^3.1.0": + "integrity" "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==" + "resolved" "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz" + "version" "3.3.2" + dependencies: + "react-is" "^16.7.0" + +"hpack.js@^2.1.6": + "integrity" "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=" + "resolved" "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz" + "version" "2.1.6" + dependencies: + "inherits" "^2.0.1" + "obuf" "^1.0.0" + "readable-stream" "^2.0.1" + "wbuf" "^1.1.0" + +"html-entities@^2.3.2": + "integrity" "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==" + "resolved" "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz" + "version" "2.3.2" + +"html-minifier-terser@^6.0.2": + "integrity" "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==" + "resolved" "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "camel-case" "^4.1.2" + "clean-css" "^5.2.2" + "commander" "^8.3.0" + "he" "^1.2.0" + "param-case" "^3.0.4" + "relateurl" "^0.2.7" + "terser" "^5.10.0" + +"html-tags@^3.1.0": + "integrity" "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==" + "resolved" "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz" + "version" "3.1.0" + +"html-void-elements@^1.0.0": + "integrity" "sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w==" + "resolved" "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz" + "version" "1.0.5" + +"html-webpack-plugin@^5.4.0": + "integrity" "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==" + "resolved" "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz" + "version" "5.5.0" dependencies: "@types/html-minifier-terser" "^6.0.0" - html-minifier-terser "^6.0.2" - lodash "^4.17.21" - pretty-error "^4.0.0" - tapable "^2.0.0" - -htmlparser2@^3.9.1: - version "3.10.1" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" - integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== - dependencies: - domelementtype "^1.3.1" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^3.1.1" - -htmlparser2@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" - integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== - dependencies: - domelementtype "^2.0.1" - domhandler "^4.0.0" - domutils "^2.5.2" - entities "^2.0.0" - -http-cache-semantics@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" - integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== - -http-deceiver@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" - integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= - -http-errors@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" - integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.1" - -http-errors@~1.6.2: - version "1.6.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - -http-parser-js@>=0.5.1: - version "0.5.5" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.5.tgz#d7c30d5d3c90d865b4a2e870181f9d6f22ac7ac5" - integrity sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA== - -http-proxy-middleware@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.3.tgz#5df04f69a89f530c2284cd71eeaa51ba52243289" - integrity sha512-1bloEwnrHMnCoO/Gcwbz7eSVvW50KPES01PecpagI+YLNLci4AcuKJrujW4Mc3sBLpFxMSlsLNHS5Nl/lvrTPA== + "html-minifier-terser" "^6.0.2" + "lodash" "^4.17.21" + "pretty-error" "^4.0.0" + "tapable" "^2.0.0" + +"htmlparser2@^3.9.1": + "integrity" "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==" + "resolved" "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz" + "version" "3.10.1" + dependencies: + "domelementtype" "^1.3.1" + "domhandler" "^2.3.0" + "domutils" "^1.5.1" + "entities" "^1.1.1" + "inherits" "^2.0.1" + "readable-stream" "^3.1.1" + +"htmlparser2@^6.1.0": + "integrity" "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==" + "resolved" "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "domelementtype" "^2.0.1" + "domhandler" "^4.0.0" + "domutils" "^2.5.2" + "entities" "^2.0.0" + +"http-cache-semantics@^4.0.0": + "integrity" "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + "resolved" "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz" + "version" "4.1.1" + +"http-deceiver@^1.2.7": + "integrity" "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" + "resolved" "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" + "version" "1.2.7" + +"http-errors@~1.6.2": + "integrity" "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=" + "resolved" "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz" + "version" "1.6.3" + dependencies: + "depd" "~1.1.2" + "inherits" "2.0.3" + "setprototypeof" "1.1.0" + "statuses" ">= 1.4.0 < 2" + +"http-errors@1.8.1": + "integrity" "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==" + "resolved" "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz" + "version" "1.8.1" + dependencies: + "depd" "~1.1.2" + "inherits" "2.0.4" + "setprototypeof" "1.2.0" + "statuses" ">= 1.5.0 < 2" + "toidentifier" "1.0.1" + +"http-parser-js@>=0.5.1": + "integrity" "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA==" + "resolved" "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz" + "version" "0.5.5" + +"http-proxy-middleware@^2.0.0": + "integrity" "sha512-1bloEwnrHMnCoO/Gcwbz7eSVvW50KPES01PecpagI+YLNLci4AcuKJrujW4Mc3sBLpFxMSlsLNHS5Nl/lvrTPA==" + "resolved" "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.3.tgz" + "version" "2.0.3" dependencies: "@types/http-proxy" "^1.17.8" - http-proxy "^1.18.1" - is-glob "^4.0.1" - is-plain-obj "^3.0.0" - micromatch "^4.0.2" - -http-proxy@^1.18.1: - version "1.18.1" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" - integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== - dependencies: - eventemitter3 "^4.0.0" - follow-redirects "^1.0.0" - requires-port "^1.0.0" - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -icss-utils@^5.0.0, icss-utils@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" - integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== - -ignore@^5.1.9, ignore@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== - -image-size@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.0.1.tgz#86d6cfc2b1d19eab5d2b368d4b9194d9e48541c5" - integrity sha512-VAwkvNSNGClRw9mDHhc5Efax8PLlsOGcUTh0T/LIriC8vPA3U5PdqXWqkz406MoYHMKW8Uf9gWr05T/rYB44kQ== - dependencies: - queue "6.0.2" - -immer@^9.0.7: - version "9.0.12" - resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.12.tgz#2d33ddf3ee1d247deab9d707ca472c8c942a0f20" - integrity sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA== - -import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.2.2, import-fresh@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-lazy@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" - integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -infima@0.2.0-alpha.37: - version "0.2.0-alpha.37" - resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.37.tgz#b87ff42d528d6d050098a560f0294fbdd12adb78" - integrity sha512-4GX7Baw+/lwS4PPW/UJNY89tWSvYG1DL6baKVdpK6mC593iRgMssxNtORMTFArLPJ/A/lzsGhRmx+z6MaMxj0Q== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -ini@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" - integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== - -ini@^1.3.5, ini@~1.3.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - -inline-style-parser@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" - integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== - -interpret@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" - integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== - -ip@^1.1.0: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= - -ipaddr.js@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -ipaddr.js@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" - integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== - -is-alphabetical@1.0.4, is-alphabetical@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" - integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== - -is-alphanumerical@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" - integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== - dependencies: - is-alphabetical "^1.0.0" - is-decimal "^1.0.0" - -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-buffer@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" - integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== - -is-ci@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" - integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== - dependencies: - ci-info "^2.0.0" - -is-core-module@^2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" - integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== - dependencies: - has "^1.0.3" - -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-decimal@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" - integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== - -is-docker@^2.0.0, is-docker@^2.1.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" - integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== - -is-extendable@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-hexadecimal@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" - integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== - -is-installed-globally@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" - integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ== - dependencies: - global-dirs "^3.0.0" - is-path-inside "^3.0.2" - -is-npm@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-5.0.0.tgz#43e8d65cc56e1b67f8d47262cf667099193f45a8" - integrity sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA== - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - -is-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" - integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== - -is-path-cwd@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" - integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== - -is-path-inside@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - -is-plain-obj@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - -is-plain-obj@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" - integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== - -is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-regex@^1.0.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" - integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= - -is-root@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" - integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg== - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-typedarray@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-whitespace-character@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7" - integrity sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w== - -is-word-character@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.4.tgz#ce0e73216f98599060592f62ff31354ddbeb0230" - integrity sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA== - -is-wsl@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== - dependencies: - is-docker "^2.0.0" - -is-yarn-global@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" - integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - -jest-worker@^27.0.2, jest-worker@^27.4.5: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" - integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + "http-proxy" "^1.18.1" + "is-glob" "^4.0.1" + "is-plain-obj" "^3.0.0" + "micromatch" "^4.0.2" + +"http-proxy@^1.18.1": + "integrity" "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==" + "resolved" "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz" + "version" "1.18.1" + dependencies: + "eventemitter3" "^4.0.0" + "follow-redirects" "^1.0.0" + "requires-port" "^1.0.0" + +"human-signals@^2.1.0": + "integrity" "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" + "resolved" "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" + "version" "2.1.0" + +"iconv-lite@0.4.24": + "integrity" "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==" + "resolved" "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" + "version" "0.4.24" + dependencies: + "safer-buffer" ">= 2.1.2 < 3" + +"icss-utils@^5.0.0", "icss-utils@^5.1.0": + "integrity" "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==" + "resolved" "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz" + "version" "5.1.0" + +"ignore@^5.1.9", "ignore@^5.2.0": + "integrity" "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==" + "resolved" "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz" + "version" "5.2.0" + +"image-size@^1.0.1": + "integrity" "sha512-VAwkvNSNGClRw9mDHhc5Efax8PLlsOGcUTh0T/LIriC8vPA3U5PdqXWqkz406MoYHMKW8Uf9gWr05T/rYB44kQ==" + "resolved" "https://registry.npmjs.org/image-size/-/image-size-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "queue" "6.0.2" + +"immer@^9.0.7": + "integrity" "sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA==" + "resolved" "https://registry.npmjs.org/immer/-/immer-9.0.12.tgz" + "version" "9.0.12" + +"import-fresh@^3.1.0", "import-fresh@^3.2.1", "import-fresh@^3.2.2", "import-fresh@^3.3.0": + "integrity" "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==" + "resolved" "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" + "version" "3.3.0" + dependencies: + "parent-module" "^1.0.0" + "resolve-from" "^4.0.0" + +"import-lazy@^2.1.0": + "integrity" "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" + "resolved" "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz" + "version" "2.1.0" + +"imurmurhash@^0.1.4": + "integrity" "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + "resolved" "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" + "version" "0.1.4" + +"indent-string@^4.0.0": + "integrity" "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + "resolved" "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" + "version" "4.0.0" + +"infima@0.2.0-alpha.37": + "integrity" "sha512-4GX7Baw+/lwS4PPW/UJNY89tWSvYG1DL6baKVdpK6mC593iRgMssxNtORMTFArLPJ/A/lzsGhRmx+z6MaMxj0Q==" + "resolved" "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.37.tgz" + "version" "0.2.0-alpha.37" + +"inflight@^1.0.4": + "integrity" "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=" + "resolved" "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + "version" "1.0.6" + dependencies: + "once" "^1.3.0" + "wrappy" "1" + +"inherits@^2.0.0", "inherits@^2.0.1", "inherits@^2.0.3", "inherits@~2.0.3", "inherits@2", "inherits@2.0.4": + "integrity" "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "resolved" "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + "version" "2.0.4" + +"inherits@2.0.3": + "integrity" "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "resolved" "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + "version" "2.0.3" + +"ini@^1.3.5", "ini@~1.3.0": + "integrity" "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + "resolved" "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" + "version" "1.3.8" + +"ini@2.0.0": + "integrity" "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==" + "resolved" "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz" + "version" "2.0.0" + +"inline-style-parser@0.1.1": + "integrity" "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" + "resolved" "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz" + "version" "0.1.1" + +"interpret@^1.0.0": + "integrity" "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + "resolved" "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz" + "version" "1.4.0" + +"ip@^1.1.0": + "integrity" "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + "resolved" "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz" + "version" "1.1.5" + +"ipaddr.js@^2.0.1": + "integrity" "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==" + "resolved" "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz" + "version" "2.0.1" + +"ipaddr.js@1.9.1": + "integrity" "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + "resolved" "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" + "version" "1.9.1" + +"is-alphabetical@^1.0.0", "is-alphabetical@1.0.4": + "integrity" "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==" + "resolved" "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz" + "version" "1.0.4" + +"is-alphanumerical@^1.0.0": + "integrity" "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==" + "resolved" "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz" + "version" "1.0.4" + dependencies: + "is-alphabetical" "^1.0.0" + "is-decimal" "^1.0.0" + +"is-arguments@^1.0.4": + "integrity" "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==" + "resolved" "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "call-bind" "^1.0.2" + "has-tostringtag" "^1.0.0" + +"is-arrayish@^0.2.1": + "integrity" "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + "resolved" "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + "version" "0.2.1" + +"is-binary-path@~2.1.0": + "integrity" "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==" + "resolved" "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "binary-extensions" "^2.0.0" + +"is-buffer@^2.0.0": + "integrity" "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" + "resolved" "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz" + "version" "2.0.5" + +"is-ci@^2.0.0": + "integrity" "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==" + "resolved" "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "ci-info" "^2.0.0" + +"is-core-module@^2.8.1": + "integrity" "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==" + "resolved" "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz" + "version" "2.8.1" + dependencies: + "has" "^1.0.3" + +"is-date-object@^1.0.1": + "integrity" "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==" + "resolved" "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz" + "version" "1.0.5" + dependencies: + "has-tostringtag" "^1.0.0" + +"is-decimal@^1.0.0": + "integrity" "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==" + "resolved" "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz" + "version" "1.0.4" + +"is-docker@^2.0.0", "is-docker@^2.1.1": + "integrity" "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" + "resolved" "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz" + "version" "2.2.1" + +"is-extendable@^0.1.0": + "integrity" "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + "resolved" "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" + "version" "0.1.1" + +"is-extglob@^2.1.1": + "integrity" "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + "resolved" "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + "version" "2.1.1" + +"is-fullwidth-code-point@^3.0.0": + "integrity" "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + "resolved" "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + "version" "3.0.0" + +"is-glob@^4.0.1", "is-glob@^4.0.3", "is-glob@~4.0.1": + "integrity" "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==" + "resolved" "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" + "version" "4.0.3" + dependencies: + "is-extglob" "^2.1.1" + +"is-hexadecimal@^1.0.0": + "integrity" "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==" + "resolved" "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz" + "version" "1.0.4" + +"is-installed-globally@^0.4.0": + "integrity" "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==" + "resolved" "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz" + "version" "0.4.0" + dependencies: + "global-dirs" "^3.0.0" + "is-path-inside" "^3.0.2" + +"is-npm@^5.0.0": + "integrity" "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==" + "resolved" "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz" + "version" "5.0.0" + +"is-number@^7.0.0": + "integrity" "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + "resolved" "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + "version" "7.0.0" + +"is-obj@^1.0.1": + "integrity" "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + "resolved" "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz" + "version" "1.0.1" + +"is-obj@^2.0.0": + "integrity" "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" + "resolved" "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz" + "version" "2.0.0" + +"is-path-cwd@^2.2.0": + "integrity" "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==" + "resolved" "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz" + "version" "2.2.0" + +"is-path-inside@^3.0.2": + "integrity" "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" + "resolved" "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" + "version" "3.0.3" + +"is-plain-obj@^2.0.0": + "integrity" "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" + "resolved" "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" + "version" "2.1.0" + +"is-plain-obj@^3.0.0": + "integrity" "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==" + "resolved" "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz" + "version" "3.0.0" + +"is-plain-object@^2.0.4": + "integrity" "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==" + "resolved" "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" + "version" "2.0.4" + dependencies: + "isobject" "^3.0.1" + +"is-regex@^1.0.4": + "integrity" "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==" + "resolved" "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz" + "version" "1.1.4" + dependencies: + "call-bind" "^1.0.2" + "has-tostringtag" "^1.0.0" + +"is-regexp@^1.0.0": + "integrity" "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=" + "resolved" "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz" + "version" "1.0.0" + +"is-root@^2.1.0": + "integrity" "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==" + "resolved" "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz" + "version" "2.1.0" + +"is-stream@^2.0.0": + "integrity" "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + "resolved" "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" + "version" "2.0.1" + +"is-typedarray@^1.0.0": + "integrity" "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "resolved" "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" + "version" "1.0.0" + +"is-whitespace-character@^1.0.0": + "integrity" "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==" + "resolved" "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz" + "version" "1.0.4" + +"is-word-character@^1.0.0": + "integrity" "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==" + "resolved" "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz" + "version" "1.0.4" + +"is-wsl@^2.2.0": + "integrity" "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==" + "resolved" "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz" + "version" "2.2.0" + dependencies: + "is-docker" "^2.0.0" + +"is-yarn-global@^0.3.0": + "integrity" "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" + "resolved" "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz" + "version" "0.3.0" + +"isarray@~1.0.0": + "integrity" "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "resolved" "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + "version" "1.0.0" + +"isarray@0.0.1": + "integrity" "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + "resolved" "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + "version" "0.0.1" + +"isexe@^2.0.0": + "integrity" "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "resolved" "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + "version" "2.0.0" + +"isobject@^3.0.1": + "integrity" "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + "resolved" "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" + "version" "3.0.1" + +"jest-worker@^27.0.2", "jest-worker@^27.4.5": + "integrity" "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==" + "resolved" "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz" + "version" "27.5.1" dependencies: "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^8.0.0" + "merge-stream" "^2.0.0" + "supports-color" "^8.0.0" -joi@^17.4.2, joi@^17.6.0: - version "17.6.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.6.0.tgz#0bb54f2f006c09a96e75ce687957bd04290054b2" - integrity sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw== +"joi@^17.4.2", "joi@^17.6.0": + "integrity" "sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw==" + "resolved" "https://registry.npmjs.org/joi/-/joi-17.6.0.tgz" + "version" "17.6.0" dependencies: "@hapi/hoek" "^9.0.0" "@hapi/topo" "^5.0.0" @@ -4684,2834 +4702,2879 @@ joi@^17.4.2, joi@^17.6.0: "@sideway/formula" "^3.0.0" "@sideway/pinpoint" "^2.0.0" -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= - -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= - -json-parse-better-errors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - -json5@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" - integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== - dependencies: - minimist "^1.2.0" - -json5@^2.1.2: - version "2.2.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" - integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== - dependencies: - minimist "^1.2.5" - -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" +"js-tokens@^3.0.0 || ^4.0.0", "js-tokens@^4.0.0": + "integrity" "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "resolved" "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + "version" "4.0.0" + +"js-yaml@^3.13.1": + "integrity" "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==" + "resolved" "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" + "version" "3.14.1" + dependencies: + "argparse" "^1.0.7" + "esprima" "^4.0.0" + +"js-yaml@^4.0.0": + "integrity" "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==" + "resolved" "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "argparse" "^2.0.1" + +"jsesc@^2.5.1": + "integrity" "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + "resolved" "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" + "version" "2.5.2" + +"jsesc@~0.5.0": + "integrity" "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + "resolved" "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" + "version" "0.5.0" + +"json-buffer@3.0.0": + "integrity" "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + "resolved" "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz" + "version" "3.0.0" + +"json-parse-better-errors@^1.0.2": + "integrity" "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + "resolved" "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz" + "version" "1.0.2" + +"json-parse-even-better-errors@^2.3.0": + "integrity" "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + "resolved" "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" + "version" "2.3.1" + +"json-schema-traverse@^0.4.1": + "integrity" "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "resolved" "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" + "version" "0.4.1" + +"json-schema-traverse@^1.0.0": + "integrity" "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "resolved" "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" + "version" "1.0.0" + +"json5@^1.0.1": + "integrity" "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==" + "resolved" "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "minimist" "^1.2.0" + +"json5@^2.1.2", "json5@^2.2.2": + "integrity" "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" + "resolved" "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" + "version" "2.2.3" + +"jsonfile@^6.0.1": + "integrity" "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==" + "resolved" "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "universalify" "^2.0.0" optionalDependencies: - graceful-fs "^4.1.6" - -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== - dependencies: - json-buffer "3.0.0" - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - -klona@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" - integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== - -latest-version@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" - integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== - dependencies: - package-json "^6.3.0" - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -lilconfig@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.4.tgz#f4507d043d7058b380b6a8f5cb7bcd4b34cee082" - integrity sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA== - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -loader-runner@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" - integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== - -loader-utils@^1.4.0: - version "1.4.2" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd3d151fec01a3" - integrity sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^1.0.1" - -loader-utils@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129" - integrity sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^2.1.2" - -loader-utils@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.0.tgz#bcecc51a7898bee7473d4bc6b845b23af8304d4f" - integrity sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ== - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.assignin@^4.0.9: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" - integrity sha1-uo31+4QesKPoBEIysOJjqNxqKKI= - -lodash.bind@^4.1.4: - version "4.2.1" - resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" - integrity sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU= - -lodash.curry@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.curry/-/lodash.curry-4.1.1.tgz#248e36072ede906501d75966200a86dab8b23170" - integrity sha1-JI42By7ekGUB11lmIAqG2riyMXA= - -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= - -lodash.defaults@^4.0.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" - integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= - -lodash.filter@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace" - integrity sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4= - -lodash.flatten@^4.2.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" - integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= - -lodash.flow@^3.3.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/lodash.flow/-/lodash.flow-3.5.0.tgz#87bf40292b8cf83e4e8ce1a3ae4209e20071675a" - integrity sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o= - -lodash.foreach@^4.3.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" - integrity sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM= - -lodash.map@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" - integrity sha1-dx7Hg540c9nEzeKLGTlMNWL09tM= - -lodash.memoize@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - -lodash.merge@^4.4.0: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.pick@^4.2.1: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" - integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM= - -lodash.reduce@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b" - integrity sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs= - -lodash.reject@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415" - integrity sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU= - -lodash.some@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" - integrity sha1-G7nzFO9ri63tE7VJFpsqlF62jk0= - -lodash.uniq@4.5.0, lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= - -lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lower-case@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" - integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== - dependencies: - tslib "^2.0.3" - -lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -magic-string@^0.25.3: - version "0.25.7" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" - integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== - dependencies: - sourcemap-codec "^1.4.4" - -make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - -markdown-escapes@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535" - integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg== - -mdast-squeeze-paragraphs@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz#7c4c114679c3bee27ef10b58e2e015be79f1ef97" - integrity sha512-zxdPn69hkQ1rm4J+2Cs2j6wDEv7O17TfXTJ33tl/+JPIoEmtV9t2ZzBM5LPHE8QlHsmVD8t3vPKCyY3oH+H8MQ== + "graceful-fs" "^4.1.6" + +"keyv@^3.0.0": + "integrity" "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==" + "resolved" "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "json-buffer" "3.0.0" + +"kind-of@^6.0.0", "kind-of@^6.0.2": + "integrity" "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + "resolved" "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" + "version" "6.0.3" + +"kleur@^3.0.3": + "integrity" "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" + "resolved" "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" + "version" "3.0.3" + +"klona@^2.0.5": + "integrity" "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==" + "resolved" "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz" + "version" "2.0.5" + +"latest-version@^5.1.0": + "integrity" "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==" + "resolved" "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "package-json" "^6.3.0" + +"leven@^3.1.0": + "integrity" "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" + "resolved" "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz" + "version" "3.1.0" + +"lilconfig@^2.0.3": + "integrity" "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==" + "resolved" "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz" + "version" "2.0.4" + +"lines-and-columns@^1.1.6": + "integrity" "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + "resolved" "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" + "version" "1.2.4" + +"loader-runner@^4.2.0": + "integrity" "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==" + "resolved" "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz" + "version" "4.2.0" + +"loader-utils@^1.4.0": + "integrity" "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==" + "resolved" "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz" + "version" "1.4.2" + dependencies: + "big.js" "^5.2.2" + "emojis-list" "^3.0.0" + "json5" "^1.0.1" + +"loader-utils@^2.0.0": + "integrity" "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==" + "resolved" "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "big.js" "^5.2.2" + "emojis-list" "^3.0.0" + "json5" "^2.1.2" + +"loader-utils@^3.2.0": + "integrity" "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==" + "resolved" "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz" + "version" "3.2.0" + +"locate-path@^3.0.0": + "integrity" "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==" + "resolved" "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "p-locate" "^3.0.0" + "path-exists" "^3.0.0" + +"locate-path@^5.0.0": + "integrity" "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==" + "resolved" "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "p-locate" "^4.1.0" + +"locate-path@^6.0.0": + "integrity" "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==" + "resolved" "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "p-locate" "^5.0.0" + +"lodash.assignin@^4.0.9": + "integrity" "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=" + "resolved" "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz" + "version" "4.2.0" + +"lodash.bind@^4.1.4": + "integrity" "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=" + "resolved" "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz" + "version" "4.2.1" + +"lodash.curry@^4.0.1": + "integrity" "sha1-JI42By7ekGUB11lmIAqG2riyMXA=" + "resolved" "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz" + "version" "4.1.1" + +"lodash.debounce@^4.0.8": + "integrity" "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + "resolved" "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" + "version" "4.0.8" + +"lodash.defaults@^4.0.1": + "integrity" "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" + "resolved" "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz" + "version" "4.2.0" + +"lodash.filter@^4.4.0": + "integrity" "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=" + "resolved" "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz" + "version" "4.6.0" + +"lodash.flatten@^4.2.0": + "integrity" "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + "resolved" "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz" + "version" "4.4.0" + +"lodash.flow@^3.3.0": + "integrity" "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o=" + "resolved" "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz" + "version" "3.5.0" + +"lodash.foreach@^4.3.0": + "integrity" "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" + "resolved" "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz" + "version" "4.5.0" + +"lodash.map@^4.4.0": + "integrity" "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=" + "resolved" "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz" + "version" "4.6.0" + +"lodash.memoize@^4.1.2": + "integrity" "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" + "resolved" "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz" + "version" "4.1.2" + +"lodash.merge@^4.4.0": + "integrity" "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "resolved" "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" + "version" "4.6.2" + +"lodash.pick@^4.2.1": + "integrity" "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" + "resolved" "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz" + "version" "4.4.0" + +"lodash.reduce@^4.4.0": + "integrity" "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" + "resolved" "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz" + "version" "4.6.0" + +"lodash.reject@^4.4.0": + "integrity" "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=" + "resolved" "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz" + "version" "4.6.0" + +"lodash.some@^4.4.0": + "integrity" "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" + "resolved" "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz" + "version" "4.6.0" + +"lodash.uniq@^4.5.0", "lodash.uniq@4.5.0": + "integrity" "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + "resolved" "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz" + "version" "4.5.0" + +"lodash@^4.17.14", "lodash@^4.17.19", "lodash@^4.17.20", "lodash@^4.17.21": + "integrity" "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "resolved" "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" + "version" "4.17.21" + +"loose-envify@^1.0.0", "loose-envify@^1.1.0", "loose-envify@^1.2.0", "loose-envify@^1.3.1", "loose-envify@^1.4.0": + "integrity" "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==" + "resolved" "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" + "version" "1.4.0" + dependencies: + "js-tokens" "^3.0.0 || ^4.0.0" + +"lower-case@^2.0.2": + "integrity" "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==" + "resolved" "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "tslib" "^2.0.3" + +"lowercase-keys@^1.0.0", "lowercase-keys@^1.0.1": + "integrity" "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + "resolved" "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz" + "version" "1.0.1" + +"lowercase-keys@^2.0.0": + "integrity" "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" + "resolved" "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz" + "version" "2.0.0" + +"lru-cache@^5.1.1": + "integrity" "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==" + "resolved" "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" + "version" "5.1.1" + dependencies: + "yallist" "^3.0.2" + +"lru-cache@^6.0.0": + "integrity" "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==" + "resolved" "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "yallist" "^4.0.0" + +"magic-string@^0.25.3": + "integrity" "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==" + "resolved" "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz" + "version" "0.25.7" + dependencies: + "sourcemap-codec" "^1.4.4" + +"make-dir@^3.0.0", "make-dir@^3.0.2", "make-dir@^3.1.0": + "integrity" "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==" + "resolved" "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "semver" "^6.0.0" + +"markdown-escapes@^1.0.0": + "integrity" "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==" + "resolved" "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz" + "version" "1.0.4" + +"mdast-squeeze-paragraphs@^4.0.0": + "integrity" "sha512-zxdPn69hkQ1rm4J+2Cs2j6wDEv7O17TfXTJ33tl/+JPIoEmtV9t2ZzBM5LPHE8QlHsmVD8t3vPKCyY3oH+H8MQ==" + "resolved" "https://registry.npmjs.org/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz" + "version" "4.0.0" dependencies: - unist-util-remove "^2.0.0" - -mdast-util-definitions@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz#c5c1a84db799173b4dcf7643cda999e440c24db2" - integrity sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ== - dependencies: - unist-util-visit "^2.0.0" + "unist-util-remove" "^2.0.0" -mdast-util-to-hast@10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz#0cfc82089494c52d46eb0e3edb7a4eb2aea021eb" - integrity sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA== +"mdast-util-definitions@^4.0.0": + "integrity" "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==" + "resolved" "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "unist-util-visit" "^2.0.0" + +"mdast-util-to-hast@10.0.1": + "integrity" "sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA==" + "resolved" "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz" + "version" "10.0.1" dependencies: "@types/mdast" "^3.0.0" "@types/unist" "^2.0.0" - mdast-util-definitions "^4.0.0" - mdurl "^1.0.0" - unist-builder "^2.0.0" - unist-util-generated "^1.0.0" - unist-util-position "^3.0.0" - unist-util-visit "^2.0.0" - -mdast-util-to-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b" - integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w== - -mdn-data@2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" - integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== - -mdurl@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" - integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - -memfs@^3.1.2, memfs@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.1.tgz#b78092f466a0dce054d63d39275b24c71d3f1305" - integrity sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw== - dependencies: - fs-monkey "1.0.3" - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - -micromatch@^4.0.2, micromatch@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== - dependencies: - braces "^3.0.1" - picomatch "^2.2.3" - -mime-db@1.51.0, "mime-db@>= 1.43.0 < 2": - version "1.51.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" - integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== - -mime-db@~1.33.0: - version "1.33.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" - integrity sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ== - -mime-types@2.1.18: - version "2.1.18" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" - integrity sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ== - dependencies: - mime-db "~1.33.0" - -mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: - version "2.1.34" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" - integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== - dependencies: - mime-db "1.51.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -mimic-response@^1.0.0, mimic-response@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - -mini-create-react-context@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz#072171561bfdc922da08a60c2197a497cc2d1d5e" - integrity sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ== + "mdast-util-definitions" "^4.0.0" + "mdurl" "^1.0.0" + "unist-builder" "^2.0.0" + "unist-util-generated" "^1.0.0" + "unist-util-position" "^3.0.0" + "unist-util-visit" "^2.0.0" + +"mdast-util-to-string@^2.0.0": + "integrity" "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==" + "resolved" "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz" + "version" "2.0.0" + +"mdn-data@2.0.14": + "integrity" "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + "resolved" "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz" + "version" "2.0.14" + +"mdurl@^1.0.0": + "integrity" "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" + "resolved" "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz" + "version" "1.0.1" + +"media-typer@0.3.0": + "integrity" "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "resolved" "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + "version" "0.3.0" + +"memfs@^3.1.2", "memfs@^3.4.1": + "integrity" "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==" + "resolved" "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz" + "version" "3.4.1" + dependencies: + "fs-monkey" "1.0.3" + +"merge-descriptors@1.0.1": + "integrity" "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "resolved" "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" + "version" "1.0.1" + +"merge-stream@^2.0.0": + "integrity" "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + "resolved" "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" + "version" "2.0.0" + +"merge2@^1.3.0", "merge2@^1.4.1": + "integrity" "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + "resolved" "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" + "version" "1.4.1" + +"methods@~1.1.2": + "integrity" "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "resolved" "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + "version" "1.1.2" + +"micromatch@^4.0.2", "micromatch@^4.0.4": + "integrity" "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==" + "resolved" "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz" + "version" "4.0.4" + dependencies: + "braces" "^3.0.1" + "picomatch" "^2.2.3" + +"mime-db@>= 1.43.0 < 2", "mime-db@1.51.0": + "integrity" "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" + "resolved" "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz" + "version" "1.51.0" + +"mime-db@~1.33.0": + "integrity" "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + "resolved" "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz" + "version" "1.33.0" + +"mime-types@^2.1.27", "mime-types@^2.1.31", "mime-types@~2.1.17", "mime-types@~2.1.24", "mime-types@~2.1.34": + "integrity" "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==" + "resolved" "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz" + "version" "2.1.34" + dependencies: + "mime-db" "1.51.0" + +"mime-types@2.1.18": + "integrity" "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==" + "resolved" "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz" + "version" "2.1.18" + dependencies: + "mime-db" "~1.33.0" + +"mime@1.6.0": + "integrity" "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + "resolved" "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" + "version" "1.6.0" + +"mimic-fn@^2.1.0": + "integrity" "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + "resolved" "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" + "version" "2.1.0" + +"mimic-response@^1.0.0", "mimic-response@^1.0.1": + "integrity" "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + "resolved" "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz" + "version" "1.0.1" + +"mini-create-react-context@^0.4.0": + "integrity" "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==" + "resolved" "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz" + "version" "0.4.1" dependencies: "@babel/runtime" "^7.12.1" - tiny-warning "^1.0.3" - -mini-css-extract-plugin@^1.6.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-1.6.2.tgz#83172b4fd812f8fc4a09d6f6d16f924f53990ca8" - integrity sha512-WhDvO3SjGm40oV5y26GjMJYjd2UMqrLAGKy5YS2/3QKJy2F7jgynuHTir/tgUUOiNQu5saXHdc8reo7YuhhT4Q== - dependencies: - loader-utils "^2.0.0" - schema-utils "^3.0.0" - webpack-sources "^1.1.0" - -minimalistic-assert@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimatch@3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^3.0.4: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.0, minimist@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" - integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== - -mkdirp@^0.5.5: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" - -mrmime@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.0.tgz#14d387f0585a5233d291baba339b063752a2398b" - integrity sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3, ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -multicast-dns-service-types@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" - integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE= - -multicast-dns@^6.0.1: - version "6.2.3" - resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" - integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== - dependencies: - dns-packet "^1.3.1" - thunky "^1.0.2" - -nanoid@^3.2.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" - integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== - -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - -neo-async@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -no-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" - integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== - dependencies: - lower-case "^2.0.2" - tslib "^2.0.3" - -node-emoji@^1.10.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c" - integrity sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A== - dependencies: - lodash "^4.17.21" - -node-fetch@2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== - dependencies: - whatwg-url "^5.0.0" - -node-forge@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.0.tgz#37a874ea723855f37db091e6c186e5b67a01d4b2" - integrity sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA== - -node-releases@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01" - integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg== - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -normalize-range@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= - -normalize-url@^4.1.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" - integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== - -normalize-url@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" - integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -nprogress@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1" - integrity sha1-y480xTIT2JVyP8urkH6UIq28r7E= - -nth-check@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2" - integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w== - dependencies: - boolbase "^1.0.0" - -nth-check@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" - integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== - dependencies: - boolbase "~1.0.0" - -object-assign@^4.1.0, object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-is@^1.0.1: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -object-keys@^1.0.12, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" - object-keys "^1.1.1" + "tiny-warning" "^1.0.3" + +"mini-css-extract-plugin@^1.6.0": + "integrity" "sha512-WhDvO3SjGm40oV5y26GjMJYjd2UMqrLAGKy5YS2/3QKJy2F7jgynuHTir/tgUUOiNQu5saXHdc8reo7YuhhT4Q==" + "resolved" "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.6.2.tgz" + "version" "1.6.2" + dependencies: + "loader-utils" "^2.0.0" + "schema-utils" "^3.0.0" + "webpack-sources" "^1.1.0" + +"minimalistic-assert@^1.0.0": + "integrity" "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + "resolved" "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" + "version" "1.0.1" + +"minimatch@^3.0.4": + "integrity" "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==" + "resolved" "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" + "version" "3.1.2" + dependencies: + "brace-expansion" "^1.1.7" + +"minimatch@3.0.4": + "integrity" "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==" + "resolved" "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "brace-expansion" "^1.1.7" + +"minimist@^1.2.0", "minimist@^1.2.5": + "integrity" "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==" + "resolved" "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz" + "version" "1.2.7" + +"mkdirp@^0.5.5": + "integrity" "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==" + "resolved" "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz" + "version" "0.5.5" + dependencies: + "minimist" "^1.2.5" + +"mrmime@^1.0.0": + "integrity" "sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ==" + "resolved" "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz" + "version" "1.0.0" + +"ms@^2.1.1", "ms@2.1.3": + "integrity" "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "resolved" "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + "version" "2.1.3" + +"ms@2.0.0": + "integrity" "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "resolved" "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + "version" "2.0.0" + +"ms@2.1.2": + "integrity" "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "resolved" "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" + "version" "2.1.2" + +"multicast-dns-service-types@^1.1.0": + "integrity" "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" + "resolved" "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz" + "version" "1.1.0" + +"multicast-dns@^6.0.1": + "integrity" "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==" + "resolved" "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz" + "version" "6.2.3" + dependencies: + "dns-packet" "^1.3.1" + "thunky" "^1.0.2" + +"nanoid@^3.2.0": + "integrity" "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==" + "resolved" "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz" + "version" "3.3.1" + +"negotiator@0.6.3": + "integrity" "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + "resolved" "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" + "version" "0.6.3" + +"neo-async@^2.6.2": + "integrity" "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + "resolved" "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" + "version" "2.6.2" + +"no-case@^3.0.4": + "integrity" "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==" + "resolved" "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "lower-case" "^2.0.2" + "tslib" "^2.0.3" + +"node-emoji@^1.10.0": + "integrity" "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==" + "resolved" "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz" + "version" "1.11.0" + dependencies: + "lodash" "^4.17.21" + +"node-fetch@2.6.7": + "integrity" "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==" + "resolved" "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz" + "version" "2.6.7" + dependencies: + "whatwg-url" "^5.0.0" + +"node-forge@^1.2.0": + "integrity" "sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA==" + "resolved" "https://registry.npmjs.org/node-forge/-/node-forge-1.3.0.tgz" + "version" "1.3.0" + +"node-releases@^2.0.8": + "integrity" "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" + "resolved" "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz" + "version" "2.0.10" + +"normalize-path@^3.0.0", "normalize-path@~3.0.0": + "integrity" "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + "resolved" "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + "version" "3.0.0" + +"normalize-range@^0.1.2": + "integrity" "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=" + "resolved" "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz" + "version" "0.1.2" + +"normalize-url@^4.1.0": + "integrity" "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==" + "resolved" "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz" + "version" "4.5.1" + +"normalize-url@^6.0.1": + "integrity" "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" + "resolved" "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz" + "version" "6.1.0" + +"npm-run-path@^4.0.1": + "integrity" "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==" + "resolved" "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz" + "version" "4.0.1" + dependencies: + "path-key" "^3.0.0" + +"nprogress@^0.2.0": + "integrity" "sha1-y480xTIT2JVyP8urkH6UIq28r7E=" + "resolved" "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz" + "version" "0.2.0" + +"nth-check@^2.0.1": + "integrity" "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==" + "resolved" "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "boolbase" "^1.0.0" + +"nth-check@~1.0.1": + "integrity" "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==" + "resolved" "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "boolbase" "~1.0.0" + +"object-assign@^4.1.0", "object-assign@^4.1.1": + "integrity" "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "resolved" "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + "version" "4.1.1" + +"object-is@^1.0.1": + "integrity" "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==" + "resolved" "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz" + "version" "1.1.5" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.3" + +"object-keys@^1.0.12", "object-keys@^1.1.1": + "integrity" "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + "resolved" "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" + "version" "1.1.1" + +"object.assign@^4.1.0": + "integrity" "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==" + "resolved" "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "call-bind" "^1.0.0" + "define-properties" "^1.1.3" + "has-symbols" "^1.0.1" + "object-keys" "^1.1.1" -obuf@^1.0.0, obuf@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" - integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== +"obuf@^1.0.0", "obuf@^1.1.2": + "integrity" "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + "resolved" "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz" + "version" "1.1.2" -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" +"on-finished@~2.3.0": + "integrity" "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=" + "resolved" "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" + "version" "2.3.0" + dependencies: + "ee-first" "1.1.1" -on-headers@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== - -once@^1.3.0, once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" +"on-headers@~1.0.2": + "integrity" "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + "resolved" "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz" + "version" "1.0.2" + +"once@^1.3.0", "once@^1.3.1", "once@^1.4.0": + "integrity" "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=" + "resolved" "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + "version" "1.4.0" + dependencies: + "wrappy" "1" -onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== +"onetime@^5.1.2": + "integrity" "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==" + "resolved" "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" + "version" "5.1.2" dependencies: - mimic-fn "^2.1.0" + "mimic-fn" "^2.1.0" -open@^8.0.9, open@^8.4.0: - version "8.4.0" - resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" - integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q== +"open@^8.0.9", "open@^8.4.0": + "integrity" "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==" + "resolved" "https://registry.npmjs.org/open/-/open-8.4.0.tgz" + "version" "8.4.0" dependencies: - define-lazy-prop "^2.0.0" - is-docker "^2.1.1" - is-wsl "^2.2.0" + "define-lazy-prop" "^2.0.0" + "is-docker" "^2.1.1" + "is-wsl" "^2.2.0" -opener@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" - integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== +"opener@^1.5.2": + "integrity" "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==" + "resolved" "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz" + "version" "1.5.2" -p-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== +"p-cancelable@^1.0.0": + "integrity" "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" + "resolved" "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz" + "version" "1.1.0" -p-limit@^2.0.0, p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== +"p-limit@^2.0.0", "p-limit@^2.2.0": + "integrity" "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==" + "resolved" "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" + "version" "2.3.0" dependencies: - p-try "^2.0.0" + "p-try" "^2.0.0" -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== +"p-limit@^3.0.2": + "integrity" "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==" + "resolved" "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" + "version" "3.1.0" dependencies: - yocto-queue "^0.1.0" + "yocto-queue" "^0.1.0" -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== +"p-locate@^3.0.0": + "integrity" "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==" + "resolved" "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz" + "version" "3.0.0" dependencies: - p-limit "^2.0.0" + "p-limit" "^2.0.0" -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== +"p-locate@^4.1.0": + "integrity" "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==" + "resolved" "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" + "version" "4.1.0" dependencies: - p-limit "^2.2.0" + "p-limit" "^2.2.0" -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== +"p-locate@^5.0.0": + "integrity" "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==" + "resolved" "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" + "version" "5.0.0" dependencies: - p-limit "^3.0.2" + "p-limit" "^3.0.2" -p-map@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" - integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== +"p-map@^4.0.0": + "integrity" "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==" + "resolved" "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz" + "version" "4.0.0" dependencies: - aggregate-error "^3.0.0" + "aggregate-error" "^3.0.0" -p-retry@^4.5.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.1.tgz#8fcddd5cdf7a67a0911a9cf2ef0e5df7f602316c" - integrity sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA== +"p-retry@^4.5.0": + "integrity" "sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==" + "resolved" "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz" + "version" "4.6.1" dependencies: "@types/retry" "^0.12.0" - retry "^0.13.1" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -package-json@^6.3.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" - integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== - dependencies: - got "^9.6.0" - registry-auth-token "^4.0.0" - registry-url "^5.0.0" - semver "^6.2.0" - -param-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" - integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== - dependencies: - dot-case "^3.0.4" - tslib "^2.0.3" - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-entities@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" - integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ== - dependencies: - character-entities "^1.0.0" - character-entities-legacy "^1.0.0" - character-reference-invalid "^1.0.0" - is-alphanumerical "^1.0.0" - is-decimal "^1.0.0" - is-hexadecimal "^1.0.0" - -parse-json@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + "retry" "^0.13.1" + +"p-try@^2.0.0": + "integrity" "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + "resolved" "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" + "version" "2.2.0" + +"package-json@^6.3.0": + "integrity" "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==" + "resolved" "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz" + "version" "6.5.0" + dependencies: + "got" "^9.6.0" + "registry-auth-token" "^4.0.0" + "registry-url" "^5.0.0" + "semver" "^6.2.0" + +"param-case@^3.0.4": + "integrity" "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==" + "resolved" "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "dot-case" "^3.0.4" + "tslib" "^2.0.3" + +"parent-module@^1.0.0": + "integrity" "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==" + "resolved" "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "callsites" "^3.0.0" + +"parse-entities@^2.0.0": + "integrity" "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==" + "resolved" "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "character-entities" "^1.0.0" + "character-entities-legacy" "^1.0.0" + "character-reference-invalid" "^1.0.0" + "is-alphanumerical" "^1.0.0" + "is-decimal" "^1.0.0" + "is-hexadecimal" "^1.0.0" + +"parse-json@^5.0.0": + "integrity" "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==" + "resolved" "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" + "version" "5.2.0" dependencies: "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -parse-numeric-range@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz#7c63b61190d61e4d53a1197f0c83c47bb670ffa3" - integrity sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ== - -parse5-htmlparser2-tree-adapter@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" - integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA== - dependencies: - parse5 "^6.0.1" - -parse5@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" - integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== - -parse5@^6.0.0, parse5@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" - integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== - -parseurl@~1.3.2, parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -pascal-case@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" - integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-is-inside@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= - -path-to-regexp@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.2.1.tgz#90b617025a16381a879bc82a38d4e8bdeb2bcf45" - integrity sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ== - -path-to-regexp@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" - integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== - dependencies: - isarray "0.0.1" - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pkg-dir@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -pkg-up@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" - integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== - dependencies: - find-up "^3.0.0" - -portfinder@^1.0.28: - version "1.0.28" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" - integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== - dependencies: - async "^2.6.2" - debug "^3.1.1" - mkdirp "^0.5.5" - -postcss-calc@^8.2.0: - version "8.2.4" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5" - integrity sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q== - dependencies: - postcss-selector-parser "^6.0.9" - postcss-value-parser "^4.2.0" - -postcss-colormin@^5.2.5: - version "5.2.5" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.2.5.tgz#d1fc269ac2ad03fe641d462b5d1dada35c69968a" - integrity sha512-+X30aDaGYq81mFqwyPpnYInsZQnNpdxMX0ajlY7AExCexEFkPVV+KrO7kXwayqEWL2xwEbNQ4nUO0ZsRWGnevg== - dependencies: - browserslist "^4.16.6" - caniuse-api "^3.0.0" - colord "^2.9.1" - postcss-value-parser "^4.2.0" - -postcss-convert-values@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.0.4.tgz#3e74dd97c581f475ae7b4500bc0a7c4fb3a6b1b6" - integrity sha512-bugzSAyjIexdObovsPZu/sBCTHccImJxLyFgeV0MmNBm/Lw5h5XnjfML6gzEmJ3A6nyfCW7hb1JXzcsA4Zfbdw== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-discard-comments@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.0.3.tgz#011acb63418d600fdbe18804e1bbecb543ad2f87" - integrity sha512-6W5BemziRoqIdAKT+1QjM4bNcJAQ7z7zk073730NHg4cUXh3/rQHHj7pmYxUB9aGhuRhBiUf0pXvIHkRwhQP0Q== - -postcss-discard-duplicates@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.3.tgz#10f202a4cfe9d407b73dfea7a477054d21ea0c1f" - integrity sha512-vPtm1Mf+kp7iAENTG7jI1MN1lk+fBqL5y+qxyi4v3H+lzsXEdfS3dwUZD45KVhgzDEgduur8ycB4hMegyMTeRw== - -postcss-discard-empty@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.0.3.tgz#ec185af4a3710b88933b0ff751aa157b6041dd6a" - integrity sha512-xGJugpaXKakwKI7sSdZjUuN4V3zSzb2Y0LOlmTajFbNinEjTfVs9PFW2lmKBaC/E64WwYppfqLD03P8l9BuueA== - -postcss-discard-overridden@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.0.4.tgz#cc999d6caf18ea16eff8b2b58f48ec3ddee35c9c" - integrity sha512-3j9QH0Qh1KkdxwiZOW82cId7zdwXVQv/gRXYDnwx5pBtR1sTkU4cXRK9lp5dSdiM0r0OICO/L8J6sV1/7m0kHg== - -postcss-discard-unused@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-5.0.3.tgz#89fd3ebdbed8320df77a4ad503bd83cff52409f5" - integrity sha512-WO6FJxL5fGnuE77ZbTcZ/nRZJ4+TOqNaqLBLWgkR4e+WdmHn77OHPyQmsRv7eOB2rLKL6tsq2bs1GwoKXD/++Q== - dependencies: - postcss-selector-parser "^6.0.5" - -postcss-loader@^6.1.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-6.2.1.tgz#0895f7346b1702103d30fdc66e4d494a93c008ef" - integrity sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q== - dependencies: - cosmiconfig "^7.0.0" - klona "^2.0.5" - semver "^7.3.5" - -postcss-merge-idents@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-5.0.3.tgz#04f333f32767bd7b7b002f0032da347ec3c8c484" - integrity sha512-Z4LCzh2WzMn69KaS2FaJcrIeDQ170V13QHq+0hnBEFKJJkD+y5qndZ/bl3AhpddrSrXWIVR+xAwjmHQIJI2Eog== - dependencies: - cssnano-utils "^3.0.2" - postcss-value-parser "^4.2.0" - -postcss-merge-longhand@^5.0.6: - version "5.0.6" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.0.6.tgz#090e60d5d3b3caad899f8774f8dccb33217d2166" - integrity sha512-rkmoPwQO6ymJSmWsX6l2hHeEBQa7C4kJb9jyi5fZB1sE8nSCv7sqchoYPixRwX/yvLoZP2y6FA5kcjiByeJqDg== - dependencies: - postcss-value-parser "^4.2.0" - stylehacks "^5.0.3" - -postcss-merge-rules@^5.0.6: - version "5.0.6" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.0.6.tgz#26b37411fe1e80202fcef61cab027265b8925f2b" - integrity sha512-nzJWJ9yXWp8AOEpn/HFAW72WKVGD2bsLiAmgw4hDchSij27bt6TF+sIK0cJUBAYT3SGcjtGGsOR89bwkkMuMgQ== + "error-ex" "^1.3.1" + "json-parse-even-better-errors" "^2.3.0" + "lines-and-columns" "^1.1.6" + +"parse-numeric-range@^1.3.0": + "integrity" "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" + "resolved" "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz" + "version" "1.3.0" + +"parse5-htmlparser2-tree-adapter@^6.0.1": + "integrity" "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==" + "resolved" "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "parse5" "^6.0.1" + +"parse5@^5.0.0": + "integrity" "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + "resolved" "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz" + "version" "5.1.1" + +"parse5@^6.0.0", "parse5@^6.0.1": + "integrity" "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + "resolved" "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz" + "version" "6.0.1" + +"parseurl@~1.3.2", "parseurl@~1.3.3": + "integrity" "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + "resolved" "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" + "version" "1.3.3" + +"pascal-case@^3.1.2": + "integrity" "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==" + "resolved" "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz" + "version" "3.1.2" + dependencies: + "no-case" "^3.0.4" + "tslib" "^2.0.3" + +"path-exists@^3.0.0": + "integrity" "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + "resolved" "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" + "version" "3.0.0" + +"path-exists@^4.0.0": + "integrity" "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + "resolved" "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" + "version" "4.0.0" + +"path-is-absolute@^1.0.0": + "integrity" "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "resolved" "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + "version" "1.0.1" + +"path-is-inside@1.0.2": + "integrity" "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + "resolved" "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz" + "version" "1.0.2" + +"path-key@^3.0.0", "path-key@^3.1.0": + "integrity" "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + "resolved" "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" + "version" "3.1.1" + +"path-parse@^1.0.7": + "integrity" "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "resolved" "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + "version" "1.0.7" + +"path-to-regexp@^1.7.0": + "integrity" "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==" + "resolved" "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz" + "version" "1.8.0" + dependencies: + "isarray" "0.0.1" + +"path-to-regexp@0.1.7": + "integrity" "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "resolved" "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" + "version" "0.1.7" + +"path-to-regexp@2.2.1": + "integrity" "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" + "resolved" "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz" + "version" "2.2.1" + +"path-type@^4.0.0": + "integrity" "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + "resolved" "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" + "version" "4.0.0" + +"picocolors@^1.0.0": + "integrity" "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "resolved" "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" + "version" "1.0.0" + +"picomatch@^2.0.4", "picomatch@^2.2.1", "picomatch@^2.2.3": + "integrity" "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + "resolved" "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + "version" "2.3.1" + +"pkg-dir@^4.1.0": + "integrity" "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==" + "resolved" "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" + "version" "4.2.0" + dependencies: + "find-up" "^4.0.0" + +"pkg-up@^3.1.0": + "integrity" "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==" + "resolved" "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "find-up" "^3.0.0" + +"portfinder@^1.0.28": + "integrity" "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==" + "resolved" "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz" + "version" "1.0.28" + dependencies: + "async" "^2.6.2" + "debug" "^3.1.1" + "mkdirp" "^0.5.5" + +"postcss-calc@^8.2.0": + "integrity" "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==" + "resolved" "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz" + "version" "8.2.4" + dependencies: + "postcss-selector-parser" "^6.0.9" + "postcss-value-parser" "^4.2.0" + +"postcss-colormin@^5.2.5": + "integrity" "sha512-+X30aDaGYq81mFqwyPpnYInsZQnNpdxMX0ajlY7AExCexEFkPVV+KrO7kXwayqEWL2xwEbNQ4nUO0ZsRWGnevg==" + "resolved" "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.2.5.tgz" + "version" "5.2.5" + dependencies: + "browserslist" "^4.16.6" + "caniuse-api" "^3.0.0" + "colord" "^2.9.1" + "postcss-value-parser" "^4.2.0" + +"postcss-convert-values@^5.0.4": + "integrity" "sha512-bugzSAyjIexdObovsPZu/sBCTHccImJxLyFgeV0MmNBm/Lw5h5XnjfML6gzEmJ3A6nyfCW7hb1JXzcsA4Zfbdw==" + "resolved" "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.0.4.tgz" + "version" "5.0.4" + dependencies: + "postcss-value-parser" "^4.2.0" + +"postcss-discard-comments@^5.0.3": + "integrity" "sha512-6W5BemziRoqIdAKT+1QjM4bNcJAQ7z7zk073730NHg4cUXh3/rQHHj7pmYxUB9aGhuRhBiUf0pXvIHkRwhQP0Q==" + "resolved" "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.0.3.tgz" + "version" "5.0.3" + +"postcss-discard-duplicates@^5.0.3": + "integrity" "sha512-vPtm1Mf+kp7iAENTG7jI1MN1lk+fBqL5y+qxyi4v3H+lzsXEdfS3dwUZD45KVhgzDEgduur8ycB4hMegyMTeRw==" + "resolved" "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.3.tgz" + "version" "5.0.3" + +"postcss-discard-empty@^5.0.3": + "integrity" "sha512-xGJugpaXKakwKI7sSdZjUuN4V3zSzb2Y0LOlmTajFbNinEjTfVs9PFW2lmKBaC/E64WwYppfqLD03P8l9BuueA==" + "resolved" "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.0.3.tgz" + "version" "5.0.3" + +"postcss-discard-overridden@^5.0.4": + "integrity" "sha512-3j9QH0Qh1KkdxwiZOW82cId7zdwXVQv/gRXYDnwx5pBtR1sTkU4cXRK9lp5dSdiM0r0OICO/L8J6sV1/7m0kHg==" + "resolved" "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.0.4.tgz" + "version" "5.0.4" + +"postcss-discard-unused@^5.0.3": + "integrity" "sha512-WO6FJxL5fGnuE77ZbTcZ/nRZJ4+TOqNaqLBLWgkR4e+WdmHn77OHPyQmsRv7eOB2rLKL6tsq2bs1GwoKXD/++Q==" + "resolved" "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-5.0.3.tgz" + "version" "5.0.3" + dependencies: + "postcss-selector-parser" "^6.0.5" + +"postcss-loader@^6.1.1": + "integrity" "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==" + "resolved" "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz" + "version" "6.2.1" + dependencies: + "cosmiconfig" "^7.0.0" + "klona" "^2.0.5" + "semver" "^7.3.5" + +"postcss-merge-idents@^5.0.3": + "integrity" "sha512-Z4LCzh2WzMn69KaS2FaJcrIeDQ170V13QHq+0hnBEFKJJkD+y5qndZ/bl3AhpddrSrXWIVR+xAwjmHQIJI2Eog==" + "resolved" "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-5.0.3.tgz" + "version" "5.0.3" + dependencies: + "cssnano-utils" "^3.0.2" + "postcss-value-parser" "^4.2.0" + +"postcss-merge-longhand@^5.0.6": + "integrity" "sha512-rkmoPwQO6ymJSmWsX6l2hHeEBQa7C4kJb9jyi5fZB1sE8nSCv7sqchoYPixRwX/yvLoZP2y6FA5kcjiByeJqDg==" + "resolved" "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.0.6.tgz" + "version" "5.0.6" + dependencies: + "postcss-value-parser" "^4.2.0" + "stylehacks" "^5.0.3" + +"postcss-merge-rules@^5.0.6": + "integrity" "sha512-nzJWJ9yXWp8AOEpn/HFAW72WKVGD2bsLiAmgw4hDchSij27bt6TF+sIK0cJUBAYT3SGcjtGGsOR89bwkkMuMgQ==" + "resolved" "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.0.6.tgz" + "version" "5.0.6" dependencies: - browserslist "^4.16.6" - caniuse-api "^3.0.0" - cssnano-utils "^3.0.2" - postcss-selector-parser "^6.0.5" + "browserslist" "^4.16.6" + "caniuse-api" "^3.0.0" + "cssnano-utils" "^3.0.2" + "postcss-selector-parser" "^6.0.5" -postcss-minify-font-values@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.0.4.tgz#627d824406b0712243221891f40a44fffe1467fd" - integrity sha512-RN6q3tyuEesvyCYYFCRGJ41J1XFvgV+dvYGHr0CeHv8F00yILlN8Slf4t8XW4IghlfZYCeyRrANO6HpJ948ieA== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-minify-gradients@^5.0.6: - version "5.0.6" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.0.6.tgz#b07cef51a93f075e94053fd972ff1cba2eaf6503" - integrity sha512-E/dT6oVxB9nLGUTiY/rG5dX9taugv9cbLNTFad3dKxOO+BQg25Q/xo2z2ddG+ZB1CbkZYaVwx5blY8VC7R/43A== - dependencies: - colord "^2.9.1" - cssnano-utils "^3.0.2" - postcss-value-parser "^4.2.0" +"postcss-minify-font-values@^5.0.4": + "integrity" "sha512-RN6q3tyuEesvyCYYFCRGJ41J1XFvgV+dvYGHr0CeHv8F00yILlN8Slf4t8XW4IghlfZYCeyRrANO6HpJ948ieA==" + "resolved" "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.0.4.tgz" + "version" "5.0.4" + dependencies: + "postcss-value-parser" "^4.2.0" + +"postcss-minify-gradients@^5.0.6": + "integrity" "sha512-E/dT6oVxB9nLGUTiY/rG5dX9taugv9cbLNTFad3dKxOO+BQg25Q/xo2z2ddG+ZB1CbkZYaVwx5blY8VC7R/43A==" + "resolved" "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.0.6.tgz" + "version" "5.0.6" + dependencies: + "colord" "^2.9.1" + "cssnano-utils" "^3.0.2" + "postcss-value-parser" "^4.2.0" -postcss-minify-params@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.0.5.tgz#86cb624358cd45c21946f8c317893f0449396646" - integrity sha512-YBNuq3Rz5LfLFNHb9wrvm6t859b8qIqfXsWeK7wROm3jSKNpO1Y5e8cOyBv6Acji15TgSrAwb3JkVNCqNyLvBg== +"postcss-minify-params@^5.0.5": + "integrity" "sha512-YBNuq3Rz5LfLFNHb9wrvm6t859b8qIqfXsWeK7wROm3jSKNpO1Y5e8cOyBv6Acji15TgSrAwb3JkVNCqNyLvBg==" + "resolved" "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.0.5.tgz" + "version" "5.0.5" dependencies: - browserslist "^4.16.6" - cssnano-utils "^3.0.2" - postcss-value-parser "^4.2.0" + "browserslist" "^4.16.6" + "cssnano-utils" "^3.0.2" + "postcss-value-parser" "^4.2.0" -postcss-minify-selectors@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.1.3.tgz#6ac12d52aa661fd509469d87ab2cebb0a1e3a1b5" - integrity sha512-9RJfTiQEKA/kZhMaEXND893nBqmYQ8qYa/G+uPdVnXF6D/FzpfI6kwBtWEcHx5FqDbA79O9n6fQJfrIj6M8jvQ== +"postcss-minify-selectors@^5.1.3": + "integrity" "sha512-9RJfTiQEKA/kZhMaEXND893nBqmYQ8qYa/G+uPdVnXF6D/FzpfI6kwBtWEcHx5FqDbA79O9n6fQJfrIj6M8jvQ==" + "resolved" "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.1.3.tgz" + "version" "5.1.3" dependencies: - postcss-selector-parser "^6.0.5" + "postcss-selector-parser" "^6.0.5" -postcss-modules-extract-imports@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" - integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== +"postcss-modules-extract-imports@^3.0.0": + "integrity" "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==" + "resolved" "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz" + "version" "3.0.0" -postcss-modules-local-by-default@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" - integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== +"postcss-modules-local-by-default@^4.0.0": + "integrity" "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==" + "resolved" "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz" + "version" "4.0.0" dependencies: - icss-utils "^5.0.0" - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.1.0" + "icss-utils" "^5.0.0" + "postcss-selector-parser" "^6.0.2" + "postcss-value-parser" "^4.1.0" -postcss-modules-scope@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" - integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== +"postcss-modules-scope@^3.0.0": + "integrity" "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==" + "resolved" "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz" + "version" "3.0.0" dependencies: - postcss-selector-parser "^6.0.4" + "postcss-selector-parser" "^6.0.4" -postcss-modules-values@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" - integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== +"postcss-modules-values@^4.0.0": + "integrity" "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==" + "resolved" "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz" + "version" "4.0.0" dependencies: - icss-utils "^5.0.0" + "icss-utils" "^5.0.0" -postcss-normalize-charset@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.0.3.tgz#719fb9f9ca9835fcbd4fed8d6e0d72a79e7b5472" - integrity sha512-iKEplDBco9EfH7sx4ut7R2r/dwTnUqyfACf62Unc9UiyFuI7uUqZZtY+u+qp7g8Qszl/U28HIfcsI3pEABWFfA== +"postcss-normalize-charset@^5.0.3": + "integrity" "sha512-iKEplDBco9EfH7sx4ut7R2r/dwTnUqyfACf62Unc9UiyFuI7uUqZZtY+u+qp7g8Qszl/U28HIfcsI3pEABWFfA==" + "resolved" "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.0.3.tgz" + "version" "5.0.3" -postcss-normalize-display-values@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.3.tgz#94cc82e20c51cc4ffba6b36e9618adc1e50db8c1" - integrity sha512-FIV5FY/qs4Ja32jiDb5mVj5iWBlS3N8tFcw2yg98+8MkRgyhtnBgSC0lxU+16AMHbjX5fbSJgw5AXLMolonuRQ== +"postcss-normalize-display-values@^5.0.3": + "integrity" "sha512-FIV5FY/qs4Ja32jiDb5mVj5iWBlS3N8tFcw2yg98+8MkRgyhtnBgSC0lxU+16AMHbjX5fbSJgw5AXLMolonuRQ==" + "resolved" "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.3.tgz" + "version" "5.0.3" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-positions@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.0.4.tgz#4001f38c99675437b83277836fb4291887fcc6cc" - integrity sha512-qynirjBX0Lc73ROomZE3lzzmXXTu48/QiEzKgMeqh28+MfuHLsuqC9po4kj84igZqqFGovz8F8hf44hA3dPYmQ== +"postcss-normalize-positions@^5.0.4": + "integrity" "sha512-qynirjBX0Lc73ROomZE3lzzmXXTu48/QiEzKgMeqh28+MfuHLsuqC9po4kj84igZqqFGovz8F8hf44hA3dPYmQ==" + "resolved" "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-repeat-style@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.4.tgz#d005adf9ee45fae78b673031a376c0c871315145" - integrity sha512-Innt+wctD7YpfeDR7r5Ik6krdyppyAg2HBRpX88fo5AYzC1Ut/l3xaxACG0KsbX49cO2n5EB13clPwuYVt8cMA== +"postcss-normalize-repeat-style@^5.0.4": + "integrity" "sha512-Innt+wctD7YpfeDR7r5Ik6krdyppyAg2HBRpX88fo5AYzC1Ut/l3xaxACG0KsbX49cO2n5EB13clPwuYVt8cMA==" + "resolved" "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-string@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.0.4.tgz#b5e00a07597e7aa8a871817bfeac2bfaa59c3333" - integrity sha512-Dfk42l0+A1CDnVpgE606ENvdmksttLynEqTQf5FL3XGQOyqxjbo25+pglCUvziicTxjtI2NLUR6KkxyUWEVubQ== +"postcss-normalize-string@^5.0.4": + "integrity" "sha512-Dfk42l0+A1CDnVpgE606ENvdmksttLynEqTQf5FL3XGQOyqxjbo25+pglCUvziicTxjtI2NLUR6KkxyUWEVubQ==" + "resolved" "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-timing-functions@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.3.tgz#47210227bfcba5e52650d7a18654337090de7072" - integrity sha512-QRfjvFh11moN4PYnJ7hia4uJXeFotyK3t2jjg8lM9mswleGsNw2Lm3I5wO+l4k1FzK96EFwEVn8X8Ojrp2gP4g== +"postcss-normalize-timing-functions@^5.0.3": + "integrity" "sha512-QRfjvFh11moN4PYnJ7hia4uJXeFotyK3t2jjg8lM9mswleGsNw2Lm3I5wO+l4k1FzK96EFwEVn8X8Ojrp2gP4g==" + "resolved" "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.3.tgz" + "version" "5.0.3" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-unicode@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.4.tgz#02866096937005cdb2c17116c690f29505a1623d" - integrity sha512-W79Regn+a+eXTzB+oV/8XJ33s3pDyFTND2yDuUCo0Xa3QSy1HtNIfRVPXNubHxjhlqmMFADr3FSCHT84ITW3ig== +"postcss-normalize-unicode@^5.0.4": + "integrity" "sha512-W79Regn+a+eXTzB+oV/8XJ33s3pDyFTND2yDuUCo0Xa3QSy1HtNIfRVPXNubHxjhlqmMFADr3FSCHT84ITW3ig==" + "resolved" "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.4.tgz" + "version" "5.0.4" dependencies: - browserslist "^4.16.6" - postcss-value-parser "^4.2.0" + "browserslist" "^4.16.6" + "postcss-value-parser" "^4.2.0" -postcss-normalize-url@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.0.5.tgz#c39efc12ff119f6f45f0b4f516902b12c8080e3a" - integrity sha512-Ws3tX+PcekYlXh+ycAt0wyzqGthkvVtZ9SZLutMVvHARxcpu4o7vvXcNoiNKyjKuWecnjS6HDI3fjBuDr5MQxQ== +"postcss-normalize-url@^5.0.5": + "integrity" "sha512-Ws3tX+PcekYlXh+ycAt0wyzqGthkvVtZ9SZLutMVvHARxcpu4o7vvXcNoiNKyjKuWecnjS6HDI3fjBuDr5MQxQ==" + "resolved" "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.0.5.tgz" + "version" "5.0.5" dependencies: - normalize-url "^6.0.1" - postcss-value-parser "^4.2.0" + "normalize-url" "^6.0.1" + "postcss-value-parser" "^4.2.0" -postcss-normalize-whitespace@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.4.tgz#1d477e7da23fecef91fc4e37d462272c7b55c5ca" - integrity sha512-wsnuHolYZjMwWZJoTC9jeI2AcjA67v4UuidDrPN9RnX8KIZfE+r2Nd6XZRwHVwUiHmRvKQtxiqo64K+h8/imaw== +"postcss-normalize-whitespace@^5.0.4": + "integrity" "sha512-wsnuHolYZjMwWZJoTC9jeI2AcjA67v4UuidDrPN9RnX8KIZfE+r2Nd6XZRwHVwUiHmRvKQtxiqo64K+h8/imaw==" + "resolved" "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-ordered-values@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.0.5.tgz#e878af822a130c3f3709737e24cb815ca7c6d040" - integrity sha512-mfY7lXpq+8bDEHfP+muqibDPhZ5eP9zgBEF9XRvoQgXcQe2Db3G1wcvjbnfjXG6wYsl+0UIjikqq4ym1V2jGMQ== +"postcss-ordered-values@^5.0.5": + "integrity" "sha512-mfY7lXpq+8bDEHfP+muqibDPhZ5eP9zgBEF9XRvoQgXcQe2Db3G1wcvjbnfjXG6wYsl+0UIjikqq4ym1V2jGMQ==" + "resolved" "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.0.5.tgz" + "version" "5.0.5" dependencies: - cssnano-utils "^3.0.2" - postcss-value-parser "^4.2.0" + "cssnano-utils" "^3.0.2" + "postcss-value-parser" "^4.2.0" -postcss-reduce-idents@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-5.0.3.tgz#b632796275b4fa1a4040799969dd17167eaf4d8b" - integrity sha512-9bj9/Xhwiti0Z35kkguJX4G6yUYVw8S1kRLU4jFSCTEuHu4yJggf4rNUoVnT45lm/vU97Wd593CxspMDbHxy4w== +"postcss-reduce-idents@^5.0.3": + "integrity" "sha512-9bj9/Xhwiti0Z35kkguJX4G6yUYVw8S1kRLU4jFSCTEuHu4yJggf4rNUoVnT45lm/vU97Wd593CxspMDbHxy4w==" + "resolved" "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-5.0.3.tgz" + "version" "5.0.3" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-reduce-initial@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.0.3.tgz#68891594defd648253703bbd8f1093162f19568d" - integrity sha512-c88TkSnQ/Dnwgb4OZbKPOBbCaauwEjbECP5uAuFPOzQ+XdjNjRH7SG0dteXrpp1LlIFEKK76iUGgmw2V0xeieA== +"postcss-reduce-initial@^5.0.3": + "integrity" "sha512-c88TkSnQ/Dnwgb4OZbKPOBbCaauwEjbECP5uAuFPOzQ+XdjNjRH7SG0dteXrpp1LlIFEKK76iUGgmw2V0xeieA==" + "resolved" "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.0.3.tgz" + "version" "5.0.3" dependencies: - browserslist "^4.16.6" - caniuse-api "^3.0.0" + "browserslist" "^4.16.6" + "caniuse-api" "^3.0.0" -postcss-reduce-transforms@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.4.tgz#717e72d30befe857f7d2784dba10eb1157863712" - integrity sha512-VIJB9SFSaL8B/B7AXb7KHL6/GNNbbCHslgdzS9UDfBZYIA2nx8NLY7iD/BXFSO/1sRUILzBTfHCoW5inP37C5g== +"postcss-reduce-transforms@^5.0.4": + "integrity" "sha512-VIJB9SFSaL8B/B7AXb7KHL6/GNNbbCHslgdzS9UDfBZYIA2nx8NLY7iD/BXFSO/1sRUILzBTfHCoW5inP37C5g==" + "resolved" "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: - version "6.0.9" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f" - integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ== +"postcss-selector-parser@^6.0.2", "postcss-selector-parser@^6.0.4", "postcss-selector-parser@^6.0.5", "postcss-selector-parser@^6.0.9": + "integrity" "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==" + "resolved" "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz" + "version" "6.0.9" dependencies: - cssesc "^3.0.0" - util-deprecate "^1.0.2" + "cssesc" "^3.0.0" + "util-deprecate" "^1.0.2" -postcss-sort-media-queries@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/postcss-sort-media-queries/-/postcss-sort-media-queries-4.2.1.tgz#a99bae69ef1098ee3b64a5fa94d258ec240d0355" - integrity sha512-9VYekQalFZ3sdgcTjXMa0dDjsfBVHXlraYJEMiOJ/2iMmI2JGCMavP16z3kWOaRu8NSaJCTgVpB/IVpH5yT9YQ== +"postcss-sort-media-queries@^4.1.0": + "integrity" "sha512-9VYekQalFZ3sdgcTjXMa0dDjsfBVHXlraYJEMiOJ/2iMmI2JGCMavP16z3kWOaRu8NSaJCTgVpB/IVpH5yT9YQ==" + "resolved" "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-4.2.1.tgz" + "version" "4.2.1" dependencies: - sort-css-media-queries "2.0.4" + "sort-css-media-queries" "2.0.4" -postcss-svgo@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.0.4.tgz#cfa8682f47b88f7cd75108ec499e133b43102abf" - integrity sha512-yDKHvULbnZtIrRqhZoA+rxreWpee28JSRH/gy9727u0UCgtpv1M/9WEWY3xySlFa0zQJcqf6oCBJPR5NwkmYpg== +"postcss-svgo@^5.0.4": + "integrity" "sha512-yDKHvULbnZtIrRqhZoA+rxreWpee28JSRH/gy9727u0UCgtpv1M/9WEWY3xySlFa0zQJcqf6oCBJPR5NwkmYpg==" + "resolved" "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-value-parser "^4.2.0" - svgo "^2.7.0" + "postcss-value-parser" "^4.2.0" + "svgo" "^2.7.0" -postcss-unique-selectors@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.0.4.tgz#08e188126b634ddfa615fb1d6c262bafdd64826e" - integrity sha512-5ampwoSDJCxDPoANBIlMgoBcYUHnhaiuLYJR5pj1DLnYQvMRVyFuTA5C3Bvt+aHtiqWpJkD/lXT50Vo1D0ZsAQ== +"postcss-unique-selectors@^5.0.4": + "integrity" "sha512-5ampwoSDJCxDPoANBIlMgoBcYUHnhaiuLYJR5pj1DLnYQvMRVyFuTA5C3Bvt+aHtiqWpJkD/lXT50Vo1D0ZsAQ==" + "resolved" "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-selector-parser "^6.0.5" + "postcss-selector-parser" "^6.0.5" -postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" - integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== +"postcss-value-parser@^4.1.0", "postcss-value-parser@^4.2.0": + "integrity" "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "resolved" "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" + "version" "4.2.0" -postcss-zindex@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-5.0.2.tgz#7e48aee54062c93418593035229ea06b92381251" - integrity sha512-KPQFjQu73H35HLHmE8Wv31ygfQoucxD52oRm4FPFv1emYhFMzUQdF8adaXCevFLIHPRp2rRYfbaDiEqZ4YjVtw== +"postcss-zindex@^5.0.2": + "integrity" "sha512-KPQFjQu73H35HLHmE8Wv31ygfQoucxD52oRm4FPFv1emYhFMzUQdF8adaXCevFLIHPRp2rRYfbaDiEqZ4YjVtw==" + "resolved" "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-5.0.2.tgz" + "version" "5.0.2" -postcss@^8.3.11, postcss@^8.3.5, postcss@^8.3.7, postcss@^8.4.5: - version "8.4.6" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.6.tgz#c5ff3c3c457a23864f32cb45ac9b741498a09ae1" - integrity sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA== +"postcss@^7.0.0 || ^8.0.1", "postcss@^8.0.9", "postcss@^8.1.0", "postcss@^8.2.15", "postcss@^8.2.2", "postcss@^8.3.11", "postcss@^8.3.5", "postcss@^8.3.7", "postcss@^8.4.4", "postcss@^8.4.5": + "integrity" "sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA==" + "resolved" "https://registry.npmjs.org/postcss/-/postcss-8.4.6.tgz" + "version" "8.4.6" dependencies: - nanoid "^3.2.0" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= - -pretty-error@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" - integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw== - dependencies: - lodash "^4.17.20" - renderkid "^3.0.0" - -pretty-time@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pretty-time/-/pretty-time-1.1.0.tgz#ffb7429afabb8535c346a34e41873adf3d74dd0e" - integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA== - -prism-react-renderer@^1.2.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.3.1.tgz#88fc9d0df6bed06ca2b9097421349f8c2f24e30d" - integrity sha512-xUeDMEz074d0zc5y6rxiMp/dlC7C+5IDDlaEUlcBOFE2wddz7hz5PNupb087mPwTt7T9BrFmewObfCBuf/LKwQ== - -prismjs@^1.23.0: - version "1.27.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057" - integrity sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA== - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -promise@^7.1.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" - integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== - dependencies: - asap "~2.0.3" - -prompts@^2.4.1, prompts@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" - integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - -prop-types@^15.6.2, prop-types@^15.7.2: - version "15.8.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" - integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.13.1" - -property-information@^5.0.0, property-information@^5.3.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.6.0.tgz#61675545fb23002f245c6540ec46077d4da3ed69" - integrity sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA== - dependencies: - xtend "^4.0.0" - -proxy-addr@~2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" - integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== - dependencies: - forwarded "0.2.0" - ipaddr.js "1.9.1" - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - -punycode@^1.3.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -pupa@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" - integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A== - dependencies: - escape-goat "^2.0.0" - -pure-color@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/pure-color/-/pure-color-1.3.0.tgz#1fe064fb0ac851f0de61320a8bf796836422f33e" - integrity sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4= - -qs@6.9.7: - version "6.9.7" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe" - integrity sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw== - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -queue@6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.2.tgz#b91525283e2315c7553d2efa18d83e76432fed65" - integrity sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA== - dependencies: - inherits "~2.0.3" - -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -range-parser@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= - -range-parser@^1.2.1, range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.3.tgz#8f80305d11c2a0a545c2d9d89d7a0286fcead43c" - integrity sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g== - dependencies: - bytes "3.1.2" - http-errors "1.8.1" - iconv-lite "0.4.24" - unpipe "1.0.0" - -rc@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -react-base16-styling@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/react-base16-styling/-/react-base16-styling-0.6.0.tgz#ef2156d66cf4139695c8a167886cb69ea660792c" - integrity sha1-7yFW1mz0E5aVyKFniGy2nqZgeSw= - dependencies: - base16 "^1.0.0" - lodash.curry "^4.0.1" - lodash.flow "^3.3.0" - pure-color "^1.2.0" - -react-dev-utils@^12.0.0: - version "12.0.0" - resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.0.tgz#4eab12cdb95692a077616770b5988f0adf806526" - integrity sha512-xBQkitdxozPxt1YZ9O1097EJiVpwHr9FoAuEVURCKV0Av8NBERovJauzP7bo1ThvuhZ4shsQ1AJiu4vQpoT1AQ== + "nanoid" "^3.2.0" + "picocolors" "^1.0.0" + "source-map-js" "^1.0.2" + +"prepend-http@^2.0.0": + "integrity" "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + "resolved" "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz" + "version" "2.0.0" + +"pretty-error@^4.0.0": + "integrity" "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==" + "resolved" "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "lodash" "^4.17.20" + "renderkid" "^3.0.0" + +"pretty-time@^1.1.0": + "integrity" "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==" + "resolved" "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz" + "version" "1.1.0" + +"prism-react-renderer@^1.2.1": + "integrity" "sha512-xUeDMEz074d0zc5y6rxiMp/dlC7C+5IDDlaEUlcBOFE2wddz7hz5PNupb087mPwTt7T9BrFmewObfCBuf/LKwQ==" + "resolved" "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-1.3.1.tgz" + "version" "1.3.1" + +"prismjs@^1.23.0": + "integrity" "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==" + "resolved" "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz" + "version" "1.27.0" + +"process-nextick-args@~2.0.0": + "integrity" "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "resolved" "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" + "version" "2.0.1" + +"promise@^7.1.1": + "integrity" "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==" + "resolved" "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz" + "version" "7.3.1" + dependencies: + "asap" "~2.0.3" + +"prompts@^2.4.1", "prompts@^2.4.2": + "integrity" "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==" + "resolved" "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "kleur" "^3.0.3" + "sisteransi" "^1.0.5" + +"prop-types@^15.0.0", "prop-types@^15.6.2", "prop-types@^15.7.2": + "integrity" "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==" + "resolved" "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" + "version" "15.8.1" + dependencies: + "loose-envify" "^1.4.0" + "object-assign" "^4.1.1" + "react-is" "^16.13.1" + +"property-information@^5.0.0", "property-information@^5.3.0": + "integrity" "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==" + "resolved" "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz" + "version" "5.6.0" + dependencies: + "xtend" "^4.0.0" + +"proxy-addr@~2.0.7": + "integrity" "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==" + "resolved" "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" + "version" "2.0.7" + dependencies: + "forwarded" "0.2.0" + "ipaddr.js" "1.9.1" + +"pump@^3.0.0": + "integrity" "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==" + "resolved" "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "end-of-stream" "^1.1.0" + "once" "^1.3.1" + +"punycode@^1.3.2": + "integrity" "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + "resolved" "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" + "version" "1.4.1" + +"punycode@^2.1.0": + "integrity" "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "resolved" "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz" + "version" "2.1.1" + +"punycode@1.3.2": + "integrity" "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + "resolved" "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" + "version" "1.3.2" + +"pupa@^2.1.1": + "integrity" "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==" + "resolved" "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz" + "version" "2.1.1" + dependencies: + "escape-goat" "^2.0.0" + +"pure-color@^1.2.0": + "integrity" "sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4=" + "resolved" "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz" + "version" "1.3.0" + +"qs@6.9.7": + "integrity" "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" + "resolved" "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz" + "version" "6.9.7" + +"querystring@0.2.0": + "integrity" "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + "resolved" "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" + "version" "0.2.0" + +"queue-microtask@^1.2.2": + "integrity" "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" + "resolved" "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + "version" "1.2.3" + +"queue@6.0.2": + "integrity" "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==" + "resolved" "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz" + "version" "6.0.2" + dependencies: + "inherits" "~2.0.3" + +"randombytes@^2.1.0": + "integrity" "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==" + "resolved" "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "safe-buffer" "^5.1.0" + +"range-parser@^1.2.1", "range-parser@~1.2.1": + "integrity" "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + "resolved" "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" + "version" "1.2.1" + +"range-parser@1.2.0": + "integrity" "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + "resolved" "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz" + "version" "1.2.0" + +"raw-body@2.4.3": + "integrity" "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==" + "resolved" "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz" + "version" "2.4.3" + dependencies: + "bytes" "3.1.2" + "http-errors" "1.8.1" + "iconv-lite" "0.4.24" + "unpipe" "1.0.0" + +"rc@^1.2.8": + "integrity" "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==" + "resolved" "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz" + "version" "1.2.8" + dependencies: + "deep-extend" "^0.6.0" + "ini" "~1.3.0" + "minimist" "^1.2.0" + "strip-json-comments" "~2.0.1" + +"react-base16-styling@^0.6.0": + "integrity" "sha1-7yFW1mz0E5aVyKFniGy2nqZgeSw=" + "resolved" "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.6.0.tgz" + "version" "0.6.0" + dependencies: + "base16" "^1.0.0" + "lodash.curry" "^4.0.1" + "lodash.flow" "^3.3.0" + "pure-color" "^1.2.0" + +"react-dev-utils@^12.0.0": + "integrity" "sha512-xBQkitdxozPxt1YZ9O1097EJiVpwHr9FoAuEVURCKV0Av8NBERovJauzP7bo1ThvuhZ4shsQ1AJiu4vQpoT1AQ==" + "resolved" "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz" + "version" "12.0.0" dependencies: "@babel/code-frame" "^7.16.0" - address "^1.1.2" - browserslist "^4.18.1" - chalk "^4.1.2" - cross-spawn "^7.0.3" - detect-port-alt "^1.1.6" - escape-string-regexp "^4.0.0" - filesize "^8.0.6" - find-up "^5.0.0" - fork-ts-checker-webpack-plugin "^6.5.0" - global-modules "^2.0.0" - globby "^11.0.4" - gzip-size "^6.0.0" - immer "^9.0.7" - is-root "^2.1.0" - loader-utils "^3.2.0" - open "^8.4.0" - pkg-up "^3.1.0" - prompts "^2.4.2" - react-error-overlay "^6.0.10" - recursive-readdir "^2.2.2" - shell-quote "^1.7.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" - -react-dom@^16.10.2: - version "16.14.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.14.0.tgz#7ad838ec29a777fb3c75c3a190f661cf92ab8b89" - integrity sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - scheduler "^0.19.1" - -react-error-overlay@^6.0.10: - version "6.0.10" - resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.10.tgz#0fe26db4fa85d9dbb8624729580e90e7159a59a6" - integrity sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA== - -react-fast-compare@^3.1.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" - integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== - -react-helmet@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-6.1.0.tgz#a750d5165cb13cf213e44747502652e794468726" - integrity sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw== - dependencies: - object-assign "^4.1.1" - prop-types "^15.7.2" - react-fast-compare "^3.1.1" - react-side-effect "^2.1.0" - -react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -react-json-view@^1.21.3: - version "1.21.3" - resolved "https://registry.yarnpkg.com/react-json-view/-/react-json-view-1.21.3.tgz#f184209ee8f1bf374fb0c41b0813cff54549c475" - integrity sha512-13p8IREj9/x/Ye4WI/JpjhoIwuzEgUAtgJZNBJckfzJt1qyh24BdTm6UQNGnyTq9dapQdrqvquZTo3dz1X6Cjw== - dependencies: - flux "^4.0.1" - react-base16-styling "^0.6.0" - react-lifecycles-compat "^3.0.4" - react-textarea-autosize "^8.3.2" - -react-lifecycles-compat@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" - integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== - -react-loadable-ssr-addon-v5-slorber@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz#2cdc91e8a744ffdf9e3556caabeb6e4278689883" - integrity sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A== + "address" "^1.1.2" + "browserslist" "^4.18.1" + "chalk" "^4.1.2" + "cross-spawn" "^7.0.3" + "detect-port-alt" "^1.1.6" + "escape-string-regexp" "^4.0.0" + "filesize" "^8.0.6" + "find-up" "^5.0.0" + "fork-ts-checker-webpack-plugin" "^6.5.0" + "global-modules" "^2.0.0" + "globby" "^11.0.4" + "gzip-size" "^6.0.0" + "immer" "^9.0.7" + "is-root" "^2.1.0" + "loader-utils" "^3.2.0" + "open" "^8.4.0" + "pkg-up" "^3.1.0" + "prompts" "^2.4.2" + "react-error-overlay" "^6.0.10" + "recursive-readdir" "^2.2.2" + "shell-quote" "^1.7.3" + "strip-ansi" "^6.0.1" + "text-table" "^0.2.0" + +"react-dom@*", "react-dom@^16.10.2", "react-dom@^16.8.4 || ^17.0.0", "react-dom@^17.0.0 || ^16.3.0 || ^15.5.4", "react-dom@>= 16.8.0 < 18.0.0": + "integrity" "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==" + "resolved" "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz" + "version" "16.14.0" + dependencies: + "loose-envify" "^1.1.0" + "object-assign" "^4.1.1" + "prop-types" "^15.6.2" + "scheduler" "^0.19.1" + +"react-error-overlay@^6.0.10": + "integrity" "sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA==" + "resolved" "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz" + "version" "6.0.10" + +"react-fast-compare@^3.1.1": + "integrity" "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" + "resolved" "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz" + "version" "3.2.0" + +"react-helmet@^6.1.0": + "integrity" "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==" + "resolved" "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "object-assign" "^4.1.1" + "prop-types" "^15.7.2" + "react-fast-compare" "^3.1.1" + "react-side-effect" "^2.1.0" + +"react-is@^16.13.1", "react-is@^16.6.0", "react-is@^16.7.0": + "integrity" "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "resolved" "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" + "version" "16.13.1" + +"react-json-view@^1.21.3": + "integrity" "sha512-13p8IREj9/x/Ye4WI/JpjhoIwuzEgUAtgJZNBJckfzJt1qyh24BdTm6UQNGnyTq9dapQdrqvquZTo3dz1X6Cjw==" + "resolved" "https://registry.npmjs.org/react-json-view/-/react-json-view-1.21.3.tgz" + "version" "1.21.3" + dependencies: + "flux" "^4.0.1" + "react-base16-styling" "^0.6.0" + "react-lifecycles-compat" "^3.0.4" + "react-textarea-autosize" "^8.3.2" + +"react-lifecycles-compat@^3.0.4": + "integrity" "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + "resolved" "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz" + "version" "3.0.4" + +"react-loadable-ssr-addon-v5-slorber@^1.0.1": + "integrity" "sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==" + "resolved" "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz" + "version" "1.0.1" dependencies: "@babel/runtime" "^7.10.3" -react-popupbox@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/react-popupbox/-/react-popupbox-2.0.8.tgz#9e0c96dcf4ddbbea8d03c28ee6c0634f0d51b791" - integrity sha512-5DT0SxLMIchKgnUkdPwTzvFhtTL5SOQd6n5dzUnnELiimjFE8eaQwL1n58NZUxs9oJsHXF3qQNvcgwEfn8VHrw== +"react-loadable@*", "react-loadable@npm:@docusaurus/react-loadable@5.5.2": + "integrity" "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==" + "resolved" "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz" + "version" "5.5.2" + dependencies: + "@types/react" "*" + "prop-types" "^15.6.2" + +"react-popupbox@^2.0.8": + "integrity" "sha512-5DT0SxLMIchKgnUkdPwTzvFhtTL5SOQd6n5dzUnnELiimjFE8eaQwL1n58NZUxs9oJsHXF3qQNvcgwEfn8VHrw==" + "resolved" "https://registry.npmjs.org/react-popupbox/-/react-popupbox-2.0.8.tgz" + "version" "2.0.8" dependencies: - deepmerge "^1.3.2" - react "^16.3.1" + "deepmerge" "^1.3.2" + "react" "^16.3.1" -react-router-config@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/react-router-config/-/react-router-config-5.1.1.tgz#0f4263d1a80c6b2dc7b9c1902c9526478194a988" - integrity sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg== +"react-router-config@^5.1.1": + "integrity" "sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==" + "resolved" "https://registry.npmjs.org/react-router-config/-/react-router-config-5.1.1.tgz" + "version" "5.1.1" dependencies: "@babel/runtime" "^7.1.2" -react-router-dom@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.0.tgz#da1bfb535a0e89a712a93b97dd76f47ad1f32363" - integrity sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ== +"react-router-dom@^5.2.0": + "integrity" "sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ==" + "resolved" "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.0.tgz" + "version" "5.3.0" dependencies: "@babel/runtime" "^7.12.13" - history "^4.9.0" - loose-envify "^1.3.1" - prop-types "^15.6.2" - react-router "5.2.1" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - -react-router@5.2.1, react-router@^5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.1.tgz#4d2e4e9d5ae9425091845b8dbc6d9d276239774d" - integrity sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ== + "history" "^4.9.0" + "loose-envify" "^1.3.1" + "prop-types" "^15.6.2" + "react-router" "5.2.1" + "tiny-invariant" "^1.0.2" + "tiny-warning" "^1.0.0" + +"react-router@^5.2.0", "react-router@>=5", "react-router@5.2.1": + "integrity" "sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==" + "resolved" "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz" + "version" "5.2.1" dependencies: "@babel/runtime" "^7.12.13" - history "^4.9.0" - hoist-non-react-statics "^3.1.0" - loose-envify "^1.3.1" - mini-create-react-context "^0.4.0" - path-to-regexp "^1.7.0" - prop-types "^15.6.2" - react-is "^16.6.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - -react-side-effect@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-2.1.1.tgz#66c5701c3e7560ab4822a4ee2742dee215d72eb3" - integrity sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ== - -react-textarea-autosize@^8.3.2: - version "8.3.3" - resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz#f70913945369da453fd554c168f6baacd1fa04d8" - integrity sha512-2XlHXK2TDxS6vbQaoPbMOfQ8GK7+irc2fVK6QFIcC8GOnH3zI/v481n+j1L0WaPVvKxwesnY93fEfH++sus2rQ== + "history" "^4.9.0" + "hoist-non-react-statics" "^3.1.0" + "loose-envify" "^1.3.1" + "mini-create-react-context" "^0.4.0" + "path-to-regexp" "^1.7.0" + "prop-types" "^15.6.2" + "react-is" "^16.6.0" + "tiny-invariant" "^1.0.2" + "tiny-warning" "^1.0.0" + +"react-side-effect@^2.1.0": + "integrity" "sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ==" + "resolved" "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.1.tgz" + "version" "2.1.1" + +"react-textarea-autosize@^8.3.2": + "integrity" "sha512-2XlHXK2TDxS6vbQaoPbMOfQ8GK7+irc2fVK6QFIcC8GOnH3zI/v481n+j1L0WaPVvKxwesnY93fEfH++sus2rQ==" + "resolved" "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz" + "version" "8.3.3" dependencies: "@babel/runtime" "^7.10.2" - use-composed-ref "^1.0.0" - use-latest "^1.0.0" - -react@^16.10.2, react@^16.3.1: - version "16.14.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d" - integrity sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - -readable-stream@^2.0.1: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.0.6, readable-stream@^3.1.1: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -reading-time@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/reading-time/-/reading-time-1.5.0.tgz#d2a7f1b6057cb2e169beaf87113cc3411b5bc5bb" - integrity sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg== - -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= - dependencies: - resolve "^1.1.6" - -recursive-readdir@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" - integrity sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg== - dependencies: - minimatch "3.0.4" - -regenerate-unicode-properties@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56" - integrity sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw== - dependencies: - regenerate "^1.4.2" - -regenerate-unicode-properties@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz#54d09c7115e1f53dc2314a974b32c1c344efe326" - integrity sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA== - dependencies: - regenerate "^1.4.2" - -regenerate@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" - integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== - -regenerator-runtime@^0.13.4: - version "0.13.9" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" - integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== - -regenerator-transform@^0.14.2: - version "0.14.5" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" - integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== + "use-composed-ref" "^1.0.0" + "use-latest" "^1.0.0" + +"react@*", "react@^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", "react@^15.0.2 || ^16.0.0 || ^17.0.0", "react@^16.10.2", "react@^16.13.1", "react@^16.13.1 || ^17.0.0", "react@^16.14.0", "react@^16.3.0 || ^17.0.0", "react@^16.3.1", "react@^16.8.0 || ^17.0.0", "react@^16.8.4 || ^17.0.0", "react@^17.0.0 || ^16.3.0 || ^15.5.4", "react@>= 16.8.0 < 18.0.0", "react@>=0.14.9", "react@>=15", "react@>=16.3.0": + "integrity" "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==" + "resolved" "https://registry.npmjs.org/react/-/react-16.14.0.tgz" + "version" "16.14.0" + dependencies: + "loose-envify" "^1.1.0" + "object-assign" "^4.1.1" + "prop-types" "^15.6.2" + +"readable-stream@^2.0.1": + "integrity" "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==" + "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz" + "version" "2.3.7" + dependencies: + "core-util-is" "~1.0.0" + "inherits" "~2.0.3" + "isarray" "~1.0.0" + "process-nextick-args" "~2.0.0" + "safe-buffer" "~5.1.1" + "string_decoder" "~1.1.1" + "util-deprecate" "~1.0.1" + +"readable-stream@^3.0.6", "readable-stream@^3.1.1": + "integrity" "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==" + "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz" + "version" "3.6.0" + dependencies: + "inherits" "^2.0.3" + "string_decoder" "^1.1.1" + "util-deprecate" "^1.0.1" + +"readdirp@~3.6.0": + "integrity" "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==" + "resolved" "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" + "version" "3.6.0" + dependencies: + "picomatch" "^2.2.1" + +"reading-time@^1.5.0": + "integrity" "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==" + "resolved" "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz" + "version" "1.5.0" + +"rechoir@^0.6.2": + "integrity" "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=" + "resolved" "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz" + "version" "0.6.2" + dependencies: + "resolve" "^1.1.6" + +"recursive-readdir@^2.2.2": + "integrity" "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==" + "resolved" "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz" + "version" "2.2.2" + dependencies: + "minimatch" "3.0.4" + +"regenerate-unicode-properties@^10.0.1": + "integrity" "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==" + "resolved" "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz" + "version" "10.0.1" + dependencies: + "regenerate" "^1.4.2" + +"regenerate-unicode-properties@^9.0.0": + "integrity" "sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==" + "resolved" "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz" + "version" "9.0.0" + dependencies: + "regenerate" "^1.4.2" + +"regenerate@^1.4.2": + "integrity" "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + "resolved" "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" + "version" "1.4.2" + +"regenerator-runtime@^0.13.4": + "integrity" "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "resolved" "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz" + "version" "0.13.9" + +"regenerator-transform@^0.14.2": + "integrity" "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==" + "resolved" "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz" + "version" "0.14.5" dependencies: "@babel/runtime" "^7.8.4" -regexp.prototype.flags@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz#b3f4c0059af9e47eca9f3f660e51d81307e72307" - integrity sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -regexpu-core@^4.5.4: - version "4.8.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.8.0.tgz#e5605ba361b67b1718478501327502f4479a98f0" - integrity sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg== - dependencies: - regenerate "^1.4.2" - regenerate-unicode-properties "^9.0.0" - regjsgen "^0.5.2" - regjsparser "^0.7.0" - unicode-match-property-ecmascript "^2.0.0" - unicode-match-property-value-ecmascript "^2.0.0" - -regexpu-core@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.0.1.tgz#c531122a7840de743dcf9c83e923b5560323ced3" - integrity sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw== - dependencies: - regenerate "^1.4.2" - regenerate-unicode-properties "^10.0.1" - regjsgen "^0.6.0" - regjsparser "^0.8.2" - unicode-match-property-ecmascript "^2.0.0" - unicode-match-property-value-ecmascript "^2.0.0" - -registry-auth-token@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" - integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== - dependencies: - rc "^1.2.8" - -registry-url@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" - integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== - dependencies: - rc "^1.2.8" - -regjsgen@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" - integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== - -regjsgen@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.6.0.tgz#83414c5354afd7d6627b16af5f10f41c4e71808d" - integrity sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA== - -regjsparser@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.7.0.tgz#a6b667b54c885e18b52554cb4960ef71187e9968" - integrity sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ== - dependencies: - jsesc "~0.5.0" - -regjsparser@^0.8.2: - version "0.8.4" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.8.4.tgz#8a14285ffcc5de78c5b95d62bbf413b6bc132d5f" - integrity sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA== - dependencies: - jsesc "~0.5.0" - -rehype-parse@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-6.0.2.tgz#aeb3fdd68085f9f796f1d3137ae2b85a98406964" - integrity sha512-0S3CpvpTAgGmnz8kiCyFLGuW5yA4OQhyNTm/nwPopZ7+PI11WnGl1TTWTGv/2hPEe/g2jRLlhVVSsoDH8waRug== - dependencies: - hast-util-from-parse5 "^5.0.0" - parse5 "^5.0.0" - xtend "^4.0.0" - -relateurl@^0.2.7: - version "0.2.7" - resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" - integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= - -remark-admonitions@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/remark-admonitions/-/remark-admonitions-1.2.1.tgz#87caa1a442aa7b4c0cafa04798ed58a342307870" - integrity sha512-Ji6p68VDvD+H1oS95Fdx9Ar5WA2wcDA4kwrrhVU7fGctC6+d3uiMICu7w7/2Xld+lnU7/gi+432+rRbup5S8ow== - dependencies: - rehype-parse "^6.0.2" - unified "^8.4.2" - unist-util-visit "^2.0.1" - -remark-emoji@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/remark-emoji/-/remark-emoji-2.2.0.tgz#1c702090a1525da5b80e15a8f963ef2c8236cac7" - integrity sha512-P3cj9s5ggsUvWw5fS2uzCHJMGuXYRb0NnZqYlNecewXt8QBU9n5vW3DUUKOhepS8F9CwdMx9B8a3i7pqFWAI5w== - dependencies: - emoticon "^3.2.0" - node-emoji "^1.10.0" - unist-util-visit "^2.0.3" - -remark-footnotes@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/remark-footnotes/-/remark-footnotes-2.0.0.tgz#9001c4c2ffebba55695d2dd80ffb8b82f7e6303f" - integrity sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ== - -remark-mdx-remove-exports@^1.6.22: - version "1.6.22" - resolved "https://registry.yarnpkg.com/remark-mdx-remove-exports/-/remark-mdx-remove-exports-1.6.22.tgz#9e34f3d02c9c54b02ca0a1fde946449338d06ecb" - integrity sha512-7g2uiTmTGfz5QyVb+toeX25frbk1Y6yd03RXGPtqx0+DVh86Gb7MkNYbk7H2X27zdZ3CQv1W/JqlFO0Oo8IxVA== - dependencies: - unist-util-remove "2.0.0" - -remark-mdx-remove-imports@^1.6.22: - version "1.6.22" - resolved "https://registry.yarnpkg.com/remark-mdx-remove-imports/-/remark-mdx-remove-imports-1.6.22.tgz#79f711c95359cff437a120d1fbdc1326ec455826" - integrity sha512-lmjAXD8Ltw0TsvBzb45S+Dxx7LTJAtDaMneMAv8LAUIPEyYoKkmGbmVsiF0/pY6mhM1Q16swCmu1TN+ie/vn/A== - dependencies: - unist-util-remove "2.0.0" - -remark-mdx@1.6.22: - version "1.6.22" - resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-1.6.22.tgz#06a8dab07dcfdd57f3373af7f86bd0e992108bbd" - integrity sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ== +"regexp.prototype.flags@^1.2.0": + "integrity" "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==" + "resolved" "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz" + "version" "1.4.1" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.3" + +"regexpu-core@^4.5.4": + "integrity" "sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg==" + "resolved" "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz" + "version" "4.8.0" + dependencies: + "regenerate" "^1.4.2" + "regenerate-unicode-properties" "^9.0.0" + "regjsgen" "^0.5.2" + "regjsparser" "^0.7.0" + "unicode-match-property-ecmascript" "^2.0.0" + "unicode-match-property-value-ecmascript" "^2.0.0" + +"regexpu-core@^5.0.1": + "integrity" "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==" + "resolved" "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "regenerate" "^1.4.2" + "regenerate-unicode-properties" "^10.0.1" + "regjsgen" "^0.6.0" + "regjsparser" "^0.8.2" + "unicode-match-property-ecmascript" "^2.0.0" + "unicode-match-property-value-ecmascript" "^2.0.0" + +"registry-auth-token@^4.0.0": + "integrity" "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==" + "resolved" "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz" + "version" "4.2.1" + dependencies: + "rc" "^1.2.8" + +"registry-url@^5.0.0": + "integrity" "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==" + "resolved" "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "rc" "^1.2.8" + +"regjsgen@^0.5.2": + "integrity" "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==" + "resolved" "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz" + "version" "0.5.2" + +"regjsgen@^0.6.0": + "integrity" "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==" + "resolved" "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz" + "version" "0.6.0" + +"regjsparser@^0.7.0": + "integrity" "sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ==" + "resolved" "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz" + "version" "0.7.0" + dependencies: + "jsesc" "~0.5.0" + +"regjsparser@^0.8.2": + "integrity" "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==" + "resolved" "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz" + "version" "0.8.4" + dependencies: + "jsesc" "~0.5.0" + +"rehype-parse@^6.0.2": + "integrity" "sha512-0S3CpvpTAgGmnz8kiCyFLGuW5yA4OQhyNTm/nwPopZ7+PI11WnGl1TTWTGv/2hPEe/g2jRLlhVVSsoDH8waRug==" + "resolved" "https://registry.npmjs.org/rehype-parse/-/rehype-parse-6.0.2.tgz" + "version" "6.0.2" + dependencies: + "hast-util-from-parse5" "^5.0.0" + "parse5" "^5.0.0" + "xtend" "^4.0.0" + +"relateurl@^0.2.7": + "integrity" "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=" + "resolved" "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz" + "version" "0.2.7" + +"remark-admonitions@^1.2.1": + "integrity" "sha512-Ji6p68VDvD+H1oS95Fdx9Ar5WA2wcDA4kwrrhVU7fGctC6+d3uiMICu7w7/2Xld+lnU7/gi+432+rRbup5S8ow==" + "resolved" "https://registry.npmjs.org/remark-admonitions/-/remark-admonitions-1.2.1.tgz" + "version" "1.2.1" + dependencies: + "rehype-parse" "^6.0.2" + "unified" "^8.4.2" + "unist-util-visit" "^2.0.1" + +"remark-emoji@^2.1.0": + "integrity" "sha512-P3cj9s5ggsUvWw5fS2uzCHJMGuXYRb0NnZqYlNecewXt8QBU9n5vW3DUUKOhepS8F9CwdMx9B8a3i7pqFWAI5w==" + "resolved" "https://registry.npmjs.org/remark-emoji/-/remark-emoji-2.2.0.tgz" + "version" "2.2.0" + dependencies: + "emoticon" "^3.2.0" + "node-emoji" "^1.10.0" + "unist-util-visit" "^2.0.3" + +"remark-footnotes@2.0.0": + "integrity" "sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ==" + "resolved" "https://registry.npmjs.org/remark-footnotes/-/remark-footnotes-2.0.0.tgz" + "version" "2.0.0" + +"remark-mdx-remove-exports@^1.6.22": + "integrity" "sha512-7g2uiTmTGfz5QyVb+toeX25frbk1Y6yd03RXGPtqx0+DVh86Gb7MkNYbk7H2X27zdZ3CQv1W/JqlFO0Oo8IxVA==" + "resolved" "https://registry.npmjs.org/remark-mdx-remove-exports/-/remark-mdx-remove-exports-1.6.22.tgz" + "version" "1.6.22" + dependencies: + "unist-util-remove" "2.0.0" + +"remark-mdx-remove-imports@^1.6.22": + "integrity" "sha512-lmjAXD8Ltw0TsvBzb45S+Dxx7LTJAtDaMneMAv8LAUIPEyYoKkmGbmVsiF0/pY6mhM1Q16swCmu1TN+ie/vn/A==" + "resolved" "https://registry.npmjs.org/remark-mdx-remove-imports/-/remark-mdx-remove-imports-1.6.22.tgz" + "version" "1.6.22" + dependencies: + "unist-util-remove" "2.0.0" + +"remark-mdx@1.6.22": + "integrity" "sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ==" + "resolved" "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz" + "version" "1.6.22" dependencies: "@babel/core" "7.12.9" "@babel/helper-plugin-utils" "7.10.4" "@babel/plugin-proposal-object-rest-spread" "7.12.1" "@babel/plugin-syntax-jsx" "7.12.1" "@mdx-js/util" "1.6.22" - is-alphabetical "1.0.4" - remark-parse "8.0.3" - unified "9.2.0" - -remark-parse@8.0.3: - version "8.0.3" - resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-8.0.3.tgz#9c62aa3b35b79a486454c690472906075f40c7e1" - integrity sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q== - dependencies: - ccount "^1.0.0" - collapse-white-space "^1.0.2" - is-alphabetical "^1.0.0" - is-decimal "^1.0.0" - is-whitespace-character "^1.0.0" - is-word-character "^1.0.0" - markdown-escapes "^1.0.0" - parse-entities "^2.0.0" - repeat-string "^1.5.4" - state-toggle "^1.0.0" - trim "0.0.1" - trim-trailing-lines "^1.0.0" - unherit "^1.0.4" - unist-util-remove-position "^2.0.0" - vfile-location "^3.0.0" - xtend "^4.0.1" - -remark-squeeze-paragraphs@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz#76eb0e085295131c84748c8e43810159c5653ead" - integrity sha512-8qRqmL9F4nuLPIgl92XUuxI3pFxize+F1H0e/W3llTk0UsjJaj01+RrirkMw7P21RKe4X6goQhYRSvNWX+70Rw== - dependencies: - mdast-squeeze-paragraphs "^4.0.0" - -remarkable-admonitions@^0.2.1: - version "0.2.2" - resolved "https://registry.yarnpkg.com/remarkable-admonitions/-/remarkable-admonitions-0.2.2.tgz#8765f9ec66be4f4c651a4e1cfb559dd7f920819c" - integrity sha512-CcMTEcLYmJLXX3IVMk4LyW4oFD2NQxh5FeLzn4k89TAPpyWIeVix/B/g/gDbZAUpCNY9l6heovR5NNIktf8X5A== - -renderkid@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" - integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg== - dependencies: - css-select "^4.1.3" - dom-converter "^0.2.0" - htmlparser2 "^6.1.0" - lodash "^4.17.21" - strip-ansi "^6.0.1" - -repeat-string@^1.5.4: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + "is-alphabetical" "1.0.4" + "remark-parse" "8.0.3" + "unified" "9.2.0" + +"remark-parse@8.0.3": + "integrity" "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==" + "resolved" "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz" + "version" "8.0.3" + dependencies: + "ccount" "^1.0.0" + "collapse-white-space" "^1.0.2" + "is-alphabetical" "^1.0.0" + "is-decimal" "^1.0.0" + "is-whitespace-character" "^1.0.0" + "is-word-character" "^1.0.0" + "markdown-escapes" "^1.0.0" + "parse-entities" "^2.0.0" + "repeat-string" "^1.5.4" + "state-toggle" "^1.0.0" + "trim" "0.0.1" + "trim-trailing-lines" "^1.0.0" + "unherit" "^1.0.4" + "unist-util-remove-position" "^2.0.0" + "vfile-location" "^3.0.0" + "xtend" "^4.0.1" + +"remark-squeeze-paragraphs@4.0.0": + "integrity" "sha512-8qRqmL9F4nuLPIgl92XUuxI3pFxize+F1H0e/W3llTk0UsjJaj01+RrirkMw7P21RKe4X6goQhYRSvNWX+70Rw==" + "resolved" "https://registry.npmjs.org/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "mdast-squeeze-paragraphs" "^4.0.0" + +"remarkable-admonitions@^0.2.1": + "integrity" "sha512-CcMTEcLYmJLXX3IVMk4LyW4oFD2NQxh5FeLzn4k89TAPpyWIeVix/B/g/gDbZAUpCNY9l6heovR5NNIktf8X5A==" + "resolved" "https://registry.npmjs.org/remarkable-admonitions/-/remarkable-admonitions-0.2.2.tgz" + "version" "0.2.2" + +"renderkid@^3.0.0": + "integrity" "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==" + "resolved" "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "css-select" "^4.1.3" + "dom-converter" "^0.2.0" + "htmlparser2" "^6.1.0" + "lodash" "^4.17.21" + "strip-ansi" "^6.0.1" + +"repeat-string@^1.5.4": + "integrity" "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + "resolved" "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" + "version" "1.6.1" + +"require-from-string@^2.0.2": + "integrity" "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + "resolved" "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" + "version" "2.0.2" "require-like@>= 0.1.1": - version "0.1.2" - resolved "https://registry.yarnpkg.com/require-like/-/require-like-0.1.2.tgz#ad6f30c13becd797010c468afa775c0c0a6b47fa" - integrity sha1-rW8wwTvs15cBDEaK+ndcDAprR/o= - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-pathname@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" - integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== - -resolve@^1.1.6, resolve@^1.14.2, resolve@^1.3.2: - version "1.22.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" - integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== - dependencies: - is-core-module "^2.8.1" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -responselike@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= - dependencies: - lowercase-keys "^1.0.0" - -retry@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" - integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -rtl-detect@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/rtl-detect/-/rtl-detect-1.0.4.tgz#40ae0ea7302a150b96bc75af7d749607392ecac6" - integrity sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ== - -rtlcss@^3.3.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-3.5.0.tgz#c9eb91269827a102bac7ae3115dd5d049de636c3" - integrity sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A== - dependencies: - find-up "^5.0.0" - picocolors "^1.0.0" - postcss "^8.3.11" - strip-json-comments "^3.1.1" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -rxjs@^7.5.4: - version "7.5.4" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.4.tgz#3d6bd407e6b7ce9a123e76b1e770dc5761aa368d" - integrity sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ== - dependencies: - tslib "^2.1.0" - -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + "integrity" "sha1-rW8wwTvs15cBDEaK+ndcDAprR/o=" + "resolved" "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz" + "version" "0.1.2" + +"requires-port@^1.0.0": + "integrity" "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + "resolved" "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" + "version" "1.0.0" + +"resolve-from@^4.0.0": + "integrity" "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + "resolved" "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" + "version" "4.0.0" + +"resolve-pathname@^3.0.0": + "integrity" "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + "resolved" "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz" + "version" "3.0.0" + +"resolve@^1.1.6", "resolve@^1.14.2", "resolve@^1.3.2": + "integrity" "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==" + "resolved" "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz" + "version" "1.22.0" + dependencies: + "is-core-module" "^2.8.1" + "path-parse" "^1.0.7" + "supports-preserve-symlinks-flag" "^1.0.0" + +"responselike@^1.0.2": + "integrity" "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=" + "resolved" "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "lowercase-keys" "^1.0.0" + +"retry@^0.13.1": + "integrity" "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" + "resolved" "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz" + "version" "0.13.1" + +"reusify@^1.0.4": + "integrity" "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + "resolved" "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" + "version" "1.0.4" + +"rimraf@^3.0.2": + "integrity" "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==" + "resolved" "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "glob" "^7.1.3" + +"rtl-detect@^1.0.4": + "integrity" "sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ==" + "resolved" "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.0.4.tgz" + "version" "1.0.4" + +"rtlcss@^3.3.0": + "integrity" "sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A==" + "resolved" "https://registry.npmjs.org/rtlcss/-/rtlcss-3.5.0.tgz" + "version" "3.5.0" + dependencies: + "find-up" "^5.0.0" + "picocolors" "^1.0.0" + "postcss" "^8.3.11" + "strip-json-comments" "^3.1.1" + +"run-parallel@^1.1.9": + "integrity" "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==" + "resolved" "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "queue-microtask" "^1.2.2" + +"rxjs@^7.5.4": + "integrity" "sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ==" + "resolved" "https://registry.npmjs.org/rxjs/-/rxjs-7.5.4.tgz" + "version" "7.5.4" + dependencies: + "tslib" "^2.1.0" + +"safe-buffer@^5.0.1", "safe-buffer@^5.1.0", "safe-buffer@>=5.1.0", "safe-buffer@~5.2.0", "safe-buffer@5.2.1": + "integrity" "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + "version" "5.2.1" + +"safe-buffer@~5.1.0", "safe-buffer@~5.1.1": + "integrity" "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + "version" "5.1.2" + +"safe-buffer@5.1.2": + "integrity" "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + "version" "5.1.2" "safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + "integrity" "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "resolved" "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" + "version" "2.1.2" -sax@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== +"sax@^1.2.4": + "integrity" "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + "resolved" "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz" + "version" "1.2.4" -scheduler@^0.19.1: - version "0.19.1" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" - integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA== +"scheduler@^0.19.1": + "integrity" "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==" + "resolved" "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz" + "version" "0.19.1" dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" + "loose-envify" "^1.1.0" + "object-assign" "^4.1.1" -schema-utils@2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" - integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== - dependencies: - "@types/json-schema" "^7.0.4" - ajv "^6.12.2" - ajv-keywords "^3.4.1" - -schema-utils@^2.6.5: - version "2.7.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" - integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== +"schema-utils@^2.6.5": + "integrity" "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==" + "resolved" "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz" + "version" "2.7.1" dependencies: "@types/json-schema" "^7.0.5" - ajv "^6.12.4" - ajv-keywords "^3.5.2" + "ajv" "^6.12.4" + "ajv-keywords" "^3.5.2" -schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" - integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== +"schema-utils@^3.0.0", "schema-utils@^3.1.0", "schema-utils@^3.1.1": + "integrity" "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==" + "resolved" "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz" + "version" "3.1.1" dependencies: "@types/json-schema" "^7.0.8" - ajv "^6.12.5" - ajv-keywords "^3.5.2" + "ajv" "^6.12.5" + "ajv-keywords" "^3.5.2" -schema-utils@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" - integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== +"schema-utils@^4.0.0": + "integrity" "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==" + "resolved" "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz" + "version" "4.0.0" dependencies: "@types/json-schema" "^7.0.9" - ajv "^8.8.0" - ajv-formats "^2.1.1" - ajv-keywords "^5.0.0" - -section-matter@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167" - integrity sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA== - dependencies: - extend-shallow "^2.0.1" - kind-of "^6.0.0" - -select-hose@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" - integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= - -selfsigned@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.0.0.tgz#e927cd5377cbb0a1075302cff8df1042cc2bce5b" - integrity sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ== - dependencies: - node-forge "^1.2.0" - -semver-diff@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" - integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg== - dependencies: - semver "^6.3.0" - -semver@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" - integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== - -semver@^5.4.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: - version "7.3.5" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== - dependencies: - lru-cache "^6.0.0" - -send@0.17.2: - version "0.17.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820" - integrity sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "1.8.1" - mime "1.6.0" - ms "2.1.3" - on-finished "~2.3.0" - range-parser "~1.2.1" - statuses "~1.5.0" - -serialize-javascript@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== - dependencies: - randombytes "^2.1.0" - -serve-handler@^6.1.3: - version "6.1.3" - resolved "https://registry.yarnpkg.com/serve-handler/-/serve-handler-6.1.3.tgz#1bf8c5ae138712af55c758477533b9117f6435e8" - integrity sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w== - dependencies: - bytes "3.0.0" - content-disposition "0.5.2" - fast-url-parser "1.1.3" - mime-types "2.1.18" - minimatch "3.0.4" - path-is-inside "1.0.2" - path-to-regexp "2.2.1" - range-parser "1.2.0" - -serve-index@^1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" - integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= - dependencies: - accepts "~1.3.4" - batch "0.6.1" - debug "2.6.9" - escape-html "~1.0.3" - http-errors "~1.6.2" - mime-types "~2.1.17" - parseurl "~1.3.2" - -serve-static@1.14.2: - version "1.14.2" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa" - integrity sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.2" - -setimmediate@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= - -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -shallow-clone@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" - integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== - dependencies: - kind-of "^6.0.2" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -shell-quote@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" - integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== - -shelljs@^0.8.4: - version "0.8.5" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" - integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - -signal-exit@^3.0.2, signal-exit@^3.0.3: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -sirv@^1.0.7: - version "1.0.19" - resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49" - integrity sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ== + "ajv" "^8.8.0" + "ajv-formats" "^2.1.1" + "ajv-keywords" "^5.0.0" + +"schema-utils@2.7.0": + "integrity" "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==" + "resolved" "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz" + "version" "2.7.0" + dependencies: + "@types/json-schema" "^7.0.4" + "ajv" "^6.12.2" + "ajv-keywords" "^3.4.1" + +"section-matter@^1.0.0": + "integrity" "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==" + "resolved" "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "extend-shallow" "^2.0.1" + "kind-of" "^6.0.0" + +"select-hose@^2.0.0": + "integrity" "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" + "resolved" "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" + "version" "2.0.0" + +"selfsigned@^2.0.0": + "integrity" "sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ==" + "resolved" "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "node-forge" "^1.2.0" + +"semver-diff@^3.1.1": + "integrity" "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==" + "resolved" "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz" + "version" "3.1.1" + dependencies: + "semver" "^6.3.0" + +"semver@^5.4.1": + "integrity" "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "resolved" "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" + "version" "5.7.1" + +"semver@^6.0.0", "semver@^6.1.1", "semver@^6.1.2", "semver@^6.2.0", "semver@^6.3.0": + "integrity" "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "resolved" "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" + "version" "6.3.0" + +"semver@^7.3.2": + "integrity" "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==" + "resolved" "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" + "version" "7.3.5" + dependencies: + "lru-cache" "^6.0.0" + +"semver@^7.3.4": + "integrity" "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==" + "resolved" "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" + "version" "7.3.5" + dependencies: + "lru-cache" "^6.0.0" + +"semver@^7.3.5": + "integrity" "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==" + "resolved" "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" + "version" "7.3.5" + dependencies: + "lru-cache" "^6.0.0" + +"semver@7.0.0": + "integrity" "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" + "resolved" "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz" + "version" "7.0.0" + +"send@0.17.2": + "integrity" "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==" + "resolved" "https://registry.npmjs.org/send/-/send-0.17.2.tgz" + "version" "0.17.2" + dependencies: + "debug" "2.6.9" + "depd" "~1.1.2" + "destroy" "~1.0.4" + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "etag" "~1.8.1" + "fresh" "0.5.2" + "http-errors" "1.8.1" + "mime" "1.6.0" + "ms" "2.1.3" + "on-finished" "~2.3.0" + "range-parser" "~1.2.1" + "statuses" "~1.5.0" + +"serialize-javascript@^6.0.0": + "integrity" "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==" + "resolved" "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "randombytes" "^2.1.0" + +"serve-handler@^6.1.3": + "integrity" "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==" + "resolved" "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz" + "version" "6.1.3" + dependencies: + "bytes" "3.0.0" + "content-disposition" "0.5.2" + "fast-url-parser" "1.1.3" + "mime-types" "2.1.18" + "minimatch" "3.0.4" + "path-is-inside" "1.0.2" + "path-to-regexp" "2.2.1" + "range-parser" "1.2.0" + +"serve-index@^1.9.1": + "integrity" "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=" + "resolved" "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz" + "version" "1.9.1" + dependencies: + "accepts" "~1.3.4" + "batch" "0.6.1" + "debug" "2.6.9" + "escape-html" "~1.0.3" + "http-errors" "~1.6.2" + "mime-types" "~2.1.17" + "parseurl" "~1.3.2" + +"serve-static@1.14.2": + "integrity" "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==" + "resolved" "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz" + "version" "1.14.2" + dependencies: + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "parseurl" "~1.3.3" + "send" "0.17.2" + +"setimmediate@^1.0.5": + "integrity" "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + "resolved" "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" + "version" "1.0.5" + +"setprototypeof@1.1.0": + "integrity" "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + "resolved" "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz" + "version" "1.1.0" + +"setprototypeof@1.2.0": + "integrity" "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "resolved" "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" + "version" "1.2.0" + +"shallow-clone@^3.0.0": + "integrity" "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==" + "resolved" "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "kind-of" "^6.0.2" + +"shebang-command@^2.0.0": + "integrity" "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==" + "resolved" "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "shebang-regex" "^3.0.0" + +"shebang-regex@^3.0.0": + "integrity" "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + "resolved" "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" + "version" "3.0.0" + +"shell-quote@^1.7.3": + "integrity" "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==" + "resolved" "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz" + "version" "1.7.3" + +"shelljs@^0.8.4": + "integrity" "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==" + "resolved" "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz" + "version" "0.8.5" + dependencies: + "glob" "^7.0.0" + "interpret" "^1.0.0" + "rechoir" "^0.6.2" + +"signal-exit@^3.0.2", "signal-exit@^3.0.3": + "integrity" "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + "resolved" "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" + "version" "3.0.7" + +"sirv@^1.0.7": + "integrity" "sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==" + "resolved" "https://registry.npmjs.org/sirv/-/sirv-1.0.19.tgz" + "version" "1.0.19" dependencies: "@polka/url" "^1.0.0-next.20" - mrmime "^1.0.0" - totalist "^1.0.0" + "mrmime" "^1.0.0" + "totalist" "^1.0.0" -sisteransi@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== +"sisteransi@^1.0.5": + "integrity" "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + "resolved" "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" + "version" "1.0.5" -sitemap@^7.0.0: - version "7.1.1" - resolved "https://registry.yarnpkg.com/sitemap/-/sitemap-7.1.1.tgz#eeed9ad6d95499161a3eadc60f8c6dce4bea2bef" - integrity sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg== +"sitemap@^7.0.0": + "integrity" "sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg==" + "resolved" "https://registry.npmjs.org/sitemap/-/sitemap-7.1.1.tgz" + "version" "7.1.1" dependencies: "@types/node" "^17.0.5" "@types/sax" "^1.2.1" - arg "^5.0.0" - sax "^1.2.4" - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slash@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" - integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== - -sockjs@^0.3.21: - version "0.3.24" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" - integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== - dependencies: - faye-websocket "^0.11.3" - uuid "^8.3.2" - websocket-driver "^0.7.4" - -sort-css-media-queries@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/sort-css-media-queries/-/sort-css-media-queries-2.0.4.tgz#b2badfa519cb4a938acbc6d3aaa913d4949dc908" - integrity sha512-PAIsEK/XupCQwitjv7XxoMvYhT7EAfyzI3hsy/MyDgTvc+Ft55ctdkctJLOy6cQejaIC+zjpUL4djFVm2ivOOw== - -source-list-map@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== - -source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== - -source-map-support@~0.5.20: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.5.0: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -sourcemap-codec@^1.4.4: - version "1.4.8" - resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" - integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== - -space-separated-tokens@^1.0.0: - version "1.1.5" - resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" - integrity sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA== - -spdy-transport@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" - integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== - dependencies: - debug "^4.1.0" - detect-node "^2.0.4" - hpack.js "^2.1.6" - obuf "^1.1.2" - readable-stream "^3.0.6" - wbuf "^1.7.3" - -spdy@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" - integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== - dependencies: - debug "^4.1.0" - handle-thing "^2.0.0" - http-deceiver "^1.2.7" - select-hose "^2.0.0" - spdy-transport "^3.0.0" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -stable@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== - -state-toggle@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe" - integrity sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ== - -"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -std-env@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.0.1.tgz#bc4cbc0e438610197e34c2d79c3df30b491f5182" - integrity sha512-mC1Ps9l77/97qeOZc+HrOL7TIaOboHqMZ24dGVQrlxFcpPpfCHpH+qfUT7Dz+6mlG8+JPA1KfBQo19iC/+Ngcw== - -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.2: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -stringify-object@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" - integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== - dependencies: - get-own-enumerable-property-symbols "^3.0.0" - is-obj "^1.0.1" - is-regexp "^1.0.0" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" - integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== - dependencies: - ansi-regex "^6.0.1" - -strip-bom-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" - integrity sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI= - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -style-to-object@0.3.0, style-to-object@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.3.0.tgz#b1b790d205991cc783801967214979ee19a76e46" - integrity sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA== - dependencies: - inline-style-parser "0.1.1" - -stylehacks@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.0.3.tgz#2ef3de567bfa2be716d29a93bf3d208c133e8d04" - integrity sha512-ENcUdpf4yO0E1rubu8rkxI+JGQk4CgjchynZ4bDBJDfqdy+uhTRSWb8/F3Jtu+Bw5MW45Po3/aQGeIyyxgQtxg== - dependencies: - browserslist "^4.16.6" - postcss-selector-parser "^6.0.4" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" + "arg" "^5.0.0" + "sax" "^1.2.4" + +"slash@^3.0.0": + "integrity" "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + "resolved" "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" + "version" "3.0.0" + +"slash@^4.0.0": + "integrity" "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==" + "resolved" "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz" + "version" "4.0.0" + +"sockjs@^0.3.21": + "integrity" "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==" + "resolved" "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz" + "version" "0.3.24" + dependencies: + "faye-websocket" "^0.11.3" + "uuid" "^8.3.2" + "websocket-driver" "^0.7.4" + +"sort-css-media-queries@2.0.4": + "integrity" "sha512-PAIsEK/XupCQwitjv7XxoMvYhT7EAfyzI3hsy/MyDgTvc+Ft55ctdkctJLOy6cQejaIC+zjpUL4djFVm2ivOOw==" + "resolved" "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.0.4.tgz" + "version" "2.0.4" + +"source-list-map@^2.0.0": + "integrity" "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + "resolved" "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz" + "version" "2.0.1" + +"source-map-js@^1.0.2": + "integrity" "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" + "resolved" "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz" + "version" "1.0.2" + +"source-map-support@~0.5.20": + "integrity" "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==" + "resolved" "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" + "version" "0.5.21" + dependencies: + "buffer-from" "^1.0.0" + "source-map" "^0.6.0" + +"source-map@^0.5.0": + "integrity" "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "resolved" "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" + "version" "0.5.7" + +"source-map@^0.6.0", "source-map@^0.6.1", "source-map@~0.6.0", "source-map@~0.6.1": + "integrity" "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "resolved" "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + "version" "0.6.1" + +"sourcemap-codec@^1.4.4": + "integrity" "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + "resolved" "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz" + "version" "1.4.8" + +"space-separated-tokens@^1.0.0": + "integrity" "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==" + "resolved" "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz" + "version" "1.1.5" + +"spdy-transport@^3.0.0": + "integrity" "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==" + "resolved" "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "debug" "^4.1.0" + "detect-node" "^2.0.4" + "hpack.js" "^2.1.6" + "obuf" "^1.1.2" + "readable-stream" "^3.0.6" + "wbuf" "^1.7.3" + +"spdy@^4.0.2": + "integrity" "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==" + "resolved" "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz" + "version" "4.0.2" + dependencies: + "debug" "^4.1.0" + "handle-thing" "^2.0.0" + "http-deceiver" "^1.2.7" + "select-hose" "^2.0.0" + "spdy-transport" "^3.0.0" + +"sprintf-js@~1.0.2": + "integrity" "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "resolved" "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" + "version" "1.0.3" + +"stable@^0.1.8": + "integrity" "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" + "resolved" "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz" + "version" "0.1.8" + +"state-toggle@^1.0.0": + "integrity" "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==" + "resolved" "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz" + "version" "1.0.3" + +"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", "statuses@~1.5.0": + "integrity" "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "resolved" "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" + "version" "1.5.0" + +"std-env@^3.0.1": + "integrity" "sha512-mC1Ps9l77/97qeOZc+HrOL7TIaOboHqMZ24dGVQrlxFcpPpfCHpH+qfUT7Dz+6mlG8+JPA1KfBQo19iC/+Ngcw==" + "resolved" "https://registry.npmjs.org/std-env/-/std-env-3.0.1.tgz" + "version" "3.0.1" + +"string_decoder@^1.1.1": + "integrity" "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==" + "resolved" "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + "version" "1.3.0" + dependencies: + "safe-buffer" "~5.2.0" + +"string_decoder@~1.1.1": + "integrity" "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==" + "resolved" "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "safe-buffer" "~5.1.0" + +"string-width@^4.0.0", "string-width@^4.1.0", "string-width@^4.2.2": + "integrity" "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==" + "resolved" "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + "version" "4.2.3" + dependencies: + "emoji-regex" "^8.0.0" + "is-fullwidth-code-point" "^3.0.0" + "strip-ansi" "^6.0.1" + +"stringify-object@^3.3.0": + "integrity" "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==" + "resolved" "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz" + "version" "3.3.0" + dependencies: + "get-own-enumerable-property-symbols" "^3.0.0" + "is-obj" "^1.0.1" + "is-regexp" "^1.0.0" + +"strip-ansi@^6.0.0", "strip-ansi@^6.0.1": + "integrity" "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==" + "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "ansi-regex" "^5.0.1" + +"strip-ansi@^7.0.0": + "integrity" "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==" + "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz" + "version" "7.0.1" + dependencies: + "ansi-regex" "^6.0.1" + +"strip-bom-string@^1.0.0": + "integrity" "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=" + "resolved" "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz" + "version" "1.0.0" + +"strip-final-newline@^2.0.0": + "integrity" "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" + "resolved" "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz" + "version" "2.0.0" + +"strip-json-comments@^3.1.1": + "integrity" "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" + "resolved" "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + "version" "3.1.1" + +"strip-json-comments@~2.0.1": + "integrity" "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + "resolved" "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" + "version" "2.0.1" + +"style-to-object@^0.3.0", "style-to-object@0.3.0": + "integrity" "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==" + "resolved" "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz" + "version" "0.3.0" + dependencies: + "inline-style-parser" "0.1.1" + +"stylehacks@^5.0.3": + "integrity" "sha512-ENcUdpf4yO0E1rubu8rkxI+JGQk4CgjchynZ4bDBJDfqdy+uhTRSWb8/F3Jtu+Bw5MW45Po3/aQGeIyyxgQtxg==" + "resolved" "https://registry.npmjs.org/stylehacks/-/stylehacks-5.0.3.tgz" + "version" "5.0.3" + dependencies: + "browserslist" "^4.16.6" + "postcss-selector-parser" "^6.0.4" + +"supports-color@^5.3.0": + "integrity" "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + "version" "5.5.0" + dependencies: + "has-flag" "^3.0.0" -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== +"supports-color@^7.1.0": + "integrity" "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + "version" "7.2.0" dependencies: - has-flag "^4.0.0" + "has-flag" "^4.0.0" -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== +"supports-color@^8.0.0": + "integrity" "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" + "version" "8.1.1" dependencies: - has-flag "^4.0.0" + "has-flag" "^4.0.0" -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +"supports-preserve-symlinks-flag@^1.0.0": + "integrity" "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + "resolved" "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" + "version" "1.0.0" -svg-parser@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" - integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== +"svg-parser@^2.0.2": + "integrity" "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + "resolved" "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz" + "version" "2.0.4" -svgo@^2.5.0, svgo@^2.7.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" - integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg== +"svgo@^2.5.0", "svgo@^2.7.0": + "integrity" "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==" + "resolved" "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz" + "version" "2.8.0" dependencies: "@trysound/sax" "0.2.0" - commander "^7.2.0" - css-select "^4.1.3" - css-tree "^1.1.3" - csso "^4.2.0" - picocolors "^1.0.0" - stable "^0.1.8" - -tapable@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" - integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== - -tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== - -terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.2.4: - version "5.3.1" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz#0320dcc270ad5372c1e8993fabbd927929773e54" - integrity sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g== - dependencies: - jest-worker "^27.4.5" - schema-utils "^3.1.1" - serialize-javascript "^6.0.0" - source-map "^0.6.1" - terser "^5.7.2" - -terser@^5.10.0, terser@^5.7.2: - version "5.14.2" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.14.2.tgz#9ac9f22b06994d736174f4091aa368db896f1c10" - integrity sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA== + "commander" "^7.2.0" + "css-select" "^4.1.3" + "css-tree" "^1.1.3" + "csso" "^4.2.0" + "picocolors" "^1.0.0" + "stable" "^0.1.8" + +"tapable@^1.0.0": + "integrity" "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" + "resolved" "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz" + "version" "1.1.3" + +"tapable@^2.0.0", "tapable@^2.1.1", "tapable@^2.2.0": + "integrity" "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" + "resolved" "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz" + "version" "2.2.1" + +"terser-webpack-plugin@^5.1.3", "terser-webpack-plugin@^5.2.4": + "integrity" "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==" + "resolved" "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz" + "version" "5.3.1" + dependencies: + "jest-worker" "^27.4.5" + "schema-utils" "^3.1.1" + "serialize-javascript" "^6.0.0" + "source-map" "^0.6.1" + "terser" "^5.7.2" + +"terser@^5.10.0", "terser@^5.7.2": + "integrity" "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==" + "resolved" "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz" + "version" "5.14.2" dependencies: "@jridgewell/source-map" "^0.3.2" - acorn "^8.5.0" - commander "^2.20.0" - source-map-support "~0.5.20" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - -thunky@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" - integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== - -timsort@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" - integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= - -tiny-invariant@^1.0.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.2.0.tgz#a1141f86b672a9148c72e978a19a73b9b94a15a9" - integrity sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg== - -tiny-warning@^1.0.0, tiny-warning@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" - integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -totalist@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" - integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= - -trim-trailing-lines@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz#bd4abbec7cc880462f10b2c8b5ce1d8d1ec7c2c0" - integrity sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ== - -trim@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" - integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= - -trough@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" - integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== - -tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - -ua-parser-js@^0.7.30: - version "0.7.33" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.33.tgz#1d04acb4ccef9293df6f70f2c3d22f3030d8b532" - integrity sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw== - -unherit@^1.0.4: - version "1.1.3" - resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.3.tgz#6c9b503f2b41b262330c80e91c8614abdaa69c22" - integrity sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ== - dependencies: - inherits "^2.0.0" - xtend "^4.0.0" - -unicode-canonical-property-names-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" - integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== - -unicode-match-property-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" - integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== - dependencies: - unicode-canonical-property-names-ecmascript "^2.0.0" - unicode-property-aliases-ecmascript "^2.0.0" - -unicode-match-property-value-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz#1a01aa57247c14c568b89775a54938788189a714" - integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw== - -unicode-property-aliases-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8" - integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ== - -unified@9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.0.tgz#67a62c627c40589edebbf60f53edfd4d822027f8" - integrity sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg== - dependencies: - bail "^1.0.0" - extend "^3.0.0" - is-buffer "^2.0.0" - is-plain-obj "^2.0.0" - trough "^1.0.0" - vfile "^4.0.0" - -unified@^8.4.2: - version "8.4.2" - resolved "https://registry.yarnpkg.com/unified/-/unified-8.4.2.tgz#13ad58b4a437faa2751a4a4c6a16f680c500fff1" - integrity sha512-JCrmN13jI4+h9UAyKEoGcDZV+i1E7BLFuG7OsaDvTXI5P0qhHX+vZO/kOhz9jn8HGENDKbwSeB0nVOg4gVStGA== - dependencies: - bail "^1.0.0" - extend "^3.0.0" - is-plain-obj "^2.0.0" - trough "^1.0.0" - vfile "^4.0.0" - -unique-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" - integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== - dependencies: - crypto-random-string "^2.0.0" - -unist-builder@2.0.3, unist-builder@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-2.0.3.tgz#77648711b5d86af0942f334397a33c5e91516436" - integrity sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw== - -unist-util-generated@^1.0.0: - version "1.1.6" - resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.6.tgz#5ab51f689e2992a472beb1b35f2ce7ff2f324d4b" - integrity sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg== - -unist-util-is@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797" - integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg== - -unist-util-position@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-3.1.0.tgz#1c42ee6301f8d52f47d14f62bbdb796571fa2d47" - integrity sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA== - -unist-util-remove-position@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz#5d19ca79fdba712301999b2b73553ca8f3b352cc" - integrity sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA== - dependencies: - unist-util-visit "^2.0.0" - -unist-util-remove@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unist-util-remove/-/unist-util-remove-2.0.0.tgz#32c2ad5578802f2ca62ab808173d505b2c898488" - integrity sha512-HwwWyNHKkeg/eXRnE11IpzY8JT55JNM1YCwwU9YNCnfzk6s8GhPXrVBBZWiwLeATJbI7euvoGSzcy9M29UeW3g== - dependencies: - unist-util-is "^4.0.0" - -unist-util-remove@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/unist-util-remove/-/unist-util-remove-2.1.0.tgz#b0b4738aa7ee445c402fda9328d604a02d010588" - integrity sha512-J8NYPyBm4baYLdCbjmf1bhPu45Cr1MWTm77qd9istEkzWpnN6O9tMsEbB2JhNnBCqGENRqEWomQ+He6au0B27Q== - dependencies: - unist-util-is "^4.0.0" - -unist-util-stringify-position@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da" - integrity sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g== + "acorn" "^8.5.0" + "commander" "^2.20.0" + "source-map-support" "~0.5.20" + +"text-table@^0.2.0": + "integrity" "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + "resolved" "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" + "version" "0.2.0" + +"thunky@^1.0.2": + "integrity" "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + "resolved" "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz" + "version" "1.1.0" + +"timsort@^0.3.0": + "integrity" "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" + "resolved" "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz" + "version" "0.3.0" + +"tiny-invariant@^1.0.2": + "integrity" "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==" + "resolved" "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz" + "version" "1.2.0" + +"tiny-warning@^1.0.0", "tiny-warning@^1.0.3": + "integrity" "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + "resolved" "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz" + "version" "1.0.3" + +"to-fast-properties@^2.0.0": + "integrity" "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + "resolved" "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" + "version" "2.0.0" + +"to-readable-stream@^1.0.0": + "integrity" "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" + "resolved" "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz" + "version" "1.0.0" + +"to-regex-range@^5.0.1": + "integrity" "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==" + "resolved" "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "is-number" "^7.0.0" + +"toidentifier@1.0.1": + "integrity" "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + "resolved" "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" + "version" "1.0.1" + +"totalist@^1.0.0": + "integrity" "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==" + "resolved" "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz" + "version" "1.1.0" + +"tr46@~0.0.3": + "integrity" "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + "resolved" "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" + "version" "0.0.3" + +"trim-trailing-lines@^1.0.0": + "integrity" "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==" + "resolved" "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz" + "version" "1.1.4" + +"trim@0.0.1": + "integrity" "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + "resolved" "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz" + "version" "0.0.1" + +"trough@^1.0.0": + "integrity" "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==" + "resolved" "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz" + "version" "1.0.5" + +"tslib@^2.0.3", "tslib@^2.1.0", "tslib@^2.2.0", "tslib@^2.3.1": + "integrity" "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "resolved" "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz" + "version" "2.3.1" + +"type-fest@^0.20.2": + "integrity" "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + "resolved" "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" + "version" "0.20.2" + +"type-is@~1.6.18": + "integrity" "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==" + "resolved" "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" + "version" "1.6.18" + dependencies: + "media-typer" "0.3.0" + "mime-types" "~2.1.24" + +"typedarray-to-buffer@^3.1.5": + "integrity" "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==" + "resolved" "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz" + "version" "3.1.5" + dependencies: + "is-typedarray" "^1.0.0" + +"typescript@>= 2.7": + "integrity" "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==" + "resolved" "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz" + "version" "4.9.5" + +"ua-parser-js@^0.7.30": + "integrity" "sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw==" + "resolved" "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.33.tgz" + "version" "0.7.33" + +"unherit@^1.0.4": + "integrity" "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==" + "resolved" "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz" + "version" "1.1.3" + dependencies: + "inherits" "^2.0.0" + "xtend" "^4.0.0" + +"unicode-canonical-property-names-ecmascript@^2.0.0": + "integrity" "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==" + "resolved" "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz" + "version" "2.0.0" + +"unicode-match-property-ecmascript@^2.0.0": + "integrity" "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==" + "resolved" "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "unicode-canonical-property-names-ecmascript" "^2.0.0" + "unicode-property-aliases-ecmascript" "^2.0.0" + +"unicode-match-property-value-ecmascript@^2.0.0": + "integrity" "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==" + "resolved" "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz" + "version" "2.0.0" + +"unicode-property-aliases-ecmascript@^2.0.0": + "integrity" "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==" + "resolved" "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz" + "version" "2.0.0" + +"unified@^8.4.2": + "integrity" "sha512-JCrmN13jI4+h9UAyKEoGcDZV+i1E7BLFuG7OsaDvTXI5P0qhHX+vZO/kOhz9jn8HGENDKbwSeB0nVOg4gVStGA==" + "resolved" "https://registry.npmjs.org/unified/-/unified-8.4.2.tgz" + "version" "8.4.2" + dependencies: + "bail" "^1.0.0" + "extend" "^3.0.0" + "is-plain-obj" "^2.0.0" + "trough" "^1.0.0" + "vfile" "^4.0.0" + +"unified@9.2.0": + "integrity" "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==" + "resolved" "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz" + "version" "9.2.0" + dependencies: + "bail" "^1.0.0" + "extend" "^3.0.0" + "is-buffer" "^2.0.0" + "is-plain-obj" "^2.0.0" + "trough" "^1.0.0" + "vfile" "^4.0.0" + +"unique-string@^2.0.0": + "integrity" "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==" + "resolved" "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "crypto-random-string" "^2.0.0" + +"unist-builder@^2.0.0", "unist-builder@2.0.3": + "integrity" "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==" + "resolved" "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz" + "version" "2.0.3" + +"unist-util-generated@^1.0.0": + "integrity" "sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==" + "resolved" "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz" + "version" "1.1.6" + +"unist-util-is@^4.0.0": + "integrity" "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==" + "resolved" "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz" + "version" "4.1.0" + +"unist-util-position@^3.0.0": + "integrity" "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA==" + "resolved" "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz" + "version" "3.1.0" + +"unist-util-remove-position@^2.0.0": + "integrity" "sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA==" + "resolved" "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "unist-util-visit" "^2.0.0" + +"unist-util-remove@^2.0.0": + "integrity" "sha512-J8NYPyBm4baYLdCbjmf1bhPu45Cr1MWTm77qd9istEkzWpnN6O9tMsEbB2JhNnBCqGENRqEWomQ+He6au0B27Q==" + "resolved" "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "unist-util-is" "^4.0.0" + +"unist-util-remove@2.0.0": + "integrity" "sha512-HwwWyNHKkeg/eXRnE11IpzY8JT55JNM1YCwwU9YNCnfzk6s8GhPXrVBBZWiwLeATJbI7euvoGSzcy9M29UeW3g==" + "resolved" "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "unist-util-is" "^4.0.0" + +"unist-util-stringify-position@^2.0.0": + "integrity" "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==" + "resolved" "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz" + "version" "2.0.3" dependencies: "@types/unist" "^2.0.2" -unist-util-visit-parents@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz#65a6ce698f78a6b0f56aa0e88f13801886cdaef6" - integrity sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg== +"unist-util-visit-parents@^3.0.0": + "integrity" "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==" + "resolved" "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz" + "version" "3.1.1" dependencies: "@types/unist" "^2.0.0" - unist-util-is "^4.0.0" + "unist-util-is" "^4.0.0" -unist-util-visit@2.0.3, unist-util-visit@^2.0.0, unist-util-visit@^2.0.1, unist-util-visit@^2.0.2, unist-util-visit@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" - integrity sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q== +"unist-util-visit@^2.0.0", "unist-util-visit@^2.0.1", "unist-util-visit@^2.0.2", "unist-util-visit@^2.0.3", "unist-util-visit@2.0.3": + "integrity" "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==" + "resolved" "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz" + "version" "2.0.3" dependencies: "@types/unist" "^2.0.0" - unist-util-is "^4.0.0" - unist-util-visit-parents "^3.0.0" - -universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - -update-notifier@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-5.1.0.tgz#4ab0d7c7f36a231dd7316cf7729313f0214d9ad9" - integrity sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw== - dependencies: - boxen "^5.0.0" - chalk "^4.1.0" - configstore "^5.0.1" - has-yarn "^2.1.0" - import-lazy "^2.1.0" - is-ci "^2.0.0" - is-installed-globally "^0.4.0" - is-npm "^5.0.0" - is-yarn-global "^0.3.0" - latest-version "^5.1.0" - pupa "^2.1.1" - semver "^7.3.4" - semver-diff "^3.1.1" - xdg-basedir "^4.0.0" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -url-loader@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2" - integrity sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA== - dependencies: - loader-utils "^2.0.0" - mime-types "^2.1.27" - schema-utils "^3.0.0" - -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= - dependencies: - prepend-http "^2.0.0" - -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -use-composed-ref@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/use-composed-ref/-/use-composed-ref-1.2.1.tgz#9bdcb5ccd894289105da2325e1210079f56bf849" - integrity sha512-6+X1FLlIcjvFMAeAD/hcxDT8tmyrWnbSPMU0EnxQuDLIxokuFzWliXBiYZuGIx+mrAMLBw0WFfCkaPw8ebzAhw== - -use-isomorphic-layout-effect@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz#7bb6589170cd2987a152042f9084f9effb75c225" - integrity sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ== - -use-latest@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/use-latest/-/use-latest-1.2.0.tgz#a44f6572b8288e0972ec411bdd0840ada366f232" - integrity sha512-d2TEuG6nSLKQLAfW3By8mKr8HurOlTkul0sOpxbClIv4SQ4iOd7BYr7VIzdbktUCnv7dua/60xzd8igMU6jmyw== - dependencies: - use-isomorphic-layout-effect "^1.0.0" - -util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -utila@~0.4: - version "0.4.0" - resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" - integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= - -utility-types@^3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.10.0.tgz#ea4148f9a741015f05ed74fd615e1d20e6bed82b" - integrity sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg== - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - -uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -value-equal@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" - integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== - -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - -vfile-location@^3.0.0, vfile-location@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-3.2.0.tgz#d8e41fbcbd406063669ebf6c33d56ae8721d0f3c" - integrity sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA== - -vfile-message@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.4.tgz#5b43b88171d409eae58477d13f23dd41d52c371a" - integrity sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ== + "unist-util-is" "^4.0.0" + "unist-util-visit-parents" "^3.0.0" + +"universalify@^2.0.0": + "integrity" "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + "resolved" "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz" + "version" "2.0.0" + +"unpipe@~1.0.0", "unpipe@1.0.0": + "integrity" "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "resolved" "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + "version" "1.0.0" + +"update-browserslist-db@^1.0.10": + "integrity" "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==" + "resolved" "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz" + "version" "1.0.10" + dependencies: + "escalade" "^3.1.1" + "picocolors" "^1.0.0" + +"update-notifier@^5.1.0": + "integrity" "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==" + "resolved" "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "boxen" "^5.0.0" + "chalk" "^4.1.0" + "configstore" "^5.0.1" + "has-yarn" "^2.1.0" + "import-lazy" "^2.1.0" + "is-ci" "^2.0.0" + "is-installed-globally" "^0.4.0" + "is-npm" "^5.0.0" + "is-yarn-global" "^0.3.0" + "latest-version" "^5.1.0" + "pupa" "^2.1.1" + "semver" "^7.3.4" + "semver-diff" "^3.1.1" + "xdg-basedir" "^4.0.0" + +"uri-js@^4.2.2": + "integrity" "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==" + "resolved" "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" + "version" "4.4.1" + dependencies: + "punycode" "^2.1.0" + +"url-loader@^4.1.1": + "integrity" "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==" + "resolved" "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz" + "version" "4.1.1" + dependencies: + "loader-utils" "^2.0.0" + "mime-types" "^2.1.27" + "schema-utils" "^3.0.0" + +"url-parse-lax@^3.0.0": + "integrity" "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=" + "resolved" "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "prepend-http" "^2.0.0" + +"url@^0.11.0": + "integrity" "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=" + "resolved" "https://registry.npmjs.org/url/-/url-0.11.0.tgz" + "version" "0.11.0" + dependencies: + "punycode" "1.3.2" + "querystring" "0.2.0" + +"use-composed-ref@^1.0.0": + "integrity" "sha512-6+X1FLlIcjvFMAeAD/hcxDT8tmyrWnbSPMU0EnxQuDLIxokuFzWliXBiYZuGIx+mrAMLBw0WFfCkaPw8ebzAhw==" + "resolved" "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.2.1.tgz" + "version" "1.2.1" + +"use-isomorphic-layout-effect@^1.0.0": + "integrity" "sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ==" + "resolved" "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz" + "version" "1.1.1" + +"use-latest@^1.0.0": + "integrity" "sha512-d2TEuG6nSLKQLAfW3By8mKr8HurOlTkul0sOpxbClIv4SQ4iOd7BYr7VIzdbktUCnv7dua/60xzd8igMU6jmyw==" + "resolved" "https://registry.npmjs.org/use-latest/-/use-latest-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "use-isomorphic-layout-effect" "^1.0.0" + +"util-deprecate@^1.0.1", "util-deprecate@^1.0.2", "util-deprecate@~1.0.1": + "integrity" "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "resolved" "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + "version" "1.0.2" + +"utila@~0.4": + "integrity" "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=" + "resolved" "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz" + "version" "0.4.0" + +"utility-types@^3.10.0": + "integrity" "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==" + "resolved" "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz" + "version" "3.10.0" + +"utils-merge@1.0.1": + "integrity" "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "resolved" "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" + "version" "1.0.1" + +"uuid@^8.3.2": + "integrity" "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + "resolved" "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" + "version" "8.3.2" + +"value-equal@^1.0.1": + "integrity" "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + "resolved" "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz" + "version" "1.0.1" + +"vary@~1.1.2": + "integrity" "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + "resolved" "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" + "version" "1.1.2" + +"vfile-location@^3.0.0", "vfile-location@^3.2.0": + "integrity" "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==" + "resolved" "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz" + "version" "3.2.0" + +"vfile-message@^2.0.0": + "integrity" "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==" + "resolved" "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz" + "version" "2.0.4" dependencies: "@types/unist" "^2.0.0" - unist-util-stringify-position "^2.0.0" + "unist-util-stringify-position" "^2.0.0" -vfile@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.2.1.tgz#03f1dce28fc625c625bc6514350fbdb00fa9e624" - integrity sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA== +"vfile@^4.0.0": + "integrity" "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==" + "resolved" "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz" + "version" "4.2.1" dependencies: "@types/unist" "^2.0.0" - is-buffer "^2.0.0" - unist-util-stringify-position "^2.0.0" - vfile-message "^2.0.0" - -wait-on@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-6.0.1.tgz#16bbc4d1e4ebdd41c5b4e63a2e16dbd1f4e5601e" - integrity sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw== - dependencies: - axios "^0.25.0" - joi "^17.6.0" - lodash "^4.17.21" - minimist "^1.2.5" - rxjs "^7.5.4" - -watchpack@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25" - integrity sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA== - dependencies: - glob-to-regexp "^0.4.1" - graceful-fs "^4.1.2" - -wbuf@^1.1.0, wbuf@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" - integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== - dependencies: - minimalistic-assert "^1.0.0" - -web-namespaces@^1.0.0, web-namespaces@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" - integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw== - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= - -webpack-bundle-analyzer@^4.4.2: - version "4.5.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz#1b0eea2947e73528754a6f9af3e91b2b6e0f79d5" - integrity sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ== - dependencies: - acorn "^8.0.4" - acorn-walk "^8.0.0" - chalk "^4.1.0" - commander "^7.2.0" - gzip-size "^6.0.0" - lodash "^4.17.20" - opener "^1.5.2" - sirv "^1.0.7" - ws "^7.3.1" - -webpack-dev-middleware@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz#aa079a8dedd7e58bfeab358a9af7dab304cee57f" - integrity sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg== - dependencies: - colorette "^2.0.10" - memfs "^3.4.1" - mime-types "^2.1.31" - range-parser "^1.2.1" - schema-utils "^4.0.0" - -webpack-dev-server@^4.7.1: - version "4.7.4" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz#d0ef7da78224578384e795ac228d8efb63d5f945" - integrity sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A== + "is-buffer" "^2.0.0" + "unist-util-stringify-position" "^2.0.0" + "vfile-message" "^2.0.0" + +"wait-on@^6.0.0": + "integrity" "sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw==" + "resolved" "https://registry.npmjs.org/wait-on/-/wait-on-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "axios" "^0.25.0" + "joi" "^17.6.0" + "lodash" "^4.17.21" + "minimist" "^1.2.5" + "rxjs" "^7.5.4" + +"watchpack@^2.3.1": + "integrity" "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==" + "resolved" "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz" + "version" "2.3.1" + dependencies: + "glob-to-regexp" "^0.4.1" + "graceful-fs" "^4.1.2" + +"wbuf@^1.1.0", "wbuf@^1.7.3": + "integrity" "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==" + "resolved" "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz" + "version" "1.7.3" + dependencies: + "minimalistic-assert" "^1.0.0" + +"web-namespaces@^1.0.0", "web-namespaces@^1.1.2": + "integrity" "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==" + "resolved" "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz" + "version" "1.1.4" + +"webidl-conversions@^3.0.0": + "integrity" "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + "resolved" "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" + "version" "3.0.1" + +"webpack-bundle-analyzer@^4.4.2": + "integrity" "sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ==" + "resolved" "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz" + "version" "4.5.0" + dependencies: + "acorn" "^8.0.4" + "acorn-walk" "^8.0.0" + "chalk" "^4.1.0" + "commander" "^7.2.0" + "gzip-size" "^6.0.0" + "lodash" "^4.17.20" + "opener" "^1.5.2" + "sirv" "^1.0.7" + "ws" "^7.3.1" + +"webpack-dev-middleware@^5.3.1": + "integrity" "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==" + "resolved" "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz" + "version" "5.3.1" + dependencies: + "colorette" "^2.0.10" + "memfs" "^3.4.1" + "mime-types" "^2.1.31" + "range-parser" "^1.2.1" + "schema-utils" "^4.0.0" + +"webpack-dev-server@^4.7.1": + "integrity" "sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A==" + "resolved" "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz" + "version" "4.7.4" dependencies: "@types/bonjour" "^3.5.9" "@types/connect-history-api-fallback" "^1.3.5" @@ -7519,212 +7582,217 @@ webpack-dev-server@^4.7.1: "@types/serve-index" "^1.9.1" "@types/sockjs" "^0.3.33" "@types/ws" "^8.2.2" - ansi-html-community "^0.0.8" - bonjour "^3.5.0" - chokidar "^3.5.3" - colorette "^2.0.10" - compression "^1.7.4" - connect-history-api-fallback "^1.6.0" - default-gateway "^6.0.3" - del "^6.0.0" - express "^4.17.1" - graceful-fs "^4.2.6" - html-entities "^2.3.2" - http-proxy-middleware "^2.0.0" - ipaddr.js "^2.0.1" - open "^8.0.9" - p-retry "^4.5.0" - portfinder "^1.0.28" - schema-utils "^4.0.0" - selfsigned "^2.0.0" - serve-index "^1.9.1" - sockjs "^0.3.21" - spdy "^4.0.2" - strip-ansi "^7.0.0" - webpack-dev-middleware "^5.3.1" - ws "^8.4.2" - -webpack-merge@^5.8.0: - version "5.8.0" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" - integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== - dependencies: - clone-deep "^4.0.1" - wildcard "^2.0.0" - -webpack-sources@^1.1.0, webpack-sources@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" - integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== - dependencies: - source-list-map "^2.0.0" - source-map "~0.6.1" - -webpack-sources@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" - integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== - -webpack@^5.61.0: - version "5.69.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.69.1.tgz#8cfd92c192c6a52c99ab00529b5a0d33aa848dc5" - integrity sha512-+VyvOSJXZMT2V5vLzOnDuMz5GxEqLk7hKWQ56YxPW/PQRUuKimPqmEIJOx8jHYeyo65pKbapbW464mvsKbaj4A== + "ansi-html-community" "^0.0.8" + "bonjour" "^3.5.0" + "chokidar" "^3.5.3" + "colorette" "^2.0.10" + "compression" "^1.7.4" + "connect-history-api-fallback" "^1.6.0" + "default-gateway" "^6.0.3" + "del" "^6.0.0" + "express" "^4.17.1" + "graceful-fs" "^4.2.6" + "html-entities" "^2.3.2" + "http-proxy-middleware" "^2.0.0" + "ipaddr.js" "^2.0.1" + "open" "^8.0.9" + "p-retry" "^4.5.0" + "portfinder" "^1.0.28" + "schema-utils" "^4.0.0" + "selfsigned" "^2.0.0" + "serve-index" "^1.9.1" + "sockjs" "^0.3.21" + "spdy" "^4.0.2" + "strip-ansi" "^7.0.0" + "webpack-dev-middleware" "^5.3.1" + "ws" "^8.4.2" + +"webpack-merge@^5.8.0": + "integrity" "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==" + "resolved" "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz" + "version" "5.8.0" + dependencies: + "clone-deep" "^4.0.1" + "wildcard" "^2.0.0" + +"webpack-sources@^1.1.0", "webpack-sources@^1.4.3": + "integrity" "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==" + "resolved" "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz" + "version" "1.4.3" + dependencies: + "source-list-map" "^2.0.0" + "source-map" "~0.6.1" + +"webpack-sources@^3.2.3": + "integrity" "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==" + "resolved" "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz" + "version" "3.2.3" + +"webpack@^4.0.0 || ^5.0.0", "webpack@^4.37.0 || ^5.0.0", "webpack@^4.4.0 || ^5.0.0", "webpack@^5.0.0", "webpack@^5.1.0", "webpack@^5.20.0", "webpack@^5.61.0", "webpack@>= 4", "webpack@>=2", "webpack@>=4.41.1 || 5.x", "webpack@3 || 4 || 5", "webpack@5.x": + "integrity" "sha512-+VyvOSJXZMT2V5vLzOnDuMz5GxEqLk7hKWQ56YxPW/PQRUuKimPqmEIJOx8jHYeyo65pKbapbW464mvsKbaj4A==" + "resolved" "https://registry.npmjs.org/webpack/-/webpack-5.69.1.tgz" + "version" "5.69.1" dependencies: "@types/eslint-scope" "^3.7.3" "@types/estree" "^0.0.51" "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/wasm-edit" "1.11.1" "@webassemblyjs/wasm-parser" "1.11.1" - acorn "^8.4.1" - acorn-import-assertions "^1.7.6" - browserslist "^4.14.5" - chrome-trace-event "^1.0.2" - enhanced-resolve "^5.8.3" - es-module-lexer "^0.9.0" - eslint-scope "5.1.1" - events "^3.2.0" - glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" - json-parse-better-errors "^1.0.2" - loader-runner "^4.2.0" - mime-types "^2.1.27" - neo-async "^2.6.2" - schema-utils "^3.1.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" - watchpack "^2.3.1" - webpack-sources "^3.2.3" - -webpackbar@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/webpackbar/-/webpackbar-5.0.2.tgz#d3dd466211c73852741dfc842b7556dcbc2b0570" - integrity sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ== - dependencies: - chalk "^4.1.0" - consola "^2.15.3" - pretty-time "^1.1.0" - std-env "^3.0.1" - -websocket-driver@>=0.5.1, websocket-driver@^0.7.4: - version "0.7.4" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" - integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== - dependencies: - http-parser-js ">=0.5.1" - safe-buffer ">=5.1.0" - websocket-extensions ">=0.1.1" - -websocket-extensions@>=0.1.1: - version "0.1.4" - resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" - integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -which@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -widest-line@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" - integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== - dependencies: - string-width "^4.0.0" - -wildcard@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" - integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write-file-atomic@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" - integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== - dependencies: - imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^3.1.5" - -ws@^7.3.1: - version "7.5.7" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" - integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== - -ws@^8.4.2: - version "8.5.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" - integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== - -xdg-basedir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" - integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== - -xml-js@^1.6.11: - version "1.6.11" - resolved "https://registry.yarnpkg.com/xml-js/-/xml-js-1.6.11.tgz#927d2f6947f7f1c19a316dd8eea3614e8b18f8e9" - integrity sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g== - dependencies: - sax "^1.2.4" - -xtend@^4.0.0, xtend@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" - integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== - -yarn@^1.17.3: - version "1.22.17" - resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.17.tgz#bf910747d22497b573131f7341c0e1d15c74036c" - integrity sha512-H0p241BXaH0UN9IeH//RT82tl5PfNraVpSpEoW+ET7lmopNC61eZ+A+IDvU8FM6Go5vx162SncDL8J1ZjRBriQ== - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -zwitch@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920" - integrity sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw== + "acorn" "^8.4.1" + "acorn-import-assertions" "^1.7.6" + "browserslist" "^4.14.5" + "chrome-trace-event" "^1.0.2" + "enhanced-resolve" "^5.8.3" + "es-module-lexer" "^0.9.0" + "eslint-scope" "5.1.1" + "events" "^3.2.0" + "glob-to-regexp" "^0.4.1" + "graceful-fs" "^4.2.9" + "json-parse-better-errors" "^1.0.2" + "loader-runner" "^4.2.0" + "mime-types" "^2.1.27" + "neo-async" "^2.6.2" + "schema-utils" "^3.1.0" + "tapable" "^2.1.1" + "terser-webpack-plugin" "^5.1.3" + "watchpack" "^2.3.1" + "webpack-sources" "^3.2.3" + +"webpackbar@^5.0.2": + "integrity" "sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ==" + "resolved" "https://registry.npmjs.org/webpackbar/-/webpackbar-5.0.2.tgz" + "version" "5.0.2" + dependencies: + "chalk" "^4.1.0" + "consola" "^2.15.3" + "pretty-time" "^1.1.0" + "std-env" "^3.0.1" + +"websocket-driver@^0.7.4", "websocket-driver@>=0.5.1": + "integrity" "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==" + "resolved" "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz" + "version" "0.7.4" + dependencies: + "http-parser-js" ">=0.5.1" + "safe-buffer" ">=5.1.0" + "websocket-extensions" ">=0.1.1" + +"websocket-extensions@>=0.1.1": + "integrity" "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" + "resolved" "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz" + "version" "0.1.4" + +"whatwg-url@^5.0.0": + "integrity" "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=" + "resolved" "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "tr46" "~0.0.3" + "webidl-conversions" "^3.0.0" + +"which@^1.3.1": + "integrity" "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==" + "resolved" "https://registry.npmjs.org/which/-/which-1.3.1.tgz" + "version" "1.3.1" + dependencies: + "isexe" "^2.0.0" + +"which@^2.0.1": + "integrity" "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==" + "resolved" "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "isexe" "^2.0.0" + +"widest-line@^3.1.0": + "integrity" "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==" + "resolved" "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "string-width" "^4.0.0" + +"wildcard@^2.0.0": + "integrity" "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==" + "resolved" "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz" + "version" "2.0.0" + +"wrap-ansi@^7.0.0": + "integrity" "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==" + "resolved" "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + "version" "7.0.0" + dependencies: + "ansi-styles" "^4.0.0" + "string-width" "^4.1.0" + "strip-ansi" "^6.0.0" + +"wrappy@1": + "integrity" "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "resolved" "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + "version" "1.0.2" + +"write-file-atomic@^3.0.0": + "integrity" "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==" + "resolved" "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz" + "version" "3.0.3" + dependencies: + "imurmurhash" "^0.1.4" + "is-typedarray" "^1.0.0" + "signal-exit" "^3.0.2" + "typedarray-to-buffer" "^3.1.5" + +"ws@^7.3.1": + "integrity" "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==" + "resolved" "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz" + "version" "7.5.7" + +"ws@^8.4.2": + "integrity" "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==" + "resolved" "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz" + "version" "8.5.0" + +"xdg-basedir@^4.0.0": + "integrity" "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" + "resolved" "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz" + "version" "4.0.0" + +"xml-js@^1.6.11": + "integrity" "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==" + "resolved" "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz" + "version" "1.6.11" + dependencies: + "sax" "^1.2.4" + +"xtend@^4.0.0", "xtend@^4.0.1": + "integrity" "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + "resolved" "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" + "version" "4.0.2" + +"yallist@^3.0.2": + "integrity" "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "resolved" "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" + "version" "3.1.1" + +"yallist@^4.0.0": + "integrity" "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "resolved" "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" + "version" "4.0.0" + +"yaml@^1.10.0", "yaml@^1.10.2", "yaml@^1.7.2": + "integrity" "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" + "resolved" "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" + "version" "1.10.2" + +"yarn@^1.17.3": + "integrity" "sha512-H0p241BXaH0UN9IeH//RT82tl5PfNraVpSpEoW+ET7lmopNC61eZ+A+IDvU8FM6Go5vx162SncDL8J1ZjRBriQ==" + "resolved" "https://registry.npmjs.org/yarn/-/yarn-1.22.17.tgz" + "version" "1.22.17" + +"yocto-queue@^0.1.0": + "integrity" "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + "resolved" "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" + "version" "0.1.0" + +"zwitch@^1.0.0": + "integrity" "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==" + "resolved" "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz" + "version" "1.0.5" From dad56a3ab8794b01efd06947881c7b7c9782f718 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Tue, 14 Mar 2023 15:45:26 +0000 Subject: [PATCH 415/898] Update artist_hosts_maya_arnold.md --- website/docs/artist_hosts_maya_arnold.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/artist_hosts_maya_arnold.md b/website/docs/artist_hosts_maya_arnold.md index b3c02a08944..da16ba66c02 100644 --- a/website/docs/artist_hosts_maya_arnold.md +++ b/website/docs/artist_hosts_maya_arnold.md @@ -6,7 +6,7 @@ sidebar_label: Arnold ## Arnold Scene Source (.ass) Arnold Scene Source can be published as a single file or a sequence of files, determined by the frame range. -When creating the instance, two objectsets are created; `content` and `proxy`. Meshes in the `proxy` objectset will be the viewport representation when loading as `standin`. Proxy representations are stored as `resources` of the subset. +When creating the instance, two objectsets are created; `content` and `proxy`. Meshes in the `proxy` objectset will be the viewport representation when loading as `standin`. ### Arnold Scene Source Proxy Workflow In order to utilize operators and proxies, the content and proxy nodes need to share the same names (including the shape names). This is done by parenting the content and proxy nodes into separate groups. For example: From 10ff798ed59e72f006f4aac8df09a8bb119c647b Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 14 Mar 2023 17:18:56 +0100 Subject: [PATCH 416/898] Fixed "Select invalid" --- .../validate_local_frames_existence.py | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/validate_local_frames_existence.py b/openpype/hosts/fusion/plugins/publish/validate_local_frames_existence.py index d80e11e078d..c1cba795e1a 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_local_frames_existence.py +++ b/openpype/hosts/fusion/plugins/publish/validate_local_frames_existence.py @@ -8,7 +8,9 @@ class ValidateLocalFramesExistence(pyblish.api.InstancePlugin): - """Checks if files for savers that's set to publish existing frames exists""" + """Checks if files for savers that's set + to publish existing frames exists + """ order = pyblish.api.ValidatorOrder label = "Validate Existing Frames Exists" @@ -17,7 +19,7 @@ class ValidateLocalFramesExistence(pyblish.api.InstancePlugin): actions = [RepairAction, SelectInvalidAction] @classmethod - def get_invalid(cls, instance): + def get_invalid(cls, instance, non_existing_frames=[]): active = instance.data.get("active", instance.data.get("publish")) if not active: return [] @@ -37,29 +39,27 @@ def get_invalid(cls, instance): for frame in range(frame_start, frame_end + 1) ] - non_existing_frames = [] - for file in files: - cls.log.error(file) if not os.path.exists(os.path.join(output_dir, file)): + cls.log.error( + f"Missing file: {os.path.join(output_dir, file)}" + ) non_existing_frames.append(file) if len(non_existing_frames) > 0: - cls.log.error( - "Some of {}'s files does not exist".format(tool.Name) - ) - return [tool, output_dir, non_existing_frames] + cls.log.error(f"Some of {tool.Name}'s files does not exist") + return [tool] def process(self, instance): - invalid = self.get_invalid(instance) + non_existing_frames = [] + invalid = self.get_invalid(instance, non_existing_frames) if invalid: raise PublishValidationError( "{} is set to publish existing frames but " - "some frames are missing in the folder:\n\n{}" + "some frames are missing. " "The missing file(s) are:\n\n{}".format( invalid[0].Name, - invalid[1], - "\n\n".join(invalid[2]), + "\n\n".join(non_existing_frames), ), title=self.label, ) From 9741d47fbc7c03d20cbc775f61ae19e321bb631c Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 14 Mar 2023 17:19:19 +0100 Subject: [PATCH 417/898] Added crude repair functionality --- .../publish/validate_local_frames_existence.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/validate_local_frames_existence.py b/openpype/hosts/fusion/plugins/publish/validate_local_frames_existence.py index c1cba795e1a..4b50e0b8379 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_local_frames_existence.py +++ b/openpype/hosts/fusion/plugins/publish/validate_local_frames_existence.py @@ -67,5 +67,14 @@ def process(self, instance): @classmethod def repair(cls, instance): invalid = cls.get_invalid(instance) - for tool in invalid: - tool.SetInput("CreateDir", 1.0) + if invalid: + data = invalid[0].GetData("openpype") + + # Change render target to local to render locally + data["creator_attributes"]["render_target"] = "local" + + invalid[0].SetData("openpype", data) + cls.log.error( + f"Reload the publisher and {invalid[0].Name} " + "will be set to render locally" + ) From 1e9670f54dd9121527438c25649c53016fd4ea92 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 14 Mar 2023 17:19:43 +0100 Subject: [PATCH 418/898] Fixed docstring and removed unused variables --- .../fusion/plugins/publish/collect_renders.py | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/collect_renders.py b/openpype/hosts/fusion/plugins/publish/collect_renders.py index cdd37b3b653..be405d24951 100644 --- a/openpype/hosts/fusion/plugins/publish/collect_renders.py +++ b/openpype/hosts/fusion/plugins/publish/collect_renders.py @@ -3,21 +3,11 @@ class CollectFusionRenders(pyblish.api.InstancePlugin): - """Collect current comp's render Mode + """Collect current saver node's render Mode Options: - local - farm - - Note that this value is set for each comp separately. When you save the - comp this information will be stored in that file. If for some reason the - available tool does not visualize which render mode is set for the - current comp, please run the following line in the console (Py2) - - comp.GetData("openpype.rendermode") - - This will return the name of the current render mode as seen above under - Options. + local (Render locally) + frames (Use existing frames) """ @@ -29,10 +19,8 @@ class CollectFusionRenders(pyblish.api.InstancePlugin): def process(self, instance): self.log.debug(pformat(instance.data)) - saver_node = instance.data["transientData"]["tool"] render_target = instance.data["render_target"] family = instance.data["family"] - families = instance.data["families"] # add targeted family to families instance.data["families"].append( From 191882424047cb517f0fc97171819dcca6d84093 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 14 Mar 2023 17:56:11 +0100 Subject: [PATCH 419/898] Moved the review representation back to render_local.py --- .../plugins/publish/extract_render_local.py | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/openpype/hosts/fusion/plugins/publish/extract_render_local.py b/openpype/hosts/fusion/plugins/publish/extract_render_local.py index 62625c899a9..ea801107c18 100644 --- a/openpype/hosts/fusion/plugins/publish/extract_render_local.py +++ b/openpype/hosts/fusion/plugins/publish/extract_render_local.py @@ -29,6 +29,41 @@ def process(self, instance): ) ) + # Generate the frame list + frame_start = context.data["frameStartHandle"] + frame_end = context.data["frameEndHandle"] + path = instance.data["path"] + output_dir = instance.data["outputDir"] + + basename = os.path.basename(path) + head, ext = os.path.splitext(basename) + files = [ + f"{head}{str(frame).zfill(4)}{ext}" + for frame in range(frame_start, frame_end + 1) + ] + repre = { + "name": ext[1:], + "ext": ext[1:], + "frameStart": f"%0{len(str(frame_end))}d" % frame_start, + "files": files, + "stagingDir": output_dir, + } + + # Get the colorspace represenation + self.set_representation_colorspace( + representation=repre, + context=context, + ) + + # review representation + if instance.data.get("review", False): + repre["tags"] = ["review"] + + # add the repre to the instance + if "representations" not in instance.data: + instance.data["representations"] = [] + instance.data["representations"].append(repre) + def render_once(self, context): """Render context comp only once, even with more render instances""" From c7ae8b53201b5a0f223aec38cc2244b305581607 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 14 Mar 2023 17:57:45 +0100 Subject: [PATCH 420/898] Collect all frames for "using existing frames" savers --- ...iew_data.py => collect_existing_frames.py} | 20 ++++++------------- ... => validate_existing_frames_existence.py} | 0 2 files changed, 6 insertions(+), 14 deletions(-) rename openpype/hosts/fusion/plugins/publish/{extract_review_data.py => collect_existing_frames.py} (74%) rename openpype/hosts/fusion/plugins/publish/{validate_local_frames_existence.py => validate_existing_frames_existence.py} (100%) diff --git a/openpype/hosts/fusion/plugins/publish/extract_review_data.py b/openpype/hosts/fusion/plugins/publish/collect_existing_frames.py similarity index 74% rename from openpype/hosts/fusion/plugins/publish/extract_review_data.py rename to openpype/hosts/fusion/plugins/publish/collect_existing_frames.py index d9416771f63..7c5f7cd55df 100644 --- a/openpype/hosts/fusion/plugins/publish/extract_review_data.py +++ b/openpype/hosts/fusion/plugins/publish/collect_existing_frames.py @@ -1,22 +1,14 @@ -import os import pyblish.api -from openpype.pipeline.publish import ( - ColormanagedPyblishPluginMixin, -) +import os -class FusionExtractReviewData( - pyblish.api.InstancePlugin, ColormanagedPyblishPluginMixin -): - """ - Extract the result of savers by starting a comp render - This will run the local render of Fusion. - """ +class CollectFusionRenders(pyblish.api.InstancePlugin): + """Collect all frames needed to publish existing frames""" - order = pyblish.api.ExtractorOrder - 0.1 - label = "Extract Review Data" + order = pyblish.api.CollectorOrder + 0.5 + label = "Collect Existing Frames" hosts = ["fusion"] - families = ["review"] + families = ["render.frames"] def process(self, instance): context = instance.context diff --git a/openpype/hosts/fusion/plugins/publish/validate_local_frames_existence.py b/openpype/hosts/fusion/plugins/publish/validate_existing_frames_existence.py similarity index 100% rename from openpype/hosts/fusion/plugins/publish/validate_local_frames_existence.py rename to openpype/hosts/fusion/plugins/publish/validate_existing_frames_existence.py From 1754ef32672256b1661669d510c1c83e6fa5f403 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 14 Mar 2023 18:06:37 +0100 Subject: [PATCH 421/898] Fixed mutable data structure problem --- .../plugins/publish/validate_existing_frames_existence.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/plugins/publish/validate_existing_frames_existence.py b/openpype/hosts/fusion/plugins/publish/validate_existing_frames_existence.py index 4b50e0b8379..a43d2c691ad 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_existing_frames_existence.py +++ b/openpype/hosts/fusion/plugins/publish/validate_existing_frames_existence.py @@ -19,7 +19,10 @@ class ValidateLocalFramesExistence(pyblish.api.InstancePlugin): actions = [RepairAction, SelectInvalidAction] @classmethod - def get_invalid(cls, instance, non_existing_frames=[]): + def get_invalid(cls, instance, non_existing_frames=None): + if non_existing_frames is None: + non_existing_frames = [] + active = instance.data.get("active", instance.data.get("publish")) if not active: return [] From 78ce629ba63ee31f104255d628dbb6067578bea9 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 14 Mar 2023 18:14:19 +0100 Subject: [PATCH 422/898] Removed double casting --- openpype/modules/kitsu/utils/update_op_with_zou.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index a2b560b75b5..1f38648dfa4 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -128,7 +128,7 @@ def update_op_assets( if frames_duration: frame_out = frame_in + frames_duration - 1 else: - frame_out = int(project_doc["data"].get("frameEnd", frame_in)) + frame_out = project_doc["data"].get("frameEnd", frame_in) item_data["frameEnd"] = int(frame_out) # Fps, fallback to project's value or default value (25.0) try: From 383ce7ccb6f20453ef2aa40d81b2af4ae5856eba Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 14 Mar 2023 18:32:18 +0100 Subject: [PATCH 423/898] Change variable name to snake_case --- .../kitsu/plugins/publish/integrate_kitsu_note.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 44134dec6d7..debbfdf98ef 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -16,9 +16,11 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): note_status_shortname = "wfa" # comment settings - CustomCommentTemplate = {} - CustomCommentTemplate["enabled"] = False - CustomCommentTemplate["comment_template"] = "{comment}" + custom_comment_template = {} + custom_comment_template = { + "enabled": False, + "comment_template": "{comment}", + } def safe_format(self, msg, **kwargs): def replace_missing(match): @@ -70,9 +72,9 @@ def process(self, context): ) # If custom comment, create it - if self.CustomCommentTemplate["enabled"]: + if self.custom_comment_template["enabled"]: publish_comment = self.safe_format( - self.CustomCommentTemplate["comment_template"], + self.custom_comment_template["comment_template"], **instance.data, ) From c53e5b2302b9916360bf3e3a2f38e550596f64d8 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 14 Mar 2023 18:32:41 +0100 Subject: [PATCH 424/898] Added docstring --- openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index debbfdf98ef..a4b229d236d 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -23,6 +23,8 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): } def safe_format(self, msg, **kwargs): + """If key is not found in kwargs, set None instead""" + def replace_missing(match): value = kwargs.get(match.group(1), None) if value is None: From a789b135aed5d1dabdbee3b3ae14904a95b34428 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Tue, 14 Mar 2023 18:33:00 +0100 Subject: [PATCH 425/898] Changed the instance check from render to review --- .../modules/kitsu/plugins/publish/integrate_kitsu_note.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index a4b229d236d..2e1e656ceef 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -48,8 +48,8 @@ def process(self, context): self.log.info("Comment is not set.") for instance in context: - # Check if instance is a render by checking its family - if "render" not in instance.data["family"]: + # Check if instance is a review by checking its family + if "review" not in instance.data["family"]: continue kitsu_task = instance.data.get("kitsu_task") From 87655075a9d5e4cc47b5a760fa5d31056444b634 Mon Sep 17 00:00:00 2001 From: Ynbot Date: Wed, 15 Mar 2023 03:26:53 +0000 Subject: [PATCH 426/898] [Automated] Bump version --- openpype/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/version.py b/openpype/version.py index 6ab03c2121f..39a7dc9344a 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.15.2" +__version__ = "3.15.3-nightly.1" From 0cb3585d91e63352dff24a861c0a19fc3a96425b Mon Sep 17 00:00:00 2001 From: mre7a <68907585+mre7a@users.noreply.github.com> Date: Wed, 15 Mar 2023 12:55:50 +0100 Subject: [PATCH 427/898] Resolve missing OPENPYPE_MONGO in deadline global job preload (#4484) * replace SpawnProcess with subprocess * clean up * replace spawn process with run process --------- Co-authored-by: Seyedmohammadreza Hashemizadeh --- .../repository/custom/plugins/GlobalJobPreLoad.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py b/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py index 20a58c91310..15226bb7733 100644 --- a/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py +++ b/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py @@ -362,11 +362,11 @@ def inject_openpype_environment(deadlinePlugin): args_str = subprocess.list2cmdline(args) print(">>> Executing: {} {}".format(exe, args_str)) - process = ProcessUtils.SpawnProcess( - exe, args_str, os.path.dirname(exe) + process_exitcode = deadlinePlugin.RunProcess( + exe, args_str, os.path.dirname(exe), -1 ) - ProcessUtils.WaitForExit(process, -1) - if process.ExitCode != 0: + + if process_exitcode != 0: raise RuntimeError( "Failed to run OpenPype process to extract environments." ) From b3816ae876ff35d6187e43357d2580e46bafe2ae Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Wed, 15 Mar 2023 17:05:00 +0100 Subject: [PATCH 428/898] Fixed key check towards kwargs --- .../kitsu/plugins/publish/integrate_kitsu_note.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 2e1e656ceef..d4282ab0484 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -16,7 +16,6 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): note_status_shortname = "wfa" # comment settings - custom_comment_template = {} custom_comment_template = { "enabled": False, "comment_template": "{comment}", @@ -26,17 +25,15 @@ def safe_format(self, msg, **kwargs): """If key is not found in kwargs, set None instead""" def replace_missing(match): - value = kwargs.get(match.group(1), None) - if value is None: + key = match.group(1) + if key not in kwargs: self.log.warning( "Key `{}` was not found in instance.data " - "and will be rendered as `` in the comment".format( - match.group(1) - ) + "and will be rendered as `` in the comment".format(key) ) return "" else: - return str(value) + return str(kwargs[key]) pattern = r"\{([^}]*)\}" return re.sub(pattern, replace_missing, msg) From a30887bb746ebba4756329cefb36eb4fa77d0db7 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Wed, 15 Mar 2023 17:05:34 +0100 Subject: [PATCH 429/898] Change name from CamelCase to snake_case --- openpype/settings/defaults/project_settings/kitsu.json | 2 +- .../schemas/projects_schema/schema_project_kitsu.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/settings/defaults/project_settings/kitsu.json b/openpype/settings/defaults/project_settings/kitsu.json index f8a98d1a0b9..738bd95e389 100644 --- a/openpype/settings/defaults/project_settings/kitsu.json +++ b/openpype/settings/defaults/project_settings/kitsu.json @@ -8,7 +8,7 @@ "IntegrateKitsuNote": { "set_status_note": false, "note_status_shortname": "wfa", - "CustomCommentTemplate": { + "custom_comment_template": { "enabled": false, "comment_template": "{comment}\n\n| | |\n|--|--|\n| version| `{version}` |\n| family | `{family}` |\n| name | `{name}` |" } diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index 1a7747b3dca..fc421c20f57 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -57,7 +57,7 @@ "type": "dict", "collapsible": true, "checkbox_key": "enabled", - "key": "CustomCommentTemplate", + "key": "custom_comment_template", "label": "Custom Comment Template", "children": [ { @@ -67,7 +67,7 @@ }, { "type": "label", - "label": "Kitsu supports markdown and here you can create a custom comment template.
You can use data from your instance's anatomy." + "label": "Kitsu supports markdown and here you can create a custom comment template.
You can use data from your publishing instance's data." }, { "key": "comment_template", From fe9c807b1fb0a9ddb56d1581c9f916c360b8c863 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 15 Mar 2023 17:13:10 +0000 Subject: [PATCH 430/898] Fix playblast panel collection --- openpype/hosts/maya/plugins/publish/collect_review.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_review.py b/openpype/hosts/maya/plugins/publish/collect_review.py index 65ff7cf0fef..548b1c996aa 100644 --- a/openpype/hosts/maya/plugins/publish/collect_review.py +++ b/openpype/hosts/maya/plugins/publish/collect_review.py @@ -24,7 +24,9 @@ def process(self, instance): task = legacy_io.Session["AVALON_TASK"] # Get panel. - instance.data["panel"] = cmds.playblast(activeEditor=True) + instance.data["panel"] = cmds.playblast( + activeEditor=True + ).split("|")[-1] # get cameras members = instance.data['setMembers'] From 8449c2131d49354b581e8db495b1b36b64f1a89f Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 15 Mar 2023 18:28:55 +0100 Subject: [PATCH 431/898] Extended Nuke testing classes with representation details --- .../nuke/test_deadline_publish_in_nuke.py | 18 +++++++++++ .../hosts/nuke/test_publish_in_nuke.py | 31 +++++++++++++++---- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/tests/integration/hosts/nuke/test_deadline_publish_in_nuke.py b/tests/integration/hosts/nuke/test_deadline_publish_in_nuke.py index cd9cbb94f89..a4026f195b0 100644 --- a/tests/integration/hosts/nuke/test_deadline_publish_in_nuke.py +++ b/tests/integration/hosts/nuke/test_deadline_publish_in_nuke.py @@ -71,12 +71,30 @@ def test_db_asserts(self, dbcon, publish_finished): failures.append( DBAssert.count_of_types(dbcon, "representation", 4)) + additional_args = {"context.subset": "workfileTest_task", + "context.ext": "nk"} + failures.append( + DBAssert.count_of_types(dbcon, "representation", 1, + additional_args=additional_args)) + additional_args = {"context.subset": "renderTest_taskMain", "context.ext": "exr"} failures.append( DBAssert.count_of_types(dbcon, "representation", 1, additional_args=additional_args)) + additional_args = {"context.subset": "renderTest_taskMain", + "name": "thumbnail"} + failures.append( + DBAssert.count_of_types(dbcon, "representation", 1, + additional_args=additional_args)) + + additional_args = {"context.subset": "renderTest_taskMain", + "name": "h264_mov"} + failures.append( + DBAssert.count_of_types(dbcon, "representation", 1, + additional_args=additional_args)) + assert not any(failures) diff --git a/tests/integration/hosts/nuke/test_publish_in_nuke.py b/tests/integration/hosts/nuke/test_publish_in_nuke.py index f84f13fa20d..a4026f195b0 100644 --- a/tests/integration/hosts/nuke/test_publish_in_nuke.py +++ b/tests/integration/hosts/nuke/test_publish_in_nuke.py @@ -1,12 +1,12 @@ import logging from tests.lib.assert_classes import DBAssert -from tests.integration.hosts.nuke.lib import NukeLocalPublishTestClass +from tests.integration.hosts.nuke.lib import NukeDeadlinePublishTestClass log = logging.getLogger("test_publish_in_nuke") -class TestPublishInNuke(NukeLocalPublishTestClass): +class TestDeadlinePublishInNuke(NukeDeadlinePublishTestClass): """Basic test case for publishing in Nuke Uses generic TestCase to prepare fixtures for test data, testing DBs, @@ -15,7 +15,7 @@ class TestPublishInNuke(NukeLocalPublishTestClass): !!! It expects modified path in WriteNode, use '[python {nuke.script_directory()}]' instead of regular root - dir (eg. instead of `c:/projects/test_project/test_asset/test_task`). + dir (eg. instead of `c:/projects`). Access file path by selecting WriteNode group, CTRL+Enter, update file input !!! @@ -36,12 +36,13 @@ class TestPublishInNuke(NukeLocalPublishTestClass): """ # https://drive.google.com/file/d/1SUurHj2aiQ21ZIMJfGVBI2KjR8kIjBGI/view?usp=sharing # noqa: E501 TEST_FILES = [ - ("1SUurHj2aiQ21ZIMJfGVBI2KjR8kIjBGI", "test_Nuke_publish.zip", "") + ("1SeWprClKhWMv2xVC9AcnekIJFExxnp_b", + "test_nuke_deadline_publish.zip", "") ] APP_GROUP = "nuke" - TIMEOUT = 50 # publish timeout + TIMEOUT = 180 # publish timeout # could be overwritten by command line arguments # keep empty to locate latest installed variant or explicit @@ -70,14 +71,32 @@ def test_db_asserts(self, dbcon, publish_finished): failures.append( DBAssert.count_of_types(dbcon, "representation", 4)) + additional_args = {"context.subset": "workfileTest_task", + "context.ext": "nk"} + failures.append( + DBAssert.count_of_types(dbcon, "representation", 1, + additional_args=additional_args)) + additional_args = {"context.subset": "renderTest_taskMain", "context.ext": "exr"} failures.append( DBAssert.count_of_types(dbcon, "representation", 1, additional_args=additional_args)) + additional_args = {"context.subset": "renderTest_taskMain", + "name": "thumbnail"} + failures.append( + DBAssert.count_of_types(dbcon, "representation", 1, + additional_args=additional_args)) + + additional_args = {"context.subset": "renderTest_taskMain", + "name": "h264_mov"} + failures.append( + DBAssert.count_of_types(dbcon, "representation", 1, + additional_args=additional_args)) + assert not any(failures) if __name__ == "__main__": - test_case = TestPublishInNuke() + test_case = TestDeadlinePublishInNuke() From 00a901120b3a5c0ed258af9bf03084c1c7e994de Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Thu, 16 Mar 2023 02:58:54 +0300 Subject: [PATCH 432/898] check for suported fusion version --- openpype/hosts/fusion/addon.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/fusion/addon.py b/openpype/hosts/fusion/addon.py index e3464f4be43..cb4dc764813 100644 --- a/openpype/hosts/fusion/addon.py +++ b/openpype/hosts/fusion/addon.py @@ -4,6 +4,8 @@ from openpype.lib import Logger FUSION_HOST_DIR = os.path.dirname(os.path.abspath(__file__)) +FUSION16_PROFILE_VERSIONS = (16, 17, 18) +FUSION9_PROFILE_VERSION = 9 def get_fusion_profile_number(module: str, app_data: str) -> int: @@ -15,8 +17,10 @@ def get_fusion_profile_number(module: str, app_data: str) -> int: The variable is added in case the version number will be updated or deleted so we could easily change the version or disable it. - app_data derives from `launch_context.env.get("AVALON_APP_NAME")`. - For the time being we will encourage user to set a version number + Currently valid Fusion versions are stored in FUSION16_PROFILE_VERSIONS + + app_data derives from `launch_context.env.get("AVALON_APP_NAME")`. + For the time being we will encourage user to set a version number set in the system settings key for the Blackmagic Fusion. """ @@ -24,16 +28,18 @@ def get_fusion_profile_number(module: str, app_data: str) -> int: if not app_data: return - fusion16_profile_versions = ("16", "17", "18") + try: app_version = re.search(r"fusion/(\d+)", app_data).group(1) - log.info(f"{module} found Fusion profile version: {app_version}") - if app_version in fusion16_profile_versions: + log.debug(f"{module} found Fusion profile version: {app_version}") + if app_version in map(str, FUSION16_PROFILE_VERSIONS): return 16 - elif app_version == "9": + elif app_version == str(FUSION9_PROFILE_VERSION): return 9 + else: + log.info(f"Found unsupported Fusion version: {app_version}") except AttributeError: - log.info("Fusion version was not found in the app data") + log.info("Fusion version was not found in the AVALON_APP_NAME data") class FusionAddon(OpenPypeModule, IHostAddon): From ef5c081b5fb77c7709bf780f552d0cc72f16a369 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Thu, 16 Mar 2023 02:59:18 +0300 Subject: [PATCH 433/898] add execution order --- openpype/hosts/fusion/hooks/pre_fusion_ocio_hook.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_ocio_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_ocio_hook.py index 6bf0f55081b..47645b7e3f0 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_ocio_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_ocio_hook.py @@ -7,6 +7,7 @@ class FusionPreLaunchOCIO(PreLaunchHook): """Set OCIO environment variable for Fusion""" app_groups = ["fusion"] + order = 3 def execute(self): """Hook entry method.""" From b305aac21dd14f8d58656b8be197926ca4505316 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Thu, 16 Mar 2023 03:01:35 +0300 Subject: [PATCH 434/898] fix docs --- .../hosts/fusion/hooks/pre_fusion_profile_hook.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py index dc6a4bf85da..08ba9c41576 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -25,9 +25,7 @@ def check_profile_variable(self, app_version) -> Path: # Check if FUSION_PROFILE_DIR exists if fusion_var_prefs_dir and Path(fusion_var_prefs_dir).is_dir(): fu_prefs_dir = Path(fusion_var_prefs_dir, fusion_profile) - self.log.info( - f"{fusion_var_prefs_dir} is set to {fu_prefs_dir}" - ) + self.log.info(f"{fusion_var_prefs_dir} is set to {fu_prefs_dir}") return fu_prefs_dir def get_profile_source(self, app_version) -> Path: @@ -106,7 +104,7 @@ def execute(self): ) = self.get_copy_fusion_prefs_settings() # Get launched application context and return correct app version - app_data = self.launch_context.env.get("AVALON_APP_NAME", "fusion/18") + app_data = self.launch_context.env.get("AVALON_APP_NAME") app_version = get_fusion_profile_number(__name__, app_data) fu_profile = self.get_fusion_profile_name(app_version) @@ -122,8 +120,9 @@ def execute(self): self.log.info(f"Setting {fu_profile_dir_variable}: {fu_profile_dir}") self.launch_context.env[fu_profile_dir_variable] = str(fu_profile_dir) - # setup masterprefs file to partially alter existing or newly generated - # Fusion profile, to add OpenPype menu, scripts and and config files. + # Add custom Fusion Master Prefs and the temporary + # profile directory variables to customize Fusion + # to define where it can read custom scripts and tools from master_prefs_variable = f"FUSION{app_version}_MasterPrefs" master_prefs = Path(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") self.log.info(f"Setting {master_prefs_variable}: {master_prefs}") From f3e20c0af9c4a68858150a52720fb1be1cb1675b Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Thu, 16 Mar 2023 03:03:39 +0300 Subject: [PATCH 435/898] force check Fusion number version in app settings --- .../hosts/fusion/hooks/pre_fusion_setup.py | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index 38627b40c12..b9f568bad25 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -1,7 +1,9 @@ import os from openpype.lib import PreLaunchHook, ApplicationLaunchFailed -from openpype.hosts.fusion import FUSION_HOST_DIR -from openpype.hosts.fusion import get_fusion_profile_number +from openpype.hosts.fusion import ( + FUSION_HOST_DIR, + get_fusion_profile_number, +) class FusionPrelaunch(PreLaunchHook): @@ -22,8 +24,14 @@ class FusionPrelaunch(PreLaunchHook): def execute(self): # making sure python 3 is installed at provided path # Py 3.3-3.10 for Fusion 18+ or Py 3.6 for Fu 16-17 - app_data = self.launch_context.env.get("AVALON_APP_NAME", "fusion/18") + app_data = self.launch_context.env.get("AVALON_APP_NAME") app_version = get_fusion_profile_number(__name__, app_data) + if not app_version: + raise ApplicationLaunchFailed( + "Fusion version information not found in System settings.\n" + "The key field in the 'applications/fusion/variants' " + "should consist a number, corresponding to the Fusion version" + ) py3_var = "FUSION_PYTHON3_HOME" fusion_python3_home = self.launch_context.env.get(py3_var, "") @@ -57,10 +65,9 @@ def execute(self): if app_version == 9: self.launch_context.env[f"FUSION_PYTHON36_HOME"] = py3_dir elif app_version == 16: - self.launch_context.env[f"FUSION{app_version}_PYTHON36_HOME"] = py3_dir # noqa + self.launch_context.env[ + f"FUSION{app_version}_PYTHON36_HOME" + ] = py3_dir - # Add custom Fusion Master Prefs and the temporary - # profile directory variables to customize Fusion - # to define where it can read custom scripts and tools from self.log.info(f"Setting OPENPYPE_FUSION: {FUSION_HOST_DIR}") self.launch_context.env["OPENPYPE_FUSION"] = FUSION_HOST_DIR From a63e297186f2fbbda5b115db9f8027d037d86d3f Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Thu, 16 Mar 2023 03:08:20 +0300 Subject: [PATCH 436/898] remove unused import --- openpype/hosts/fusion/api/workio.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/fusion/api/workio.py b/openpype/hosts/fusion/api/workio.py index fbb5a588f4d..fa4b62c1236 100644 --- a/openpype/hosts/fusion/api/workio.py +++ b/openpype/hosts/fusion/api/workio.py @@ -1,5 +1,4 @@ """Host API required Work Files tool""" -import sys import os from .lib import get_fusion_module, get_current_comp From ce22b665b4b1ce1216f84156c09074cb6436545a Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 16 Mar 2023 10:39:47 +0100 Subject: [PATCH 437/898] Fixed comments in code --- .../kitsu/plugins/publish/integrate_kitsu_note.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index d4282ab0484..69b456426f5 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -22,21 +22,24 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): } def safe_format(self, msg, **kwargs): - """If key is not found in kwargs, set None instead""" + """Pars the msg thourgh a custom format code. + It makes sure non existing keys gets None returned instead of error + """ - def replace_missing(match): + def replace_missing_key(match): + """If key is not found in kwargs, set None instead""" key = match.group(1) if key not in kwargs: self.log.warning( - "Key `{}` was not found in instance.data " - "and will be rendered as `` in the comment".format(key) + "Key '{}' was not found in instance.data " + "and will be rendered as '' in the comment".format(key) ) return "" else: return str(kwargs[key]) pattern = r"\{([^}]*)\}" - return re.sub(pattern, replace_missing, msg) + return re.sub(pattern, replace_missing_key, msg) def process(self, context): # Get comment text body From adc648616f2eebe7780a81de5882bf95e805ddf9 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 16 Mar 2023 10:40:03 +0100 Subject: [PATCH 438/898] Look for review in families instead of family --- openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 69b456426f5..3ad53a1f12f 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -49,7 +49,7 @@ def process(self, context): for instance in context: # Check if instance is a review by checking its family - if "review" not in instance.data["family"]: + if "review" not in instance.data["families"]: continue kitsu_task = instance.data.get("kitsu_task") From d0656e92a54e43468ab6bec24e0031a685cc9145 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov <11698866+movalex@users.noreply.github.com> Date: Thu, 16 Mar 2023 12:47:19 +0300 Subject: [PATCH 439/898] Update openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py Co-authored-by: Roy Nieterau --- openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py index 08ba9c41576..c69ac10b67f 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -46,7 +46,7 @@ def get_profile_source(self, app_version) -> Path: ).expanduser() elif platform.system() == "Linux": profile_source = Path("~/.fusion", fu_prefs_dir).expanduser() - self.log.info(f"Got Fusion prefs file: {profile_source}") + self.log.info(f"Locating source Fusion prefs directory: {profile_source}") return profile_source def get_copy_fusion_prefs_settings(self): From d0f74f134865a95c1fa1d8e6e5135f842f424509 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov <11698866+movalex@users.noreply.github.com> Date: Thu, 16 Mar 2023 12:48:04 +0300 Subject: [PATCH 440/898] Update openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py Co-authored-by: Roy Nieterau --- openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py index c69ac10b67f..ba8997fd747 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -75,7 +75,7 @@ def copy_fusion_profile( """ if copy_to.exists() and not force_sync: self.log.info( - "Local Fusion preferences folder exists, skipping profile copy" + "Destination Fusion preferences folder exists, skipping profile copy" ) return self.log.info(f"Starting copying Fusion preferences") From f96670d9dfa482174584b85f93f386aff472e841 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 16 Mar 2023 11:20:00 +0100 Subject: [PATCH 441/898] use right validation for ffmpeg executable --- openpype/lib/vendor_bin_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/lib/vendor_bin_utils.py b/openpype/lib/vendor_bin_utils.py index b6797dbba0c..00dd1955fee 100644 --- a/openpype/lib/vendor_bin_utils.py +++ b/openpype/lib/vendor_bin_utils.py @@ -375,7 +375,7 @@ def get_ffmpeg_tool_path(tool="ffmpeg"): # Look to PATH for the tool if not tool_executable_path: from_path = find_executable(tool) - if from_path and _oiio_executable_validation(from_path): + if from_path and _ffmpeg_executable_validation(from_path): tool_executable_path = from_path CachedToolPaths.cache_executable_path(tool, tool_executable_path) From 1c97ec027fcfb2991c3a38a2cde309cb13543f0d Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 16 Mar 2023 23:10:39 +0800 Subject: [PATCH 442/898] adding 3dsmax into apps_group at add_last_workfile_arg --- openpype/hooks/pre_add_last_workfile_arg.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hooks/pre_add_last_workfile_arg.py b/openpype/hooks/pre_add_last_workfile_arg.py index 1c8746c559e..2558daef303 100644 --- a/openpype/hooks/pre_add_last_workfile_arg.py +++ b/openpype/hooks/pre_add_last_workfile_arg.py @@ -14,6 +14,7 @@ class AddLastWorkfileToLaunchArgs(PreLaunchHook): # Execute after workfile template copy order = 10 app_groups = [ + "3dsmax", "maya", "nuke", "nukex", From f70eac116d1978a337c8adc912413ab5a12bd842 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 16 Mar 2023 17:11:16 +0100 Subject: [PATCH 443/898] Made the format function more logical --- .../plugins/publish/integrate_kitsu_note.py | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 3ad53a1f12f..b0063282d05 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -21,25 +21,27 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): "comment_template": "{comment}", } - def safe_format(self, msg, **kwargs): - """Pars the msg thourgh a custom format code. - It makes sure non existing keys gets None returned instead of error - """ + def format_publish_comment(self, instance): + """Format the instance's publish comment + Formats `instance.data` against the custom template. + """ + def replace_missing_key(match): """If key is not found in kwargs, set None instead""" key = match.group(1) - if key not in kwargs: + if key not in instance.data: self.log.warning( - "Key '{}' was not found in instance.data " - "and will be rendered as '' in the comment".format(key) + "Key "{}" was not found in instance.data " + "and will be rendered as "" in the comment".format(key) ) return "" else: - return str(kwargs[key]) + return str(instance.data[key]) + template = self.custom_comment_template["comment_template"] pattern = r"\{([^}]*)\}" - return re.sub(pattern, replace_missing_key, msg) + return re.sub(pattern, replace_missing_key, template) def process(self, context): # Get comment text body @@ -75,10 +77,7 @@ def process(self, context): # If custom comment, create it if self.custom_comment_template["enabled"]: - publish_comment = self.safe_format( - self.custom_comment_template["comment_template"], - **instance.data, - ) + publish_comment = self.format_publish_comment(instance) self.log.debug("Comment is `{}`".format(publish_comment)) From 5a7bf785f72d4dacbf9283ee362f447991db2de8 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Thu, 16 Mar 2023 17:13:17 +0100 Subject: [PATCH 444/898] Fixed hound comments --- .../modules/kitsu/plugins/publish/integrate_kitsu_note.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index b0063282d05..a5a58c8462c 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -26,14 +26,15 @@ def format_publish_comment(self, instance): Formats `instance.data` against the custom template. """ - + def replace_missing_key(match): """If key is not found in kwargs, set None instead""" key = match.group(1) if key not in instance.data: self.log.warning( - "Key "{}" was not found in instance.data " - "and will be rendered as "" in the comment".format(key) + "Key '{}' was not found in instance.data " + "and will be rendered as " + " in the comment".format(key) ) return "" else: From 6b67508d405b18013502396d32fbf2cba4f41ec6 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Thu, 16 Mar 2023 17:03:11 +0000 Subject: [PATCH 445/898] Update openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py Co-authored-by: Roy Nieterau --- .../hosts/maya/plugins/publish/extract_arnold_scene_source.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index 8c9d90e2e6b..54b8a005b28 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -122,9 +122,7 @@ def _extract(self, nodes, attribute_data, kwargs): with delete_after() as delete_bin: duplicate_nodes = [] for node in nodes: - parent = cmds.ls( - cmds.listRelatives(node, parent=True)[0], long=True - )[0] + parent = cmds.listRelatives(node, parent=True, fullPath=True)[0] duplicate_transform = cmds.duplicate(node)[0] duplicate_transform = "{}|{}".format( parent, duplicate_transform From b443b52d82fc5ea8246cb92e5484a31e73296016 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Thu, 16 Mar 2023 17:03:51 +0000 Subject: [PATCH 446/898] Update openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py Co-authored-by: Roy Nieterau --- .../hosts/maya/plugins/publish/extract_arnold_scene_source.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index 54b8a005b28..f672c5a94b1 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -140,8 +140,7 @@ def _extract(self, nodes, attribute_data, kwargs): )[0] basename = node.split("|")[-1].split(":")[-1] - cmds.rename(duplicate_transform, basename) - duplicate_transform = "|" + basename + duplicate_transform = cmds.rename(duplicate_transform, basename) duplicate_nodes.append(duplicate_transform) delete_bin.append(duplicate_transform) From eaac0cb2e783e259de904c67278e60cb14e0ab88 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Thu, 16 Mar 2023 17:04:12 +0000 Subject: [PATCH 447/898] Update openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py Co-authored-by: Roy Nieterau --- .../hosts/maya/plugins/publish/extract_arnold_scene_source.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index f672c5a94b1..4de0f49de10 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -148,9 +148,9 @@ def _extract(self, nodes, attribute_data, kwargs): # Copy cbId from original to mtoa_constant. attr_name = "mtoa_constant_cbId" duplicate_shapes = cmds.listRelatives( - duplicate_transform, shapes=True + duplicate_transform, shapes=True, fullPath=True ) - original_shapes = cmds.listRelatives(node, shapes=True) + original_shapes = cmds.listRelatives(node, shapes=True, fullPath=True) for duplicate_shape in duplicate_shapes: duplicate_path = ( duplicate_transform + "|" + duplicate_shape From 60de2b537fec0bb53c475854a015839b1f0836e8 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Thu, 16 Mar 2023 17:09:42 +0000 Subject: [PATCH 448/898] Update openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py Co-authored-by: Roy Nieterau --- .../publish/validate_arnold_scene_source_cbid.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py index 5d0ef798383..87c47978c84 100644 --- a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py +++ b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py @@ -37,12 +37,16 @@ def get_invalid_couples(self, instance): invalid_couples = [] for content_name, content_node in content_nodes_by_name.items(): - for proxy_name, proxy_node in proxy_nodes_by_name.items(): - if content_name == proxy_name: - content_value = cmds.getAttr(content_node + ".cbId") - proxy_value = cmds.getAttr(proxy_node + ".cbId") - if content_value != proxy_value: - invalid_couples.append((content_node, proxy_node)) + proxy_node = proxy_nodes_by_name.get(content_name, None) + + if not proxy_node: + self.log.debug("Content node '{}' has no matching proxy node.".format(content_node)) + continue + + content_id = lib.get_id(content_node) + proxy_id = lib.get_id(proxy_node) + if content_id != proxy_id: + invalid_couples.append((content_node, proxy_node)) return invalid_couples From e599dcda0d5cee6f91239201dda6a2febb509888 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Thu, 16 Mar 2023 17:11:54 +0000 Subject: [PATCH 449/898] Update openpype/hosts/maya/tools/mayalookassigner/commands.py Co-authored-by: Roy Nieterau --- openpype/hosts/maya/tools/mayalookassigner/commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/tools/mayalookassigner/commands.py b/openpype/hosts/maya/tools/mayalookassigner/commands.py index c22a8c92111..d7061f12e1e 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/commands.py +++ b/openpype/hosts/maya/tools/mayalookassigner/commands.py @@ -108,7 +108,7 @@ def create_asset_id_hash(nodes): """ node_id_hash = defaultdict(list) for node in nodes: - shapes = cmds.ls(cmds.listRelatives(node, shapes=True), long=True) + shapes = cmds.listRelatives(node, shapes=True, fullPath=True) # iterate over content of reference node if cmds.nodeType(node) == "reference": ref_hashes = create_asset_id_hash( From d22e0bb6fa27b719b34efc4b14adf1919457aa10 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 16 Mar 2023 17:29:08 +0000 Subject: [PATCH 450/898] setMembers > contentMembers --- .../maya/plugins/publish/collect_arnold_scene_source.py | 4 ++-- .../maya/plugins/publish/extract_arnold_scene_source.py | 2 +- .../maya/plugins/publish/validate_arnold_scene_source.py | 6 +++--- .../plugins/publish/validate_arnold_scene_source_cbid.py | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/collect_arnold_scene_source.py index fd4993d09ea..ab15d0419fe 100644 --- a/openpype/hosts/maya/plugins/publish/collect_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/collect_arnold_scene_source.py @@ -23,7 +23,7 @@ def process(self, instance): continue if objset.endswith("content_SET"): set_members = get_all_children(cmds.ls(members, long=True)) - instance.data["setMembers"] = set_members + instance.data["contentMembers"] = set_members self.log.debug("content members: {}".format(set_members)) elif objset.endswith("proxy_SET"): set_members = get_all_children(cmds.ls(members, long=True)) @@ -35,7 +35,7 @@ def process(self, instance): cameras = cmds.ls(type="camera", long=True) renderable = [c for c in cameras if cmds.getAttr("%s.renderable" % c)] camera = renderable[0] - for node in instance.data["setMembers"]: + for node in instance.data["contentMembers"]: camera_shapes = cmds.listRelatives( node, shapes=True, type="camera" ) diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index 4de0f49de10..0325c2518ea 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -72,7 +72,7 @@ def process(self, instance): } filenames = self._extract( - instance.data["setMembers"], attribute_data, kwargs + instance.data["contentMembers"], attribute_data, kwargs ) if "representations" not in instance.data: diff --git a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py index e582560e123..2a7eabe2853 100644 --- a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py @@ -43,7 +43,7 @@ def process(self, instance): ungrouped_nodes = [] nodes, content_nodes_by_name, content_parents = self._get_nodes_data( - instance.data["setMembers"] + instance.data["contentMembers"] ) ungrouped_nodes.extend(nodes) @@ -64,11 +64,11 @@ def process(self, instance): return # Validate for content and proxy nodes amount being the same. - if len(instance.data["setMembers"]) != len(instance.data["proxy"]): + if len(instance.data["contentMembers"]) != len(instance.data["proxy"]): raise PublishValidationError( "Amount of content nodes ({}) and proxy nodes ({}) needs to " "be the same.".format( - len(instance.data["setMembers"]), + len(instance.data["contentMembers"]), len(instance.data["proxy"]) ) ) diff --git a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py index 87c47978c84..0cc2b482e47 100644 --- a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py +++ b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py @@ -29,7 +29,7 @@ def _get_nodes_data(nodes): def get_invalid_couples(self, instance): content_nodes_by_name = self._get_nodes_data( - instance.data["setMembers"] + instance.data["contentMembers"] ) proxy_nodes_by_name = self._get_nodes_data( instance.data.get("proxy", []) From 1e3862ca7a9aacc6d8e7d27602919a48146a813e Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 16 Mar 2023 17:40:57 +0000 Subject: [PATCH 451/898] Copy cbid from duplicated nodes. --- .../publish/extract_arnold_scene_source.py | 38 ++++--------------- 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index 0325c2518ea..1678f976270 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -4,9 +4,7 @@ import arnold from openpype.pipeline import publish -from openpype.hosts.maya.api.lib import ( - maintained_selection, attribute_values, delete_after -) +from openpype.hosts.maya.api import lib class ExtractArnoldSceneSource(publish.Extractor): @@ -119,7 +117,7 @@ def _extract(self, nodes, attribute_data, kwargs): filenames = [] # Duplicating nodes so they are direct children of the world. This # makes the hierarchy of any exported ass file the same. - with delete_after() as delete_bin: + with lib.delete_after() as delete_bin: duplicate_nodes = [] for node in nodes: parent = cmds.listRelatives(node, parent=True, fullPath=True)[0] @@ -145,32 +143,12 @@ def _extract(self, nodes, attribute_data, kwargs): duplicate_nodes.append(duplicate_transform) delete_bin.append(duplicate_transform) - # Copy cbId from original to mtoa_constant. - attr_name = "mtoa_constant_cbId" - duplicate_shapes = cmds.listRelatives( - duplicate_transform, shapes=True, fullPath=True - ) - original_shapes = cmds.listRelatives(node, shapes=True, fullPath=True) - for duplicate_shape in duplicate_shapes: - duplicate_path = ( - duplicate_transform + "|" + duplicate_shape - ) - for original_shape in original_shapes: - original_path = node + "|" + original_shape - if duplicate_shape == original_shape: - cmds.addAttr( - duplicate_path, - longName=attr_name, - dataType="string" - ) - cmds.setAttr( - duplicate_path + "." + attr_name, - cmds.getAttr(original_path + ".cbId"), - type="string" - ) - - with attribute_values(attribute_data): - with maintained_selection(): + # Copy cbId to mtoa_constant. + for node in duplicate_nodes: + lib.set_attribute("mtoa_constant_cbId", lib.get_id(node)) + + with lib.attribute_values(attribute_data): + with lib.maintained_selection(): self.log.info( "Writing: {}".format(duplicate_nodes) ) From 3396784820145e0656b6905b4f5e99697e9f9994 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Thu, 16 Mar 2023 21:32:48 +0300 Subject: [PATCH 452/898] use dictionary to store fusion versions and variables --- openpype/hosts/fusion/__init__.py | 6 ++-- openpype/hosts/fusion/addon.py | 50 +++++++++++++++++-------------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/openpype/hosts/fusion/__init__.py b/openpype/hosts/fusion/__init__.py index f0e7843fffd..1da11ba9d13 100644 --- a/openpype/hosts/fusion/__init__.py +++ b/openpype/hosts/fusion/__init__.py @@ -1,12 +1,14 @@ from .addon import ( - get_fusion_profile_number, + get_fusion_version, FusionAddon, FUSION_HOST_DIR, + FUSION_VERSIONS_DICT, ) __all__ = ( - "get_fusion_profile_number", + "get_fusion_version", "FusionAddon", "FUSION_HOST_DIR", + "FUSION_VERSIONS_DICT", ) diff --git a/openpype/hosts/fusion/addon.py b/openpype/hosts/fusion/addon.py index cb4dc764813..2ea16e0d6bf 100644 --- a/openpype/hosts/fusion/addon.py +++ b/openpype/hosts/fusion/addon.py @@ -4,24 +4,29 @@ from openpype.lib import Logger FUSION_HOST_DIR = os.path.dirname(os.path.abspath(__file__)) -FUSION16_PROFILE_VERSIONS = (16, 17, 18) -FUSION9_PROFILE_VERSION = 9 +# FUSION_VERSIONS_DICT is used by the pre-launch hooks +# The keys correspond to all currently supported Fusion versions +# Values is the list of corresponding python_home variables and a profile +# number, which is used to specify pufion profile derectory variable. +FUSION_VERSIONS_DICT = { + 9: ["FUSION_PYTHON36_HOME", 9], + 16: ["FUSION16_PYTHON36_HOME", 16], + 17: ["FUSION16_PYTHON36_HOME", 16], + 18: ["FUSION_PYTHON3_HOME", 16], +} -def get_fusion_profile_number(module: str, app_data: str) -> int: + +def get_fusion_version(app_data): """ - FUSION_PROFILE_VERSION variable is used by the pre-launch hooks. - Since Fusion v16, the profile folder variable became version-specific, - but then it was abandoned by BlackmagicDesign devs, and now, despite it is - already Fusion version 18, still FUSION16_PROFILE_DIR is used. - The variable is added in case the version number will be - updated or deleted so we could easily change the version or disable it. + The function is triggered by the prelaunch hooks to get the fusion version. - Currently valid Fusion versions are stored in FUSION16_PROFILE_VERSIONS + `app_data` is obtained by prelaunch hooks from the + `launch_context.env.get("AVALON_APP_NAME")`. - app_data derives from `launch_context.env.get("AVALON_APP_NAME")`. - For the time being we will encourage user to set a version number - set in the system settings key for the Blackmagic Fusion. + To get a correct Fusion version, a version number should be present + in the `applications/fusion/variants` key + int the Blackmagic Fusion Application Settings. """ log = Logger.get_logger(__name__) @@ -29,17 +34,16 @@ def get_fusion_profile_number(module: str, app_data: str) -> int: if not app_data: return - try: - app_version = re.search(r"fusion/(\d+)", app_data).group(1) - log.debug(f"{module} found Fusion profile version: {app_version}") - if app_version in map(str, FUSION16_PROFILE_VERSIONS): - return 16 - elif app_version == str(FUSION9_PROFILE_VERSION): - return 9 + app_version_candidates = re.findall("\d+", app_data) + for app_version in app_version_candidates: + if int(app_version) in FUSION_VERSIONS_DICT: + return int(app_version) else: - log.info(f"Found unsupported Fusion version: {app_version}") - except AttributeError: - log.info("Fusion version was not found in the AVALON_APP_NAME data") + log.info( + "Unsupported Fusion version: {app_version}".format( + app_version=app_version + ) + ) class FusionAddon(OpenPypeModule, IHostAddon): From e61ec028e24f5e0dfcceb3de1902c03f66c8edd7 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Thu, 16 Mar 2023 21:33:11 +0300 Subject: [PATCH 453/898] delete unused module --- openpype/hosts/fusion/api/workio.py | 38 ----------------------------- 1 file changed, 38 deletions(-) delete mode 100644 openpype/hosts/fusion/api/workio.py diff --git a/openpype/hosts/fusion/api/workio.py b/openpype/hosts/fusion/api/workio.py deleted file mode 100644 index fa4b62c1236..00000000000 --- a/openpype/hosts/fusion/api/workio.py +++ /dev/null @@ -1,38 +0,0 @@ -"""Host API required Work Files tool""" -import os - -from .lib import get_fusion_module, get_current_comp - - -def file_extensions(): - return [".comp"] - - -def has_unsaved_changes(): - comp = get_current_comp() - return comp.GetAttrs()["COMPB_Modified"] - - -def save_file(filepath): - comp = get_current_comp() - comp.Save(filepath) - - -def open_file(filepath): - fusion = get_fusion_module() - return fusion.LoadComp(filepath) - - -def current_file(): - comp = get_current_comp() - current_filepath = comp.GetAttrs()["COMPS_FileName"] - return current_filepath or None - - -def work_root(session): - work_dir = session["AVALON_WORKDIR"] - scene_dir = session.get("AVALON_SCENEDIR") - if scene_dir: - return os.path.join(work_dir, scene_dir) - else: - return work_dir From 502198d00b4420d766a4a87c6f71c63d7e35ebf8 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Thu, 16 Mar 2023 21:53:12 +0300 Subject: [PATCH 454/898] update fusion hooks to get correct version and variables --- .../fusion/hooks/pre_fusion_profile_hook.py | 61 +++++++++++++------ .../hosts/fusion/hooks/pre_fusion_setup.py | 38 +++++------- 2 files changed, 56 insertions(+), 43 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py index ba8997fd747..b6ddacb5718 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -3,24 +3,38 @@ import platform from pathlib import Path from openpype.lib import PreLaunchHook -from openpype.hosts.fusion import FUSION_HOST_DIR, get_fusion_profile_number +from openpype.hosts.fusion import ( + FUSION_HOST_DIR, + FUSION_VERSIONS_DICT, + get_fusion_version, +) class FusionCopyPrefsPrelaunch(PreLaunchHook): - """Prepares local Fusion profile directory, copies existing Fusion profile + """ + Prepares local Fusion profile directory, copies existing Fusion profile. + This also sets FUSION MasterPrefs variable, which is used + to apply Master.prefs file to override some Fusion profile settings to: + - enable the OpenPype menu + - force Python 3 over Python 2 + - force English interface + - force grey color scheme (because it is better that the purple one!) + Master.prefs is defined in openpype/hosts/fusion/deploy/fusion_shared.prefs """ app_groups = ["fusion"] order = 2 - def get_fusion_profile_name(self, app_version) -> str: + def get_fusion_profile_name(self, profile_version) -> str: # Returns 'Default', unless FUSION16_PROFILE is set - return os.getenv(f"FUSION{app_version}_PROFILE", "Default") + return os.getenv(f"FUSION{profile_version}_PROFILE", "Default") - def check_profile_variable(self, app_version) -> Path: + def get_fusion_profile_dir(self, profile_version) -> Path: # Get FUSION_PROFILE_DIR variable - fusion_profile = self.get_fusion_profile_name(app_version) - fusion_var_prefs_dir = os.getenv(f"FUSION{app_version}_PROFILE_DIR") + fusion_profile = self.get_fusion_profile_name(profile_version) + fusion_var_prefs_dir = os.getenv( + f"FUSION{profile_version}_PROFILE_DIR" + ) # Check if FUSION_PROFILE_DIR exists if fusion_var_prefs_dir and Path(fusion_var_prefs_dir).is_dir(): @@ -28,12 +42,12 @@ def check_profile_variable(self, app_version) -> Path: self.log.info(f"{fusion_var_prefs_dir} is set to {fu_prefs_dir}") return fu_prefs_dir - def get_profile_source(self, app_version) -> Path: + def get_profile_source(self, profile_version) -> Path: """Get Fusion preferences profile location. See Per-User_Preferences_and_Paths on VFXpedia for reference. """ - fusion_profile = self.get_fusion_profile_name(app_version) - profile_source = self.check_profile_variable(app_version) + fusion_profile = self.get_fusion_profile_name(profile_version) + profile_source = self.get_fusion_profile_dir(profile_version) if profile_source: return profile_source # otherwise get default location of the profile folder @@ -46,7 +60,9 @@ def get_profile_source(self, app_version) -> Path: ).expanduser() elif platform.system() == "Linux": profile_source = Path("~/.fusion", fu_prefs_dir).expanduser() - self.log.info(f"Locating source Fusion prefs directory: {profile_source}") + self.log.info( + f"Locating source Fusion prefs directory: {profile_source}" + ) return profile_source def get_copy_fusion_prefs_settings(self): @@ -82,14 +98,20 @@ def copy_fusion_profile( self.log.info(f"force_sync option is set to {force_sync}") try: copy_to.mkdir(exist_ok=True, parents=True) - except Exception: - self.log.warn(f"Could not create folder at {copy_to}") + except PermissionError: + self.log.warn(f"Creating the folder not permitted at {copy_to}") return if not copy_from.exists(): self.log.warning(f"Fusion preferences not found in {copy_from}") return for file in copy_from.iterdir(): - if file.suffix in (".prefs", ".def", ".blocklist", ".fu"): + if file.suffix in ( + ".prefs", + ".def", + ".blocklist", + ".fu", + ".toolbars", + ): # convert Path to str to be compatible with Python 3.6+ shutil.copy(str(file), str(copy_to)) self.log.info( @@ -105,25 +127,26 @@ def execute(self): # Get launched application context and return correct app version app_data = self.launch_context.env.get("AVALON_APP_NAME") - app_version = get_fusion_profile_number(__name__, app_data) - fu_profile = self.get_fusion_profile_name(app_version) + app_version = get_fusion_version(app_data) + _, profile_version = FUSION_VERSIONS_DICT[app_version] + fu_profile = self.get_fusion_profile_name(profile_version) # do a copy of Fusion profile if copy_status toggle is enabled if copy_status and fu_profile_dir is not None: - profile_source = self.get_profile_source(app_version) + profile_source = self.get_profile_source(profile_version) dest_folder = Path(fu_profile_dir, fu_profile) self.copy_fusion_profile(profile_source, dest_folder, force_sync) # Add temporary profile directory variables to customize Fusion # to define where it can read custom scripts and tools from - fu_profile_dir_variable = f"FUSION{app_version}_PROFILE_DIR" + fu_profile_dir_variable = f"FUSION{profile_version}_PROFILE_DIR" self.log.info(f"Setting {fu_profile_dir_variable}: {fu_profile_dir}") self.launch_context.env[fu_profile_dir_variable] = str(fu_profile_dir) # Add custom Fusion Master Prefs and the temporary # profile directory variables to customize Fusion # to define where it can read custom scripts and tools from - master_prefs_variable = f"FUSION{app_version}_MasterPrefs" + master_prefs_variable = f"FUSION{profile_version}_MasterPrefs" master_prefs = Path(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") self.log.info(f"Setting {master_prefs_variable}: {master_prefs}") self.launch_context.env[master_prefs_variable] = str(master_prefs) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index b9f568bad25..a014268c8f5 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -2,20 +2,19 @@ from openpype.lib import PreLaunchHook, ApplicationLaunchFailed from openpype.hosts.fusion import ( FUSION_HOST_DIR, - get_fusion_profile_number, + FUSION_VERSIONS_DICT, + get_fusion_version, ) class FusionPrelaunch(PreLaunchHook): - """Prepares OpenPype Fusion environment - - Requires FUSION_PYTHON3_HOME to be defined in the environment for Fusion - to point at a valid Python 3 build for Fusion. That is Python 3.3-3.10 - for Fusion 18 and Fusion 3.6 for Fusion 16 and 17. - - This also sets FUSION16_MasterPrefs to apply the fusion master prefs - as set in openpype/hosts/fusion/deploy/fusion_shared.prefs to enable - the OpenPype menu and force Python 3 over Python 2. + """ + Prepares OpenPype Fusion environment. + Requires correct Python home variable to be defined in the environment + settings for Fusion to point at a valid Python 3 build for Fusion. + Python3 versions that are supported by Fusion: + Fusion 9, 16, 17 : Python 3.6 + Fusion 18 : Python 3.6 - 3.10 """ app_groups = ["fusion"] @@ -25,15 +24,14 @@ def execute(self): # making sure python 3 is installed at provided path # Py 3.3-3.10 for Fusion 18+ or Py 3.6 for Fu 16-17 app_data = self.launch_context.env.get("AVALON_APP_NAME") - app_version = get_fusion_profile_number(__name__, app_data) + app_version = get_fusion_version(app_data) if not app_version: raise ApplicationLaunchFailed( "Fusion version information not found in System settings.\n" "The key field in the 'applications/fusion/variants' " "should consist a number, corresponding to the Fusion version" ) - - py3_var = "FUSION_PYTHON3_HOME" + py3_var, _ = FUSION_VERSIONS_DICT[app_version] fusion_python3_home = self.launch_context.env.get(py3_var, "") for path in fusion_python3_home.split(os.pathsep): @@ -42,7 +40,6 @@ def execute(self): # But make to set only a single path as final variable. py3_dir = os.path.normpath(path) if os.path.isdir(py3_dir): - self.log.info(f"Looking for Python 3 in: {py3_dir}") break else: raise ApplicationLaunchFailed( @@ -57,17 +54,10 @@ def execute(self): self.launch_context.env[py3_var] = py3_dir # Fusion 18+ requires FUSION_PYTHON3_HOME to also be on PATH - self.launch_context.env["PATH"] += ";" + py3_dir + if app_version > 17: + self.launch_context.env["PATH"] += ";" + py3_dir - # Fusion 16 and 17 use FUSION16_PYTHON36_HOME instead of - # FUSION_PYTHON3_HOME and will only work with a Python 3.6 version - # TODO: Detect Fusion version to only set for specific Fusion build - if app_version == 9: - self.launch_context.env[f"FUSION_PYTHON36_HOME"] = py3_dir - elif app_version == 16: - self.launch_context.env[ - f"FUSION{app_version}_PYTHON36_HOME" - ] = py3_dir + self.launch_context.env[py3_var] = py3_dir self.log.info(f"Setting OPENPYPE_FUSION: {FUSION_HOST_DIR}") self.launch_context.env["OPENPYPE_FUSION"] = FUSION_HOST_DIR From 4d252b698af788f22fd18607289991fc6cac9d48 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Thu, 16 Mar 2023 21:54:45 +0300 Subject: [PATCH 455/898] fix regex escape sequence --- openpype/hosts/fusion/addon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/addon.py b/openpype/hosts/fusion/addon.py index 2ea16e0d6bf..0eb7e09003f 100644 --- a/openpype/hosts/fusion/addon.py +++ b/openpype/hosts/fusion/addon.py @@ -34,7 +34,7 @@ def get_fusion_version(app_data): if not app_data: return - app_version_candidates = re.findall("\d+", app_data) + app_version_candidates = re.findall(r"\d+", app_data) for app_version in app_version_candidates: if int(app_version) in FUSION_VERSIONS_DICT: return int(app_version) From 5ebdbcf2d284ec7c02f58454e81c998f64b423e2 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Thu, 16 Mar 2023 21:55:58 +0300 Subject: [PATCH 456/898] remove whitespaces --- openpype/hosts/fusion/hooks/pre_fusion_setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index a014268c8f5..a337a4245e2 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -10,11 +10,11 @@ class FusionPrelaunch(PreLaunchHook): """ Prepares OpenPype Fusion environment. - Requires correct Python home variable to be defined in the environment + Requires correct Python home variable to be defined in the environment settings for Fusion to point at a valid Python 3 build for Fusion. Python3 versions that are supported by Fusion: Fusion 9, 16, 17 : Python 3.6 - Fusion 18 : Python 3.6 - 3.10 + Fusion 18 : Python 3.6 - 3.10 """ app_groups = ["fusion"] From dacd50061b602d73ede815cb46e1c656fe41dc9d Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Thu, 16 Mar 2023 22:19:46 +0300 Subject: [PATCH 457/898] fix line length --- openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py index b6ddacb5718..6e7d2558fdb 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -91,7 +91,7 @@ def copy_fusion_profile( """ if copy_to.exists() and not force_sync: self.log.info( - "Destination Fusion preferences folder exists, skipping profile copy" + "Destination Fusion preferences folder already exists" ) return self.log.info(f"Starting copying Fusion preferences") From 30d38ab3d1da328551a52c9ae47391af4b49ada6 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Thu, 16 Mar 2023 22:21:02 +0300 Subject: [PATCH 458/898] fix typo, early check if no fusion version found --- openpype/hosts/fusion/addon.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/addon.py b/openpype/hosts/fusion/addon.py index 0eb7e09003f..73142671241 100644 --- a/openpype/hosts/fusion/addon.py +++ b/openpype/hosts/fusion/addon.py @@ -26,7 +26,7 @@ def get_fusion_version(app_data): To get a correct Fusion version, a version number should be present in the `applications/fusion/variants` key - int the Blackmagic Fusion Application Settings. + of the Blackmagic Fusion Application Settings. """ log = Logger.get_logger(__name__) @@ -35,6 +35,8 @@ def get_fusion_version(app_data): return app_version_candidates = re.findall(r"\d+", app_data) + if not app_version_candidates: + return for app_version in app_version_candidates: if int(app_version) in FUSION_VERSIONS_DICT: return int(app_version) From 316c3577c6143aab061677fbf643340ed2d6c1e6 Mon Sep 17 00:00:00 2001 From: Joseff Date: Thu, 16 Mar 2023 20:35:21 +0100 Subject: [PATCH 459/898] Fixed a bug where the QThread in the splash screen could be destroyed before finishing execution --- openpype/hosts/unreal/ue_workers.py | 42 ++++++++++++++++++++++++++--- openpype/widgets/splash_screen.py | 7 +++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/unreal/ue_workers.py b/openpype/hosts/unreal/ue_workers.py index 00f83a7d7a4..f7bc0e90dca 100644 --- a/openpype/hosts/unreal/ue_workers.py +++ b/openpype/hosts/unreal/ue_workers.py @@ -28,6 +28,15 @@ def parse_prj_progress(line: str, progress_signal: QtCore.Signal(int)) -> int: progress_signal.emit(int(percent_match.group())) +def retrieve_exit_code(line: str): + match = re.search('ExitCode=\d+', line) + if match is not None: + split: list[str] = match.group().split('=') + return int(split[1]) + + return None + + class UEProjectGenerationWorker(QtCore.QObject): finished = QtCore.Signal(str) failed = QtCore.Signal(str) @@ -225,9 +234,30 @@ def run(self): msg = f"Unreal Python not found at {python_path}" self.failed.emit(msg, 1) raise RuntimeError(msg) - subprocess.check_call( - [python_path.as_posix(), "-m", "pip", "install", "pyside2"] - ) + pyside_cmd = [python_path.as_posix(), + "-m", + "pip", + "install", + "pyside2"] + + pyside_install = subprocess.Popen(pyside_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + + for line in pyside_install.stdout: + decoded_line: str = line.decode(errors='replace') + print(decoded_line, end='') + self.log.emit(decoded_line) + + pyside_install.stdout.close() + return_code = pyside_install.wait() + + if return_code and return_code != 0: + msg = 'Failed to create the project! ' \ + f'The installation of PySide2 has failed!' + self.failed.emit(msg, return_code) + raise RuntimeError(msg) + self.progress.emit(100) self.finished.emit("Project successfully built!") @@ -274,18 +304,22 @@ def _build_and_move_plugin(self, plugin_build_path: Path): build_proc = subprocess.Popen(build_plugin_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return_code: int = None for line in build_proc.stdout: decoded_line: str = line.decode(errors='replace') print(decoded_line, end='') self.log.emit(decoded_line) + if return_code is None: + return_code = retrieve_exit_code(decoded_line) parse_comp_progress(decoded_line, self.progress) build_proc.stdout.close() - return_code = build_proc.wait() + build_proc.wait() if return_code and return_code != 0: msg = 'Failed to build plugin' \ f' project! Exited with return code {return_code}' + dir_util.remove_tree(temp_dir.as_posix()) self.failed.emit(msg, return_code) raise RuntimeError(msg) diff --git a/openpype/widgets/splash_screen.py b/openpype/widgets/splash_screen.py index fffe143ea5a..6bb0944c469 100644 --- a/openpype/widgets/splash_screen.py +++ b/openpype/widgets/splash_screen.py @@ -80,8 +80,14 @@ def quit_and_close(self): """ self.thread_return_code = 0 self.q_thread.quit() + + if not self.q_thread.wait(5000): + raise RuntimeError("Failed to quit the QThread! " + "The deadline has been reached! The thread " + "has not finished it's execution!.") self.close() + @QtCore.Slot() def toggle_log(self): if self.is_log_visible: @@ -256,3 +262,4 @@ def fail(self, text: str, return_code: int = 1): self.close_btn.show() self.thread_return_code = return_code self.q_thread.exit(return_code) + self.q_thread.wait() From 97af187f8077d987851b121b02e50dc8a351caa6 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Thu, 16 Mar 2023 22:46:20 +0300 Subject: [PATCH 460/898] catch typos, update comment --- openpype/hosts/fusion/addon.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/addon.py b/openpype/hosts/fusion/addon.py index 73142671241..e7c7a03fa2c 100644 --- a/openpype/hosts/fusion/addon.py +++ b/openpype/hosts/fusion/addon.py @@ -7,8 +7,8 @@ # FUSION_VERSIONS_DICT is used by the pre-launch hooks # The keys correspond to all currently supported Fusion versions -# Values is the list of corresponding python_home variables and a profile -# number, which is used to specify pufion profile derectory variable. +# Each value is a list of corresponding Python home variables and a profile +# number, which is used by the profile hook to set Fusion profile variables. FUSION_VERSIONS_DICT = { 9: ["FUSION_PYTHON36_HOME", 9], 16: ["FUSION16_PYTHON36_HOME", 16], From 3c3722d4082417bb3a2605cf2af4ee9a0448f299 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Fri, 17 Mar 2023 00:30:25 +0300 Subject: [PATCH 461/898] use os.pathsep to build the PATH variable --- openpype/hosts/fusion/hooks/pre_fusion_setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index a337a4245e2..64c498dd014 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -54,8 +54,8 @@ def execute(self): self.launch_context.env[py3_var] = py3_dir # Fusion 18+ requires FUSION_PYTHON3_HOME to also be on PATH - if app_version > 17: - self.launch_context.env["PATH"] += ";" + py3_dir + if app_version >= 18: + self.launch_context.env["PATH"] += os.pathsep + py3_dir self.launch_context.env[py3_var] = py3_dir From fcb723068336eca63635b231cdbd6e7760182981 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Fri, 17 Mar 2023 00:57:47 +0300 Subject: [PATCH 462/898] use immutable values --- openpype/hosts/fusion/addon.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/fusion/addon.py b/openpype/hosts/fusion/addon.py index e7c7a03fa2c..345e348c3b7 100644 --- a/openpype/hosts/fusion/addon.py +++ b/openpype/hosts/fusion/addon.py @@ -10,10 +10,10 @@ # Each value is a list of corresponding Python home variables and a profile # number, which is used by the profile hook to set Fusion profile variables. FUSION_VERSIONS_DICT = { - 9: ["FUSION_PYTHON36_HOME", 9], - 16: ["FUSION16_PYTHON36_HOME", 16], - 17: ["FUSION16_PYTHON36_HOME", 16], - 18: ["FUSION_PYTHON3_HOME", 16], + 9: ("FUSION_PYTHON36_HOME", 9), + 16: ("FUSION16_PYTHON36_HOME", 16), + 17: ("FUSION16_PYTHON36_HOME", 16), + 18: ("FUSION_PYTHON3_HOME", 16), } From d299824e219a41dc2043925916d20c90ab633d32 Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Fri, 17 Mar 2023 01:02:51 +0300 Subject: [PATCH 463/898] ok, do not force grey interface in masterprefs (purple is still bad!) --- openpype/hosts/fusion/deploy/fusion_shared.prefs | 1 - openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py | 1 - 2 files changed, 2 deletions(-) diff --git a/openpype/hosts/fusion/deploy/fusion_shared.prefs b/openpype/hosts/fusion/deploy/fusion_shared.prefs index 17ac3ad37a2..b379ea7c660 100644 --- a/openpype/hosts/fusion/deploy/fusion_shared.prefs +++ b/openpype/hosts/fusion/deploy/fusion_shared.prefs @@ -13,7 +13,6 @@ Global = { Python3Forced = true }, UserInterface = { - Skin = "Neutral", Language = "en_US" }, }, diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py index 6e7d2558fdb..15c9424990a 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -18,7 +18,6 @@ class FusionCopyPrefsPrelaunch(PreLaunchHook): - enable the OpenPype menu - force Python 3 over Python 2 - force English interface - - force grey color scheme (because it is better that the purple one!) Master.prefs is defined in openpype/hosts/fusion/deploy/fusion_shared.prefs """ From 3b62d0f4a7dfba155d588cfa3c40e6fe5075a61a Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Fri, 17 Mar 2023 01:03:22 +0300 Subject: [PATCH 464/898] clarify the error message --- openpype/hosts/fusion/hooks/pre_fusion_setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index 64c498dd014..f27cd1674ba 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -28,8 +28,8 @@ def execute(self): if not app_version: raise ApplicationLaunchFailed( "Fusion version information not found in System settings.\n" - "The key field in the 'applications/fusion/variants' " - "should consist a number, corresponding to the Fusion version" + "The key field in the 'applications/fusion/variants' should " + "consist a number, corresponding to major Fusion version." ) py3_var, _ = FUSION_VERSIONS_DICT[app_version] fusion_python3_home = self.launch_context.env.get(py3_var, "") From bec46399857dd13cf482dc28688a1ffec9a15dac Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov Date: Fri, 17 Mar 2023 01:14:39 +0300 Subject: [PATCH 465/898] revert change --- openpype/hosts/fusion/hooks/pre_fusion_ocio_hook.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_ocio_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_ocio_hook.py index 47645b7e3f0..6bf0f55081b 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_ocio_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_ocio_hook.py @@ -7,7 +7,6 @@ class FusionPreLaunchOCIO(PreLaunchHook): """Set OCIO environment variable for Fusion""" app_groups = ["fusion"] - order = 3 def execute(self): """Hook entry method.""" From caf101bd7d461e9616904c17ec19e1540d18187b Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 17 Mar 2023 07:26:57 +0000 Subject: [PATCH 466/898] rsplit instead of split --- .../maya/plugins/publish/validate_arnold_scene_source_cbid.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py index 0cc2b482e47..457c3b7d52f 100644 --- a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py +++ b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py @@ -22,8 +22,8 @@ class ValidateArnoldSceneSourceCbid(pyblish.api.InstancePlugin): def _get_nodes_data(nodes): nodes_by_name = {} for node in nodes: - node_split = node.split("|") - nodes_by_name[node_split[-1].split(":")[-1]] = node + node_name = node.rsplit("|", 1)[-1].rsplit(":", 1)[-1] + nodes_by_name[node_name] = node return nodes_by_name From baf60646730e34d8d9965472b8923d71144e1d30 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 17 Mar 2023 07:39:08 +0000 Subject: [PATCH 467/898] Validate against same named nodes in different hierarchies. --- .../publish/validate_arnold_scene_source.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py index 2a7eabe2853..8f443f6963c 100644 --- a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py @@ -26,6 +26,7 @@ def _get_nodes_data(self, nodes): ungrouped_nodes = [] nodes_by_name = {} parents = [] + same_named_nodes = [] for node in nodes: node_split = node.split("|") if len(node_split) == 2: @@ -35,7 +36,21 @@ def _get_nodes_data(self, nodes): if parent: parents.append(parent) - nodes_by_name[node_split[-1].split(":")[-1]] = node + node_name = node.rsplit("|", 1)[-1].rsplit(":", 1)[-1] + + # Check for same same nodes, which can happen in different + # hierarchies. + if node_name in nodes_by_name: + same_named_nodes.append((node, nodes_by_name[node_name])) + + nodes_by_name[node_name] = node + + if same_named_nodes: + raise PublishValidationError( + "Found nodes with the same name:\n{}".format( + "\n".join(["{}".format(n) for n in same_named_nodes]) + ) + ) return ungrouped_nodes, nodes_by_name, parents From 1048f58db3c72b2e061f0f6091143e210d13b3c0 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 17 Mar 2023 07:43:11 +0000 Subject: [PATCH 468/898] Use set_id and get_id --- .../plugins/publish/validate_arnold_scene_source_cbid.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py index 457c3b7d52f..ad174404dc7 100644 --- a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py +++ b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py @@ -67,8 +67,4 @@ def process(self, instance): @classmethod def repair(cls, instance): for content_node, proxy_node in cls.get_invalid_couples(cls, instance): - cmds.setAttr( - proxy_node + ".cbId", - cmds.getAttr(content_node + ".cbId"), - type="string" - ) + lib.set_id(proxy_node, lib.get_id(content_node), overwrite=False) From 214b76796c70aa1bb6608bb4f8510fcaba0e015f Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 17 Mar 2023 07:47:19 +0000 Subject: [PATCH 469/898] Failsafe for mtoa not loaded and user feedback. --- .../hosts/maya/tools/mayalookassigner/app.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/maya/tools/mayalookassigner/app.py b/openpype/hosts/maya/tools/mayalookassigner/app.py index e66f0d73e2d..2a8775fff6f 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/app.py +++ b/openpype/hosts/maya/tools/mayalookassigner/app.py @@ -251,12 +251,23 @@ def on_process_selected(self): vrayproxy_assign_look(vp, subset_name) nodes = list(set(item["nodes"]).difference(vray_proxies)) + else: + self.echo( + "Could not assign to VRayProxy because vrayformaya plugin " + "is not loaded." + ) # Assign Arnold Standin look. - arnold_standins = set(cmds.ls(type="aiStandIn", long=True)) - for standin in arnold_standins: - if standin in nodes: - arnold_standin.assign_look(standin, subset_name) + if cmds.pluginInfo("mtoa", query=True, loaded=True): + arnold_standins = set(cmds.ls(type="aiStandIn", long=True)) + for standin in arnold_standins: + if standin in nodes: + arnold_standin.assign_look(standin, subset_name) + else: + self.echo( + "Could not assign to aiStandIn because mtoa plugin is not " + "loaded." + ) nodes = list(set(item["nodes"]).difference(arnold_standins)) From 14bd9b86b91876cb3be5d1c9d713b7a92931da80 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Fri, 17 Mar 2023 07:48:17 +0000 Subject: [PATCH 470/898] Update openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py Co-authored-by: Roy Nieterau --- .../tools/mayalookassigner/arnold_standin.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py index 7d3b7e59b3e..d4f93aeca6a 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py +++ b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py @@ -189,16 +189,16 @@ def assign_look(standin, subset): continue shading_engine_assignments( - edit["shader"], - "surfaceShader", - edit["nodes"], - node_assignments + shading_engine=edit["shader"], + attr="surfaceShader", + nodes=edit["nodes"], + assignments=node_assignments ) shading_engine_assignments( - edit["shader"], - "displacementShader", - edit["nodes"], - node_assignments + shading_engine=edit["shader"], + attr="displacementShader", + nodes=edit["nodes"], + assignments=node_assignments ) if edit["action"] == "setattr": From 54af7a82d5142d3f52575d7e86be3a827c450404 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 17 Mar 2023 07:49:48 +0000 Subject: [PATCH 471/898] attr > attribute --- .../maya/tools/mayalookassigner/arnold_standin.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py index d4f93aeca6a..4f85d151089 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py +++ b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py @@ -109,13 +109,13 @@ def get_standin_path(node): return path -def shading_engine_assignments(shading_engine, attr, nodes, assignments): +def shading_engine_assignments(shading_engine, attribute, nodes, assignments): shader_inputs = cmds.listConnections( - shading_engine + "." + attr, source=True) + shading_engine + "." + attribute, source=True) if not shader_inputs: log.info( "Shading engine \"{}\" missing input \"{}\"".format( - shading_engine, attr + shading_engine, attribute ) ) @@ -128,7 +128,7 @@ def shading_engine_assignments(shading_engine, attr, nodes, assignments): "{}").format(node)) nodes[i] = node.split(".")[0] - shader_type = "shader" if attr == "surfaceShader" else "disp_map" + shader_type = "shader" if attribute == "surfaceShader" else "disp_map" assignment = "{}='{}'".format(shader_type, shader_inputs[0]) for node in nodes: assignments[node].append(assignment) @@ -190,13 +190,13 @@ def assign_look(standin, subset): shading_engine_assignments( shading_engine=edit["shader"], - attr="surfaceShader", + attribute="surfaceShader", nodes=edit["nodes"], assignments=node_assignments ) shading_engine_assignments( shading_engine=edit["shader"], - attr="displacementShader", + attribute="displacementShader", nodes=edit["nodes"], assignments=node_assignments ) From 6d1fd474a396f64b03ef999fda2b7761274ea317 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 17 Mar 2023 07:53:24 +0000 Subject: [PATCH 472/898] Use calculate_visibility_mask --- .../tools/mayalookassigner/arnold_standin.py | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py index 4f85d151089..6d7be80060d 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py +++ b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py @@ -224,22 +224,7 @@ def assign_look(standin, subset): node_assignments[node].append(assignment) if visibility: - # https://arnoldsupport.com/2018/11/21/backdoor-setting-visibility/ - mapping = { - "primaryVisibility": 1, # Camera - "castsShadows": 2, # Shadow - "aiVisibleInDiffuseTransmission": 4, - "aiVisibleInSpecularTransmission": 8, - "aiVisibleInVolume": 16, - "aiVisibleInDiffuseReflection": 32, - "aiVisibleInSpecularReflection": 64 - } - mask = 255 - for attr, value in mapping.items(): - if edit["attributes"].get(attr, True): - continue - mask -= value - + mask = calculate_visibility_mask(edit["attributes"]) assignment = "visibility={}".format(mask) for node in edit["nodes"]: From e420883189ad06b8bcc76107fab0399e3e1f8465 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 17 Mar 2023 07:55:20 +0000 Subject: [PATCH 473/898] Hound --- .../maya/plugins/publish/extract_arnold_scene_source.py | 8 ++++++-- .../plugins/publish/validate_arnold_scene_source_cbid.py | 9 ++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index 1678f976270..c2523d4d120 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -120,7 +120,9 @@ def _extract(self, nodes, attribute_data, kwargs): with lib.delete_after() as delete_bin: duplicate_nodes = [] for node in nodes: - parent = cmds.listRelatives(node, parent=True, fullPath=True)[0] + parent = cmds.listRelatives( + node, parent=True, fullPath=True + )[0] duplicate_transform = cmds.duplicate(node)[0] duplicate_transform = "{}|{}".format( parent, duplicate_transform @@ -138,7 +140,9 @@ def _extract(self, nodes, attribute_data, kwargs): )[0] basename = node.split("|")[-1].split(":")[-1] - duplicate_transform = cmds.rename(duplicate_transform, basename) + duplicate_transform = cmds.rename( + duplicate_transform, basename + ) duplicate_nodes.append(duplicate_transform) delete_bin.append(duplicate_transform) diff --git a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py index ad174404dc7..dafad2f40ae 100644 --- a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py +++ b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py @@ -1,6 +1,5 @@ -import maya.cmds as cmds - import pyblish.api +from openpype.hosts.maya.api import lib from openpype.pipeline.publish import ( ValidateContentsOrder, PublishValidationError, RepairAction ) @@ -40,7 +39,11 @@ def get_invalid_couples(self, instance): proxy_node = proxy_nodes_by_name.get(content_name, None) if not proxy_node: - self.log.debug("Content node '{}' has no matching proxy node.".format(content_node)) + self.log.debug( + "Content node '{}' has no matching proxy node.".format( + content_node + ) + ) continue content_id = lib.get_id(content_node) From 0e8f251c5cbb58f4f67e18f8af8d9a7f06d8c0d6 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 17 Mar 2023 07:55:27 +0000 Subject: [PATCH 474/898] Hound --- .../hosts/maya/plugins/publish/validate_arnold_scene_source.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py index 8f443f6963c..d09a8610c46 100644 --- a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py @@ -1,5 +1,3 @@ -import maya.cmds as cmds - import pyblish.api from openpype.pipeline.publish import ( ValidateContentsOrder, PublishValidationError From 7cd7b2daf97f8f9776888f40d7123db84a006377 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 17 Mar 2023 09:03:35 +0000 Subject: [PATCH 475/898] Fix extractor --- .../publish/extract_arnold_scene_source.py | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index c2523d4d120..7348c2db4d7 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -120,6 +120,10 @@ def _extract(self, nodes, attribute_data, kwargs): with lib.delete_after() as delete_bin: duplicate_nodes = [] for node in nodes: + # Only interested in transforms: + if cmds.nodeType(node) != "transform": + continue + parent = cmds.listRelatives( node, parent=True, fullPath=True )[0] @@ -128,13 +132,6 @@ def _extract(self, nodes, attribute_data, kwargs): parent, duplicate_transform ) - # Discard the children. - shapes = cmds.listRelatives(duplicate_transform, shapes=True) - children = cmds.listRelatives( - duplicate_transform, children=True - ) - cmds.delete(set(children) - set(shapes)) - duplicate_transform = cmds.parent( duplicate_transform, world=True )[0] @@ -144,12 +141,22 @@ def _extract(self, nodes, attribute_data, kwargs): duplicate_transform, basename ) + # Discard the children. + shapes = cmds.listRelatives( + duplicate_transform, shapes=True, fullPath=True + ) + children = cmds.listRelatives( + duplicate_transform, children=True, fullPath=True + ) + cmds.delete(set(children) - set(shapes)) + duplicate_nodes.append(duplicate_transform) + duplicate_nodes.extend(shapes) delete_bin.append(duplicate_transform) # Copy cbId to mtoa_constant. for node in duplicate_nodes: - lib.set_attribute("mtoa_constant_cbId", lib.get_id(node)) + lib.set_attribute("mtoa_constant_cbId", lib.get_id(node), node) with lib.attribute_values(attribute_data): with lib.maintained_selection(): From 289efe25f8ec1d238ee1f95433b7aea355d42fd0 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 17 Mar 2023 10:35:53 +0100 Subject: [PATCH 476/898] Ftrack: Ftrack additional families filtering (#4633) * make sure all families are used for additional filtering * rely on instance and context data instead of legacy_io * formatting changes * fix variable values after change of condition * use 'families' variable for adding 'ftrack' family * Removed duplicated log * change variable name --- .../plugins/publish/collect_ftrack_family.py | 87 +++++++++---------- 1 file changed, 41 insertions(+), 46 deletions(-) diff --git a/openpype/modules/ftrack/plugins/publish/collect_ftrack_family.py b/openpype/modules/ftrack/plugins/publish/collect_ftrack_family.py index 576a7d36c4c..97815f490f4 100644 --- a/openpype/modules/ftrack/plugins/publish/collect_ftrack_family.py +++ b/openpype/modules/ftrack/plugins/publish/collect_ftrack_family.py @@ -7,23 +7,22 @@ """ import pyblish.api -from openpype.pipeline import legacy_io from openpype.lib import filter_profiles class CollectFtrackFamily(pyblish.api.InstancePlugin): - """ - Adds explicitly 'ftrack' to families to upload instance to FTrack. + """Adds explicitly 'ftrack' to families to upload instance to FTrack. - Uses selection by combination of hosts/families/tasks names via - profiles resolution. + Uses selection by combination of hosts/families/tasks names via + profiles resolution. - Triggered everywhere, checks instance against configured. + Triggered everywhere, checks instance against configured. - Checks advanced filtering which works on 'families' not on main - 'family', as some variants dynamically resolves addition of ftrack - based on 'families' (editorial drives it by presence of 'review') + Checks advanced filtering which works on 'families' not on main + 'family', as some variants dynamically resolves addition of ftrack + based on 'families' (editorial drives it by presence of 'review') """ + label = "Collect Ftrack Family" order = pyblish.api.CollectorOrder + 0.4990 @@ -34,68 +33,64 @@ def process(self, instance): self.log.warning("No profiles present for adding Ftrack family") return - add_ftrack_family = False - task_name = instance.data.get("task", - legacy_io.Session["AVALON_TASK"]) - host_name = legacy_io.Session["AVALON_APP"] + host_name = instance.context.data["hostName"] family = instance.data["family"] + task_name = instance.data.get("task") filtering_criteria = { "hosts": host_name, "families": family, "tasks": task_name } - profile = filter_profiles(self.profiles, filtering_criteria, - logger=self.log) + profile = filter_profiles( + self.profiles, + filtering_criteria, + logger=self.log + ) + + add_ftrack_family = False + families = instance.data.setdefault("families", []) if profile: - families = instance.data.get("families") add_ftrack_family = profile["add_ftrack_family"] - additional_filters = profile.get("advanced_filtering") if additional_filters: - self.log.info("'{}' families used for additional filtering". - format(families)) + families_set = set(families) | {family} + self.log.info( + "'{}' families used for additional filtering".format( + families_set)) add_ftrack_family = self._get_add_ftrack_f_from_addit_filters( additional_filters, - families, + families_set, add_ftrack_family ) - if add_ftrack_family: - self.log.debug("Adding ftrack family for '{}'". - format(instance.data.get("family"))) - - if families: - if "ftrack" not in families: - instance.data["families"].append("ftrack") - else: - instance.data["families"] = ["ftrack"] + result_str = "Not adding" + if add_ftrack_family: + result_str = "Adding" + if "ftrack" not in families: + families.append("ftrack") - result_str = "Adding" - if not add_ftrack_family: - result_str = "Not adding" self.log.info("{} 'ftrack' family for instance with '{}'".format( result_str, family )) - def _get_add_ftrack_f_from_addit_filters(self, - additional_filters, - families, - add_ftrack_family): - """ - Compares additional filters - working on instance's families. + def _get_add_ftrack_f_from_addit_filters( + self, additional_filters, families, add_ftrack_family + ): + """Compares additional filters - working on instance's families. - Triggered for more detailed filtering when main family matches, - but content of 'families' actually matter. - (For example 'review' in 'families' should result in adding to - Ftrack) + Triggered for more detailed filtering when main family matches, + but content of 'families' actually matter. + (For example 'review' in 'families' should result in adding to + Ftrack) - Args: - additional_filters (dict) - from Setting - families (list) - subfamilies - add_ftrack_family (bool) - add ftrack to families if True + Args: + additional_filters (dict) - from Setting + families (set[str]) - subfamilies + add_ftrack_family (bool) - add ftrack to families if True """ + override_filter = None override_filter_value = -1 for additional_filter in additional_filters: From 249bda0c8020ac5f8b00575de58cc17690cf697d Mon Sep 17 00:00:00 2001 From: Alexey Bogomolov <11698866+movalex@users.noreply.github.com> Date: Fri, 17 Mar 2023 13:41:32 +0300 Subject: [PATCH 477/898] Clockify: refresh and fix the integration (#4607) * WIP clockify fix * WIP disable wp validation, make sync work * fix launcher start timer action * fix finish time entry * fix start and stop timers, cleanup, add TODO * show task name and type in description, add TODO * change rate limiter constants * black formatting * remove task type from data * cleanup debug prints * fix hound comments * remove unused import * move ids to property, fix user validation * remove f-strings, rollback description parsing * attempt to fix ftrack actions * check if sync action got some projects * get api data on process * remove unused variable * remove ratelimiter dependency * add response validation * a bit cleanup * Update openpype/modules/clockify/clockify_module.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> * Update openpype/modules/clockify/clockify_api.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> * Update openpype/modules/clockify/clockify_api.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> * Update openpype/modules/clockify/clockify_api.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> * Update openpype/modules/clockify/ftrack/server/action_clockify_sync_server.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> * replace dunders with underscores * remove excessive variables * update set_user_id * continue check_running if no timer found * bring back come py2 compatibility * cleanup * get values directly from clockapi * hound * get task type to fill the tag field correctly * add logger, catch some json errors * remove check running timer, add project_id verification module * add current task_id check * remove package entries * make method private, fix typo * get task_type for the idle-restarted timer * remove trailing whitespace * show correct idle countdown values * finx indentation * Update openpype/modules/clockify/clockify_api.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> * Update openpype/modules/clockify/clockify_module.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> * revert lock file * remove unused constants and redundant code * import clockify_api inside the method * do not query asset docs double time, add comments * add permissions check fail Exception * rename clockapi to clockify_api * formatting * removed unused variables --------- Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Co-authored-by: Jakub Trllo --- openpype/modules/clockify/clockify_api.py | 359 ++++++++---------- openpype/modules/clockify/clockify_module.py | 177 ++++----- openpype/modules/clockify/constants.py | 2 +- .../server/action_clockify_sync_server.py | 25 +- .../ftrack/user/action_clockify_sync_local.py | 26 +- .../launcher_actions/ClockifyStart.py | 46 ++- .../clockify/launcher_actions/ClockifySync.py | 55 ++- openpype/modules/clockify/widgets.py | 16 +- .../modules/timers_manager/timers_manager.py | 4 +- 9 files changed, 360 insertions(+), 350 deletions(-) diff --git a/openpype/modules/clockify/clockify_api.py b/openpype/modules/clockify/clockify_api.py index 6af911fffcb..80979c83ab2 100644 --- a/openpype/modules/clockify/clockify_api.py +++ b/openpype/modules/clockify/clockify_api.py @@ -6,34 +6,22 @@ import requests from .constants import ( CLOCKIFY_ENDPOINT, - ADMIN_PERMISSION_NAMES + ADMIN_PERMISSION_NAMES, ) from openpype.lib.local_settings import OpenPypeSecureRegistry - - -def time_check(obj): - if obj.request_counter < 10: - obj.request_counter += 1 - return - - wait_time = 1 - (time.time() - obj.request_time) - if wait_time > 0: - time.sleep(wait_time) - - obj.request_time = time.time() - obj.request_counter = 0 +from openpype.lib import Logger class ClockifyAPI: + log = Logger.get_logger(__name__) + def __init__(self, api_key=None, master_parent=None): self.workspace_name = None - self.workspace_id = None self.master_parent = master_parent self.api_key = api_key - self.request_counter = 0 - self.request_time = time.time() - + self._workspace_id = None + self._user_id = None self._secure_registry = None @property @@ -44,11 +32,19 @@ def secure_registry(self): @property def headers(self): - return {"X-Api-Key": self.api_key} + return {"x-api-key": self.api_key} + + @property + def workspace_id(self): + return self._workspace_id + + @property + def user_id(self): + return self._user_id def verify_api(self): for key, value in self.headers.items(): - if value is None or value.strip() == '': + if value is None or value.strip() == "": return False return True @@ -59,65 +55,55 @@ def set_api(self, api_key=None): if api_key is not None and self.validate_api_key(api_key) is True: self.api_key = api_key self.set_workspace() + self.set_user_id() if self.master_parent: self.master_parent.signed_in() return True return False def validate_api_key(self, api_key): - test_headers = {'X-Api-Key': api_key} - action_url = 'workspaces/' - time_check(self) + test_headers = {"x-api-key": api_key} + action_url = "user" response = requests.get( - CLOCKIFY_ENDPOINT + action_url, - headers=test_headers + CLOCKIFY_ENDPOINT + action_url, headers=test_headers ) if response.status_code != 200: return False return True - def validate_workspace_perm(self, workspace_id=None): - user_id = self.get_user_id() + def validate_workspace_permissions(self, workspace_id=None, user_id=None): if user_id is None: + self.log.info("No user_id found during validation") return False if workspace_id is None: workspace_id = self.workspace_id - action_url = "/workspaces/{}/users/{}/permissions".format( - workspace_id, user_id - ) - time_check(self) + action_url = f"workspaces/{workspace_id}/users?includeRoles=1" response = requests.get( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers + CLOCKIFY_ENDPOINT + action_url, headers=self.headers ) - user_permissions = response.json() - for perm in user_permissions: - if perm['name'] in ADMIN_PERMISSION_NAMES: + data = response.json() + for user in data: + if user.get("id") == user_id: + roles_data = user.get("roles") + for entities in roles_data: + if entities.get("role") in ADMIN_PERMISSION_NAMES: return True return False def get_user_id(self): - action_url = 'v1/user/' - time_check(self) + action_url = "user" response = requests.get( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers + CLOCKIFY_ENDPOINT + action_url, headers=self.headers ) - # this regex is neccessary: UNICODE strings are crashing - # during json serialization - id_regex = '\"{1}id\"{1}\:{1}\"{1}\w+\"{1}' - result = re.findall(id_regex, str(response.content)) - if len(result) != 1: - # replace with log and better message? - print('User ID was not found (this is a BUG!!!)') - return None - return json.loads('{'+result[0]+'}')['id'] + result = response.json() + user_id = result.get("id", None) + + return user_id def set_workspace(self, name=None): if name is None: - name = os.environ.get('CLOCKIFY_WORKSPACE', None) + name = os.environ.get("CLOCKIFY_WORKSPACE", None) self.workspace_name = name - self.workspace_id = None if self.workspace_name is None: return try: @@ -125,7 +111,7 @@ def set_workspace(self, name=None): except Exception: result = False if result is not False: - self.workspace_id = result + self._workspace_id = result if self.master_parent is not None: self.master_parent.start_timer_check() return True @@ -139,6 +125,14 @@ def validate_workspace(self, name=None): return all_workspaces[name] return False + def set_user_id(self): + try: + user_id = self.get_user_id() + except Exception: + user_id = None + if user_id is not None: + self._user_id = user_id + def get_api_key(self): return self.secure_registry.get_item("api_key", None) @@ -146,11 +140,9 @@ def save_api_key(self, api_key): self.secure_registry.set_item("api_key", api_key) def get_workspaces(self): - action_url = 'workspaces/' - time_check(self) + action_url = "workspaces/" response = requests.get( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers + CLOCKIFY_ENDPOINT + action_url, headers=self.headers ) return { workspace["name"]: workspace["id"] for workspace in response.json() @@ -159,27 +151,22 @@ def get_workspaces(self): def get_projects(self, workspace_id=None): if workspace_id is None: workspace_id = self.workspace_id - action_url = 'workspaces/{}/projects/'.format(workspace_id) - time_check(self) + action_url = f"workspaces/{workspace_id}/projects" response = requests.get( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers + CLOCKIFY_ENDPOINT + action_url, headers=self.headers ) - - return { - project["name"]: project["id"] for project in response.json() - } + if response.status_code != 403: + result = response.json() + return {project["name"]: project["id"] for project in result} def get_project_by_id(self, project_id, workspace_id=None): if workspace_id is None: workspace_id = self.workspace_id - action_url = 'workspaces/{}/projects/{}/'.format( + action_url = "workspaces/{}/projects/{}".format( workspace_id, project_id ) - time_check(self) response = requests.get( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers + CLOCKIFY_ENDPOINT + action_url, headers=self.headers ) return response.json() @@ -187,32 +174,24 @@ def get_project_by_id(self, project_id, workspace_id=None): def get_tags(self, workspace_id=None): if workspace_id is None: workspace_id = self.workspace_id - action_url = 'workspaces/{}/tags/'.format(workspace_id) - time_check(self) + action_url = "workspaces/{}/tags".format(workspace_id) response = requests.get( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers + CLOCKIFY_ENDPOINT + action_url, headers=self.headers ) - return { - tag["name"]: tag["id"] for tag in response.json() - } + return {tag["name"]: tag["id"] for tag in response.json()} def get_tasks(self, project_id, workspace_id=None): if workspace_id is None: workspace_id = self.workspace_id - action_url = 'workspaces/{}/projects/{}/tasks/'.format( + action_url = "workspaces/{}/projects/{}/tasks".format( workspace_id, project_id ) - time_check(self) response = requests.get( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers + CLOCKIFY_ENDPOINT + action_url, headers=self.headers ) - return { - task["name"]: task["id"] for task in response.json() - } + return {task["name"]: task["id"] for task in response.json()} def get_workspace_id(self, workspace_name): all_workspaces = self.get_workspaces() @@ -236,48 +215,64 @@ def get_tag_id(self, tag_name, workspace_id=None): return None return all_tasks[tag_name] - def get_task_id( - self, task_name, project_id, workspace_id=None - ): + def get_task_id(self, task_name, project_id, workspace_id=None): if workspace_id is None: workspace_id = self.workspace_id - all_tasks = self.get_tasks( - project_id, workspace_id - ) + all_tasks = self.get_tasks(project_id, workspace_id) if task_name not in all_tasks: return None return all_tasks[task_name] def get_current_time(self): - return str(datetime.datetime.utcnow().isoformat())+'Z' + return str(datetime.datetime.utcnow().isoformat()) + "Z" def start_time_entry( - self, description, project_id, task_id=None, tag_ids=[], - workspace_id=None, billable=True + self, + description, + project_id, + task_id=None, + tag_ids=None, + workspace_id=None, + user_id=None, + billable=True, ): # Workspace if workspace_id is None: workspace_id = self.workspace_id + # User ID + if user_id is None: + user_id = self._user_id + + # get running timer to check if we need to start it + current_timer = self.get_in_progress() # Check if is currently run another times and has same values - current = self.get_in_progress(workspace_id) - if current is not None: + # DO not restart the timer, if it is already running for curent task + if current_timer: + current_timer_hierarchy = current_timer.get("description") + current_project_id = current_timer.get("projectId") + current_task_id = current_timer.get("taskId") if ( - current.get("description", None) == description and - current.get("projectId", None) == project_id and - current.get("taskId", None) == task_id + description == current_timer_hierarchy + and project_id == current_project_id + and task_id == current_task_id ): + self.log.info( + "Timer for the current project is already running" + ) self.bool_timer_run = True return self.bool_timer_run - self.finish_time_entry(workspace_id) + self.finish_time_entry() # Convert billable to strings if billable: - billable = 'true' + billable = "true" else: - billable = 'false' + billable = "false" # Rest API Action - action_url = 'workspaces/{}/timeEntries/'.format(workspace_id) + action_url = "workspaces/{}/user/{}/time-entries".format( + workspace_id, user_id + ) start = self.get_current_time() body = { "start": start, @@ -285,169 +280,135 @@ def start_time_entry( "description": description, "projectId": project_id, "taskId": task_id, - "tagIds": tag_ids + "tagIds": tag_ids, } - time_check(self) response = requests.post( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers, - json=body + CLOCKIFY_ENDPOINT + action_url, headers=self.headers, json=body ) - - success = False if response.status_code < 300: - success = True - return success + return True + return False - def get_in_progress(self, workspace_id=None): + def _get_current_timer_values(self, response): + if response is None: + return + try: + output = response.json() + except json.decoder.JSONDecodeError: + return None + if output and isinstance(output, list): + return output[0] + return None + + def get_in_progress(self, user_id=None, workspace_id=None): if workspace_id is None: workspace_id = self.workspace_id - action_url = 'workspaces/{}/timeEntries/inProgress'.format( - workspace_id + if user_id is None: + user_id = self.user_id + + action_url = ( + f"workspaces/{workspace_id}/user/" + f"{user_id}/time-entries?in-progress=1" ) - time_check(self) response = requests.get( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers + CLOCKIFY_ENDPOINT + action_url, headers=self.headers ) - try: - output = response.json() - except json.decoder.JSONDecodeError: - output = None - return output + return self._get_current_timer_values(response) - def finish_time_entry(self, workspace_id=None): + def finish_time_entry(self, workspace_id=None, user_id=None): if workspace_id is None: workspace_id = self.workspace_id - current = self.get_in_progress(workspace_id) - if current is None: + if user_id is None: + user_id = self.user_id + current_timer = self.get_in_progress() + if not current_timer: return - - current_id = current["id"] - action_url = 'workspaces/{}/timeEntries/{}'.format( - workspace_id, current_id + action_url = "workspaces/{}/user/{}/time-entries".format( + workspace_id, user_id ) - body = { - "start": current["timeInterval"]["start"], - "billable": current["billable"], - "description": current["description"], - "projectId": current["projectId"], - "taskId": current["taskId"], - "tagIds": current["tagIds"], - "end": self.get_current_time() - } - time_check(self) - response = requests.put( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers, - json=body + body = {"end": self.get_current_time()} + response = requests.patch( + CLOCKIFY_ENDPOINT + action_url, headers=self.headers, json=body ) return response.json() - def get_time_entries( - self, workspace_id=None, quantity=10 - ): + def get_time_entries(self, workspace_id=None, user_id=None, quantity=10): if workspace_id is None: workspace_id = self.workspace_id - action_url = 'workspaces/{}/timeEntries/'.format(workspace_id) - time_check(self) + if user_id is None: + user_id = self.user_id + action_url = "workspaces/{}/user/{}/time-entries".format( + workspace_id, user_id + ) response = requests.get( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers + CLOCKIFY_ENDPOINT + action_url, headers=self.headers ) return response.json()[:quantity] - def remove_time_entry(self, tid, workspace_id=None): + def remove_time_entry(self, tid, workspace_id=None, user_id=None): if workspace_id is None: workspace_id = self.workspace_id - action_url = 'workspaces/{}/timeEntries/{}'.format( - workspace_id, tid + action_url = "workspaces/{}/user/{}/time-entries/{}".format( + workspace_id, user_id, tid ) - time_check(self) response = requests.delete( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers + CLOCKIFY_ENDPOINT + action_url, headers=self.headers ) return response.json() def add_project(self, name, workspace_id=None): if workspace_id is None: workspace_id = self.workspace_id - action_url = 'workspaces/{}/projects/'.format(workspace_id) + action_url = "workspaces/{}/projects".format(workspace_id) body = { "name": name, "clientId": "", "isPublic": "false", - "estimate": { - "estimate": 0, - "type": "AUTO" - }, + "estimate": {"estimate": 0, "type": "AUTO"}, "color": "#f44336", - "billable": "true" + "billable": "true", } - time_check(self) response = requests.post( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers, - json=body + CLOCKIFY_ENDPOINT + action_url, headers=self.headers, json=body ) return response.json() def add_workspace(self, name): - action_url = 'workspaces/' + action_url = "workspaces/" body = {"name": name} - time_check(self) response = requests.post( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers, - json=body + CLOCKIFY_ENDPOINT + action_url, headers=self.headers, json=body ) return response.json() - def add_task( - self, name, project_id, workspace_id=None - ): + def add_task(self, name, project_id, workspace_id=None): if workspace_id is None: workspace_id = self.workspace_id - action_url = 'workspaces/{}/projects/{}/tasks/'.format( + action_url = "workspaces/{}/projects/{}/tasks".format( workspace_id, project_id ) - body = { - "name": name, - "projectId": project_id - } - time_check(self) + body = {"name": name, "projectId": project_id} response = requests.post( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers, - json=body + CLOCKIFY_ENDPOINT + action_url, headers=self.headers, json=body ) return response.json() def add_tag(self, name, workspace_id=None): if workspace_id is None: workspace_id = self.workspace_id - action_url = 'workspaces/{}/tags'.format(workspace_id) - body = { - "name": name - } - time_check(self) + action_url = "workspaces/{}/tags".format(workspace_id) + body = {"name": name} response = requests.post( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers, - json=body + CLOCKIFY_ENDPOINT + action_url, headers=self.headers, json=body ) return response.json() - def delete_project( - self, project_id, workspace_id=None - ): + def delete_project(self, project_id, workspace_id=None): if workspace_id is None: workspace_id = self.workspace_id - action_url = '/workspaces/{}/projects/{}'.format( + action_url = "/workspaces/{}/projects/{}".format( workspace_id, project_id ) - time_check(self) response = requests.delete( CLOCKIFY_ENDPOINT + action_url, headers=self.headers, @@ -455,12 +416,12 @@ def delete_project( return response.json() def convert_input( - self, entity_id, entity_name, mode='Workspace', project_id=None + self, entity_id, entity_name, mode="Workspace", project_id=None ): if entity_id is None: error = False error_msg = 'Missing information "{}"' - if mode.lower() == 'workspace': + if mode.lower() == "workspace": if entity_id is None and entity_name is None: if self.workspace_id is not None: entity_id = self.workspace_id @@ -471,14 +432,14 @@ def convert_input( else: if entity_id is None and entity_name is None: error = True - elif mode.lower() == 'project': + elif mode.lower() == "project": entity_id = self.get_project_id(entity_name) - elif mode.lower() == 'task': + elif mode.lower() == "task": entity_id = self.get_task_id( task_name=entity_name, project_id=project_id ) else: - raise TypeError('Unknown type') + raise TypeError("Unknown type") # Raise error if error: raise ValueError(error_msg.format(mode)) diff --git a/openpype/modules/clockify/clockify_module.py b/openpype/modules/clockify/clockify_module.py index 300d5576e2a..200a268ad7c 100644 --- a/openpype/modules/clockify/clockify_module.py +++ b/openpype/modules/clockify/clockify_module.py @@ -2,24 +2,13 @@ import threading import time -from openpype.modules import ( - OpenPypeModule, - ITrayModule, - IPluginPaths -) - -from .clockify_api import ClockifyAPI -from .constants import ( - CLOCKIFY_FTRACK_USER_PATH, - CLOCKIFY_FTRACK_SERVER_PATH -) - - -class ClockifyModule( - OpenPypeModule, - ITrayModule, - IPluginPaths -): +from openpype.modules import OpenPypeModule, ITrayModule, IPluginPaths +from openpype.client import get_asset_by_name + +from .constants import CLOCKIFY_FTRACK_USER_PATH, CLOCKIFY_FTRACK_SERVER_PATH + + +class ClockifyModule(OpenPypeModule, ITrayModule, IPluginPaths): name = "clockify" def initialize(self, modules_settings): @@ -33,18 +22,23 @@ def initialize(self, modules_settings): self.timer_manager = None self.MessageWidgetClass = None self.message_widget = None - - self.clockapi = ClockifyAPI(master_parent=self) + self._clockify_api = None # TimersManager attributes # - set `timers_manager_connector` only in `tray_init` self.timers_manager_connector = None self._timers_manager_module = None + @property + def clockify_api(self): + if self._clockify_api is None: + from .clockify_api import ClockifyAPI + + self._clockify_api = ClockifyAPI(master_parent=self) + return self._clockify_api + def get_global_environments(self): - return { - "CLOCKIFY_WORKSPACE": self.workspace_name - } + return {"CLOCKIFY_WORKSPACE": self.workspace_name} def tray_init(self): from .widgets import ClockifySettings, MessageWidget @@ -52,7 +46,7 @@ def tray_init(self): self.MessageWidgetClass = MessageWidget self.message_widget = None - self.widget_settings = ClockifySettings(self.clockapi) + self.widget_settings = ClockifySettings(self.clockify_api) self.widget_settings_required = None self.thread_timer_check = None @@ -61,7 +55,7 @@ def tray_init(self): self.bool_api_key_set = False self.bool_workspace_set = False self.bool_timer_run = False - self.bool_api_key_set = self.clockapi.set_api() + self.bool_api_key_set = self.clockify_api.set_api() # Define itself as TimersManager connector self.timers_manager_connector = self @@ -71,12 +65,11 @@ def tray_start(self): self.show_settings() return - self.bool_workspace_set = self.clockapi.workspace_id is not None + self.bool_workspace_set = self.clockify_api.workspace_id is not None if self.bool_workspace_set is False: return self.start_timer_check() - self.set_menu_visibility() def tray_exit(self, *_a, **_kw): @@ -85,23 +78,19 @@ def tray_exit(self, *_a, **_kw): def get_plugin_paths(self): """Implementaton of IPluginPaths to get plugin paths.""" actions_path = os.path.join( - os.path.dirname(os.path.abspath(__file__)), - "launcher_actions" + os.path.dirname(os.path.abspath(__file__)), "launcher_actions" ) - return { - "actions": [actions_path] - } + return {"actions": [actions_path]} def get_ftrack_event_handler_paths(self): """Function for Ftrack module to add ftrack event handler paths.""" return { "user": [CLOCKIFY_FTRACK_USER_PATH], - "server": [CLOCKIFY_FTRACK_SERVER_PATH] + "server": [CLOCKIFY_FTRACK_SERVER_PATH], } def clockify_timer_stopped(self): self.bool_timer_run = False - # Call `ITimersManager` method self.timer_stopped() def start_timer_check(self): @@ -122,45 +111,44 @@ def stop_timer_check(self): def check_running(self): while self.bool_thread_check_running is True: bool_timer_run = False - if self.clockapi.get_in_progress() is not None: + if self.clockify_api.get_in_progress() is not None: bool_timer_run = True if self.bool_timer_run != bool_timer_run: if self.bool_timer_run is True: self.clockify_timer_stopped() elif self.bool_timer_run is False: - actual_timer = self.clockapi.get_in_progress() - if not actual_timer: + current_timer = self.clockify_api.get_in_progress() + if current_timer is None: continue - - actual_proj_id = actual_timer["projectId"] - if not actual_proj_id: + current_proj_id = current_timer.get("projectId") + if not current_proj_id: continue - project = self.clockapi.get_project_by_id(actual_proj_id) + project = self.clockify_api.get_project_by_id( + current_proj_id + ) if project and project.get("code") == 501: continue - project_name = project["name"] + project_name = project.get("name") - actual_timer_hierarchy = actual_timer["description"] - hierarchy_items = actual_timer_hierarchy.split("/") + current_timer_hierarchy = current_timer.get("description") + if not current_timer_hierarchy: + continue + hierarchy_items = current_timer_hierarchy.split("/") # Each pype timer must have at least 2 items! if len(hierarchy_items) < 2: continue + task_name = hierarchy_items[-1] hierarchy = hierarchy_items[:-1] - task_type = None - if len(actual_timer.get("tags", [])) > 0: - task_type = actual_timer["tags"][0].get("name") data = { "task_name": task_name, "hierarchy": hierarchy, "project_name": project_name, - "task_type": task_type } - # Call `ITimersManager` method self.timer_started(data) self.bool_timer_run = bool_timer_run @@ -184,6 +172,7 @@ def on_message_widget_close(self): def tray_menu(self, parent_menu): # Menu for Tray App from qtpy import QtWidgets + menu = QtWidgets.QMenu("Clockify", parent_menu) menu.setProperty("submenu", "on") @@ -204,7 +193,9 @@ def tray_menu(self, parent_menu): parent_menu.addMenu(menu) def show_settings(self): - self.widget_settings.input_api_key.setText(self.clockapi.get_api_key()) + self.widget_settings.input_api_key.setText( + self.clockify_api.get_api_key() + ) self.widget_settings.show() def set_menu_visibility(self): @@ -218,72 +209,82 @@ def register_timers_manager(self, timer_manager_module): def timer_started(self, data): """Tell TimersManager that timer started.""" if self._timers_manager_module is not None: - self._timers_manager_module.timer_started(self._module.id, data) + self._timers_manager_module.timer_started(self.id, data) def timer_stopped(self): """Tell TimersManager that timer stopped.""" if self._timers_manager_module is not None: - self._timers_manager_module.timer_stopped(self._module.id) + self._timers_manager_module.timer_stopped(self.id) def stop_timer(self): """Called from TimersManager to stop timer.""" - self.clockapi.finish_time_entry() + self.clockify_api.finish_time_entry() - def start_timer(self, input_data): - """Called from TimersManager to start timer.""" - # If not api key is not entered then skip - if not self.clockapi.get_api_key(): - return - - actual_timer = self.clockapi.get_in_progress() - actual_timer_hierarchy = None - actual_project_id = None - if actual_timer is not None: - actual_timer_hierarchy = actual_timer.get("description") - actual_project_id = actual_timer.get("projectId") - - # Concatenate hierarchy and task to get description - desc_items = [val for val in input_data.get("hierarchy", [])] - desc_items.append(input_data["task_name"]) - description = "/".join(desc_items) - - # Check project existence - project_name = input_data["project_name"] - project_id = self.clockapi.get_project_id(project_name) + def _verify_project_exists(self, project_name): + project_id = self.clockify_api.get_project_id(project_name) if not project_id: - self.log.warning(( - "Project \"{}\" was not found in Clockify. Timer won't start." - ).format(project_name)) + self.log.warning( + 'Project "{}" was not found in Clockify. Timer won\'t start.' + ).format(project_name) if not self.MessageWidgetClass: return msg = ( - "Project \"{}\" is not" - " in Clockify Workspace \"{}\"." + 'Project "{}" is not' + ' in Clockify Workspace "{}".' "

Please inform your Project Manager." - ).format(project_name, str(self.clockapi.workspace_name)) + ).format(project_name, str(self.clockify_api.workspace_name)) self.message_widget = self.MessageWidgetClass( msg, "Clockify - Info Message" ) self.message_widget.closed.connect(self.on_message_widget_close) self.message_widget.show() + return False + return project_id + def start_timer(self, input_data): + """Called from TimersManager to start timer.""" + # If not api key is not entered then skip + if not self.clockify_api.get_api_key(): return - if ( - actual_timer is not None and - description == actual_timer_hierarchy and - project_id == actual_project_id - ): + task_name = input_data.get("task_name") + + # Concatenate hierarchy and task to get description + description_items = list(input_data.get("hierarchy", [])) + description_items.append(task_name) + description = "/".join(description_items) + + # Check project existence + project_name = input_data.get("project_name") + project_id = self._verify_project_exists(project_name) + if not project_id: return + # Setup timer tags tag_ids = [] - task_tag_id = self.clockapi.get_tag_id(input_data["task_type"]) + tag_name = input_data.get("task_type") + if not tag_name: + # no task_type found in the input data + # if the timer is restarted by idle time (bug?) + asset_name = input_data["hierarchy"][-1] + asset_doc = get_asset_by_name(project_name, asset_name) + task_info = asset_doc["data"]["tasks"][task_name] + tag_name = task_info.get("type", "") + if not tag_name: + self.log.info("No tag information found for the timer") + + task_tag_id = self.clockify_api.get_tag_id(tag_name) if task_tag_id is not None: tag_ids.append(task_tag_id) - self.clockapi.start_time_entry( - description, project_id, tag_ids=tag_ids + # Start timer + self.clockify_api.start_time_entry( + description, + project_id, + tag_ids=tag_ids, + workspace_id=self.clockify_api.workspace_id, + user_id=self.clockify_api.user_id, ) diff --git a/openpype/modules/clockify/constants.py b/openpype/modules/clockify/constants.py index 66f6cb899a5..4574f91be1d 100644 --- a/openpype/modules/clockify/constants.py +++ b/openpype/modules/clockify/constants.py @@ -9,4 +9,4 @@ ) ADMIN_PERMISSION_NAMES = ["WORKSPACE_OWN", "WORKSPACE_ADMIN"] -CLOCKIFY_ENDPOINT = "https://api.clockify.me/api/" +CLOCKIFY_ENDPOINT = "https://api.clockify.me/api/v1/" diff --git a/openpype/modules/clockify/ftrack/server/action_clockify_sync_server.py b/openpype/modules/clockify/ftrack/server/action_clockify_sync_server.py index c6b55947da6..985cf49b972 100644 --- a/openpype/modules/clockify/ftrack/server/action_clockify_sync_server.py +++ b/openpype/modules/clockify/ftrack/server/action_clockify_sync_server.py @@ -4,7 +4,7 @@ from openpype_modules.clockify.clockify_api import ClockifyAPI -class SyncClocifyServer(ServerAction): +class SyncClockifyServer(ServerAction): '''Synchronise project names and task types.''' identifier = "clockify.sync.server" @@ -14,12 +14,12 @@ class SyncClocifyServer(ServerAction): role_list = ["Pypeclub", "Administrator", "project Manager"] def __init__(self, *args, **kwargs): - super(SyncClocifyServer, self).__init__(*args, **kwargs) + super(SyncClockifyServer, self).__init__(*args, **kwargs) workspace_name = os.environ.get("CLOCKIFY_WORKSPACE") api_key = os.environ.get("CLOCKIFY_API_KEY") - self.clockapi = ClockifyAPI(api_key) - self.clockapi.set_workspace(workspace_name) + self.clockify_api = ClockifyAPI(api_key) + self.clockify_api.set_workspace(workspace_name) if api_key is None: modified_key = "None" else: @@ -48,13 +48,16 @@ def discover(self, session, entities, event): return True def launch(self, session, entities, event): - if self.clockapi.workspace_id is None: + self.clockify_api.set_api() + if self.clockify_api.workspace_id is None: return { "success": False, "message": "Clockify Workspace or API key are not set!" } - if self.clockapi.validate_workspace_perm() is False: + if not self.clockify_api.validate_workspace_permissions( + self.clockify_api.workspace_id, self.clockify_api.user_id + ): return { "success": False, "message": "Missing permissions for this action!" @@ -88,9 +91,9 @@ def launch(self, session, entities, event): task_type["name"] for task_type in task_types ] try: - clockify_projects = self.clockapi.get_projects() + clockify_projects = self.clockify_api.get_projects() if project_name not in clockify_projects: - response = self.clockapi.add_project(project_name) + response = self.clockify_api.add_project(project_name) if "id" not in response: self.log.warning( "Project \"{}\" can't be created. Response: {}".format( @@ -105,7 +108,7 @@ def launch(self, session, entities, event): ).format(project_name) } - clockify_workspace_tags = self.clockapi.get_tags() + clockify_workspace_tags = self.clockify_api.get_tags() for task_type_name in task_type_names: if task_type_name in clockify_workspace_tags: self.log.debug( @@ -113,7 +116,7 @@ def launch(self, session, entities, event): ) continue - response = self.clockapi.add_tag(task_type_name) + response = self.clockify_api.add_tag(task_type_name) if "id" not in response: self.log.warning( "Task \"{}\" can't be created. Response: {}".format( @@ -138,4 +141,4 @@ def launch(self, session, entities, event): def register(session, **kw): - SyncClocifyServer(session).register() + SyncClockifyServer(session).register() diff --git a/openpype/modules/clockify/ftrack/user/action_clockify_sync_local.py b/openpype/modules/clockify/ftrack/user/action_clockify_sync_local.py index a430791906c..0e8cf6bd374 100644 --- a/openpype/modules/clockify/ftrack/user/action_clockify_sync_local.py +++ b/openpype/modules/clockify/ftrack/user/action_clockify_sync_local.py @@ -3,7 +3,7 @@ from openpype_modules.clockify.clockify_api import ClockifyAPI -class SyncClocifyLocal(BaseAction): +class SyncClockifyLocal(BaseAction): '''Synchronise project names and task types.''' #: Action identifier. @@ -18,9 +18,9 @@ class SyncClocifyLocal(BaseAction): icon = statics_icon("app_icons", "clockify-white.png") def __init__(self, *args, **kwargs): - super(SyncClocifyLocal, self).__init__(*args, **kwargs) + super(SyncClockifyLocal, self).__init__(*args, **kwargs) #: CLockifyApi - self.clockapi = ClockifyAPI() + self.clockify_api = ClockifyAPI() def discover(self, session, entities, event): if ( @@ -31,14 +31,18 @@ def discover(self, session, entities, event): return False def launch(self, session, entities, event): - self.clockapi.set_api() - if self.clockapi.workspace_id is None: + self.clockify_api.set_api() + if self.clockify_api.workspace_id is None: return { "success": False, "message": "Clockify Workspace or API key are not set!" } - if self.clockapi.validate_workspace_perm() is False: + if ( + self.clockify_api.validate_workspace_permissions( + self.clockify_api.workspace_id, self.clockify_api.user_id) + is False + ): return { "success": False, "message": "Missing permissions for this action!" @@ -74,9 +78,9 @@ def launch(self, session, entities, event): task_type["name"] for task_type in task_types ] try: - clockify_projects = self.clockapi.get_projects() + clockify_projects = self.clockify_api.get_projects() if project_name not in clockify_projects: - response = self.clockapi.add_project(project_name) + response = self.clockify_api.add_project(project_name) if "id" not in response: self.log.warning( "Project \"{}\" can't be created. Response: {}".format( @@ -91,7 +95,7 @@ def launch(self, session, entities, event): ).format(project_name) } - clockify_workspace_tags = self.clockapi.get_tags() + clockify_workspace_tags = self.clockify_api.get_tags() for task_type_name in task_type_names: if task_type_name in clockify_workspace_tags: self.log.debug( @@ -99,7 +103,7 @@ def launch(self, session, entities, event): ) continue - response = self.clockapi.add_tag(task_type_name) + response = self.clockify_api.add_tag(task_type_name) if "id" not in response: self.log.warning( "Task \"{}\" can't be created. Response: {}".format( @@ -121,4 +125,4 @@ def launch(self, session, entities, event): def register(session, **kw): - SyncClocifyLocal(session).register() + SyncClockifyLocal(session).register() diff --git a/openpype/modules/clockify/launcher_actions/ClockifyStart.py b/openpype/modules/clockify/launcher_actions/ClockifyStart.py index 7663aecc316..4a653c1b8db 100644 --- a/openpype/modules/clockify/launcher_actions/ClockifyStart.py +++ b/openpype/modules/clockify/launcher_actions/ClockifyStart.py @@ -6,9 +6,9 @@ class ClockifyStart(LauncherAction): name = "clockify_start_timer" label = "Clockify - Start Timer" - icon = "clockify_icon" + icon = "app_icons/clockify.png" order = 500 - clockapi = ClockifyAPI() + clockify_api = ClockifyAPI() def is_compatible(self, session): """Return whether the action is compatible with the session""" @@ -17,23 +17,39 @@ def is_compatible(self, session): return False def process(self, session, **kwargs): + self.clockify_api.set_api() + user_id = self.clockify_api.user_id + workspace_id = self.clockify_api.workspace_id project_name = session["AVALON_PROJECT"] asset_name = session["AVALON_ASSET"] task_name = session["AVALON_TASK"] - description = asset_name - asset_doc = get_asset_by_name( - project_name, asset_name, fields=["data.parents"] - ) - if asset_doc is not None: - desc_items = asset_doc.get("data", {}).get("parents", []) - desc_items.append(asset_name) - desc_items.append(task_name) - description = "/".join(desc_items) - project_id = self.clockapi.get_project_id(project_name) + # fetch asset docs + asset_doc = get_asset_by_name(project_name, asset_name) + + # get task type to fill the timer tag + task_info = asset_doc["data"]["tasks"][task_name] + task_type = task_info["type"] + + # check if the task has hierarchy and fill the + parents_data = asset_doc["data"] + if parents_data is not None: + description_items = parents_data.get("parents", []) + description_items.append(asset_name) + description_items.append(task_name) + description = "/".join(description_items) + + project_id = self.clockify_api.get_project_id( + project_name, workspace_id + ) tag_ids = [] - tag_ids.append(self.clockapi.get_tag_id(task_name)) - self.clockapi.start_time_entry( - description, project_id, tag_ids=tag_ids + tag_name = task_type + tag_ids.append(self.clockify_api.get_tag_id(tag_name, workspace_id)) + self.clockify_api.start_time_entry( + description, + project_id, + tag_ids=tag_ids, + workspace_id=workspace_id, + user_id=user_id, ) diff --git a/openpype/modules/clockify/launcher_actions/ClockifySync.py b/openpype/modules/clockify/launcher_actions/ClockifySync.py index c346a1b4f62..cbd2519a04e 100644 --- a/openpype/modules/clockify/launcher_actions/ClockifySync.py +++ b/openpype/modules/clockify/launcher_actions/ClockifySync.py @@ -3,20 +3,39 @@ from openpype.pipeline import LauncherAction -class ClockifySync(LauncherAction): +class ClockifyPermissionsCheckFailed(Exception): + """Timer start failed due to user permissions check. + Message should be self explanatory as traceback won't be shown. + """ + + pass + +class ClockifySync(LauncherAction): name = "sync_to_clockify" label = "Sync to Clockify" - icon = "clockify_white_icon" + icon = "app_icons/clockify-white.png" order = 500 - clockapi = ClockifyAPI() - have_permissions = clockapi.validate_workspace_perm() + clockify_api = ClockifyAPI() def is_compatible(self, session): - """Return whether the action is compatible with the session""" - return self.have_permissions + """Check if there's some projects to sync""" + try: + next(get_projects()) + return True + except StopIteration: + return False def process(self, session, **kwargs): + self.clockify_api.set_api() + workspace_id = self.clockify_api.workspace_id + user_id = self.clockify_api.user_id + if not self.clockify_api.validate_workspace_permissions( + workspace_id, user_id + ): + raise ClockifyPermissionsCheckFailed( + "Current CLockify user is missing permissions for this action!" + ) project_name = session.get("AVALON_PROJECT") or "" projects_to_sync = [] @@ -30,24 +49,28 @@ def process(self, session, **kwargs): task_types = project["config"]["tasks"].keys() projects_info[project["name"]] = task_types - clockify_projects = self.clockapi.get_projects() + clockify_projects = self.clockify_api.get_projects(workspace_id) for project_name, task_types in projects_info.items(): if project_name in clockify_projects: continue - response = self.clockapi.add_project(project_name) + response = self.clockify_api.add_project( + project_name, workspace_id + ) if "id" not in response: - self.log.error("Project {} can't be created".format( - project_name - )) + self.log.error( + "Project {} can't be created".format(project_name) + ) continue - clockify_workspace_tags = self.clockapi.get_tags() + clockify_workspace_tags = self.clockify_api.get_tags(workspace_id) for task_type in task_types: if task_type not in clockify_workspace_tags: - response = self.clockapi.add_tag(task_type) + response = self.clockify_api.add_tag( + task_type, workspace_id + ) if "id" not in response: - self.log.error('Task {} can\'t be created'.format( - task_type - )) + self.log.error( + "Task {} can't be created".format(task_type) + ) continue diff --git a/openpype/modules/clockify/widgets.py b/openpype/modules/clockify/widgets.py index 122b6212c0e..8c28f38b6ef 100644 --- a/openpype/modules/clockify/widgets.py +++ b/openpype/modules/clockify/widgets.py @@ -77,15 +77,15 @@ def close(self, *args, **kwargs): class ClockifySettings(QtWidgets.QWidget): - SIZE_W = 300 + SIZE_W = 500 SIZE_H = 130 loginSignal = QtCore.Signal(object, object, object) - def __init__(self, clockapi, optional=True): + def __init__(self, clockify_api, optional=True): super(ClockifySettings, self).__init__() - self.clockapi = clockapi + self.clockify_api = clockify_api self.optional = optional self.validated = False @@ -162,17 +162,17 @@ def invalid_input(self, entity): def click_ok(self): api_key = self.input_api_key.text().strip() if self.optional is True and api_key == '': - self.clockapi.save_api_key(None) - self.clockapi.set_api(api_key) + self.clockify_api.save_api_key(None) + self.clockify_api.set_api(api_key) self.validated = False self._close_widget() return - validation = self.clockapi.validate_api_key(api_key) + validation = self.clockify_api.validate_api_key(api_key) if validation: - self.clockapi.save_api_key(api_key) - self.clockapi.set_api(api_key) + self.clockify_api.save_api_key(api_key) + self.clockify_api.set_api(api_key) self.validated = True self._close_widget() else: diff --git a/openpype/modules/timers_manager/timers_manager.py b/openpype/modules/timers_manager/timers_manager.py index 0ba68285a4c..43286f7da4a 100644 --- a/openpype/modules/timers_manager/timers_manager.py +++ b/openpype/modules/timers_manager/timers_manager.py @@ -141,7 +141,9 @@ def tray_init(self): signal_handler = SignalHandler(self) idle_manager = IdleManager() widget_user_idle = WidgetUserIdle(self) - widget_user_idle.set_countdown_start(self.time_show_message) + widget_user_idle.set_countdown_start( + self.time_stop_timer - self.time_show_message + ) idle_manager.signal_reset_timer.connect( widget_user_idle.reset_countdown From 0b67d9c7581510ee271aa698a11000874680581d Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 17 Mar 2023 12:07:43 +0000 Subject: [PATCH 478/898] Initial working GPU extractor --- .../maya/plugins/publish/extract_gpu_cache.py | 45 +++++++++++++++++++ openpype/plugins/publish/integrate.py | 2 +- .../plugins/publish/integrate_hero_version.py | 20 ++++++++- 3 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 openpype/hosts/maya/plugins/publish/extract_gpu_cache.py diff --git a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py new file mode 100644 index 00000000000..0e69f6dc571 --- /dev/null +++ b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py @@ -0,0 +1,45 @@ +import os + +from maya import cmds + +from openpype.pipeline import publish +from openpype.hosts.maya.api.lib import ( + maintained_selection, attribute_values, delete_after +) + + +class ExtractGPUCache(publish.Extractor): + """Extract the content of the instance to an CPU cache file.""" + + label = "CPU Cache" + hosts = ["maya"] + families = ["model"] + + def process(self, instance): + staging_dir = self.staging_dir(instance) + filename = "{}.abc".format(instance.name) + + # Write out GPU cache file. + cmds.gpuCache( + instance[:], + directory=staging_dir, + fileName=filename, + saveMultipleFiles=False + ) + + if "representations" not in instance.data: + instance.data["representations"] = [] + + representation = { + "name": "gpu_cache", + "ext": "abc", + "files": filename, + "stagingDir": staging_dir, + "data": {"heroSuffix": "gpu_cache"} + } + + instance.data["representations"].append(representation) + + self.log.info( + "Extracted instance {} to: {}".format(instance.name, staging_dir) + ) diff --git a/openpype/plugins/publish/integrate.py b/openpype/plugins/publish/integrate.py index b1170068716..f8fb6041b33 100644 --- a/openpype/plugins/publish/integrate.py +++ b/openpype/plugins/publish/integrate.py @@ -398,7 +398,7 @@ def register(self, instance, file_transactions, filtered_repres): self.log.debug("{}".format(op_session.to_data())) op_session.commit() - # Backwards compatibility + # Backwards compatibility used in hero integration. # todo: can we avoid the need to store this? instance.data["published_representations"] = { p["representation"]["_id"]: p for p in prepared_representations diff --git a/openpype/plugins/publish/integrate_hero_version.py b/openpype/plugins/publish/integrate_hero_version.py index e796f7b376a..4d7d0accad6 100644 --- a/openpype/plugins/publish/integrate_hero_version.py +++ b/openpype/plugins/publish/integrate_hero_version.py @@ -18,7 +18,7 @@ prepare_hero_version_update_data, prepare_representation_update_data, ) -from openpype.lib import create_hard_link +from openpype.lib import create_hard_link, StringTemplate from openpype.pipeline import ( schema ) @@ -306,6 +306,23 @@ def integrate_instance( anatomy_filled = anatomy.format(anatomy_data) template_filled = anatomy_filled[template_key]["path"] + # For representations that have the same extension, an + # additional suffix can be available to make the destination + # filename different. + hero_suffix = repre_info["representation"]["data"].get( + "heroSuffix" + ) + if hero_suffix: + fill_data = copy.deepcopy(template_filled.used_values) + template_filled.template = template_filled.replace( + "." + fill_data["ext"], + "_{}.{}".format(hero_suffix, fill_data["ext"]) + ) + template_filled = StringTemplate( + template_filled.template + ).format(fill_data) + + # Prepare new repre repre_data = { "path": str(template_filled), "template": hero_template @@ -316,7 +333,6 @@ def integrate_instance( if value is not None: repre_context[key] = value - # Prepare new repre repre = copy.deepcopy(repre_info["representation"]) repre["parent"] = new_hero_version["_id"] repre["context"] = repre_context From cf6242292e6586c7f8c7162337d30cb8a559c4cf Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 17 Mar 2023 13:10:44 +0100 Subject: [PATCH 479/898] Fix #4648: Fix Collect Render for V-Ray, Redshift and Renderman - Not entirely sure this is the correct colorspace solution for all renderers. But at least this hotfixes the collecting. --- openpype/hosts/maya/api/lib_renderproducts.py | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/maya/api/lib_renderproducts.py b/openpype/hosts/maya/api/lib_renderproducts.py index a54256c59a1..ed85b1619a4 100644 --- a/openpype/hosts/maya/api/lib_renderproducts.py +++ b/openpype/hosts/maya/api/lib_renderproducts.py @@ -857,6 +857,7 @@ def get_render_products(self): if default_ext in {"exr (multichannel)", "exr (deep)"}: default_ext = "exr" + colorspace = lib.get_color_management_output_transform() products = [] # add beauty as default when not disabled @@ -868,7 +869,7 @@ def get_render_products(self): productName="", ext=default_ext, camera=camera, - colorspace=lib.get_color_management_output_transform(), + colorspace=colorspace, multipart=self.multipart ) ) @@ -882,6 +883,7 @@ def get_render_products(self): productName="Alpha", ext=default_ext, camera=camera, + colorspace=colorspace, multipart=self.multipart ) ) @@ -917,7 +919,8 @@ def get_render_products(self): product = RenderProduct(productName=name, ext=default_ext, aov=aov, - camera=camera) + camera=camera, + colorspace=colorspace) products.append(product) # Continue as we've processed this special case AOV continue @@ -929,7 +932,7 @@ def get_render_products(self): ext=default_ext, aov=aov, camera=camera, - colorspace=lib.get_color_management_output_transform() + colorspace=colorspace ) products.append(product) @@ -1130,6 +1133,7 @@ def get_render_products(self): products = [] light_groups_enabled = False has_beauty_aov = False + colorspace = lib.get_color_management_output_transform() for aov in aovs: enabled = self._get_attr(aov, "enabled") if not enabled: @@ -1173,7 +1177,8 @@ def get_render_products(self): ext=ext, multipart=False, camera=camera, - driver=aov) + driver=aov, + colorspace=colorspace) products.append(product) if light_groups: @@ -1188,7 +1193,8 @@ def get_render_products(self): ext=ext, multipart=False, camera=camera, - driver=aov) + driver=aov, + colorspace=colorspace) products.append(product) # When a Beauty AOV is added manually, it will be rendered as @@ -1204,7 +1210,8 @@ def get_render_products(self): RenderProduct(productName=beauty_name, ext=ext, multipart=self.multipart, - camera=camera)) + camera=camera, + colorspace=colorspace)) return products @@ -1236,6 +1243,8 @@ def get_render_products(self): """ from rfm2.api.displays import get_displays # noqa + colorspace = lib.get_color_management_output_transform() + cameras = [ self.sanitize_camera_name(c) for c in self.get_renderable_cameras() @@ -1302,7 +1311,8 @@ def get_render_products(self): productName=aov_name, ext=extensions, camera=camera, - multipart=True + multipart=True, + colorspace=colorspace ) if has_cryptomatte and matte_enabled: @@ -1311,7 +1321,8 @@ def get_render_products(self): aov=cryptomatte_aov, ext=extensions, camera=camera, - multipart=True + multipart=True, + colorspace=colorspace ) else: # this code should handle the case where no multipart From c05a3b3b1d8777861114e8ec88732f87f28f6c60 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 17 Mar 2023 12:17:58 +0000 Subject: [PATCH 480/898] Hound and BigRoy feedback --- openpype/hosts/maya/plugins/publish/extract_gpu_cache.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py index 0e69f6dc571..413561e409d 100644 --- a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py +++ b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py @@ -1,17 +1,12 @@ -import os - from maya import cmds from openpype.pipeline import publish -from openpype.hosts.maya.api.lib import ( - maintained_selection, attribute_values, delete_after -) class ExtractGPUCache(publish.Extractor): """Extract the content of the instance to an CPU cache file.""" - label = "CPU Cache" + label = "GPU Cache" hosts = ["maya"] families = ["model"] From 72a0c017608d7947b1c4ac8ba08fc4b66b3bd2eb Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 17 Mar 2023 22:26:36 +0800 Subject: [PATCH 481/898] add callback for setting resolution referenced from DB record for Max --- openpype/hosts/max/api/lib.py | 64 ++++++++++++++++++++++++++++++ openpype/hosts/max/api/menu.py | 13 +++++- openpype/hosts/max/api/pipeline.py | 4 ++ 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index 4fb750d91bd..6a7f63ca75b 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -6,6 +6,13 @@ from typing import Union import contextlib +from openpype.client import ( + get_project +) +from openpype.pipeline import legacy_io + +from openpype.pipeline.context_tools import get_current_project_asset + JSON_PREFIX = "JSON::" @@ -157,6 +164,63 @@ def get_multipass_setting(project_setting=None): ["multipass"]) +def set_scene_resolution(width, height): + """Set the render resolution + + Args: + width(int): value of the width + height(int): value of the height + + Returns: + None + + """ + rt.renderWidth = width + rt.renderHeight = height + + +def reset_scene_resolution(): + """Apply the scene resolution from the project definition + + scene resolution can be overwritten by an asset if the asset.data contains + any information regarding scene resolution . + + Returns: + None + """ + project_name = legacy_io.active_project() + project_doc = get_project(project_name) + project_data = project_doc["data"] + asset_data = get_current_project_asset()["data"] + + # Set project resolution + width_key = "resolutionWidth" + height_key = "resolutionHeight" + proj_width_key = project_data.get(width_key, 1920) + proj_height_key = project_data.get(height_key, 1080) + + width = asset_data.get(width_key, proj_width_key) + height = asset_data.get(height_key, proj_height_key) + + set_scene_resolution(width, height) + + +def set_context_setting(): + """Apply the project settings from the project definition + + Settings can be overwritten by an asset if the asset.data contains + any information regarding those settings. + + Examples of settings: + frame range + resolution + + Returns: + None + """ + reset_scene_resolution() + + def get_max_version(): """ Args: diff --git a/openpype/hosts/max/api/menu.py b/openpype/hosts/max/api/menu.py index 5c273b49b4c..1f189723945 100644 --- a/openpype/hosts/max/api/menu.py +++ b/openpype/hosts/max/api/menu.py @@ -4,7 +4,7 @@ from pymxs import runtime as rt from openpype.tools.utils import host_tools - +from openpype.hosts.max.api import lib class OpenPypeMenu(object): """Object representing OpenPype menu. @@ -107,6 +107,13 @@ def build_openpype_menu(self) -> QtWidgets.QAction: workfiles_action = QtWidgets.QAction("Work Files...", openpype_menu) workfiles_action.triggered.connect(self.workfiles_callback) openpype_menu.addAction(workfiles_action) + + openpype_menu.addSeparator() + + res_action = QtWidgets.QAction("Set Resolution", openpype_menu) + res_action.triggered.connect(self.resolution_callback) + openpype_menu.addAction(res_action) + return openpype_menu def load_callback(self): @@ -128,3 +135,7 @@ def library_callback(self): def workfiles_callback(self): """Callback to show Workfiles tool.""" host_tools.show_workfiles(parent=self.main_widget) + + def resolution_callback(self): + """Callback to reset scene resolution""" + return lib.reset_scene_resolution() diff --git a/openpype/hosts/max/api/pipeline.py b/openpype/hosts/max/api/pipeline.py index f8a7b8ea5c1..b3c12f59bc8 100644 --- a/openpype/hosts/max/api/pipeline.py +++ b/openpype/hosts/max/api/pipeline.py @@ -49,6 +49,10 @@ def install(self): self.menu = OpenPypeMenu() self._has_been_setup = True + def context_setting(): + return lib.set_context_setting() + rt.callbacks.addScript(rt.Name('systemPostNew'), + context_setting) def has_unsaved_changes(self): # TODO: how to get it from 3dsmax? From 543ec0d926e70f285dc008a3fc00623873c8c6d0 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 17 Mar 2023 22:28:48 +0800 Subject: [PATCH 482/898] cosmetic issue fix --- openpype/hosts/max/api/pipeline.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/max/api/pipeline.py b/openpype/hosts/max/api/pipeline.py index b3c12f59bc8..dacc402318d 100644 --- a/openpype/hosts/max/api/pipeline.py +++ b/openpype/hosts/max/api/pipeline.py @@ -49,6 +49,7 @@ def install(self): self.menu = OpenPypeMenu() self._has_been_setup = True + def context_setting(): return lib.set_context_setting() rt.callbacks.addScript(rt.Name('systemPostNew'), From a6805987ca5d2ddaea8c1d97fa98e5a964a0b540 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 17 Mar 2023 14:58:28 +0000 Subject: [PATCH 483/898] Ensure gpu and alembic do not overwrite when integrating. --- openpype/hosts/maya/plugins/publish/extract_gpu_cache.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py index 413561e409d..e77890b5343 100644 --- a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py +++ b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py @@ -30,7 +30,8 @@ def process(self, instance): "ext": "abc", "files": filename, "stagingDir": staging_dir, - "data": {"heroSuffix": "gpu_cache"} + "data": {"heroSuffix": "gpu_cache"}, + "outputName": "gpu_cache" } instance.data["representations"].append(representation) From 00b83e58792db4e33d5d218ce942a8667d724265 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 17 Mar 2023 16:21:27 +0100 Subject: [PATCH 484/898] Refactor `app_data` -> `app_name` --- openpype/hosts/fusion/addon.py | 8 ++++---- openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/fusion/addon.py b/openpype/hosts/fusion/addon.py index 345e348c3b7..45683cfbde1 100644 --- a/openpype/hosts/fusion/addon.py +++ b/openpype/hosts/fusion/addon.py @@ -17,11 +17,11 @@ } -def get_fusion_version(app_data): +def get_fusion_version(app_name): """ The function is triggered by the prelaunch hooks to get the fusion version. - `app_data` is obtained by prelaunch hooks from the + `app_name` is obtained by prelaunch hooks from the `launch_context.env.get("AVALON_APP_NAME")`. To get a correct Fusion version, a version number should be present @@ -31,10 +31,10 @@ def get_fusion_version(app_data): log = Logger.get_logger(__name__) - if not app_data: + if not app_name: return - app_version_candidates = re.findall(r"\d+", app_data) + app_version_candidates = re.findall(r"\d+", app_name) if not app_version_candidates: return for app_version in app_version_candidates: diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py index 15c9424990a..cf168194c31 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -125,8 +125,8 @@ def execute(self): ) = self.get_copy_fusion_prefs_settings() # Get launched application context and return correct app version - app_data = self.launch_context.env.get("AVALON_APP_NAME") - app_version = get_fusion_version(app_data) + app_name = self.launch_context.env.get("AVALON_APP_NAME") + app_version = get_fusion_version(app_name) _, profile_version = FUSION_VERSIONS_DICT[app_version] fu_profile = self.get_fusion_profile_name(profile_version) From c86e8e1d6ea0ae292fe414d5c499451884b230e1 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 17 Mar 2023 16:22:01 +0100 Subject: [PATCH 485/898] Added empty line in the end VSC removed it automatically before. --- openpype/settings/defaults/project_settings/kitsu.json | 2 +- .../entities/schemas/projects_schema/schema_project_kitsu.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/settings/defaults/project_settings/kitsu.json b/openpype/settings/defaults/project_settings/kitsu.json index 738bd95e389..11c138e8e50 100644 --- a/openpype/settings/defaults/project_settings/kitsu.json +++ b/openpype/settings/defaults/project_settings/kitsu.json @@ -14,4 +14,4 @@ } } } -} \ No newline at end of file +} diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index fc421c20f57..7ceb979d6fc 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -82,4 +82,4 @@ ] } ] -} \ No newline at end of file +} From 8a91e4aaa07dc10ae0d0c373749af103e284e5a7 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 17 Mar 2023 16:22:28 +0100 Subject: [PATCH 486/898] Fixed comment --- .../modules/kitsu/plugins/publish/integrate_kitsu_note.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index a5a58c8462c..67702578c53 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -33,8 +33,8 @@ def replace_missing_key(match): if key not in instance.data: self.log.warning( "Key '{}' was not found in instance.data " - "and will be rendered as " - " in the comment".format(key) + "and will be rendered as an empty string " + "in the comment".format(key) ) return "" else: From 94ba8151e72b6d069d8a72fb74477a6ad0f7739c Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Fri, 17 Mar 2023 16:23:13 +0100 Subject: [PATCH 487/898] Read the comment from the instance instead from the context --- .../kitsu/plugins/publish/integrate_kitsu_note.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 67702578c53..cf36bbc4fed 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -45,11 +45,6 @@ def replace_missing_key(match): return re.sub(pattern, replace_missing_key, template) def process(self, context): - # Get comment text body - publish_comment = context.data.get("comment") - if not publish_comment: - self.log.info("Comment is not set.") - for instance in context: # Check if instance is a review by checking its family if "review" not in instance.data["families"]: @@ -76,11 +71,15 @@ def process(self, context): "changed!".format(self.note_status_shortname) ) - # If custom comment, create it + # Get comment text body + publish_comment = instance.data.get("comment") if self.custom_comment_template["enabled"]: publish_comment = self.format_publish_comment(instance) - self.log.debug("Comment is `{}`".format(publish_comment)) + if not publish_comment: + self.log.info("Comment is not set.") + else: + self.log.debug("Comment is `{}`".format(publish_comment)) # Add comment to kitsu task task_id = kitsu_task["id"] From 35157c81de68b6bcb049ce610b31809856273624 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 17 Mar 2023 16:30:04 +0100 Subject: [PATCH 488/898] Report if Fusion version not detected --- .../hosts/fusion/hooks/pre_fusion_profile_hook.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py index cf168194c31..3a4d8274280 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -2,7 +2,7 @@ import shutil import platform from pathlib import Path -from openpype.lib import PreLaunchHook +from openpype.lib import PreLaunchHook, ApplicationLaunchFailed from openpype.hosts.fusion import ( FUSION_HOST_DIR, FUSION_VERSIONS_DICT, @@ -127,6 +127,15 @@ def execute(self): # Get launched application context and return correct app version app_name = self.launch_context.env.get("AVALON_APP_NAME") app_version = get_fusion_version(app_name) + if app_version is None or True: + version_names = ", ".join(str(x) for x in FUSION_VERSIONS_DICT) + raise ApplicationLaunchFailed( + "Unable to detect valid Fusion version number from app " + f"name: {app_name}.\nMake sure to include at least a digit " + "to indicate the Fusion version like '18'.\n" + f"Detectable Fusion versions are: {version_names}" + ) + _, profile_version = FUSION_VERSIONS_DICT[app_version] fu_profile = self.get_fusion_profile_name(profile_version) From 3160a0ede09c859f1a40651af3bf805d1dca2fc7 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 17 Mar 2023 16:30:21 +0100 Subject: [PATCH 489/898] Remove the debugging logic :) --- openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py index 3a4d8274280..ee80a9c90ae 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -127,7 +127,7 @@ def execute(self): # Get launched application context and return correct app version app_name = self.launch_context.env.get("AVALON_APP_NAME") app_version = get_fusion_version(app_name) - if app_version is None or True: + if app_version is None: version_names = ", ".join(str(x) for x in FUSION_VERSIONS_DICT) raise ApplicationLaunchFailed( "Unable to detect valid Fusion version number from app " From f6be90d7a415636e2e848ee4c0f3766dbf87eda6 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 17 Mar 2023 16:33:16 +0100 Subject: [PATCH 490/898] Debug log instead of info log --- openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py index ee80a9c90ae..4e5ff4159b0 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -93,8 +93,8 @@ def copy_fusion_profile( "Destination Fusion preferences folder already exists" ) return - self.log.info(f"Starting copying Fusion preferences") - self.log.info(f"force_sync option is set to {force_sync}") + self.log.info("Starting copying Fusion preferences") + self.log.debug(f"force_sync option is set to {force_sync}") try: copy_to.mkdir(exist_ok=True, parents=True) except PermissionError: From c71651e29e7c51e13513095c5f43180645375404 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 17 Mar 2023 16:37:51 +0100 Subject: [PATCH 491/898] Match other method calls to `warning` --- openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py index 4e5ff4159b0..b0a4e19f44b 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -98,7 +98,7 @@ def copy_fusion_profile( try: copy_to.mkdir(exist_ok=True, parents=True) except PermissionError: - self.log.warn(f"Creating the folder not permitted at {copy_to}") + self.log.warning(f"Creating the folder not permitted at {copy_to}") return if not copy_from.exists(): self.log.warning(f"Fusion preferences not found in {copy_from}") From b63b02687011d1771f6165754e280e062e0ff763 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 17 Mar 2023 15:38:44 +0000 Subject: [PATCH 492/898] Filter to transforms with shapes only. --- .../maya/plugins/publish/extract_arnold_scene_source.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index 7348c2db4d7..63e6ff0f367 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -124,6 +124,13 @@ def _extract(self, nodes, attribute_data, kwargs): if cmds.nodeType(node) != "transform": continue + # Only interested in transforms with shapes. + shapes = cmds.listRelatives( + node, shapes=True, fullPath=True + ) or [] + if not shapes: + continue + parent = cmds.listRelatives( node, parent=True, fullPath=True )[0] From 6a06f80db0e600fdc28d85a8ccac839a38c64ead Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 17 Mar 2023 16:39:39 +0100 Subject: [PATCH 493/898] Cosmetics + do not add new line because its confusing in command line logs --- openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py index b0a4e19f44b..339cf35a7d2 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -114,7 +114,7 @@ def copy_fusion_profile( # convert Path to str to be compatible with Python 3.6+ shutil.copy(str(file), str(copy_to)) self.log.info( - f"successfully copied preferences:\n {copy_from} to {copy_to}" + f"Successfully copied preferences: {copy_from} to {copy_to}" ) def execute(self): From ae44c0de29af77db9d3e9a342acc5b341cab4954 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 17 Mar 2023 16:42:23 +0100 Subject: [PATCH 494/898] Report the existing folder in the log --- openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py index 339cf35a7d2..fd726ccda14 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -90,7 +90,8 @@ def copy_fusion_profile( """ if copy_to.exists() and not force_sync: self.log.info( - "Destination Fusion preferences folder already exists" + "Destination Fusion preferences folder already exists: " + f"{copy_to} " ) return self.log.info("Starting copying Fusion preferences") From a13f80ef972a4aec8c2a972d9566fa1c4afdef60 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Fri, 17 Mar 2023 17:14:22 +0100 Subject: [PATCH 495/898] Maya: Yeti Validate Rig Input - OP-3454 (#4554) * Collect input_SET children in instance. * Fix docs. * Only validate yeti if there are nodes in the scene. * Revert code * Remove connection logic from loader * Connection inventory action * Hound * Revert "Collect input_SET children in instance." This reverts commit 052e65ca1befb19049ee9f02f472d20cf78d8dc1. * Update docs * Update openpype/hosts/maya/plugins/inventory/connect_yeti_rig.py Co-authored-by: Roy Nieterau * Update openpype/hosts/maya/plugins/inventory/connect_yeti_rig.py Co-authored-by: Roy Nieterau * Update openpype/hosts/maya/plugins/inventory/connect_yeti_rig.py Co-authored-by: Roy Nieterau * Update website/docs/artist_hosts_maya_yeti.md Co-authored-by: Roy Nieterau * BigRoy feedback * Hound * Fix typo * Update openpype/hosts/maya/plugins/inventory/connect_yeti_rig.py Co-authored-by: Roy Nieterau * Update openpype/hosts/maya/plugins/publish/validate_yeti_renderscript_callbacks.py Co-authored-by: Roy Nieterau * Update openpype/hosts/maya/plugins/inventory/connect_yeti_rig.py Co-authored-by: Roy Nieterau * Dont use AVALON_PROJECT * Hound * Update openpype/hosts/maya/plugins/publish/validate_yeti_renderscript_callbacks.py Co-authored-by: Roy Nieterau --------- Co-authored-by: Roy Nieterau --- .../plugins/inventory/connect_yeti_rig.py | 178 ++++++++++++++++++ .../hosts/maya/plugins/load/load_yeti_rig.py | 94 +++------ .../validate_yeti_renderscript_callbacks.py | 12 ++ website/docs/artist_hosts_maya_yeti.md | 83 ++++---- website/docs/assets/maya-yeti_hair_setup.png | Bin 0 -> 138812 bytes .../assets/maya-yeti_load_connections.png | Bin 0 -> 125692 bytes .../docs/assets/maya-yeti_publish_setup.png | Bin 0 -> 133890 bytes website/docs/assets/maya-yeti_rig.jpg | Bin 59405 -> 0 bytes website/docs/assets/maya-yeti_rig_setup.png | Bin 0 -> 111360 bytes website/docs/assets/maya-yeti_simple_rig.png | Bin 0 -> 96188 bytes 10 files changed, 260 insertions(+), 107 deletions(-) create mode 100644 openpype/hosts/maya/plugins/inventory/connect_yeti_rig.py create mode 100644 website/docs/assets/maya-yeti_hair_setup.png create mode 100644 website/docs/assets/maya-yeti_load_connections.png create mode 100644 website/docs/assets/maya-yeti_publish_setup.png delete mode 100644 website/docs/assets/maya-yeti_rig.jpg create mode 100644 website/docs/assets/maya-yeti_rig_setup.png create mode 100644 website/docs/assets/maya-yeti_simple_rig.png diff --git a/openpype/hosts/maya/plugins/inventory/connect_yeti_rig.py b/openpype/hosts/maya/plugins/inventory/connect_yeti_rig.py new file mode 100644 index 00000000000..924a1a46277 --- /dev/null +++ b/openpype/hosts/maya/plugins/inventory/connect_yeti_rig.py @@ -0,0 +1,178 @@ +import os +import json +from collections import defaultdict + +from maya import cmds + +from openpype.pipeline import ( + InventoryAction, get_representation_context, get_representation_path +) +from openpype.hosts.maya.api.lib import get_container_members, get_id + + +class ConnectYetiRig(InventoryAction): + """Connect Yeti Rig with an animation or pointcache.""" + + label = "Connect Yeti Rig" + icon = "link" + color = "white" + + def process(self, containers): + # Validate selection is more than 1. + message = ( + "Only 1 container selected. 2+ containers needed for this action." + ) + if len(containers) == 1: + self.display_warning(message) + return + + # Categorize containers by family. + containers_by_family = defaultdict(list) + for container in containers: + family = get_representation_context( + container["representation"] + )["subset"]["data"]["family"] + containers_by_family[family].append(container) + + # Validate to only 1 source container. + source_containers = containers_by_family.get("animation", []) + source_containers += containers_by_family.get("pointcache", []) + source_container_namespaces = [ + x["namespace"] for x in source_containers + ] + message = ( + "{} animation containers selected:\n\n{}\n\nOnly select 1 of type " + "\"animation\" or \"pointcache\".".format( + len(source_containers), source_container_namespaces + ) + ) + if len(source_containers) != 1: + self.display_warning(message) + return + + source_container = source_containers[0] + source_ids = self.nodes_by_id(source_container) + + # Target containers. + target_ids = {} + inputs = [] + + yeti_rig_containers = containers_by_family.get("yetiRig") + if not yeti_rig_containers: + self.display_warning( + "Select at least one yetiRig container" + ) + return + + for container in yeti_rig_containers: + target_ids.update(self.nodes_by_id(container)) + + maya_file = get_representation_path( + get_representation_context( + container["representation"] + )["representation"] + ) + _, ext = os.path.splitext(maya_file) + settings_file = maya_file.replace(ext, ".rigsettings") + if not os.path.exists(settings_file): + continue + + with open(settings_file) as f: + inputs.extend(json.load(f)["inputs"]) + + # Compare loaded connections to scene. + for input in inputs: + source_node = source_ids.get(input["sourceID"]) + target_node = target_ids.get(input["destinationID"]) + + if not source_node or not target_node: + self.log.debug( + "Could not find nodes for input:\n" + + json.dumps(input, indent=4, sort_keys=True) + ) + continue + source_attr, target_attr = input["connections"] + + if not cmds.attributeQuery( + source_attr, node=source_node, exists=True + ): + self.log.debug( + "Could not find attribute {} on node {} for " + "input:\n{}".format( + source_attr, + source_node, + json.dumps(input, indent=4, sort_keys=True) + ) + ) + continue + + if not cmds.attributeQuery( + target_attr, node=target_node, exists=True + ): + self.log.debug( + "Could not find attribute {} on node {} for " + "input:\n{}".format( + target_attr, + target_node, + json.dumps(input, indent=4, sort_keys=True) + ) + ) + continue + + source_plug = "{}.{}".format( + source_node, source_attr + ) + target_plug = "{}.{}".format( + target_node, target_attr + ) + if cmds.isConnected( + source_plug, target_plug, ignoreUnitConversion=True + ): + self.log.debug( + "Connection already exists: {} -> {}".format( + source_plug, target_plug + ) + ) + continue + + cmds.connectAttr(source_plug, target_plug, force=True) + self.log.debug( + "Connected attributes: {} -> {}".format( + source_plug, target_plug + ) + ) + + def nodes_by_id(self, container): + ids = {} + for member in get_container_members(container): + id = get_id(member) + if not id: + continue + ids[id] = member + + return ids + + def display_warning(self, message, show_cancel=False): + """Show feedback to user. + + Returns: + bool + """ + + from qtpy import QtWidgets + + accept = QtWidgets.QMessageBox.Ok + if show_cancel: + buttons = accept | QtWidgets.QMessageBox.Cancel + else: + buttons = accept + + state = QtWidgets.QMessageBox.warning( + None, + "", + message, + buttons=buttons, + defaultButton=accept + ) + + return state == accept diff --git a/openpype/hosts/maya/plugins/load/load_yeti_rig.py b/openpype/hosts/maya/plugins/load/load_yeti_rig.py index 651607de8a5..6a13d2e145a 100644 --- a/openpype/hosts/maya/plugins/load/load_yeti_rig.py +++ b/openpype/hosts/maya/plugins/load/load_yeti_rig.py @@ -1,17 +1,12 @@ -import os -from collections import defaultdict +import maya.cmds as cmds -from openpype.settings import get_project_settings +from openpype.settings import get_current_project_settings import openpype.hosts.maya.api.plugin from openpype.hosts.maya.api import lib class YetiRigLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): - """ - This loader will load Yeti rig. You can select something in scene and if it - has same ID as mesh published with rig, their shapes will be linked - together. - """ + """This loader will load Yeti rig.""" families = ["yetiRig"] representations = ["ma"] @@ -22,72 +17,31 @@ class YetiRigLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): color = "orange" def process_reference( - self, context, name=None, namespace=None, options=None): + self, context, name=None, namespace=None, options=None + ): - import maya.cmds as cmds - - # get roots of selected hierarchies - selected_roots = [] - for sel in cmds.ls(sl=True, long=True): - selected_roots.append(sel.split("|")[1]) - - # get all objects under those roots - selected_hierarchy = [] - for root in selected_roots: - selected_hierarchy.append(cmds.listRelatives( - root, - allDescendents=True) or []) - - # flatten the list and filter only shapes - shapes_flat = [] - for root in selected_hierarchy: - shapes = cmds.ls(root, long=True, type="mesh") or [] - for shape in shapes: - shapes_flat.append(shape) - - # create dictionary of cbId and shape nodes - scene_lookup = defaultdict(list) - for node in shapes_flat: - cb_id = lib.get_id(node) - scene_lookup[cb_id] = node - - # load rig + group_name = "{}:{}".format(namespace, name) with lib.maintained_selection(): - file_url = self.prepare_root_value(self.fname, - context["project"]["name"]) - nodes = cmds.file(file_url, - namespace=namespace, - reference=True, - returnNewNodes=True, - groupReference=True, - groupName="{}:{}".format(namespace, name)) - - # for every shape node we've just loaded find matching shape by its - # cbId in selection. If found outMesh of scene shape will connect to - # inMesh of loaded shape. - for destination_node in nodes: - source_node = scene_lookup[lib.get_id(destination_node)] - if source_node: - self.log.info("found: {}".format(source_node)) - self.log.info( - "creating connection to {}".format(destination_node)) - - cmds.connectAttr("{}.outMesh".format(source_node), - "{}.inMesh".format(destination_node), - force=True) - - groupName = "{}:{}".format(namespace, name) - - settings = get_project_settings(os.environ['AVALON_PROJECT']) - colors = settings['maya']['load']['colors'] + file_url = self.prepare_root_value( + self.fname, context["project"]["name"] + ) + nodes = cmds.file( + file_url, + namespace=namespace, + reference=True, + returnNewNodes=True, + groupReference=True, + groupName=group_name + ) - c = colors.get('yetiRig') + settings = get_current_project_settings() + colors = settings["maya"]["load"]["colors"] + c = colors.get("yetiRig") if c is not None: - cmds.setAttr(groupName + ".useOutlinerColor", 1) - cmds.setAttr(groupName + ".outlinerColor", - (float(c[0])/255), - (float(c[1])/255), - (float(c[2])/255) + cmds.setAttr(group_name + ".useOutlinerColor", 1) + cmds.setAttr( + group_name + ".outlinerColor", + (float(c[0]) / 255), (float(c[1]) / 255), (float(c[2]) / 255) ) self[:] = nodes diff --git a/openpype/hosts/maya/plugins/publish/validate_yeti_renderscript_callbacks.py b/openpype/hosts/maya/plugins/publish/validate_yeti_renderscript_callbacks.py index a864a18cee9..06250f57795 100644 --- a/openpype/hosts/maya/plugins/publish/validate_yeti_renderscript_callbacks.py +++ b/openpype/hosts/maya/plugins/publish/validate_yeti_renderscript_callbacks.py @@ -48,6 +48,18 @@ def get_invalid(cls, instance): yeti_loaded = cmds.pluginInfo("pgYetiMaya", query=True, loaded=True) + if not yeti_loaded and not cmds.ls(type="pgYetiMaya"): + # The yeti plug-in is available and loaded so at + # this point we don't really care whether the scene + # has any yeti callback set or not since if the callback + # is there it wouldn't error and if it weren't then + # nothing happens because there are no yeti nodes. + cls.log.info( + "Yeti is loaded but no yeti nodes were found. " + "Callback validation skipped.." + ) + return False + renderer = instance.data["renderer"] if renderer == "redshift": cls.log.info("Redshift ignores any pre and post render callbacks") diff --git a/website/docs/artist_hosts_maya_yeti.md b/website/docs/artist_hosts_maya_yeti.md index f5a6a4d2c95..aa783cc8b61 100644 --- a/website/docs/artist_hosts_maya_yeti.md +++ b/website/docs/artist_hosts_maya_yeti.md @@ -9,7 +9,9 @@ sidebar_label: Yeti OpenPype can work with [Yeti](https://peregrinelabs.com/yeti/) in two data modes. It can handle Yeti caches and Yeti rigs. -### Creating and publishing Yeti caches +## Yeti Caches + +### Creating and publishing Let start by creating simple Yeti setup, just one object and Yeti node. Open new empty scene in Maya and create sphere. Then select sphere and go **Yeti → Create Yeti Node on Mesh** @@ -44,7 +46,15 @@ You can now publish Yeti cache as any other types. **OpenPype → Publish**. It create sequence of `.fur` files and `.fursettings` metadata file with Yeti node setting. -### Loading Yeti caches +:::note Collect Yeti Cache failure +If you encounter **Collect Yeti Cache** failure during collecting phase, and the error is like +```fix +No object matches name: pgYetiMaya1Shape.cbId +``` +then it is probably caused by scene not being saved before publishing. +::: + +### Loading You can load Yeti cache by **OpenPype → Load ...**. Select your cache, right+click on it and select **Load Yeti cache**. This will create Yeti node in scene and set its @@ -52,26 +62,39 @@ cache path to point to your published cache files. Note that this Yeti node will be named with same name as the one you've used to publish cache. Also notice that when you open graph on this Yeti node, all nodes are as they were in publishing node. -### Creating and publishing Yeti Rig +## Yeti Rigs + +### Creating and publishing + +Yeti Rigs are designed to connect to published models or animation rig. The workflow gives the Yeti Rig full control on that geometry to do additional things on top of whatever input comes in, e.g. deleting faces, pushing faces in/out, subdividing, etc. + +Let's start with a [model](artist_hosts_maya.md#loading-model) or [rig](artist_hosts_maya.md#loading-rigs) loaded into the scene. Here we are using a simple rig. -Yeti Rigs are working in similar way as caches, but are more complex and they deal with -other data used by Yeti, like geometry and textures. +![Maya - Yeti Simple Rig](assets/maya-yeti_simple_rig.png) -Let's start by [loading](artist_hosts_maya.md#loading-model) into new scene some model. -I've loaded my Buddha model. +We'll need to prepare the scene a bit. We want some Yeti hair on the ball geometry, so duplicating the geometry, adding the Yeti hair and grouping it together. + +![Maya - Yeti Hair Setup](assets/maya-yeti_hair_setup.png) + +:::note yeti nodes and types +You can use any number of Yeti nodes and types, but they have to have unique names. +::: -Create select model mesh, create Yeti node - **Yeti → Create Yeti Node on Mesh** and -setup similar Yeti graph as in cache example above. +Now we need to connect the Yeti Rig with the animation rig. Yeti Rigs work by publishing the attribute connections from its input nodes and reconnect them later in the pipeline. This means we can only use attribute connections to from outside of the Yeti Rig hierarchy. Internal to the Yeti Rig hierarchy, we can use any complexity of node connections. We'll connnect the Yeti Rig geometry to the animation rig, with the transform and mesh attributes. -Then select this Yeti node (mine is called with default name `pgYetiMaya1`) and -create *Yeti Rig instance* - **OpenPype → Create...** and select **Yeti Cache**. +![Maya - Yeti Rig Setup](assets/maya-yeti_rig_setup.png) + +Now we are ready for publishing. Select the Yeti Rig group (`rig_GRP`) and +create *Yeti Rig instance* - **OpenPype → Create...** and select **Yeti Rig**. Leave `Use selection` checked. -Last step is to add our model geometry to rig instance, so middle+drag its -geometry to `input_SET` under `yetiRigDefault` set representing rig instance. +Last step is to add our geometry to the rig instance, so middle+drag its +geometry to `input_SET` under the `yetiRigMain` set representing rig instance. Note that its name can differ and is based on your subset name. -![Maya - Yeti Rig Setup](assets/maya-yeti_rig.jpg) +![Maya - Yeti Publish Setup](assets/maya-yeti_publish_setup.png) + +You can have any number of nodes in the Yeti Rig, but only nodes with incoming attribute connections from outside of the Yeti Rig hierarchy is needed in the `input_SET`. Save your scene and ready for publishing our new simple Yeti Rig! @@ -81,28 +104,14 @@ the beginning of your timeline. It will also collect all textures used in Yeti node, copy them to publish folder `resource` directory and set *Image search path* of published node to this location. -:::note Collect Yeti Cache failure -If you encounter **Collect Yeti Cache** failure during collecting phase, and the error is like -```fix -No object matches name: pgYetiMaya1Shape.cbId -``` -then it is probably caused by scene not being saved before publishing. -::: - -### Loading Yeti Rig +### Loading -You can load published Yeti Rigs as any other thing in OpenPype - **OpenPype → Load ...**, +You can load published Yeti Rigs in OpenPype with **OpenPype → Load ...**, select you Yeti rig and right+click on it. In context menu you should see -**Load Yeti Cache** and **Load Yeti Rig** items (among others). First one will -load that one frame cache. The other one will load whole rig. - -Notice that although we put only geometry into `input_SET`, whole hierarchy was -pulled inside also. This allows you to store complex scene element along Yeti -node. - -:::tip auto-connecting rig mesh to existing one -If you select some objects before loading rig it will try to find shapes -under selected hierarchies and match them with shapes loaded with rig (published -under `input_SET`). This mechanism uses *cbId* attribute on those shapes. -If match is found shapes are connected using their `outMesh` and `outMesh`. Thus you can easily connect existing animation to loaded rig. -::: +**Load Yeti Rig** item (among others). + +To connect the Yeti Rig with published animation, we'll load in the animation and use the Inventory to establish the connections. + +![Maya - Yeti Publish Setup](assets/maya-yeti_load_connections.png) + +The Yeti Rig should now be following the animation. :tada: diff --git a/website/docs/assets/maya-yeti_hair_setup.png b/website/docs/assets/maya-yeti_hair_setup.png new file mode 100644 index 0000000000000000000000000000000000000000..8cd7f5f97a259bb653d7bdbe171d9a12cf8ac7be GIT binary patch literal 138812 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 MZWh2!_Zu@zC-RKjZe8Y@R=?oKtf2P(R@GSfdH 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

6UB=BTN2JGQDhT}p%k(-!~F@xZG> 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≦Kv8 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 literal 0 HcmV?d00001 diff --git a/website/docs/assets/maya-yeti_rig.jpg b/website/docs/assets/maya-yeti_rig.jpg deleted file mode 100644 index 07b13db409d0ad6bf1f887896e6f3d0fd5e7e10b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59405 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%0D1;wn^$71V{3R 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 EFKbZ!`Tzg` diff --git a/website/docs/assets/maya-yeti_rig_setup.png b/website/docs/assets/maya-yeti_rig_setup.png new file mode 100644 index 0000000000000000000000000000000000000000..876ecba0a2b0e4496f590a650de56532c3b104f0 GIT binary patch literal 111360 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
^s@U(eB2|H$bp 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 literal 0 HcmV?d00001 diff --git a/website/docs/assets/maya-yeti_simple_rig.png b/website/docs/assets/maya-yeti_simple_rig.png new file mode 100644 index 0000000000000000000000000000000000000000..31a60ac40b3f712e7ecd1bcdac4fc80017977594 GIT binary patch literal 96188 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

`}O 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 literal 0 HcmV?d00001 From 3159bcb878a4002459d2dbcd52f63216453475e0 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 17 Mar 2023 17:39:54 +0100 Subject: [PATCH 496/898] Use right plugic class for 'CollectInstanceCommentDef' --- openpype/plugins/publish/collect_comment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/plugins/publish/collect_comment.py b/openpype/plugins/publish/collect_comment.py index 5be04731ace..9f41e37f222 100644 --- a/openpype/plugins/publish/collect_comment.py +++ b/openpype/plugins/publish/collect_comment.py @@ -29,7 +29,7 @@ class CollectInstanceCommentDef( - pyblish.api.ContextPlugin, + pyblish.api.InstancePlugin, OpenPypePyblishPluginMixin ): label = "Comment per instance" From ab4179d49a06185da3b852861c50e216ad226238 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 17 Mar 2023 16:51:36 +0000 Subject: [PATCH 497/898] Properly get and set model panel camera. --- .../maya/plugins/publish/extract_playblast.py | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_playblast.py b/openpype/hosts/maya/plugins/publish/extract_playblast.py index 06d3ccb4a9f..a652db2eb5e 100644 --- a/openpype/hosts/maya/plugins/publish/extract_playblast.py +++ b/openpype/hosts/maya/plugins/publish/extract_playblast.py @@ -114,21 +114,12 @@ def process(self, instance): # Image planes do not update the file sequence unless the active panel # is viewing through the camera. - model_panel = instance.context.data.get("model_panel") - if not model_panel: - model_panels = cmds.getPanel(type="modelPanel") - visible_panels = cmds.getPanel(visiblePanels=True) - model_panel = list( - set(visible_panels) - (set(visible_panels) - set(model_panels)) - )[0] - instance.context.data["model_panel"] = model_panel - - panel_camera = instance.context.data.get("panel_camera") - if not panel_camera: - panel_camera = capture.parse_view(model_panel)["camera"] - instance.context.data["panel_camera"] = panel_camera - - cmds.modelPanel(model_panel, edit=True, camera=preset["camera"]) + panel_camera = cmds.modelPanel( + instance.data["panel"], query=True, camera=True + ) + cmds.modelPanel( + instance.data["panel"], edit=True, camera=preset["camera"] + ) # Disable Pan/Zoom. pan_zoom = cmds.getAttr("{}.panZoomEnabled".format(preset["camera"])) @@ -188,7 +179,7 @@ def process(self, instance): cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), pan_zoom) # Restore panel camera. - cmds.modelPanel(model_panel, edit=True, camera=panel_camera) + cmds.modelPanel(instance.data["panel"], edit=True, camera=panel_camera) self.log.debug("playblast path {}".format(path)) From 785c352407a2953a05bc958555e236a3771f4e09 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 17 Mar 2023 17:41:33 +0000 Subject: [PATCH 498/898] Adjust loader for extractor. --- openpype/hosts/maya/plugins/load/load_gpucache.py | 2 +- openpype/hosts/maya/plugins/publish/extract_gpu_cache.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/load/load_gpucache.py b/openpype/hosts/maya/plugins/load/load_gpucache.py index 07e5734f43d..b7ca7292f5c 100644 --- a/openpype/hosts/maya/plugins/load/load_gpucache.py +++ b/openpype/hosts/maya/plugins/load/load_gpucache.py @@ -11,7 +11,7 @@ class GpuCacheLoader(load.LoaderPlugin): """Load Alembic as gpuCache""" families = ["model", "animation", "proxyAbc", "pointcache"] - representations = ["abc"] + representations = ["gpu_cache"] label = "Import Gpu Cache" order = -5 diff --git a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py index e77890b5343..db848337226 100644 --- a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py +++ b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py @@ -8,7 +8,7 @@ class ExtractGPUCache(publish.Extractor): label = "GPU Cache" hosts = ["maya"] - families = ["model"] + families = ["model", "animation", "pointcache"] def process(self, instance): staging_dir = self.staging_dir(instance) From f050a024aa5c97cb61c2f780349e89dbce5c0f82 Mon Sep 17 00:00:00 2001 From: Thomas Fricard Date: Thu, 16 Mar 2023 16:52:06 +0100 Subject: [PATCH 499/898] add an include parent hierarchy option in animation creator plugin of maya --- openpype/hosts/maya/plugins/create/create_animation.py | 4 +++- openpype/settings/defaults/project_settings/maya.json | 1 + .../schemas/projects_schema/schemas/schema_maya_create.json | 5 +++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/create/create_animation.py b/openpype/hosts/maya/plugins/create/create_animation.py index a4b6e865982..2ea1b22bcb6 100644 --- a/openpype/hosts/maya/plugins/create/create_animation.py +++ b/openpype/hosts/maya/plugins/create/create_animation.py @@ -13,6 +13,7 @@ class CreateAnimation(plugin.Creator): icon = "male" write_color_sets = False write_face_sets = False + include_parent_hierarchy = False include_user_defined_attributes = False def __init__(self, *args, **kwargs): @@ -37,7 +38,8 @@ def __init__(self, *args, **kwargs): self.data["visibleOnly"] = False # Include the groups above the out_SET content - self.data["includeParentHierarchy"] = False # Include parent groups + # Include parent groups + self.data["includeParentHierarchy"] = self.include_parent_hierarchy # Default to exporting world-space self.data["worldSpace"] = True diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index 63ba4542f3f..2aa95fd1be6 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -147,6 +147,7 @@ "enabled": true, "write_color_sets": false, "write_face_sets": false, + "include_parent_hierarchy": false, "include_user_defined_attributes": false, "defaults": [ "Main" diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json index 1598f906439..d6e6c97b8cd 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json @@ -132,6 +132,11 @@ "key": "write_face_sets", "label": "Write Face Sets" }, + { + "type": "boolean", + "key": "include_parent_hierarchy", + "label": "Include Parent Hierarchy" + }, { "type": "boolean", "key": "include_user_defined_attributes", From 3eb8833596bf5b0780ebf4eca381e937e62c29b1 Mon Sep 17 00:00:00 2001 From: Thomas Fricard <51854004+friquette@users.noreply.github.com> Date: Fri, 17 Mar 2023 09:06:45 +0100 Subject: [PATCH 500/898] Update openpype/hosts/maya/plugins/create/create_animation.py Co-authored-by: Roy Nieterau --- openpype/hosts/maya/plugins/create/create_animation.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/create/create_animation.py b/openpype/hosts/maya/plugins/create/create_animation.py index 2ea1b22bcb6..f992ff2c1af 100644 --- a/openpype/hosts/maya/plugins/create/create_animation.py +++ b/openpype/hosts/maya/plugins/create/create_animation.py @@ -38,7 +38,6 @@ def __init__(self, *args, **kwargs): self.data["visibleOnly"] = False # Include the groups above the out_SET content - # Include parent groups self.data["includeParentHierarchy"] = self.include_parent_hierarchy # Default to exporting world-space From ecdc8966d05b9cd5256b664dd635b7004ccfb860 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 13 Jan 2023 12:36:20 +0100 Subject: [PATCH 501/898] Implement Maya image file node loader --- .../hosts/maya/plugins/load/load_image.py | 176 ++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 openpype/hosts/maya/plugins/load/load_image.py diff --git a/openpype/hosts/maya/plugins/load/load_image.py b/openpype/hosts/maya/plugins/load/load_image.py new file mode 100644 index 00000000000..cdd895ff4b4 --- /dev/null +++ b/openpype/hosts/maya/plugins/load/load_image.py @@ -0,0 +1,176 @@ +from openpype.pipeline import ( + load, + get_representation_path +) +from openpype.lib import EnumDef +from openpype.hosts.maya.api.pipeline import containerise +from openpype.hosts.maya.api.lib import ( + unique_namespace, + namespaced +) + +from maya import cmds + + +def create_texture(): + """Create place2dTexture with file node with uv connections + + Mimics Maya "file [Texture]" creation. + """ + + place = cmds.shadingNode("place2dTexture", asUtility=True, name="place2d") + file = cmds.shadingNode("file", asTexture=True, name="file") + + connections = ["coverage", "translateFrame", "rotateFrame", "rotateUV", + "mirrorU", "mirrorV", "stagger", "wrapV", "wrapU", + "repeatUV", "offset", "noiseUV", "vertexUvThree", + "vertexUvTwo", "vertexUvOne", "vertexCameraOne"] + for attr in connections: + src = "{}.{}".format(place, attr) + dest = "{}.{}".format(file, attr) + cmds.connectAttr(src, dest) + + cmds.connectAttr(place + '.outUV', file + '.uvCoord') + cmds.connectAttr(place + '.outUvFilterSize', file + '.uvFilterSize') + + return file, place + + +def create_projection(): + """Create texture with place3dTexture and projection + + Mimics Maya "file [Projection]" creation. + """ + + file, place = create_texture() + projection = cmds.shadingNode("projection", asTexture=True, + name="projection") + place3d = cmds.shadingNode("place3dTexture", asUtility=True, + name="place3d") + + cmds.connectAttr(place3d + '.worldInverseMatrix[0]', + projection + ".placementMatrix") + cmds.connectAttr(file + '.outColor', projection + ".image") + + return file, place, projection, place3d + + +def create_stencil(): + """Create texture with extra place2dTexture offset and stencil + + Mimics Maya "file [Stencil]" creation. + """ + + file, place = create_texture() + + place_stencil = cmds.shadingNode("place2dTexture", asUtility=True, + name="place2d_stencil") + stencil = cmds.shadingNode("stencil", asTexture=True, name="stencil") + + for src_attr, dest_attr in [ + ("outUV", "uvCoord"), + ("outUvFilterSize", "uvFilterSize") + ]: + src_plug = "{}.{}".format(place_stencil, src_attr) + cmds.connectAttr(src_plug, "{}.{}".format(place, dest_attr)) + cmds.connectAttr(src_plug, "{}.{}".format(stencil, dest_attr)) + + return file, place, stencil, place_stencil + + +class FileNodeLoader(load.LoaderPlugin): + """File node loader.""" + # TODO: Implement color space manamagent OCIO (set correct color space) + + families = ["image", "plate", "render"] + label = "Load file node" + representations = ["exr", "tif", "png", "jpg"] + icon = "image" + color = "orange" + order = 2 + + options = [ + EnumDef( + "mode", + items={ + "texture": "Texture", + "projection": "Projection", + "stencil": "Stencil" + }, + default="texture", + label="Texture Mode" + ) + ] + + def load(self, context, name, namespace, data): + + path = self.fname + asset = context['asset']['name'] + namespace = namespace or unique_namespace( + asset + "_", + prefix="_" if asset[0].isdigit() else "", + suffix="_", + ) + + with namespaced(namespace, new=True) as namespace: + # Create the nodes within the namespace + nodes = { + "texture": create_texture, + "projection": create_projection, + "stencil": create_stencil + }[data.get("mode", "texture")]() + + # Set the file node attributes + file_node = cmds.ls(nodes, type="file")[0] + cmds.setAttr(file_node + ".fileTextureName", path, type="string") + + # Set UV tiling mode if UDIM tiles + # TODO: Detect UDIM tiles and set accordingly (also on update) + cmds.setAttr(file_node + ".uvTilingMode", 3) # UDIM-tiles + + # Enable sequence if publish has `startFrame` and `endFrame` and + # `startFrame != endFrame` + # TODO: Detect sequences (also on update) + # cmds.setAttr(file_node + ".useFrameExtension", True) + + # For ease of access for the user select all the nodes and select + # the file node last so that UI shows its attributes by default + cmds.select(list(nodes) + [file_node], replace=True) + + return containerise( + name=name, + namespace=namespace, + nodes=nodes, + context=context, + loader=self.__class__.__name__ + ) + + def update(self, container, representation): + + path = get_representation_path(representation) + members = cmds.sets(container['objectName'], query=True) + + file_node = cmds.ls(members, type="file")[0] + cmds.setAttr(file_node + ".fileTextureName", path, type="string") + + # Update representation + cmds.setAttr( + container["objectName"] + ".representation", + str(representation["_id"]), + type="string" + ) + + def switch(self, container, representation): + self.update(container, representation) + + def remove(self, container): + members = cmds.sets(container['objectName'], query=True) + cmds.lockNode(members, lock=False) + cmds.delete([container['objectName']] + members) + + # Clean up the namespace + try: + cmds.namespace(removeNamespace=container['namespace'], + deleteNamespaceContent=True) + except RuntimeError: + pass From c6b583e85f96acd48d2951b38e89666007075e95 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 6 Mar 2023 11:36:51 +0100 Subject: [PATCH 502/898] Detect udim and frame sequences --- .../hosts/maya/plugins/load/load_image.py | 39 +++++++++++++++++-- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/maya/plugins/load/load_image.py b/openpype/hosts/maya/plugins/load/load_image.py index cdd895ff4b4..117d1a7d0fb 100644 --- a/openpype/hosts/maya/plugins/load/load_image.py +++ b/openpype/hosts/maya/plugins/load/load_image.py @@ -112,6 +112,10 @@ def load(self, context, name, namespace, data): suffix="_", ) + repre_context = context["representation"]["context"] + has_frames = repre_context.get("frame") is not None + has_udim = repre_context.get("udim") is not None + with namespaced(namespace, new=True) as namespace: # Create the nodes within the namespace nodes = { @@ -125,13 +129,15 @@ def load(self, context, name, namespace, data): cmds.setAttr(file_node + ".fileTextureName", path, type="string") # Set UV tiling mode if UDIM tiles - # TODO: Detect UDIM tiles and set accordingly (also on update) - cmds.setAttr(file_node + ".uvTilingMode", 3) # UDIM-tiles + if has_udim: + cmds.setAttr(file_node + ".uvTilingMode", 3) # UDIM-tiles # Enable sequence if publish has `startFrame` and `endFrame` and # `startFrame != endFrame` - # TODO: Detect sequences (also on update) - # cmds.setAttr(file_node + ".useFrameExtension", True) + if has_frames: + is_sequence = self._is_sequence(context) + if is_sequence: + cmds.setAttr(file_node + ".useFrameExtension", True) # For ease of access for the user select all the nodes and select # the file node last so that UI shows its attributes by default @@ -174,3 +180,28 @@ def remove(self, container): deleteNamespaceContent=True) except RuntimeError: pass + + def _is_sequence(self, context): + """Check whether frameStart and frameEnd are not the same.""" + version = context.get("version", {}) + representation = context.get("representation", {}) + + print(version) + print(representation) + + for doc in [representation, version]: + # Frame range can be set on version or representation. When set on + # representation it overrides data on subset + data = doc.get("data", {}) + start = data.get("frameStartHandle", data.get("frameStart", None)) + end = data.get("frameEndHandle", data.get("frameEnd", None)) + + if start is None or end is None: + continue + + if start != end: + return True + else: + return False + + return False From a48e638798da6eadd87904cf6652424b33759d56 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 6 Mar 2023 12:33:54 +0100 Subject: [PATCH 503/898] Explicitly set the frame and udim token based on template. --- .../hosts/maya/plugins/load/load_image.py | 67 ++++++++++++++++--- 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/openpype/hosts/maya/plugins/load/load_image.py b/openpype/hosts/maya/plugins/load/load_image.py index 117d1a7d0fb..b7b0b5d4c83 100644 --- a/openpype/hosts/maya/plugins/load/load_image.py +++ b/openpype/hosts/maya/plugins/load/load_image.py @@ -1,6 +1,7 @@ +import copy from openpype.pipeline import ( load, - get_representation_path + get_representation_context ) from openpype.lib import EnumDef from openpype.hosts.maya.api.pipeline import containerise @@ -8,6 +9,8 @@ unique_namespace, namespaced ) +from openpype.pipeline.load.utils import get_representation_path_from_context + from maya import cmds @@ -104,7 +107,7 @@ class FileNodeLoader(load.LoaderPlugin): def load(self, context, name, namespace, data): - path = self.fname + path = self._format_path(context) asset = context['asset']['name'] namespace = namespace or unique_namespace( asset + "_", @@ -123,10 +126,7 @@ def load(self, context, name, namespace, data): "projection": create_projection, "stencil": create_stencil }[data.get("mode", "texture")]() - - # Set the file node attributes file_node = cmds.ls(nodes, type="file")[0] - cmds.setAttr(file_node + ".fileTextureName", path, type="string") # Set UV tiling mode if UDIM tiles if has_udim: @@ -137,8 +137,17 @@ def load(self, context, name, namespace, data): if has_frames: is_sequence = self._is_sequence(context) if is_sequence: + # When enabling useFrameExtension maya automatically + # connects an expression to .frameExtension to set + # the current frame. However, this expression is generated + # with some delay and thus it'll show a warning if frame 0 + # doesn't exist because we're explicitly setting the + # token. cmds.setAttr(file_node + ".useFrameExtension", True) + # Set the file node path attribute + cmds.setAttr(file_node + ".fileTextureName", path, type="string") + # For ease of access for the user select all the nodes and select # the file node last so that UI shows its attributes by default cmds.select(list(nodes) + [file_node], replace=True) @@ -153,7 +162,8 @@ def load(self, context, name, namespace, data): def update(self, container, representation): - path = get_representation_path(representation) + context = get_representation_context(representation) + path = self._format_path(context) members = cmds.sets(container['objectName'], query=True) file_node = cmds.ls(members, type="file")[0] @@ -186,9 +196,6 @@ def _is_sequence(self, context): version = context.get("version", {}) representation = context.get("representation", {}) - print(version) - print(representation) - for doc in [representation, version]: # Frame range can be set on version or representation. When set on # representation it overrides data on subset @@ -205,3 +212,45 @@ def _is_sequence(self, context): return False return False + + def _format_path(self, context): + """Format the path with correct tokens for frames and udim tiles.""" + + context = copy.deepcopy(context) + representation = context["representation"] + template = representation.get("data", {}).get("template") + if not template: + # No template to find token locations for + return get_representation_path_from_context(context) + + def _placeholder(key): + # Substitute with a long placeholder value so that potential + # custom formatting with padding doesn't find its way into + # our formatting, so that wouldn't be padded as 0 + return "___{}___".format(key) + + # We want to format UDIM and Frame numbers with the specific tokens + # so we in-place change the representation context so it's formatted + # with the tokens as we'd want them. So we explicitly change those + # tokens around with what we'd need. + tokens = { + "frame": "", + "udim": "" + } + has_tokens = False + repre_context = representation["context"] + for key, token in tokens.items(): + if key in repre_context: + repre_context[key] = _placeholder(key) + has_tokens = True + + # Replace with our custom template that has the tokens set + representation["data"]["template"] = template + path = get_representation_path_from_context(context) + + if has_tokens: + for key, token in tokens.items(): + if key in repre_context: + path = path.replace(_placeholder(key), token) + + return path From 1c5b82168853236b532828a0c4daf8187f0f00a8 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 6 Mar 2023 12:34:58 +0100 Subject: [PATCH 504/898] Cosmetics --- openpype/hosts/maya/plugins/load/load_image.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/load/load_image.py b/openpype/hosts/maya/plugins/load/load_image.py index b7b0b5d4c83..c08724dca03 100644 --- a/openpype/hosts/maya/plugins/load/load_image.py +++ b/openpype/hosts/maya/plugins/load/load_image.py @@ -239,7 +239,7 @@ def _placeholder(key): } has_tokens = False repre_context = representation["context"] - for key, token in tokens.items(): + for key, _token in tokens.items(): if key in repre_context: repre_context[key] = _placeholder(key) has_tokens = True From 4ac950aa604b5107d68f314df94472148148f2f5 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 6 Mar 2023 15:26:55 +0100 Subject: [PATCH 505/898] Set color space from publish using representation color space data or falling back to imageio settings file rules in OP settings --- .../hosts/maya/plugins/load/load_image.py | 148 +++++++++++++----- 1 file changed, 113 insertions(+), 35 deletions(-) diff --git a/openpype/hosts/maya/plugins/load/load_image.py b/openpype/hosts/maya/plugins/load/load_image.py index c08724dca03..0e535f1692d 100644 --- a/openpype/hosts/maya/plugins/load/load_image.py +++ b/openpype/hosts/maya/plugins/load/load_image.py @@ -1,16 +1,24 @@ +import os import copy + +from openpype.lib import EnumDef from openpype.pipeline import ( load, get_representation_context ) -from openpype.lib import EnumDef +from openpype.pipeline.load.utils import get_representation_path_from_context +from openpype.pipeline.colorspace import ( + get_imageio_colorspace_from_filepath, + get_imageio_config, + get_imageio_file_rules +) +from openpype.settings import get_project_settings + from openpype.hosts.maya.api.pipeline import containerise from openpype.hosts.maya.api.lib import ( unique_namespace, namespaced ) -from openpype.pipeline.load.utils import get_representation_path_from_context - from maya import cmds @@ -83,7 +91,6 @@ def create_stencil(): class FileNodeLoader(load.LoaderPlugin): """File node loader.""" - # TODO: Implement color space manamagent OCIO (set correct color space) families = ["image", "plate", "render"] label = "Load file node" @@ -107,7 +114,6 @@ class FileNodeLoader(load.LoaderPlugin): def load(self, context, name, namespace, data): - path = self._format_path(context) asset = context['asset']['name'] namespace = namespace or unique_namespace( asset + "_", @@ -115,10 +121,6 @@ def load(self, context, name, namespace, data): suffix="_", ) - repre_context = context["representation"]["context"] - has_frames = repre_context.get("frame") is not None - has_udim = repre_context.get("udim") is not None - with namespaced(namespace, new=True) as namespace: # Create the nodes within the namespace nodes = { @@ -126,31 +128,14 @@ def load(self, context, name, namespace, data): "projection": create_projection, "stencil": create_stencil }[data.get("mode", "texture")]() - file_node = cmds.ls(nodes, type="file")[0] - - # Set UV tiling mode if UDIM tiles - if has_udim: - cmds.setAttr(file_node + ".uvTilingMode", 3) # UDIM-tiles - - # Enable sequence if publish has `startFrame` and `endFrame` and - # `startFrame != endFrame` - if has_frames: - is_sequence = self._is_sequence(context) - if is_sequence: - # When enabling useFrameExtension maya automatically - # connects an expression to .frameExtension to set - # the current frame. However, this expression is generated - # with some delay and thus it'll show a warning if frame 0 - # doesn't exist because we're explicitly setting the - # token. - cmds.setAttr(file_node + ".useFrameExtension", True) - - # Set the file node path attribute - cmds.setAttr(file_node + ".fileTextureName", path, type="string") - - # For ease of access for the user select all the nodes and select - # the file node last so that UI shows its attributes by default - cmds.select(list(nodes) + [file_node], replace=True) + + file_node = cmds.ls(nodes, type="file")[0] + + self._apply_representation_context(context, file_node) + + # For ease of access for the user select all the nodes and select + # the file node last so that UI shows its attributes by default + cmds.select(list(nodes) + [file_node], replace=True) return containerise( name=name, @@ -167,7 +152,7 @@ def update(self, container, representation): members = cmds.sets(container['objectName'], query=True) file_node = cmds.ls(members, type="file")[0] - cmds.setAttr(file_node + ".fileTextureName", path, type="string") + self._apply_representation_context(context, file_node) # Update representation cmds.setAttr( @@ -191,6 +176,51 @@ def remove(self, container): except RuntimeError: pass + def _apply_representation_context(self, context, file_node): + """Update the file node to match the context. + + This sets the file node's attributes for: + - file path + - udim tiling mode (if it is an udim tile) + - use frame extension (if it is a sequence) + - colorspace + + """ + + repre_context = context["representation"]["context"] + has_frames = repre_context.get("frame") is not None + has_udim = repre_context.get("udim") is not None + + # Set UV tiling mode if UDIM tiles + if has_udim: + cmds.setAttr(file_node + ".uvTilingMode", 3) # UDIM-tiles + else: + cmds.setAttr(file_node + ".uvTilingMode", 0) # off + + # Enable sequence if publish has `startFrame` and `endFrame` and + # `startFrame != endFrame` + if has_frames and self._is_sequence(context): + # When enabling useFrameExtension maya automatically + # connects an expression to .frameExtension to set + # the current frame. However, this expression is generated + # with some delay and thus it'll show a warning if frame 0 + # doesn't exist because we're explicitly setting the + # token. + cmds.setAttr(file_node + ".useFrameExtension", True) + else: + cmds.setAttr(file_node + ".useFrameExtension", False) + + # Set the file node path attribute + path = self._format_path(context) + cmds.setAttr(file_node + ".fileTextureName", path, type="string") + + # Set colorspace + colorspace = self._get_colorspace(context) + if colorspace: + cmds.setAttr(file_node + ".colorSpace", colorspace, type="string") + else: + self.log.debug("Unknown colorspace - setting colorspace skipped.") + def _is_sequence(self, context): """Check whether frameStart and frameEnd are not the same.""" version = context.get("version", {}) @@ -213,6 +243,54 @@ def _is_sequence(self, context): return False + def _get_colorspace(self, context): + """Return colorspace of the file to load. + + Retrieves the explicit colorspace from the publish. If no colorspace + data is stored with published content then project imageio settings + are used to make an assumption of the colorspace based on the file + rules. If no file rules match then None is returned. + + Returns: + str or None: The colorspace of the file or None if not detected. + + """ + + # We can't apply color spaces if management is not enabled + if not cmds.colorManagementPrefs(query=True, cmEnabled=True): + return + + representation = context["representation"] + colorspace_data = representation.get("data", {}).get("colorspaceData") + if colorspace_data: + return colorspace_data["colorspace"] + + # Assume colorspace from filepath based on project settings + project_name = context["project"]["name"] + host_name = os.environ.get("AVALON_APP") + project_settings = get_project_settings(project_name) + + config_data = get_imageio_config( + project_name, host_name, + project_settings=project_settings + ) + file_rules = get_imageio_file_rules( + project_name, host_name, + project_settings=project_settings + ) + + path = get_representation_path_from_context(context) + colorspace = get_imageio_colorspace_from_filepath( + path=path, + host_name=host_name, + project_name=project_name, + config_data=config_data, + file_rules=file_rules, + project_settings=project_settings + ) + + return colorspace + def _format_path(self, context): """Format the path with correct tokens for frames and udim tiles.""" From 5a7e90daa8df073b4af735799d6b53ba2e911921 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 6 Mar 2023 15:27:42 +0100 Subject: [PATCH 506/898] Cleanup --- openpype/hosts/maya/plugins/load/load_image.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/maya/plugins/load/load_image.py b/openpype/hosts/maya/plugins/load/load_image.py index 0e535f1692d..e975fb8b619 100644 --- a/openpype/hosts/maya/plugins/load/load_image.py +++ b/openpype/hosts/maya/plugins/load/load_image.py @@ -147,11 +147,10 @@ def load(self, context, name, namespace, data): def update(self, container, representation): - context = get_representation_context(representation) - path = self._format_path(context) members = cmds.sets(container['objectName'], query=True) - file_node = cmds.ls(members, type="file")[0] + + context = get_representation_context(representation) self._apply_representation_context(context, file_node) # Update representation From 91b99cafd42b69a00dc714f1a71089de60467771 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 6 Mar 2023 15:48:43 +0100 Subject: [PATCH 507/898] Correctly set the UDIM token using capitals + cleanup comment --- openpype/hosts/maya/plugins/load/load_image.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/maya/plugins/load/load_image.py b/openpype/hosts/maya/plugins/load/load_image.py index e975fb8b619..3cf2394525c 100644 --- a/openpype/hosts/maya/plugins/load/load_image.py +++ b/openpype/hosts/maya/plugins/load/load_image.py @@ -306,13 +306,12 @@ def _placeholder(key): # our formatting, so that wouldn't be padded as 0 return "___{}___".format(key) - # We want to format UDIM and Frame numbers with the specific tokens - # so we in-place change the representation context so it's formatted - # with the tokens as we'd want them. So we explicitly change those - # tokens around with what we'd need. + # We format UDIM and Frame numbers with their specific tokens. To do so + # we in-place change the representation context data to format the path + # with our own data tokens = { "frame": "", - "udim": "" + "udim": "" } has_tokens = False repre_context = representation["context"] From b47722b35823d557e64377e74130185b5cb143a7 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 6 Mar 2023 15:52:47 +0100 Subject: [PATCH 508/898] Fix comment --- openpype/hosts/maya/plugins/load/load_image.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/load/load_image.py b/openpype/hosts/maya/plugins/load/load_image.py index 3cf2394525c..b464c268fcb 100644 --- a/openpype/hosts/maya/plugins/load/load_image.py +++ b/openpype/hosts/maya/plugins/load/load_image.py @@ -226,8 +226,8 @@ def _is_sequence(self, context): representation = context.get("representation", {}) for doc in [representation, version]: - # Frame range can be set on version or representation. When set on - # representation it overrides data on subset + # Frame range can be set on version or representation. + # When set on representation it overrides version data. data = doc.get("data", {}) start = data.get("frameStartHandle", data.get("frameStart", None)) end = data.get("frameEndHandle", data.get("frameEnd", None)) From 812fa065cfa5068eba12e83c5bf428e9dfd68255 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 15 Mar 2023 16:08:07 +0000 Subject: [PATCH 509/898] Multiple Values - support multiple values for render attributes. - support repairing the render attributes. --- .../publish/validate_rendersettings.py | 80 ++++++++++++------- .../schemas/schema_maya_publish.json | 12 ++- 2 files changed, 60 insertions(+), 32 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_rendersettings.py b/openpype/hosts/maya/plugins/publish/validate_rendersettings.py index 94e26335936..3b2bd1a84aa 100644 --- a/openpype/hosts/maya/plugins/publish/validate_rendersettings.py +++ b/openpype/hosts/maya/plugins/publish/validate_rendersettings.py @@ -242,10 +242,6 @@ def get_invalid(cls, instance): cls.DEFAULT_PADDING, "0" * cls.DEFAULT_PADDING)) # load validation definitions from settings - validation_settings = ( - instance.context.data["project_settings"]["maya"]["publish"]["ValidateRenderSettings"].get( # noqa: E501 - "{}_render_attributes".format(renderer)) or [] - ) settings_lights_flag = instance.context.data["project_settings"].get( "maya", {}).get( "RenderSettings", {}).get( @@ -253,15 +249,54 @@ def get_invalid(cls, instance): instance_lights_flag = instance.data.get("renderSetupIncludeLights") if settings_lights_flag != instance_lights_flag: - cls.log.warning('Instance flag for "Render Setup Include Lights" is set to {0} and Settings flag is set to {1}'.format(instance_lights_flag, settings_lights_flag)) # noqa + cls.log.warning( + "Instance flag for \"Render Setup Include Lights\" is set to " + "{} and Settings flag is set to {}".format( + instance_lights_flag, settings_lights_flag + ) + ) # go through definitions and test if such node.attribute exists. # if so, compare its value from the one required. - for attr, value in OrderedDict(validation_settings).items(): - cls.log.debug("{}: {}".format(attr, value)) + for attribute, data in cls.get_nodes(instance, renderer).items(): + for node in data["nodes"]: + try: + render_value = cmds.getAttr( + "{}.{}".format(node, attribute) + ) + except RuntimeError: + invalid = True + cls.log.error( + "Cannot get value of {}.{}".format(node, attribute) + ) + else: + if str(render_value) not in data["values"]: + invalid = True + cls.log.error( + "Invalid value {} set on {}.{}. Expecting " + "{}".format( + render_value, node, attribute, data["values"] + ) + ) + + return invalid + + @classmethod + def get_nodes(cls, instance, renderer): + maya_settings = instance.context.data["project_settings"]["maya"] + validation_settings = ( + maya_settings["publish"]["ValidateRenderSettings"].get( + "{}_render_attributes".format(renderer) + ) or [] + ) + result = {} + for attr, values in OrderedDict(validation_settings).items(): + cls.log.debug("{}: {}".format(attr, values)) if "." not in attr: - cls.log.warning("Skipping invalid attribute defined in " - "validation settings: '{}'".format(attr)) + cls.log.warning( + "Skipping invalid attribute defined in validation " + "settings: \"{}\"".format(attr) + ) continue node_type, attribute_name = attr.split(".", 1) @@ -271,28 +306,13 @@ def get_invalid(cls, instance): if not nodes: cls.log.warning( - "No nodes of type '{}' found.".format(node_type)) + "No nodes of type \"{}\" found.".format(node_type) + ) continue - for node in nodes: - try: - render_value = cmds.getAttr( - "{}.{}".format(node, attribute_name)) - except RuntimeError: - invalid = True - cls.log.error( - "Cannot get value of {}.{}".format( - node, attribute_name)) - else: - if str(value) != str(render_value): - invalid = True - cls.log.error( - ("Invalid value {} set on {}.{}. " - "Expecting {}").format( - render_value, node, attribute_name, value) - ) + result[attribute_name] = {"nodes": nodes, "values": values} - return invalid + return result @classmethod def repair(cls, instance): @@ -305,6 +325,10 @@ def repair(cls, instance): "{aov_separator}", instance.data.get("aovSeparator", "_") ) + for attribute, data in cls.get_nodes(instance, renderer).items(): + for node in data["nodes"]: + lib.set_attribute(attribute, data["values"][0], node) + with lib.renderlayer(layer_node): default = lib.RENDER_ATTRS['default'] render_attrs = lib.RENDER_ATTRS.get(renderer, default) diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json index 3484f42f6b6..5a66f8a5130 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json @@ -369,7 +369,8 @@ "label": "Arnold Render Attributes", "use_label_wrap": true, "object_type": { - "type": "text" + "type": "list", + "object_type": "text" } }, { @@ -379,7 +380,8 @@ "label": "Vray Render Attributes", "use_label_wrap": true, "object_type": { - "type": "text" + "type": "list", + "object_type": "text" } }, { @@ -389,7 +391,8 @@ "label": "Redshift Render Attributes", "use_label_wrap": true, "object_type": { - "type": "text" + "type": "list", + "object_type": "text" } }, { @@ -399,7 +402,8 @@ "label": "Renderman Render Attributes", "use_label_wrap": true, "object_type": { - "type": "text" + "type": "list", + "object_type": "text" } } ] From 51fa89bef31b6b8f5ed7927bbadd31a64195977e Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 15 Mar 2023 16:08:14 +0000 Subject: [PATCH 510/898] Docs cosmetics. --- website/docs/admin_hosts_maya.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/website/docs/admin_hosts_maya.md b/website/docs/admin_hosts_maya.md index ae0cf76f536..685213c2063 100644 --- a/website/docs/admin_hosts_maya.md +++ b/website/docs/admin_hosts_maya.md @@ -6,13 +6,13 @@ sidebar_label: Maya ## Publish Plugins -### Render Settings Validator +### Render Settings Validator `ValidateRenderSettings` Render Settings Validator is here to make sure artists will submit renders -we correct settings. Some of these settings are needed by OpenPype but some -can be defined by TD using [OpenPype Settings UI](admin_settings.md). +with the correct settings. Some of these settings are needed by OpenPype but some +can be defined by the admin using [OpenPype Settings UI](admin_settings.md). OpenPype enforced settings include: @@ -51,7 +51,7 @@ just one instance of this node type but if that is not so, validator will go thr instances and check the value there. Node type for **VRay** settings is `VRaySettingsNode`, for **Renderman** it is `rmanGlobals`, for **Redshift** it is `RedshiftOptions`. -### Model Name Validator +### Model Name Validator `ValidateRenderSettings` @@ -95,7 +95,7 @@ You can set various aspects of scene submission to farm with per-project setting - **Optional** will mark sumission plugin optional - **Active** will enable/disable plugin - - **Tile Assembler Plugin** will set what should be used to assemble tiles on Deadline. Either **Open Image IO** will be used + - **Tile Assembler Plugin** will set what should be used to assemble tiles on Deadline. Either **Open Image IO** will be used or Deadlines **Draft Tile Assembler**. - **Use Published scene** enable to render from published scene instead of scene in work area. Rendering from published files is much safer. - **Use Asset dependencies** will mark job pending on farm until asset dependencies are fulfilled - for example Deadline will wait for scene file to be synced to cloud, etc. @@ -169,5 +169,3 @@ Fill in the necessary fields (the optional fields are regex filters) - Build your workfile ![maya build template](assets/maya-build_workfile_from_template.png) - - From 8bd4598e0907a07635b0a9aff3b0eabffa29685c Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 15 Mar 2023 16:26:48 +0000 Subject: [PATCH 511/898] Update docs --- website/docs/admin_hosts_maya.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/website/docs/admin_hosts_maya.md b/website/docs/admin_hosts_maya.md index 685213c2063..82109f0e0c0 100644 --- a/website/docs/admin_hosts_maya.md +++ b/website/docs/admin_hosts_maya.md @@ -36,10 +36,9 @@ For **Renderman**: For **Arnold**: - there shouldn't be `` token when merge AOVs option is turned on - Additional check can be added via Settings - **Project Settings > Maya > Publish plugin > ValidateRenderSettings**. You can add as many options as you want for every supported renderer. In first field put node type and attribute -and in the second required value. +and in the second required value. You can create multiple values for an attribute, but when repairing it'll be the first value in the list that get selected. ![Settings example](assets/maya-admin_render_settings_validator.png) From b8633c42793ccd0c9417ad29b639c9b322591d3c Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 16 Mar 2023 16:59:56 +0000 Subject: [PATCH 512/898] Ensure attributes values from settings are correct. --- .../publish/validate_rendersettings.py | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_rendersettings.py b/openpype/hosts/maya/plugins/publish/validate_rendersettings.py index 3b2bd1a84aa..53f340cd2c0 100644 --- a/openpype/hosts/maya/plugins/publish/validate_rendersettings.py +++ b/openpype/hosts/maya/plugins/publish/validate_rendersettings.py @@ -13,6 +13,22 @@ from openpype.hosts.maya.api import lib +def convert_to_int_or_float(string_value): + # Order of types are important here since float can convert string + # representation of integer. + types = [int, float] + for t in types: + try: + result = t(string_value) + except ValueError: + continue + else: + return result + + # Neither integer or float. + return string_value + + def get_redshift_image_format_labels(): """Return nice labels for Redshift image formats.""" var = "$g_redshiftImageFormatLabels" @@ -259,6 +275,15 @@ def get_invalid(cls, instance): # go through definitions and test if such node.attribute exists. # if so, compare its value from the one required. for attribute, data in cls.get_nodes(instance, renderer).items(): + # Validate the settings has values. + if not data["values"]: + cls.log.error( + "Settings for {}.{} is missing values.".format( + node, attribute + ) + ) + continue + for node in data["nodes"]: try: render_value = cmds.getAttr( @@ -270,7 +295,7 @@ def get_invalid(cls, instance): "Cannot get value of {}.{}".format(node, attribute) ) else: - if str(render_value) not in data["values"]: + if render_value not in data["values"]: invalid = True cls.log.error( "Invalid value {} set on {}.{}. Expecting " @@ -299,6 +324,8 @@ def get_nodes(cls, instance, renderer): ) continue + values = [convert_to_int_or_float(v) for v in values] + node_type, attribute_name = attr.split(".", 1) # first get node of that type @@ -326,6 +353,8 @@ def repair(cls, instance): ) for attribute, data in cls.get_nodes(instance, renderer).items(): + if not data["values"]: + continue for node in data["nodes"]: lib.set_attribute(attribute, data["values"][0], node) From 917a1f4d0a20852614f32818ef13caff425c2cad Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 17 Mar 2023 10:26:56 +0000 Subject: [PATCH 513/898] Update docs image --- .../maya-admin_render_settings_validator.png | Bin 11220 -> 11855 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/website/docs/assets/maya-admin_render_settings_validator.png b/website/docs/assets/maya-admin_render_settings_validator.png index 8687b538b124c6857534d9033a46c70deb875fde..8ee11f16f6fb275901e1b11243d5a39d38d7b02c 100644 GIT binary patch literal 11855 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 literal 11220 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 Date: Fri, 17 Mar 2023 15:58:59 +0000 Subject: [PATCH 514/898] Info on attribute collection --- website/docs/admin_hosts_maya.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/website/docs/admin_hosts_maya.md b/website/docs/admin_hosts_maya.md index 82109f0e0c0..23cacb41938 100644 --- a/website/docs/admin_hosts_maya.md +++ b/website/docs/admin_hosts_maya.md @@ -50,6 +50,10 @@ just one instance of this node type but if that is not so, validator will go thr instances and check the value there. Node type for **VRay** settings is `VRaySettingsNode`, for **Renderman** it is `rmanGlobals`, for **Redshift** it is `RedshiftOptions`. +:::info getting attribute values +If you do not know what an attributes value is supposed to be, for example for dropdown menu (enum), try changing the attribute and look in the script editor where it should log what the attribute was set to. +::: + ### Model Name Validator `ValidateRenderSettings` From 739b2db0f099286acf7f0f194403652fd23f18b1 Mon Sep 17 00:00:00 2001 From: moonyuet Date: Tue, 14 Mar 2023 09:48:24 +0100 Subject: [PATCH 515/898] MaxScene Family introduction --- .../max/plugins/create/create_maxScene.py | 26 ++++++++++ .../hosts/max/plugins/load/load_max_scene.py | 3 +- .../plugins/publish/extract_max_scene_raw.py | 3 +- openpype/plugins/publish/integrate.py | 1 + openpype/plugins/publish/integrate_legacy.py | 1 + tools/build.ps1 | 49 +++++++++---------- 6 files changed, 56 insertions(+), 27 deletions(-) create mode 100644 openpype/hosts/max/plugins/create/create_maxScene.py diff --git a/openpype/hosts/max/plugins/create/create_maxScene.py b/openpype/hosts/max/plugins/create/create_maxScene.py new file mode 100644 index 00000000000..52da615be40 --- /dev/null +++ b/openpype/hosts/max/plugins/create/create_maxScene.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +"""Creator plugin for creating raw max scene.""" +from openpype.hosts.max.api import plugin +from openpype.pipeline import CreatedInstance + + +class CreateMaxScene(plugin.MaxCreator): + identifier = "io.openpype.creators.max.maxScene" + label = "Max Scene(Raw)" + family = "maxScene" + icon = "gear" + + def create(self, subset_name, instance_data, pre_create_data): + from pymxs import runtime as rt + sel_obj = list(rt.selection) + instance = super(CreateMaxScene, self).create( + subset_name, + instance_data, + pre_create_data) # type: CreatedInstance + container = rt.getNodeByName(instance.data.get("instance_node")) + # TODO: Disable "Add to Containers?" Panel + # parent the selected cameras into the container + for obj in sel_obj: + obj.parent = container + # for additional work on the node: + # instance_node = rt.getNodeByName(instance.get("instance_node")) diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index b863b9363f5..fa8b6b28948 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -9,7 +9,8 @@ class MaxSceneLoader(load.LoaderPlugin): """Max Scene Loader""" - families = ["camera"] + families = ["camera", + "maxScene"] representations = ["max"] order = -8 icon = "code-fork" diff --git a/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py b/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py index cacc84c5912..4e567ab76e1 100644 --- a/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py +++ b/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py @@ -19,7 +19,8 @@ class ExtractMaxSceneRaw(publish.Extractor, order = pyblish.api.ExtractorOrder - 0.2 label = "Extract Max Scene (Raw)" - hosts = ["max"] + hosts = ["max", + "maxScene"] families = ["camera"] optional = True diff --git a/openpype/plugins/publish/integrate.py b/openpype/plugins/publish/integrate.py index b1170068716..69b7734c70c 100644 --- a/openpype/plugins/publish/integrate.py +++ b/openpype/plugins/publish/integrate.py @@ -84,6 +84,7 @@ class IntegrateAsset(pyblish.api.InstancePlugin): "camera", "animation", "model", + "maxScene", "mayaAscii", "mayaScene", "setdress", diff --git a/openpype/plugins/publish/integrate_legacy.py b/openpype/plugins/publish/integrate_legacy.py index b93abab1d88..66c2c9be512 100644 --- a/openpype/plugins/publish/integrate_legacy.py +++ b/openpype/plugins/publish/integrate_legacy.py @@ -80,6 +80,7 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): "camera", "animation", "model", + "maxScene", "mayaAscii", "mayaScene", "setdress", diff --git a/tools/build.ps1 b/tools/build.ps1 index 195b2dc75e4..f60cb2d0c44 100644 --- a/tools/build.ps1 +++ b/tools/build.ps1 @@ -22,10 +22,10 @@ https://openpype.io/docs #> -$arguments=$ARGS -$disable_submodule_update="" -if($arguments -eq "--no-submodule-update") { - $disable_submodule_update=$true +$arguments = $ARGS +$disable_submodule_update = "" +if ($arguments -eq "--no-submodule-update") { + $disable_submodule_update = $true } $current_dir = Get-Location @@ -45,13 +45,11 @@ function Start-Progress { # $origpos.Y -= 1 - while (($job.State -eq "Running") -and ($job.State -ne "NotStarted")) - { + while (($job.State -eq "Running") -and ($job.State -ne "NotStarted")) { $host.UI.RawUI.CursorPosition = $origpos Write-Host $scroll[$idx] -NoNewline $idx++ - if ($idx -ge $scroll.Length) - { + if ($idx -ge $scroll.Length) { $idx = 0 } Start-Sleep -Milliseconds 100 @@ -59,7 +57,7 @@ function Start-Progress { # It's over - clear the activity indicator. $host.UI.RawUI.CursorPosition = $origpos Write-Host ' ' - <# + <# .SYNOPSIS Display spinner for running job .PARAMETER code @@ -69,17 +67,17 @@ function Start-Progress { function Exit-WithCode($exitcode) { - # Only exit this host process if it's a child of another PowerShell parent process... - $parentPID = (Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$PID" | Select-Object -Property ParentProcessId).ParentProcessId - $parentProcName = (Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$parentPID" | Select-Object -Property Name).Name - if ('powershell.exe' -eq $parentProcName) { $host.SetShouldExit($exitcode) } + # Only exit this host process if it's a child of another PowerShell parent process... + $parentPID = (Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$PID" | Select-Object -Property ParentProcessId).ParentProcessId + $parentProcName = (Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$parentPID" | Select-Object -Property Name).Name + if ('powershell.exe' -eq $parentProcName) { $host.SetShouldExit($exitcode) } - exit $exitcode + exit $exitcode } function Show-PSWarning() { if ($PSVersionTable.PSVersion.Major -lt 7) { - Write-Color -Text "!!! ", "You are using old version of PowerShell - ", "$($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor)" -Color Red, Yellow, White + Write-Color -Text "!!! ", "You are using old version of PowerShell - ", "$($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor)" -Color Red, Yellow, White Write-Color -Text " Please update to at least 7.0 - ", "https://github.com/PowerShell/PowerShell/releases" -Color Yellow, White Exit-WithCode 1 } @@ -87,7 +85,7 @@ function Show-PSWarning() { function Install-Poetry() { Write-Color -Text ">>> ", "Installing Poetry ... " -Color Green, Gray - $env:POETRY_HOME="$openpype_root\.poetry" + $env:POETRY_HOME = "$openpype_root\.poetry" (Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py -UseBasicParsing).Content | python - } @@ -126,8 +124,8 @@ $version_file = Get-Content -Path "$($openpype_root)\openpype\version.py" $result = [regex]::Matches($version_file, '__version__ = "(?\d+\.\d+.\d+.*)"') $openpype_version = $result[0].Groups['version'].Value if (-not $openpype_version) { - Write-Color -Text "!!! ", "Cannot determine OpenPype version." -Color Yellow, Gray - Exit-WithCode 1 + Write-Color -Text "!!! ", "Cannot determine OpenPype version." -Color Yellow, Gray + Exit-WithCode 1 } # Create build directory if not exist @@ -147,7 +145,8 @@ catch { if (-not $disable_submodule_update) { Write-Color -Text ">>> ", "Making sure submodules are up-to-date ..." -Color Green, Gray & git submodule update --init --recursive -} else { +} +else { Write-Color -Text "*** ", "Not updating submodules ..." -Color Green, Gray } @@ -158,7 +157,8 @@ if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) { Write-Color -Text "NOT FOUND" -Color Yellow Write-Color -Text "*** ", "We need to install Poetry create virtual env first ..." -Color Yellow, Gray & "$openpype_root\tools\create_env.ps1" -} else { +} +else { Write-Color -Text "OK" -Color Green } @@ -173,8 +173,7 @@ $startTime = [int][double]::Parse((Get-Date -UFormat %s)) $out = & "$($env:POETRY_HOME)\bin\poetry" run python setup.py build 2>&1 Set-Content -Path "$($openpype_root)\build\build.log" -Value $out -if ($LASTEXITCODE -ne 0) -{ +if ($LASTEXITCODE -ne 0) { Write-Color -Text "------------------------------------------" -Color Red Get-Content "$($openpype_root)\build\build.log" Write-Color -Text "------------------------------------------" -Color Yellow @@ -189,8 +188,8 @@ Write-Color -Text ">>> ", "Restoring current directory" -Color Green, Gray Set-Location -Path $current_dir $endTime = [int][double]::Parse((Get-Date -UFormat %s)) -try -{ +try { New-BurntToastNotification -AppLogo "$openpype_root/openpype/resources/icons/openpype_icon.png" -Text "OpenPype build complete!", "All done in $( $endTime - $startTime ) secs. You will find OpenPype and build log in build directory." -} catch {} +} +catch {} Write-Color -Text "*** ", "All done in ", $($endTime - $startTime), " secs. You will find OpenPype and build log in ", "'.\build'", " directory." -Color Green, Gray, White, Gray, White, Gray From 6a93cb199033dbd144f30c73571828b3657f88fb Mon Sep 17 00:00:00 2001 From: moonyuet Date: Tue, 14 Mar 2023 09:52:14 +0100 Subject: [PATCH 516/898] rename creator --- openpype/hosts/max/plugins/create/create_maxScene.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/plugins/create/create_maxScene.py b/openpype/hosts/max/plugins/create/create_maxScene.py index 52da615be40..7900336f32a 100644 --- a/openpype/hosts/max/plugins/create/create_maxScene.py +++ b/openpype/hosts/max/plugins/create/create_maxScene.py @@ -6,7 +6,7 @@ class CreateMaxScene(plugin.MaxCreator): identifier = "io.openpype.creators.max.maxScene" - label = "Max Scene(Raw)" + label = "Max Scene" family = "maxScene" icon = "gear" From 5895b4f376714dce66f5d8a40552cda71b92368c Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 15 Mar 2023 21:42:15 +0800 Subject: [PATCH 517/898] putting maxScene into correct families --- .../plugins/publish/extract_max_scene_raw.py | 6 +-- tools/build.ps1 | 49 ++++++++++--------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py b/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py index 4e567ab76e1..969f87be481 100644 --- a/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py +++ b/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py @@ -19,9 +19,9 @@ class ExtractMaxSceneRaw(publish.Extractor, order = pyblish.api.ExtractorOrder - 0.2 label = "Extract Max Scene (Raw)" - hosts = ["max", - "maxScene"] - families = ["camera"] + hosts = ["max"] + families = ["camera", + "maxScene"] optional = True def process(self, instance): diff --git a/tools/build.ps1 b/tools/build.ps1 index f60cb2d0c44..195b2dc75e4 100644 --- a/tools/build.ps1 +++ b/tools/build.ps1 @@ -22,10 +22,10 @@ https://openpype.io/docs #> -$arguments = $ARGS -$disable_submodule_update = "" -if ($arguments -eq "--no-submodule-update") { - $disable_submodule_update = $true +$arguments=$ARGS +$disable_submodule_update="" +if($arguments -eq "--no-submodule-update") { + $disable_submodule_update=$true } $current_dir = Get-Location @@ -45,11 +45,13 @@ function Start-Progress { # $origpos.Y -= 1 - while (($job.State -eq "Running") -and ($job.State -ne "NotStarted")) { + while (($job.State -eq "Running") -and ($job.State -ne "NotStarted")) + { $host.UI.RawUI.CursorPosition = $origpos Write-Host $scroll[$idx] -NoNewline $idx++ - if ($idx -ge $scroll.Length) { + if ($idx -ge $scroll.Length) + { $idx = 0 } Start-Sleep -Milliseconds 100 @@ -57,7 +59,7 @@ function Start-Progress { # It's over - clear the activity indicator. $host.UI.RawUI.CursorPosition = $origpos Write-Host ' ' - <# + <# .SYNOPSIS Display spinner for running job .PARAMETER code @@ -67,17 +69,17 @@ function Start-Progress { function Exit-WithCode($exitcode) { - # Only exit this host process if it's a child of another PowerShell parent process... - $parentPID = (Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$PID" | Select-Object -Property ParentProcessId).ParentProcessId - $parentProcName = (Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$parentPID" | Select-Object -Property Name).Name - if ('powershell.exe' -eq $parentProcName) { $host.SetShouldExit($exitcode) } + # Only exit this host process if it's a child of another PowerShell parent process... + $parentPID = (Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$PID" | Select-Object -Property ParentProcessId).ParentProcessId + $parentProcName = (Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$parentPID" | Select-Object -Property Name).Name + if ('powershell.exe' -eq $parentProcName) { $host.SetShouldExit($exitcode) } - exit $exitcode + exit $exitcode } function Show-PSWarning() { if ($PSVersionTable.PSVersion.Major -lt 7) { - Write-Color -Text "!!! ", "You are using old version of PowerShell - ", "$($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor)" -Color Red, Yellow, White + Write-Color -Text "!!! ", "You are using old version of PowerShell - ", "$($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor)" -Color Red, Yellow, White Write-Color -Text " Please update to at least 7.0 - ", "https://github.com/PowerShell/PowerShell/releases" -Color Yellow, White Exit-WithCode 1 } @@ -85,7 +87,7 @@ function Show-PSWarning() { function Install-Poetry() { Write-Color -Text ">>> ", "Installing Poetry ... " -Color Green, Gray - $env:POETRY_HOME = "$openpype_root\.poetry" + $env:POETRY_HOME="$openpype_root\.poetry" (Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py -UseBasicParsing).Content | python - } @@ -124,8 +126,8 @@ $version_file = Get-Content -Path "$($openpype_root)\openpype\version.py" $result = [regex]::Matches($version_file, '__version__ = "(?\d+\.\d+.\d+.*)"') $openpype_version = $result[0].Groups['version'].Value if (-not $openpype_version) { - Write-Color -Text "!!! ", "Cannot determine OpenPype version." -Color Yellow, Gray - Exit-WithCode 1 + Write-Color -Text "!!! ", "Cannot determine OpenPype version." -Color Yellow, Gray + Exit-WithCode 1 } # Create build directory if not exist @@ -145,8 +147,7 @@ catch { if (-not $disable_submodule_update) { Write-Color -Text ">>> ", "Making sure submodules are up-to-date ..." -Color Green, Gray & git submodule update --init --recursive -} -else { +} else { Write-Color -Text "*** ", "Not updating submodules ..." -Color Green, Gray } @@ -157,8 +158,7 @@ if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) { Write-Color -Text "NOT FOUND" -Color Yellow Write-Color -Text "*** ", "We need to install Poetry create virtual env first ..." -Color Yellow, Gray & "$openpype_root\tools\create_env.ps1" -} -else { +} else { Write-Color -Text "OK" -Color Green } @@ -173,7 +173,8 @@ $startTime = [int][double]::Parse((Get-Date -UFormat %s)) $out = & "$($env:POETRY_HOME)\bin\poetry" run python setup.py build 2>&1 Set-Content -Path "$($openpype_root)\build\build.log" -Value $out -if ($LASTEXITCODE -ne 0) { +if ($LASTEXITCODE -ne 0) +{ Write-Color -Text "------------------------------------------" -Color Red Get-Content "$($openpype_root)\build\build.log" Write-Color -Text "------------------------------------------" -Color Yellow @@ -188,8 +189,8 @@ Write-Color -Text ">>> ", "Restoring current directory" -Color Green, Gray Set-Location -Path $current_dir $endTime = [int][double]::Parse((Get-Date -UFormat %s)) -try { +try +{ New-BurntToastNotification -AppLogo "$openpype_root/openpype/resources/icons/openpype_icon.png" -Text "OpenPype build complete!", "All done in $( $endTime - $startTime ) secs. You will find OpenPype and build log in build directory." -} -catch {} +} catch {} Write-Color -Text "*** ", "All done in ", $($endTime - $startTime), " secs. You will find OpenPype and build log in ", "'.\build'", " directory." -Color Green, Gray, White, Gray, White, Gray From b2be8462c4ce95b17084e96f949377612681b8a1 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 15 Mar 2023 23:32:54 +0800 Subject: [PATCH 518/898] updating the loader so that the version will work in scene inventory --- .../hosts/max/plugins/load/load_max_scene.py | 3 +- .../publish/validate_no_max_content.py | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 openpype/hosts/max/plugins/publish/validate_no_max_content.py diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index fa8b6b28948..460f4822a64 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -47,8 +47,7 @@ def update(self, container, representation): path = get_representation_path(representation) node = rt.getNodeByName(container["instance_node"]) - - max_objects = self.get_container_children(node) + max_objects = node.Children for max_object in max_objects: max_object.source = path diff --git a/openpype/hosts/max/plugins/publish/validate_no_max_content.py b/openpype/hosts/max/plugins/publish/validate_no_max_content.py new file mode 100644 index 00000000000..0cf3b53044e --- /dev/null +++ b/openpype/hosts/max/plugins/publish/validate_no_max_content.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +import pyblish.api +from openpype.pipeline import PublishValidationError +from pymxs import runtime as rt + + +class ValidateMaxContents(pyblish.api.InstancePlugin): + """Validates Max contents. + + Check if MaxScene container includes any contents underneath. + """ + + order = pyblish.api.ValidatorOrder + families = ["maxScene"] + hosts = ["max"] + label = "Max Scene Contents" + + def process(self, instance): + invalid = self.get_invalid(instance) + if invalid: + raise PublishValidationError("No content found in the container") + + def get_invalid(self, instance): + invalid = [] + container = rt.getNodeByName(instance.data["instance_node"]) + if not container.Children: + invalid.append(container) + + return invalid From e35f7e0bb5d805b80f46aa9fdb1e40a18667fa2a Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 16 Mar 2023 00:06:29 +0800 Subject: [PATCH 519/898] update the validator which errors out with the empty container --- .../plugins/publish/validate_no_max_content.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/validate_no_max_content.py b/openpype/hosts/max/plugins/publish/validate_no_max_content.py index 0cf3b53044e..c20a1968ede 100644 --- a/openpype/hosts/max/plugins/publish/validate_no_max_content.py +++ b/openpype/hosts/max/plugins/publish/validate_no_max_content.py @@ -11,19 +11,13 @@ class ValidateMaxContents(pyblish.api.InstancePlugin): """ order = pyblish.api.ValidatorOrder - families = ["maxScene"] + families = ["camera", + "maxScene", + "maxrender"] hosts = ["max"] label = "Max Scene Contents" def process(self, instance): - invalid = self.get_invalid(instance) - if invalid: - raise PublishValidationError("No content found in the container") - - def get_invalid(self, instance): - invalid = [] container = rt.getNodeByName(instance.data["instance_node"]) - if not container.Children: - invalid.append(container) - - return invalid + if not list(container.Children): + raise PublishValidationError("No content found in the container") From 99ed91d0adb162a61005ce689d485d6f25619808 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 16 Mar 2023 14:03:25 +0800 Subject: [PATCH 520/898] fix the bug of submitting the frames for published job --- openpype/hosts/max/api/lib_renderproducts.py | 48 ++++++++++++++------ 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/openpype/hosts/max/api/lib_renderproducts.py b/openpype/hosts/max/api/lib_renderproducts.py index a74a6a74263..350eb976619 100644 --- a/openpype/hosts/max/api/lib_renderproducts.py +++ b/openpype/hosts/max/api/lib_renderproducts.py @@ -8,6 +8,7 @@ get_current_renderer, get_default_render_folder ) +from openpype.pipeline.context_tools import get_current_project_asset from openpype.settings import get_project_settings from openpype.pipeline import legacy_io @@ -34,14 +35,20 @@ def render_product(self, container): filename, container) + context = get_current_project_asset() + startFrame = context["data"].get("frameStart") + endFrame = context["data"].get("frameEnd") + 1 + img_fmt = self._project_settings["max"]["RenderSettings"]["image_format"] # noqa - full_render_list = [] - beauty = self.beauty_render_product(output_file, img_fmt) - full_render_list.append(beauty) + full_render_list = self.beauty_render_product(output_file, + startFrame, + endFrame, + img_fmt) renderer_class = get_current_renderer() renderer = str(renderer_class).split(":")[0] + if renderer == "VUE_File_Renderer": return full_render_list @@ -54,6 +61,8 @@ def render_product(self, container): "Quicksilver_Hardware_Renderer", ]: render_elem_list = self.render_elements_product(output_file, + startFrame, + endFrame, img_fmt) if render_elem_list: full_render_list.extend(iter(render_elem_list)) @@ -61,18 +70,24 @@ def render_product(self, container): if renderer == "Arnold": aov_list = self.arnold_render_product(output_file, + startFrame, + endFrame, img_fmt) if aov_list: full_render_list.extend(iter(aov_list)) return full_render_list - def beauty_render_product(self, folder, fmt): - beauty_output = f"{folder}.####.{fmt}" - beauty_output = beauty_output.replace("\\", "/") - return beauty_output + def beauty_render_product(self, folder, startFrame, endFrame, fmt): + beauty_frame_range = [] + for f in range(startFrame, endFrame): + beauty_output = f"{folder}.{f}.{fmt}" + beauty_output = beauty_output.replace("\\", "/") + beauty_frame_range.append(beauty_output) + + return beauty_frame_range # TODO: Get the arnold render product - def arnold_render_product(self, folder, fmt): + def arnold_render_product(self, folder, startFrame, endFrame, fmt): """Get all the Arnold AOVs""" aovs = [] @@ -85,15 +100,17 @@ def arnold_render_product(self, folder, fmt): for i in range(aov_group_num): # get the specific AOV group for aov in aov_mgr.drivers[i].aov_list: - render_element = f"{folder}_{aov.name}.####.{fmt}" - render_element = render_element.replace("\\", "/") - aovs.append(render_element) + for f in range(startFrame, endFrame): + render_element = f"{folder}_{aov.name}.{f}.{fmt}" + render_element = render_element.replace("\\", "/") + aovs.append(render_element) + # close the AOVs manager window amw.close() return aovs - def render_elements_product(self, folder, fmt): + def render_elements_product(self, folder, startFrame, endFrame, fmt): """Get all the render element output files. """ render_dirname = [] @@ -104,9 +121,10 @@ def render_elements_product(self, folder, fmt): renderlayer_name = render_elem.GetRenderElement(i) target, renderpass = str(renderlayer_name).split(":") if renderlayer_name.enabled: - render_element = f"{folder}_{renderpass}.####.{fmt}" - render_element = render_element.replace("\\", "/") - render_dirname.append(render_element) + for f in range(startFrame, endFrame): + render_element = f"{folder}_{renderpass}.{f}.{fmt}" + render_element = render_element.replace("\\", "/") + render_dirname.append(render_element) return render_dirname From fa69594c7079b8b482f649cf62f49a240da3be4a Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 27 Feb 2023 20:09:03 +0800 Subject: [PATCH 521/898] creator, validator and extractor for point cloud from tyFlow --- .../max/plugins/create/create_pointcloud.py | 26 +++ .../max/plugins/publish/extract_pointcloud.py | 170 ++++++++++++++++++ .../plugins/publish/validate_pointcloud.py | 74 ++++++++ openpype/plugins/publish/integrate.py | 1 + openpype/plugins/publish/integrate_legacy.py | 1 + .../defaults/project_settings/max.json | 15 ++ .../projects_schema/schema_project_max.json | 24 ++- 7 files changed, 310 insertions(+), 1 deletion(-) create mode 100644 openpype/hosts/max/plugins/create/create_pointcloud.py create mode 100644 openpype/hosts/max/plugins/publish/extract_pointcloud.py create mode 100644 openpype/hosts/max/plugins/publish/validate_pointcloud.py diff --git a/openpype/hosts/max/plugins/create/create_pointcloud.py b/openpype/hosts/max/plugins/create/create_pointcloud.py new file mode 100644 index 00000000000..c83acac3dfe --- /dev/null +++ b/openpype/hosts/max/plugins/create/create_pointcloud.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +"""Creator plugin for creating point cloud.""" +from openpype.hosts.max.api import plugin +from openpype.pipeline import CreatedInstance + + +class CreatePointCloud(plugin.MaxCreator): + identifier = "io.openpype.creators.max.pointcloud" + label = "Point Cloud" + family = "pointcloud" + icon = "gear" + + def create(self, subset_name, instance_data, pre_create_data): + from pymxs import runtime as rt + sel_obj = list(rt.selection) + instance = super(CreatePointCloud, self).create( + subset_name, + instance_data, + pre_create_data) # type: CreatedInstance + container = rt.getNodeByName(instance.data.get("instance_node")) + # TODO: Disable "Add to Containers?" Panel + # parent the selected cameras into the container + for obj in sel_obj: + obj.parent = container + # for additional work on the node: + # instance_node = rt.getNodeByName(instance.get("instance_node")) diff --git a/openpype/hosts/max/plugins/publish/extract_pointcloud.py b/openpype/hosts/max/plugins/publish/extract_pointcloud.py new file mode 100644 index 00000000000..9c471bc09e5 --- /dev/null +++ b/openpype/hosts/max/plugins/publish/extract_pointcloud.py @@ -0,0 +1,170 @@ +import os +import pyblish.api +from openpype.pipeline import publish +from pymxs import runtime as rt +from openpype.hosts.max.api import ( + maintained_selection +) +from openpype.settings import get_project_settings +from openpype.pipeline import legacy_io + + +def get_setting(project_setting=None): + project_setting = get_project_settings( + legacy_io.Session["AVALON_PROJECT"] + ) + return (project_setting["max"]["PointCloud"]) + + +class ExtractPointCloud(publish.Extractor): + """ + Extract PTF format with tyFlow operators + """ + + order = pyblish.api.ExtractorOrder - 0.2 + label = "Extract Point Cloud" + hosts = ["max"] + families = ["pointcloud"] + partition_start = 1 + partition_count = 100 + + + def process(self, instance): + start = str(instance.data.get("frameStartHandle", 1)) + end = str(instance.data.get("frameEndHandle", 1)) + container = instance.data["instance_node"] + + self.log.info("Extracting PRT...") + + stagingdir = self.staging_dir(instance) + filename = "{name}.prt".format(**instance.data) + path = os.path.join(stagingdir, filename) + + with maintained_selection(): + job_args = self.export_particle(container, + start, + end, + path) + for job in job_args: + rt.execute(job) + + self.log.info("Performing Extraction ...") + if "representations" not in instance.data: + instance.data["representations"] = [] + + self.log.info("Writing PRT with TyFlow Plugin...") + filenames = self.get_files(path, start, end) + self.log.info("filename: {0}".format(filenames)) + representation = { + 'name': 'prt', + 'ext': 'prt', + 'files': filenames if len(filenames) > 1 else filenames[0], + "stagingDir": stagingdir, + } + instance.data["representations"].append(representation) + self.log.info("Extracted instance '%s' to: %s" % (instance.name, + path)) + + def export_particle(self, + container, + start, + end, + filepath): + job_args = [] + opt_list = self.get_operators(container) + for operator in opt_list: + export_mode = "{0}.exportMode=2".format(operator) + job_args.append(export_mode) + start_frame = "{0}.frameStart={1}".format(operator, + start) + job_args.append(start_frame) + end_frame = "{0}.frameEnd={1}".format(operator, + end) + job_args.append(end_frame) + filepath = filepath.replace("\\", "/") + prt_filename = '{0}.PRTFilename="{1}"'.format(operator, + filepath) + + job_args.append(prt_filename) + # Partition + mode = "{0}.PRTPartitionsMode=2".format(operator) + job_args.append(mode) + + additional_args = self.get_custom_attr(operator) + for args in additional_args: + job_args.append(args) + + prt_export = "{0}.exportPRT()".format(operator) + job_args.append(prt_export) + + return job_args + + def get_operators(self, container): + """Get Export Particles Operator""" + + opt_list = [] + node = rt.getNodebyName(container) + selection_list = list(node.Children) + for sel in selection_list: + obj = sel.baseobject + # TODO: to see if it can be used maxscript instead + anim_names = rt.getsubanimnames(obj) + for anim_name in anim_names: + sub_anim = rt.getsubanim(obj, anim_name) + boolean = rt.isProperty(sub_anim, "Export_Particles") + event_name = sub_anim.name + if boolean: + opt = "${0}.{1}.export_particles".format(sel.name, + event_name) + opt_list.append(opt) + + return opt_list + + def get_custom_attr(self, operator): + """Get Custom Attributes""" + + custom_attr_list = [] + attr_settings = get_setting()["attribute"] + for key, value in attr_settings.items(): + custom_attr = "{0}.PRTChannels_{1}=True".format(operator, + value) + self.log.debug( + "{0} will be added as custom attribute".format(key) + ) + custom_attr_list.append(custom_attr) + + return custom_attr_list + + def get_files(self, + path, + start_frame, + end_frame): + """ + Note: + Set the filenames accordingly to the tyFlow file + naming extension for the publishing purpose + + Actual File Output from tyFlow: + __partof..prt + e.g. tyFlow_cloth_CCCS_blobbyFill_001__part1of1_00004.prt + Renamed Output: + ..prt + e.g. pointcloudMain.0001.prt + """ + filenames = [] + filename = os.path.basename(path) + orig_name, ext = os.path.splitext(filename) + partition_start = str(self.partition_start) + partition_count = str(self.partition_count) + for frame in range(int(start_frame), int(end_frame) + 1): + actual_name = "{}__part{:03}of{}_{:05}".format(orig_name, + partition_start, + partition_count, + frame) + actual_filename = path.replace(orig_name, actual_name) + new_name = "{}.{:04}".format(orig_name, frame) + renamed_filename = path.replace(orig_name, new_name) + os.rename(actual_filename, renamed_filename) + filenames.append(os.path.basename(renamed_filename)) + + return filenames diff --git a/openpype/hosts/max/plugins/publish/validate_pointcloud.py b/openpype/hosts/max/plugins/publish/validate_pointcloud.py new file mode 100644 index 00000000000..c6725d61263 --- /dev/null +++ b/openpype/hosts/max/plugins/publish/validate_pointcloud.py @@ -0,0 +1,74 @@ +import pyblish.api +from openpype.pipeline import PublishValidationError +from pymxs import runtime as rt + + +class ValidatePointCloud(pyblish.api.InstancePlugin): + """Validate that workfile was saved.""" + + order = pyblish.api.ValidatorOrder + families = ["pointcloud"] + hosts = ["max"] + label = "Validate Point Cloud" + + def process(self, instance): + """ + Notes: + + 1. Validate the container only include tyFlow objects + 2. Validate if tyFlow operator Export Particle exists + + """ + invalid = self.get_tyFlow_object(instance) + if invalid: + raise PublishValidationError("Non tyFlow object " + "found: {}".format(invalid)) + invalid = self.get_tyFlow_operator(instance) + if invalid: + raise PublishValidationError("tyFlow ExportParticle operator " + "not found: {}".format(invalid)) + + def get_tyFlow_object(self, instance): + invalid = [] + container = instance.data["instance_node"] + self.log.info("Validating tyFlow container " + "for {}".format(container)) + + con = rt.getNodeByName(container) + selection_list = list(con.Children) + for sel in selection_list: + sel_tmp = str(sel) + if rt.classOf(sel) in [rt.tyFlow, + rt.Editable_Mesh]: + if "tyFlow" not in sel_tmp: + invalid.append(sel) + else: + invalid.append(sel) + + return invalid + + def get_tyFlow_operator(self, instance): + invalid = [] + container = instance.data["instance_node"] + self.log.info("Validating tyFlow object " + "for {}".format(container)) + + con = rt.getNodeByName(container) + selection_list = list(con.Children) + bool_list = [] + for sel in selection_list: + obj = sel.baseobject + anim_names = rt.getsubanimnames(obj) + for anim_name in anim_names: + # get all the names of the related tyFlow nodes + sub_anim = rt.getsubanim(obj, anim_name) + # check if there is export particle operator + boolean = rt.isProperty(sub_anim, "Export_Particles") + bool_list.append(str(boolean)) + # if the export_particles property is not there + # it means there is not a "Export Particle" operator + if "True" not in bool_list: + self.log.error("Operator 'Export Particles' not found!") + invalid.append(sel) + + return invalid diff --git a/openpype/plugins/publish/integrate.py b/openpype/plugins/publish/integrate.py index 69b7734c70c..6a0327ec843 100644 --- a/openpype/plugins/publish/integrate.py +++ b/openpype/plugins/publish/integrate.py @@ -80,6 +80,7 @@ class IntegrateAsset(pyblish.api.InstancePlugin): order = pyblish.api.IntegratorOrder families = ["workfile", "pointcache", + "pointcloud", "proxyAbc", "camera", "animation", diff --git a/openpype/plugins/publish/integrate_legacy.py b/openpype/plugins/publish/integrate_legacy.py index 66c2c9be512..1d0177f1515 100644 --- a/openpype/plugins/publish/integrate_legacy.py +++ b/openpype/plugins/publish/integrate_legacy.py @@ -76,6 +76,7 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): order = pyblish.api.IntegratorOrder + 0.00001 families = ["workfile", "pointcache", + "pointcloud", "proxyAbc", "camera", "animation", diff --git a/openpype/settings/defaults/project_settings/max.json b/openpype/settings/defaults/project_settings/max.json index 667b42411d6..d59cdf8c4a3 100644 --- a/openpype/settings/defaults/project_settings/max.json +++ b/openpype/settings/defaults/project_settings/max.json @@ -4,5 +4,20 @@ "aov_separator": "underscore", "image_format": "exr", "multipass": true + }, + "PointCloud":{ + "attribute":{ + "Age": "age", + "Radius": "radius", + "Position": "position", + "Rotation": "rotation", + "Scale": "scale", + "Velocity": "velocity", + "Color": "color", + "TextureCoordinate": "texcoord", + "MaterialID": "matid", + "custFloats": "custFloats", + "custVecs": "custVecs" + } } } diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_max.json b/openpype/settings/entities/schemas/projects_schema/schema_project_max.json index 8a283c1acc3..4fba9aff0a0 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_max.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_max.json @@ -51,6 +51,28 @@ "label": "multipass" } ] + }, + { + "type": "dict", + "collapsible": true, + "key": "PointCloud", + "label": "Point Cloud", + "children": [ + { + "type": "label", + "label": "Define the channel attribute names before exporting as PRT" + }, + { + "type": "dict-modifiable", + "collapsible": true, + "key": "attribute", + "label": "Channel Attribute", + "use_label_wrap": true, + "object_type": { + "type": "text" + } + } + ] } ] -} \ No newline at end of file +} From 7df1b215c7831c33de0c2ebf55fc8e7d39ec9fff Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 27 Feb 2023 20:18:19 +0800 Subject: [PATCH 522/898] hound fix --- openpype/hosts/max/plugins/publish/extract_pointcloud.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/max/plugins/publish/extract_pointcloud.py b/openpype/hosts/max/plugins/publish/extract_pointcloud.py index 9c471bc09e5..1ef127b73b5 100644 --- a/openpype/hosts/max/plugins/publish/extract_pointcloud.py +++ b/openpype/hosts/max/plugins/publish/extract_pointcloud.py @@ -28,7 +28,6 @@ class ExtractPointCloud(publish.Extractor): partition_start = 1 partition_count = 100 - def process(self, instance): start = str(instance.data.get("frameStartHandle", 1)) end = str(instance.data.get("frameEndHandle", 1)) From 399600769483ea7b3062ec02fd4bf70680caa0ec Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 27 Feb 2023 22:05:11 +0800 Subject: [PATCH 523/898] update validators --- .../max/plugins/publish/extract_pointcloud.py | 6 +- .../plugins/publish/validate_pointcloud.py | 121 +++++++++++++++++- 2 files changed, 121 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/extract_pointcloud.py b/openpype/hosts/max/plugins/publish/extract_pointcloud.py index 1ef127b73b5..4436c066435 100644 --- a/openpype/hosts/max/plugins/publish/extract_pointcloud.py +++ b/openpype/hosts/max/plugins/publish/extract_pointcloud.py @@ -72,8 +72,6 @@ def export_particle(self, job_args = [] opt_list = self.get_operators(container) for operator in opt_list: - export_mode = "{0}.exportMode=2".format(operator) - job_args.append(export_mode) start_frame = "{0}.frameStart={1}".format(operator, start) job_args.append(start_frame) @@ -153,8 +151,8 @@ def get_files(self, filenames = [] filename = os.path.basename(path) orig_name, ext = os.path.splitext(filename) - partition_start = str(self.partition_start) - partition_count = str(self.partition_count) + partition_start = self.partition_start + partition_count = self.partition_count for frame in range(int(start_frame), int(end_frame) + 1): actual_name = "{}__part{:03}of{}_{:05}".format(orig_name, partition_start, diff --git a/openpype/hosts/max/plugins/publish/validate_pointcloud.py b/openpype/hosts/max/plugins/publish/validate_pointcloud.py index c6725d61263..ba9f2834a60 100644 --- a/openpype/hosts/max/plugins/publish/validate_pointcloud.py +++ b/openpype/hosts/max/plugins/publish/validate_pointcloud.py @@ -1,6 +1,15 @@ import pyblish.api from openpype.pipeline import PublishValidationError from pymxs import runtime as rt +from openpype.settings import get_project_settings +from openpype.pipeline import legacy_io + + +def get_setting(project_setting=None): + project_setting = get_project_settings( + legacy_io.Session["AVALON_PROJECT"] + ) + return (project_setting["max"]["PointCloud"]) class ValidatePointCloud(pyblish.api.InstancePlugin): @@ -15,8 +24,14 @@ def process(self, instance): """ Notes: - 1. Validate the container only include tyFlow objects - 2. Validate if tyFlow operator Export Particle exists + 1. Validate the container only include tyFlow objects + 2. Validate if tyFlow operator Export Particle exists + 3. Validate if the export mode of Export Particle is at PRT format + 4. Validate the partition count and range set as default value + Partition Count : 100 + Partition Range : 1 to 1 + 5. Validate if the custom attribute(s) exist as parameter(s) + of export_particle operator """ invalid = self.get_tyFlow_object(instance) @@ -28,6 +43,19 @@ def process(self, instance): raise PublishValidationError("tyFlow ExportParticle operator " "not found: {}".format(invalid)) + invalid = self.validate_export_mode(instance) + if invalid: + raise PublishValidationError("The export mode is not at PRT") + + invalid = self.validate_partition_value(instance) + if invalid: + raise PublishValidationError("tyFlow Partition setting is " + "not at the default value") + invalid = self.validate_custom_attribute(instance) + if invalid: + raise PublishValidationError("Custom Attribute not found " + ":{}".format(invalid)) + def get_tyFlow_object(self, instance): invalid = [] container = instance.data["instance_node"] @@ -72,3 +100,92 @@ def get_tyFlow_operator(self, instance): invalid.append(sel) return invalid + + def validate_custom_attribute(self, instance): + invalid = [] + container = instance.data["instance_node"] + self.log.info("Validating tyFlow custom " + "attributes for {}".format(container)) + + con = rt.getNodeByName(container) + selection_list = list(con.Children) + for sel in selection_list: + obj = sel.baseobject + anim_names = rt.getsubanimnames(obj) + for anim_name in anim_names: + # get all the names of the related tyFlow nodes + sub_anim = rt.getsubanim(obj, anim_name) + # check if there is export particle operator + boolean = rt.isProperty(sub_anim, "Export_Particles") + event_name = sub_anim.name + if boolean: + opt = "${0}.{1}.export_particles".format(sel.name, + event_name) + attributes = get_setting()["attribute"] + for key, value in attributes.items(): + custom_attr = "{0}.PRTChannels_{1}".format(opt, + value) + try: + rt.execute(custom_attr) + except RuntimeError: + invalid.add(key) + + return invalid + + def validate_partition_value(self, instance): + invalid = [] + container = instance.data["instance_node"] + self.log.info("Validating tyFlow partition " + "value for {}".format(container)) + + con = rt.getNodeByName(container) + selection_list = list(con.Children) + for sel in selection_list: + obj = sel.baseobject + anim_names = rt.getsubanimnames(obj) + for anim_name in anim_names: + # get all the names of the related tyFlow nodes + sub_anim = rt.getsubanim(obj, anim_name) + # check if there is export particle operator + boolean = rt.isProperty(sub_anim, "Export_Particles") + event_name = sub_anim.name + if boolean: + opt = "${0}.{1}.export_particles".format(sel.name, + event_name) + count = rt.execute(f'{opt}.PRTPartitionsCount') + if count != 100: + invalid.append(count) + start = rt.execute(f'{opt}.PRTPartitionsFrom') + if start != 1: + invalid.append(start) + end = rt.execute(f'{opt}.PRTPartitionsTo') + if end != 1: + invalid.append(end) + + return invalid + + def validate_export_mode(self, instance): + invalid = [] + container = instance.data["instance_node"] + self.log.info("Validating tyFlow partition " + "value for {}".format(container)) + + con = rt.getNodeByName(container) + selection_list = list(con.Children) + for sel in selection_list: + obj = sel.baseobject + anim_names = rt.getsubanimnames(obj) + for anim_name in anim_names: + # get all the names of the related tyFlow nodes + sub_anim = rt.getsubanim(obj, anim_name) + # check if there is export particle operator + boolean = rt.isProperty(sub_anim, "Export_Particles") + event_name = sub_anim.name + if boolean: + opt = "${0}.{1}.export_particles".format(sel.name, + event_name) + export_mode = rt.execute(f'{opt}.exportMode') + if export_mode != 2: + invalid.append(export_mode) + + return invalid From 29138974b49da0d03eaf2bbbcedd3243d6420bfe Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 27 Feb 2023 22:24:25 +0800 Subject: [PATCH 524/898] update validators --- openpype/hosts/max/plugins/publish/validate_pointcloud.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/validate_pointcloud.py b/openpype/hosts/max/plugins/publish/validate_pointcloud.py index ba9f2834a60..34310eac7af 100644 --- a/openpype/hosts/max/plugins/publish/validate_pointcloud.py +++ b/openpype/hosts/max/plugins/publish/validate_pointcloud.py @@ -167,8 +167,8 @@ def validate_partition_value(self, instance): def validate_export_mode(self, instance): invalid = [] container = instance.data["instance_node"] - self.log.info("Validating tyFlow partition " - "value for {}".format(container)) + self.log.info("Validating tyFlow export " + "mode for {}".format(container)) con = rt.getNodeByName(container) selection_list = list(con.Children) From a4c36b9e4f1a52107010515aa28358e174658833 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 28 Feb 2023 18:14:25 +0800 Subject: [PATCH 525/898] add loaders --- .../hosts/max/plugins/load/load_pointcloud.py | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 openpype/hosts/max/plugins/load/load_pointcloud.py diff --git a/openpype/hosts/max/plugins/load/load_pointcloud.py b/openpype/hosts/max/plugins/load/load_pointcloud.py new file mode 100644 index 00000000000..dfa63e23f86 --- /dev/null +++ b/openpype/hosts/max/plugins/load/load_pointcloud.py @@ -0,0 +1,51 @@ +import os +from openpype.pipeline import ( + load, get_representation_path +) +from openpype.hosts.max.api.pipeline import containerise +from openpype.hosts.max.api import lib + + +class PointCloudLoader(load.LoaderPlugin): + """Point Cloud Loader""" + + families = ["pointcloud"] + representations = ["prt"] + order = -8 + icon = "code-fork" + color = "green" + + def load(self, context, name=None, namespace=None, data=None): + """load point cloud by tyCache""" + + from pymxs import runtime as rt + filepath = os.path.normpath(self.fname) + obj = rt.tyCache() + obj.filename = filepath + + prt_container = rt.getNodeByName(f"{obj.name}") + + return containerise( + name, [prt_container], context, loader=self.__class__.__name__) + + def update(self, container, representation): + """update the container""" + + from pymxs import runtime as rt + path = get_representation_path(representation) + node = rt.getNodeByName(container["instance_node"]) + + prt_objects = self.get_container_children(node) + for prt_object in prt_objects: + prt_object.source = path + + lib.imprint(container["instance_node"], { + "representation": str(representation["_id"]) + }) + + def remove(self, container): + """remove the container""" + from pymxs import runtime as rt + + node = rt.getNodeByName(container["instance_node"]) + rt.delete(node) From f95f8f6ebe4a1d32a97ca3daa14d061a31befce9 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 28 Feb 2023 18:31:53 +0800 Subject: [PATCH 526/898] add loader --- openpype/hosts/max/plugins/load/load_pointcloud.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_pointcloud.py b/openpype/hosts/max/plugins/load/load_pointcloud.py index dfa63e23f86..27bc88b4f32 100644 --- a/openpype/hosts/max/plugins/load/load_pointcloud.py +++ b/openpype/hosts/max/plugins/load/load_pointcloud.py @@ -17,8 +17,8 @@ class PointCloudLoader(load.LoaderPlugin): def load(self, context, name=None, namespace=None, data=None): """load point cloud by tyCache""" - from pymxs import runtime as rt + filepath = os.path.normpath(self.fname) obj = rt.tyCache() obj.filename = filepath @@ -30,8 +30,8 @@ def load(self, context, name=None, namespace=None, data=None): def update(self, container, representation): """update the container""" - from pymxs import runtime as rt + path = get_representation_path(representation) node = rt.getNodeByName(container["instance_node"]) From 416b7d9b942fc34901fe03fedcfe4fb3bcd3b730 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 1 Mar 2023 15:37:30 +0800 Subject: [PATCH 527/898] add partition naming format into the extractor --- .../max/plugins/publish/extract_pointcloud.py | 68 +++++++++++++++---- 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/extract_pointcloud.py b/openpype/hosts/max/plugins/publish/extract_pointcloud.py index 4436c066435..db83bf71fc7 100644 --- a/openpype/hosts/max/plugins/publish/extract_pointcloud.py +++ b/openpype/hosts/max/plugins/publish/extract_pointcloud.py @@ -18,15 +18,31 @@ def get_setting(project_setting=None): class ExtractPointCloud(publish.Extractor): """ - Extract PTF format with tyFlow operators + Extract PRT format with tyFlow operators + + Notes: + Currently only works for the default partition setting + + Args: + export_particle(): sets up all job arguments for attributes + to be exported in MAXscript + + get_operators(): get the export_particle operator + + get_custom_attr(): get all custom channel attributes from the Openpype + setting and sets it as job arguments before exporting + + get_files(): get the files with tyFlow naming convention before publishing + + partition_output_name(): get the naming with partition settings. + get_partition(): get partition value + """ order = pyblish.api.ExtractorOrder - 0.2 label = "Extract Point Cloud" hosts = ["max"] families = ["pointcloud"] - partition_start = 1 - partition_count = 100 def process(self, instance): start = str(instance.data.get("frameStartHandle", 1)) @@ -52,13 +68,17 @@ def process(self, instance): instance.data["representations"] = [] self.log.info("Writing PRT with TyFlow Plugin...") - filenames = self.get_files(path, start, end) - self.log.info("filename: {0}".format(filenames)) + filenames = self.get_files(container, path, start, end) + self.log.debug("filenames: {0}".format(filenames)) + + partition = self.partition_output_name(container) + representation = { 'name': 'prt', 'ext': 'prt', 'files': filenames if len(filenames) > 1 else filenames[0], "stagingDir": stagingdir, + "outputName": partition # partition value } instance.data["representations"].append(representation) self.log.info("Extracted instance '%s' to: %s" % (instance.name, @@ -133,6 +153,7 @@ def get_custom_attr(self, operator): return custom_attr_list def get_files(self, + container, path, start_frame, end_frame): @@ -144,24 +165,43 @@ def get_files(self, Actual File Output from tyFlow: __partof..prt e.g. tyFlow_cloth_CCCS_blobbyFill_001__part1of1_00004.prt - Renamed Output: - ..prt - e.g. pointcloudMain.0001.prt """ filenames = [] filename = os.path.basename(path) orig_name, ext = os.path.splitext(filename) - partition_start = self.partition_start - partition_count = self.partition_count + partition_count, partition_start = self.get_partition(container) for frame in range(int(start_frame), int(end_frame) + 1): actual_name = "{}__part{:03}of{}_{:05}".format(orig_name, partition_start, partition_count, frame) actual_filename = path.replace(orig_name, actual_name) - new_name = "{}.{:04}".format(orig_name, frame) - renamed_filename = path.replace(orig_name, new_name) - os.rename(actual_filename, renamed_filename) - filenames.append(os.path.basename(renamed_filename)) + filenames.append(os.path.basename(actual_filename)) return filenames + + def partition_output_name(self, container): + """ + Notes: + Partition output name set for mapping + the published file output + + todo: + Customizes the setting for the output + """ + partition_count, partition_start = self.get_partition(container) + partition = "_part{:03}of{}".format(partition_start, + partition_count) + + return partition + + def get_partition(self, container): + """ + Get Partition Value + """ + opt_list = self.get_operators(container) + for operator in opt_list: + count = rt.execute(f'{operator}.PRTPartitionsCount') + start = rt.execute(f'{operator}.PRTPartitionsFrom') + + return count, start From b9ab6f634e8219c0af436895f9cc7d38f56ebca2 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 1 Mar 2023 15:39:25 +0800 Subject: [PATCH 528/898] hound fix --- openpype/hosts/max/plugins/publish/extract_pointcloud.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/extract_pointcloud.py b/openpype/hosts/max/plugins/publish/extract_pointcloud.py index db83bf71fc7..0e4f4621eac 100644 --- a/openpype/hosts/max/plugins/publish/extract_pointcloud.py +++ b/openpype/hosts/max/plugins/publish/extract_pointcloud.py @@ -29,10 +29,11 @@ class ExtractPointCloud(publish.Extractor): get_operators(): get the export_particle operator - get_custom_attr(): get all custom channel attributes from the Openpype + get_custom_attr(): get all custom channel attributes from Openpype setting and sets it as job arguments before exporting - get_files(): get the files with tyFlow naming convention before publishing + get_files(): get the files with tyFlow naming convention + before publishing partition_output_name(): get the naming with partition settings. get_partition(): get partition value @@ -78,7 +79,7 @@ def process(self, instance): 'ext': 'prt', 'files': filenames if len(filenames) > 1 else filenames[0], "stagingDir": stagingdir, - "outputName": partition # partition value + "outputName": partition # partition value } instance.data["representations"].append(representation) self.log.info("Extracted instance '%s' to: %s" % (instance.name, From b1f3e114058276b65e7c21da477642422f9c49b3 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 2 Mar 2023 00:05:54 +0800 Subject: [PATCH 529/898] fix the validator check on exportMode --- openpype/hosts/max/plugins/publish/validate_pointcloud.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/plugins/publish/validate_pointcloud.py b/openpype/hosts/max/plugins/publish/validate_pointcloud.py index 34310eac7af..f6540586483 100644 --- a/openpype/hosts/max/plugins/publish/validate_pointcloud.py +++ b/openpype/hosts/max/plugins/publish/validate_pointcloud.py @@ -185,7 +185,7 @@ def validate_export_mode(self, instance): opt = "${0}.{1}.export_particles".format(sel.name, event_name) export_mode = rt.execute(f'{opt}.exportMode') - if export_mode != 2: + if export_mode != 1: invalid.append(export_mode) return invalid From 341ef34e353a52644a5bd92a02992adc3c0830d5 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 2 Mar 2023 23:18:33 +0800 Subject: [PATCH 530/898] update frame range --- openpype/hosts/max/plugins/publish/extract_pointcloud.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/extract_pointcloud.py b/openpype/hosts/max/plugins/publish/extract_pointcloud.py index 0e4f4621eac..e8d58ab7134 100644 --- a/openpype/hosts/max/plugins/publish/extract_pointcloud.py +++ b/openpype/hosts/max/plugins/publish/extract_pointcloud.py @@ -46,10 +46,9 @@ class ExtractPointCloud(publish.Extractor): families = ["pointcloud"] def process(self, instance): - start = str(instance.data.get("frameStartHandle", 1)) - end = str(instance.data.get("frameEndHandle", 1)) + start = int(instance.context.data.get("frameStart")) + end = int(instance.context.data.get("frameEnd")) container = instance.data["instance_node"] - self.log.info("Extracting PRT...") stagingdir = self.staging_dir(instance) From f537020b97bfbf6584cfac373ee5dc264509d7e1 Mon Sep 17 00:00:00 2001 From: Ynbot Date: Sat, 18 Mar 2023 03:26:38 +0000 Subject: [PATCH 531/898] [Automated] Bump version --- openpype/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/version.py b/openpype/version.py index 39a7dc9344a..339c17dc70e 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.15.3-nightly.1" +__version__ = "3.15.3-nightly.2" From 0fe0e8c02cbafc56b202c828d5010e3d1b665d56 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Sat, 18 Mar 2023 10:03:28 +0000 Subject: [PATCH 532/898] Settings for GPU cache extractor --- .../maya/plugins/publish/extract_gpu_cache.py | 33 +++++++++-- .../defaults/project_settings/maya.json | 15 +++++ .../schemas/schema_maya_publish.json | 59 +++++++++++++++++++ 3 files changed, 102 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py index db848337226..544a2d376a8 100644 --- a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py +++ b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py @@ -1,3 +1,5 @@ +import json + from maya import cmds from openpype.pipeline import publish @@ -9,18 +11,39 @@ class ExtractGPUCache(publish.Extractor): label = "GPU Cache" hosts = ["maya"] families = ["model", "animation", "pointcache"] + simulationRate = 1.0 + sampleMultiplier = 1 + optimize = True + optimizationThreshold = 40000 + optimizeAnimationsForMotionBlur = True + writeMaterials = True + useBaseTessellation = True def process(self, instance): staging_dir = self.staging_dir(instance) filename = "{}.abc".format(instance.name) # Write out GPU cache file. - cmds.gpuCache( - instance[:], - directory=staging_dir, - fileName=filename, - saveMultipleFiles=False + kwargs = { + "directory": staging_dir, + "fileName": filename, + "saveMultipleFiles": False, + "simulationRate": self.simulationRate, + "sampleMultiplier": self.sampleMultiplier, + "optimize": self.optimize, + "optimizationThreshold": self.optimizationThreshold, + "optimizeAnimationsForMotionBlur": ( + self.optimizeAnimationsForMotionBlur + ), + "writeMaterials": self.writeMaterials, + "useBaseTessellation": self.useBaseTessellation + } + self.log.debug( + "Extract {} with:\n{}".format( + instance[:], json.dumps(kwargs, indent=4, sort_keys=True) + ) ) + cmds.gpuCache(instance[:], **kwargs) if "representations" not in instance.data: instance.data["representations"] = [] diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index 63ba4542f3f..801a04d1444 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -923,6 +923,21 @@ "enabled": true, "active": true, "ogsfx_path": "/maya2glTF/PBR/shaders/glTF_PBR.ogsfx" + }, + "ExtractGPUCache": { + "enabled": true, + "families": [ + "model", + "animation", + "pointcache" + ], + "simulationRate": 0.0, + "sampleMultiplier": 0, + "optimize": true, + "optimizationThreshold": 40000, + "optimizeAnimationsForMotionBlur": true, + "writeMaterials": true, + "useBaseTessellation": true } }, "load": { diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json index 3484f42f6b6..03a447b05e6 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json @@ -992,6 +992,65 @@ "label": "GLSL Shader Directory" } ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ExtractGPUCache", + "label": "Extract GPU Cache", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "key": "families", + "label": "Families", + "type": "list", + "object_type": "text" + }, + { + "key": "simulationRate", + "label": "Evaluate Every", + "type": "number", + "decimal": 4, + "minimum": 1 + }, + { + "key": "sampleMultiplier", + "label": "Save Every", + "type": "number", + "minimum": 1 + }, + { + "key": "optimize", + "label": "Optimize Hierarchy", + "type": "boolean" + }, + { + "key": "optimizationThreshold", + "label": "Optimization Threshold", + "type": "number", + "minimum": 1 + }, + { + "key": "optimizeAnimationsForMotionBlur", + "label": "Optimize Animations For Motion Blur", + "type": "boolean" + }, + { + "key": "writeMaterials", + "label": "Write Materials", + "type": "boolean" + }, + { + "key": "useBaseTessellation", + "label": "User Base Tesselation", + "type": "boolean" + } + ] } ] } From 69ff474801b4f7cb8aa463cac6119b868a2669b9 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Sat, 18 Mar 2023 10:26:59 +0000 Subject: [PATCH 533/898] Remove hero suffix logic. --- .../maya/plugins/publish/extract_gpu_cache.py | 1 - .../plugins/publish/integrate_hero_version.py | 16 ---------------- 2 files changed, 17 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py index 544a2d376a8..6e8eaf57ce2 100644 --- a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py +++ b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py @@ -53,7 +53,6 @@ def process(self, instance): "ext": "abc", "files": filename, "stagingDir": staging_dir, - "data": {"heroSuffix": "gpu_cache"}, "outputName": "gpu_cache" } diff --git a/openpype/plugins/publish/integrate_hero_version.py b/openpype/plugins/publish/integrate_hero_version.py index 4d7d0accad6..6e233dd5a9b 100644 --- a/openpype/plugins/publish/integrate_hero_version.py +++ b/openpype/plugins/publish/integrate_hero_version.py @@ -306,22 +306,6 @@ def integrate_instance( anatomy_filled = anatomy.format(anatomy_data) template_filled = anatomy_filled[template_key]["path"] - # For representations that have the same extension, an - # additional suffix can be available to make the destination - # filename different. - hero_suffix = repre_info["representation"]["data"].get( - "heroSuffix" - ) - if hero_suffix: - fill_data = copy.deepcopy(template_filled.used_values) - template_filled.template = template_filled.replace( - "." + fill_data["ext"], - "_{}.{}".format(hero_suffix, fill_data["ext"]) - ) - template_filled = StringTemplate( - template_filled.template - ).format(fill_data) - # Prepare new repre repre_data = { "path": str(template_filled), From 6490c1e387b04fe13ad6d754fa0a8d18e695ad89 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Sat, 18 Mar 2023 10:27:49 +0000 Subject: [PATCH 534/898] Hound --- openpype/plugins/publish/integrate_hero_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/plugins/publish/integrate_hero_version.py b/openpype/plugins/publish/integrate_hero_version.py index 6e233dd5a9b..7adb2b66ec9 100644 --- a/openpype/plugins/publish/integrate_hero_version.py +++ b/openpype/plugins/publish/integrate_hero_version.py @@ -18,7 +18,7 @@ prepare_hero_version_update_data, prepare_representation_update_data, ) -from openpype.lib import create_hard_link, StringTemplate +from openpype.lib import create_hard_link from openpype.pipeline import ( schema ) From 03c6fab3ea0ed2a979e06b29eef6914bfa440d76 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Sat, 18 Mar 2023 10:29:01 +0000 Subject: [PATCH 535/898] Remove hero edits. --- openpype/plugins/publish/integrate_hero_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/plugins/publish/integrate_hero_version.py b/openpype/plugins/publish/integrate_hero_version.py index 7adb2b66ec9..e796f7b376a 100644 --- a/openpype/plugins/publish/integrate_hero_version.py +++ b/openpype/plugins/publish/integrate_hero_version.py @@ -306,7 +306,6 @@ def integrate_instance( anatomy_filled = anatomy.format(anatomy_data) template_filled = anatomy_filled[template_key]["path"] - # Prepare new repre repre_data = { "path": str(template_filled), "template": hero_template @@ -317,6 +316,7 @@ def integrate_instance( if value is not None: repre_context[key] = value + # Prepare new repre repre = copy.deepcopy(repre_info["representation"]) repre["parent"] = new_hero_version["_id"] repre["context"] = repre_context From b3e8fb2c175eb8de1a43b88550b8659a95c9966d Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Sat, 18 Mar 2023 10:40:30 +0000 Subject: [PATCH 536/898] Ensure unique extraction. --- openpype/hosts/maya/plugins/publish/extract_gpu_cache.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py index 6e8eaf57ce2..b51242fa503 100644 --- a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py +++ b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py @@ -21,7 +21,7 @@ class ExtractGPUCache(publish.Extractor): def process(self, instance): staging_dir = self.staging_dir(instance) - filename = "{}.abc".format(instance.name) + filename = "{}_gpu_cache".format(instance.name) # Write out GPU cache file. kwargs = { @@ -51,9 +51,9 @@ def process(self, instance): representation = { "name": "gpu_cache", "ext": "abc", - "files": filename, + "files": filename + ".abc", "stagingDir": staging_dir, - "outputName": "gpu_cache" + #"outputName": "gpu_cache" } instance.data["representations"].append(representation) From 12c54e22d6ebaa09f21621606f9dd1d96bd73aa7 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Sat, 18 Mar 2023 10:40:47 +0000 Subject: [PATCH 537/898] Ensure unique integration --- openpype/hosts/maya/plugins/publish/extract_gpu_cache.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py index b51242fa503..91efab38edf 100644 --- a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py +++ b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py @@ -53,7 +53,7 @@ def process(self, instance): "ext": "abc", "files": filename + ".abc", "stagingDir": staging_dir, - #"outputName": "gpu_cache" + "outputName": "gpu_cache" } instance.data["representations"].append(representation) From 1dec179dc766d341a56b37baf3e07f6d092aca98 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Sat, 18 Mar 2023 19:29:20 +0100 Subject: [PATCH 538/898] Changed the name from existing to expected frames --- ...ollect_existing_frames.py => collect_expected_frames.py} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename openpype/hosts/fusion/plugins/publish/{collect_existing_frames.py => collect_expected_frames.py} (88%) diff --git a/openpype/hosts/fusion/plugins/publish/collect_existing_frames.py b/openpype/hosts/fusion/plugins/publish/collect_expected_frames.py similarity index 88% rename from openpype/hosts/fusion/plugins/publish/collect_existing_frames.py rename to openpype/hosts/fusion/plugins/publish/collect_expected_frames.py index 7c5f7cd55df..485ca0c9a48 100644 --- a/openpype/hosts/fusion/plugins/publish/collect_existing_frames.py +++ b/openpype/hosts/fusion/plugins/publish/collect_expected_frames.py @@ -2,11 +2,11 @@ import os -class CollectFusionRenders(pyblish.api.InstancePlugin): - """Collect all frames needed to publish existing frames""" +class CollectFusionExpectedFrames(pyblish.api.InstancePlugin): + """Collect all frames needed to publish expected frames""" order = pyblish.api.CollectorOrder + 0.5 - label = "Collect Existing Frames" + label = "Collect Expected Frames" hosts = ["fusion"] families = ["render.frames"] From aad3325e046de74696ba93bd8b2d592b423a3d8b Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Sat, 18 Mar 2023 19:29:32 +0100 Subject: [PATCH 539/898] Cleaned up code --- openpype/hosts/fusion/plugins/publish/collect_renders.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/collect_renders.py b/openpype/hosts/fusion/plugins/publish/collect_renders.py index be405d24951..7f38e68447d 100644 --- a/openpype/hosts/fusion/plugins/publish/collect_renders.py +++ b/openpype/hosts/fusion/plugins/publish/collect_renders.py @@ -1,5 +1,4 @@ import pyblish.api -from pprint import pformat class CollectFusionRenders(pyblish.api.InstancePlugin): @@ -17,8 +16,6 @@ class CollectFusionRenders(pyblish.api.InstancePlugin): families = ["render"] def process(self, instance): - self.log.debug(pformat(instance.data)) - render_target = instance.data["render_target"] family = instance.data["family"] @@ -26,5 +23,3 @@ def process(self, instance): instance.data["families"].append( "{}.{}".format(family, render_target) ) - - self.log.debug(pformat(instance.data)) From f2e782368fe5a135c1d01f4ee6a85fe8840e0f94 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Sat, 18 Mar 2023 19:30:13 +0100 Subject: [PATCH 540/898] Changed to dot notation for clearer code --- ...nce.py => validate_expected_frames_existence.py} | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) rename openpype/hosts/fusion/plugins/publish/{validate_existing_frames_existence.py => validate_expected_frames_existence.py} (87%) diff --git a/openpype/hosts/fusion/plugins/publish/validate_existing_frames_existence.py b/openpype/hosts/fusion/plugins/publish/validate_expected_frames_existence.py similarity index 87% rename from openpype/hosts/fusion/plugins/publish/validate_existing_frames_existence.py rename to openpype/hosts/fusion/plugins/publish/validate_expected_frames_existence.py index a43d2c691ad..e74eb82366b 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_existing_frames_existence.py +++ b/openpype/hosts/fusion/plugins/publish/validate_expected_frames_existence.py @@ -9,11 +9,11 @@ class ValidateLocalFramesExistence(pyblish.api.InstancePlugin): """Checks if files for savers that's set - to publish existing frames exists + to publish expected frames exists """ order = pyblish.api.ValidatorOrder - label = "Validate Existing Frames Exists" + label = "Validate Expected Frames Exists" families = ["render"] hosts = ["fusion"] actions = [RepairAction, SelectInvalidAction] @@ -71,13 +71,12 @@ def process(self, instance): def repair(cls, instance): invalid = cls.get_invalid(instance) if invalid: - data = invalid[0].GetData("openpype") + tool = invalid[0] # Change render target to local to render locally - data["creator_attributes"]["render_target"] = "local" + tool.SetData("openpype.creator_attributes.render_target", "local") - invalid[0].SetData("openpype", data) - cls.log.error( - f"Reload the publisher and {invalid[0].Name} " + cls.log.info( + f"Reload the publisher and {tool.Name} " "will be set to render locally" ) From 0401f40ac941b0fba6f31c954aeb98da380d6301 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Sat, 18 Mar 2023 19:50:11 +0100 Subject: [PATCH 541/898] Collect frames in expected_frames instead of in redner_local --- .../publish/collect_expected_frames.py | 7 +++- .../plugins/publish/extract_render_local.py | 39 +------------------ 2 files changed, 6 insertions(+), 40 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/collect_expected_frames.py b/openpype/hosts/fusion/plugins/publish/collect_expected_frames.py index 485ca0c9a48..0ba777629fa 100644 --- a/openpype/hosts/fusion/plugins/publish/collect_expected_frames.py +++ b/openpype/hosts/fusion/plugins/publish/collect_expected_frames.py @@ -1,14 +1,17 @@ import pyblish.api +from openpype.pipeline import publish import os -class CollectFusionExpectedFrames(pyblish.api.InstancePlugin): +class CollectFusionExpectedFrames( + pyblish.api.InstancePlugin, publish.ColormanagedPyblishPluginMixin +): """Collect all frames needed to publish expected frames""" order = pyblish.api.CollectorOrder + 0.5 label = "Collect Expected Frames" hosts = ["fusion"] - families = ["render.frames"] + families = ["render"] def process(self, instance): context = instance.context diff --git a/openpype/hosts/fusion/plugins/publish/extract_render_local.py b/openpype/hosts/fusion/plugins/publish/extract_render_local.py index ea801107c18..673c5a3ce30 100644 --- a/openpype/hosts/fusion/plugins/publish/extract_render_local.py +++ b/openpype/hosts/fusion/plugins/publish/extract_render_local.py @@ -4,9 +4,7 @@ from openpype.hosts.fusion.api import comp_lock_and_undo_chunk -class FusionRenderLocal( - pyblish.api.InstancePlugin, publish.ColormanagedPyblishPluginMixin -): +class FusionRenderLocal(pyblish.api.InstancePlugin): """Render the current Fusion composition locally.""" order = pyblish.api.ExtractorOrder - 0.2 @@ -29,41 +27,6 @@ def process(self, instance): ) ) - # Generate the frame list - frame_start = context.data["frameStartHandle"] - frame_end = context.data["frameEndHandle"] - path = instance.data["path"] - output_dir = instance.data["outputDir"] - - basename = os.path.basename(path) - head, ext = os.path.splitext(basename) - files = [ - f"{head}{str(frame).zfill(4)}{ext}" - for frame in range(frame_start, frame_end + 1) - ] - repre = { - "name": ext[1:], - "ext": ext[1:], - "frameStart": f"%0{len(str(frame_end))}d" % frame_start, - "files": files, - "stagingDir": output_dir, - } - - # Get the colorspace represenation - self.set_representation_colorspace( - representation=repre, - context=context, - ) - - # review representation - if instance.data.get("review", False): - repre["tags"] = ["review"] - - # add the repre to the instance - if "representations" not in instance.data: - instance.data["representations"] = [] - instance.data["representations"].append(repre) - def render_once(self, context): """Render context comp only once, even with more render instances""" From 519cd3050888478202e7e2328fb3894ca5a7ab0a Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Sat, 18 Mar 2023 19:50:49 +0100 Subject: [PATCH 542/898] Removed code that should never be able to happen --- .../fusion/plugins/publish/validate_create_folder_checked.py | 4 ---- .../plugins/publish/validate_expected_frames_existence.py | 4 ---- 2 files changed, 8 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py b/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py index 53dea2af712..8a91f23578c 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py +++ b/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py @@ -21,10 +21,6 @@ class ValidateCreateFolderChecked(pyblish.api.InstancePlugin): @classmethod def get_invalid(cls, instance): - active = instance.data.get("active", instance.data.get("publish")) - if not active: - return [] - tool = instance[0] create_dir = tool.GetInput("CreateDir") if create_dir == 0.0: diff --git a/openpype/hosts/fusion/plugins/publish/validate_expected_frames_existence.py b/openpype/hosts/fusion/plugins/publish/validate_expected_frames_existence.py index e74eb82366b..c208b8ef159 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_expected_frames_existence.py +++ b/openpype/hosts/fusion/plugins/publish/validate_expected_frames_existence.py @@ -23,10 +23,6 @@ def get_invalid(cls, instance, non_existing_frames=None): if non_existing_frames is None: non_existing_frames = [] - active = instance.data.get("active", instance.data.get("publish")) - if not active: - return [] - if instance.data.get("render_target") == "frames": tool = instance[0] From 5ebca028eede5a0545b5f41e3f685b922ccc0f58 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 19 Mar 2023 13:25:22 +0100 Subject: [PATCH 543/898] Remove `FramesPerTask` as Deadline job info submission - `FramesPerTask` does not exist and should be `ChunkSize` which is also set. --- openpype/modules/deadline/plugins/publish/submit_max_deadline.py | 1 - .../modules/deadline/plugins/publish/submit_maya_deadline.py | 1 - 2 files changed, 2 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index 417a03de744..392e36b08e9 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -74,7 +74,6 @@ def get_job_info(self): job_info.ChunkSize = instance.data.get("chunkSize", 1) job_info.Comment = context.data.get("comment") job_info.Priority = instance.data.get("priority", self.priority) - job_info.FramesPerTask = instance.data.get("framesPerTask", 1) if self.group: job_info.Group = self.group diff --git a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py index 062732c059e..6884db4dc97 100644 --- a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py @@ -145,7 +145,6 @@ def get_job_info(self): job_info.ChunkSize = instance.data.get("chunkSize", 10) job_info.Comment = context.data.get("comment") job_info.Priority = instance.data.get("priority", self.priority) - job_info.FramesPerTask = instance.data.get("framesPerTask", 1) if self.group != "none" and self.group: job_info.Group = self.group From 0cd7ddcef423003c1e40f29a88e6943c61ef7cdf Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 19 Mar 2023 13:26:57 +0100 Subject: [PATCH 544/898] Remove setting of `ChunkSize` from instance data since CollectRender actually applies it through "renderGlobals" --- .../modules/deadline/plugins/publish/submit_maya_deadline.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py index 6884db4dc97..19d4f170b60 100644 --- a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py @@ -142,7 +142,6 @@ def get_job_info(self): job_info.Pool = instance.data.get("primaryPool") job_info.SecondaryPool = instance.data.get("secondaryPool") - job_info.ChunkSize = instance.data.get("chunkSize", 10) job_info.Comment = context.data.get("comment") job_info.Priority = instance.data.get("priority", self.priority) From f38bb352444caf23a624fffe26614161abb75a73 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Mon, 20 Mar 2023 09:20:52 +0000 Subject: [PATCH 545/898] Update openpype/hosts/maya/plugins/publish/extract_gpu_cache.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fabià Serra Arrizabalaga --- openpype/hosts/maya/plugins/publish/extract_gpu_cache.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py index 91efab38edf..965122822c5 100644 --- a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py +++ b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py @@ -6,7 +6,7 @@ class ExtractGPUCache(publish.Extractor): - """Extract the content of the instance to an CPU cache file.""" + """Extract the content of the instance to a GPU cache file.""" label = "GPU Cache" hosts = ["maya"] From d24c4e03dd41faa775efdc57b31b3cc3132f10b8 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 20 Mar 2023 17:56:50 +0800 Subject: [PATCH 546/898] 3dsmax: render instance settings in creator --- .../hosts/max/plugins/create/create_render.py | 50 +++++++++++++++++++ .../max/plugins/publish/collect_render.py | 11 +++- .../deadline/plugins/publish/collect_pools.py | 2 +- .../plugins/publish/submit_max_deadline.py | 13 +++-- 4 files changed, 66 insertions(+), 10 deletions(-) diff --git a/openpype/hosts/max/plugins/create/create_render.py b/openpype/hosts/max/plugins/create/create_render.py index 269fff2e32c..31e3ddcb090 100644 --- a/openpype/hosts/max/plugins/create/create_render.py +++ b/openpype/hosts/max/plugins/create/create_render.py @@ -1,8 +1,22 @@ # -*- coding: utf-8 -*- """Creator plugin for creating camera.""" from openpype.hosts.max.api import plugin +from openpype.lib import ( + TextDef, + BoolDef, + NumberDef, +) from openpype.pipeline import CreatedInstance from openpype.hosts.max.api.lib_rendersettings import RenderSettings +from openpype.settings import get_project_settings +from openpype.pipeline import legacy_io + + +def setting(project_setting=None): + render_setting = get_project_settings( + legacy_io.Session["AVALON_PROJECT"] + ) + return render_setting["deadline"]["publish"]["MaxSubmitDeadline"] class CreateRender(plugin.MaxCreator): @@ -31,3 +45,39 @@ def create(self, subset_name, instance_data, pre_create_data): RenderSettings().set_render_camera(sel_obj) # set output paths for rendering(mandatory for deadline) RenderSettings().render_output(container_name) + + def get_instance_attr_defs(self): + return [ + BoolDef("use_published", + default=setting()["active"], + label="Use Published Scene"), + + NumberDef("priority", + minimum=1, + maximum=250, + decimals=0, + default=setting()["priority"], + label="Priority"), + + NumberDef("chunkSize", + minimum=1, + maximum=50, + decimals=0, + default=setting()["chunk_size"], + label="Chunk Size"), + + TextDef("group", + default=setting()["group"], + label="Group Name"), + + TextDef("deadline_pool", + default=setting()["deadline_pool"], + label="Deadline Pool"), + + TextDef("deadline_pool_secondary", + default=setting()["deadline_pool_secondary"], + label="Deadline Pool Secondary") + ] + + def get_pre_create_attr_defs(self): + return self.get_instance_attr_defs() diff --git a/openpype/hosts/max/plugins/publish/collect_render.py b/openpype/hosts/max/plugins/publish/collect_render.py index 7c9e311c2fb..357135750f7 100644 --- a/openpype/hosts/max/plugins/publish/collect_render.py +++ b/openpype/hosts/max/plugins/publish/collect_render.py @@ -47,11 +47,13 @@ def process(self, instance): self.log.debug(f"Setting {version_int} to context.") context.data["version"] = version_int + creator_attr = instance.data["creator_attributes"] + # setup the plugin as 3dsmax for the internal renderer data = { "subset": instance.name, "asset": asset, - "publish": True, + "publish": creator_attr["use_published"], "maxversion": str(get_max_version()), "imageFormat": img_format, "family": 'maxrender', @@ -61,7 +63,12 @@ def process(self, instance): "plugin": "3dsmax", "frameStart": context.data['frameStart'], "frameEnd": context.data['frameEnd'], - "version": version_int + "version": version_int, + "priority": creator_attr["priority"], + "chunkSize": creator_attr["chunkSize"], + "group": creator_attr["group"], + "primaryPool": creator_attr["deadline_pool"], + "secondaryPool": creator_attr["deadline_pool_secondary"] } self.log.info("data: {0}".format(data)) instance.data.update(data) diff --git a/openpype/modules/deadline/plugins/publish/collect_pools.py b/openpype/modules/deadline/plugins/publish/collect_pools.py index 48130848d51..c9b4f485d81 100644 --- a/openpype/modules/deadline/plugins/publish/collect_pools.py +++ b/openpype/modules/deadline/plugins/publish/collect_pools.py @@ -10,7 +10,7 @@ class CollectDeadlinePools(pyblish.api.InstancePlugin): order = pyblish.api.CollectorOrder + 0.420 label = "Collect Deadline Pools" - families = ["rendering", "render.farm", "renderFarm", "renderlayer"] + families = ["rendering", "render.farm", "renderFarm", "renderlayer", "maxrender"] primary_pool = None secondary_pool = None diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index 417a03de744..6d62dd7f334 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -21,7 +21,7 @@ class MaxPluginInfo(object): SaveFile = attr.ib(default=True) IgnoreInputs = attr.ib(default=True) - +#TODO: add the optional attirbute class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline): label = "Submit Render to Deadline" @@ -49,11 +49,13 @@ def get_job_info(self): instance = self._instance context = instance.context - # Always use the original work file name for the Job name even when # rendering is done from the published Work File. The original work # file name is clearer because it can also have subversion strings, # etc. which are stripped for the published file. + if not instance.data.get("publish"): + self.use_published = False + src_filepath = context.data["currentFile"] src_filename = os.path.basename(src_filepath) @@ -71,13 +73,10 @@ def get_job_info(self): job_info.Pool = instance.data.get("primaryPool") job_info.SecondaryPool = instance.data.get("secondaryPool") - job_info.ChunkSize = instance.data.get("chunkSize", 1) + job_info.ChunkSize = instance.data.get("chunkSize", self.chunk_size) job_info.Comment = context.data.get("comment") job_info.Priority = instance.data.get("priority", self.priority) - job_info.FramesPerTask = instance.data.get("framesPerTask", 1) - - if self.group: - job_info.Group = self.group + job_info.Group = instance.data.get("group", self.group) # Add options from RenderGlobals render_globals = instance.data.get("renderGlobals", {}) From f1c490b21cf69294b7c1ab7e03a8115557c552de Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 20 Mar 2023 10:57:16 +0100 Subject: [PATCH 547/898] Fix `get_all_asset_nodes` --- openpype/hosts/maya/tools/mayalookassigner/commands.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/openpype/hosts/maya/tools/mayalookassigner/commands.py b/openpype/hosts/maya/tools/mayalookassigner/commands.py index 0135eb4f49b..3d9746511d9 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/commands.py +++ b/openpype/hosts/maya/tools/mayalookassigner/commands.py @@ -80,9 +80,7 @@ def get_all_asset_nodes(): Returns: list: list of dictionaries """ - nodes = cmds.ls(dag=True, noIntermediate=True, long=True) - items = create_items_from_nodes(nodes) - return items + return cmds.ls(dag=True, noIntermediate=True, long=True) def create_asset_id_hash(nodes): From fff1e3f0c1b257d03170fd665ccd09636fc611ad Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 20 Mar 2023 18:08:51 +0800 Subject: [PATCH 548/898] cosmetic fix and add optional for 3dsmax deadline submission --- .../deadline/plugins/publish/collect_pools.py | 6 +++++- .../deadline/plugins/publish/submit_max_deadline.py | 12 +++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/collect_pools.py b/openpype/modules/deadline/plugins/publish/collect_pools.py index c9b4f485d81..3a424f9e743 100644 --- a/openpype/modules/deadline/plugins/publish/collect_pools.py +++ b/openpype/modules/deadline/plugins/publish/collect_pools.py @@ -10,7 +10,11 @@ class CollectDeadlinePools(pyblish.api.InstancePlugin): order = pyblish.api.CollectorOrder + 0.420 label = "Collect Deadline Pools" - families = ["rendering", "render.farm", "renderFarm", "renderlayer", "maxrender"] + families = ["rendering", + "render.farm", + "renderFarm", + "renderlayer", + "maxrender"] primary_pool = None secondary_pool = None diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index 6d62dd7f334..1f1a59a8e68 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -3,7 +3,10 @@ import copy import attr -from openpype.pipeline import legacy_io +from openpype.pipeline import ( + legacy_io, + OptionalPyblishPluginMixin +) from openpype.settings import get_project_settings from openpype.hosts.max.api.lib import ( get_current_renderer, @@ -21,8 +24,8 @@ class MaxPluginInfo(object): SaveFile = attr.ib(default=True) IgnoreInputs = attr.ib(default=True) -#TODO: add the optional attirbute -class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline): +class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, + OptionalPyblishPluginMixin): label = "Submit Render to Deadline" hosts = ["max"] @@ -39,6 +42,7 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline): deadline_pool = None deadline_pool_secondary = None framePerTask = 1 + optional = True def get_job_info(self): job_info = DeadlineJobInfo(Plugin="3dsmax") @@ -49,6 +53,8 @@ def get_job_info(self): instance = self._instance context = instance.context + if not self.is_active(instance.data): + return # Always use the original work file name for the Job name even when # rendering is done from the published Work File. The original work # file name is clearer because it can also have subversion strings, From 7baa5754e05d6f30794cb265245f8d55a68a0c37 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 20 Mar 2023 18:09:39 +0800 Subject: [PATCH 549/898] cosmetic issue fix --- openpype/modules/deadline/plugins/publish/submit_max_deadline.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index 1f1a59a8e68..d04c4b9c09f 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -24,6 +24,7 @@ class MaxPluginInfo(object): SaveFile = attr.ib(default=True) IgnoreInputs = attr.ib(default=True) + class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, OptionalPyblishPluginMixin): From 507941c20898a9cf524851189a10176263543116 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 20 Mar 2023 18:36:36 +0800 Subject: [PATCH 550/898] use apply_settings --- .../hosts/max/plugins/create/create_render.py | 32 ++++++++++--------- .../plugins/publish/submit_max_deadline.py | 4 +-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/openpype/hosts/max/plugins/create/create_render.py b/openpype/hosts/max/plugins/create/create_render.py index 31e3ddcb090..dc1605bb5eb 100644 --- a/openpype/hosts/max/plugins/create/create_render.py +++ b/openpype/hosts/max/plugins/create/create_render.py @@ -8,15 +8,6 @@ ) from openpype.pipeline import CreatedInstance from openpype.hosts.max.api.lib_rendersettings import RenderSettings -from openpype.settings import get_project_settings -from openpype.pipeline import legacy_io - - -def setting(project_setting=None): - render_setting = get_project_settings( - legacy_io.Session["AVALON_PROJECT"] - ) - return render_setting["deadline"]["publish"]["MaxSubmitDeadline"] class CreateRender(plugin.MaxCreator): @@ -25,6 +16,17 @@ class CreateRender(plugin.MaxCreator): family = "maxrender" icon = "gear" + def apply_settings(self, project_settings, system_settings): + plugin_settings = ( + project_settings["deadline"]["publish"]["MaxSubmitDeadline"] + ) + self.use_published = plugin_settings["use_published"] + self.priority = plugin_settings["priority"] + self.chunkSize = plugin_settings["chunk_size"] + self.group = plugin_settings["group"] + self.deadline_pool = plugin_settings["deadline_pool"] + self.deadline_pool_secondary = plugin_settings["deadline_pool_secondary"] + def create(self, subset_name, instance_data, pre_create_data): from pymxs import runtime as rt sel_obj = list(rt.selection) @@ -49,33 +51,33 @@ def create(self, subset_name, instance_data, pre_create_data): def get_instance_attr_defs(self): return [ BoolDef("use_published", - default=setting()["active"], + default=self.use_published, label="Use Published Scene"), NumberDef("priority", minimum=1, maximum=250, decimals=0, - default=setting()["priority"], + default=self.priority, label="Priority"), NumberDef("chunkSize", minimum=1, maximum=50, decimals=0, - default=setting()["chunk_size"], + default=self.chunkSize, label="Chunk Size"), TextDef("group", - default=setting()["group"], + default=self.group, label="Group Name"), TextDef("deadline_pool", - default=setting()["deadline_pool"], + default=self.deadline_pool, label="Deadline Pool"), TextDef("deadline_pool_secondary", - default=setting()["deadline_pool_secondary"], + default=self.deadline_pool_secondary, label="Deadline Pool Secondary") ] diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index d04c4b9c09f..92e06ca7659 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -60,8 +60,6 @@ def get_job_info(self): # rendering is done from the published Work File. The original work # file name is clearer because it can also have subversion strings, # etc. which are stripped for the published file. - if not instance.data.get("publish"): - self.use_published = False src_filepath = context.data["currentFile"] src_filename = os.path.basename(src_filepath) @@ -80,7 +78,7 @@ def get_job_info(self): job_info.Pool = instance.data.get("primaryPool") job_info.SecondaryPool = instance.data.get("secondaryPool") - job_info.ChunkSize = instance.data.get("chunkSize", self.chunk_size) + job_info.ChunkSize = instance.data.get("chunkSize", 1) job_info.Comment = context.data.get("comment") job_info.Priority = instance.data.get("priority", self.priority) job_info.Group = instance.data.get("group", self.group) From e00ef8210c9fb592bf9ee84c5c8e56df785a2845 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 20 Mar 2023 18:37:58 +0800 Subject: [PATCH 551/898] cosmetic issue fix --- openpype/hosts/max/plugins/create/create_render.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/max/plugins/create/create_render.py b/openpype/hosts/max/plugins/create/create_render.py index dc1605bb5eb..a24c5ea000c 100644 --- a/openpype/hosts/max/plugins/create/create_render.py +++ b/openpype/hosts/max/plugins/create/create_render.py @@ -25,7 +25,7 @@ def apply_settings(self, project_settings, system_settings): self.chunkSize = plugin_settings["chunk_size"] self.group = plugin_settings["group"] self.deadline_pool = plugin_settings["deadline_pool"] - self.deadline_pool_secondary = plugin_settings["deadline_pool_secondary"] + self.pool_secondary = plugin_settings["deadline_pool_secondary"] def create(self, subset_name, instance_data, pre_create_data): from pymxs import runtime as rt @@ -77,7 +77,7 @@ def get_instance_attr_defs(self): label="Deadline Pool"), TextDef("deadline_pool_secondary", - default=self.deadline_pool_secondary, + default=self.pool_secondary, label="Deadline Pool Secondary") ] From 4506a2f3ef3e7fe7b7002d89266fdb8dfb6ce8da Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 20 Mar 2023 13:41:17 +0100 Subject: [PATCH 552/898] Fix broken Nuke local test Accidentally used DL version --- tests/integration/hosts/nuke/test_publish_in_nuke.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/integration/hosts/nuke/test_publish_in_nuke.py b/tests/integration/hosts/nuke/test_publish_in_nuke.py index a4026f195b0..bfd84e4fd57 100644 --- a/tests/integration/hosts/nuke/test_publish_in_nuke.py +++ b/tests/integration/hosts/nuke/test_publish_in_nuke.py @@ -1,12 +1,12 @@ import logging from tests.lib.assert_classes import DBAssert -from tests.integration.hosts.nuke.lib import NukeDeadlinePublishTestClass +from tests.integration.hosts.nuke.lib import NukeLocalPublishTestClass log = logging.getLogger("test_publish_in_nuke") -class TestDeadlinePublishInNuke(NukeDeadlinePublishTestClass): +class TestPublishInNuke(NukeLocalPublishTestClass): """Basic test case for publishing in Nuke Uses generic TestCase to prepare fixtures for test data, testing DBs, @@ -36,13 +36,12 @@ class TestDeadlinePublishInNuke(NukeDeadlinePublishTestClass): """ # https://drive.google.com/file/d/1SUurHj2aiQ21ZIMJfGVBI2KjR8kIjBGI/view?usp=sharing # noqa: E501 TEST_FILES = [ - ("1SeWprClKhWMv2xVC9AcnekIJFExxnp_b", - "test_nuke_deadline_publish.zip", "") + ("1SUurHj2aiQ21ZIMJfGVBI2KjR8kIjBGI", "test_Nuke_publish.zip", "") ] APP_GROUP = "nuke" - TIMEOUT = 180 # publish timeout + TIMEOUT = 50 # publish timeout # could be overwritten by command line arguments # keep empty to locate latest installed variant or explicit @@ -99,4 +98,4 @@ def test_db_asserts(self, dbcon, publish_finished): if __name__ == "__main__": - test_case = TestDeadlinePublishInNuke() + test_case = TestPublishInNuke() From 36db7faab4c763ed58d9ac3a124a54c9ecac5e9b Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 20 Mar 2023 23:51:49 +0800 Subject: [PATCH 553/898] only allows user to set up the attributes in publish tab --- .../hosts/max/plugins/create/create_render.py | 52 ----------- .../max/plugins/publish/collect_render.py | 9 +- .../plugins/publish/submit_max_deadline.py | 86 ++++++++++++++++--- 3 files changed, 77 insertions(+), 70 deletions(-) diff --git a/openpype/hosts/max/plugins/create/create_render.py b/openpype/hosts/max/plugins/create/create_render.py index a24c5ea000c..269fff2e32c 100644 --- a/openpype/hosts/max/plugins/create/create_render.py +++ b/openpype/hosts/max/plugins/create/create_render.py @@ -1,11 +1,6 @@ # -*- coding: utf-8 -*- """Creator plugin for creating camera.""" from openpype.hosts.max.api import plugin -from openpype.lib import ( - TextDef, - BoolDef, - NumberDef, -) from openpype.pipeline import CreatedInstance from openpype.hosts.max.api.lib_rendersettings import RenderSettings @@ -16,17 +11,6 @@ class CreateRender(plugin.MaxCreator): family = "maxrender" icon = "gear" - def apply_settings(self, project_settings, system_settings): - plugin_settings = ( - project_settings["deadline"]["publish"]["MaxSubmitDeadline"] - ) - self.use_published = plugin_settings["use_published"] - self.priority = plugin_settings["priority"] - self.chunkSize = plugin_settings["chunk_size"] - self.group = plugin_settings["group"] - self.deadline_pool = plugin_settings["deadline_pool"] - self.pool_secondary = plugin_settings["deadline_pool_secondary"] - def create(self, subset_name, instance_data, pre_create_data): from pymxs import runtime as rt sel_obj = list(rt.selection) @@ -47,39 +31,3 @@ def create(self, subset_name, instance_data, pre_create_data): RenderSettings().set_render_camera(sel_obj) # set output paths for rendering(mandatory for deadline) RenderSettings().render_output(container_name) - - def get_instance_attr_defs(self): - return [ - BoolDef("use_published", - default=self.use_published, - label="Use Published Scene"), - - NumberDef("priority", - minimum=1, - maximum=250, - decimals=0, - default=self.priority, - label="Priority"), - - NumberDef("chunkSize", - minimum=1, - maximum=50, - decimals=0, - default=self.chunkSize, - label="Chunk Size"), - - TextDef("group", - default=self.group, - label="Group Name"), - - TextDef("deadline_pool", - default=self.deadline_pool, - label="Deadline Pool"), - - TextDef("deadline_pool_secondary", - default=self.pool_secondary, - label="Deadline Pool Secondary") - ] - - def get_pre_create_attr_defs(self): - return self.get_instance_attr_defs() diff --git a/openpype/hosts/max/plugins/publish/collect_render.py b/openpype/hosts/max/plugins/publish/collect_render.py index 357135750f7..63e4108c849 100644 --- a/openpype/hosts/max/plugins/publish/collect_render.py +++ b/openpype/hosts/max/plugins/publish/collect_render.py @@ -47,13 +47,11 @@ def process(self, instance): self.log.debug(f"Setting {version_int} to context.") context.data["version"] = version_int - creator_attr = instance.data["creator_attributes"] - # setup the plugin as 3dsmax for the internal renderer data = { "subset": instance.name, "asset": asset, - "publish": creator_attr["use_published"], + "publish": True, "maxversion": str(get_max_version()), "imageFormat": img_format, "family": 'maxrender', @@ -64,11 +62,6 @@ def process(self, instance): "frameStart": context.data['frameStart'], "frameEnd": context.data['frameEnd'], "version": version_int, - "priority": creator_attr["priority"], - "chunkSize": creator_attr["chunkSize"], - "group": creator_attr["group"], - "primaryPool": creator_attr["deadline_pool"], - "secondaryPool": creator_attr["deadline_pool_secondary"] } self.log.info("data: {0}".format(data)) instance.data.update(data) diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index 92e06ca7659..83ecdfd6af6 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -3,9 +3,14 @@ import copy import attr +from openpype.lib import ( + TextDef, + BoolDef, + NumberDef, +) from openpype.pipeline import ( legacy_io, - OptionalPyblishPluginMixin + OpenPypePyblishPluginMixin ) from openpype.settings import get_project_settings from openpype.hosts.max.api.lib import ( @@ -26,7 +31,7 @@ class MaxPluginInfo(object): class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, - OptionalPyblishPluginMixin): + OpenPypePyblishPluginMixin): label = "Submit Render to Deadline" hosts = ["max"] @@ -36,7 +41,7 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, use_published = True priority = 50 tile_priority = 50 - chunk_size = 1 + chunkSize = 1 jobInfo = {} pluginInfo = {} group = None @@ -45,6 +50,22 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, framePerTask = 1 optional = True + @classmethod + def apply_settings(cls, project_settings, system_settings): + settings = project_settings["deadline"]["publish"]["MaxSubmitDeadline"] # noqa + + # Take some defaults from settings + cls.use_published = settings.get("use_published", + cls.use_published) + cls.priority = settings.get("priority", + cls.priority) + cls.chunkSize = settings.get("chunk_size", cls.chunkSize) + cls.group = settings.get("group", cls.group) + cls.deadline_pool = settings.get("deadline_pool", + cls.deadline_pool) + cls.deadline_pool_secondary = settings.get("deadline_pool_secondary", + cls.deadline_pool_secondary) + def get_job_info(self): job_info = DeadlineJobInfo(Plugin="3dsmax") @@ -54,8 +75,6 @@ def get_job_info(self): instance = self._instance context = instance.context - if not self.is_active(instance.data): - return # Always use the original work file name for the Job name even when # rendering is done from the published Work File. The original work # file name is clearer because it can also have subversion strings, @@ -76,12 +95,22 @@ def get_job_info(self): ) job_info.Frames = frames - job_info.Pool = instance.data.get("primaryPool") - job_info.SecondaryPool = instance.data.get("secondaryPool") - job_info.ChunkSize = instance.data.get("chunkSize", 1) + attr_values = self.get_attr_values_from_data(instance.data) + + if attr_values.get("deadline_pool"): + job_info.Pool = attr_values.get("deadline_pool") + else: + job_info.Pool = instance.data.get("primaryPool") + if attr_values.get("deadline_pool_secondary"): + job_info.SecondaryPool = attr_values.get("deadline_pool_secondary") + else: + job_info.SecondaryPool = instance.data.get("secondaryPool", + self.deadline_pool_secondary) + + job_info.ChunkSize = attr_values.get("chunkSize", 1) job_info.Comment = context.data.get("comment") - job_info.Priority = instance.data.get("priority", self.priority) - job_info.Group = instance.data.get("group", self.group) + job_info.Priority = attr_values.get("priority", self.priority) + job_info.Group = attr_values.get("group", self.group) # Add options from RenderGlobals render_globals = instance.data.get("renderGlobals", {}) @@ -220,3 +249,40 @@ def _clean_name(path): plugin_info.update(plugin_data) return job_info, plugin_info + + @classmethod + def get_attribute_defs(cls): + defs = super(MaxSubmitDeadline, cls).get_attribute_defs() + defs.extend([ + BoolDef("use_published", + default=cls.use_published, + label="Use Published Scene"), + + NumberDef("priority", + minimum=1, + maximum=250, + decimals=0, + default=cls.priority, + label="Priority"), + + NumberDef("chunkSize", + minimum=1, + maximum=50, + decimals=0, + default=cls.chunkSize, + label="Frame Per Task"), + + TextDef("group", + default=cls.group, + label="Group Name"), + + TextDef("deadline_pool", + default=cls.deadline_pool, + label="Deadline Pool"), + + TextDef("deadline_pool_secondary", + default=cls.deadline_pool_secondary, + label="Deadline Pool Secondary") + ]) + + return defs From fb6bc696f8a5f94b54689c2d4e6c390f8058220c Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 20 Mar 2023 23:54:16 +0800 Subject: [PATCH 554/898] cosmetic issue fix --- .../modules/deadline/plugins/publish/submit_max_deadline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index 83ecdfd6af6..478c2ce2de0 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -105,7 +105,7 @@ def get_job_info(self): job_info.SecondaryPool = attr_values.get("deadline_pool_secondary") else: job_info.SecondaryPool = instance.data.get("secondaryPool", - self.deadline_pool_secondary) + self.deadline_pool_secondary) # noqa job_info.ChunkSize = attr_values.get("chunkSize", 1) job_info.Comment = context.data.get("comment") From 81c6b91633de5b9973ac70a8b515636a5b532a17 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Mon, 20 Mar 2023 17:24:03 +0000 Subject: [PATCH 555/898] Update openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py Co-authored-by: Roy Nieterau --- .../maya/plugins/publish/extract_arnold_scene_source.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index 63e6ff0f367..f7d059cdb68 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -139,9 +139,11 @@ def _extract(self, nodes, attribute_data, kwargs): parent, duplicate_transform ) - duplicate_transform = cmds.parent( - duplicate_transform, world=True - )[0] + + if cmds.listRelatives(duplicate_transform, parent=True): + duplicate_transform = cmds.parent( + duplicate_transform, world=True + )[0] basename = node.split("|")[-1].split(":")[-1] duplicate_transform = cmds.rename( From b22fbf58dc4d93a21c98507bfe9fb2a60a5b8a75 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Mon, 20 Mar 2023 17:34:13 +0000 Subject: [PATCH 556/898] Update openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py Co-authored-by: Roy Nieterau --- .../hosts/maya/plugins/publish/extract_arnold_scene_source.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index f7d059cdb68..225b8dbb280 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -150,7 +150,7 @@ def _extract(self, nodes, attribute_data, kwargs): duplicate_transform, basename ) - # Discard the children. + # Discard children nodes that are not shapes shapes = cmds.listRelatives( duplicate_transform, shapes=True, fullPath=True ) From c2c963c703900e5587828cb756e83a28da940ed9 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Mon, 20 Mar 2023 17:49:26 +0000 Subject: [PATCH 557/898] Improve same named nodes error message. --- .../publish/validate_arnold_scene_source.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py index d09a8610c46..a0e2e84a001 100644 --- a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py @@ -24,7 +24,7 @@ def _get_nodes_data(self, nodes): ungrouped_nodes = [] nodes_by_name = {} parents = [] - same_named_nodes = [] + same_named_nodes = {} for node in nodes: node_split = node.split("|") if len(node_split) == 2: @@ -39,16 +39,21 @@ def _get_nodes_data(self, nodes): # Check for same same nodes, which can happen in different # hierarchies. if node_name in nodes_by_name: - same_named_nodes.append((node, nodes_by_name[node_name])) + try: + same_named_nodes[node_name].append(node) + except KeyError: + same_named_nodes[node_name] = [ + nodes_by_name[node_name], node + ] nodes_by_name[node_name] = node if same_named_nodes: - raise PublishValidationError( - "Found nodes with the same name:\n{}".format( - "\n".join(["{}".format(n) for n in same_named_nodes]) - ) - ) + message = "Found nodes with the same name:" + for name, nodes in same_named_nodes.items(): + message += "\n\n\"{}\":\n{}".format(name, "\n".join(nodes)) + + raise PublishValidationError(message) return ungrouped_nodes, nodes_by_name, parents From 5511b479ab84fd5dbeba822f213fa1a117cd8c10 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Mon, 20 Mar 2023 17:50:40 +0000 Subject: [PATCH 558/898] _get_nodes_data > _get_nodes_by_name --- .../maya/plugins/publish/validate_arnold_scene_source.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py index a0e2e84a001..7055dc145ea 100644 --- a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py @@ -20,7 +20,7 @@ class ValidateArnoldSceneSource(pyblish.api.InstancePlugin): families = ["ass"] label = "Validate Arnold Scene Source" - def _get_nodes_data(self, nodes): + def _get_nodes_by_name(self, nodes): ungrouped_nodes = [] nodes_by_name = {} parents = [] @@ -60,12 +60,12 @@ def _get_nodes_data(self, nodes): def process(self, instance): ungrouped_nodes = [] - nodes, content_nodes_by_name, content_parents = self._get_nodes_data( - instance.data["contentMembers"] + nodes, content_nodes_by_name, content_parents = ( + self._get_nodes_by_name(instance.data["contentMembers"]) ) ungrouped_nodes.extend(nodes) - nodes, proxy_nodes_by_name, proxy_parents = self._get_nodes_data( + nodes, proxy_nodes_by_name, proxy_parents = self._get_nodes_by_name( instance.data.get("proxy", []) ) ungrouped_nodes.extend(nodes) From cd5493edea38ddf4680c137b0a07ab6eca389b93 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Mon, 20 Mar 2023 17:54:15 +0000 Subject: [PATCH 559/898] _get_nodes_data > _get_nodes_by_name --- .../plugins/publish/validate_arnold_scene_source_cbid.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py index dafad2f40ae..6a4799f73f7 100644 --- a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py +++ b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py @@ -18,7 +18,7 @@ class ValidateArnoldSceneSourceCbid(pyblish.api.InstancePlugin): actions = [RepairAction] @staticmethod - def _get_nodes_data(nodes): + def _get_nodes_by_name(nodes): nodes_by_name = {} for node in nodes: node_name = node.rsplit("|", 1)[-1].rsplit(":", 1)[-1] @@ -27,10 +27,10 @@ def _get_nodes_data(nodes): return nodes_by_name def get_invalid_couples(self, instance): - content_nodes_by_name = self._get_nodes_data( + content_nodes_by_name = self._get_nodes_by_name( instance.data["contentMembers"] ) - proxy_nodes_by_name = self._get_nodes_data( + proxy_nodes_by_name = self._get_nodes_by_name( instance.data.get("proxy", []) ) From 12c85bc46cdd4e5621c3305a01e608ea9dc0e7a9 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Mon, 20 Mar 2023 17:55:09 +0000 Subject: [PATCH 560/898] Make get_invalid_couples class method --- .../plugins/publish/validate_arnold_scene_source_cbid.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py index 6a4799f73f7..e27723e1045 100644 --- a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py +++ b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py @@ -26,11 +26,12 @@ def _get_nodes_by_name(nodes): return nodes_by_name - def get_invalid_couples(self, instance): - content_nodes_by_name = self._get_nodes_by_name( + @classmethod + def get_invalid_couples(cls, instance): + content_nodes_by_name = cls._get_nodes_by_name( instance.data["contentMembers"] ) - proxy_nodes_by_name = self._get_nodes_by_name( + proxy_nodes_by_name = cls._get_nodes_by_name( instance.data.get("proxy", []) ) @@ -39,7 +40,7 @@ def get_invalid_couples(self, instance): proxy_node = proxy_nodes_by_name.get(content_name, None) if not proxy_node: - self.log.debug( + cls.log.debug( "Content node '{}' has no matching proxy node.".format( content_node ) From b7e87dc1e193c056750c65900b21fb8093da1da9 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Mon, 20 Mar 2023 18:04:32 +0000 Subject: [PATCH 561/898] Hound --- .../hosts/maya/plugins/publish/extract_arnold_scene_source.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index 225b8dbb280..8344f028940 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -139,7 +139,6 @@ def _extract(self, nodes, attribute_data, kwargs): parent, duplicate_transform ) - if cmds.listRelatives(duplicate_transform, parent=True): duplicate_transform = cmds.parent( duplicate_transform, world=True From 2af4c94e2ca6328328b49bed562c2a4106ba9c90 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 21 Mar 2023 15:43:45 +0800 Subject: [PATCH 562/898] move the pool settings into the pool collectors --- .../deadline/plugins/publish/collect_pools.py | 46 +++++++++++++++++-- .../plugins/publish/submit_max_deadline.py | 25 ++-------- .../publish/validate_deadline_pools.py | 6 ++- 3 files changed, 51 insertions(+), 26 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/collect_pools.py b/openpype/modules/deadline/plugins/publish/collect_pools.py index 3a424f9e743..eb84308e9d9 100644 --- a/openpype/modules/deadline/plugins/publish/collect_pools.py +++ b/openpype/modules/deadline/plugins/publish/collect_pools.py @@ -3,9 +3,12 @@ """ import pyblish.api +from openpype.lib import TextDef +from openpype.pipeline.publish import OpenPypePyblishPluginMixin -class CollectDeadlinePools(pyblish.api.InstancePlugin): +class CollectDeadlinePools(pyblish.api.InstancePlugin, + OpenPypePyblishPluginMixin): """Collect pools from instance if present, from Setting otherwise.""" order = pyblish.api.CollectorOrder + 0.420 @@ -19,9 +22,46 @@ class CollectDeadlinePools(pyblish.api.InstancePlugin): primary_pool = None secondary_pool = None + @classmethod + def apply_settings(cls, project_settings, system_settings): + # deadline.publish.CollectDeadlinePools + settings = project_settings["deadline"]["publish"]["CollectDeadlinePools"] # noqa + cls.primary_pool = settings.get("primary_pool", None) + cls.secondary_pool = settings.get("secondary_pool", None) + for family in cls.families: + if family == "maxrender": + max_setting = project_settings["deadline"]["publish"]["MaxSubmitDeadline"] # noqa + cls.primary_pool = max_setting.get("deadline_pool", None) + cls.secondary_pool = max_setting.get("deadline_pool_secondary", None) + def process(self, instance): + + attr_values = self.get_attr_values_from_data(instance.data) if not instance.data.get("primaryPool"): - instance.data["primaryPool"] = self.primary_pool or "none" + instance.data["primaryPool"] = ( + attr_values.get("primaryPool") or self.primary_pool or "none" + ) if not instance.data.get("secondaryPool"): - instance.data["secondaryPool"] = self.secondary_pool or "none" + instance.data["secondaryPool"] = ( + attr_values.get("secondaryPool") or self.secondary_pool or "none" # noqa + ) + + @classmethod + def get_attribute_defs(cls): + # TODO: Preferably this would be an enum for the user + # but the Deadline server URL can be dynamic and + # can be set per render instance. Since get_attribute_defs + # can't be dynamic unfortunately EnumDef isn't possible (yet?) + # pool_names = self.deadline_module.get_deadline_pools(deadline_url, + # self.log) + # secondary_pool_names = ["-"] + pool_names + + return [ + TextDef("primaryPool", + label="Primary Pool", + default=cls.primary_pool), + TextDef("secondaryPool", + label="Secondary Pool", + default=cls.secondary_pool) + ] diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index 478c2ce2de0..c55e85cfb00 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -61,10 +61,6 @@ def apply_settings(cls, project_settings, system_settings): cls.priority) cls.chunkSize = settings.get("chunk_size", cls.chunkSize) cls.group = settings.get("group", cls.group) - cls.deadline_pool = settings.get("deadline_pool", - cls.deadline_pool) - cls.deadline_pool_secondary = settings.get("deadline_pool_secondary", - cls.deadline_pool_secondary) def get_job_info(self): job_info = DeadlineJobInfo(Plugin="3dsmax") @@ -95,17 +91,10 @@ def get_job_info(self): ) job_info.Frames = frames - attr_values = self.get_attr_values_from_data(instance.data) + job_info.Pool = instance.data.get("primaryPool") + job_info.SecondaryPool = instance.data.get("secondaryPool") - if attr_values.get("deadline_pool"): - job_info.Pool = attr_values.get("deadline_pool") - else: - job_info.Pool = instance.data.get("primaryPool") - if attr_values.get("deadline_pool_secondary"): - job_info.SecondaryPool = attr_values.get("deadline_pool_secondary") - else: - job_info.SecondaryPool = instance.data.get("secondaryPool", - self.deadline_pool_secondary) # noqa + attr_values = self.get_attr_values_from_data(instance.data) job_info.ChunkSize = attr_values.get("chunkSize", 1) job_info.Comment = context.data.get("comment") @@ -275,14 +264,6 @@ def get_attribute_defs(cls): TextDef("group", default=cls.group, label="Group Name"), - - TextDef("deadline_pool", - default=cls.deadline_pool, - label="Deadline Pool"), - - TextDef("deadline_pool_secondary", - default=cls.deadline_pool_secondary, - label="Deadline Pool Secondary") ]) return defs diff --git a/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py b/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py index 78eed17c986..3c02c7933f2 100644 --- a/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py +++ b/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py @@ -17,7 +17,11 @@ class ValidateDeadlinePools(OptionalPyblishPluginMixin, label = "Validate Deadline Pools" order = pyblish.api.ValidatorOrder - families = ["rendering", "render.farm", "renderFarm", "renderlayer"] + families = ["rendering", + "render.farm", + "renderFarm", + "renderlayer", + "maxrender"] optional = True def process(self, instance): From c48fddbba33cdb290c6f86c34bc68bb25a943607 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 21 Mar 2023 15:45:01 +0800 Subject: [PATCH 563/898] cosmetic issue fix --- openpype/modules/deadline/plugins/publish/collect_pools.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/modules/deadline/plugins/publish/collect_pools.py b/openpype/modules/deadline/plugins/publish/collect_pools.py index eb84308e9d9..b2732d375f2 100644 --- a/openpype/modules/deadline/plugins/publish/collect_pools.py +++ b/openpype/modules/deadline/plugins/publish/collect_pools.py @@ -32,7 +32,8 @@ def apply_settings(cls, project_settings, system_settings): if family == "maxrender": max_setting = project_settings["deadline"]["publish"]["MaxSubmitDeadline"] # noqa cls.primary_pool = max_setting.get("deadline_pool", None) - cls.secondary_pool = max_setting.get("deadline_pool_secondary", None) + cls.secondary_pool = max_setting.get("deadline_pool_secondary", + None) def process(self, instance): From d8441216e4fa4c8b1b0b1ee2e58d1df4eb2b28a3 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 21 Mar 2023 15:55:07 +0800 Subject: [PATCH 564/898] move the pool settings into the pool collectors --- openpype/modules/deadline/plugins/publish/collect_pools.py | 6 ------ .../modules/deadline/plugins/publish/submit_max_deadline.py | 6 ++++-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/collect_pools.py b/openpype/modules/deadline/plugins/publish/collect_pools.py index b2732d375f2..e221eb00ea6 100644 --- a/openpype/modules/deadline/plugins/publish/collect_pools.py +++ b/openpype/modules/deadline/plugins/publish/collect_pools.py @@ -28,12 +28,6 @@ def apply_settings(cls, project_settings, system_settings): settings = project_settings["deadline"]["publish"]["CollectDeadlinePools"] # noqa cls.primary_pool = settings.get("primary_pool", None) cls.secondary_pool = settings.get("secondary_pool", None) - for family in cls.families: - if family == "maxrender": - max_setting = project_settings["deadline"]["publish"]["MaxSubmitDeadline"] # noqa - cls.primary_pool = max_setting.get("deadline_pool", None) - cls.secondary_pool = max_setting.get("deadline_pool_secondary", - None) def process(self, instance): diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index c55e85cfb00..e681346556f 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -91,8 +91,10 @@ def get_job_info(self): ) job_info.Frames = frames - job_info.Pool = instance.data.get("primaryPool") - job_info.SecondaryPool = instance.data.get("secondaryPool") + job_info.Pool = instance.data.get("primaryPool", + self.deadline_pool) + job_info.SecondaryPool = instance.data.get("secondaryPool", + self.deadline_pool_secondary) attr_values = self.get_attr_values_from_data(instance.data) From 6c1882236419d68934d6130242ffc9cf75c4eeba Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 21 Mar 2023 15:56:15 +0800 Subject: [PATCH 565/898] hound fix --- .../modules/deadline/plugins/publish/submit_max_deadline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index e681346556f..e99752b7aba 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -94,7 +94,7 @@ def get_job_info(self): job_info.Pool = instance.data.get("primaryPool", self.deadline_pool) job_info.SecondaryPool = instance.data.get("secondaryPool", - self.deadline_pool_secondary) + self.deadline_pool_secondary) # noqa attr_values = self.get_attr_values_from_data(instance.data) From 2246fa15abeae14607ada49e189bc88c3280f3f0 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 21 Mar 2023 07:56:19 +0000 Subject: [PATCH 566/898] Documentation for settings --- website/docs/admin_hosts_maya.md | 37 ++++++++++++++++--- website/docs/assets/maya-admin_gpu_cache.png | Bin 0 -> 20248 bytes 2 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 website/docs/assets/maya-admin_gpu_cache.png diff --git a/website/docs/admin_hosts_maya.md b/website/docs/admin_hosts_maya.md index ae0cf76f536..d38b9110623 100644 --- a/website/docs/admin_hosts_maya.md +++ b/website/docs/admin_hosts_maya.md @@ -6,7 +6,7 @@ sidebar_label: Maya ## Publish Plugins -### Render Settings Validator +### Render Settings Validator `ValidateRenderSettings` @@ -51,7 +51,7 @@ just one instance of this node type but if that is not so, validator will go thr instances and check the value there. Node type for **VRay** settings is `VRaySettingsNode`, for **Renderman** it is `rmanGlobals`, for **Redshift** it is `RedshiftOptions`. -### Model Name Validator +### Model Name Validator `ValidateRenderSettings` @@ -95,7 +95,7 @@ You can set various aspects of scene submission to farm with per-project setting - **Optional** will mark sumission plugin optional - **Active** will enable/disable plugin - - **Tile Assembler Plugin** will set what should be used to assemble tiles on Deadline. Either **Open Image IO** will be used + - **Tile Assembler Plugin** will set what should be used to assemble tiles on Deadline. Either **Open Image IO** will be used or Deadlines **Draft Tile Assembler**. - **Use Published scene** enable to render from published scene instead of scene in work area. Rendering from published files is much safer. - **Use Asset dependencies** will mark job pending on farm until asset dependencies are fulfilled - for example Deadline will wait for scene file to be synced to cloud, etc. @@ -107,6 +107,35 @@ or Deadlines **Draft Tile Assembler**. This is useful to fix some specific renderer glitches and advanced hacking of Maya Scene files. `Patch name` is label for patch for easier orientation. `Patch regex` is regex used to find line in file, after `Patch line` string is inserted. Note that you need to add line ending. +### Extract GPU Cache + +![Maya GPU Cache](assets/maya-admin_gpu_cache.png) + +- **Evaluate Every** Specifies which samples are saved during cache creation. For example, a value of 2 specifies that only every other sample specified by the Evaluate every # frame(s) option is saved to your Alembic file. + +- **Save Every** Specifies how often samples are taken during file creation. By default, one sample of your object's transformations is taken every frame and saved to the Alembic file. + + For example, a value of 2 caches the transformations of the current object at every other frame of the Cache Time Range. + +- **Optimize Hierarchy** When on, nodes and objects in a selected hierarchy are consolidated to maximize the performance of the cache file during playback. +- **Optimization Threshold** (Available only when Optimize Hierarchy is on.) Specifies the maximum number of vertices contained in a single draw primitive. The default value of 40000 may be ideal for most Maya supported graphics cards. When set to the default value, after optimization, each object in the GPU cache file(s) will have no more than 40000 vertices. This value can be set higher depending on the memory available on your system graphics card. + +- **Optimize Animations for Motion Blur** When on, objects with animated transform nodes display with motion blur when the cache is played back in Viewport 2.0 render mode. See Viewport 2.0 options. + + Maya first determines if the GPU cache includes animation data. If the GPU cache is static and does not contain animation data, Maya does not optimize the GPU cache for motion blur. + +:::note Motion Blur does not support Cached Playback. +::: + +- **Write Materials** When on, Maya exports the Lambert and Phong materials from source geometry to the GPU Cache file. These materials display when the GPU-cached file is played back in Viewport 2.0. + + GPU-cached objects support all the high-quality lighting and shading effects provide by the Viewport 2.0 rendering mode. See Viewport 2.0 options. + +:::note Lambert and Phong materials do not display on GPU-cached files when they are played back in scene view's High Quality Rendering or Default Quality Rendering modes. +::: + +- **Use Base Tessellation** Exports geometry with base tessellation and no smoothing applied. If this setting is turned off, the extractor will export geometry with the current Smooth Mesh Preview setting applied. + ## Custom Menu You can add your custom tools menu into Maya by extending definitions in **Maya -> Scripts Menu Definition**. ![Custom menu definition](assets/maya-admin_scriptsmenu.png) @@ -169,5 +198,3 @@ Fill in the necessary fields (the optional fields are regex filters) - Build your workfile ![maya build template](assets/maya-build_workfile_from_template.png) - - diff --git a/website/docs/assets/maya-admin_gpu_cache.png b/website/docs/assets/maya-admin_gpu_cache.png new file mode 100644 index 0000000000000000000000000000000000000000..8b07b06c1e26c91ce42a77b34182abd0c5db975e GIT binary patch literal 20248 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 Hr-UW|ar0GU literal 0 HcmV?d00001 From 6bdca1561bc14fd024f0d264887f4a2202fbcc79 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 21 Mar 2023 16:00:29 +0800 Subject: [PATCH 567/898] clean up the duplicate attributes for pool settings --- .../deadline/plugins/publish/submit_max_deadline.py | 8 ++------ .../settings/defaults/project_settings/deadline.json | 2 -- .../projects_schema/schema_project_deadline.json | 10 ---------- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index e99752b7aba..65d08b9ef44 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -45,8 +45,6 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, jobInfo = {} pluginInfo = {} group = None - deadline_pool = None - deadline_pool_secondary = None framePerTask = 1 optional = True @@ -91,10 +89,8 @@ def get_job_info(self): ) job_info.Frames = frames - job_info.Pool = instance.data.get("primaryPool", - self.deadline_pool) - job_info.SecondaryPool = instance.data.get("secondaryPool", - self.deadline_pool_secondary) # noqa + job_info.Pool = instance.data.get("primaryPool") + job_info.SecondaryPool = instance.data.get("secondaryPool") attr_values = self.get_attr_values_from_data(instance.data) diff --git a/openpype/settings/defaults/project_settings/deadline.json b/openpype/settings/defaults/project_settings/deadline.json index 0cbd3232993..dec6a405a04 100644 --- a/openpype/settings/defaults/project_settings/deadline.json +++ b/openpype/settings/defaults/project_settings/deadline.json @@ -44,8 +44,6 @@ "priority": 50, "chunk_size": 10, "group": "none", - "deadline_pool": "", - "deadline_pool_secondary": "", "framePerTask": 1 }, "NukeSubmitDeadline": { diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json b/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json index 9906939cc73..29551cc9f8e 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json @@ -246,16 +246,6 @@ "key": "group", "label": "Group Name" }, - { - "type": "text", - "key": "deadline_pool", - "label": "Deadline pool" - }, - { - "type": "text", - "key": "deadline_pool_secondary", - "label": "Deadline pool (secondary)" - }, { "type": "number", "key": "framePerTask", From 44120036bf8d8c45fd89cae46837cbe8088c63ed Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 21 Mar 2023 16:03:40 +0800 Subject: [PATCH 568/898] clean up setting --- openpype/settings/defaults/project_settings/deadline.json | 3 +-- .../schemas/projects_schema/schema_project_deadline.json | 7 +------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/openpype/settings/defaults/project_settings/deadline.json b/openpype/settings/defaults/project_settings/deadline.json index dec6a405a04..fdd70f1a44a 100644 --- a/openpype/settings/defaults/project_settings/deadline.json +++ b/openpype/settings/defaults/project_settings/deadline.json @@ -43,8 +43,7 @@ "use_published": true, "priority": 50, "chunk_size": 10, - "group": "none", - "framePerTask": 1 + "group": "none" }, "NukeSubmitDeadline": { "enabled": true, diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json b/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json index 29551cc9f8e..d8b5e4dc1fa 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json @@ -239,17 +239,12 @@ { "type": "number", "key": "chunk_size", - "label": "Chunk Size" + "label": "Frame per Task" }, { "type": "text", "key": "group", "label": "Group Name" - }, - { - "type": "number", - "key": "framePerTask", - "label": "Frame Per Task" } ] }, From 828f59bfb55e10c2c207c98eab7d6f1184d2826e Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 21 Mar 2023 16:37:58 +0800 Subject: [PATCH 569/898] clean up attributes --- .../modules/deadline/plugins/publish/submit_max_deadline.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index 65d08b9ef44..dec4bcc500e 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -40,13 +40,10 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, use_published = True priority = 50 - tile_priority = 50 - chunkSize = 1 + chunk_size = 1 jobInfo = {} pluginInfo = {} group = None - framePerTask = 1 - optional = True @classmethod def apply_settings(cls, project_settings, system_settings): From 71a28cb76048d0fa057f2ec6ede62fe84fe54587 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 21 Mar 2023 10:09:36 +0100 Subject: [PATCH 570/898] Scene inventory: Fix code errors when "not found" entries are found (#4594) * Avoid VersionDelegate error if version value is not set, e.g. for NOT FOUND instances * Ignore items without `representation` data * Add not found items per container into the model like regular containers * Do not provide set version + remove options for NOT FOUND items --- openpype/tools/sceneinventory/model.py | 16 ++++++++-------- openpype/tools/sceneinventory/view.py | 7 +++++++ openpype/tools/utils/delegates.py | 8 +++++--- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/openpype/tools/sceneinventory/model.py b/openpype/tools/sceneinventory/model.py index 680dfd5a510..63d29451457 100644 --- a/openpype/tools/sceneinventory/model.py +++ b/openpype/tools/sceneinventory/model.py @@ -327,7 +327,7 @@ def add_items(self, items, parent=None): project_name, repre_id ) if not representation: - not_found["representation"].append(group_items) + not_found["representation"].extend(group_items) not_found_ids.append(repre_id) continue @@ -335,7 +335,7 @@ def add_items(self, items, parent=None): project_name, representation["parent"] ) if not version: - not_found["version"].append(group_items) + not_found["version"].extend(group_items) not_found_ids.append(repre_id) continue @@ -348,13 +348,13 @@ def add_items(self, items, parent=None): subset = get_subset_by_id(project_name, version["parent"]) if not subset: - not_found["subset"].append(group_items) + not_found["subset"].extend(group_items) not_found_ids.append(repre_id) continue asset = get_asset_by_id(project_name, subset["parent"]) if not asset: - not_found["asset"].append(group_items) + not_found["asset"].extend(group_items) not_found_ids.append(repre_id) continue @@ -380,11 +380,11 @@ def add_items(self, items, parent=None): self.add_child(group_node, parent=parent) - for _group_items in group_items: + for item in group_items: item_node = Item() - item_node["Name"] = ", ".join( - [item["objectName"] for item in _group_items] - ) + item_node.update(item) + item_node["Name"] = item.get("objectName", "NO NAME") + item_node["isNotFound"] = True self.add_child(item_node, parent=group_node) for repre_id, group_dict in sorted(grouped.items()): diff --git a/openpype/tools/sceneinventory/view.py b/openpype/tools/sceneinventory/view.py index a04171e4292..3279be6094d 100644 --- a/openpype/tools/sceneinventory/view.py +++ b/openpype/tools/sceneinventory/view.py @@ -80,9 +80,16 @@ def _leave_hierarchy(self): self.setStyleSheet("QTreeView {}") def _build_item_menu_for_selection(self, items, menu): + + # Exclude items that are "NOT FOUND" since setting versions, updating + # and removal won't work for those items. + items = [item for item in items if not item.get("isNotFound")] + if not items: return + # An item might not have a representation, for example when an item + # is listed as "NOT FOUND" repre_ids = { item["representation"] for item in items diff --git a/openpype/tools/utils/delegates.py b/openpype/tools/utils/delegates.py index d76284afb1a..fa69113ef1d 100644 --- a/openpype/tools/utils/delegates.py +++ b/openpype/tools/utils/delegates.py @@ -30,9 +30,11 @@ def __init__(self, dbcon, *args, **kwargs): def displayText(self, value, locale): if isinstance(value, HeroVersionType): return lib.format_version(value, True) - assert isinstance(value, numbers.Integral), ( - "Version is not integer. \"{}\" {}".format(value, str(type(value))) - ) + if not isinstance(value, numbers.Integral): + # For cases where no version is resolved like NOT FOUND cases + # where a representation might not exist in current database + return + return lib.format_version(value) def paint(self, painter, option, index): From b40289c9b5df00ae2222d70fce6a5b8a1e37498d Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 21 Mar 2023 09:17:20 +0000 Subject: [PATCH 571/898] simulationRate > step, sampleMultiplier > stepSave --- openpype/hosts/maya/plugins/publish/extract_gpu_cache.py | 8 ++++---- openpype/settings/defaults/project_settings/maya.json | 4 ++-- .../projects_schema/schemas/schema_maya_publish.json | 8 ++++---- website/docs/admin_hosts_maya.md | 6 +++--- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py index 965122822c5..f92bb9c67f2 100644 --- a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py +++ b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py @@ -11,8 +11,8 @@ class ExtractGPUCache(publish.Extractor): label = "GPU Cache" hosts = ["maya"] families = ["model", "animation", "pointcache"] - simulationRate = 1.0 - sampleMultiplier = 1 + step = 1.0 + stepSave = 1 optimize = True optimizationThreshold = 40000 optimizeAnimationsForMotionBlur = True @@ -28,8 +28,8 @@ def process(self, instance): "directory": staging_dir, "fileName": filename, "saveMultipleFiles": False, - "simulationRate": self.simulationRate, - "sampleMultiplier": self.sampleMultiplier, + "step": self.step, + "stepSave": self.stepSave, "optimize": self.optimize, "optimizationThreshold": self.optimizationThreshold, "optimizeAnimationsForMotionBlur": ( diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index 8fec46ccf22..b06a97dce38 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -932,8 +932,8 @@ "animation", "pointcache" ], - "simulationRate": 0.0, - "sampleMultiplier": 0, + "step": 0.0, + "stepSave": 0, "optimize": true, "optimizationThreshold": 40000, "optimizeAnimationsForMotionBlur": true, diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json index 24a48056561..09b235fa0e1 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json @@ -1016,15 +1016,15 @@ "object_type": "text" }, { - "key": "simulationRate", - "label": "Evaluate Every", + "key": "step", + "label": "Step", "type": "number", "decimal": 4, "minimum": 1 }, { - "key": "sampleMultiplier", - "label": "Save Every", + "key": "stepSave", + "label": "Step Save", "type": "number", "minimum": 1 }, diff --git a/website/docs/admin_hosts_maya.md b/website/docs/admin_hosts_maya.md index 3cfd28b20ae..e07bb7d6694 100644 --- a/website/docs/admin_hosts_maya.md +++ b/website/docs/admin_hosts_maya.md @@ -110,12 +110,12 @@ This is useful to fix some specific renderer glitches and advanced hacking of Ma ![Maya GPU Cache](assets/maya-admin_gpu_cache.png) -- **Evaluate Every** Specifies which samples are saved during cache creation. For example, a value of 2 specifies that only every other sample specified by the Evaluate every # frame(s) option is saved to your Alembic file. - -- **Save Every** Specifies how often samples are taken during file creation. By default, one sample of your object's transformations is taken every frame and saved to the Alembic file. +- **Step** Specifies how often samples are taken during file creation. By default, one sample of your object's transformations is taken every frame and saved to the Alembic file. For example, a value of 2 caches the transformations of the current object at every other frame of the Cache Time Range. +- **Step Save** Specifies which samples are saved during cache creation. For example, a value of 2 specifies that only every other sample specified by the Step # frame(s) option is saved to your Alembic file. + - **Optimize Hierarchy** When on, nodes and objects in a selected hierarchy are consolidated to maximize the performance of the cache file during playback. - **Optimization Threshold** (Available only when Optimize Hierarchy is on.) Specifies the maximum number of vertices contained in a single draw primitive. The default value of 40000 may be ideal for most Maya supported graphics cards. When set to the default value, after optimization, each object in the GPU cache file(s) will have no more than 40000 vertices. This value can be set higher depending on the memory available on your system graphics card. From e083a18dda71214eb33c5b1f3872cc324f7ff915 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 21 Mar 2023 09:19:54 +0000 Subject: [PATCH 572/898] Default values for step and stepSave. --- openpype/settings/defaults/project_settings/maya.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index b06a97dce38..7757f201ad6 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -932,8 +932,8 @@ "animation", "pointcache" ], - "step": 0.0, - "stepSave": 0, + "step": 1.0, + "stepSave": 1, "optimize": true, "optimizationThreshold": 40000, "optimizeAnimationsForMotionBlur": true, From a0c599203e992b8aea3f7898ce040362e3c11032 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 21 Mar 2023 10:42:06 +0100 Subject: [PATCH 573/898] Global: add tags field to thumbnail representation (#4660) * Fix add tags field to thumbnail representation Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- .../plugins/publish/preintegrate_thumbnail_representation.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openpype/plugins/publish/preintegrate_thumbnail_representation.py b/openpype/plugins/publish/preintegrate_thumbnail_representation.py index b88ccee9dce..1c95b82c978 100644 --- a/openpype/plugins/publish/preintegrate_thumbnail_representation.py +++ b/openpype/plugins/publish/preintegrate_thumbnail_representation.py @@ -60,6 +60,8 @@ def process(self, instance): if not found_profile: return + thumbnail_repre.setdefault("tags", []) + if not found_profile["integrate_thumbnail"]: if "delete" not in thumbnail_repre["tags"]: thumbnail_repre["tags"].append("delete") From 55b984dc66c4948b793033afe27e111047b62ae1 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 21 Mar 2023 17:45:35 +0800 Subject: [PATCH 574/898] scene length setting for 3dsmax --- openpype/hosts/max/api/lib.py | 127 +++++++++++++++++++++++++++++ openpype/hosts/max/api/menu.py | 21 ++++- openpype/hosts/max/api/pipeline.py | 5 ++ 3 files changed, 152 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index 4fb750d91bd..f1d1f91dd1a 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -6,6 +6,14 @@ from typing import Union import contextlib +from openpype.client import ( + get_project, + get_asset_by_name +) +from openpype.pipeline import legacy_io + +from openpype.pipeline.context_tools import get_current_project_asset + JSON_PREFIX = "JSON::" @@ -157,6 +165,125 @@ def get_multipass_setting(project_setting=None): ["multipass"]) +def set_scene_resolution(width, height): + """Set the render resolution + + Args: + width(int): value of the width + height(int): value of the height + + Returns: + None + + """ + rt.renderWidth = width + rt.renderHeight = height + + +def reset_scene_resolution(): + """Apply the scene resolution from the project definition + + scene resolution can be overwritten by an asset if the asset.data contains + any information regarding scene resolution . + + Returns: + None + """ + project_name = legacy_io.active_project() + project_doc = get_project(project_name) + project_data = project_doc["data"] + asset_data = get_current_project_asset()["data"] + + # Set project resolution + width_key = "resolutionWidth" + height_key = "resolutionHeight" + proj_width_key = project_data.get(width_key, 1920) + proj_height_key = project_data.get(height_key, 1080) + + width = asset_data.get(width_key, proj_width_key) + height = asset_data.get(height_key, proj_height_key) + + set_scene_resolution(width, height) + + +def get_frame_range(): + """Get the current assets frame range and handles.""" + # Set frame start/end + project_name = legacy_io.active_project() + asset_name = legacy_io.Session["AVALON_ASSET"] + asset = get_asset_by_name(project_name, asset_name) + + frame_start = asset["data"].get("frameStart") + frame_end = asset["data"].get("frameEnd") + # Backwards compatibility + if frame_start is None or frame_end is None: + frame_start = asset["data"].get("edit_in") + frame_end = asset["data"].get("edit_out") + + if frame_start is None or frame_end is None: + return + + handles = asset["data"].get("handles") or 0 + handle_start = asset["data"].get("handleStart") + if handle_start is None: + handle_start = handles + + handle_end = asset["data"].get("handleEnd") + if handle_end is None: + handle_end = handles + + return { + "frameStart": frame_start, + "frameEnd": frame_end, + "handleStart": handle_start, + "handleEnd": handle_end + } + + +def reset_frame_range(fps=True): + """Set frame range to current asset + + Args: + animationRange: A System Global variable which lets you get and + set an Interval value that defines the start and end frames + of the Active Time Segment. + frameRate: A System Global variable which lets you get + and set an Integer value that defines the current + scene frame rate in frames-per-second. + """ + if fps: + fps_number = float(legacy_io.Session.get("AVALON_FPS", + 25)) + rt.frameRate = fps_number + + frame_range = get_frame_range() + + frame_start = frame_range["frameStart"] - int(frame_range["handleStart"]) + frame_end = frame_range["frameEnd"] + int(frame_range["handleEnd"]) + + frange_cmd = f"animationRange = interval {frame_start} {frame_end}" + + rt.execute(frange_cmd) + + +def set_context_setting(): + """Apply the project settings from the project definition + + Settings can be overwritten by an asset if the asset.data contains + any information regarding those settings. + + Examples of settings: + frame range + resolution + + Returns: + None + """ + reset_scene_resolution() + + reset_frame_range() + + def get_max_version(): """ Args: diff --git a/openpype/hosts/max/api/menu.py b/openpype/hosts/max/api/menu.py index 5c273b49b4c..fdac5eba09b 100644 --- a/openpype/hosts/max/api/menu.py +++ b/openpype/hosts/max/api/menu.py @@ -4,7 +4,7 @@ from pymxs import runtime as rt from openpype.tools.utils import host_tools - +from openpype.hosts.max.api import lib class OpenPypeMenu(object): """Object representing OpenPype menu. @@ -107,6 +107,17 @@ def build_openpype_menu(self) -> QtWidgets.QAction: workfiles_action = QtWidgets.QAction("Work Files...", openpype_menu) workfiles_action.triggered.connect(self.workfiles_callback) openpype_menu.addAction(workfiles_action) + + openpype_menu.addSeparator() + + res_action = QtWidgets.QAction("Set Resolution", openpype_menu) + res_action.triggered.connect(self.resolution_callback) + openpype_menu.addAction(res_action) + + frame_action = QtWidgets.QAction("Set Frame Range", openpype_menu) + frame_action.triggered.connect(self.frame_range_callback) + openpype_menu.addAction(frame_action) + return openpype_menu def load_callback(self): @@ -128,3 +139,11 @@ def library_callback(self): def workfiles_callback(self): """Callback to show Workfiles tool.""" host_tools.show_workfiles(parent=self.main_widget) + + def resolution_callback(self): + """Callback to reset scene resolution""" + return lib.reset_scene_resolution() + + def frame_range_callback(self): + """Callback to reset frame range""" + return lib.reset_frame_range() diff --git a/openpype/hosts/max/api/pipeline.py b/openpype/hosts/max/api/pipeline.py index f8a7b8ea5c1..dacc402318d 100644 --- a/openpype/hosts/max/api/pipeline.py +++ b/openpype/hosts/max/api/pipeline.py @@ -50,6 +50,11 @@ def install(self): self._has_been_setup = True + def context_setting(): + return lib.set_context_setting() + rt.callbacks.addScript(rt.Name('systemPostNew'), + context_setting) + def has_unsaved_changes(self): # TODO: how to get it from 3dsmax? return True From b8ce4b71e2fdd7786d0cb14b5b6c1bf91b5e6851 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Mar 2023 11:20:32 +0100 Subject: [PATCH 575/898] hiero: fix padding in workfile input --- openpype/hosts/hiero/api/plugin.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/hiero/api/plugin.py b/openpype/hosts/hiero/api/plugin.py index 07457db1a40..5ca901caaa2 100644 --- a/openpype/hosts/hiero/api/plugin.py +++ b/openpype/hosts/hiero/api/plugin.py @@ -146,6 +146,8 @@ def camel_case_split(self, text): return " ".join([str(m.group(0)).capitalize() for m in matches]) def create_row(self, layout, type, text, **kwargs): + value_keys = ["setText", "setCheckState", "setValue", "setChecked"] + # get type attribute from qwidgets attr = getattr(QtWidgets, type) @@ -167,14 +169,27 @@ def create_row(self, layout, type, text, **kwargs): # assign the created attribute to variable item = getattr(self, attr_name) + + # set attributes to item which are not values for func, val in kwargs.items(): + if func in value_keys: + continue + if getattr(item, func): + log.debug("Setting {} to {}".format(func, val)) func_attr = getattr(item, func) if isinstance(val, tuple): func_attr(*val) else: func_attr(val) + # set values to item + for value_item in value_keys: + if value_item not in kwargs: + continue + if getattr(item, value_item): + getattr(item, value_item)(kwargs[value_item]) + # add to layout layout.addRow(label, item) @@ -276,8 +291,11 @@ def populate_widgets(self, data, content_layout=None): elif v["type"] == "QSpinBox": data[k]["value"] = self.create_row( content_layout, "QSpinBox", v["label"], - setValue=v["value"], setMinimum=0, + setValue=v["value"], + setDisplayIntegerBase=10000, + setRange=(0, 99999), setMinimum=0, setMaximum=100000, setToolTip=tool_tip) + return data From a24dcd207cceb8959a832a3c576a59bba0200064 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 21 Mar 2023 18:53:12 +0800 Subject: [PATCH 576/898] renaming chunksize variablesd --- .../modules/deadline/plugins/publish/submit_max_deadline.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index dec4bcc500e..c728b6b9c72 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -54,7 +54,7 @@ def apply_settings(cls, project_settings, system_settings): cls.use_published) cls.priority = settings.get("priority", cls.priority) - cls.chunkSize = settings.get("chunk_size", cls.chunkSize) + cls.chuck_size = settings.get("chunk_size", cls.chunk_size) cls.group = settings.get("group", cls.group) def get_job_info(self): @@ -253,7 +253,7 @@ def get_attribute_defs(cls): minimum=1, maximum=50, decimals=0, - default=cls.chunkSize, + default=cls.chunk_size, label="Frame Per Task"), TextDef("group", From 7e7f6ced16d0e867ed2f6a67c05012c5020c0c52 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Tue, 21 Mar 2023 10:54:07 +0000 Subject: [PATCH 577/898] Update openpype/hosts/maya/plugins/publish/extract_gpu_cache.py --- openpype/hosts/maya/plugins/publish/extract_gpu_cache.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py index f92bb9c67f2..deee4569821 100644 --- a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py +++ b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py @@ -28,8 +28,8 @@ def process(self, instance): "directory": staging_dir, "fileName": filename, "saveMultipleFiles": False, - "step": self.step, - "stepSave": self.stepSave, + "simulationRate": self.step, + "sampleMultiplier": self.stepSave, "optimize": self.optimize, "optimizationThreshold": self.optimizationThreshold, "optimizeAnimationsForMotionBlur": ( From ba6135f49e7b0e1c8794f681b58a887e39a368e5 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Mar 2023 14:05:00 +0100 Subject: [PATCH 578/898] Nuke: removing frame-range data --- .../nuke/plugins/publish/collect_backdrop.py | 32 ++----------------- 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/collect_backdrop.py b/openpype/hosts/nuke/plugins/publish/collect_backdrop.py index 8eaefa68541..7d51af7e9e4 100644 --- a/openpype/hosts/nuke/plugins/publish/collect_backdrop.py +++ b/openpype/hosts/nuke/plugins/publish/collect_backdrop.py @@ -51,38 +51,10 @@ def process(self, instance): instance.data["label"] = "{0} ({1} nodes)".format( bckn.name(), len(instance.data["transientData"]["childNodes"])) - instance.data["families"].append(instance.data["family"]) - - # Get frame range - handle_start = instance.context.data["handleStart"] - handle_end = instance.context.data["handleEnd"] - first_frame = int(nuke.root()["first_frame"].getValue()) - last_frame = int(nuke.root()["last_frame"].getValue()) - # get version version = instance.context.data.get('version') - if not version: - raise RuntimeError("Script name has no version in the name.") - - instance.data['version'] = version - - # Add version data to instance - version_data = { - "handles": handle_start, - "handleStart": handle_start, - "handleEnd": handle_end, - "frameStart": first_frame + handle_start, - "frameEnd": last_frame - handle_end, - "version": int(version), - "families": [instance.data["family"]] + instance.data["families"], - "subset": instance.data["subset"], - "fps": instance.context.data["fps"] - } + if version: + instance.data['version'] = version - instance.data.update({ - "versionData": version_data, - "frameStart": first_frame, - "frameEnd": last_frame - }) self.log.info("Backdrop instance collected: `{}`".format(instance)) From 6f16f3e4f402ff37fd6c8264615d856a6cea67f4 Mon Sep 17 00:00:00 2001 From: Sharkitty <81646000+Sharkitty@users.noreply.github.com> Date: Tue, 21 Mar 2023 14:22:23 +0000 Subject: [PATCH 579/898] Enhancement kitsu note with exceptions (#4537) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Enhancement: Allowing kitsu not status exceptions * Update openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py Co-authored-by: Félix David * adding equal/not equal option * Making equal/not equal option available at for every list item * Changed into , renamed into , added documentation * Using upper cases during check, so the new settings aren't case sensitive * Linting little detail * Renaming Equality into Condition, new screenshot with both equal and not equal shown on it * Update website/docs/module_kitsu.md README adjustments Co-authored-by: Félix David * Changes needed to resolve conflict * Changing context into instance where appropriate * Minor change to avoid changing a line that doesn't need to be changed * Turning exceptions into conditions. Making checks positive instead of negative. Changing implementation based on suggestions. --------- Co-authored-by: Félix David --- .../plugins/publish/integrate_kitsu_note.py | 24 ++++++++++++---- .../defaults/project_settings/kitsu.json | 1 + .../projects_schema/schema_project_kitsu.json | 26 ++++++++++++++++++ .../assets/integrate_kitsu_note_settings.png | Bin 0 -> 30524 bytes website/docs/module_kitsu.md | 12 ++++++++ 5 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 website/docs/assets/integrate_kitsu_note_settings.png diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index cf36bbc4fed..6fda32d85f5 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -14,6 +14,7 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): # status settings set_status_note = False note_status_shortname = "wfa" + status_conditions = list() # comment settings custom_comment_template = { @@ -56,9 +57,19 @@ def process(self, context): # Get note status, by default uses the task status for the note # if it is not specified in the configuration - note_status = kitsu_task["task_status"]["id"] - - if self.set_status_note: + shortname = kitsu_task["task_status"]["short_name"].upper() + note_status = kitsu_task["task_status_id"] + + # Check if any status condition is not met + allow_status_change = True + for status_cond in self.status_conditions: + condition = status_cond["condition"] == "equal" + match = status_cond["short_name"].upper() == shortname + if match and not condition or condition and not match: + allow_status_change = False + break + + if self.set_status_note and allow_status_change: kitsu_status = gazu.task.get_task_status_by_short_name( self.note_status_shortname ) @@ -82,10 +93,11 @@ def process(self, context): self.log.debug("Comment is `{}`".format(publish_comment)) # Add comment to kitsu task - task_id = kitsu_task["id"] - self.log.debug("Add new note in taks id {}".format(task_id)) + self.log.debug( + "Add new note in tasks id {}".format(kitsu_task["id"]) + ) kitsu_comment = gazu.task.add_comment( - task_id, note_status, comment=publish_comment + kitsu_task, note_status, comment=publish_comment ) instance.data["kitsu_comment"] = kitsu_comment diff --git a/openpype/settings/defaults/project_settings/kitsu.json b/openpype/settings/defaults/project_settings/kitsu.json index 11c138e8e50..0638450595a 100644 --- a/openpype/settings/defaults/project_settings/kitsu.json +++ b/openpype/settings/defaults/project_settings/kitsu.json @@ -8,6 +8,7 @@ "IntegrateKitsuNote": { "set_status_note": false, "note_status_shortname": "wfa", + "status_conditions": [], "custom_comment_template": { "enabled": false, "comment_template": "{comment}\n\n| | |\n|--|--|\n| version| `{version}` |\n| family | `{family}` |\n| name | `{name}` |" diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index 7ceb979d6fc..ee309f63a72 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -51,6 +51,32 @@ { "type": "text", "key": "note_status_shortname", + "label": "Note shortname" + }, + { + "type": "list", + "key": "status_conditions", + "label": "Status conditions", + "object_type": { + "type": "dict", + "key": "conditions_dict", + "children": [ + { + "type": "enum", + "key": "condition", + "label": "Condition", + "enum_items": [ + {"equal": "Equal"}, + {"not_equal": "Not equal"} + ] + }, + { + "type": "text", + "key": "short_name", + "label": "Short name" + } + ] + }, "label": "Status shortname" }, { diff --git a/website/docs/assets/integrate_kitsu_note_settings.png b/website/docs/assets/integrate_kitsu_note_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..127e79ab8063dae0408f90a82d6bb4b5e233ed47 GIT binary patch literal 30524 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 literal 0 HcmV?d00001 diff --git a/website/docs/module_kitsu.md b/website/docs/module_kitsu.md index 7be2a42c458..23898fba2e7 100644 --- a/website/docs/module_kitsu.md +++ b/website/docs/module_kitsu.md @@ -38,6 +38,18 @@ This functionality cannot deal with all cases and is not error proof, some inter openpype_console module kitsu push-to-zou -l me@domain.ext -p my_password ``` +## Integrate Kitsu Note +Task status can be automatically set during publish thanks to `Integrate Kitsu Note`. This feature can be configured in: + +`Admin -> Studio Settings -> Project Settings -> Kitsu -> Integrate Kitsu Note`. + +There are three settings available: +- `Set status on note` -> turns on and off this integrator. +- `Note shortname` -> Which status shortname should be set automatically (Case sensitive). +- `Status conditions` -> Conditions that need to be met for kitsu status to be changed. You can add as many conditions as you like. There are two fields to each conditions: `Condition` (Whether current status should be equal or not equal to the condition status) and `Short name` (Kitsu Shortname of the condition status). + +![Integrate Kitsu Note project settings](assets/integrate_kitsu_note_settings.png) + ## Q&A ### Is it safe to rename an entity from Kitsu? Absolutely! Entities are linked by their unique IDs between the two databases. From 96e184c8ca7db7d579065e3617149a38c176ebae Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 21 Mar 2023 15:29:19 +0100 Subject: [PATCH 580/898] Integrator: Enforce unique destination transfers, disallow overwrites in queued transfers (#4662) * Fix #4656: Enforce unique destination transfer in Integrator Note that this is per instance - it doesn't validate cross-instance destinations in the context * Use explicit DuplicateDestinationError and raise as KnownPublishError --- openpype/lib/file_transaction.py | 22 +++++++++++++++++++++- openpype/plugins/publish/integrate.py | 16 ++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/openpype/lib/file_transaction.py b/openpype/lib/file_transaction.py index fe70b37cb19..81332a88915 100644 --- a/openpype/lib/file_transaction.py +++ b/openpype/lib/file_transaction.py @@ -13,6 +13,16 @@ from shutil import copyfile +class DuplicateDestinationError(ValueError): + """Error raised when transfer destination already exists in queue. + + The error is only raised if `allow_queue_replacements` is False on the + FileTransaction instance and the added file to transfer is of a different + src file than the one already detected in the queue. + + """ + + class FileTransaction(object): """File transaction with rollback options. @@ -44,7 +54,7 @@ class FileTransaction(object): MODE_COPY = 0 MODE_HARDLINK = 1 - def __init__(self, log=None): + def __init__(self, log=None, allow_queue_replacements=False): if log is None: log = logging.getLogger("FileTransaction") @@ -60,6 +70,8 @@ def __init__(self, log=None): # Backup file location mapping to original locations self._backup_to_original = {} + self._allow_queue_replacements = allow_queue_replacements + def add(self, src, dst, mode=MODE_COPY): """Add a new file to transfer queue. @@ -82,6 +94,14 @@ def add(self, src, dst, mode=MODE_COPY): src, dst)) return else: + if not self._allow_queue_replacements: + raise DuplicateDestinationError( + "Transfer to destination is already in queue: " + "{} -> {}. It's not allowed to be replaced by " + "a new transfer from {}".format( + queued_src, dst, src + )) + self.log.warning("File transfer in queue replaced..") self.log.debug( "Removed from queue: {} -> {} replaced by {} -> {}".format( diff --git a/openpype/plugins/publish/integrate.py b/openpype/plugins/publish/integrate.py index 6a0327ec843..760b1a6b370 100644 --- a/openpype/plugins/publish/integrate.py +++ b/openpype/plugins/publish/integrate.py @@ -24,7 +24,10 @@ get_version_by_name, ) from openpype.lib import source_hash -from openpype.lib.file_transaction import FileTransaction +from openpype.lib.file_transaction import ( + FileTransaction, + DuplicateDestinationError +) from openpype.pipeline.publish import ( KnownPublishError, get_publish_template_name, @@ -170,9 +173,18 @@ def process(self, instance): ).format(instance.data["family"])) return - file_transactions = FileTransaction(log=self.log) + file_transactions = FileTransaction(log=self.log, + # Enforce unique transfers + allow_queue_replacements=False) try: self.register(instance, file_transactions, filtered_repres) + except DuplicateDestinationError as exc: + # Raise DuplicateDestinationError as KnownPublishError + # and rollback the transactions + file_transactions.rollback() + six.reraise(KnownPublishError, + KnownPublishError(exc), + sys.exc_info()[2]) except Exception: # clean destination # todo: preferably we'd also rollback *any* changes to the database From c42ce4e96c7d14767d1aa0a62b126ffa43ccd942 Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Wed, 1 Mar 2023 14:41:51 +0100 Subject: [PATCH 581/898] Enhancement: Adding family requirements option to kitsu note --- .../plugins/publish/integrate_kitsu_note.py | 51 +++++++++++++++++++ .../defaults/project_settings/kitsu.json | 1 + .../projects_schema/schema_project_kitsu.json | 26 ++++++++++ 3 files changed, 78 insertions(+) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 6fda32d85f5..8e0037fcf76 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -15,6 +15,7 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): set_status_note = False note_status_shortname = "wfa" status_conditions = list() + family_requirements = list() # comment settings custom_comment_template = { @@ -72,6 +73,56 @@ def process(self, context): if self.set_status_note and allow_status_change: kitsu_status = gazu.task.get_task_status_by_short_name( self.note_status_shortname + families = set() + for instance in context: + if instance.data.get('publish'): + families.add(instance.data['family']) + + # Get note status, by default uses the task status for the note + # if it is not specified in the configuration + kitsu_task = context.data["kitsu_task"] + shortname = kitsu_task["task_status"]["short_name"].upper() + note_status = kitsu_task["task_status_id"] + if self.set_status_note and next( + ( + False + for status_except in self.status_exceptions + if shortname == status_except["short_name"].upper() + and status_except["condition"] == "equal" + or + shortname != status_except["short_name"].upper() + and status_except["condition"] == "not_equal" + ), + True, + ) and next( + ( + True + for family in families + if next( + ( + False + for family_req in self.family_requirements + if family_req['equality'] != 'equal' + and family_req['family'] == family + or + family_req['equality'] == 'not_equal' + and family_req['family'] == family + ), + True, + ) + ), + False, + ): + kitsu_status = gazu.task.get_task_status_by_short_name( + self.note_status_shortname + ) + if kitsu_status: + note_status = kitsu_status + self.log.info("Note Kitsu status: {}".format(note_status)) + else: + self.log.info( + "Cannot find {} status. The status will not be " + "changed!".format(self.note_status_shortname) ) if kitsu_status: note_status = kitsu_status diff --git a/openpype/settings/defaults/project_settings/kitsu.json b/openpype/settings/defaults/project_settings/kitsu.json index 0638450595a..32c6c253c70 100644 --- a/openpype/settings/defaults/project_settings/kitsu.json +++ b/openpype/settings/defaults/project_settings/kitsu.json @@ -9,6 +9,7 @@ "set_status_note": false, "note_status_shortname": "wfa", "status_conditions": [], + "family_requirements": [], "custom_comment_template": { "enabled": false, "comment_template": "{comment}\n\n| | |\n|--|--|\n| version| `{version}` |\n| family | `{family}` |\n| name | `{name}` |" diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index ee309f63a72..c32a2cb5af2 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -79,6 +79,31 @@ }, "label": "Status shortname" }, + { + "type": "list", + "key": "family_requirements", + "label": "Family requirements", + "object_type": { + "type": "dict", + "key": "requirement_dict", + "children": [ + { + "type": "enum", + "key": "equality", + "label": "Equality", + "enum_items": [ + {"equal": "Equal"}, + {"not_equal": "Not equal"} + ] + }, + { + "type": "text", + "key": "family", + "label": "Family" + } + ] + } + }, { "type": "dict", "collapsible": true, @@ -102,6 +127,7 @@ "label": "Custom comment" } ] + } } ] } From b467909fd65622f524ff1ba35f2cca53cd62afab Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Wed, 1 Mar 2023 14:48:37 +0100 Subject: [PATCH 582/898] Using lower cases for families and a small fix --- .../modules/kitsu/plugins/publish/integrate_kitsu_note.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 8e0037fcf76..bd43fe3b7c1 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -102,11 +102,11 @@ def process(self, context): ( False for family_req in self.family_requirements - if family_req['equality'] != 'equal' - and family_req['family'] == family + if family_req['equality'] == 'equal' + and family_req['family'].lower() != family or family_req['equality'] == 'not_equal' - and family_req['family'] == family + and family_req['family'].lower() == family ), True, ) From d3330f482a7e4d8945d871e13359f03938577240 Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Wed, 1 Mar 2023 15:11:56 +0100 Subject: [PATCH 583/898] Edited kitsu module readme --- website/docs/module_kitsu.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/website/docs/module_kitsu.md b/website/docs/module_kitsu.md index 23898fba2e7..08b7073c3d5 100644 --- a/website/docs/module_kitsu.md +++ b/website/docs/module_kitsu.md @@ -43,10 +43,11 @@ Task status can be automatically set during publish thanks to `Integrate Kitsu N `Admin -> Studio Settings -> Project Settings -> Kitsu -> Integrate Kitsu Note`. -There are three settings available: +There are four settings available: - `Set status on note` -> turns on and off this integrator. - `Note shortname` -> Which status shortname should be set automatically (Case sensitive). - `Status conditions` -> Conditions that need to be met for kitsu status to be changed. You can add as many conditions as you like. There are two fields to each conditions: `Condition` (Whether current status should be equal or not equal to the condition status) and `Short name` (Kitsu Shortname of the condition status). +- `Family requirements` -> With this option you can add requirements to which families must be pushed or not in order to have the task status set by this integrator. There are two fields for each requirements: `Equality` (Same as the above) and `Family` (name of the family concerned by this requirement). For instance, adding one item set to `Not equal` and `workfile`, would mean the task status would change if a subset from another family than workfile is published (workfile can still be included), but not if you only publish the workfile subset. ![Integrate Kitsu Note project settings](assets/integrate_kitsu_note_settings.png) From 7356887df6402f5d4acfb7448a47aec5b5c33877 Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Wed, 1 Mar 2023 18:45:15 +0100 Subject: [PATCH 584/898] Renaming equality into condition, made a new screenshot so both equal and not equal settings are shown --- .../plugins/publish/integrate_kitsu_note.py | 4 ++-- .../projects_schema/schema_project_kitsu.json | 4 ++-- .../assets/integrate_kitsu_note_settings.png | Bin 30524 -> 44847 bytes website/docs/module_kitsu.md | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index bd43fe3b7c1..2c85a5f70b7 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -102,10 +102,10 @@ def process(self, context): ( False for family_req in self.family_requirements - if family_req['equality'] == 'equal' + if family_req['condition'] == 'equal' and family_req['family'].lower() != family or - family_req['equality'] == 'not_equal' + family_req['condition'] == 'not_equal' and family_req['family'].lower() == family ), True, diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index c32a2cb5af2..ba77f2b4718 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -89,8 +89,8 @@ "children": [ { "type": "enum", - "key": "equality", - "label": "Equality", + "key": "condition", + "label": "Condition", "enum_items": [ {"equal": "Equal"}, {"not_equal": "Not equal"} diff --git a/website/docs/assets/integrate_kitsu_note_settings.png b/website/docs/assets/integrate_kitsu_note_settings.png index 127e79ab8063dae0408f90a82d6bb4b5e233ed47..fd055942d023e2ffc12fc508cd7079eb834045c3 100644 GIT binary patch literal 44847 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 BT7Uom literal 30524 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 diff --git a/website/docs/module_kitsu.md b/website/docs/module_kitsu.md index 08b7073c3d5..daa7102b79a 100644 --- a/website/docs/module_kitsu.md +++ b/website/docs/module_kitsu.md @@ -47,7 +47,7 @@ There are four settings available: - `Set status on note` -> turns on and off this integrator. - `Note shortname` -> Which status shortname should be set automatically (Case sensitive). - `Status conditions` -> Conditions that need to be met for kitsu status to be changed. You can add as many conditions as you like. There are two fields to each conditions: `Condition` (Whether current status should be equal or not equal to the condition status) and `Short name` (Kitsu Shortname of the condition status). -- `Family requirements` -> With this option you can add requirements to which families must be pushed or not in order to have the task status set by this integrator. There are two fields for each requirements: `Equality` (Same as the above) and `Family` (name of the family concerned by this requirement). For instance, adding one item set to `Not equal` and `workfile`, would mean the task status would change if a subset from another family than workfile is published (workfile can still be included), but not if you only publish the workfile subset. +- `Family requirements` -> With this option you can add requirements to which families must be pushed or not in order to have the task status set by this integrator. There are two fields for each requirements: `Condition` (Same as the above) and `Family` (name of the family concerned by this requirement). For instance, adding one item set to `Not equal` and `workfile`, would mean the task status would change if a subset from another family than workfile is published (workfile can still be included), but not if you only publish the workfile subset. ![Integrate Kitsu Note project settings](assets/integrate_kitsu_note_settings.png) From d8360b5b19cad2110efdc71a9c72d007c2c8b927 Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Wed, 8 Mar 2023 12:11:09 +0100 Subject: [PATCH 585/898] Made changes to resolve conflicts with develop. Changes how publisshed families are accessed. --- .../plugins/publish/integrate_kitsu_note.py | 96 +++++++++---------- 1 file changed, 47 insertions(+), 49 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 2c85a5f70b7..3c3607a9875 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -73,56 +73,54 @@ def process(self, context): if self.set_status_note and allow_status_change: kitsu_status = gazu.task.get_task_status_by_short_name( self.note_status_shortname - families = set() + families = set( + instance.data.get('kitsu_task') + for instance in context + if instance.data.get('publish') + ) + for instance in context: - if instance.data.get('publish'): - families.add(instance.data['family']) - - # Get note status, by default uses the task status for the note - # if it is not specified in the configuration - kitsu_task = context.data["kitsu_task"] - shortname = kitsu_task["task_status"]["short_name"].upper() - note_status = kitsu_task["task_status_id"] - if self.set_status_note and next( - ( - False - for status_except in self.status_exceptions - if shortname == status_except["short_name"].upper() - and status_except["condition"] == "equal" - or - shortname != status_except["short_name"].upper() - and status_except["condition"] == "not_equal" - ), - True, - ) and next( - ( - True - for family in families - if next( - ( - False - for family_req in self.family_requirements - if family_req['condition'] == 'equal' - and family_req['family'].lower() != family - or - family_req['condition'] == 'not_equal' - and family_req['family'].lower() == family - ), - True, - ) - ), - False, - ): - kitsu_status = gazu.task.get_task_status_by_short_name( - self.note_status_shortname - ) - if kitsu_status: - note_status = kitsu_status - self.log.info("Note Kitsu status: {}".format(note_status)) - else: - self.log.info( - "Cannot find {} status. The status will not be " - "changed!".format(self.note_status_shortname) + kitsu_task = instance.data.get("kitsu_task") + if not kitsu_task: + continue + + # Get note status, by default uses the task status for the note + # if it is not specified in the configuration + kitsu_task = context.data["kitsu_task"] + shortname = kitsu_task["task_status"]["short_name"].upper() + note_status = kitsu_task["task_status_id"] + if self.set_status_note and next( + ( + False + for status_except in self.status_exceptions + if shortname == status_except["short_name"].upper() + and status_except["condition"] == "equal" + or + shortname != status_except["short_name"].upper() + and status_except["condition"] == "not_equal" + ), + True, + ) and next( + ( + True + for family in families + if next( + ( + False + for family_req in self.family_requirements + if family_req['condition'] == 'equal' + and family_req['family'].lower() != family + or + family_req['condition'] == 'not_equal' + and family_req['family'].lower() == family + ), + True, + ) + ), + False, + ): + kitsu_status = gazu.task.get_task_status_by_short_name( + self.note_status_shortname ) if kitsu_status: note_status = kitsu_status From 6e13275054fc3aaedb3f5d487ef45330aee615b9 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 21 Mar 2023 16:29:46 +0100 Subject: [PATCH 586/898] Cleanup unused imports --- openpype/hosts/fusion/plugins/publish/extract_render_local.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/extract_render_local.py b/openpype/hosts/fusion/plugins/publish/extract_render_local.py index 673c5a3ce30..16a582032f1 100644 --- a/openpype/hosts/fusion/plugins/publish/extract_render_local.py +++ b/openpype/hosts/fusion/plugins/publish/extract_render_local.py @@ -1,6 +1,4 @@ -import os import pyblish.api -from openpype.pipeline import publish from openpype.hosts.fusion.api import comp_lock_and_undo_chunk From 83aabf4c2bfed63cbaa63fab3de14d5b53668a14 Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Wed, 8 Mar 2023 12:15:00 +0100 Subject: [PATCH 587/898] Linted --- .../plugins/publish/integrate_kitsu_note.py | 71 +++++++++++-------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 3c3607a9875..f394a3d04ba 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -55,6 +55,10 @@ def process(self, context): kitsu_task = instance.data.get("kitsu_task") if kitsu_task is None: continue + # Get comment text body + publish_comment = context.data.get("comment") + if not publish_comment: + self.log.info("Comment is not set.") # Get note status, by default uses the task status for the note # if it is not specified in the configuration @@ -74,9 +78,9 @@ def process(self, context): kitsu_status = gazu.task.get_task_status_by_short_name( self.note_status_shortname families = set( - instance.data.get('kitsu_task') + instance.data.get("kitsu_task") for instance in context - if instance.data.get('publish') + if instance.data.get("publish") ) for instance in context: @@ -89,35 +93,37 @@ def process(self, context): kitsu_task = context.data["kitsu_task"] shortname = kitsu_task["task_status"]["short_name"].upper() note_status = kitsu_task["task_status_id"] - if self.set_status_note and next( - ( - False - for status_except in self.status_exceptions - if shortname == status_except["short_name"].upper() - and status_except["condition"] == "equal" - or - shortname != status_except["short_name"].upper() - and status_except["condition"] == "not_equal" - ), - True, - ) and next( - ( - True - for family in families - if next( - ( - False - for family_req in self.family_requirements - if family_req['condition'] == 'equal' - and family_req['family'].lower() != family - or - family_req['condition'] == 'not_equal' - and family_req['family'].lower() == family - ), - True, - ) - ), - False, + if ( + self.set_status_note + and next( + ( + False + for status_except in self.status_exceptions + if shortname == status_except["short_name"].upper() + and status_except["condition"] == "equal" + or shortname != status_except["short_name"].upper() + and status_except["condition"] == "not_equal" + ), + True, + ) + and next( + ( + True + for family in families + if next( + ( + False + for family_req in self.family_requirements + if family_req["condition"] == "equal" + and family_req["family"].lower() != family + or family_req["condition"] == "not_equal" + and family_req["family"].lower() == family + ), + True, + ) + ), + False, + ) ): kitsu_status = gazu.task.get_task_status_by_short_name( self.note_status_shortname @@ -147,6 +153,9 @@ def process(self, context): ) kitsu_comment = gazu.task.add_comment( kitsu_task, note_status, comment=publish_comment + instance.data["kitsu_task"], + note_status, + comment=publish_comment, ) instance.data["kitsu_comment"] = kitsu_comment From 2022a38c650bf6dcd5603c88ecbebd09d176b2b0 Mon Sep 17 00:00:00 2001 From: Sharkitty <81646000+Sharkitty@users.noreply.github.com> Date: Wed, 15 Mar 2023 09:20:17 +0000 Subject: [PATCH 588/898] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adjustment to documentation, and families set declaration Co-authored-by: Félix David --- .../modules/kitsu/plugins/publish/integrate_kitsu_note.py | 4 ++-- website/docs/module_kitsu.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index f394a3d04ba..0bb2a63feab 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -77,11 +77,11 @@ def process(self, context): if self.set_status_note and allow_status_change: kitsu_status = gazu.task.get_task_status_by_short_name( self.note_status_shortname - families = set( + families = { instance.data.get("kitsu_task") for instance in context if instance.data.get("publish") - ) + } for instance in context: kitsu_task = instance.data.get("kitsu_task") diff --git a/website/docs/module_kitsu.md b/website/docs/module_kitsu.md index daa7102b79a..9a85f83e3ff 100644 --- a/website/docs/module_kitsu.md +++ b/website/docs/module_kitsu.md @@ -44,10 +44,10 @@ Task status can be automatically set during publish thanks to `Integrate Kitsu N `Admin -> Studio Settings -> Project Settings -> Kitsu -> Integrate Kitsu Note`. There are four settings available: -- `Set status on note` -> turns on and off this integrator. +- `Set status on note` -> Turns on and off this integrator. - `Note shortname` -> Which status shortname should be set automatically (Case sensitive). - `Status conditions` -> Conditions that need to be met for kitsu status to be changed. You can add as many conditions as you like. There are two fields to each conditions: `Condition` (Whether current status should be equal or not equal to the condition status) and `Short name` (Kitsu Shortname of the condition status). -- `Family requirements` -> With this option you can add requirements to which families must be pushed or not in order to have the task status set by this integrator. There are two fields for each requirements: `Condition` (Same as the above) and `Family` (name of the family concerned by this requirement). For instance, adding one item set to `Not equal` and `workfile`, would mean the task status would change if a subset from another family than workfile is published (workfile can still be included), but not if you only publish the workfile subset. +- `Family requirements` -> With this option you can add requirements to which families must be pushed or not in order to have the task status set by this integrator. There are two fields for each requirements: `Condition` (Same as the above) and `Family` (name of the family concerned by this requirement). For instance, adding one item set to `Not equal` and `workfile`, would mean the task status would change if a subset from another family than workfile is published (workfile can still be included), but not if you publish the workfile subset only. ![Integrate Kitsu Note project settings](assets/integrate_kitsu_note_settings.png) From 36ee01997672e78591e80e1d93278dc9db1a2800 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Tue, 21 Mar 2023 16:48:50 +0100 Subject: [PATCH 589/898] :rotating_light: some style fixes --- openpype/hosts/unreal/ue_workers.py | 114 +++++++++++++++------------- openpype/widgets/splash_screen.py | 4 +- 2 files changed, 62 insertions(+), 56 deletions(-) diff --git a/openpype/hosts/unreal/ue_workers.py b/openpype/hosts/unreal/ue_workers.py index f7bc0e90dca..d1740124a87 100644 --- a/openpype/hosts/unreal/ue_workers.py +++ b/openpype/hosts/unreal/ue_workers.py @@ -5,33 +5,33 @@ import subprocess from distutils import dir_util from pathlib import Path -from typing import List +from typing import List, Union import openpype.hosts.unreal.lib as ue_lib from qtpy import QtCore -def parse_comp_progress(line: str, progress_signal: QtCore.Signal(int)) -> int: - match = re.search('\[[1-9]+/[0-9]+\]', line) +def parse_comp_progress(line: str, progress_signal: QtCore.Signal(int)): + match = re.search(r"\[[1-9]+/[0-9]+]", line) if match is not None: - split: list[str] = match.group().split('/') + split: list[str] = match.group().split("/") curr: float = float(split[0][1:]) total: float = float(split[1][:-1]) progress_signal.emit(int((curr / total) * 100.0)) -def parse_prj_progress(line: str, progress_signal: QtCore.Signal(int)) -> int: - match = re.search('@progress', line) +def parse_prj_progress(line: str, progress_signal: QtCore.Signal(int)): + match = re.search("@progress", line) if match is not None: - percent_match = re.search('\d{1,3}', line) + percent_match = re.search(r"\d{1,3}", line) progress_signal.emit(int(percent_match.group())) def retrieve_exit_code(line: str): - match = re.search('ExitCode=\d+', line) + match = re.search(r"ExitCode=\d+", line) if match is not None: - split: list[str] = match.group().split('=') + split: list[str] = match.group().split("=") return int(split[1]) return None @@ -86,16 +86,19 @@ def run(self): if self.dev_mode: stage_count = 4 - self.stage_begin.emit(f'Generating a new UE project ... 1 out of ' - f'{stage_count}') + self.stage_begin.emit( + ("Generating a new UE project ... 1 out of " + f"{stage_count}")) - commandlet_cmd = [f'{ue_editor_exe.as_posix()}', - f'{cmdlet_project.as_posix()}', - f'-run=OPGenerateProject', - f'{project_file.resolve().as_posix()}'] + commandlet_cmd = [ + f"{ue_editor_exe.as_posix()}", + f"{cmdlet_project.as_posix()}", + "-run=OPGenerateProject", + f"{project_file.resolve().as_posix()}", + ] if self.dev_mode: - commandlet_cmd.append('-GenerateCode') + commandlet_cmd.append("-GenerateCode") gen_process = subprocess.Popen(commandlet_cmd, stdout=subprocess.PIPE, @@ -103,24 +106,27 @@ def run(self): for line in gen_process.stdout: decoded_line = line.decode(errors="replace") - print(decoded_line, end='') + print(decoded_line, end="") self.log.emit(decoded_line) gen_process.stdout.close() return_code = gen_process.wait() if return_code and return_code != 0: - msg = 'Failed to generate ' + self.project_name \ - + f' project! Exited with return code {return_code}' + msg = ( + f"Failed to generate {self.project_name} " + f"project! Exited with return code {return_code}" + ) self.failed.emit(msg, return_code) raise RuntimeError(msg) print("--- Project has been generated successfully.") - self.stage_begin.emit(f'Writing the Engine ID of the build UE ... 1' - f' out of {stage_count}') + self.stage_begin.emit( + (f"Writing the Engine ID of the build UE ... 1" + f" out of {stage_count}")) if not project_file.is_file(): - msg = "Failed to write the Engine ID into .uproject file! Can " \ - "not read!" + msg = ("Failed to write the Engine ID into .uproject file! Can " + "not read!") self.failed.emit(msg) raise RuntimeError(msg) @@ -134,13 +140,14 @@ def run(self): pf.seek(0) json.dump(pf_json, pf, indent=4) pf.truncate() - print(f'--- Engine ID has been written into the project file') + print("--- Engine ID has been written into the project file") self.progress.emit(90) if self.dev_mode: # 2nd stage - self.stage_begin.emit(f'Generating project files ... 2 out of ' - f'{stage_count}') + self.stage_begin.emit( + (f"Generating project files ... 2 out of " + f"{stage_count}")) self.progress.emit(0) ubt_path = ue_lib.get_path_to_ubt(self.engine_path, @@ -163,8 +170,8 @@ def run(self): stdout=subprocess.PIPE, stderr=subprocess.PIPE) for line in gen_proc.stdout: - decoded_line: str = line.decode(errors='replace') - print(decoded_line, end='') + decoded_line: str = line.decode(errors="replace") + print(decoded_line, end="") self.log.emit(decoded_line) parse_prj_progress(decoded_line, self.progress) @@ -172,13 +179,13 @@ def run(self): return_code = gen_proc.wait() if return_code and return_code != 0: - msg = 'Failed to generate project files! ' \ - f'Exited with return code {return_code}' + msg = ("Failed to generate project files! " + f"Exited with return code {return_code}") self.failed.emit(msg, return_code) raise RuntimeError(msg) - self.stage_begin.emit(f'Building the project ... 3 out of ' - f'{stage_count}') + self.stage_begin.emit( + f"Building the project ... 3 out of {stage_count}") self.progress.emit(0) # 3rd stage build_prj_cmd = [ubt_path.as_posix(), @@ -186,16 +193,16 @@ def run(self): arch, "Development", "-TargetType=Editor", - f'-Project={project_file}', - f'{project_file}', + f"-Project={project_file}", + f"{project_file}", "-IgnoreJunk"] build_prj_proc = subprocess.Popen(build_prj_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) for line in build_prj_proc.stdout: - decoded_line: str = line.decode(errors='replace') - print(decoded_line, end='') + decoded_line: str = line.decode(errors="replace") + print(decoded_line, end="") self.log.emit(decoded_line) parse_comp_progress(decoded_line, self.progress) @@ -203,16 +210,17 @@ def run(self): return_code = build_prj_proc.wait() if return_code and return_code != 0: - msg = 'Failed to build project! ' \ - f'Exited with return code {return_code}' + msg = ("Failed to build project! " + f"Exited with return code {return_code}") self.failed.emit(msg, return_code) raise RuntimeError(msg) # ensure we have PySide2 installed in engine self.progress.emit(0) - self.stage_begin.emit(f'Checking PySide2 installation... {stage_count}' - f' out of {stage_count}') + self.stage_begin.emit( + (f"Checking PySide2 installation... {stage_count} " + f" out of {stage_count}")) python_path = None if platform.system().lower() == "windows": python_path = self.engine_path / ("Engine/Binaries/ThirdParty/" @@ -245,16 +253,16 @@ def run(self): stderr=subprocess.PIPE) for line in pyside_install.stdout: - decoded_line: str = line.decode(errors='replace') - print(decoded_line, end='') + decoded_line: str = line.decode(errors="replace") + print(decoded_line, end="") self.log.emit(decoded_line) pyside_install.stdout.close() return_code = pyside_install.wait() if return_code and return_code != 0: - msg = 'Failed to create the project! ' \ - f'The installation of PySide2 has failed!' + msg = ("Failed to create the project! " + "The installation of PySide2 has failed!") self.failed.emit(msg, return_code) raise RuntimeError(msg) @@ -296,18 +304,18 @@ def _build_and_move_plugin(self, plugin_build_path: Path): # in order to successfully build the plugin, # It must be built outside the Engine directory and then moved - build_plugin_cmd: List[str] = [f'{uat_path.as_posix()}', - 'BuildPlugin', - f'-Plugin={uplugin_path.as_posix()}', - f'-Package={temp_dir.as_posix()}'] + build_plugin_cmd: List[str] = [f"{uat_path.as_posix()}", + "BuildPlugin", + f"-Plugin={uplugin_path.as_posix()}", + f"-Package={temp_dir.as_posix()}"] build_proc = subprocess.Popen(build_plugin_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - return_code: int = None + return_code: Union[None, int] = None for line in build_proc.stdout: - decoded_line: str = line.decode(errors='replace') - print(decoded_line, end='') + decoded_line: str = line.decode(errors="replace") + print(decoded_line, end="") self.log.emit(decoded_line) if return_code is None: return_code = retrieve_exit_code(decoded_line) @@ -317,8 +325,8 @@ def _build_and_move_plugin(self, plugin_build_path: Path): build_proc.wait() if return_code and return_code != 0: - msg = 'Failed to build plugin' \ - f' project! Exited with return code {return_code}' + msg = ("Failed to build plugin" + f" project! Exited with return code {return_code}") dir_util.remove_tree(temp_dir.as_posix()) self.failed.emit(msg, return_code) raise RuntimeError(msg) diff --git a/openpype/widgets/splash_screen.py b/openpype/widgets/splash_screen.py index 6bb0944c469..7c1ff72ecd3 100644 --- a/openpype/widgets/splash_screen.py +++ b/openpype/widgets/splash_screen.py @@ -49,9 +49,7 @@ def __init__(self, self.init_ui() def was_proc_successful(self) -> bool: - if self.thread_return_code == 0: - return True - return False + return self.thread_return_code == 0 def start_thread(self, q_thread: QtCore.QThread): """Saves the reference to this thread and starts it. From 6433b1f270420f84a8742467dc34a51b71996e92 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 21 Mar 2023 16:52:13 +0100 Subject: [PATCH 590/898] Render only the local saver tools instead of all active savers in the comp --- .../plugins/publish/extract_render_local.py | 63 ++++++++++++++++--- 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/fusion/plugins/publish/extract_render_local.py b/openpype/hosts/fusion/plugins/publish/extract_render_local.py index 16a582032f1..5a0140c5258 100644 --- a/openpype/hosts/fusion/plugins/publish/extract_render_local.py +++ b/openpype/hosts/fusion/plugins/publish/extract_render_local.py @@ -1,7 +1,43 @@ +import logging +import contextlib import pyblish.api from openpype.hosts.fusion.api import comp_lock_and_undo_chunk +log = logging.getLogger(__name__) + + +@contextlib.contextmanager +def enabled_savers(comp, savers): + """Enable only the `savers` in Comp during the context. + + Any Saver tool in the passed composition that is not in the savers list + will be set to passthrough during the context. + + Args: + comp (object): Fusion composition object. + savers (list): List of Saver tool objects. + + """ + passthrough_key = "TOOLB_PassThrough" + original_states = {} + enabled_save_names = {saver.Name for saver in savers} + try: + all_savers = comp.GetToolList(False, "Saver").values() + for saver in all_savers: + original_state = saver.GetAttrs()[passthrough_key] + original_states[saver] = original_state + + # The passthrough state we want to set (passthrough != enabled) + state = saver.Name not in enabled_save_names + if state != original_state: + saver.SetAttrs({passthrough_key: state}) + yield + finally: + for saver, original_state in original_states.items(): + saver.SetAttrs({"TOOLB_PassThrough": original_state}) + + class FusionRenderLocal(pyblish.api.InstancePlugin): """Render the current Fusion composition locally.""" @@ -32,6 +68,16 @@ def render_once(self, context): # to speed up the rendering. The check below makes sure that we only # execute the rendering once and not for each instance. key = f"__hasRun{self.__class__.__name__}" + + savers_to_render = [ + # Get the saver tool from the instance + instance[0] for instance in context if + # Only active instances + instance.data.get("publish", True) and + # Only render.local instances + "render.local" in instance.data["families"] + ] + if key not in context.data: # We initialize as false to indicate it wasn't successful yet # so we can keep track of whether Fusion succeeded @@ -44,15 +90,18 @@ def render_once(self, context): self.log.info("Starting Fusion render") self.log.info(f"Start frame: {frame_start}") self.log.info(f"End frame: {frame_end}") + saver_names = ", ".join(saver.Name for saver in savers_to_render) + self.log.info(f"Rendering tools: {saver_names}") with comp_lock_and_undo_chunk(current_comp): - result = current_comp.Render( - { - "Start": frame_start, - "End": frame_end, - "Wait": True, - } - ) + with enabled_savers(current_comp, savers_to_render): + result = current_comp.Render( + { + "Start": frame_start, + "End": frame_end, + "Wait": True, + } + ) context.data[key] = bool(result) From 25f7478955e75d852095236ce6a9b21c6a5d9a9d Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 21 Mar 2023 17:02:31 +0100 Subject: [PATCH 591/898] Remove unused functions (#4671) --- .../maya/plugins/publish/extract_look.py | 30 ------------------- 1 file changed, 30 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index bc506b7feb1..447c9a615cc 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -30,36 +30,6 @@ def _has_arnold(): return False -def escape_space(path): - """Ensure path is enclosed by quotes to allow paths with spaces""" - return '"{}"'.format(path) if " " in path else path - - -def get_ocio_config_path(profile_folder): - """Path to OpenPype vendorized OCIO. - - Vendorized OCIO config file path is grabbed from the specific path - hierarchy specified below. - - "{OPENPYPE_ROOT}/vendor/OpenColorIO-Configs/{profile_folder}/config.ocio" - Args: - profile_folder (str): Name of folder to grab config file from. - - Returns: - str: Path to vendorized config file. - """ - - return os.path.join( - os.environ["OPENPYPE_ROOT"], - "vendor", - "bin", - "ocioconfig", - "OpenColorIOConfigs", - profile_folder, - "config.ocio" - ) - - def find_paths_by_hash(texture_hash): """Find the texture hash key in the dictionary. From 41d6269471f7f99c6323377fc6406ba1a0dfa59e Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Mar 2023 17:11:45 +0100 Subject: [PATCH 592/898] nuke: load nukenodes family timelessly --- .../hosts/nuke/plugins/load/load_backdrop.py | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/openpype/hosts/nuke/plugins/load/load_backdrop.py b/openpype/hosts/nuke/plugins/load/load_backdrop.py index f227aa161ab..67c7877e609 100644 --- a/openpype/hosts/nuke/plugins/load/load_backdrop.py +++ b/openpype/hosts/nuke/plugins/load/load_backdrop.py @@ -54,22 +54,19 @@ def load(self, context, name, namespace, data): version = context['version'] version_data = version.get("data", {}) vname = version.get("name", None) - first = version_data.get("frameStart", None) - last = version_data.get("frameEnd", None) namespace = namespace or context['asset']['name'] colorspace = version_data.get("colorspace", None) object_name = "{}_{}".format(name, namespace) # prepare data for imprinting # add additional metadata from the version to imprint to Avalon knob - add_keys = ["frameStart", "frameEnd", "handleStart", "handleEnd", - "source", "author", "fps"] + add_keys = ["source", "author", "fps"] - data_imprint = {"frameStart": first, - "frameEnd": last, - "version": vname, - "colorspaceInput": colorspace, - "objectName": object_name} + data_imprint = { + "version": vname, + "colorspaceInput": colorspace, + "objectName": object_name + } for k in add_keys: data_imprint.update({k: version_data[k]}) @@ -204,18 +201,13 @@ def update(self, container, representation): name = container['name'] version_data = version_doc.get("data", {}) vname = version_doc.get("name", None) - first = version_data.get("frameStart", None) - last = version_data.get("frameEnd", None) namespace = container['namespace'] colorspace = version_data.get("colorspace", None) object_name = "{}_{}".format(name, namespace) - add_keys = ["frameStart", "frameEnd", "handleStart", "handleEnd", - "source", "author", "fps"] + add_keys = ["source", "author", "fps"] data_imprint = {"representation": str(representation["_id"]), - "frameStart": first, - "frameEnd": last, "version": vname, "colorspaceInput": colorspace, "objectName": object_name} From 5ca5498b03bb1a88564b43e09fa4e660111614ec Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Tue, 21 Mar 2023 17:33:50 +0100 Subject: [PATCH 593/898] Changed family requirement check based on discussions --- .../plugins/publish/integrate_kitsu_note.py | 81 ++++++------------- 1 file changed, 24 insertions(+), 57 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 0bb2a63feab..366e70934f2 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -53,12 +53,8 @@ def process(self, context): continue kitsu_task = instance.data.get("kitsu_task") - if kitsu_task is None: + if not kitsu_task: continue - # Get comment text body - publish_comment = context.data.get("comment") - if not publish_comment: - self.log.info("Comment is not set.") # Get note status, by default uses the task status for the note # if it is not specified in the configuration @@ -74,57 +70,31 @@ def process(self, context): allow_status_change = False break - if self.set_status_note and allow_status_change: - kitsu_status = gazu.task.get_task_status_by_short_name( - self.note_status_shortname - families = { - instance.data.get("kitsu_task") - for instance in context - if instance.data.get("publish") - } + if allow_status_change: + # Get families + families = { + instance.data.get("kitsu_task") + for instance in context + if instance.data.get("publish") + } + + # Check if any family requirement is met + for family_requirement in self.family_requirements: + condition = family_requirement["condition"] == "equal" + + for family in families: + match = ( + family_requirement["short_name"].lower() == family + ) + if match and not condition or condition and not match: + allow_status_change = True + break - for instance in context: - kitsu_task = instance.data.get("kitsu_task") - if not kitsu_task: - continue + if allow_status_change: + break - # Get note status, by default uses the task status for the note - # if it is not specified in the configuration - kitsu_task = context.data["kitsu_task"] - shortname = kitsu_task["task_status"]["short_name"].upper() - note_status = kitsu_task["task_status_id"] - if ( - self.set_status_note - and next( - ( - False - for status_except in self.status_exceptions - if shortname == status_except["short_name"].upper() - and status_except["condition"] == "equal" - or shortname != status_except["short_name"].upper() - and status_except["condition"] == "not_equal" - ), - True, - ) - and next( - ( - True - for family in families - if next( - ( - False - for family_req in self.family_requirements - if family_req["condition"] == "equal" - and family_req["family"].lower() != family - or family_req["condition"] == "not_equal" - and family_req["family"].lower() == family - ), - True, - ) - ), - False, - ) - ): + # Set note status + if self.set_status_note and allow_status_change: kitsu_status = gazu.task.get_task_status_by_short_name( self.note_status_shortname ) @@ -153,9 +123,6 @@ def process(self, context): ) kitsu_comment = gazu.task.add_comment( kitsu_task, note_status, comment=publish_comment - instance.data["kitsu_task"], - note_status, - comment=publish_comment, ) instance.data["kitsu_comment"] = kitsu_comment From 109435fee281acd7be8bd2f2a67573e4221e8761 Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Tue, 21 Mar 2023 17:48:01 +0100 Subject: [PATCH 594/898] Fixed kitsu project settings schema, updated documentation screenshot --- .../projects_schema/schema_project_kitsu.json | 1 - .../assets/integrate_kitsu_note_settings.png | Bin 44847 -> 46673 bytes 2 files changed, 1 deletion(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index ba77f2b4718..0a3a5e6e7b2 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -127,7 +127,6 @@ "label": "Custom comment" } ] - } } ] } diff --git a/website/docs/assets/integrate_kitsu_note_settings.png b/website/docs/assets/integrate_kitsu_note_settings.png index fd055942d023e2ffc12fc508cd7079eb834045c3..6f76556afa54b4a1cd946ffb78d200ec3cd3e3b1 100644 GIT binary patch literal 46673 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%0D3V?)tF)Lx2^;H(ZQbbO&WO=KC?o7RUlAm zZ6H(@@r6VL8l2bD*xD{lQ9YTkeAM}+IC^wB6`S7a!NZRnovKT(lHQPK$g72f5R|}i zZ41Zrfq(6@3x|it?Y+i5$A$cdwSEdI&S)_272JLB`Jv%!nonKL?I3VagP-4y^41Wu(C2ZR5f4>$)Xbn2Q4|zWq?peMMT>O?GT#)6#QE)1F$<%&+?Hs@PqetG?XnN((T zADtOHadon>Tb$|Yn}f$s^F%mG!!YUNl+>4J;!*|TDQrgK_LV&DGCPUZdmI}@3=1UH ziKJbQPnMXh9EV0eUaw>N`2dKg96l%)L{toqpR&+~Et|C~cQICF2)mdp=J z)$Nn)djjMoIXwPU^^jrru0p}?#j#|jrU3B`>4o-3j~I(wz`0}X19wUbBP_e2)JkVt z&2I?h*k~v5vjC%Am`i5$j3gzsH=rjv_g9z8TsntamvyRajJifR!-zTk=^^gl+Y`se z##%$m#ohWPiAp^N>C%BK0IlYL4R8~>lCytBeZGED`NE>+p{_GCU;pG8p>b-k&%E~9 z#xIu9P4uFoX;OZBWUiZI_x`!OI6pq1##1rS=ykKN%_~Jogc6o=bC`^57^V)n0Nq=JEh)}OLW3N4z0>>Coyk}pb#L( z1*qh~BNl%C1Z@LWVb=`{)As?6^R2TS?_B-VolkUqd_>oW3r!Cp1zN?9hW>vUU5AQoRh59yB+7N2|>(1$=*?ZEwRQgNvf=hvsI8_dOdyU`)% zCB+bP17-{D;*qz@e@<>0jk$e#=kA?Xo>1EKCxO(Hj{Emq-?PLS_UI11n5co&sUN{;&>d7oN-6dC=ClxJ#mEKskkHP&Jf;2{`(!aA zPVdCVsrOS0icRFDI*$PztG{PSWSbCN=X~uOrY*h|kb@$V;;E*)PR=`o6@bPJ}l*5oZUwgUlACDtC-2eiD$S1kgW^s$gmBIjXZ!Z?a6F&;Q7TZ``~`g`{9vE-<7UY3f}_|G^u=c_ zmsmv`1*WDQ4yB~dT#8FM8x5W(nEX#`%K@IXhUFyxo2z{&0Mvd891xCo-@ zaPvXquHCcN%0!&r$M4AGhql~4|Ir^jnoz5b{Nsa~%`MDw9Wr${pLjd>sET)7Jdvv! zaRjGkzcWtf*zU&p!7%b8{j+cmJ=NZ`7Z2?xLd$uGn3-_L2@oUX(wC%9MqwcBUE6|O zcc!9azoR|3IkD<5|DcrIb0*)N3FFPO2!0m#d4@3Xd+aoN9xh4hcj@FHm`c;IE&5>C z#83siZcW2dM-^O^#VJ2IL-M=eoGjf%!Px6*Ug9b7#o4lj|a9?OHMVO&&cd$crOjqa!o#y&DbM4H`$f@=PMKPGunUM1yBLJ z_d4J?bECHwt3%QFjt!RFDQS|iHT)cSL`gRfi$yg9*^2lBp!ih^xSK0h9sQ>4OHs7#6`TCMx{HQF=oJ-zNzwL0u6ybAEy=1kAiFs&S?{+*r z$%kE!NUBq;cl29l6t+tY18TSL%HK+#db-(!-!U8znU zqciXxLb0K{y9P74BL3^!ThJPW+Wct6-QHoM9r;r>1krio5x*bS2U{)HOL^W!O-|8d zkw-0uzY9dhjz-1A%p)$}r8wrZS3ermc?X1;*9`wmejXiy@ScC#*<>sg^j;)({hZ}D zaXaH5;kWv!Bh!%{y%E7mB62wk1DeJgt6DO#Ixd<_&7N3y2AVzvVLqW-G zw=J7Xa4JU{rGZpZpvgCm(!TUWQ@be-XrASM&WR#{*!+A)wX$)V~;EK{^nWBLBv1<6&{hg`z4TGT<#DFR3C0H47XRjp_7NV3=d*KN44b|GQgw2cSq_=rZ;Th8X zX7?)T7D$(q-A?y<-IJLL2m0r^F>yEZb5cKZIexiRrMEi?@f4w5&g)x9(r zjxSPb=dUyA!ZYM(XQ{Y`7wUBXXkAS%JuQE|D55Wd`iZ3qgXwc#{36;!zT2G?fm$kW z-w%VoyI$;NwM9(r-tH;W#n||x32dU{vYl<^`8$W%KqANX0@-R5z4*hwAPsz95dbvW z1VF}EB*1$DKcx^MgS05=ykd9}5YHx$vf8S*4Hrk^CBNk`b%^=ZPc&XP2%uU{-?JmS z-guF!PyG5`qAbTZ{+NmlASh{A{qoeig+}z}sWb0+Zu6asR!Cv)8!PDao98~yDpzUd zVhZ2byORbt%{CU79V^U@p4`4l=g*M%<@uizUHsZS7N{{^?=)X7&0mnCF38!a;phbVY6XIwAgPo5kA z6fL6&2&78do*Qe3PZ>kjw9tm}i!u9=Iwcfr`Rw)hsIKuZItO*FVvYS8PcOHM9gaG- z<&uNlTG7((i)5?R0eR> z@Y&mCG-?M!AV0+~AdMj9^>f?1>2kfV7(P7No*g|SzxWtaI+5P$tEAQGI27w|iyu{< zu4qh!@wznclPC6btMyPI3*{ElSRu#LdaAC{o6j~WuED(^0vfC36hmTQ`IZ~=9g{)p z7JL|63U0y>QF3xe+vGNAnPj0@nGH9opC~vGeWc6e7Y2Z#}_$q5lNQ5|FQ`LU; zt6Mg~qj~PrHLG+}0Qu5-`8JIBm6a9K9ZZ~sY$5|1Vr*q4rJv*W4Tubny}dm_=at78 zn0S;~1r=fGd3k9aO4mhzwwrg9v}7jqsyfkL$SwTM(wpPE@-CH(2-0Uaq;6Q3d1cHw z1qL<(8yKiGH@nVHjLN?5CCBZ9f0}oyVS zOCygV;$l6b;g<8Lv6}^OxonpZslmY}E&mD~5(!0K4foHPWmo_Qs$Z^zA0cpSW%cZyE zhF9d+4$@GP)>t@oD53_7S~IfFus7iZSLplq@BS+*7B8u(fq>K2#=nY>^@*d~q%IYh zKdB!jpAE5i{XA~E&!N^<&8gj1!!l*PKB`?o_sXCP*g4;o_J9&CO1;LZ>gi>%)PsFW z$rku!BD*&TCphe$#Zr74I62%!idBn1~N7<&N@v5t~32qM_r*lQ1fImdU?ce}hLCkcC`yUAh*fw$AvL~B((4hh#MstI3V`N7{BI-SV~>qK!s zF{FVwUd~{9r0NVh&$@Za_fS*h@q5>>e$L%SJ=DE8ldv<(D&@T1THCyv=M}pn*a7~tV z>?32N-I+j8_=(S9Dl4(tm1SdadKRU!mlBmbR!h51Pxu#zs2LryGkM{1riih)SmXk~ z-`(9EUq(w!&1!h^&NxvhqHmq6#AbR8qmw&sU1F0P+tg=p$*{kCpF1%HvK&JE;GRZd zZ@dg`M5audljwa(9gk|QsHq6t*L=+G!BE7ir()^u*_4M6jYkV+s;sFW#5dZa+hy~@Ka;SD7MJ-lP@ekfz!tN>JlSNpvp@~gUdo6JXZ_Z>xMf2JTELF zw>N(i$8eU1q38Fv1ac>)ufC0!jwMw`T)ZZQ&P94XOPP-2t2R8!Q$BYXb(IJ6Y#e+t zA&voqIjv#t*dZTp!>m08DH}Lnn6svvRR!5TkWus3TS<|+**4gut*5viBzo~}$+Arj zd#zQo@u)kODZEL8ERlD^-p|QpB=ePyA8l#Mt_27EvPop3#qX{0ZoFKT%|Eu|yf{VD z7{{n`S-9We1xqqC**3FvEURaoNc%}J-~cj0d8ie3gWC-1-$-RZ!X=3WHd7i15^M3c z<`9b`X~+s>aaF-(^%S3%a5J`-l&{LO8GUhinX`I3t9CR31S2GwI*pebecd1S-B%LL z3K3_A@ii`ypW>jEaM1^O!q4nxQKM#$I^Ksx>x+-F-gRipKePB}&!glb(xMP ziCPp3KLzXS>kMDL#N73J^Ey4XO$4@3Ow!f_S`%>r@X~ zZG<~eFB(Gl`bdntavZ`!vRQ*dd7c(V_`>{sgh_rrEqZH{bs~4+oV6~2Xepo>Wpk{l zY!k=ExIr;ojd{cTJcYb#hNBzWjnBYZ)g}w`D=8^aK99}#lDphLms4%W(l^rc0u&Vk zE|1G)WWv?KCT)vF_!}QRc0Q;uI^#V$sYGefXeGH`8 zX!0qHm!_r zBTX23=ErH1n^4rI4(cbXR^2M~d<5N$9SXRA0(_Emr+r#5Wt-h~?}|*wl=Wu&6j?lA zv7AR@L5r?Gx*t7k?Q&Ey8f|;X0X3Xzd+1)|pb^tnY!L)Yaf!dj<$?bZyf~BGd=HSi zMegBYrS$ZJjS@b8d3jfPP5ZJ*1M$()yhk&3jbgexI2$YJ)|r$y6Ga=YR!6SVEGDvf zif?T6sw<@yL79pju%_Y8 z%!Q==X9WPCD!wEPjvoP`<&9Y>BqZ@7(F=wIR)@{09V3O0TR^eO++Z@kXyo0?=m|23 zkctGxN8|Y>VZ$SIxCvp4%4_*F7L3J)CY>*41)>6!h25RBlW4m3;YI& z(MmHZ;Gyp)IpARoUJUG#W^{co?N6Px9-Nk$u1{unJL+~`krcz`2~myqsmzHl^~InT zVlEu^w9sPWbU3SaFXICa(-xK!}Zy3{ktK1TF9Hp|xHP25Btv;Tl!S~UXG zYGRwltY!rdUPV+ajA{)l;S%^tT-`zBmjB(bV8KYprFR#(#BQv%cGdFxma430IB?MH z2HVLDt|o>o);qH@5LW9QUGPJZldSR>FzE+qiNR^Q{{U#=EUYL;^V?oBwP%)^mGMJm ziZ9NL?Rm9Dp=iK|k5^eblx|K}Co9g0r{4n`L0oC3)anrVd{grm9=C3s=!P@fF@s+* zCU0ohoa3*p#qwzJ zFh)mzo+l!XbD_>LiJT)zCZmr#EC4383@%U*Jn$6|6^rci!Ui$F7H7(h4gQMDdLk4P z)uX~m=YYA&)CNeN5r^Cqk9Om(%6RL%?wIix`3gYMro%ANQ1V zxd+9Lsn#hCpSW{KpZ!cfFx)#Z)pTvgy`GQZZFp_pd66Ft7B}E!5+#qunM@hJQCjQn4q8$yu6|l&q%od`+K`=Q>A5RXa12^ed=*5Qw8!4tjl|qOzg)lI*Lld?ZCEa?oM2E1ig(feI#9gk-vD31bEC zDKIRlY#}JXk|=SY!~nD?zB<)O{8@bs>&S!Y6y9Bposm!F5)3&XOd`Ex@;cg20e+!# zA0jY%vN0z{*1YLxvn_DUDOh_@B3XTsD(MUl8Ld8zPLS}I)dg(Q#d5gV$uftXT9xk8 z3L}N>!px$gua%dlc-!^I+ZeE0uc@PT@3b0c5mw@{-w}bgV0i2QzQjiPa0l6DHJn)T zC*T=G!%}`{dXD+D)x%Lq8c^ILmgfYH&#CHMX%U7?x0)GxXjjQAb@?~|0{C&Zch!+pd(W@% zu3zEj6;eqXJi||Xfq~VHnE;xnC{aQD?;*&layE)uM|R*7L;T_EyT=J4ha1S^?sJ?Z zJu$ADx>PM8 z#k;l8W(Q|3(eD`MwOXdtwv}_d@#r7Hv=caRsP5Jyu-p~Y^mEc1!xQyD?{D$&o{zVz z4er-O`GJ68^$=jrA|zvD*0K>6bC-swKOoC{$3kE|VPTz*a%2}os<-@@Va-U#+H=~e`3=^-r?Ykk6E@2<^I%8YiC|#YbWOh3;bl@hx&D|nifk>Gx zQcpv~urLEGv%9N0W(*|bj2qZ5KF}9U|53G+T}TrBQKeYK*c<=NfK--X=BR)&0nc)u zD@jp%_faz7XsWjbiY#)N8_wHyqkaAuOIo8#q^#g+y5!zX zD1mia0+M8&FW%S##ry&+J+?L{9!RbjPrq^oXXPzffaZf?v-~xf01^jw8^`*9)<2mMM>en>u8D{eX@8QxG4bu=ia^0?GJaYJxcCv zFZv9j*M0>!tnQ?0mxqlao-WcFAHR;VF%8$0H6q9dzvt8hw)zq8b@%ibT%7C%6A8p` zPF7U%cKVUK|6=y4&QfR$yWRAW0_lahpr>x#a@n z4_`EPy@6?|LEl;`&FP&s#w&*i2!OvhyL!~>QUEyO*uW@1wa)26k_AE_pbj(paJa;vvp7i;SfIh> z#p%I1H0*q}rI ze0me0QDhQK+x-6p4F6AsM7@&qBHC|C9_PT_;`Lv2J=>V?G*o1jqQYK2A=t97 z@c~AW$y(X-#?=)wFtCTNa0eR&JlNm$O4qaLIA_bVnv^UoA#raee!@D_egFt7Y>C#R zX1>gSvvqH%`G0sgbW2 zdZ}iL3r3|isaqlwI1bb9g@E)1AgZ`sZz3|1hYojA1;XcK7SadhIKl@bP2+0@vw~EU zsd6%=rL2Ds{qv#Iz4dN9Tk~)bp!s8QJEl?+pv>_jYQIbeA|P?%oJ{Cl2fS9Uce;6Nb8sG0S|{T2157&Ul1NonAh4T)p}k~zLk7? z3Zg+jKHMAYen<)IJY4zSps#|>u$8qk37{wHsf74a#+1V5p8r~lJ^@q^!66625N5n@ z?(U{z>rj9z{|5|=7SPIauG1I!;azgnl;n>GQzo{;pOI7?t^yV$)8i) zM%xcQzH?`;gL$OrhP~o;#}(Pq`a|V8enA_c2FKsXa{kcYa7PONQqTaXI_^L^+Cw&h zTm8J+!ZpXc=GWU47~HI858Q~XZZr(>okz14H$BQuCMIp{vJZLKKUx4zw6qzq1LQ)i zYA2)22I9=sMLuYCKGz7;_R?p2WE1*=i~w;mR-Mo z&1MRn6J}>;^B*1zMn*^5LS;Q|TTb*^eQkR3E5FUqCk+f>C%doFIT{<^{TdzJu~`Z2 zpKUgg)0XR>H%VFYbDC;yxrd72e0VtOymN^>*68JBz|?qo*xH-mM2hg3R(eqbTJs6C zU1XS?PpX_*4&j;s_xI#_5N&g6U}BY(V@E<><}Rf6G=Jnc0RKixi1{(CrfS@gp3~>$ z!~_0>8? z{O22N7dxSR{=xqIKLnUKL*F!>QPV3I=r*J8yUaG9SMQ{vRv!#VUei3X7w~NyQpWk^ zZO_W_R5?v|k}G(S&dzd)k){`%Kbk?UMb_&~VgB(vE83Uyt=g2SI(|HcSjZPl{w9u5 z?a3b(VR&RqVO}SQTuhq33i06I?xErX>SG{#Tlm_$Eh-Ml+W^kU;F{&YBXm$g@aFI8 ztI$X$Bk&{_Z5lo4&11UT`iYd#Z9`4E3;+JTV)Vxde7sn#I)l!6`FigAZ*q=`^j&9n zJoV}<3|u9PQy0SewiyL1-yuxuIX+KbWml`VrS|dh>D8&4^*)k_ppjElZCg85F;K(v z5kpa{IFM$lS($h2^Xlh;Ss$#(flw5=slsCN86%_7#+XfdM#c;4-!HXYci((&egYa0 z*TF|LNV|oEgi=8Fs5=0RdDZ>4XC*Fv;s?)-x0Z3}#1Bwp|L|69SS0-o2$6dC+}Hg2 z+p2ALA8v|T+^gUt>e)19xb&WvZ?1^P2{NCwbi9OgP8K`}ekt(Vn!muP4>HJ|QbAkelu!-hx;|gK}OmlZ#VXuX!-qZ0n1 z+F#R?&i^Up9Ji;lw=8 zeJ&yOmg?!#JAMmoUZGr8<5JKD4`8D~EYgobM%wfVF(BAK9iSF_f zis53c@o+s+5Dg(h|2Vj62(+~!77rf=3^|+q>ghq$ZSfAEqM>m-J^mX$aT+XEW#?b% z%uv|ACE|XP^d$wyn=fQgxa$~7wN|{J!0-0{4~24}XUgz)p{0BDw{I;vWL}B+AZR~_ zUXi_bju_9coE8PQmYtVpc)GV#cL?#)pXBt_vxaFoy#VPY9V6XR0pB+N)1zz3e#@z` z=X>*)hxcAzXLO)}i*R{m{K3Hta7^ScteakTclW4P>)(SW@>TBUe|YVSHiujZ4IO0P z9Udt$J|tR(q(BZwA+4+SduilXu~@BQ@8s2ml}9Y^qY*R>a7CB69b0al?S?%AA4;yn zO+$O*g`cngPcVNgx$oQjv8Jw?5JUdzZFy)CebN9_n_+T5Tkpi1))Cyiu*+_mn+-{x=4gBBCA6NYjH}y~2w2qLabrtO{FXaOL?c}^d!+)_M)5RkRu3J(x zvMJr45=l4_f|VQvwUH}>yM)PJyloacac z8VJVHA?}*HxR8N|du`2L!b$oeCT*jlzKp*1=uUDN&2*@&Xz&QSn{mmwW)wf|TXn)s zjcd=qTU-6-?BB2_?*fG_NoG&iy;7#RLa-yQ!xPcH1e=vBNGxZnK5au?XvYDCktl0n z6@2ub&exvwxH)9#IKg{6`S_m{%3fZZwzK*;4>(65Y#VEX1dm#S{FvlFDP4n^djtE- z?yCe~Qmo;hiGTI=S?o4Y0z@}-uu#VfaLDB@_Z|AnNAK*c1uz{&LmUxZz5F$3;jW9t=J#EBRn|UAx{iH|G z7ut2XV&IELJfRQHu?Qfc<>U;VpHF2!6v?HQl`_I7n29aGsgE2;rwgyVm@M!OyN#o8VOkR%6zf3vENfHe){Jv~Yxzb|{HnVx1 z^Fb~)x4C;E$sBfdd29?l`m1JEx@w$u1qnTg>&yCTMe;$z+AI*{Xa&A{+9@ z%4jCIJYW1Z<|X6cfJ;XwP`iPV8X1|4gHO77L@;p3K<|A#wT(rp*WXrC4bWpCrL7cz)P8kR>~L5D*?wU#?W zxvoxAG?*k{)x5r- z=3rPw_3XoXXSY;l1Qw;(x0sm8?7wTi0(~ZzyuEr4GnQvviTxIPK_n0>Wi1_@_gre+ zk*;abGN>`gSFx`8_{t>7CoP1lq};ESozQ+n4Tr?iMJ#H(RHfs!4)3>Lrfnq*fNVU@t#gpU!P$KcUb3xrRgltZHHPE&i1MiZz&lfAvH)zs16zSnfAWi;3SJwC$e7C;bPB3xYdv~l zPj!-Uld={}Z>GwGrB&lIZp75qCD?^D%Jr#%`L8POK1;K@4_@gF2S!;ODP1#(%`d-> z>UahKs?T^Lcz?n{bQp+(I2ZV7lG);}FX%oYI3ggGIq%f7^*%)V3Zi2;dH%!POSDwhJ^^4q%} zw6nb5e9{_xC;q6+_fH3^Ih4f_@^yv=Q~x$$Fm9h?N+_*8rRi%ew~_c4HijZ|&iQ9D zVe9UPP0Mkx&nv4aeLbB+K9G`LSXa^X?R*?k*dbi0KI{ToR29WdwZESd4D~wEGeNTRxe26%jPfgqC?={>!zgj)O_`c<@2TDCo z50L}3uBf)cR19hbklfH)=LB3ji`I~(DPvy{IBktY;N5!6#oQde5m(~Td>T+Q1zdS> z0{f@*^o-86?(Vl;Gsmox73OB6OlizOB#@p2a3C{#N24!BZj8 zeDdRFY3Va>Y*z)=O&Z~3ve+4Y{Si1REIf>;LyQ{GY&3UQ(~6{Nu~N*bU0VmaFVJ!K zfunDBL5GrBV;lO=ZHf2v8fYE_$j=gtcRXw;FB zcQEh^WZ42dt{{(49s#_4iHnTpxgBBoLSw*YAkF-&D8+GJ6W;kf;?jBH)$h^Or`UZ>M z=`btg@=WG;LBYH{c-3%Kzio4}Q>>*1(zpc`%&R~%nD$`y)Qz1k=BDwDMEnQi$CRXU zO@#QXsri>a^IHqr?kF{7HFmjt=&|OfB|bIT*ff{h#AQkb)E2TWxlVWA39OU#mbe4B z9JQkL&7qIee3AAG{ATrjGH9u z0cG&DuCHs#YCuIKYYRgtCPuzARPS3*ai(k5x}EiJ%0=X&&Z4V@k5{asVa z9dlO<;XA<}F(J#a9n8ewr6UsJ#&c4@+ZiCO%~nxJNNQG3T9fwOZ-TGN1lJJdooFKv z+#$cIQ9w;=xNkBiC~PBL=_qQ#Pf4yi(jYP9n?Y zO29l_2nK&FEFS+0S)itns<6@Xc|NRIWwbbJLeb?Tn!m5$H%n}Xt1N}df|fU?*xS7% zUE`&_a+f7fcX0Z(@`K5_iw!4nn#iG;Yb2C&l8LK=ucnoUoSBz5p1z>&TMMO+bZBC^ z@yLc+o?2=AYZsTrr6pFQHN}wvwf&!Vw*?x)Nwx!SYSj=>wBhq)@_3a`&zW|$??E4g}4!JvCOP`omYah zh4@bfksl!44cWXF5I5KjN{6IugKQh9{(@TPW>bTh<^iEhh(NDWu()1o0tzW_mX8jo z$q7h&CH!zz6}TLuYVHfcy8?cX#EC@}NA@^7XosZ97XkOQ$d*$a)tD>3R+OM!P>*uko&OdunVs)0$-kM zLztpu^rM9V^>MqL+DELc?V-dJsGj|*QH<^C&lox7i34S?h}hU)lwp_m z5&Y(!(9rk_dYtWmMeq0=|7LW<3;uWJ?n($8Qc3C%b>(%z!(lXl`mk9%ibg4rJsVH? zjTYXWDE;O@qhm9t`S7jT@PFY`sWgRVRqXdjY4)({nb|6^(j+VFrVm=5c&$!$SJwc9GhS z_@{#~-My+J6Z7_BQ|)|@&lq_f!*lX`R!NfYCSttv&rRz0IjR%AEj<%bZ6LZ#^iA>y z0?p98Jf|y#xSk;Yivz;9elw!0MSRUW`hBvr;9Y+=wfqT-_Gkz;E2xeJN47*$OGXck zdu}j$HYZp$Gz0Em&B5ZVOrv@&r?~EPnb;)iFHUa&l(8&oGAr`+=5#I^2RmKPLvvDIJ26n$ccy+gSASaq-$V3Q zJriq$98uO@?3FC1V^yD2ax4$N^VMT9>DS=D&GovwdA_0i=y84|r>WTc^~dWI!F7V>SIrC; zCkBn2qannji;!Dqu}7&8*6@1mxWOEYC)56YO52a^lDkPAE>DkV+P(ROp8qzzr7{qr zglf*pNHH1pW{e7IZ!+WS3uPj}8gBlDzrT1ni0!emzfi-TG)Kw2A|sD4%sCF|LgjL@!H7l;xIj`55qScjJV`t_59P% z3WBKiM0c)v8F5mEH)`JbUg*b%ULP$fpYjX-rn|WZ@yBe~HM5(%fr01vkL#RxqUSeW zX5u^=c}e?(!j|a)Z&CDjL^Hbj4JOSrvL@>`Bwp&9K{XYQ-ca07bF*P^Eo;XMc?ovS zePyGc#I@6+MnCy}XD6zVtm||ZUmm{vOWNJR!!c}K;=O`tOytnmCO*)6Cx0@9#@B0&C&fKV~G4a4a$=xc*70-2vG>p~6l&62dc3z*- zKP05>L-9Wk6K)sXvy_oq_l*(?E4$?!2PhVoabIiO{2g(uaJ%6C|6q+j{96I_@V^yM z=lrX{-rryG-}uMuf2+`zXZ*JcZT0_iCEU98@c+3FxS2?4W+qN-KT3k2cI=hg1VyA@ zEh@^gn_d$KKW5I+?QW7x>AShCJ1Ddb-Ue`UbLjTZ)b;nzYqVbt&C?<#Dd#7~O#4(b zr2H<#yU&YjD(aXJlAg|8Vu$kVnf?5sE8;(-C{K@NrCzC;X#|d}rRCH9fxVZRLyP^n zEpmU#Wfx?&)}0vb_xZfHPO9VSG?h-GSC@RsY;1vCQ}{g$ADvtl1VM&KpUNKA_+Z8(^}EU+2lixC*Vjfo1);B-kzOHlJ*wDpsQY8_jO-joRD^ynv$tcT zmwHX7@#n^XMpo5(Btf%B%X`8tBaNY(E6Jj8W|;eeHIl-+6*T)>StSLGTE!<}Y)t&! z+{%>63x1@Z`IP2;^t#U0+Pf@Ea7!xl!yYAzZZ}QoAzIl_oo{xlGU*a`?qa1}VV#!< zEv)h1h54TsWqJg3slZWa?2PDMnXYGpmd>9Qv6&+0?)x($ZJCXo zn#v!suwU(RTuG1Bcwt8#QAb%Izk6{ckqWIPwsXNULbU97>~V*68yeKL(89BUQ74Db ze!`b+?nK8~8WnrIbtf#S8`V{T*N|5(h2Q7r&a* zt1I=rJLT9fU3z`QipVdCJ_gFPKGZmtC0RFFuoF?>o^yH5=AHk$_|| zEFH`KJtfU?7bz)OA-)-^^PN9n={{fQ3fP;4u6bdgGwL1J>L`Q4Yr6)a;b_qe`K%A2o?r-Od^`m09>jclX&m` zcx(`Q@(IncJs3nqowH&Z*0K@J+zrb$A3Oe;ODcE*0R5f?TuEjn* zC1*XYQw@kE$9i(8%dZ zm#+K6iCqu^b?cUQ;0xhoa@@Z@Ej_O6trX3<>N4T+{t=5qj5GD=1VeLMb}ua}6tE{6_Ez9SY92Bubcqp0}1H!!s9iCGL zJo=+vQrd-><#XD_!=V$ndSHqF+2X_QbLsD8S0PB-Iz9$HwX+t4g@TbCuq_tVH@D3{ zvhjQRWs5g1BKO2pka?p%a&M!E(Kzue@7--QYfmF@!I{hk2M0VskPvyLIN$s9!>+=t zgTfyVhJqm9)AHR@_YiC$L#VB0l9;}?r~zb5yIeR^T`0hmj=m{A;w>;k<;fvMWq&L@ zRF_rSn)^O;Y;m%jEOnkK9!HPdN4~2Ip9>ZKWFTKpmbEeWXq@r*V4Iq?L=ED==Jf(k zhO~;*(N!CUdvV_R?%}_`zJKevi)0itCB9ODxfXS+jRSp5f~&V^V1hdDaYho^cWQRk zzF0dDDLZA}FUc%ue++%70-G~AP-dBQ(%2EDRruq8CRmD_()F3EKtOOZU|#n3kG{xb zIBvstmZGs|>s-x+jpaMflGDj{Uhih5!m8MM&L^3z9ms?DexSxmoiI4^=QHu9v3eTP zb+^PP`P!|ZxmUbniQDn5Y2xc3Lrem)?kY zo}vAGZIxy}mZa-kyqx*Cc!S5f_QCWSQ@@^5xYvFz?TmZ{{B>i#dUGw_0tws<#nP29 zA{Xa8d|C;HJM1T5haVbZHBaIoB&td;MTUQLkne4jnfzz}>Y4kgT_i?z(nWS@vth@4 zFOB)M5WHe?xGmnz|9craj?^VGo(b7p?v>1LEL7K9RBx}Um~2vZB{YmUGUjjmIh2wu z27MY*Dkhl|8GMS4XTtPDW5#rV+vS*n;=|<^Rg^GxQxYC7hnpbxuGiNp+G65%6#<#v zI*mKe5>K#04@-+Z8Y?G`9Hy<%s*jmQ2tl|Cz8IxmV|HH3ou=gmxE8zYa@>Un;Bk= zrfmSU+{FsAun>lKpX#qRHU$wklqjIOE;hD$FoDB(L#UI>jGsq{n>pdt&ZUyKrC@c` zKzxMqVJQ~2^lH(h4eeo@Nip`pw6ZW)T|jjS&c_S7QeYopdxBiEA@6;DawilW7V5z- zi4p3;^KC+_@MSf{dX0R5*IULH^6EBk8L10qrusJUsq$mH=+eFVhrDHXIy{c z>!M9j^svmUWV{tjCgxsKZm+;_@!OC-)Y*R#f-h}DpSj+!0BY86_C=DVVy*=f-?`Dqgw_FLJPVOQqYX467 zX66+p;DNea(!zG-iH6w9B2$|TGV|Uzw$-6k3KSI7SUwYsW1$^{!3>#uv#mblyF-s< zzePKyB8+A$&|aQ&Ug_;EN+2AN|4soptIyb&Dq2c&V~l%uC;9rvnC6cmJ7i!`TBnwWl<#uYVP^ z>%N$4`0k`ctZ~L^-ie8zD^!B2@P>axXoi3~G_;G?3M3DY7M1@RgND5KaZBc)LW>T%r{3#b@EF8K$vCeDOp?lh7gZ%O zhRL3tyQ?O;5c~+I?Q~jB8t4jvn47+|kv)?buY7C30KLP<(^k*qe zEm8ex?&Graj6GrZqj%Q>da@8Aj*v2^!jQANkwSicZvHBEifOj(s49Ng)Awt39s(sl z+1`Lxm2QjMTh^}5RgE5^5B(Zer%5(Qzw?v7GO}<^N6e0%(jE#S6JBk~M*3NRT$tHk%-G&pv`n6ncO`w&tL*-2F7mjp zqT?uI51YT(VmB^dmlqC^`+cbtsbfniD$Xug8U;eJ8;oXCAa{FK3I`7ln~3PGwYBwd z`LAE%jhxz*_(4mH&ojYs$~h^uj+@<}uDB_Y$If|i&d=o_T+Es`NjjzK#yuxu;fCY@ z5vVw-fh_dxBFw90I)m2d@l{OSB=qO|DTcaYi#z_RMM1whs?V$2X24hA(V3##mpxcu}&aWT{nGQ5U{4I=g34nW#d@WD zJ6Qh|mmQ6AkWa~;ExSy@@_w?=&C z(nL#6dqT`L8<&F(*q7Yp=|e?6=#{GhTJ41x8{2rD4WhQ}W|UgcaQFA8uT3Kods8uC zqq*NE6!f8Sjb; zdaZiGNI8yg21x-NaUJSGN9VAG2@XrfMj&s{*(XOT>}+j_#F?nD=xk0={Jc(_Cio%n zDF<6My}#;i%s-eMEH0f>f<#I>e>6_ifwfK>BO~M65KUL1_0ZJ5#OB~5p7xK;U&c$* zwy6EX<>W*}-wcmiLPC=cHU=|av99IT{8JEK=X$i&_sOauzci`Kuwe8LA#%fMbiY>Z ziB_(Kpy`V^mN;4RQA19H7jZe83b#|M;O!^&H6mjA{le0s;bZ9YALIX8>$cn^i!j*e zM29}BU90!*6pJ1|p5&%c99Z=F`ugyKVa^m1PFt$VX$LO6o-TA_yr8Jbt(pWqN-^ch z%!1SOikyJNPrDH`Sj5E0FDEfb5vukZ;t&9NQu4m}vuKD-PRBpWkUrqz?50n4RrBx= z3W$Z0+fni7_6b8?T>6%qRcG1ZXFz$rR2M?->z*aCHNgy8C(6-@6o7gC{fdtrH#fcr zX>2j)EPmfCjK`?zKW=_Dr@jzrg4U|rzg}qIjBeQov%LOB+r}IX_QlOCn+Gh@g?%|B zj6THp3Q8~im);fW$MiTqMvMrM6+9zo<+gD?q9tdXkKwuuY=EBwA)G}Bb|;L@8J5o# z=Xy?xP`5vlU{anc0gOZ;G7{%8IW*@_|C7Klt2Z)7yT)Np9oW#A`+K&Ur%hQJe#gH2 zTM;fq8J);(t_FQna%>0S;KMZqb#-vav{X5a#G~GVPsi#C1uCn2N#GmvhMW;8rEp?b zCO8V_lrOk1Q8?OD$2EhHRr+4>?*y7pmIWkxobR*;;+9v?KWE4rbrv{3(u2rcJ>CZE ztsy7qX}R4SnmLjyk_scpO;xDbry^484Jio zB&vQM&0cbxvl*_3UA*ycI)j*6%!?Bp+)LYq!E1{3tg8>1%gM6f=v*1kTQ$0_~8`keZBq({FU1hkwp@{ z?g=rYTFLcc$AvQvDk_?pKU)S|#H-o)^4M>~s!zmnB zh5|l)K`vcsJ-rk5G?Ps@tz6)?_2^pPVsHC{pnRuu+@9#cQrYeMxMAOzr7}!XX7W@k z>i*?c?~_&f`RogQzxw%wfY)85{wPd6PuUlP{MD5ta)-p?v+^ewKjvUtr;shI7Y`M@k`2?YS8cE-REt|Judo6Z z4v_e4A3cJN>C%LqB5Rr%TQ>mU^AyiLR_gXcw;(6GUNy+&1IutcT`-LpBxACZ6`KUS`rNzu*cV$cLvj;H ze^QXv^qU?AsM@31d@4)^eIOg^@sV4y#3_-uveXH^Qlc@xs`Vppi$Xfp@z>pMbx?^m-(E9ieOj z**mpRgZ)V)_|9@ENNgW!?7slqU5-A1Bl5jLD8+}}2vu8*B!4qh>g@^_fRx@f+iGTW z4Ky+CoBt-sbf;<6{#$r*zuR`b*xR?QnB>rylCb&I`TNH=@nX20j?yb3249;!9qy(d0+$!-YliREYm3;FYD4s44;TRu8Pl+O{OsJXGcJxt$VpM^Runa z1vQj$dzQq8Tu`CUE2B5+C%~CAQ`eW2Mm0(ObQ$?wJKm&`_qnVy77%lV)&k}ErjA$p zc8X{G?Ck9Qkb7TszCu7`M?9r-=2IYFqjb2$@ zoi_%98)h|Nf-!r+&4v%-JDktrGEav?9_LI5T2UGrpK~^ zT|ZtU$GP_4fMe*|QJF77D8)icY?r(UI6knaFvCec0txd(r4=L(=unzIe)3!xVebGT zW_7xbkl^L}r^cmmfP9x%)NFf$uhsSm5qV|27QfbUyJd&-@>K375~JYwb5(;EUTSO` zW5C3mbp|Me$Y9S0y?Cj3LT`prJ0FY}pOkqDrWDG}`)z21=I)DYCiw!(3GEu*sqB(& zJX99cF7wA+hQPqEE@wjp112|ViXAAlY8{uRouKV3XrZKh9Uaod1pJ09>mvne2A!cw z^byycpFpJu9n+D}WL5<$s7`%#yfs~{%5bnT9JC$g0jbE>AY|DQnag%6oN$P;i!9BK@1YwB;2Wtty^P}#5luiCCW9Lm1mk9wZu zL6U4`DY9l4#x^2LWeXwuZnE!WmqHSfLNTT+jck)8`Ot=DNo1zJJ^IvwipBVtrNR9=p@=nq_-$a?1DS9hy2@NiT_up9#@7!^3rr za(Y|(&4SeF5T{2^-Bbww|@pkk=#$vo540`myejg2KXxgmn;s z8BHIFndQ!O$v?XH$=xQ}s!tr#fsh6XW#og!ZaTXAdBY`NOPq|n7m1c(;@6vF7}i57 z@5w>#---g|co79Q?vxFxl?t-q70#_2$@9y9OpjG2J)cz(bMro$7Va>fV9!tE`KRwQ zt_wKn(f}^|7^*z^EBCy~R}}y}|A8N2)A`TxqE^C}NFBTRam!*3Q_i9UYg0Rh$HG_YA#CaR) zl0&hPega8F^y8JC>%RiPWkv{O?N)fWA97f|j2BpS(U zf6+HK+LVo^UPpEFfyXHsJLn|-;>BcB2hZELUnBd0j^gj@tQ-w*x6M@7mH~e|RJHXa zLi_lR^-1x>q>P+sY2p1{yEaLp3%k^T0wi|$M$VTxIxT1ypaNz;98vFoar5i`j!_pb z=N+A%rKO?2$T)ZRO$t$$!2_fTiLK1P&aa9cs`-COyo>pM9rbPc=;_%M-1B^|MMo7{`=+Pd0QF=>7@+#oSHk72_+@TSr>R6DM8j5SJFQx8+a>I50mjxi z6H+F1CbMv~?gCB%1x{j?9V6wBr4;b_zzAFmU`N*cZD^vIo39n>c#}9M1W=)_&;NELw4JKU=!oPxMmJEX8LH`4S|18BT{KVi4A z6DgAXQA}`(JTk-cJHL5>man`^=ozQF0ypR0Kp>s~KLMw${Ei0U(1wq;tXCZI3-|sK zA>sa)B*(>^#ulg2(T=NvwIgp2>5W}UB*vg|uLuT%Zx4^>o1DZEX0CkmkJPf5$7tV7 zj5vqBY$%6ZJlJQxz)Q45X5>@Y;pYk_(LjOVXQDC<@3a(XMLE`4r!?R$+t=SP7tsm; z;hV96H;8Wy+~BF%^XbKq-8PAkC}CE1{lmf`Td?QlW^%}WsHviWAB9d>{8Q5@?usqD zwDDT1_|kJBYc&#Q4{-(qF|2RbLdRYj@B1(QG!jarOga8aw%b z`Z!3Es(W^|%VX@6#$t?B_waWwEBC|+Acp~DzQq8u?vesH8Vj_aM8>}D5nNR^gM>)P zkhmE8E0okwnM%y8u_<^54}A|XL8wr#^{OPb{w2)FqTtPcDxPfn&+43^fv!>u=^zLM z42vY*+rn%{65OV4Zo(cjRgC~OzwUZx#crGZGkenJBI~`907e~`*Pr7xW$Tk#v93h( z{?3YpY4DO*VJut}oLRE@FDNN0uk53cwyRu7*KYOr*Agx)wfH5MNWd9bi>&TUX+BSl ztMB=s^I*Q2i+BsaaXa-yVCKGdQyT@0`rFZ7v|6 zRilFhy!)2KtC~~t2{C6D7?%xu_7U3Ff!x^M1=1fO1$NCCT$^-e{6*wo*V_klIblCq z6FmS9|6VQGZwOCv^3?M{zGTpQ$eiI6wnh%a6-DQ<`$NCS;XqZe`sEZhwkQbi2LZNb zWm8j@z`YHQ%a zFhM$)urIf>*1E|c=i67d1N2@+_@Nm92-4E(qTQ^lrpmyP$#iR7ph0 z%3!cL&BWQ+*{k8M@N2aoWCRs!2d%!b{LTB^Fl1~~*3C9l@zE+B*Im8Rbya3<;Wh6C z-5UTbqr(*JGCxHJoY%3Dlqc=81PWQ#FDGDpO5;|tHONBwZdb<#G<tkvQ^X^T7p9 zeKOi=4B*;7!k1)+(eLyCyx)e9P9$XwctYE%f7e8in;Yu1pr4~hHa(rfZQXnKPR=|M zsR=TeHDwNW?6wU{oz?H(=dQ1>zkByCa;X8I-4H-`6lIrholbx ziFg#xygn9G35z}MXmmeQOC9W)8DRw|7ml@cxe4d)_|K69)v+a<_BCg^v4IkZBA@>m zGgk&s&)yN*rEQ}Pdz?pr<4ns~$!m$o1EVx9Ik^=i0qA%+ttYetV$i&2PAiGu z7W7~$pGfRqN50~Es;bneq=;1n&o^u^U=P{fZY1sjLfl1W)>=VHmDFx4_mp@5~mnznr{OV)yP-6Y;Qk1}>^PadM6&U6n>`BzV^DkYVp84_OMPbC&(s0q-l+xm0 zQN-W-KiBZ|(ZSR3gOAaV^$Qc{=*Ctv)J zOqP92`PlPTWs&;>X93*+m@7&E_V16zMn=B#C>5Y!6?@Tc=4=gc%S{%ef68R_n*BE> z%W&kMFj)XM<>V-xYAMin10;?2^1#E1&Ay>A$AYgY7qfHcXzmp_`c~_){se5?1wh(x zs?|g;8HpEJj1EZ!HQf(Nfgj8}{&&O7JvLzru|r!5#7gcc^TB zz93_9ti6A@wBO*`385;}nz0(hOOQtm-nhb1no|@Dj<{kBfQ7MpGjIU0esxn;)v4Bgs7R)D_>~5thA5Y zkAa+d#~gs^iB*`5JW7B4nsSeW@azkzN$PDaW_ z_;_U~(9Z(Nq7}j^*(yH~aDM=qU8$GGA-tX;fWf)D$LOY}CVI7sXmHl}R^lYRm6_2~ zPU>~=U(>qjjh{CdMU!Awr|68@qTT5-+oG^l361YBNbosJ@n9=ZQ*(@#yr1)?iIG9h?p#5E8>D#YD@lknE}85) zh$oMt)Qk1lvU-A*cMN6#gK2v54#%`hS_vbU$R=LR_ z1By?Fn2kYM0$|>bglu^$`^MjKO~3;HQbfG_O~7hBwm0hl@*MhwjDpJa+P4bBg(w~= zu?9Y~*a6paVv0+>PAEXm*x{brZ7@4K>NNHD56ZgkZxO1ytbb=49|(DVIW6=$Ny1+| z+-=f)!MA7}Flas^;HSWaJj(4B0DHs{Mdt>XHwd3W@m#LnHKOYODPY?HS|c{ZsJObC z*VGIfTNKW44xa#81=%ubN(}u4nmNy-g^vga#E0`QTvXT!ipk{8F%7g&UI;9=r8LVo ziNbMR4X!e!@-Pji45+ck<~Zl;AG2K1vrGtve)HAOG)BGiycZA*SJ9Y#P#C0G4!>95 zSR9TJ)XUBKWTItZQH@y`ET!`I-a}@ajWcZOnoxW|Tooak-I@K!@1OcsaQyRK!*y1Z zqn*aiH-HQw%tiyW$}%yVXqo_XCj{|wcEK+vSFABCd9EwbKMdAQM5UJna5#UOHS5$> z1}`S+4(G?aPDugV*)_1od*Z&GjQX@yF`q_7|8cHisPvUVu3p9VoV>EK-y_Ro#u&y5 z4c=wy`yps~3$Oi40xB8(bBBbFw9mq9#q1?z*$30WH(;iDU5kpLH+fthBT?8JF=+X2 zN{K$st9XW1H$g8i9x1tSlWmr|LCBRZ(N!x^z}nWjXDC0vp)s7I@|nw4hU>vV!Kp^# z)K*l9(7AKZUC#=M289r&%88_}#|xt;NLXx0_Yw7 z;0wRoIcjlsCKn)0>CL%&YNWYGl8tMeI(;zSVG~1i37F@@WkHl=kz`lQl19EWG}Cj& zKToQ|Y&zIG5tTBObb(MLps^(8602{ZG$@#4l9X6Gs2)&ABB(FqEgd_ZwOu&j0?PLs ztA{19#x9M8KLDd$Dc_hrO&*?6G7EtpyWX^`!TN1u^S&tHr-

  • bzki{Py{Pds_+NLrzF>l&iL#!pA0lu=Pb|*x!3Ya10B1s6(fwHio`Y3yaj;;$ zSpO;pTMD}L!oUc5B$$9UZ>Xry9CqnoQ2#JDgmUBB-mIjn*kxAm2^h(8Qz)&95RJ%DcAH$#yOlU0il?itP#kFet zVX0*Pm=a~yqVi{q9+Fl9tPMKgOo85tq9;V{?&`dqQ`T_{?}s!LI$E-1{V_a z<;#vsPHSi9RNbM=V2O=UwH_n>B~g+y?dA_nO2E_?7kfx4cduBi`Qp(@c~BMEkV-F~ zfD&`QFqPA0o97ZHry$dsucNJo_g`)@$5PY9iUE&<7g|Sr#a712@4Ag-OuGxsMniHZ za4v83HW^&~xAgsKP5-;Tzc(qC^g2od zK}7GHodh!q(_Un%%2`c(4%-QUK|t6-GYB-hX>80?E-6{HzFg@zShZX1)@Cb8*j#A< zEYsoEXYzq1Z$JS#pE8v?TZ(O0VGX*OSy`A}-DqjCm)FfG>3-fe>b3es2@(G-N5Ad) z_BPVx*{xychLzNT3j^rj;2`{0^r~Mqs____v?Bt~)45@brV6etg}~3FPX?6OHh8Xy zNZe@{Yt8f1Z5_t7K{JJ+@qrYAGlgmK645k`RLJrziIew=bPCS1VtXxwN^+~qXe!SY z9H66D?s6$TRuNhlloQ(D>^CU&X3jfjxY{P#c}GtV14jlbqfM*J);pwq_kNCh%zeM? zw>9603)+@u30@Sg*L7Iu!|(@vIEuwIBx}R)`a-uYDo1nqoi%yELvc9G7Oh)N4sYyTSoVD7{H*p-T zcm*2c>PA~IoC12%sZjD4zRTru`gwm{kh10`m)m;+cu3HWnQzCu#%xhI9lNsnISh)> z;5DY@+duFKr(g`75W81oOUbU1`h=S4d|RD-BIsCh_2TB>@u||L`zh!zb*|&Odu6^W*5!Z zBAKf0Xl&d&yTv@z4M@bA(OTBhVG}P|Db6>Gi}6;o^wauIviqxtC#htc+F0{nx6foB z=IG^5ht=Yv0WEq-fLZ1V`)d_wO5C@bn#ZXlX~6M#jT-yj7b;j8|1>K2VR>2-ura!N zF%DiSP;;gS(yI@S5@&}en4@7q^716BtE-@N`gHpe7Z(b%ze<(|1?|9^h1bZ5HTLep zdZ*~2e(mH`7{FBuGb|tpU?~FC8`{bg zto1Fg2zD=LkH`0J+z|^Kd9cl=01o1m?Fr?N=C*O{^9^P+1=HKW;c;uaHb~z~4!9=@ zSS1Z8$Og-kR&0W^_Z-)Ji4uAs?nQl~8YBFv6@}c0nk@=Dd$44$276RwQDXRUcuAK4 zW+yRPOjqGVx-t^_R!Uen?qZOyEWx1sLjdHGo9E;pHpMr@{*_6{uLwz>hi&9 zxI}kbKmUL#T{(Jkl7+s=d8wkv&--X`kJGUO2g{UofO)?!#9vCA?UY$4c(0kMp z0}Ea`+z(i(CzZjE*Usiw;%1gBaqqISo@A;f7Ou&0bDG#eX*c1eR#d&(#^;Il+^Nxk;P=(h**;EW8$UFEG)$QBYdDJF|ZB2(LQ@z&l zvzTqIsOw$exrmz9zkt)U<#gm**Dkrb1y09??t=4*s{&qV6!*3?73Y&X}NFqIrsE^+$uhWrSF&( zanVkX(9SLVT8H#kslnCQGUHmL)JX{B-r4TW_NJIE9rzUs=m|qExgD0ot3EpLw&?9> z2;@8AP5wyK@{d%{#zH4zm>yUF*%X7Vl2LgdacjE-H zgGl-LXXPHuBp0&tx!l~>q?a8>o|>U-o~d}L2?%JzNgxou+_WZkoTufdS|<39OPpTo zo%h1o?|)pc7wRBwxVJR^EGSq~${<0C3<5E?h{k$73)el6k#TN3x?nx1BtN@GYY!v% zg?tPyOyKh%Lh%!)!MBjt6e{2wq|F*i>|k%s*#K@N1R{$6vlo6#kqxpiMtpfoNkcJT I!94Uo0HuA#d;kCd literal 44847 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 BT7Uom From afd6faffc3e6309d325e960e3461fe2a64435292 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 21 Mar 2023 17:53:04 +0100 Subject: [PATCH 595/898] Update openpype/modules/deadline/plugins/publish/submit_max_deadline.py Co-authored-by: Kayla Man <64118225+moonyuet@users.noreply.github.com> --- .../modules/deadline/plugins/publish/submit_max_deadline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index 392e36b08e9..226ca2eb985 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -71,7 +71,7 @@ def get_job_info(self): job_info.Pool = instance.data.get("primaryPool") job_info.SecondaryPool = instance.data.get("secondaryPool") - job_info.ChunkSize = instance.data.get("chunkSize", 1) + job_info.ChunkSize = instance.data.get("chunkSize", self.chunk_size) job_info.Comment = context.data.get("comment") job_info.Priority = instance.data.get("priority", self.priority) From c8c31018d656ea206c42e4a083365e21b4252861 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Tue, 21 Mar 2023 18:10:09 +0100 Subject: [PATCH 596/898] General: Filter available applications (#4667) * added project settings for applications * filter applications by new settings in launcher and ftrack * disable filtering by default --- .../event_handlers_user/action_applications.py | 9 +++++++++ .../defaults/project_settings/applications.json | 3 +++ .../schemas/projects_schema/schema_main.json | 4 ++++ .../schema_project_applications.json | 14 ++++++++++++++ openpype/tools/launcher/models.py | 6 ++++++ 5 files changed, 36 insertions(+) create mode 100644 openpype/settings/defaults/project_settings/applications.json create mode 100644 openpype/settings/entities/schemas/projects_schema/schema_project_applications.json diff --git a/openpype/modules/ftrack/event_handlers_user/action_applications.py b/openpype/modules/ftrack/event_handlers_user/action_applications.py index 102f04c9566..30399b463dd 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_applications.py +++ b/openpype/modules/ftrack/event_handlers_user/action_applications.py @@ -124,6 +124,11 @@ def discover(self, session, entities, event): if not avalon_project_apps: return False + settings = self.get_project_settings_from_event( + event, avalon_project_doc["name"]) + + only_available = settings["applications"]["only_available"] + items = [] for app_name in avalon_project_apps: app = self.application_manager.applications.get(app_name) @@ -133,6 +138,10 @@ def discover(self, session, entities, event): if app.group.name in CUSTOM_LAUNCH_APP_GROUPS: continue + # Skip applications without valid executables + if only_available and not app.find_executable(): + continue + app_icon = app.icon if app_icon and self.icon_url: try: diff --git a/openpype/settings/defaults/project_settings/applications.json b/openpype/settings/defaults/project_settings/applications.json new file mode 100644 index 00000000000..62f3cdfe1be --- /dev/null +++ b/openpype/settings/defaults/project_settings/applications.json @@ -0,0 +1,3 @@ +{ + "only_available": false +} diff --git a/openpype/settings/entities/schemas/projects_schema/schema_main.json b/openpype/settings/entities/schemas/projects_schema/schema_main.json index ebe59c7942b..8c1d8ccbdd1 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_main.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_main.json @@ -82,6 +82,10 @@ "type": "schema", "name": "schema_project_slack" }, + { + "type": "schema", + "name": "schema_project_applications" + }, { "type": "schema", "name": "schema_project_max" diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_applications.json b/openpype/settings/entities/schemas/projects_schema/schema_project_applications.json new file mode 100644 index 00000000000..030ed3ee8ad --- /dev/null +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_applications.json @@ -0,0 +1,14 @@ +{ + "type": "dict", + "key": "applications", + "label": "Applications", + "collapsible": true, + "is_file": true, + "children": [ + { + "type": "boolean", + "key": "only_available", + "label": "Show only available applications" + } + ] +} diff --git a/openpype/tools/launcher/models.py b/openpype/tools/launcher/models.py index 6c763544a90..3aa6c5d8cb7 100644 --- a/openpype/tools/launcher/models.py +++ b/openpype/tools/launcher/models.py @@ -19,6 +19,7 @@ CUSTOM_LAUNCH_APP_GROUPS, ApplicationManager ) +from openpype.settings import get_project_settings from openpype.pipeline import discover_launcher_actions from openpype.tools.utils.lib import ( DynamicQThread, @@ -94,6 +95,8 @@ def get_application_actions(self): if not project_doc: return actions + project_settings = get_project_settings(project_name) + only_available = project_settings["applications"]["only_available"] self.application_manager.refresh() for app_def in project_doc["config"]["apps"]: app_name = app_def["name"] @@ -104,6 +107,9 @@ def get_application_actions(self): if app.group.name in CUSTOM_LAUNCH_APP_GROUPS: continue + if only_available and not app.find_executable(): + continue + # Get from app definition, if not there from app in project action = type( "app_{}".format(app_name), From 9f6bc9459a5288bfa55e7b78a4cb8c49e0ae681c Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 21 Mar 2023 18:03:48 +0000 Subject: [PATCH 597/898] Revert alembic representation exclusion. --- openpype/hosts/maya/plugins/load/load_gpucache.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/load/load_gpucache.py b/openpype/hosts/maya/plugins/load/load_gpucache.py index b7ca7292f5c..c447311454c 100644 --- a/openpype/hosts/maya/plugins/load/load_gpucache.py +++ b/openpype/hosts/maya/plugins/load/load_gpucache.py @@ -11,7 +11,7 @@ class GpuCacheLoader(load.LoaderPlugin): """Load Alembic as gpuCache""" families = ["model", "animation", "proxyAbc", "pointcache"] - representations = ["gpu_cache"] + representations = ["abc", "gpu_cache"] label = "Import Gpu Cache" order = -5 From 2e8ba574e258384d3ee3b630b4af4e31a25878db Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 21 Mar 2023 18:04:10 +0000 Subject: [PATCH 598/898] Appropriate label --- openpype/hosts/maya/plugins/load/load_gpucache.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/load/load_gpucache.py b/openpype/hosts/maya/plugins/load/load_gpucache.py index c447311454c..f342679791a 100644 --- a/openpype/hosts/maya/plugins/load/load_gpucache.py +++ b/openpype/hosts/maya/plugins/load/load_gpucache.py @@ -13,7 +13,7 @@ class GpuCacheLoader(load.LoaderPlugin): families = ["model", "animation", "proxyAbc", "pointcache"] representations = ["abc", "gpu_cache"] - label = "Import Gpu Cache" + label = "Load Gpu Cache" order = -5 icon = "code-fork" color = "orange" From e516a75ce3649be96ab9a53abca42e4d7c417e35 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 21 Mar 2023 18:04:16 +0000 Subject: [PATCH 599/898] Code cosmetics --- .../hosts/maya/plugins/load/load_gpucache.py | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/openpype/hosts/maya/plugins/load/load_gpucache.py b/openpype/hosts/maya/plugins/load/load_gpucache.py index f342679791a..794b21eb5d5 100644 --- a/openpype/hosts/maya/plugins/load/load_gpucache.py +++ b/openpype/hosts/maya/plugins/load/load_gpucache.py @@ -1,5 +1,9 @@ import os +import maya.cmds as cmds + +from openpype.hosts.maya.api.pipeline import containerise +from openpype.hosts.maya.api.lib import unique_namespace from openpype.pipeline import ( load, get_representation_path @@ -20,10 +24,6 @@ class GpuCacheLoader(load.LoaderPlugin): def load(self, context, name, namespace, data): - import maya.cmds as cmds - from openpype.hosts.maya.api.pipeline import containerise - from openpype.hosts.maya.api.lib import unique_namespace - asset = context['asset']['name'] namespace = namespace or unique_namespace( asset + "_", @@ -42,10 +42,9 @@ def load(self, context, name, namespace, data): c = colors.get('model') if c is not None: cmds.setAttr(root + ".useOutlinerColor", 1) - cmds.setAttr(root + ".outlinerColor", - (float(c[0])/255), - (float(c[1])/255), - (float(c[2])/255) + cmds.setAttr( + root + ".outlinerColor", + (float(c[0]) / 255), (float(c[1]) / 255), (float(c[2]) / 255) ) # Create transform with shape @@ -74,9 +73,6 @@ def load(self, context, name, namespace, data): loader=self.__class__.__name__) def update(self, container, representation): - - import maya.cmds as cmds - path = get_representation_path(representation) # Update the cache @@ -96,7 +92,6 @@ def switch(self, container, representation): self.update(container, representation) def remove(self, container): - import maya.cmds as cmds members = cmds.sets(container['objectName'], query=True) cmds.lockNode(members, lock=False) cmds.delete([container['objectName']] + members) From 749bf7d2290ff256da95f634090d5a2c3bff18dd Mon Sep 17 00:00:00 2001 From: Ynbot Date: Wed, 22 Mar 2023 03:26:05 +0000 Subject: [PATCH 600/898] [Automated] Bump version --- openpype/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/version.py b/openpype/version.py index 339c17dc70e..5b6db12b5e4 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.15.3-nightly.2" +__version__ = "3.15.3-nightly.3" From 28b424bf2fe113857d3513948a6bdcd897fbb859 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 22 Mar 2023 12:13:21 +0100 Subject: [PATCH 601/898] Publisher: Windows reduce command window pop-ups during Publishing (#4672) * Avoid command pop-ups during publishing (tip by @iLLiCiTiT) * No need to pass creationflags because it's already done in `run_subprocess` * Hide command window for `shell=True` calls * Update openpype/lib/execute.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --------- Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- openpype/lib/execute.py | 4 ++++ openpype/lib/vendor_bin_utils.py | 12 ++++++++++-- openpype/plugins/publish/extract_burnin.py | 6 +----- openpype/scripts/otio_burnin.py | 6 ------ 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/openpype/lib/execute.py b/openpype/lib/execute.py index 759a4db0cb7..7a929a0ade1 100644 --- a/openpype/lib/execute.py +++ b/openpype/lib/execute.py @@ -102,6 +102,10 @@ def run_subprocess(*args, **kwargs): if ( platform.system().lower() == "windows" and "creationflags" not in kwargs + # shell=True already tries to hide the console window + # and passing these creationflags then shows the window again + # so we avoid it for shell=True cases + and kwargs.get("shell") is not True ): kwargs["creationflags"] = ( subprocess.CREATE_NEW_PROCESS_GROUP diff --git a/openpype/lib/vendor_bin_utils.py b/openpype/lib/vendor_bin_utils.py index 00dd1955fee..e5deb7a6b23 100644 --- a/openpype/lib/vendor_bin_utils.py +++ b/openpype/lib/vendor_bin_utils.py @@ -224,18 +224,26 @@ def find_tool_in_custom_paths(paths, tool, validation_func=None): def _check_args_returncode(args): try: - # Python 2 compatibility where DEVNULL is not available + kwargs = {} + if platform.system().lower() == "windows": + kwargs["creationflags"] = ( + subprocess.CREATE_NEW_PROCESS_GROUP + | getattr(subprocess, "DETACHED_PROCESS", 0) + | getattr(subprocess, "CREATE_NO_WINDOW", 0) + ) + if hasattr(subprocess, "DEVNULL"): proc = subprocess.Popen( args, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, + **kwargs ) proc.wait() else: with open(os.devnull, "w") as devnull: proc = subprocess.Popen( - args, stdout=devnull, stderr=devnull, + args, stdout=devnull, stderr=devnull, **kwargs ) proc.wait() diff --git a/openpype/plugins/publish/extract_burnin.py b/openpype/plugins/publish/extract_burnin.py index f113e61bb09..38ec08e8d97 100644 --- a/openpype/plugins/publish/extract_burnin.py +++ b/openpype/plugins/publish/extract_burnin.py @@ -16,9 +16,7 @@ get_transcode_temp_directory, convert_input_paths_for_ffmpeg, - should_convert_for_ffmpeg, - - CREATE_NO_WINDOW + should_convert_for_ffmpeg ) from openpype.lib.profiles_filtering import filter_profiles @@ -338,8 +336,6 @@ def main_process(self, instance): "logger": self.log, "env": {} } - if platform.system().lower() == "windows": - process_kwargs["creationflags"] = CREATE_NO_WINDOW run_openpype_process(*args, **process_kwargs) # Remove the temporary json diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index cb4646c099d..ef449f4f74e 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -345,12 +345,6 @@ def render(self, output, args=None, overwrite=False, **kwargs): "stderr": subprocess.PIPE, "shell": True, } - if platform.system().lower() == "windows": - kwargs["creationflags"] = ( - subprocess.CREATE_NEW_PROCESS_GROUP - | getattr(subprocess, "DETACHED_PROCESS", 0) - | getattr(subprocess, "CREATE_NO_WINDOW", 0) - ) proc = subprocess.Popen(command, **kwargs) _stdout, _stderr = proc.communicate() From 20219b465bc1c066bf3af5c53b0e2447450d1f5a Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 22 Mar 2023 19:57:45 +0800 Subject: [PATCH 602/898] resolution setting updated --- openpype/hosts/max/api/lib.py | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index 6a7f63ca75b..b6e39587977 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -6,12 +6,10 @@ from typing import Union import contextlib -from openpype.client import ( - get_project +from openpype.pipeline.context_tools import ( + get_current_project_asset, + get_current_project ) -from openpype.pipeline import legacy_io - -from openpype.pipeline.context_tools import get_current_project_asset JSON_PREFIX = "JSON::" @@ -164,7 +162,7 @@ def get_multipass_setting(project_setting=None): ["multipass"]) -def set_scene_resolution(width, height): +def set_scene_resolution(width: int, height: int): """Set the render resolution Args: @@ -188,19 +186,15 @@ def reset_scene_resolution(): Returns: None """ - project_name = legacy_io.active_project() - project_doc = get_project(project_name) - project_data = project_doc["data"] - asset_data = get_current_project_asset()["data"] - + project_resolution_data = get_current_project(fields=["data.resolutionWidth", + "data.resolutionHeight"])["data"] + asset_resolution_data = get_current_project_asset(fields=["data.resolutionWidth", + "data.resolutionHeight"])["data"] # Set project resolution - width_key = "resolutionWidth" - height_key = "resolutionHeight" - proj_width_key = project_data.get(width_key, 1920) - proj_height_key = project_data.get(height_key, 1080) - - width = asset_data.get(width_key, proj_width_key) - height = asset_data.get(height_key, proj_height_key) + project_width = int(project_resolution_data.get("resolutionWidth", 1920)) + project_height = int(project_resolution_data.get("resolutionHeight", 1080)) + width = int(asset_resolution_data.get("resolutionWidth", project_width)) + height = int(asset_resolution_data.get("resolutionHeight", project_height)) set_scene_resolution(width, height) From 0bce4762f12e10e3097c5acdafe746a3b1cc71cd Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 22 Mar 2023 20:00:23 +0800 Subject: [PATCH 603/898] hound fix --- openpype/hosts/max/api/lib.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index b6e39587977..577dc6e99dd 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -186,10 +186,11 @@ def reset_scene_resolution(): Returns: None """ - project_resolution_data = get_current_project(fields=["data.resolutionWidth", - "data.resolutionHeight"])["data"] - asset_resolution_data = get_current_project_asset(fields=["data.resolutionWidth", - "data.resolutionHeight"])["data"] + data = ["data.resolutionWidth","data.resolutionHeight"] + project_resolution = get_current_project(fields=data)["data"] + project_resolution_data = project_resolution["data"] + asset_resolution = get_current_project_asset(fields=data)["data"] + asset_resolution_data = asset_resolution["data"] # Set project resolution project_width = int(project_resolution_data.get("resolutionWidth", 1920)) project_height = int(project_resolution_data.get("resolutionHeight", 1080)) From e70be13d9650c6c28239cb1578c06751c5e670c5 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 22 Mar 2023 20:00:59 +0800 Subject: [PATCH 604/898] hound fix --- openpype/hosts/max/api/lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index 577dc6e99dd..ac1d1587923 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -186,7 +186,7 @@ def reset_scene_resolution(): Returns: None """ - data = ["data.resolutionWidth","data.resolutionHeight"] + data = ["data.resolutionWidth", "data.resolutionHeight"] project_resolution = get_current_project(fields=data)["data"] project_resolution_data = project_resolution["data"] asset_resolution = get_current_project_asset(fields=data)["data"] From e9eb09e100d990e5a6d8648ff32df0d3e7ec4969 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 22 Mar 2023 12:58:33 +0000 Subject: [PATCH 605/898] Initial working version --- .../maya/plugins/publish/collect_review.py | 23 +++-- openpype/lib/execute.py | 7 ++ openpype/plugins/publish/extract_burnin.py | 4 + openpype/scripts/otio_burnin.py | 87 +++++++++++++++++-- 4 files changed, 109 insertions(+), 12 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_review.py b/openpype/hosts/maya/plugins/publish/collect_review.py index 80fd5b0dbdc..3d3ee09eed7 100644 --- a/openpype/hosts/maya/plugins/publish/collect_review.py +++ b/openpype/hosts/maya/plugins/publish/collect_review.py @@ -146,11 +146,24 @@ def process(self, instance): ) # Collect focal length. - data = { - "cameraFocalLength": cmds.getAttr(camera + ".focalLength") - } + #Refactor to lib or use available lib method. + plug = "{0}.focalLength".format(camera) + focal_length = None + if not cmds.listConnections(plug, destination=False, source=True): + # Static. + focal_length = cmds.getAttr(plug) + else: + # Dynamic. + start = instance.data["frameStart"] + end = instance.data["frameEnd"] + 1 + focal_length = [ + cmds.getAttr(plug, time=t) for t in range(int(start), int(end)) + ] + + key = "focalLength" + instance.data[key] = focal_length try: - instance.data["customData"].update(data) + instance.data["burninDataMembers"].append(key) except KeyError: - instance.data["customData"] = data + instance.data["burninDataMembers"] = [key] diff --git a/openpype/lib/execute.py b/openpype/lib/execute.py index 759a4db0cb7..5ba62f177f4 100644 --- a/openpype/lib/execute.py +++ b/openpype/lib/execute.py @@ -8,6 +8,8 @@ from .log import Logger from .vendor_bin_utils import find_executable +from .openpype_version import is_running_from_build + # MSDN process creation flag (Windows only) CREATE_NO_WINDOW = 0x08000000 @@ -196,6 +198,11 @@ def run_openpype_process(*args, **kwargs): # Skip envs that can affect OpenPype process # - fill more if you find more env = clean_envs_for_openpype_process(os.environ) + + # Add OpenPype version if we are running from build. + if not is_running_from_build(): + env.pop("OPENPYPE_VERSION", None) + return run_subprocess(args, env=env, **kwargs) diff --git a/openpype/plugins/publish/extract_burnin.py b/openpype/plugins/publish/extract_burnin.py index f113e61bb09..de876c84862 100644 --- a/openpype/plugins/publish/extract_burnin.py +++ b/openpype/plugins/publish/extract_burnin.py @@ -254,6 +254,10 @@ def main_process(self, instance): # Add context data burnin_data. burnin_data["custom"] = custom_data + # Add data members. + for key in instance.data.get("burninDataMembers", []): + burnin_data[key] = instance.data[key] + # Add source camera name to burnin data camera_name = repre.get("camera_name") if camera_name: diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index cb4646c099d..bb7a208103f 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -4,8 +4,10 @@ import subprocess import platform import json -import opentimelineio_contrib.adapters.ffmpeg_burnins as ffmpeg_burnins +import tempfile +from string import Formatter +import opentimelineio_contrib.adapters.ffmpeg_burnins as ffmpeg_burnins from openpype.lib import ( get_ffmpeg_tool_path, get_ffmpeg_codec_args, @@ -23,7 +25,7 @@ ).format(ffmpeg_path) DRAWTEXT = ( - "drawtext=fontfile='%(font)s':text=\\'%(text)s\\':" + "drawtext@'%(label)s'=fontfile='%(font)s':text=\\'%(text)s\\':" "x=%(x)s:y=%(y)s:fontcolor=%(color)s@%(opacity).1f:fontsize=%(size)d" ) TIMECODE = ( @@ -39,6 +41,34 @@ SOURCE_TIMECODE_KEY = "{source_timecode}" +def convert_list_to_cmd(list_to_convert, fps, label=""): + path = None + #need to clean up temp file when done + with tempfile.NamedTemporaryFile(mode="w", delete=False) as f: + for i, value in enumerate(list_to_convert): + seconds = i / fps + + # Escape special character + value = str(value).replace(":", "\\:") + + filter = "drawtext" + if label: + filter += "@" + label + + line = ( + "{start} {filter} reinit text='{value}';" + "\n".format(start=seconds, filter=filter, value=value) + ) + + f.write(line) + f.flush() + path = f.name + path = path.replace("\\", "/") + path = path.replace(":", "\\:") + + return "sendcmd=f='{}'".format(path) + + def _get_ffprobe_data(source): """Reimplemented from otio burnins to be able use full path to ffprobe :param str source: source media file @@ -144,7 +174,7 @@ def __init__( self.options_init.update(options_init) def add_text( - self, text, align, frame_start=None, frame_end=None, options=None + self, text, align, frame_start=None, frame_end=None, options=None, cmd="" ): """ Adding static text to a filter. @@ -165,7 +195,13 @@ def add_text( if frame_end is not None: options["frame_end"] = frame_end - self._add_burnin(text, align, options, DRAWTEXT) + draw_text = DRAWTEXT + if cmd: + draw_text = "{}, {}".format(cmd, DRAWTEXT) + + options["label"] = align + + self._add_burnin(text, align, options, draw_text) def add_timecode( self, align, frame_start=None, frame_end=None, frame_start_tc=None, @@ -501,7 +537,7 @@ def burnins_from_data( if not value: continue - if isinstance(value, (dict, list, tuple)): + if isinstance(value, (dict, tuple)): raise TypeError(( "Expected string or number type." " Got: {} - \"{}\"" @@ -573,8 +609,43 @@ def burnins_from_data( burnin.add_timecode(*args) continue - text = value.format(**data) - burnin.add_text(text, align, frame_start, frame_end) + cmd = "" + text = None + keys = [i[1] for i in Formatter().parse(value) if i[1] is not None] + list_to_convert = [] + + # Warn about nested dictionary support for lists. Ei. we dont support + # it. + if "[" in "".join(keys): + print( + "We dont support converting nested dictionaries to lists," + " so skipping {}".format(value) + ) + else: + for key in keys: + data_value = data[key] + + # Multiple lists are not supported. + if isinstance(data_value, list) and list_to_convert: + raise ValueError( + "Found multiple lists to convert, which is not " + "supported: {}".format(value) + ) + + if isinstance(data_value, list): + print("Found list to convert: {}".format(data_value)) + for v in data_value: + data[key] = v + list_to_convert.append(value.format(**data)) + + if list_to_convert: + text = list_to_convert[0] + cmd = convert_list_to_cmd(list_to_convert, 25.0, label=align)# need to fetch fps properly + print("cmd: " + cmd) + else: + text = value.format(**data) + print(text) + burnin.add_text(text, align, frame_start, frame_end, cmd=cmd) ffmpeg_args = [] if codec_data: @@ -613,6 +684,8 @@ def burnins_from_data( with open(in_data_json_path, "r") as file_stream: in_data = json.load(file_stream) + print(json.dumps(in_data, indent=4, sort_keys=True)) + burnins_from_data( in_data["input"], in_data["output"], From 583fecd4009003681fb6cc535aecdbe641a66022 Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Wed, 22 Mar 2023 14:37:59 +0100 Subject: [PATCH 606/898] Fixes and adjustments based on reviews --- .../plugins/publish/integrate_kitsu_note.py | 18 ++-- .../defaults/project_settings/kitsu.json | 6 +- .../projects_schema/schema_project_kitsu.json | 97 ++++++++++-------- .../assets/integrate_kitsu_note_settings.png | Bin 46673 -> 48874 bytes website/docs/module_kitsu.md | 4 +- 5 files changed, 69 insertions(+), 56 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 366e70934f2..a5253d78786 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -14,8 +14,10 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): # status settings set_status_note = False note_status_shortname = "wfa" - status_conditions = list() - family_requirements = list() + status_change_conditions = { + "status_conditions": [], + "family_requirements": [], + } # comment settings custom_comment_template = { @@ -63,7 +65,7 @@ def process(self, context): # Check if any status condition is not met allow_status_change = True - for status_cond in self.status_conditions: + for status_cond in self.status_change_conditions["status_conditions"]: condition = status_cond["condition"] == "equal" match = status_cond["short_name"].upper() == shortname if match and not condition or condition and not match: @@ -73,20 +75,22 @@ def process(self, context): if allow_status_change: # Get families families = { - instance.data.get("kitsu_task") + instance.data.get("family") for instance in context if instance.data.get("publish") } + allow_status_change = False + # Check if any family requirement is met - for family_requirement in self.family_requirements: + for family_requirement in self.status_change_conditions["family_requirements"]: condition = family_requirement["condition"] == "equal" for family in families: match = ( - family_requirement["short_name"].lower() == family + family_requirement["family"].lower() == family ) - if match and not condition or condition and not match: + if match and condition or not condition and not match: allow_status_change = True break diff --git a/openpype/settings/defaults/project_settings/kitsu.json b/openpype/settings/defaults/project_settings/kitsu.json index 32c6c253c70..59a36d8b97d 100644 --- a/openpype/settings/defaults/project_settings/kitsu.json +++ b/openpype/settings/defaults/project_settings/kitsu.json @@ -8,8 +8,10 @@ "IntegrateKitsuNote": { "set_status_note": false, "note_status_shortname": "wfa", - "status_conditions": [], - "family_requirements": [], + "status_change_conditions": { + "status_conditions": [], + "family_requirements": [] + }, "custom_comment_template": { "enabled": false, "comment_template": "{comment}\n\n| | |\n|--|--|\n| version| `{version}` |\n| family | `{family}` |\n| name | `{name}` |" diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index 0a3a5e6e7b2..8aeed00542e 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -54,55 +54,62 @@ "label": "Note shortname" }, { - "type": "list", - "key": "status_conditions", - "label": "Status conditions", - "object_type": { - "type": "dict", - "key": "conditions_dict", - "children": [ - { - "type": "enum", - "key": "condition", - "label": "Condition", - "enum_items": [ - {"equal": "Equal"}, - {"not_equal": "Not equal"} + "type": "dict", + "collapsible": true, + "key": "status_change_conditions", + "label": "Status change conditions", + "children": [ + { + "type": "list", + "key": "status_conditions", + "label": "Status conditions", + "object_type": { + "type": "dict", + "key": "condition_dict", + "children": [ + { + "type": "enum", + "key": "condition", + "label": "Condition", + "enum_items": [ + {"equal": "Equal"}, + {"not_equal": "Not equal"} + ] + }, + { + "type": "text", + "key": "short_name", + "label": "Short name" + } ] - }, - { - "type": "text", - "key": "short_name", - "label": "Short name" } - ] - }, - "label": "Status shortname" - }, - { - "type": "list", - "key": "family_requirements", - "label": "Family requirements", - "object_type": { - "type": "dict", - "key": "requirement_dict", - "children": [ - { - "type": "enum", - "key": "condition", - "label": "Condition", - "enum_items": [ - {"equal": "Equal"}, - {"not_equal": "Not equal"} + }, + { + "type": "list", + "key": "family_requirements", + "label": "Family requirements", + "object_type": { + "type": "dict", + "key": "requirement_dict", + "children": [ + { + "type": "enum", + "key": "condition", + "label": "Condition", + "enum_items": [ + {"equal": "Equal"}, + {"not_equal": "Not equal"} + ] + }, + { + "type": "text", + "key": "family", + "label": "Family" + } ] - }, - { - "type": "text", - "key": "family", - "label": "Family" } - ] - } + } + ] }, { "type": "dict", diff --git a/website/docs/assets/integrate_kitsu_note_settings.png b/website/docs/assets/integrate_kitsu_note_settings.png index 6f76556afa54b4a1cd946ffb78d200ec3cd3e3b1..9c59f0bf5cc9a748de1a8b66b248f539ee8014b5 100644 GIT binary patch literal 48874 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%0D3V?)tF)Lx2^;H(ZQbbO&WO=KC?o7RUlAm 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

  • bzki{Py{Pds_+NLrzF>l&iL#!pA0lu=Pb|*x!3Ya10B1s6(fwHio`Y3yaj;;$ zSpO;pTMD}L!oUc5B$$9UZ>Xry9CqnoQ2#JDgmUBB-mIjn*kxAm2^h(8Qz)&95RJ%DcAH$#yOlU0il?itP#kFet zVX0*Pm=a~yqVi{q9+Fl9tPMKgOo85tq9;V{?&`dqQ`T_{?}s!LI$E-1{V_a z<;#vsPHSi9RNbM=V2O=UwH_n>B~g+y?dA_nO2E_?7kfx4cduBi`Qp(@c~BMEkV-F~ zfD&`QFqPA0o97ZHry$dsucNJo_g`)@$5PY9iUE&<7g|Sr#a712@4Ag-OuGxsMniHZ za4v83HW^&~xAgsKP5-;Tzc(qC^g2od zK}7GHodh!q(_Un%%2`c(4%-QUK|t6-GYB-hX>80?E-6{HzFg@zShZX1)@Cb8*j#A< zEYsoEXYzq1Z$JS#pE8v?TZ(O0VGX*OSy`A}-DqjCm)FfG>3-fe>b3es2@(G-N5Ad) z_BPVx*{xychLzNT3j^rj;2`{0^r~Mqs____v?Bt~)45@brV6etg}~3FPX?6OHh8Xy zNZe@{Yt8f1Z5_t7K{JJ+@qrYAGlgmK645k`RLJrziIew=bPCS1VtXxwN^+~qXe!SY z9H66D?s6$TRuNhlloQ(D>^CU&X3jfjxY{P#c}GtV14jlbqfM*J);pwq_kNCh%zeM? zw>9603)+@u30@Sg*L7Iu!|(@vIEuwIBx}R)`a-uYDo1nqoi%yELvc9G7Oh)N4sYyTSoVD7{H*p-T zcm*2c>PA~IoC12%sZjD4zRTru`gwm{kh10`m)m;+cu3HWnQzCu#%xhI9lNsnISh)> z;5DY@+duFKr(g`75W81oOUbU1`h=S4d|RD-BIsCh_2TB>@u||L`zh!zb*|&Odu6^W*5!Z zBAKf0Xl&d&yTv@z4M@bA(OTBhVG}P|Db6>Gi}6;o^wauIviqxtC#htc+F0{nx6foB z=IG^5ht=Yv0WEq-fLZ1V`)d_wO5C@bn#ZXlX~6M#jT-yj7b;j8|1>K2VR>2-ura!N zF%DiSP;;gS(yI@S5@&}en4@7q^716BtE-@N`gHpe7Z(b%ze<(|1?|9^h1bZ5HTLep zdZ*~2e(mH`7{FBuGb|tpU?~FC8`{bg zto1Fg2zD=LkH`0J+z|^Kd9cl=01o1m?Fr?N=C*O{^9^P+1=HKW;c;uaHb~z~4!9=@ zSS1Z8$Og-kR&0W^_Z-)Ji4uAs?nQl~8YBFv6@}c0nk@=Dd$44$276RwQDXRUcuAK4 zW+yRPOjqGVx-t^_R!Uen?qZOyEWx1sLjdHGo9E;pHpMr@{*_6{uLwz>hi&9 zxI}kbKmUL#T{(Jkl7+s=d8wkv&--X`kJGUO2g{UofO)?!#9vCA?UY$4c(0kMp z0}Ea`+z(i(CzZjE*Usiw;%1gBaqqISo@A;f7Ou&0bDG#eX*c1eR#d&(#^;Il+^Nxk;P=(h**;EW8$UFEG)$QBYdDJF|ZB2(LQ@z&l zvzTqIsOw$exrmz9zkt)U<#gm**Dkrb1y09??t=4*s{&qV6!*3?73Y&X}NFqIrsE^+$uhWrSF&( zanVkX(9SLVT8H#kslnCQGUHmL)JX{B-r4TW_NJIE9rzUs=m|qExgD0ot3EpLw&?9> z2;@8AP5wyK@{d%{#zH4zm>yUF*%X7Vl2LgdacjE-H zgGl-LXXPHuBp0&tx!l~>q?a8>o|>U-o~d}L2?%JzNgxou+_WZkoTufdS|<39OPpTo zo%h1o?|)pc7wRBwxVJR^EGSq~${<0C3<5E?h{k$73)el6k#TN3x?nx1BtN@GYY!v% zg?tPyOyKh%Lh%!)!MBjt6e{2wq|F*i>|k%s*#K@N1R{$6vlo6#kqxpiMtpfoNkcJT I!94Uo0HuA#d;kCd diff --git a/website/docs/module_kitsu.md b/website/docs/module_kitsu.md index 9a85f83e3ff..05cff87fccc 100644 --- a/website/docs/module_kitsu.md +++ b/website/docs/module_kitsu.md @@ -46,8 +46,8 @@ Task status can be automatically set during publish thanks to `Integrate Kitsu N There are four settings available: - `Set status on note` -> Turns on and off this integrator. - `Note shortname` -> Which status shortname should be set automatically (Case sensitive). -- `Status conditions` -> Conditions that need to be met for kitsu status to be changed. You can add as many conditions as you like. There are two fields to each conditions: `Condition` (Whether current status should be equal or not equal to the condition status) and `Short name` (Kitsu Shortname of the condition status). -- `Family requirements` -> With this option you can add requirements to which families must be pushed or not in order to have the task status set by this integrator. There are two fields for each requirements: `Condition` (Same as the above) and `Family` (name of the family concerned by this requirement). For instance, adding one item set to `Not equal` and `workfile`, would mean the task status would change if a subset from another family than workfile is published (workfile can still be included), but not if you publish the workfile subset only. +- `Status change conditions - Status conditions` -> Conditions that need to be met for kitsu status to be changed. You can add as many conditions as you like. There are two fields to each conditions: `Condition` (Whether current status should be equal or not equal to the condition status) and `Short name` (Kitsu Shortname of the condition status). +- `Status change conditions - Family requirements` -> With this option you can add requirements to which families must be pushed or not in order to have the task status set by this integrator. There are two fields for each requirements: `Condition` (Same as the above) and `Family` (name of the family concerned by this requirement). For instance, adding one item set to `Not equal` and `workfile`, would mean the task status would change if a subset from another family than workfile is published (workfile can still be included), but not if you publish the workfile subset only. ![Integrate Kitsu Note project settings](assets/integrate_kitsu_note_settings.png) From 3af273679011d230d48aaa97a8d8468e69944c70 Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Wed, 22 Mar 2023 14:38:42 +0100 Subject: [PATCH 607/898] linted --- .../kitsu/plugins/publish/integrate_kitsu_note.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index a5253d78786..6a1b09dde19 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -65,7 +65,9 @@ def process(self, context): # Check if any status condition is not met allow_status_change = True - for status_cond in self.status_change_conditions["status_conditions"]: + for status_cond in self.status_change_conditions[ + "status_conditions" + ]: condition = status_cond["condition"] == "equal" match = status_cond["short_name"].upper() == shortname if match and not condition or condition and not match: @@ -83,13 +85,13 @@ def process(self, context): allow_status_change = False # Check if any family requirement is met - for family_requirement in self.status_change_conditions["family_requirements"]: + for family_requirement in self.status_change_conditions[ + "family_requirements" + ]: condition = family_requirement["condition"] == "equal" for family in families: - match = ( - family_requirement["family"].lower() == family - ) + match = family_requirement["family"].lower() == family if match and condition or not condition and not match: allow_status_change = True break From d861e556319bcc4f34fba481d6ec1e0aef9fbc84 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 22 Mar 2023 21:49:00 +0800 Subject: [PATCH 608/898] update the frame range settings --- openpype/hosts/max/api/lib.py | 72 ++++++++++++++--------------------- 1 file changed, 28 insertions(+), 44 deletions(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index f1d1f91dd1a..ac8f6aedfe9 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -6,13 +6,10 @@ from typing import Union import contextlib -from openpype.client import ( - get_project, - get_asset_by_name +from openpype.pipeline.context_tools import ( + get_current_project_asset, + get_current_project ) -from openpype.pipeline import legacy_io - -from openpype.pipeline.context_tools import get_current_project_asset JSON_PREFIX = "JSON::" @@ -165,7 +162,7 @@ def get_multipass_setting(project_setting=None): ["multipass"]) -def set_scene_resolution(width, height): +def set_scene_resolution(width: int, height: int): """Set the render resolution Args: @@ -189,49 +186,43 @@ def reset_scene_resolution(): Returns: None """ - project_name = legacy_io.active_project() - project_doc = get_project(project_name) - project_data = project_doc["data"] - asset_data = get_current_project_asset()["data"] - + data = ["data.resolutionWidth", "data.resolutionHeight"] + project_resolution = get_current_project(fields=data)["data"] + project_resolution_data = project_resolution["data"] + asset_resolution = get_current_project_asset(fields=data)["data"] + asset_resolution_data = asset_resolution["data"] # Set project resolution - width_key = "resolutionWidth" - height_key = "resolutionHeight" - proj_width_key = project_data.get(width_key, 1920) - proj_height_key = project_data.get(height_key, 1080) - - width = asset_data.get(width_key, proj_width_key) - height = asset_data.get(height_key, proj_height_key) + project_width = int(project_resolution_data.get("resolutionWidth", 1920)) + project_height = int(project_resolution_data.get("resolutionHeight", 1080)) + width = int(asset_resolution_data.get("resolutionWidth", project_width)) + height = int(asset_resolution_data.get("resolutionHeight", project_height)) set_scene_resolution(width, height) -def get_frame_range(): - """Get the current assets frame range and handles.""" - # Set frame start/end - project_name = legacy_io.active_project() - asset_name = legacy_io.Session["AVALON_ASSET"] - asset = get_asset_by_name(project_name, asset_name) +def get_frame_range() -> dict: + """Get the current assets frame range and handles. + Returns: + dict: with frame start, frame end, handle start, handle end. + """ + # Set frame start/end + asset = get_current_project_asset() frame_start = asset["data"].get("frameStart") frame_end = asset["data"].get("frameEnd") # Backwards compatibility if frame_start is None or frame_end is None: frame_start = asset["data"].get("edit_in") frame_end = asset["data"].get("edit_out") - if frame_start is None or frame_end is None: return - handles = asset["data"].get("handles") or 0 handle_start = asset["data"].get("handleStart") if handle_start is None: handle_start = handles - handle_end = asset["data"].get("handleEnd") if handle_end is None: handle_end = handles - return { "frameStart": frame_start, "frameEnd": frame_end, @@ -240,29 +231,24 @@ def get_frame_range(): } -def reset_frame_range(fps=True): - """Set frame range to current asset +def reset_frame_range(fps: bool=True): + """Set frame range to current asset. - Args: + This is part of 3dsmax documentation: animationRange: A System Global variable which lets you get and - set an Interval value that defines the start and end frames - of the Active Time Segment. + set an Interval value that defines the start and end frames + of the Active Time Segment. frameRate: A System Global variable which lets you get - and set an Integer value that defines the current - scene frame rate in frames-per-second. + and set an Integer value that defines the current + scene frame rate in frames-per-second. """ if fps: - fps_number = float(legacy_io.Session.get("AVALON_FPS", - 25)) + fps_number = float(get_current_project(fields=["data.fps"])["data"]["fps"]) rt.frameRate = fps_number - frame_range = get_frame_range() - frame_start = frame_range["frameStart"] - int(frame_range["handleStart"]) frame_end = frame_range["frameEnd"] + int(frame_range["handleEnd"]) - frange_cmd = f"animationRange = interval {frame_start} {frame_end}" - rt.execute(frange_cmd) @@ -281,8 +267,6 @@ def set_context_setting(): """ reset_scene_resolution() - reset_frame_range() - def get_max_version(): """ From 4e8354eec810023d83a23616c1af0d76035932a6 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 22 Mar 2023 21:54:43 +0800 Subject: [PATCH 609/898] hound fix --- openpype/hosts/max/api/lib.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index ac8f6aedfe9..09edaaa2ef6 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -182,7 +182,6 @@ def reset_scene_resolution(): scene resolution can be overwritten by an asset if the asset.data contains any information regarding scene resolution . - Returns: None """ @@ -204,7 +203,7 @@ def get_frame_range() -> dict: """Get the current assets frame range and handles. Returns: - dict: with frame start, frame end, handle start, handle end. + dict: with frame start, frame end, handle start, handle end. """ # Set frame start/end asset = get_current_project_asset() @@ -233,17 +232,18 @@ def get_frame_range() -> dict: def reset_frame_range(fps: bool=True): """Set frame range to current asset. - - This is part of 3dsmax documentation: - animationRange: A System Global variable which lets you get and - set an Interval value that defines the start and end frames - of the Active Time Segment. - frameRate: A System Global variable which lets you get - and set an Integer value that defines the current - scene frame rate in frames-per-second. + This is part of 3dsmax documentation: + + animationRange: A System Global variable which lets you get and + set an Interval value that defines the start and end frames + of the Active Time Segment. + frameRate: A System Global variable which lets you get + and set an Integer value that defines the current + scene frame rate in frames-per-second. """ if fps: - fps_number = float(get_current_project(fields=["data.fps"])["data"]["fps"]) + data_fps = get_current_project(fields=["data.fps"]) + fps_number = float(data_fps["data"]["fps"]) rt.frameRate = fps_number frame_range = get_frame_range() frame_start = frame_range["frameStart"] - int(frame_range["handleStart"]) From e373ccf4e3a747d3db3266f56478cdacfeb0aa3c Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 22 Mar 2023 21:57:19 +0800 Subject: [PATCH 610/898] hound fix --- openpype/hosts/max/api/lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index 09edaaa2ef6..c398d7cf48f 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -230,7 +230,7 @@ def get_frame_range() -> dict: } -def reset_frame_range(fps: bool=True): +def reset_frame_range(fps:bool=True): """Set frame range to current asset. This is part of 3dsmax documentation: From 57308ff488e0a2f931231a455cad13ca23eaaa7e Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 22 Mar 2023 21:58:29 +0800 Subject: [PATCH 611/898] hound fix --- openpype/hosts/max/api/lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index c398d7cf48f..aa7f72b26cb 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -230,7 +230,7 @@ def get_frame_range() -> dict: } -def reset_frame_range(fps:bool=True): +def reset_frame_range(fps: bool = True): """Set frame range to current asset. This is part of 3dsmax documentation: From 9eadc11941f4cffc6b1061f56f9751efd848c7de Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Wed, 22 Mar 2023 14:58:14 +0000 Subject: [PATCH 612/898] Update openpype/scripts/otio_burnin.py Co-authored-by: Roy Nieterau --- openpype/scripts/otio_burnin.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index bb7a208103f..e7c165ba0e2 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -684,8 +684,6 @@ def burnins_from_data( with open(in_data_json_path, "r") as file_stream: in_data = json.load(file_stream) - print(json.dumps(in_data, indent=4, sort_keys=True)) - burnins_from_data( in_data["input"], in_data["output"], From 22dac59ccf3d6269ec582c15de387fb23bc0e8e9 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 22 Mar 2023 14:58:46 +0000 Subject: [PATCH 613/898] Store burnin data as dictionary directly. --- openpype/hosts/maya/plugins/publish/collect_review.py | 6 ++---- openpype/plugins/publish/extract_burnin.py | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_review.py b/openpype/hosts/maya/plugins/publish/collect_review.py index 3d3ee09eed7..0857e8224d5 100644 --- a/openpype/hosts/maya/plugins/publish/collect_review.py +++ b/openpype/hosts/maya/plugins/publish/collect_review.py @@ -161,9 +161,7 @@ def process(self, instance): ] key = "focalLength" - instance.data[key] = focal_length - try: - instance.data["burninDataMembers"].append(key) + instance.data["burninDataMembers"][key] = focal_length except KeyError: - instance.data["burninDataMembers"] = [key] + instance.data["burninDataMembers"] = {key: focal_length} diff --git a/openpype/plugins/publish/extract_burnin.py b/openpype/plugins/publish/extract_burnin.py index de876c84862..8d29f814b56 100644 --- a/openpype/plugins/publish/extract_burnin.py +++ b/openpype/plugins/publish/extract_burnin.py @@ -255,8 +255,7 @@ def main_process(self, instance): burnin_data["custom"] = custom_data # Add data members. - for key in instance.data.get("burninDataMembers", []): - burnin_data[key] = instance.data[key] + burnin_data.update(instance.data.get("burninDataMembers", {})) # Add source camera name to burnin data camera_name = repre.get("camera_name") From f0bdc76183098782b1b42b37db8bb9386f3f864a Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 22 Mar 2023 14:59:40 +0000 Subject: [PATCH 614/898] Clean up prints --- openpype/scripts/otio_burnin.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index e7c165ba0e2..fa3f1e33893 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -641,10 +641,9 @@ def burnins_from_data( if list_to_convert: text = list_to_convert[0] cmd = convert_list_to_cmd(list_to_convert, 25.0, label=align)# need to fetch fps properly - print("cmd: " + cmd) else: text = value.format(**data) - print(text) + burnin.add_text(text, align, frame_start, frame_end, cmd=cmd) ffmpeg_args = [] From 266992f93ba45706e126358dfc47d9a18aaf015f Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Wed, 22 Mar 2023 15:00:05 +0000 Subject: [PATCH 615/898] Update openpype/scripts/otio_burnin.py Co-authored-by: Roy Nieterau --- openpype/scripts/otio_burnin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index e7c165ba0e2..5e32e8d2671 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -537,7 +537,7 @@ def burnins_from_data( if not value: continue - if isinstance(value, (dict, tuple)): + if isinstance(value, dict): raise TypeError(( "Expected string or number type." " Got: {} - \"{}\"" From 4f334a1f8061dfb8d38b176f2b8468e33df26c23 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 22 Mar 2023 15:02:31 +0000 Subject: [PATCH 616/898] Update type error message --- openpype/scripts/otio_burnin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index 58727bc6b87..142ab748afc 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -539,7 +539,7 @@ def burnins_from_data( if isinstance(value, dict): raise TypeError(( - "Expected string or number type." + "Expected string, number or list type." " Got: {} - \"{}\"" " (Make sure you have new burnin presets)." ).format(str(type(value)), str(value))) From 4f0aafe560be44bd42baff8946ff5d336bf31714 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 22 Mar 2023 15:08:32 +0000 Subject: [PATCH 617/898] Get FPS properly --- openpype/scripts/otio_burnin.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index 142ab748afc..ee29d240b2f 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -640,7 +640,9 @@ def burnins_from_data( if list_to_convert: text = list_to_convert[0] - cmd = convert_list_to_cmd(list_to_convert, 25.0, label=align)# need to fetch fps properly + cmd = convert_list_to_cmd( + list_to_convert, data["fps"], label=align + ) else: text = value.format(**data) From a364a82b7dddf64bb8178c3e6b93ccc0565328d6 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 22 Mar 2023 15:10:02 +0000 Subject: [PATCH 618/898] Hound --- openpype/scripts/otio_burnin.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index ee29d240b2f..4bbb684deb3 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -174,7 +174,13 @@ def __init__( self.options_init.update(options_init) def add_text( - self, text, align, frame_start=None, frame_end=None, options=None, cmd="" + self, + text, + align, + frame_start=None, + frame_end=None, + options=None, + cmd="" ): """ Adding static text to a filter. @@ -450,11 +456,13 @@ def burnins_from_data( True by default. Presets must be set separately. Should be dict with 2 keys: - - "options" - sets look of burnins - colors, opacity,...(more info: ModifiedBurnins doc) + - "options" - sets look of burnins - colors, opacity,... + (more info: ModifiedBurnins doc) - *OPTIONAL* default values are used when not included - "burnins" - contains dictionary with burnins settings - *OPTIONAL* burnins won't be added (easier is not to use this) - - each key of "burnins" represents Alignment, there are 6 possibilities: + - each key of "burnins" represents Alignment, + there are 6 possibilities: TOP_LEFT TOP_CENTERED TOP_RIGHT BOTTOM_LEFT BOTTOM_CENTERED BOTTOM_RIGHT - value must be string with text you want to burn-in From 84817a77a33d4e0236ca7cdc9e7300665f77571c Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 22 Mar 2023 15:42:45 +0000 Subject: [PATCH 619/898] Code cosmetics --- .../hosts/maya/plugins/publish/collect_review.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_review.py b/openpype/hosts/maya/plugins/publish/collect_review.py index 0857e8224d5..ce11e8a71f1 100644 --- a/openpype/hosts/maya/plugins/publish/collect_review.py +++ b/openpype/hosts/maya/plugins/publish/collect_review.py @@ -5,6 +5,7 @@ from openpype.client import get_subset_by_name from openpype.pipeline import legacy_io +from openpype.hosts.maya.api.lib import get_attribute_input class CollectReview(pyblish.api.InstancePlugin): @@ -146,19 +147,16 @@ def process(self, instance): ) # Collect focal length. - #Refactor to lib or use available lib method. - plug = "{0}.focalLength".format(camera) + attr = camera + ".focalLength" focal_length = None - if not cmds.listConnections(plug, destination=False, source=True): - # Static. - focal_length = cmds.getAttr(plug) - else: - # Dynamic. + if get_attribute_input(attr): start = instance.data["frameStart"] end = instance.data["frameEnd"] + 1 focal_length = [ - cmds.getAttr(plug, time=t) for t in range(int(start), int(end)) + cmds.getAttr(attr, time=t) for t in range(int(start), int(end)) ] + else: + focal_length = cmds.getAttr(attr) key = "focalLength" try: From 7ff781f3bddff9b5923789cb3406e67162c43c1a Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 22 Mar 2023 16:32:41 +0000 Subject: [PATCH 620/898] Clean up temporary files and support float truncating --- openpype/scripts/otio_burnin.py | 89 +++++++++++++++++---------------- 1 file changed, 47 insertions(+), 42 deletions(-) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index 4bbb684deb3..afae4f9e08f 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -41,9 +41,8 @@ SOURCE_TIMECODE_KEY = "{source_timecode}" -def convert_list_to_cmd(list_to_convert, fps, label=""): +def convert_list_to_commands(list_to_convert, fps, label=""): path = None - #need to clean up temp file when done with tempfile.NamedTemporaryFile(mode="w", delete=False) as f: for i, value in enumerate(list_to_convert): seconds = i / fps @@ -63,10 +62,8 @@ def convert_list_to_cmd(list_to_convert, fps, label=""): f.write(line) f.flush() path = f.name - path = path.replace("\\", "/") - path = path.replace(":", "\\:") - return "sendcmd=f='{}'".format(path) + return path def _get_ffprobe_data(source): @@ -541,6 +538,7 @@ def burnins_from_data( if source_timecode is not None: data[SOURCE_TIMECODE_KEY[1:-1]] = SOURCE_TIMECODE_KEY + clean_up_paths = [] for align_text, value in burnin_values.items(): if not value: continue @@ -583,8 +581,48 @@ def burnins_from_data( print("Source does not have set timecode value.") value = value.replace(SOURCE_TIMECODE_KEY, MISSING_KEY_VALUE) - key_pattern = re.compile(r"(\{.*?[^{0]*\})") + # Convert lists. + cmd = "" + text = None + keys = [i[1] for i in Formatter().parse(value) if i[1] is not None] + list_to_convert = [] + + # Warn about nested dictionary support for lists. Ei. we dont support + # it. + if "[" in "".join(keys): + print( + "We dont support converting nested dictionaries to lists," + " so skipping {}".format(value) + ) + else: + for key in keys: + data_value = data[key] + + # Multiple lists are not supported. + if isinstance(data_value, list) and list_to_convert: + raise ValueError( + "Found multiple lists to convert, which is not " + "supported: {}".format(value) + ) + if isinstance(data_value, list): + print("Found list to convert: {}".format(data_value)) + for v in data_value: + data[key] = v + list_to_convert.append(value.format(**data)) + + if list_to_convert: + value = list_to_convert[0] + path = convert_list_to_commands( + list_to_convert, data["fps"], label=align + ) + cmd = "sendcmd=f='{}'".format(path) + cmd = cmd.replace("\\", "/") + cmd = cmd.replace(":", "\\:") + clean_up_paths.append(path) + + # Failsafe for missing keys. + key_pattern = re.compile(r"(\{.*?[^{0]*\})") missing_keys = [] for group in key_pattern.findall(value): try: @@ -617,42 +655,7 @@ def burnins_from_data( burnin.add_timecode(*args) continue - cmd = "" - text = None - keys = [i[1] for i in Formatter().parse(value) if i[1] is not None] - list_to_convert = [] - - # Warn about nested dictionary support for lists. Ei. we dont support - # it. - if "[" in "".join(keys): - print( - "We dont support converting nested dictionaries to lists," - " so skipping {}".format(value) - ) - else: - for key in keys: - data_value = data[key] - - # Multiple lists are not supported. - if isinstance(data_value, list) and list_to_convert: - raise ValueError( - "Found multiple lists to convert, which is not " - "supported: {}".format(value) - ) - - if isinstance(data_value, list): - print("Found list to convert: {}".format(data_value)) - for v in data_value: - data[key] = v - list_to_convert.append(value.format(**data)) - - if list_to_convert: - text = list_to_convert[0] - cmd = convert_list_to_cmd( - list_to_convert, data["fps"], label=align - ) - else: - text = value.format(**data) + text = value.format(**data) burnin.add_text(text, align, frame_start, frame_end, cmd=cmd) @@ -685,6 +688,8 @@ def burnins_from_data( burnin.render( output_path, args=ffmpeg_args_str, overwrite=overwrite, **data ) + for path in clean_up_paths: + os.remove(path) if __name__ == "__main__": From 833e48ae0f5f31e57b920950a0f5cea38a967263 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 22 Mar 2023 16:43:56 +0000 Subject: [PATCH 621/898] Docs --- website/docs/pype2/admin_presets_plugins.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/docs/pype2/admin_presets_plugins.md b/website/docs/pype2/admin_presets_plugins.md index fcdc09439b9..2a30e7e8e95 100644 --- a/website/docs/pype2/admin_presets_plugins.md +++ b/website/docs/pype2/admin_presets_plugins.md @@ -293,6 +293,7 @@ If source representation has suffix **"h264"** and burnin suffix is **"client"** - It is allowed to use [Anatomy templates](admin_config#anatomy) themselves in burnins if they can be filled with available data. - Additional keys in burnins: + | Burnin key | Description | | --- | --- | | frame_start | First frame number. | @@ -303,6 +304,7 @@ If source representation has suffix **"h264"** and burnin suffix is **"client"** | resolution_height | Resolution height. | | fps | Fps of an output. | | timecode | Timecode by frame start and fps. | + | focalLength | **Only available in Maya**

    Camera focal length per frame. Use syntax `{focalLength:.2f}` for decimal truncating. Eg. `35.234985` with `{focalLength:.2f}` would produce `35.23`, whereas `{focalLength:.0f}` would produce `35`. | :::warning `timecode` is specific key that can be **only at the end of content**. (`"BOTTOM_RIGHT": "TC: {timecode}"`) From 62ced23858534c081c4aee84714b236507e64439 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 23 Mar 2023 00:45:58 +0800 Subject: [PATCH 622/898] remove irrelevant attrs of data --- openpype/hosts/max/api/lib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index aa7f72b26cb..ac7d75db086 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -186,9 +186,9 @@ def reset_scene_resolution(): None """ data = ["data.resolutionWidth", "data.resolutionHeight"] - project_resolution = get_current_project(fields=data)["data"] + project_resolution = get_current_project(fields=data) project_resolution_data = project_resolution["data"] - asset_resolution = get_current_project_asset(fields=data)["data"] + asset_resolution = get_current_project_asset(fields=data) asset_resolution_data = asset_resolution["data"] # Set project resolution project_width = int(project_resolution_data.get("resolutionWidth", 1920)) From 499351a2807e58ed8bf770b63566b2b34e6d8fae Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 23 Mar 2023 00:47:18 +0800 Subject: [PATCH 623/898] remove irrelevant attributes --- openpype/hosts/max/api/lib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index ac1d1587923..39657a25256 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -187,9 +187,9 @@ def reset_scene_resolution(): None """ data = ["data.resolutionWidth", "data.resolutionHeight"] - project_resolution = get_current_project(fields=data)["data"] + project_resolution = get_current_project(fields=data) project_resolution_data = project_resolution["data"] - asset_resolution = get_current_project_asset(fields=data)["data"] + asset_resolution = get_current_project_asset(fields=data) asset_resolution_data = asset_resolution["data"] # Set project resolution project_width = int(project_resolution_data.get("resolutionWidth", 1920)) From f823b065d312c8f9dc24d10d51ebcb014319866c Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 22 Mar 2023 22:36:11 +0100 Subject: [PATCH 624/898] celaction: moving conditional workfile parameters into settings --- .../celaction/hooks/pre_celaction_setup.py | 22 +++++++++++-------- .../publish/collect_celaction_cli_kwargs.py | 2 +- .../defaults/project_settings/celaction.json | 9 ++++++++ .../schema_project_celaction.json | 14 ++++++++++++ 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/openpype/hosts/celaction/hooks/pre_celaction_setup.py b/openpype/hosts/celaction/hooks/pre_celaction_setup.py index 62cebf99ed2..7506f1a52cb 100644 --- a/openpype/hosts/celaction/hooks/pre_celaction_setup.py +++ b/openpype/hosts/celaction/hooks/pre_celaction_setup.py @@ -38,8 +38,9 @@ def execute(self): ) path_to_cli = os.path.join(CELACTION_SCRIPTS_DIR, "publish_cli.py") - subproces_args = get_openpype_execute_args("run", path_to_cli) - openpype_executable = subproces_args.pop(0) + subprocess_args = get_openpype_execute_args("run", path_to_cli) + openpype_executable = subprocess_args.pop(0) + workfile_settings = self.get_workfile_settings() winreg.SetValueEx( hKey, @@ -49,15 +50,15 @@ def execute(self): openpype_executable ) - parameters = subproces_args + [ - "--currentFile", "*SCENE*", - "--chunk", "*CHUNK*", - "--frameStart", "*START*", - "--frameEnd", "*END*", - "--resolutionWidth", "*X*", - "--resolutionHeight", "*Y*" + # add required arguments for workfile path + parameters = subprocess_args + [ + "--currentFile", "*SCENE*" ] + # Add custom parameters from workfile settings + if workfile_settings["parameters"]: + parameters += workfile_settings["parameters"] + winreg.SetValueEx( hKey, "SubmitParametersTitle", 0, winreg.REG_SZ, subprocess.list2cmdline(parameters) @@ -135,3 +136,6 @@ def workfile_path(self): self.log.info(f"Workfile to open: \"{workfile_path}\"") return workfile_path + + def get_workfile_settings(self): + return self.data["project_settings"]["celaction"]["workfile"] diff --git a/openpype/hosts/celaction/plugins/publish/collect_celaction_cli_kwargs.py b/openpype/hosts/celaction/plugins/publish/collect_celaction_cli_kwargs.py index 43b81b83e7e..54dea15dffc 100644 --- a/openpype/hosts/celaction/plugins/publish/collect_celaction_cli_kwargs.py +++ b/openpype/hosts/celaction/plugins/publish/collect_celaction_cli_kwargs.py @@ -39,7 +39,7 @@ def process(self, context): passing_kwargs[key] = value if missing_kwargs: - raise RuntimeError("Missing arguments {}".format( + self.log.debug("Missing arguments {}".format( ", ".join( [f'"{key}"' for key in missing_kwargs] ) diff --git a/openpype/settings/defaults/project_settings/celaction.json b/openpype/settings/defaults/project_settings/celaction.json index bdba6d73227..0194b2c48c3 100644 --- a/openpype/settings/defaults/project_settings/celaction.json +++ b/openpype/settings/defaults/project_settings/celaction.json @@ -9,6 +9,15 @@ "rules": {} } }, + "workfile": { + "parameters": [ + "--chunk *CHUNK*", + "--frameStart *START*", + "--frameEnd *END*", + "--resolutionWidth *X*", + "--resolutionHeight *Y*" + ] + }, "publish": { "CollectRenderPath": { "output_extension": "png", diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_celaction.json b/openpype/settings/entities/schemas/projects_schema/schema_project_celaction.json index 2320d9ae266..4ca3cbb4da2 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_celaction.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_celaction.json @@ -22,6 +22,20 @@ ] }, + { + "type": "dict", + "collapsible": true, + "key": "workfile", + "label": "Workfile", + "children": [ + { + "key": "parameters", + "label": "Parameters", + "type": "list", + "object_type": "text" + } + ] + }, { "type": "dict", "collapsible": true, From 230139baf6dfdad8b131b2547ce76d474f11f777 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 22 Mar 2023 23:32:19 +0100 Subject: [PATCH 625/898] Fix some minor grammar/typos --- .../docs/project_settings/settings_project_global.md | 10 +++++----- website/docs/pype2/admin_presets_plugins.md | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/website/docs/project_settings/settings_project_global.md b/website/docs/project_settings/settings_project_global.md index 6c1a269b1f0..b6d624caa85 100644 --- a/website/docs/project_settings/settings_project_global.md +++ b/website/docs/project_settings/settings_project_global.md @@ -82,8 +82,8 @@ All context filters are lists which may contain strings or Regular expressions ( - **`tasks`** - Currently processed task. `["modeling", "animation"]` :::important Filtering -Filters are optional. In case when multiple profiles match current context, profile with higher number of matched filters has higher priority that profile without filters. -(Eg. order of when filter is added doesn't matter, only the precision of matching does.) +Filters are optional. In case when multiple profiles match current context, profile with higher number of matched filters has higher priority than profile without filters. +(The order the profiles in settings doesn't matter, only the precision of matching does.) ::: ## Publish plugins @@ -94,7 +94,7 @@ Publish plugins used across all integrations. ### Extract Review Plugin responsible for automatic FFmpeg conversion to variety of formats. -Extract review is using [profile filtering](#profile-filters) to be able render different outputs for different situations. +Extract review uses [profile filtering](#profile-filters) to render different outputs for different situations. Applicable context filters: **`hosts`** - Host from which publishing was triggered. `["maya", "nuke"]` @@ -104,7 +104,7 @@ Applicable context filters: **Output Definitions** -Profile may generate multiple outputs from a single input. Each output must define unique name and output extension (use the extension without a dot e.g. **mp4**). All other settings of output definition are optional. +A profile may generate multiple outputs from a single input. Each output must define unique name and output extension (use the extension without a dot e.g. **mp4**). All other settings of output definition are optional. ![global_extract_review_output_defs](assets/global_extract_review_output_defs.png) - **`Tags`** @@ -118,7 +118,7 @@ Profile may generate multiple outputs from a single input. Each output must defi - **Output arguments** other FFmpeg output arguments like codec definition. - **`Output width`** and **`Output height`** - - it is possible to rescale output to specified resolution and keep aspect ratio. + - It is possible to rescale output to specified resolution and keep aspect ratio. - If value is set to 0, source resolution will be used. - **`Overscan crop`** diff --git a/website/docs/pype2/admin_presets_plugins.md b/website/docs/pype2/admin_presets_plugins.md index fcdc09439b9..e589f7d14be 100644 --- a/website/docs/pype2/admin_presets_plugins.md +++ b/website/docs/pype2/admin_presets_plugins.md @@ -36,7 +36,7 @@ All context filters are lists which may contain strings or Regular expressions ( - **families** - Main family of processed instance. `["plate", "model"]` :::important Filtering -Filters are optional and may not be set. In case when multiple profiles match current context, profile with filters has higher priority that profile without filters. +Filters are optional and may not be set. In case when multiple profiles match current context, profile with filters has higher priority than profile without filters. ::: #### Profile outputs From 654bef0afcfb5159b541b38c7abd5e4ae50c307e Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 22 Mar 2023 23:53:30 +0100 Subject: [PATCH 626/898] Tweak logging - preserve order and clarify versions with groups --- openpype/lib/applications.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/openpype/lib/applications.py b/openpype/lib/applications.py index 7cc296f47bc..e9d49337f9b 100644 --- a/openpype/lib/applications.py +++ b/openpype/lib/applications.py @@ -1508,8 +1508,8 @@ def prepare_app_environments( if key in source_env: source_env[key] = value - # `added_env_keys` has debug purpose - added_env_keys = {app.group.name, app.name} + # `app_and_tool_labels` has debug purpose + app_and_tool_labels = ["/".join([app.group.name, app.name])] # Environments for application environments = [ app.group.environment, @@ -1532,15 +1532,14 @@ def prepare_app_environments( for group_name in sorted(groups_by_name.keys()): group = groups_by_name[group_name] environments.append(group.environment) - added_env_keys.add(group_name) for tool_name in sorted(tool_by_group_name[group_name].keys()): tool = tool_by_group_name[group_name][tool_name] environments.append(tool.environment) - added_env_keys.add(tool.name) + app_and_tool_labels.append("/".join([group_name, tool_name])) log.debug( "Will add environments for apps and tools: {}".format( - ", ".join(added_env_keys) + ", ".join(app_and_tool_labels) ) ) From aa6dc207f1cad419fd968dfd85d6d0b1923d55ba Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 23 Mar 2023 00:45:50 +0100 Subject: [PATCH 627/898] Fix grammar --- openpype/hosts/blender/api/ops.py | 4 ++-- openpype/hosts/photoshop/api/launch_logic.py | 4 ++-- openpype/hosts/tvpaint/api/communication_server.py | 4 ++-- openpype/tools/utils/lib.py | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/blender/api/ops.py b/openpype/hosts/blender/api/ops.py index b1fa13acb9d..158c32fb5a2 100644 --- a/openpype/hosts/blender/api/ops.py +++ b/openpype/hosts/blender/api/ops.py @@ -84,11 +84,11 @@ def __init__(self, callback, *args, **kwargs): self.kwargs = kwargs def execute(self): - """Execute callback and store it's result. + """Execute callback and store its result. Method must be called from main thread. Item is marked as `done` when callback execution finished. Store output of callback of exception - information when callback raise one. + information when callback raises one. """ print("Executing process in main thread") if self.done: diff --git a/openpype/hosts/photoshop/api/launch_logic.py b/openpype/hosts/photoshop/api/launch_logic.py index 89ba6ad4e6c..25732446b51 100644 --- a/openpype/hosts/photoshop/api/launch_logic.py +++ b/openpype/hosts/photoshop/api/launch_logic.py @@ -66,11 +66,11 @@ def result(self): return self._result def execute(self): - """Execute callback and store it's result. + """Execute callback and store its result. Method must be called from main thread. Item is marked as `done` when callback execution finished. Store output of callback of exception - information when callback raise one. + information when callback raises one. """ log.debug("Executing process in main thread") if self.done: diff --git a/openpype/hosts/tvpaint/api/communication_server.py b/openpype/hosts/tvpaint/api/communication_server.py index e94e64e04a6..6f76c25e0ce 100644 --- a/openpype/hosts/tvpaint/api/communication_server.py +++ b/openpype/hosts/tvpaint/api/communication_server.py @@ -389,11 +389,11 @@ def __init__(self, callback, *args, **kwargs): self.kwargs = kwargs def execute(self): - """Execute callback and store it's result. + """Execute callback and store its result. Method must be called from main thread. Item is marked as `done` when callback execution finished. Store output of callback of exception - information when callback raise one. + information when callback raises one. """ log.debug("Executing process in main thread") if self.done: diff --git a/openpype/tools/utils/lib.py b/openpype/tools/utils/lib.py index 8d38f03b8d9..950c782727b 100644 --- a/openpype/tools/utils/lib.py +++ b/openpype/tools/utils/lib.py @@ -862,11 +862,11 @@ def result(self): return self._result def execute(self): - """Execute callback and store it's result. + """Execute callback and store its result. Method must be called from main thread. Item is marked as `done` when callback execution finished. Store output of callback of exception - information when callback raise one. + information when callback raises one. """ if self.done: self.log.warning("- item is already processed") From fb6c1f7f350d8f525e9db61851a0801c18f80669 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 23 Mar 2023 00:48:13 +0100 Subject: [PATCH 628/898] Fix grammar --- openpype/hooks/pre_foundry_apps.py | 4 ++-- openpype/modules/example_addons/example_addon/addon.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/hooks/pre_foundry_apps.py b/openpype/hooks/pre_foundry_apps.py index 2092d5025dc..21ec8e78814 100644 --- a/openpype/hooks/pre_foundry_apps.py +++ b/openpype/hooks/pre_foundry_apps.py @@ -7,7 +7,7 @@ class LaunchFoundryAppsWindows(PreLaunchHook): Nuke is executed "like" python process so it is required to pass `CREATE_NEW_CONSOLE` flag on windows to trigger creation of new console. - At the same time the newly created console won't create it's own stdout + At the same time the newly created console won't create its own stdout and stderr handlers so they should not be redirected to DEVNULL. """ @@ -18,7 +18,7 @@ class LaunchFoundryAppsWindows(PreLaunchHook): def execute(self): # Change `creationflags` to CREATE_NEW_CONSOLE - # - on Windows will nuke create new window using it's console + # - on Windows nuke will create new window using its console # Set `stdout` and `stderr` to None so new created console does not # have redirected output to DEVNULL in build self.launch_context.kwargs.update({ diff --git a/openpype/modules/example_addons/example_addon/addon.py b/openpype/modules/example_addons/example_addon/addon.py index ead647b41d0..be1d3ff9205 100644 --- a/openpype/modules/example_addons/example_addon/addon.py +++ b/openpype/modules/example_addons/example_addon/addon.py @@ -44,7 +44,7 @@ def get_settings_root_path(self): class ExampleAddon(OpenPypeAddOn, IPluginPaths, ITrayAction): - """This Addon has defined it's settings and interface. + """This Addon has defined its settings and interface. This example has system settings with an enabled option. And use few other interfaces: From 47052f7445316e49dff631c91c5967ea7a60b486 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 23 Mar 2023 11:15:51 +0800 Subject: [PATCH 629/898] incrment workfile version --- .../publish/increment_workfile_version.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 openpype/hosts/max/plugins/publish/increment_workfile_version.py diff --git a/openpype/hosts/max/plugins/publish/increment_workfile_version.py b/openpype/hosts/max/plugins/publish/increment_workfile_version.py new file mode 100644 index 00000000000..eda8cd7677c --- /dev/null +++ b/openpype/hosts/max/plugins/publish/increment_workfile_version.py @@ -0,0 +1,20 @@ +import pyblish.api +from openpype.lib import version_up +from pymxs import runtime as rt + + +class IncrementWorkfileVersion(pyblish.api.ContextPlugin): + """Increment current workfile version.""" + + order = pyblish.api.IntegratorOrder + 0.9 + label = "Increment Workfile Version" + optional = True + hosts = ["max"] + families = ["workfile"] + + def process(self, context): + path = context.data["currentFile"] + filepath = version_up(path) + + rt.saveMaxFile(filepath) + self.log.info('Incrementing file version') From 2130f3d826dbb4e156f02acc680596091a1b4ce8 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 23 Mar 2023 11:19:46 +0800 Subject: [PATCH 630/898] remove optional --- openpype/hosts/max/plugins/publish/increment_workfile_version.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/max/plugins/publish/increment_workfile_version.py b/openpype/hosts/max/plugins/publish/increment_workfile_version.py index eda8cd7677c..7b4f4e238d6 100644 --- a/openpype/hosts/max/plugins/publish/increment_workfile_version.py +++ b/openpype/hosts/max/plugins/publish/increment_workfile_version.py @@ -8,7 +8,6 @@ class IncrementWorkfileVersion(pyblish.api.ContextPlugin): order = pyblish.api.IntegratorOrder + 0.9 label = "Increment Workfile Version" - optional = True hosts = ["max"] families = ["workfile"] From f681e9843d03a04ef2e5f413b3cc32953c45ced4 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 23 Mar 2023 09:50:28 +0100 Subject: [PATCH 631/898] Extract Review code refactor (#3930) * Tweak variable names * Use `filter_profiles` from lib * Fix type fallback * Simplify additional family filters * Use legacy_io.Session instead of os.environ * Fix logging message * Indent todo comment for better todo highlighting in Pycharm * Simplify gap filling logic * Optimize getting nearest frames * Fix logic for nearest frame - This fixes cases where nearest frame isn't directly the next frame * Refactor `index` in variable `idx` to match `missing_idx` naming * Use `filter_profiles` from lib * Match family filter validation of extract review * Fix typo `overscal` -> `overscan` * Use `legacy_io.Session` instead of `os.environ` * Remove unused import * use 'KnownPublishError' instead of 'AssertionError' * modify nearest frame logic in holes fill * Fix unsupported indexing of clique Collection + slightly simplify --------- Co-authored-by: Jakub Trllo --- openpype/plugins/publish/extract_burnin.py | 33 +- openpype/plugins/publish/extract_review.py | 398 ++++----------------- 2 files changed, 83 insertions(+), 348 deletions(-) diff --git a/openpype/plugins/publish/extract_burnin.py b/openpype/plugins/publish/extract_burnin.py index 38ec08e8d97..44ba4a5025d 100644 --- a/openpype/plugins/publish/extract_burnin.py +++ b/openpype/plugins/publish/extract_burnin.py @@ -725,7 +725,6 @@ def filter_burnins_defs(self, profile, instance): return filtered_burnin_defs families = self.families_from_instance(instance) - low_families = [family.lower() for family in families] for filename_suffix, orig_burnin_def in burnin_defs.items(): burnin_def = copy.deepcopy(orig_burnin_def) @@ -736,7 +735,7 @@ def filter_burnins_defs(self, profile, instance): families_filters = def_filter["families"] if not self.families_filter_validation( - low_families, families_filters + families, families_filters ): self.log.debug(( "Skipped burnin definition \"{}\". Family" @@ -773,31 +772,19 @@ def filter_burnins_defs(self, profile, instance): return filtered_burnin_defs def families_filter_validation(self, families, output_families_filter): - """Determine if entered families intersect with families filters. + """Determines if entered families intersect with families filters. All family values are lowered to avoid unexpected results. """ - if not output_families_filter: - return True - - for family_filter in output_families_filter: - if not family_filter: - continue - - if not isinstance(family_filter, (list, tuple)): - if family_filter.lower() not in families: - continue - return True - valid = True - for family in family_filter: - if family.lower() not in families: - valid = False - break - - if valid: - return True - return False + families_filter_lower = set(family.lower() for family in + output_families_filter + # Exclude empty filter values + if family) + if not families_filter_lower: + return True + return any(family.lower() in families_filter_lower + for family in families) def families_from_instance(self, instance): """Return all families of entered instance.""" diff --git a/openpype/plugins/publish/extract_review.py b/openpype/plugins/publish/extract_review.py index acb1fc10bf7..7de92a8bbda 100644 --- a/openpype/plugins/publish/extract_review.py +++ b/openpype/plugins/publish/extract_review.py @@ -12,7 +12,7 @@ from openpype.lib import ( get_ffmpeg_tool_path, - + filter_profiles, path_to_subprocess_arg, run_subprocess, ) @@ -23,6 +23,7 @@ convert_input_paths_for_ffmpeg, get_transcode_temp_directory, ) +from openpype.pipeline.publish import KnownPublishError class ExtractReview(pyblish.api.InstancePlugin): @@ -88,21 +89,23 @@ def process(self, instance): def _get_outputs_for_instance(self, instance): host_name = instance.context.data["hostName"] - task_name = os.environ["AVALON_TASK"] family = self.main_family_from_instance(instance) self.log.info("Host: \"{}\"".format(host_name)) - self.log.info("Task: \"{}\"".format(task_name)) self.log.info("Family: \"{}\"".format(family)) - profile = self.find_matching_profile( - host_name, task_name, family - ) + profile = filter_profiles( + self.profiles, + { + "hosts": host_name, + "families": family, + }, + logger=self.log) if not profile: self.log.info(( "Skipped instance. None of profiles in presets are for" - " Host: \"{}\" | Family: \"{}\" | Task \"{}\"" - ).format(host_name, family, task_name)) + " Host: \"{}\" | Family: \"{}\"" + ).format(host_name, family)) return self.log.debug("Matching profile: \"{}\"".format(json.dumps(profile))) @@ -112,17 +115,19 @@ def _get_outputs_for_instance(self, instance): filtered_outputs = self.filter_output_defs( profile, subset_name, instance_families ) + if not filtered_outputs: + self.log.info(( + "Skipped instance. All output definitions from selected" + " profile do not match instance families \"{}\" or" + " subset name \"{}\"." + ).format(str(instance_families), subset_name)) + # Store `filename_suffix` to save arguments profile_outputs = [] for filename_suffix, definition in filtered_outputs.items(): definition["filename_suffix"] = filename_suffix profile_outputs.append(definition) - if not filtered_outputs: - self.log.info(( - "Skipped instance. All output definitions from selected" - " profile does not match to instance families. \"{}\"" - ).format(str(instance_families))) return profile_outputs def _get_outputs_per_representations(self, instance, profile_outputs): @@ -216,6 +221,7 @@ def main_process(self, instance): outputs_per_repres = self._get_outputs_per_representations( instance, profile_outputs ) + for repre, output_defs in outputs_per_repres: # Check if input should be preconverted before processing # Store original staging dir (it's value may change) @@ -297,10 +303,10 @@ def main_process(self, instance): shutil.rmtree(new_staging_dir) def _render_output_definitions( - self, instance, repre, src_repre_staging_dir, output_defs + self, instance, repre, src_repre_staging_dir, output_definitions ): fill_data = copy.deepcopy(instance.data["anatomyData"]) - for _output_def in output_defs: + for _output_def in output_definitions: output_def = copy.deepcopy(_output_def) # Make sure output definition has "tags" key if "tags" not in output_def: @@ -346,10 +352,11 @@ def _render_output_definitions( if temp_data["input_is_sequence"]: self.log.info("Filling gaps in sequence.") files_to_clean = self.fill_sequence_gaps( - temp_data["origin_repre"]["files"], - new_repre["stagingDir"], - temp_data["frame_start"], - temp_data["frame_end"]) + files=temp_data["origin_repre"]["files"], + staging_dir=new_repre["stagingDir"], + start_frame=temp_data["frame_start"], + end_frame=temp_data["frame_end"] + ) # create or update outputName output_name = new_repre.get("outputName", "") @@ -421,10 +428,10 @@ def _render_output_definitions( def input_is_sequence(self, repre): """Deduce from representation data if input is sequence.""" # TODO GLOBAL ISSUE - Find better way how to find out if input - # is sequence. Issues( in theory): - # - there may be multiple files ant not be sequence - # - remainders are not checked at all - # - there can be more than one collection + # is sequence. Issues (in theory): + # - there may be multiple files ant not be sequence + # - remainders are not checked at all + # - there can be more than one collection return isinstance(repre["files"], (list, tuple)) def prepare_temp_data(self, instance, repre, output_def): @@ -816,76 +823,41 @@ def fill_sequence_gaps(self, files, staging_dir, start_frame, end_frame): is done. Raises: - AssertionError: if more then one collection is obtained. - + KnownPublishError: if more than one collection is obtained. """ - start_frame = int(start_frame) - end_frame = int(end_frame) - collections = clique.assemble(files)[0] - msg = "Multiple collections {} found.".format(collections) - assert len(collections) == 1, msg - col = collections[0] - # do nothing if no gap is found in input range - not_gap = True - for fr in range(start_frame, end_frame + 1): - if fr not in col.indexes: - not_gap = False + collections = clique.assemble(files)[0] + if len(collections) != 1: + raise KnownPublishError( + "Multiple collections {} found.".format(collections)) - if not_gap: - return [] + col = collections[0] - holes = col.holes() - - # generate ideal sequence - complete_col = clique.assemble( - [("{}{:0" + str(col.padding) + "d}{}").format( - col.head, f, col.tail - ) for f in range(start_frame, end_frame)] - )[0][0] # type: clique.Collection - - new_files = {} - last_existing_file = None - - for idx in holes.indexes: - # get previous existing file - test_file = os.path.normpath(os.path.join( - staging_dir, - ("{}{:0" + str(complete_col.padding) + "d}{}").format( - complete_col.head, idx - 1, complete_col.tail))) - if os.path.isfile(test_file): - new_files[idx] = test_file - last_existing_file = test_file + # Prepare which hole is filled with what frame + # - the frame is filled only with already existing frames + prev_frame = next(iter(col.indexes)) + hole_frame_to_nearest = {} + for frame in range(int(start_frame), int(end_frame) + 1): + if frame in col.indexes: + prev_frame = frame else: - if not last_existing_file: - # previous file is not found (sequence has a hole - # at the beginning. Use first available frame - # there is. - try: - last_existing_file = list(col)[0] - except IndexError: - # empty collection? - raise AssertionError( - "Invalid sequence collected") - new_files[idx] = os.path.normpath( - os.path.join(staging_dir, last_existing_file)) - - files_to_clean = [] - if new_files: - # so now new files are dict with missing frame as a key and - # existing file as a value. - for frame, file in new_files.items(): - self.log.info( - "Filling gap {} with {}".format(frame, file)) + # Use previous frame as source for hole + hole_frame_to_nearest[frame] = prev_frame + + # Calculate paths + added_files = [] + col_format = col.format("{head}{padding}{tail}") + for hole_frame, src_frame in hole_frame_to_nearest.items(): + hole_fpath = os.path.join(staging_dir, col_format % hole_frame) + src_fpath = os.path.join(staging_dir, col_format % src_frame) + if not os.path.isfile(src_fpath): + raise KnownPublishError( + "Missing previously detected file: {}".format(src_fpath)) - hole = os.path.join( - staging_dir, - ("{}{:0" + str(col.padding) + "d}{}").format( - col.head, frame, col.tail)) - speedcopy.copyfile(file, hole) - files_to_clean.append(hole) + speedcopy.copyfile(src_fpath, hole_fpath) + added_files.append(hole_fpath) - return files_to_clean + return added_files def input_output_paths(self, new_repre, output_def, temp_data): """Deduce input nad output file paths based on entered data. @@ -1281,7 +1253,7 @@ def rescaling_filters(self, temp_data, output_def, new_repre): # 'use_input_res' is set to 'True'. use_input_res = False - # Overscal color + # Overscan color overscan_color_value = "black" overscan_color = output_def.get("overscan_color") if overscan_color: @@ -1468,240 +1440,20 @@ def families_from_instance(self, instance): families.append(family) return families - def compile_list_of_regexes(self, in_list): - """Convert strings in entered list to compiled regex objects.""" - regexes = [] - if not in_list: - return regexes - - for item in in_list: - if not item: - continue - - try: - regexes.append(re.compile(item)) - except TypeError: - self.log.warning(( - "Invalid type \"{}\" value \"{}\"." - " Expected string based object. Skipping." - ).format(str(type(item)), str(item))) - - return regexes - - def validate_value_by_regexes(self, value, in_list): - """Validates in any regex from list match entered value. - - Args: - in_list (list): List with regexes. - value (str): String where regexes is checked. - - Returns: - int: Returns `0` when list is not set or is empty. Returns `1` when - any regex match value and returns `-1` when none of regexes - match value entered. - """ - if not in_list: - return 0 - - output = -1 - regexes = self.compile_list_of_regexes(in_list) - for regex in regexes: - if not value: - continue - if re.match(regex, value): - output = 1 - break - return output - - def profile_exclusion(self, matching_profiles): - """Find out most matching profile byt host, task and family match. - - Profiles are selectively filtered. Each profile should have - "__value__" key with list of booleans. Each boolean represents - existence of filter for specific key (host, tasks, family). - Profiles are looped in sequence. In each sequence are split into - true_list and false_list. For next sequence loop are used profiles in - true_list if there are any profiles else false_list is used. - - Filtering ends when only one profile left in true_list. Or when all - existence booleans loops passed, in that case first profile from left - profiles is returned. - - Args: - matching_profiles (list): Profiles with same values. - - Returns: - dict: Most matching profile. - """ - self.log.info( - "Search for first most matching profile in match order:" - " Host name -> Task name -> Family." - ) - # Filter all profiles with highest points value. First filter profiles - # with matching host if there are any then filter profiles by task - # name if there are any and lastly filter by family. Else use first in - # list. - idx = 0 - final_profile = None - while True: - profiles_true = [] - profiles_false = [] - for profile in matching_profiles: - value = profile["__value__"] - # Just use first profile when idx is greater than values. - if not idx < len(value): - final_profile = profile - break - - if value[idx]: - profiles_true.append(profile) - else: - profiles_false.append(profile) - - if final_profile is not None: - break - - if profiles_true: - matching_profiles = profiles_true - else: - matching_profiles = profiles_false - - if len(matching_profiles) == 1: - final_profile = matching_profiles[0] - break - idx += 1 - - final_profile.pop("__value__") - return final_profile - - def find_matching_profile(self, host_name, task_name, family): - """ Filter profiles by Host name, Task name and main Family. - - Filtering keys are "hosts" (list), "tasks" (list), "families" (list). - If key is not find or is empty than it's expected to match. - - Args: - profiles (list): Profiles definition from presets. - host_name (str): Current running host name. - task_name (str): Current context task name. - family (str): Main family of current Instance. - - Returns: - dict/None: Return most matching profile or None if none of profiles - match at least one criteria. - """ - - matching_profiles = None - if not self.profiles: - return matching_profiles - - highest_profile_points = -1 - # Each profile get 1 point for each matching filter. Profile with most - # points is returned. For cases when more than one profile will match - # are also stored ordered lists of matching values. - for profile in self.profiles: - profile_points = 0 - profile_value = [] - - # Host filtering - host_names = profile.get("hosts") - match = self.validate_value_by_regexes(host_name, host_names) - if match == -1: - self.log.debug( - "\"{}\" not found in {}".format(host_name, host_names) - ) - continue - profile_points += match - profile_value.append(bool(match)) - - # Task filtering - task_names = profile.get("tasks") - match = self.validate_value_by_regexes(task_name, task_names) - if match == -1: - self.log.debug( - "\"{}\" not found in {}".format(task_name, task_names) - ) - continue - profile_points += match - profile_value.append(bool(match)) - - # Family filtering - families = profile.get("families") - match = self.validate_value_by_regexes(family, families) - if match == -1: - self.log.debug( - "\"{}\" not found in {}".format(family, families) - ) - continue - profile_points += match - profile_value.append(bool(match)) - - if profile_points < highest_profile_points: - continue - - if profile_points > highest_profile_points: - matching_profiles = [] - highest_profile_points = profile_points - - if profile_points == highest_profile_points: - profile["__value__"] = profile_value - matching_profiles.append(profile) - - if not matching_profiles: - self.log.warning(( - "None of profiles match your setup." - " Host \"{}\" | Task: \"{}\" | Family: \"{}\"" - ).format(host_name, task_name, family)) - return - - if len(matching_profiles) == 1: - # Pop temporary key `__value__` - matching_profiles[0].pop("__value__") - return matching_profiles[0] - - self.log.warning(( - "More than one profile match your setup." - " Host \"{}\" | Task: \"{}\" | Family: \"{}\"" - ).format(host_name, task_name, family)) - - return self.profile_exclusion(matching_profiles) - def families_filter_validation(self, families, output_families_filter): """Determines if entered families intersect with families filters. All family values are lowered to avoid unexpected results. """ - if not output_families_filter: - return True - - single_families = [] - combination_families = [] - for family_filter in output_families_filter: - if not family_filter: - continue - if isinstance(family_filter, (list, tuple)): - _family_filter = [] - for family in family_filter: - if family: - _family_filter.append(family.lower()) - combination_families.append(_family_filter) - else: - single_families.append(family_filter.lower()) - for family in single_families: - if family in families: - return True - - for family_combination in combination_families: - valid = True - for family in family_combination: - if family not in families: - valid = False - break - - if valid: - return True - return False + families_filter_lower = set(family.lower() for family in + output_families_filter + # Exclude empty filter values + if family) + if not families_filter_lower: + return True + return any(family.lower() in families_filter_lower + for family in families) def filter_output_defs(self, profile, subset_name, families): """Return outputs matching input instance families. @@ -1716,14 +1468,10 @@ def filter_output_defs(self, profile, subset_name, families): Returns: list: Containg all output definitions matching entered families. """ - outputs = profile.get("outputs") or [] + outputs = profile.get("outputs") or {} if not outputs: return outputs - # lower values - # QUESTION is this valid operation? - families = [family.lower() for family in families] - filtered_outputs = {} for filename_suffix, output_def in outputs.items(): output_filters = output_def.get("filter") @@ -1995,14 +1743,14 @@ class OverscanCrop: relative_source_regex = re.compile(r"%([\+\-])") def __init__( - self, input_width, input_height, string_value, overscal_color=None + self, input_width, input_height, string_value, overscan_color=None ): # Make sure that is not None string_value = string_value or "" self.input_width = input_width self.input_height = input_height - self.overscal_color = overscal_color + self.overscan_color = overscan_color width, height = self._convert_string_to_values(string_value) self._width_value = width @@ -2058,20 +1806,20 @@ def video_filters(self): elif width >= self.input_width and height >= self.input_height: output.append( "pad={}:{}:(iw-ow)/2:(ih-oh)/2:{}".format( - width, height, self.overscal_color + width, height, self.overscan_color ) ) elif width > self.input_width and height < self.input_height: output.append("crop=iw:{}".format(height)) output.append("pad={}:ih:(iw-ow)/2:(ih-oh)/2:{}".format( - width, self.overscal_color + width, self.overscan_color )) elif width < self.input_width and height > self.input_height: output.append("crop={}:ih".format(width)) output.append("pad=iw:{}:(iw-ow)/2:(ih-oh)/2:{}".format( - height, self.overscal_color + height, self.overscan_color )) return output From 90f5cdf7f37942c5dd4c81fd4feee51fe568bd33 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 23 Mar 2023 09:59:56 +0100 Subject: [PATCH 632/898] Use `app.full_name` (#4686) --- openpype/lib/applications.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/lib/applications.py b/openpype/lib/applications.py index e9d49337f9b..9c791eff38e 100644 --- a/openpype/lib/applications.py +++ b/openpype/lib/applications.py @@ -1509,7 +1509,7 @@ def prepare_app_environments( source_env[key] = value # `app_and_tool_labels` has debug purpose - app_and_tool_labels = ["/".join([app.group.name, app.name])] + app_and_tool_labels = [app.full_name] # Environments for application environments = [ app.group.environment, @@ -1535,7 +1535,7 @@ def prepare_app_environments( for tool_name in sorted(tool_by_group_name[group_name].keys()): tool = tool_by_group_name[group_name][tool_name] environments.append(tool.environment) - app_and_tool_labels.append("/".join([group_name, tool_name])) + app_and_tool_labels.append(tool.full_name) log.debug( "Will add environments for apps and tools: {}".format( From a14b645d892e71ef60c6e15da0a9e7f350d6b66f Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 23 Mar 2023 10:01:50 +0100 Subject: [PATCH 633/898] Fix class name and docstring (#4683) --- openpype/hooks/pre_create_extra_workdir_folders.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openpype/hooks/pre_create_extra_workdir_folders.py b/openpype/hooks/pre_create_extra_workdir_folders.py index c5af620c877..8856281120f 100644 --- a/openpype/hooks/pre_create_extra_workdir_folders.py +++ b/openpype/hooks/pre_create_extra_workdir_folders.py @@ -3,10 +3,13 @@ from openpype.pipeline.workfile import create_workdir_extra_folders -class AddLastWorkfileToLaunchArgs(PreLaunchHook): - """Add last workfile path to launch arguments. +class CreateWorkdirExtraFolders(PreLaunchHook): + """Create extra folders for the work directory. + + Based on setting `project_settings/global/tools/Workfiles/extra_folders` + profile filtering will decide whether extra folders need to be created in + the work directory. - This is not possible to do for all applications the same way. """ # Execute after workfile template copy From 5995750ec1eff10ad5265b60ce75dfb1b72a8262 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 23 Mar 2023 09:14:58 +0000 Subject: [PATCH 634/898] Functionality --- openpype/hosts/maya/plugins/create/create_review.py | 2 ++ openpype/hosts/maya/plugins/publish/extract_playblast.py | 5 ++++- openpype/hosts/maya/plugins/publish/extract_thumbnail.py | 5 ++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/create/create_review.py b/openpype/hosts/maya/plugins/create/create_review.py index f1b626c06b9..e709239ae78 100644 --- a/openpype/hosts/maya/plugins/create/create_review.py +++ b/openpype/hosts/maya/plugins/create/create_review.py @@ -26,6 +26,7 @@ class CreateReview(plugin.Creator): "alpha cut" ] useMayaTimeline = True + panZoom = False def __init__(self, *args, **kwargs): super(CreateReview, self).__init__(*args, **kwargs) @@ -45,5 +46,6 @@ def __init__(self, *args, **kwargs): data["keepImages"] = self.keepImages data["imagePlane"] = self.imagePlane data["transparency"] = self.transparency + data["panZoom"] = self.panZoom self.data = data diff --git a/openpype/hosts/maya/plugins/publish/extract_playblast.py b/openpype/hosts/maya/plugins/publish/extract_playblast.py index 94571ff7312..31cb3435acc 100644 --- a/openpype/hosts/maya/plugins/publish/extract_playblast.py +++ b/openpype/hosts/maya/plugins/publish/extract_playblast.py @@ -114,7 +114,10 @@ def process(self, instance): # Disable Pan/Zoom. pan_zoom = cmds.getAttr("{}.panZoomEnabled".format(preset["camera"])) - cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), False) + cmds.setAttr( + "{}.panZoomEnabled".format(preset["camera"]), + instance.data["panZoom"] + ) # Need to explicitly enable some viewport changes so the viewport is # refreshed ahead of playblasting. diff --git a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py index 1d94bd58c56..ba8712c73da 100644 --- a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py +++ b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py @@ -124,7 +124,10 @@ def process(self, instance): # Disable Pan/Zoom. pan_zoom = cmds.getAttr("{}.panZoomEnabled".format(preset["camera"])) - cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), False) + cmds.setAttr( + "{}.panZoomEnabled".format(preset["camera"]), + instance.data["panZoom"] + ) with lib.maintained_time(): # Force viewer to False in call to capture because we have our own From d791000b80cb0b4b05e4d0a4d04edafcf44f65e5 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 23 Mar 2023 09:25:15 +0000 Subject: [PATCH 635/898] Settings --- openpype/settings/defaults/project_settings/maya.json | 3 ++- .../schemas/projects_schema/schemas/schema_maya_capture.json | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index 2aa95fd1be6..4a97ea8a09c 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -817,7 +817,8 @@ }, "Generic": { "isolate_view": true, - "off_screen": true + "off_screen": true, + "pan_zoom": false }, "Renderer": { "rendererName": "vp2Renderer" diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json index 1f0e4eeffbd..8d37aa299e9 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json @@ -91,6 +91,11 @@ "type": "boolean", "key": "off_screen", "label": " Off Screen" + }, + { + "type": "boolean", + "key": "pan_zoom", + "label": " 2D Pan/Zoom" } ] }, From 21c25ac21c3d362c6f602a30706a3c480ab46620 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 23 Mar 2023 09:25:22 +0000 Subject: [PATCH 636/898] Code cosmetics --- .../maya/plugins/publish/extract_thumbnail.py | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py index ba8712c73da..2d3daa53c6c 100644 --- a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py +++ b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py @@ -26,28 +26,28 @@ class ExtractThumbnail(publish.Extractor): def process(self, instance): self.log.info("Extracting capture..") - camera = instance.data['review_camera'] + camera = instance.data["review_camera"] - capture_preset = ( - instance.context.data["project_settings"]['maya']['publish']['ExtractPlayblast']['capture_preset'] - ) + maya_setting = instance.context.data["project_settings"]["maya"] + plugin_setting = maya_setting["publish"]["ExtractPlayblast"] + capture_preset = plugin_setting["capture_preset"] override_viewport_options = ( - capture_preset['Viewport Options']['override_viewport_options'] + capture_preset["Viewport Options"]["override_viewport_options"] ) try: preset = lib.load_capture_preset(data=capture_preset) except KeyError as ke: - self.log.error('Error loading capture presets: {}'.format(str(ke))) + self.log.error("Error loading capture presets: {}".format(str(ke))) preset = {} - self.log.info('Using viewport preset: {}'.format(preset)) + self.log.info("Using viewport preset: {}".format(preset)) # preset["off_screen"] = False - preset['camera'] = camera - preset['start_frame'] = instance.data["frameStart"] - preset['end_frame'] = instance.data["frameStart"] - preset['camera_options'] = { + preset["camera"] = camera + preset["start_frame"] = instance.data["frameStart"] + preset["end_frame"] = instance.data["frameStart"] + preset["camera_options"] = { "displayGateMask": False, "displayResolution": False, "displayFilmGate": False, @@ -74,14 +74,14 @@ def process(self, instance): # used, if not then the asset resolution is # used if review_instance_width and review_instance_height: - preset['width'] = review_instance_width - preset['height'] = review_instance_height + preset["width"] = review_instance_width + preset["height"] = review_instance_height elif width_preset and height_preset: - preset['width'] = width_preset - preset['height'] = height_preset + preset["width"] = width_preset + preset["height"] = height_preset elif asset_width and asset_height: - preset['width'] = asset_width - preset['height'] = asset_height + preset["width"] = asset_width + preset["height"] = asset_height # Create temp directory for thumbnail # - this is to avoid "override" of source file @@ -96,8 +96,8 @@ def process(self, instance): self.log.info("Outputting images to %s" % path) - preset['filename'] = path - preset['overwrite'] = True + preset["filename"] = path + preset["overwrite"] = True pm.refresh(f=True) @@ -133,7 +133,7 @@ def process(self, instance): # Force viewer to False in call to capture because we have our own # viewer opening call to allow a signal to trigger between # playblast and viewer - preset['viewer'] = False + preset["viewer"] = False # Update preset with current panel setting # if override_viewport_options is turned off @@ -156,9 +156,9 @@ def process(self, instance): instance.data["representations"] = [] representation = { - 'name': 'thumbnail', - 'ext': 'jpg', - 'files': thumbnail, + "name": "thumbnail", + "ext": "jpg", + "files": thumbnail, "stagingDir": dst_staging, "thumbnail": True } From 4d53e4f5fb81e633eb0a404d6cbca7da152572a8 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 23 Mar 2023 10:27:02 +0100 Subject: [PATCH 637/898] Application launch context: Include app group name in logger (#4684) * Include app group name with app name for logger * Include app group name in launch finished log message * Include app group name with launching message * Use `application.full_name` instead --- openpype/lib/applications.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openpype/lib/applications.py b/openpype/lib/applications.py index 9c791eff38e..127d31d042d 100644 --- a/openpype/lib/applications.py +++ b/openpype/lib/applications.py @@ -889,7 +889,8 @@ def __init__(self, application, executable, env_group=None, **data): self.modules_manager = ModulesManager() # Logger - logger_name = "{}-{}".format(self.__class__.__name__, self.app_name) + logger_name = "{}-{}".format(self.__class__.__name__, + self.application.full_name) self.log = Logger.get_logger(logger_name) self.executable = executable @@ -1246,7 +1247,7 @@ def launch(self): args_len_str = " ({})".format(len(args)) self.log.info( "Launching \"{}\" with args{}: {}".format( - self.app_name, args_len_str, args + self.application.full_name, args_len_str, args ) ) self.launch_args = args @@ -1271,7 +1272,9 @@ def launch(self): exc_info=True ) - self.log.debug("Launch of {} finished.".format(self.app_name)) + self.log.debug("Launch of {} finished.".format( + self.application.full_name + )) return self.process From 75e67807c3c7af4c68e3fcebd5b155fd4b5f51fe Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 23 Mar 2023 10:42:54 +0000 Subject: [PATCH 638/898] Docs --- .../schemas/schema_maya_capture.json | 2 +- website/docs/admin_hosts_maya.md | 33 ++++++++++++++++++ .../maya-admin_extract_playblast_settings.png | Bin 0 -> 26814 bytes ...ract_playblast_settings_camera_options.png | Bin 0 -> 16732 bytes ...ct_playblast_settings_viewport_options.png | Bin 0 -> 1064191 bytes 5 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 website/docs/assets/maya-admin_extract_playblast_settings.png create mode 100644 website/docs/assets/maya-admin_extract_playblast_settings_camera_options.png create mode 100644 website/docs/assets/maya-admin_extract_playblast_settings_viewport_options.png diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json index 8d37aa299e9..dec5a5cdc26 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json @@ -161,7 +161,7 @@ { "type": "boolean", "key": "override_viewport_options", - "label": "override_viewport_options" + "label": "Override Viewport Options" }, { "type": "enum", diff --git a/website/docs/admin_hosts_maya.md b/website/docs/admin_hosts_maya.md index 23cacb41938..fe30703c2e4 100644 --- a/website/docs/admin_hosts_maya.md +++ b/website/docs/admin_hosts_maya.md @@ -110,6 +110,39 @@ or Deadlines **Draft Tile Assembler**. This is useful to fix some specific renderer glitches and advanced hacking of Maya Scene files. `Patch name` is label for patch for easier orientation. `Patch regex` is regex used to find line in file, after `Patch line` string is inserted. Note that you need to add line ending. +### Extract Playblast Settings (review) +These settings provide granular control over how the playblasts or reviews are produced in Maya. + +![Extract Playblast Settings](assets/maya-admin_extract_playblast_settings.png) + +- **Compression type** which file encoding to use. +- **Data format** what format is the file encoding. +- **Quality** lets you control the compression value for the output. Results can vary depending on the compression you selected. Quality values can range from 0 to 100, with a default value of 95. +- **Background Color** the viewports background color. +- **Background Bottom** the viewports background bottom color. +- **Background Top** the viewports background top color. +- **Override display options** override the viewports display options to use what is set in the settings. +- **Isolate view** isolates the view to what is in the review instance. If only a camera is present in the review instance, all nodes are displayed in view. +- **Off Screen** records the playblast hidden from the user. +- **2D Pan/Zoom** enables the 2D Pan/Zoom functionality of the camera. +- **Renderer name** which renderer to use for playblasting. +- **Width** width of the output resolution. +- **Height** height of the output resolution. + +#### Viewport Options + +Most settings to override in the viewport are self explanatory and can be found in Maya. + +![Extract Playblast Settings](assets/maya-admin_extract_playblast_settings_viewport_options.png) + +- **Override Viewport Options** enable to use the settings below for the viewport when publishing the review. + +#### Camera Options + +These camera options can be overridden when publishing the review. They can be found on the camera shape node. + +![Extract Playblast Settings](assets/maya-admin_extract_playblast_settings_camera_options.png) + ## Custom Menu You can add your custom tools menu into Maya by extending definitions in **Maya -> Scripts Menu Definition**. ![Custom menu definition](assets/maya-admin_scriptsmenu.png) diff --git a/website/docs/assets/maya-admin_extract_playblast_settings.png b/website/docs/assets/maya-admin_extract_playblast_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..9312e30321b332c1d22c18f1c77175ca25cf954e GIT binary patch literal 26814 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

    KZ;uX*}2 zujdv4sTC}Bxxzk8TYL=m8t{MTb2J~iJV}i#JiI3*H}_;v36+`B4(Dh(S~qs&#SEWQ z+|N$^M9soYCxVsd{)<`*A$+13;lZt6g;Pg_T~OGgg#`bT5TWMtRC2Xtk)GW&9YN_A zPl^D!QCQc98Bm~!9%~1Hr@J!qpyspAyEY1dWl_zk-kt|qLx>mM4adtV%i^=gQK$Ud z3kxp*nMa-4Ups{ZI^JY1N&0J*1myiLV*b0X{cj3Ue4)>TgnHVT&f<@Mh*$U6Pa$pn z_M{QnquNLew=-tPI1zc)4)$SeZzLV(8lO>OW|?sN_C0CQGlJ_WDQmR=fIe4+I`a0` zb56JXP-n}=zhp~#(wKb5&Ne3cd&||N@7z4aG@aVIQ=q5*v_v_}wM?udb_E3&wLJ0c zv)b~;NefI8Y%mA_3yAq*RTa&c?0u@=)#RAyf=!xflI$NWUgbFDGqQuKlXz;GLDk8; zTo0v=swRm58Sfqms9T-B#n!L!se1cX#f|M>%{G`7XY6}2h01yB6P8lldZOwG7KbO8 zS69o390oW|bP08YFBmMp?8nvXBCxKN+~BMdtza7)-{#fiX8Yn-555Q8ew=;gRrTp|L(hIe*#W{N(_2Px$*Kd4P@n=#D&5Ojkm#c2GwTr$-Ej~&z20x zWB_IT?6=w@vfUhyFT4C4$PT$=ZY=V>P=&W%yU#LlzDdzcBa-W*_WMTYw}7k15y$v;B%L+bL%lg`v>D` zc|rH-^fy}`1MQ=F((k9!lJ2gk(t@dMMcV}1UGG@@U>GXNKz=@%Hhs*OXR(3DAp}W@ zFV{uj<@GuWShomfVeNxxChod_a2Ibx~Nv;l5x`t|< z?jFPjO|Wgpg;c0a9Co}t7z^g^j?^^o-d$Yt=^RQ89Zn2of^5ytp%hv6ujBRVEj|p^wP@$rd!l?XHrk|@O zKyyVe7;-T<>K-}%oQtIs-EGaLV!I=@->f5NvUPfu$^w zG`9CKB2nDYYxpJ7n1=fjhj#AT(iqNRh6-7FPi)8*J+iO!L zpC#w9-08g9_MMWv3}0MOXwef5@Ac7+I79iGMk`cGaP#sCgBUct%zI^?P9Dr-2!JgK z3TgQ+6}z!7hY}Rp8H&9}!hf)|r`bNq)%RvU=(?JNaas0|%UqJnvyCP<8x)g9HPv8i z{ZXZc7s%K9E4$OJ?GeHZMQ_sG;$D4wMXl3X)h0JJ_PRc-LhSM)SYo&0xO4{R_;a0o>Nh-xy^}|hVz)Z$ z1d*F_=~TtqkjIzhf}wX$>)$)AZLv~35BAn*^JRQ}5_mdPf!5I7lKN)LVGv{KFw@3T z`W4H|I&ZU(f|T4IE{%YVs*-nKEsX%u#SprZ!a$}W*l2N=?iD;4N)3s#!d_A-Lf>Pv zh6*?B=x^rD=afVrrzy?yyGwgo`t3&}tZ}%Bdl*I;P@0#xz(pCbZTJ-cm{>|bbp_MSM^^0W%9<(SJbST_Oe znOCutB1|ZT=CoaE%3&-6Yj#OSvun3c!S|L2enShHf4hbK%WjvtlrLbG0?c?!I)ZP~ zO!R;%lQi89YJJ^YE)7>aL6#GVc|F+jai+0}JVqS%;Ki3hn!?AY<>a5Ojy=dtytwCG zO7GAWQLEHg*(qKGdqg5YUqJCCsu(dBoM%Fwg^>wi;t{OnT$Ww02@7?rNuDbI2(ph$(K^!VTvDm3pNHP<~YSL>`x;7N~ytxZ^yYsK#h z7%L0Nv|59j+gvFwL9Ua4DZ4$(-wjUkMiA&t9_QPhug`9TNjOV!rEf){KzQ&*hG=!aAXJkhB8j!eGnG z2h9G30A-`^WhLOv-kp);Tt|-CXTmv%@|^wQ9N}BcK9(hSM5MtS@kNlOoEzlH|1Sm! z*Pj^YqeE=#FF)Fv;zv5-tB!l|XOViw*qQ2{>2`!EZkGw)ch*||ayi3qM|ui@I2uCU zb(iuQE3~)EUx9$z3)Vq3YOai_VrH@6!^nX^qa<db(x`$ z^+6IfQ_aHd3KFP?wU@Y_z+7ynXP;nHlM4yxT}X9Cfl*b01aJm;yHR6=AxNKqAw^i~ zU#jK40=3)sd|*@jzw?aK!qPU6S+*PsLxrm~w3xK~Bm@Bxi47N@sNlt94UhC%2<>_&C-!qQ_ zMQCX}?fd7jsXrBLAkkuciP>WEKD`ktZq!(8Yjl07A?fI3m^pbimuNKE*{a>e?Za-Z zP{Q;g6FhslYEgZr#+Ckj>_gba77Yy_6`sZWEzF-HW3OE!d?Jwi zER}+%pyWhC`Eze{i-IY)xYAJ7N)`2{mP>IX!^Gx={xW9T7i@5_lMUR+0kBxyR;Z$e zb572IlW8QpMW4zozg72x6)d8=R_HrxP$$e#*-|AaKu!E*Q;}-_wdsP2bQd#F_ah12 z^t!!CXbo0;*@DMN!VOgv6B_tvjft`;Rc+04pV&~^ zz)t@~Q*pTh{y9U*Y-Kmv86UM}ez>*kojM278<~_#ke45%GR-LeV*8pa0euz?wP20d zbqJ2gS7^VsUO-PW-14&MXsVbShb-sUgW0$g3#co$UmYVOLS4J(sW!Jv{U0`B35O_5 z%U}KC;Jvw0RvEH$cmk&x%eAp*Be(VvAFdJ>)282@5|b%u5RaCeeSDb+`y%|P4GzfY zgHwfv@AVz^|HXNz|Ea=UblmojfIb7W~4d=DpMWu=S>IK<(S)3w?!*c*DS@ z4}*R5XeTP~LA*iRhtU+xoXIz|zyk#~ogOb?f;5Ol-l^7ax&oWTU*ogf+J zTmKeK@b^?WFP!*)7@z+08mupIk>uqOg|{XXtJI*fhF>{Zj~C}ip7LVW9gh%vfX=6mUFy#0Kg&=9yTiO>No9zpFV$>O!8M;?Oyg) za)#t-?Rg37Co}wvI}+WOl?E0&=(0dRjIgCP;@FKf<&EMnh+SX7{WwwFSNU^kxEKye z_z^!L?q#_-9ZkP!Gh$=UD-8J@)Nq?0^7%rem^YJ;zAYh$8!|8hAgws4dO@I}7H~hW z;+^y=S1m`sPM@Bgc4Qt&4_FEe{))%u)+~(wT#fohDSEE!Fg>6&JQz|}HGhJw$;xKP@ zT6L+d&>iKjD^q5^sHjZ%kNjV?&D(bln)d|tX}IaF#B|2DuZI>1=meiyw^&{7skrpr z$C7(?rozCf*t9qSY^*!?Ei0p7{aj&v9A)6DqegvxPDHjzj_Ql{_DSn-#SQ+(sk^G( zf+E@q;<{JBo|}7eb5pbyV&k;hFqH>1E}8|hGIT6Z#jj6dq(hAqBiNz4E_`4gC@jFa zkgrP{9{OoYp85qvzzrip8U}GMSfQBEkBTYFm1MA6PZ;_6@2FHRQWK|2qD1*HV(;4B zn+7nIz9ARYOh%*iK--U2wHk!%vosLE@(ySvZ{(taiZ_&}x)KzkFGD^>NQ|U3#ZEpn z;#~-B+6Ox$cC|;>6qcMy!Z^ts9L3+SJ6dDk?~U(K=-Ca!MT)j4aOF%Azf&{L!SEX3 zgLe8iQ@&fK+`i~=d$0;QaHvW$n#?%w7fOya+pntW%=@_PQYV>s1TER6%0lrKzJf``X-)lqRWVcSi6o zV;8fI2c>aE$EPp*r@VnBLB8Kbpe^oTiOur0b29or{ogwOW1{~JESl(H@>!Qo-olSD zB_mHm@!e-gX*_-kfy5i*Q);ojc$3HJQW>X#oO|8njMJ(9yr|Z1iqi|pV(&OY= z_e&6s;(9Bw$-_?$ooD?>jD0VDrySodak^jrqzticjeoQmo%7d<4Na``uNAP?N$9L8 z93FNV)Ut5$Ahp_L2g7c6)Jw;e?R5i#k#i`^X;#9koHhGY;fsSJq&x`lor2I_c z`AWz7oDD8x)PkBXkza)FpI%>4q8+lDE|#nY|Cd6h zM1z)*JXiXSXG%iork2{*Zi3t^lf2m_vJ+trI z?4HmRaf9WgDYMd-AW9#C>XLzLkwni_GUDl(BI}OZJ7aAdo~h@g71?UL zkCFLYeUCiq>!FIzv|bV${pMD(kx#Lin7DA+c&WjppLfyfRnG?WfZe0lFWj&rtchSL z8~2pp&Gu7-jH(qVF`7)CHG$n#uQ@WIviY~5RILWgQva*HGmnR|{r5OyWaPmlA-f3K zDT7dqL{eGGzSg6Mj6K<+hC%kqk}Z)kc9MM^ODVhTOxdzCVHi8-8aM&#<|zA zEWm!X^zbw~>m29D3DTTujuK|7(X7XHYDrSNQE{Cz4!EHHJXQ(?chyfY8O)?bH(sY< zJq>!`=BBP`-Sz`GzOI*bxxU@f!?2XPy8YU7;&S`&Pd)X&j!gYhf;!FUaWkk~{t`XW zO7pr5*S*#c3*)bsJ~+$T!g?EH%L+tr2AHZ{m}QUaBqRDg$jYceLFvyir#VK08%N^r za=yL?v51BnA#9SMy=iJz>Yxje9WNLe8~DlD2OP+N_ICn%+~U|#jbjjwFr@z4x$J|6 z@0!~uTwR{DaxWHE55!{%oX^;vV~Q_1?OoJAzaaUBTNv7pX)Us6om7c1io> zNsw$^4TL{Al|YDdnzEI#0re3Urhn!#`F~J4uh}q4luSAMLaz2_Yo zhb0ha#LFW_&eDReG~ly=9#yh6Oi8MSkTGYZe36adl+}CzT%X02|lE8H`x)yWfttM71nL>N{{h}nQFl>>7W zP;2f6sa#xMW1J|O806gMYY}~c!OHj*=A=Y20K@yt#Uh(8s}|;y*)z;6r%_pT?Ta`qewYG^GmP?F`jC}E|zF|cz#j^Cr5(?ChTz8spF@l&eJIxCf z+0C+&Y~tePim%zbgwUGKxaKeG%LR8x5C}h&*eX7L{qY6rc0c zXSk0u1+-}XK9KlI9U&fvxQ*;?K&P>8#DxjOSCa~XWmyKajXh+cUjU(8$Nuf(pVue? z4N^Tr?}|u{z5dpFDlu5)V7C$v8&92)q;vXp|11#kM@z{E%y~YR7I6Gx=e{E82rc^5 zMhY&S>b0K|x6 zizdz0)x*-*jyc}~Ug+&sc68O^vD&|RDS5~EONuI>lg%kw+F=o zqC2T9#uvz>cqu3zQYF`pxC551FUDqlW!?d;VGF#+ls*O@4)>-l)tOetDpULId&W8*y%$7RZeM(6iY z+t(%UdDR(7Yj%&NKJjulh{7MiI)p+tEmNealFM$XiSd zaxA3vQ)$w`lxhfvU8Yu){^cPvP;)Z&YzcmwtIa&STj_=tIr;fvO!0VW#qrX5SH7

    mA^a3JxJqb`bjrvYR~P)_x<9Pepb*8Sdz0|&rX?4ZeBm_7^of*V<5j>_tWHmjy4(P4AcH?oC>|U z$WU3|rY=em-JeJF5)sW^Do4+(-`4X;`N{r8BcgOGvNEv@vL!CJB0D2f6NLoL8mas@ z&g1LcyneF0w9ko;BRGTK4ATB>Ns9St&(4d(j7rY>p~`Lj$D|bd9xfm4fAOso49vT> zN0#MURgfFKF$H}^{nw?QL>9xE>qzeT%5-HCKcE}&BkK_=kr`pwApdgQ`{ zCzb>!%k;M6b}R`-Ct}sd02Y}KL1r5q+%qxT-?C?7Yqh`i*1PnhIB{!&NVEY&EbHI4 z9?h`cms;zu^_&veDy`jP`olZqCFG0j%*#dbtK3*8=J9SEV%S-mM&*7sX+TxSPz}1+0n?R*^{l?7Ft*6 z$NoV}ZClhf*+;uVu%O+gw^D-7i$$dHqdxMZ7Y)^CT@Nq%Pz>Aj{M0sU)W}_CI;;JK zJ=KZUTenVZoyFJ{w$fgA3w@e2{&$oMJr9yN>80oXGX5A;1M7V2H-Ecaj}o{EU)gYr z9ZZepqhnks0GyhfH)*$VM_5s3#jC2~qX^Dv0V= z`|1!?8hIV}ua^(ozqbo59`E-HhW)=nu}~;1T}TT&Sdf7Q8CZ~k1sPb7fdv^@kbwmm zSdf7Q8CZ~k1sSN9f#KT1zXc8~aA1K03mjPBzyb#rIIzHh1r985V1WY*99ZDM0tXg2 zu)u)@4lHnBfddO1Sm3|{2NpQ6z<~u0EO20f0}C8j;J^Y07C5lLfdvjMaNu}3U^_Kl zOf-(ti+nnb&ycdNg?q>Ixso!^Aia!qKIxZydIO&yC;biSX3}2LhZ3K<{@0{)NIysV zccjxvbJhJ)@~j}KzWVf9uB{>c3hB+Hn@InMbQ?+a>GPBR`=|N*4Czgz`f~L94APk- z(bbHmmvjFt(iw^LO1_`%Q<=}Tq+ceDkp7tTzx?+hKL3C;Oxi_yJLyW2c&N`+q*s$v zmdZSXB$`y8>U}zNsq7w-c($Ijk@TCSU-#+X^Qr6qnWTFqpDyC_0@8_~OLd4I^@-%? z8q#l*{tIan>8+#<{`Y_7b2I5OpDyL|MA3C2Wxt*ze*Gdzv~2O8|A|l0Bw9pMNL_qa zQhP2Yod|xNOSxB&{x6c`U9z-;bUo=>(l*j||9c0Ye@MFAr`Pd$qWC4cB)_8Tmr4JF zB-(z@r~mFhhxq)zNuu}JqN|=?8hfJacS-+^B-%ueu8Zzximt4&dLneN`g9%X*GbZY ze@XffsX}@`Njhb%Pc^WIfMS2@)fb=cWcS-+5`YP!z(%<{v z5AZoblHJhQ7wzYfPSjYDEJ~kjCjB!>b&IAuNe6tAy*NzzCaISsd!n)Obm+?B<1^Lw zS!L_mOGqn7>MPldUm(dANuFQtf2&>kE#0a6d1XD->!(v@C+U?W(eN_TIVAP3uKgxS zG9vpZ{q-M6zd^d1B)$3{NyjUj^|b2wGf1KC)qKB#B)hSJqDGidgl2niC7CmaS?3}L4&ghxB>d^flPohj)7Y}5U zG)C12|D7bgr?Gl1No^KQvTfIqWIN_tf2gniv%Y@GS`SH|pCEmbR3ZHZ=@!yQNgpJA ziu7@kGg<#DDNj0B^+*QR zlO*dJ_v!=v)>!=aB#jA;hiAHejeF_3i%Gvv8X{>NC`tZhAO0)p4@tV#to|2qUrF+* zbn+ZY<1#!GK9ha7iu?Vf|3nf7{vv7Ir~Q2XE$PFg50So0x|^iFd?`u16|JFMeX71J znwE3DJ}n(Cxqt5}b#$&gbH$k}J7-HXFW|HQfBoI1V&|DND~e}!R_m@8R!*%btZcY? zCRfj_zj|!N{I7hc^#03+?O)}xqowd<_SKlmkZgOBo-&-pDkD~_*zsKEIexdH}W2KgL zW2>j^?^jC2jbjH(hf9UuI&!dJh24?LenY9SdU~v|Zn~6w?6FdDY~wV4wm;wsD3r)F z^8Hfr!Y>{OE(FT|q6Y$F|R|qqycpwUoxT&#e1?sqnVP4;Fr#g3ih)Xyeg2 z3)%RurNYe=aWh4{B2`4`h7zR4fWwbZe0Y~9G%7~jOE zYKd!Pn2cInjkEsT>ao)Hv9VHVwI0|wR^kDEjEz)F?ffc*BHLZQP!_B&jZva2dA8JH zkFOi!%6Q;!}SS`J5PU)!e=B)>k& zODBx1TURQLjjW~^h#cd`x-mVsodO#2`NF1+=BZL`q-`CQich`-sQwyMf9=SMdYUCU zH8FX6sZ=W!N48IvI#h?Tb*V`8$+3F6bc_!0d0^sfsb!-&;FJ-l9HETu+ec{Z*v2VW zjLTw$si$U262i9aC3}coT1%fAyZ+yN-vPnjiHE@m%+WqqALfM!AekC!odc&{^BQY=kzCY}9zF z%Z1z=^>jL&l90~rW5@E8ucH%L=~%74lXSj94BgK7X6<>j(bE)vMQy_qZ;%?r(jr5qg7y!l3Vv5=agDC!KxyUFp`8eSu~T`;K*iVuZ)(y=5EM8O5gT z+=%DK##zREQd3DOF0!nSV6Pi_!1SvA&YI?oGEMtZ9JTdob>rAkZz~Tp+Da_caLG*A z6Q#wk*?RLGU%TVx-+pzL)eSkfkNkPktl8yXF&8;#>Grz&QHm-ZE!PtEHz6UrfVH(QPqgI^Dq!jGE~-5ywsU z7bOz!>^V4GUD0vd!3{kd4npq9!(1CaIJ|;3 z?YV8khCuhsikbJ&y41LptUWEPV_->;KO%mSBVNd-L&ztC_6|q;o>{2gvtk9msw-Of zJGG)?&ut?6wnLuR(<`d)na-fu%}g3V&2b}+l}E7;q{8$ zE2F0cj6Aq9wI%q4*6w&f0X1kp^XhXH&%Mxrui^#gPo=QePZk#5 zQ))f$g071{3NZYORV^2Fo&RKtxO+=&T^GLU>{oo0#(fx_Ho2nhtaC~ioi~}vb+}Y} zjhe3+8*PI>hPp_z53XpnL141oc z@`{jWW<~3jpZ@ffNb@T%t}n{rLQ#Sy|E0gX`|iK{rFx701w(}QmuAL_BkO)xdQw{J zhe)_YQx8^G6fe7V_U_`XmsRrAnj#XV?`Gf66LU-t-QOs=T)JVBZw zjYs7b&YpgK;q0u^Hr^*=g|h^g&yPxv^TUe4Fm7OIZJ6|*JZiu1^hN$SgRl&rl&Omu zXk+T`{8iObtK4SQvEs&((-|EjruNp&jtr70Cz zUM5e+iEj?&%W>?VCp4$!{ybU^RuGH>+X^v-?^9uT_ z$p3S1>ETjMZr<%jAxxT_IaLn?&P$vB6&hB)qI)QXp*yzy2@09pq!|9V=&WGcBBO;7 zT6s~@_9TFcj8tp`&uKKL7n~c)^X9a4LAt2JrQ*eB1)Kha>}cAgA1<|=cgZV0n;v$W zE})^0`vU3}tUZWnu(iH;Mb7LEIt^&!)>-@#p2?LdCvc@X57mO8aEk}4b%oG9F* z3RigAv>M}$&8a1(qf&tDtPCMrEp$aISlI>FC zJun~5@Lq3QADgE(S}>}q3H-BZW`EW^4z|XmX-Tk=5rV6CJAA+_>jOR{=MfFBzrL2f7 zLu-Xj2j7C+kj|;;nmE0p4adK#@eYK@lhCxHY?JG&S{!)~Qo$_DCzzA7;sZPDJOy9O zZB&lw1v*#^3^suIS%-pHY~9Aiq^KraTcReZ>x3&HzotAptg7rD5e#N=Y`I7aEnZ6K zC)cRDxxT9^ZI!K;8m+Rc11CVDhBzjK`A&Wf_2xOQA#I+ss(5;h$gtCOl~|OH>lf!5 zY1RXWOAA|6)o}AVl(H-1?x_@#!q6({3;=Y z6iUdsl5gGZfjQR`ELW5D1iRm4Jt5rBn=*&{&DIk_o;lVN$o5Xn@0fWxzvK_*H1a(1 z2{ZEFHH)45bdIUF$FTx4>%M0mB%HtX_0I{GeHk0SEtlnpTUbc7py^yXJl$yGCrkK< zaYdr<EFenmrCSfV*n*AbveMGB$_ zmL*wH-jq8quF<$NsT-LdTWo%8bx#4|QQJc4A)cZT+LEXuW!+O%)LVDNapUZ|B?{?v zedAl zE%wg-bz@6S+JXz*S`=ag<}U>qHlA=?$fqX$`VkZY)#EVamHbsl(sWYQB)%|{8n-`n&DW9q^L>HlZ%UBK+Bs&vu4 z>zNk`ASz;a3uy7G4Pl}3*nkE?NlvVar{m43)5kv5r#0Qx)yL#?pVMjjZlx=+4^a!h z!dA$aYnf_0Y9f-)h%KiTC?ZK)(0vuuT(uOa!Y3#Q1V~a<`*r_+%*UGRy(=VuO}=FA z+Iy|J<{a}i#y`gxbF5_U*VwilWHq7-H`&s3;gTms7q0K8=)xsOrY>A^B@1@B-H7-- zc6nY|g8d^RSgQfN8NYAG(2R*l{{<#8bZhV!fHOE2a1~}AaUh_$%bwa}Y7hU*LOYCo z)Q{r~j41{pUyOj{8kcZK-;e`=PzL7p(?ZjREz6#9O5=GLyA{H=8$||o_pz2RQygfB zsL`=uq^(Y_Q;_%vYaln3HXRa)ZVY<2YBv1Skqv)p-EnvT+f{JPX*lmDc z$T)t=kr-3IYPV4W%tVv`v1Um<$g!tSC~D#4ug(hCa|IyD;)Ko9Y`gS}jG)mApz_eR zFuC$%y@1pXX;>{RAX;GKA!U8+FwNPymXlCz*HCLnMG$cZFhd&-;QUwq2XUA}YD{in8z_O`7Xy4+rD1@fD~$mdFfc(8PajbZq#aiI zWgITdu)>tVg_&M)6mm%Aagbw{YBDbQS8dSVFgTo{?dzMj%(v4T#vZk%BK`9ZzE)_r^u+h!6)i7<&6}zy|0CuSqo))J3oZ_`} zz%5c#qqqg~lt+dwaKXL|a`jnMI(N__6{mxi#X-=rdLd8Zi7eQf*aVO$bNZcUrAs*y7ik0$UOr3v|ITM*nBk8%8d= z-c00T$CqPl#~0$8@J6W*v#X9`7pXoKyPOh-T~^OCvl|p>ki*SMfP@C&i;xgr)N6sn zli-V8*u*bz;Dbp)vn4a&jiZ+xoHI)JtB2=`UQob>&5;7;fL?C1=tY$>7xZ$QG(NZX zk${+Z8KD;e4UfDGT@a6>7oOj6&Syx6OcwG-$DVQ&)h@E*&4w=AgvCJ@YH!RLjyXdY z+1VXeyD$<71ae6AF-I6fH4I>Mt(gGEjw}F-)u>tZ zLj%o?cyyRvPK7VosuwfFVv8{dVlE237odCLiE&q>*En!Fu6E&pKR_Ml?1YtJa>z6B z?1ag7++K9-tV~%Y$HtvIC;sY7uX@UA%}Y;VRx~=9^A8mgqtVIz#AtN5`-tA%lFxso zp!DgFB}GI+e){fFXye$H?27q$00+t#q7FO7&2Vg8z2z4Lc&=mfrfe$9;9;8-mrhEg zlA2*EB4y%a21?$HzzQ4SYytD#FX-XFY(5X}Dup|oapPlQnS$5;GC*ka7VKuLg=U=k zV6j_PKPqPiAh>vd5p6+%@j<|Bfo0c8R(s5d;4|I;D8*>zXK*Hf9v6k?4QpuuqQ1VF zE*^5A#mQ(-^)l2QPcguzp`(P6D#Y!g^QyAcL6XPEsdGqloollL)qzMlMoK(B{HNb*Q^pl}p%j7g6_i0R&q^NV4 za-fTcn1wo2r00=zoS9MnwfL@+%_m_`H4*|i&Rb|zoT2rx$m z&YdQRG@%Ue7pIw;Nuptxn91lR-IKC-5pCrpWB^rgSKPdMt)dUSTLQ4g1eF7Y62&z& zo}6TQ`HTNXD12qv&tR~^Y#5Wzpm8_BiuTnoIC-itEq*^5oFIsjxCL!k_OKL60HfT5 z4mYHImGUD%g_SI#qlHB(zorb5gS8JyJR~N}U0&oYBtU1qdqgzIZ2MX;~2EoRN)k&@zcJ zQA-o9PeNC6zS)f-EY4q)?>zU84zEQ+59?Nm{NmIMHVQJ!L>pH6 z%vQwwLl_IS%v>GfR|`jg$J7dog=5bb+IdzRQHa5|^eOF7a{%6;4Wpc8j2MY546saF zE_}36bZS#(&uE6f&bBY(@Lfa~V^}zwbkLSqc7RqLAvS!yUOKVR5Z%pl@F(&dym71#4Atw@8WNTVw8mM7 zkWpNW*z{^LlxEbT*iGfxGC@@E+Dkh`(t04Ae~;g_i1HQCbCyOQUTm!Vx+2n(S3V|*ofS0EK< zp7YZ^`CAb;@ME%RoB_#`z!PR##_tCTH!C38ioiHvt}})Gg*?F|l$Afy-ga1@tGE2z zDJjA6qHqgAp+I`!e=`LHQ{5n&SBB9c2wcqwgFgm)5)(FF6-73+dNT{>YD3(n_u13` z52l{}zlD%qFfnLm&{o#71@+)8y8uvxt%5MZOE)0j)lnjKW?=S={54+#;KzCT;30zV z#-65UJ&H}MLxGCrL4nEhRdmRas5=IvyH0qJU=s69I6gTe-Uxw?rKcX4KKt0d#sjZ) zP%rLKTLP7_c`cL}bq4x@#PBPy&uUnu0vIBy?>6sP9EKCt65f8!8Uzv|}DUkna{x;Y{5vH0eEf~V}X zDvHW;01-7-Mh9scLo{x~E(Y6zrkb~V*c@mIXSW>IP-?crDz5hiylg=?Mh>k;)U~=T z8i$}Q+Ys+AWV}~xaj<^j<2>@H&sL_ig75oK`ZOs2WvZD`K;r@2?QKiH)?#wyo41fe zn-Em$23v6Wj5gUX$21{;^6^3m#+L@G%o+!E#u}f(2(&6f4FaQMs@vfPAZnry_oFSq z?Bzy5YRAZhn~-Nn^|0@0bQIVGU5FZlAgVTViG(W-3lvALYQjo#RVbVu3@|Bc9qWy( z*uHWE8H4LWxS5P+d^4sIF;NysAOvXqx&U`3_C_E|eU4VzGtcU7YlYW}(pQD2GN@am z)3hUzYHXUq=TK}!!d8mL!|3qa4aOHH28IVjyXBN*&2n(jL&|+k$6R&7t0Xp#u$$p* zo%uG;Dt;joR75O%;yduR4s?n5ze9^KPoXZ{9WFC11Nnq?tYd952MeWu2fRV@kkG z6j9zk4*`GGHG90Kk&*~T7%KBw9q=O^iv+1Kcq<7d9p47Ltll$oG&Uiz{v3t)tE}&6 z)Ooy|7yiDYNjg4kS@wmbkmyp%vEv?ic#y$U7VG&;KLk&-I0X%3_ z7Qtf}G`0jMtH8um5upHx7QnvyBji1%(Jc*z&|d<3Ggd}BB@v&2+7logrpxG)c#k34 zg?&ijji4Mb60$)m0XUbh*q@a@q%{bI-qI`l*>>ao}lqw<0fq+29eUWDWlv@mv=RC`O2QCQtwB6E? zWy{*=vyX8%SX)-#@}@xLpjWjV)ZlSKYV3mniTkWm7K({VlMTji9FE&a2`9EAlNu-MVarT6}N@4K0S&cnV? z38h*6K`T|@?&kY&p`F`wzVaZ(cgZP^8(bI%=a-%Q+6iobkL>P^hBK$ZP}PIVw>^zc}~&3(a@Bw zv!P5mR~vTuaf;RUkR`B(n2na~elTi6HZ2jH4KSay@db{uhdj~Gs^2dF_?BduL%Wkc7m< zQ3b#Ym}rlR3ek?De!L`c!|G>JR_|THl%anC3BQrmrZh(K=oUVj$gA%bUOiJ-tf*%T z#GypFkjOz+rOY;5TQTXT&C8(7ZYCd-a2jbG8&!a9%@mgSRVX#EapG_tZtI(&wKJM9KDA@fF!P$+Fcz!s(2l|BVA+IMp^blMzZ7#7kQd9-vgbEwy( zbe`!pj)$V(1v7`5h}t)@bj8^C?vf1tZaT_676kQ+)S^yt`$6DLJ=MYqgz+3Rz)In8 z+1wr#3AcADQteR(w(;rf+)PELy--eye8B|4w{*^rc`2OVsYi)a7zB7nR8CqOC-q>w z)TosUt(g934)oILV&E=g7C#wcAT-0EdDk)mRO@=63gvKbdA*rtkPhMlBFeu8L;_Yk zMZ!t4U6b{KYGqqShpQ@daBAI(;!Ld;LH)SOG_fWBd%1GVWyW^cTCh$2d4{-6Mkw#Cb^~Ai@+hZpX_w!Cr*_8yqjp zIR)p7c_Izt>zab^F_VfgUak#B2^xwdA5c5SwM^-tD{|geW@>S4Rc<9}M_{aDct?o{ ziL_mSX^VOx87(>Juk2=6>s6*ekP4i4j?JhlRHyhd$8Ck#Ao$iLZr>7j1*|~@6ckrU z%pfS%M83;Q#x&CxIqB9ymL9g|v^69QWIf|#m$)!VMFuH}#KdMPR1fzH*8HM24-!`~ z#wp)n!VSoP-yTjK)?p~A71n*It5Lm)x*n%|QFq*zzelem%K=A=6T5eC?#JvMoV$-i z=cm1UuZo)qwz7K5_oz}X#ESsu0TZf$(|Gk}J_OhuqoZ*iv2x(wm@zB@f*C7?Q?%9Be0MxxM+erG0p^C&hbCqfzGH8|l~UrkX!z~*v$GW$0;%-*`2D2C77 zz_P+=uD}T8i0lx;)xw9xRGZB9!8?dQ!C-M>kyQqShJQCkFr?I%tN;Q_GzuWN3b4Wu z*R{7}^h1#v{f@OY24#UjQ=S7;y9QmKBSuhriqLnc#j$l!^8h2Mb_?_|z?wk2m6VY7F$98oiDg*4puQySQlK&|N37D%))pr% zk_3#c zG))cVWQwxWSMrsYRFr%af}{!K{vAq^XOz+j!~8A&d^AoUtB3KU{+5D|Za&~^{(lOt zvs&UKa9uTt5bNIz`QC3Z-HV2p)V#{elE&le$kP7~tv}Fs?x*?}uu)$GO zeR-k+6fwtvg0zYvFw~>?iMN1LT1$s1Su)?)eBww=(FVGta*YEq0^{(N(y9*twMeRU z0#sF^Aw1!O8+u|wg)6$mSYfV}g{DC4Th-C@XrIcCGiC$nP^rZ}-bu-qO`9^MKe_Gz zkwKM1Mg%Y zK_JX)_q0Ef{G0K5sjzL@j{fbOCz#VvYsUH=1T%u?LY{yFC!z}|1!bFCUxxS5a>J=u z3ReP=0sdrcV1*#mL#Y~r36_L0!D*t%q=8u2vjPPfGMt?xQd}t((}Z{qI#RGHSBgWe z8*9)CchwTCWvu5E8Jt_4Cnt7f2H0DIAuCckJ1AR%Myr_36nwUO00_`@^s98Ou&g-A z7p(*G1Uxs^eidwo%)ACfmaZZwvoH+F!bUZsadD$-cuh#&7j%%@jjHuM@!2UgtFUiTW3WA)0xf3lQfO?G2kMoS2+mplb>M5R<;#0|d z{_i<~u*1Mgt`vkSfExe=2O=~kMocu106c(&(Z;gKCly=#JYgy<_PA*FaLPE7 z!R}L0;SfsoT^XSq6%w;;np<9XVx+ucBYA9eWF_)zXO|so688y}6f)&CKf!yXq!c(`@4LHA`-j0gf%fRXwpfA>O)}c_?BKFf2L`jJ$j<0v+Nzr!t zP*F#Neox$wNFQSJnn@jkl4L?mU6|T}r1#!x99>U`lX`T;Tfz;EsH9?j%j@I_BHN15 z70b9)Mx^mhDYmhh2+MXec>Hlbn#Ln9RH)TaLo|FPi;qe{Db{PbpNILP}H5&>Zx}q!T*9@KRgv=i<|L{6Nmg4 zQOB=Lly;Zs2tk7!#wX(tT@~mO{UqKKX=qBol_=wGZC^kc&`df-i0&J2Ua(dQWo*N_ zE>t2+T4}}PeT3m70k-c@JRl(y*_uRAvC<2RCQ#hLQDdtky9; z=Bhqi}4u(>fl&lCLTfCs!!lF=l?*s&9O4xl@Cv zC?z%*icg#y=y(vIMUg38{CC;&q6K#}+)nYLo!&tIyXYAQ+cRqBX`3xdpMi))r}G7Z zN^K3!t)r!yo;NlLP=&XCB`!AW-zqMwQZ!^9Bd2V^Moep(7X^+$EYON*PE4%@#jWb_7Sq?-4-gFJJ3y#-3wC|odIKW zTdyX?*YSFJBBu-%iK>N*+b}koU)KtYEnioF8fIC258X#;fbFsG8(Wu<69|E`fw$_6 z5G)~Z3;_wuA0~Z$+5ym+>|ANLXN`?bSe?FzpgdMaNKUABj7qDAc4@ z_Y?%!r(yVxb=F=j8{r{WSgnXbD=c7q^t(D<0|Xv`S{;EQjEKQtTG5GOROQLHc5QJL z@gN2#v;#lVDohk17+YV27{&*PVhp3$mSAYHYk~K*#6G1^H*wIl7;&4HCQ#J8*8)ZA zV%?%Ip&Y@0igOe91R^PgFjJQpkOQNawzMBKQp6mRs1(lhw+GhZX|0y}p3GX9>-A4l zH-=Q^tKDi~Boj9m7{zak)G>!9d`DU?L-!b+5in9M3KVJMRI1jrzeoYGej5c*?#$UU za%ai`UPsL3I&ifkd^O*BCgQ`K*%`e4i9%av$C+oG+0j`oR8Gm+Qa+sh3*oW&@55)z z@j38m{tMOsXn)ZaS3R`6>8dL(nhn%_7eaM?e>vVc8n}9QA$QUK<++P0;j35R>J^cz zSK%rktV`+Lh3_s;xS}Z}yw`d3m3s?KYf5XLFXYx#3gtC8TZ>=6D&Y0>YwD%v3QeW@ z8U(d2;lmXDFn-p*AW!crdk2REOH;adAhkUuJOEm8 za(Ua-n!=i?`hh}udE0gS$F95Xrm@LDuiV3&B@{iiXAP;&*GmX=jZ07Z<<)h0I7}#| zmY3&u?EjH228(VRA8f^Ep|Gb`&uyy}=B=q0_SEb0yA>qhF$huO4WM%6sr(ANDYR-5;``cy0>-5^5r+} z@2f6v#pm+nJ8JuLH_hrc0OF!Y3l~l8DHNvar8T8GzO1S5nJSgg4E)AV6o{KsCDbA} z>wDI$*;C&(CT-Y5s`sE;X+i6n`nFPO4HQ1OI8!)b4M>*EQcAt>hWZqL)>(&hr?f^o zs!-p9VVK$j?7T+?uIak{J7$+JxM@dU-%a~(TE2Y$P1WTK#?YLx{nz#3UfFNOo;q*@ z22XW3zG3w1Q&Jp64S%9{Bnxk-dQ=PcVsfEtx5->rSuoc~zPiq}zz5pcM<}RSmoz1< zFgGwLuy3#)Qo?B@eX@;{yyd3-`*-wBFK^v3hVI{AVxaHFMD}MLqllBE(}Mpg!qnupXHKSn%5l+iH7SNQxm($ev0g z8}pR)A1>6Vo-Q0(-hLBFy>1LlCO1}FK96&U6KTgR-b>+AJs)!e|Jm*6In*~(n2*`7 zDUR*$F_P&}4E!;*2bDu}>5L(|BCe+O7J<-`feu9$?Q``2Sx%sL3 zZ$N1a`fzMVb$NZPy1aS+O=CM`B42mNr*jXO30%~t>f6?=0fSa!cS)eb1Cn1Xx55aDSh0WnJsxttAc};aw z^EQx&D=3?aP6o&)3(`ylOo^wMI=yy*@D( zXq-p_yKun*P*({OfsF$wt_!CCO;hE1ZjZFNWY8pJ4jjeGT#|UtS_7{#kFpvHAwG98bx{# z=}x4t>hw?edk4}zNPCf1B8AK0@6(aaM9QM+4ajpA5@|YJC-%wNI$epsq@@SxMx;+7 zeGKU%NFPG_TmARr_&bC|db*Ix>0p*e&_Q5qs{~hTskk%uSzW3?WkH72mwaf9B z3XEUK_V^JA(5^RApIQ@ z>0O5OV$c=tuNzP==^$-?g+$s+f05>8NJoRNxV3t$c2##uLplSAbNEuEWjgUUdB9ajMWnYQC6#rg*H1&4=OJ-^ory$R_?zjCNdFayb7Un_ zHxlKfkw1To@Ba;Hu5&X?E1y3diFKcYvomqxGBm!hgf{v)`{q;@{hm{tuGjN89oJ^GKgV`U=vQ zkw_=o#x}hUDO`Tm?{NKG#}^>6T=qM01;?L>1fu^`S%u`NW--{EyrKV zC6mZ={sR*E59!ZpW7>VU{p7J+>r59R{a;A`38@E(Yj2fKT#Nr%r=wXv*F4K+J)8ra z@0{zTfxLiqnz0zbcaFi)uAe;bZAipqA4IwyiF5z2k+}Xj_gVMfBJqA&{hXIfr|PsA zf724@uzAM(b;s^v+~+v3PuM?SN4gJbFVa0oTo1P*eF13_>AOgmA-x`nbe@G|%H?0y z7e~(`To0!On>_XJ6JFcWbIX#C30ynncQll&XK`jBUyjKAtrY4RPvvdR0T?KSqskG*-9{?!-n`~H1j z{L2dtcQl=S-qL$;HJIliFaM|a&ram;fA7JL+SqzC?3Qw&*VG7Qc4!qSg4;iy}bw_d)jeqh#j>DkJUeh!JFO25G%BUaKOs z>dhy$Dq#RhLuK^CGzMYDYhxD97q1SoPDG7-)bmC#Zm6|u*2#ef?bGFv=3Z|Izgt=C z5C;R#ruOPUt+xeTIDk&5d-;(8LthE>u{IVoQmS_42S%hr2P(Z7VAG6&kqRHGdW$*S zLjxer1EB+0T+&Q+-+jE=+uVhAfJBzgFIa$}Fk`NwdQG5Azv@T}M;lMKqdSDi8AYF7 zm`<*Nkt(~v5QzqrFi|maOMy%k&y-MBO=?BS@|Yqpem&a7qzPOiQ)mS93vC01svFfX zj|?2tQ}RTx4s@5zX1nos*o~+cw^dI@GpRBRje$-~WItglIX0-H=Cz@LB+i|TBZkU0 zQt4zPm32eCh_Eh*_DKqQOSlTjX=PGYo*L@+QR? zU}-*)lnRsUDv{=r%S-cJrP@e-$TB8Hv!9zQ42)MeA&3<=sy-J6GX)EZ@X?{tp=8-u zpnMgvb599V?}9MN4|R=19%SWK zj7w23?UhL{f6*m7uH1Cxr>|_f_^lU}4GIy`aPzXa?&#Rm@x_kZmCtuHExr7*aE9EK zpV#-FMV^<#-Es2MZ*bvZQkI6E^X5Z32UDop`dZgCXgtBT7 zL31k00GmK*!u>}Eu)40Sb~N=*tSEQXw|_OELt_XeCJ|gFO$FN$X2s9B7b&tpL7*3i zYAiZ3{Z{kl$@&G$AE;to;3EeCX&Sw&fd<#Sql8~(y#*HFa9B^Je0LE|Zx;~;K79hq z9SgUQb#&Y?wqk5zVr)gVqgB52S3B}IjMXM`{k4wP8@6|hO>BQiH>KJ!drLL6Abx!m z&`l0Nl(GvFtL}@HHq{1#*U-?vM(CcHxM2k-UeVF90_3mQJ^_LkkKx*OUb|szY1dm{0c20y zFrj<9+)=xw97pp}z(TVG`xT1n=__UelK4HGl!*9{Xt)HGwq zeG5{6WttU!G|T_UmLQ+T;7oUf}s+&lhT_8km>17 z_>?@oEy=2@Z23kp@OJFi*Bm%yu+kn#*KwsLPKM zdMbMkxFYS~+IHKkI7*1G+)(XrUxC%gHCX9*9s3%5rGG{L4fsX|(?6Ep|C_u?Vg9-P z@x9%g@@W zc>$r-m2U~>$X|4s0%rM3-ZC4&WiKsce8_8l^II>z{5F8b&s^D5yyUHi1H?V-wOo4H z`GvD@L*s4*gPZASIqw3m_|};~u1BCMx|r=}mO~v)=U#qEu#M=!Hy7E1%Fo%`oUdN_Y+!Q2O|x*Yn@^Dm8*arxOMPo<;zop;^!PKcPZFArx^NRO02_IH2n z2S4~)cUZdL3+YZB*yH$HA@={Zci5|!AoK+x^I1&px8G6yLH>@n*YL}&<6dG<(R)4a z%_I2e9l)0F2`QoGYV2MVa00nBQQf=|WHSwn%NCNdPXQg2IrAJi>ELB(5uX=3WHcrBc=Lr~aob7mSl z*Y=0?KdN@l1mH*Lbo}be-hAK$-FnoHA0xeu)}FgEe$B>ebIN2g1HHXi8JLL+jsAzd zE*){Q*9GMURLH6?khcr!=K4@>gxks&GBcw*WT-@~FF0liU|sY&twY==DoW~J4(y{< z&5D|bNki2erZ_cHq-6UT*2oRqILp^odxcoc=0U+4UD+Uq3BOWl)*-eOVU}=DF&@Seyh#0Y(P| zM7xbK3$`huf{t^2+%nM zVbLOzT}gVQ&q*#gj3t5vJ6Ph7*GwA`%B^~i#wEGrTRRd+4&wwVxr-$$tY}PCX+=jt zfFb-OW5o4MIu*c;Aprq^TPKN(cZ^M}rbRAlU~GVA>Yyfwcj(V>V8uHLaEFFm2&N&i z4$j;Ma&UlQv}lEpNaS4LU^aYUzp z4Kuwee6JS(mgW^O@W{>`Mk-f>kX&1$bY^uJXX7waQPvzSW7#^OD;UJ08Uj^UQ1Yn( zixJkU7U~Wtga`qQ7|*IAEVhGHIAS|mh2w~GWUUCx@0cp+mjplNUgU0d0)-~rDkRZyzBB0X~5JD$60u`$?N>b3e^OVe({HD3I;LG}%=>(ImqB zkRkH%z&~k`{|icR>=@%8Pmuibyb=+)E|dVBZMcN&O|~fnPP))@f-{3N2HKFi)3#5? zi2E5)+YZ6)P&C=45?yQQ&D)MzWaojZ)c%{g)r=jtttnR8qb@L8?)_9%##R8ehj@pI zDVX~B5*tYgs#(9S$5D+(w&bRccsl^xK}P0jb-zeYw$4fx@w&)KQ$ke)qbf9G80L7co-hPwJto9ezHvy`M^Qj^)s>zYzG@Mzel zIIW;fD-BU{XYAos{*eKjKXn_A+@JAut#$+wZ;IoQ{x-Z7$n!O;9v}n;PxKX zLqei{ie}OP%*5^&X^-jX&r8|L%|z7)5eEaO+okBBg8@5T)ks9)*T`Q3Bh!RYux=|8 za$1#PpdpLGVj0q}RUepY(tBymlw&%mUM%`)wT6L*tu+cf;4!HV@i~Kw=Av`iXf{=i zExgvb?9*!vDIJ_Hj)5Vw-f6vxE1)9Zw!muftKJ3g1_3070#NGfJ?1>O;;;z-C^;PM z3fAu^w88;XRQ>ROLdVm{AYFj^BRYztx&3)EhACgsQ0+LSaSs9XA)X%@2t41gYXF|U z%||q<47lHlOF*VOfIMtq&167$9LF@`x9Io*ptICJdot%mzw!#hG#{ljE(fM%BBt3B zk7>&AacSy;Os6=fK+WM1h<%26I=uzSOmlM~!_fQy)5js*eQ3sBz8! zF$-BO6F>~SOSSR?C8ZX-XHejtK-T#&mZY zhFR!f7*=aQ48&3my0hNiq0DN-I3`$a5{^l1ZwXd=tX?j;BWi3aj(WTcuP_vIR5dfQG0es=*_s*bZQ)2SkZ5igM(s3@ zYi1lYqje*Yk>tBaf@+jTE(6shsb(DA$PoY=GgUHxO@dxV&LMU60^C`VbL>?!>~HAe z)Df68bP>ihR!c&aj9{}l=w?){R2Nzu!Cae~3To`|0@Q?*GYvI1&PHS!9E)ihRnFKk z4#0}JDgIuFaz@Q>UnMpdOmkc_gHwn=LCy&c(OSSQA>)LG$#&e@)Ci_IHhE%0TpDP8i#`MEc6B14uwpQCCAN^(ij7&+Uu5wQwMb1;h%x$akK?-(oibTB6Q6Y z^hYHLPS3>0>@tNS%AQXm9;TVGUcy%IAP>Ae%JRA>u#^J@ii?j?W{V5>*xD#CNdfh6 zyg;OVGopRLKgWiMfmXkH0OUK0ee1f5!zYTS`HT~$bU`qFh~KNS=RtzUMbL9-oaZ>_ zWQWiLl`!+vyz>W!Xt;uTLo2|#02j3PioFJ#i#}^yR)p4-)hkS?*!@6hT+lqBG~m|D zz!)Yf9qf3~sClFjE=}G%9F!uBHUOS=P2!cHqY&n(o`W#{DR&~|X;(cdA&Jtu(eVMs zbTP!mhRj2l3UnG{rO;kR>!0-`(tcCU6{vW4PD&>7A_1TNC@b$~>O!*Tp?IjEC>VUr zX`e`}JQ9W&cpm1BPZ(#H?KL4xUGWLyitwF%*sr?JKv%|c(=N?fA@YPUoEWECbq+ly zgi)JkmW5APVq83DSxA>DZ)+%%@hrxQsMeou2x}hw<2IgRqr{FiNw_!4^ z;6RKBj8HTKEtTk@qy2~uH>7>NgRDD(OjySvak`*lid^GYjDH}fbETSR94Dj0-mmmo zUE0n1SEL@+Jx3}G;+Drzo7&N9;PNXPhkn53JcDoe0Fv_0^HwKvD`L+OqUMDL9;IjHR0RDlK3&v{I2qm+>Tc;$Rke=2i1z&L^I^9Yf;CVt2Usk+%SEe59AGR^5`K(Fi>9%uo5Wf&(=s0K7j70jFT$M9 z>^JTdy+6hhWx&E;cvK$#+$kx+wW4qfT*ysG9hQa7I}T{)MsP%czA) zLdgmCs7i(sbvB65GRpfDe>H48F#2h4}$|%mZsypc{D5oEm_Q zk}sj47E;By2h1>;9Can7Bm%psr|2ce2-{Vo?8I)ro~-Po&o-E!jgffj7~+#jkg{;F z#P24wjVQcKoNl1AYTfB`#_}0n5hODFp4?j zOE8iEMY^~OV(0`y5{X#lXH-F29%;e5Jg5y7ZPyT?JPVXZqB>RG8WSoD<>!OSK~51wh@YG=w@pfc=5Q<(}W$JR`#5oQO~{ zq;s&CD@yuwM>|(|EbW2gA&PcYjG8f=okqE8XTJ(EiL(&GJKMoK9S|9ov#JXM-;;)jX7mKdrb)~;BX_9+^p`DQt!S(~{bggfSxesrK65t(Je%#ZK z!B=BGl+d&d$7XokYv!?NST`wj3~L6uZ!3v#h29>F9A6Pt`~C=Vk4bc1M2*OmW{Lm3 z-r13M1|x@LMq#ad>)1$d+;iAG$Xg1}gwSAMEN(!c`KNiEUwILGG};nIM(&H$%VXi7 zkpaW-JYu3CcnhC|xHt(Hgjy5_3CLDQpZ~eqxL|9)=#@%BqXw7=04%Ik3aXQB%$}7{KLI>Ax5=oi;CAX2j*L=;Oy%aQX^9 z`u#Jnqw|_o?_PDyd5(liauCa(_pZvj^Y1#(mt_ydSkiOX%)UE!jh`p#DwbP?9PjdT z#Jo`T-RABWtyT3=!ieZQQ*F-M9K$H{Mm$WMoG@+vh*`o;S~klrZ9z;hJW}gHBO)}n zVTA>>BIFx6p5YF<1v!P+hYmZhBn2)H82l8fJ`L+rhdsd3#d4Ot2+e)H+`k3=p`5a@ z&wbX!8pf7g3~tr|#T)`uyL4lUz!7vc-0D zYKxO_)$j;Wf%5eBl@X{~qt9|o^zpb)m&!=SsRb$Im zAJCpWOKd*)1=KS9pPw|X#@@TYo{EDFcBwjl0^iLcYb?-+xsDD@NIX|He4sckKHDn2?7kV`a4 zB}9_xqNvvUmYQ{Fx<6%Ob6PN3G&6K<|Z=p;W45 z-C0Z?b%4{lGfElSg^R;z608Ix0oKW(YQ-?18{svT!R+tyUgtCW(5!;Dk3Au+`Mit@ zD5`fY;ncG4lz|?v*43)sFq6jm_3}P}yA{HANwU|%8sl+jZPnt05HVmvJMo<{VEh8| zu@!1W4BX1Dc*p~1i}#YWJV$2?3xv5{R*)CbMr^VFUalN#(Xd_ZoPVAn7qtHtm@r?} z`|}JraHsRqHTcnv4E!V&YTv0H{IH?{HMwXce`8C_J#~kny+6ez9OtU3Aty9fM(Jzb*KcRr43(VOR>l>4C-Or$pZAI7W-;44y~!d8k%ek zg7dY}s@wp$H^qzbh&Cg)cxw!@#cRATrX}Xh;{K|5_Be$TPtfY}gT|U*`TG51Vj4=t z`LaaBM#C;yglVFUFw#YQg_xOGv}oB%miX|00Dzp=@q!mPT9x=dmqgHir*gowuLNtO zMFcfD>j8DR6~$}>v=n$H!T+!lLP@Ex@SiO-58aMy}MV<7^3BR>3c}^c%JV(AcvpjMVnw%_L&IKcb*_Hq%Cfw z_unWW!VEu@v*Mjdl`LUP5>vO1BH%J)?D{>KUYivQ;T$n4m`Jsk8t+(_yHoMvu2PHr zHQ*OIPjdu>zdJ|}0g-y)XQG=cy8t>xhjldI9pcY`wM^AHy2cR_&drDhCsG-_l1*g* z(!%4&YaBHWR3t`?0~Ian3d#z5H)eYftTqp~&d>#`ywRV5Uvi;*KmUT~HMDhs}vQuc6CS5Ta!=!l$}u+*&V(7O=b zu84rBcsw3w_X?~sBwgnF_hV#;Q>%c$z&lN)D`P|j!?<&s0EbmIsr&^fa>m?G(k9tT zQ?yA=o+$HtC0}_d1;>zxjV28HcOU}}D18#5CVvaR9*xte>QNkWb_{&-Sw~O*Qz(p{ z#I@(*6-TxNB~9Rdlk5EkSkutM)EGUPs5lBd2g@OyI@G(A=Ru<`+X$+Pk`5JN>SI5w zb{o(bgIPGCk;76(X_yw`-3F+GyvUTgnCsEhhNY6Gh6)p0Y8ioTPN7HY8?*$%IZbN_ z2n#IMrX2|xi+FqjW8b|6lGx+rLjAD|IqO3o5r+pGz!-L#x_*^(+#R|q^nN(<2w}*J zZLCkt8))5UX6xRWEF!2rPelDC+qqZYGl?y3^xYp#S7b3W@8Z?FU%V}$O-L=zbzGE)9* zrhwyAQv)D2vMdP~sey{X1Vv-038Dw-Ql~CNOG>U6Bc4K4X!#VUYji4TT)3#>UmcPz z$tp&t61_bX|LGKQplY!4KzmrH8I^1upOdlpNdp}GbC98rMwstT&B5dD2nU~vJaU|a z-#Fk1Hn)&_A+8t7W@!ep=9m7lEfSVbf*vO*|tu$uERfpLVt=i{Zw! z$d&^B3m7PY)Mb+qd7k0K!tgs4o6G-&Gb zW6lPmt(ZekZPp`OYPg+%{dohK5Ox<$fqT^C0S2#zynb4Jr@QD-0)OH6@cHJO1vD%*4s zEG>mR%&%-NX-i}0r1hN&9+C6(hFB16i@+c@jB2;FONN@L>-x(t!<9znxjSksq+! zh_bs5Zj6=~6Ev1BkfFTfCXr^@VG~+66LWFE@icUTk+MbiD#}9ckD*MccHtKYPU&w! zrSrA-DLMvH*p_UM9Z(7G7cT9XVYy*nWw$HnZ7LQADU^dJdUmv4`KS7tYrkYg_5fVt zlJ+=emch%^DO~V1h85ag&OoZZ*~3cZ%pUhUr8I&!Rwb^jyIkK=&XXA)K4bhqzE<#6 zzEi5NBc9K>Lbgu5gnC!8=Ix0_V>IGU`e9Vnu|ZS=6B#xJcn+o$uHQwng`!h7mBsVb zR9DCE(Oa6)V;;o%9NAIG1j-;J1Rr1VSB^b{2S+Y}NhVLi2Q-7n_&xxrEFAujM@ujK zoh8zD(&_+geb9Nk+yjh5r&#)7_xXf%i>JRM>*qerA{ECKdefK)9un4kf-&L>KZXyT z<<;VI3lx*SMpg->r^=4~skIJQ;rJ)ZK|@c}p1>Vp69-3MtWB{7c-6d9EiYH- z+2`M25vp!NSMxyKJJn(JhWjh@hRTD-#q9d}4*9wqKH&D=a&mGp@E>p;eW~oq1bwX@ zkOGW)p)q<|TdgE8=Miv0^LXoI1WNQpMwc|wLSNDj^P11PbtZ}kG%|cZfk0i1qdaT| zeGk}_=golMvu9`VExDRRiGgYY=M%u@znfn@HPZiFY4%B-tCi89>?8#Oi4 zB+LU!!iYXuBs%v7i^acH;F5oC%@-%CYT!KP1^dx8i^x$c((K)SI|Wbf?AeaoS#mno z5p=n8arNBr)%?=45PIdTrNQf;@Y!2tQ{_`Ed3xLPuz=b>D@cO5b0JFlB+OcYC=@_OHxcQVCzZ8dsM`uCBn<72&Jj zU72tNfZo1^(#hM+c=IB6I*xV7#*%WZJxUDVXwaR z3sTlTFSoTip4-i5#&=h}Tz_Rew-F&7^r3KjY1=%-vj@$nU**QWNVI z*|xRc^HAK3*Sv9jH%iU-k5_x(VWY1<1x9pHLLy3=yhfSx>40%PaE}yMCnUgYkSf92<5c zNNLaR@$udL&@FA;>g^ui>h^$ z1{a^LyTQG3{k8EW{aaDo#&J~u3a*Z~ZA9_jZXp5V!uFE9n`c($Z{Ay*Xt{pn%DsCl zE9-mfD_hs@otW5r{j4Rtseinu=DoRRyq}%g)3X&{K*sK^{XO3J)}EgJjijADjvwmg z`1r;i)ZQ~D#N%C+=rTZFO?#~$p>=U(#yer7$tgvg!T#^*XQzOCU53|#mh{MdJcD+E z5HvvzRMV~rP`Y66&1={0npnH?`iZr*l?&HST)%Sd#9m&yzO0)8<~P0-{kwIXCE?Tn zDc(4~QI!V?$={qS`i8DZHDIsTvT-+>&Kb=toK@qbUtPvNb|WckXBV+6noyGbly=}w zo7~xm=^^!y5=Xg#Tsw^^g5{2u8dEUk^ZLAH!M)^tx#b!(X9o)nUC zk2Rx&{_%}ZdxuvxVUE{0^{W#L(dC>lm^v$0&RBZk_P<*VBWQu7+&GSNkeJfaKZ@8$ zH-lJE7$BAxu+?s)bFnC~l|>J4RZZRcly_+5!s|iW-ihl$+r-T^tj{K_Q&2u}^Fcka z5oG~QrwTYm#O zThV>!#Tt5+bhh9pf8}>g7&>9g8sCjMv=BU`A3OsyjZ^B>9f3eeXyl1a) zk$(Yy-CFBu?;mHw#vy8CF)rrw=9xTtb6_y-!sOTPVvBZ7++10iU%QL) z)bdN5f9bhb`u$$7-h(Yh&vW`Oq*%}6wBqdEis-4BH)v=W@AIb$Si{GM((CxNGkHM!$EU%rlWrN4fxM1yUE%+mXJE zbUV^NBJI#=C;om0=?<&fh_LJyKS^%yS0P@5Q7du5}~58|ht0pGNwBk^UKp zb@8vM_fCAj2kD(iab=y3>ugsRO>aP+vye#B={mg$f6vzGZTS29NbHx7A>D*Dg!Eyg zzeC!H^dY2=BW*@niS!PnSmx1&h-n72TqKkcX4bmk@??dWG>O=Yi zr1v2Gq5eI9zr4?}Eg-!G$wN98be)fKuR!AbVf+6KX+6?^MJ@4{V5W!y&uWY%V(A%v47cT$D+SD9@iqRM&f+`TcjKG-@nG+ z>yY@jgv2@aL8PmYu0%SP{YAPsk4YE*l8%i?q~m%d(!pyVK>9oV`^BP*>oDA3q~rfa zB263gchbe{M~kkwwR$XgFxL><_n(k@kUopF18D?l6zNm?`&RtD73m8|9Y}HXC0$G7 zEu8m%jPyT|{wvZ$NIyr~kMtlC`SHIZJ%IFUq{omhK;oR?dLjMCYOSz8xJKWHM7kb9 zA}#kJ-K*0#@%N`lKSH8x=t8;#>4nf0*N;bQ?BmMjHOkb}k$xA6GK2h!?O3MMmH10u z#`#TIKsl9E){$O64P|yBQC?Ag{T|YJNE~1O?nC+`B=Rn%UZnTvzkh*GQs&iB7S z`X5M?AxwX)6Z?hrbFMbpelwpq?(BC%ms>yk|IJ90M`t5lrxWWT9fltM{s7Y7AT?UQ zsW1FDT>s@LvkQrId>QGhNS{Xf2PE>MFCuM6`Z^NtvH#ho*Xa~4KkIk6e)5{7NNoR~ zA(`=KpR@nhB5_XsITG)=^}GF=Rj;}4*3Wr=G16O+NXH7KcOYGZbgfRj#{OBU6Q4I_ z9m!v}e$F|rb@Bnu!!*JmP;znF6Qm-WTbvftg(n6&(U%0dux}LjmwljBOf*}=}dciA^0IUXtIFZm>*p~!;c4wP2Hn? z`-_hhbMJqCGKb=FUNHAf#oTaZG&eX~^q<1F!QnDKMjzMD=LXB8x$a*U^UEH5elq{S zn^DfCdjqxJRICqI`*Pjs<)GY3-!F=}4?H`WyN<*}3ptod2nu+#n7bX1@5bZj2Ockw zhS_4v@cO>d(fsIOwV3Z7tc~V}yKBX^(e;C)qx^;B^7`&>sdRLGvABLzez^quc~2T199`en4SM^!h4R5c7H|Td>jTxc z%oB7zx3Jk_8-Jn+wPHI9SU)TzKLnB=dcHGEFegh3x`x@CK-EmKja8tFs>S&vR3&u% z==yRoH#m(P?UDmc!6V)5%O&g4jq68A-TGm4GX~A(ktglr<_;9%|KWy7Ej9G)B0I5r4tkJf?!9I{W zyxtU~vp6MG`lKe7FJGjcq%w7$qW)TOo{SLY)Npl_WRGIvv=5?F(B8gTtV=~A*CIpVSHM#uG{9Pez5UUBpE&UmjO_!pG40WZ$crFRgNiKRJvrULwKZ>=7 z_K`SuQV#0!TS=v#Nr;rGbu!mFidc_!tsfrbr!8uDu!1SAia>3_DT(K%lNhXYqdz4( zgv37Zp6>OdLZe#PLMSQJrXWCVcuI6e}pP^jsfs!JNoLpjB%aBb` z83LkZp`!~pNmaiV!PpiJb_>ycE;G&d4GWibrz*K%yUNUEW_Tgyu;K&q8OjtW2lKMe zWu)li!$vGVAaZPvD}M?UuD=p#b+9<^?WHe&>!EM$zV6L&BGzQZTKIINh^LD6_4RHr zncg1vejmQI?pwER za&p~6x*65Z*)7%3GWhk;KsE+XaPDY$qi~Lho#2o!6rv~hty{Hja$l{p?Z(L)SFPGN ziEpcLZ56Mz?%O$e`G^4OC>_~QGz>R(gju!T*b`RRz*6N!i}IeKY1g*P2M=$ z*}iUa6$WB*)r9Woa%XKzIhNw1f_`Ql_++|V=q4PB>2gK)&T3~H30*h2uDU9}Z|AJ~ z*|~4$4>j4?VQ)bSut~kDj}9JM+8?yF9=u){6kVcxEZ ze!=hvFu=!6hG4;BoaGJl^s3p;MVQj7*z1i@e6&zfxwyzdQKWob;-4F3+8~zjhr2*F-jZ1_;I`HHt+)pZ-t z;b&GfU9)W2;Q;)5xY)96`CHz60mb;O;A=CTE#4)UbzM0V$n^+RL07T)%yOu+Y3a3B z1>1-Yyy6;mATvDQneVzH*gfpvw>bCTdUfRf)o(WU%boSBp!R%AG|xLOFnKDS&Hr(1 z>_0-fT=0%?Q3}$Ll4@t`@89{uAKv-L^^d`kK->e&G6u_iifd~`XK5B5AtD5 z?rZ+J`osJ`UsJ;`w~~8_GAn(L73U3N_uI#<-4l4eb(kB?A0oS zt9@1*#?9G!aE&Hx`|83!+DSh)s8CKcy@z{V>Tig)E1hjSv9KW(XFHeZZ=Id`%l&Dz zM7E;TH|d?@f>GIXi>3>zkzwk^pcX5h!c93g%t8#*S=c;7*Cnu6q0XjNlj|@zJNK14 z)z{XY`#R0FWO6v-arz}qPODOIXizqc3b8K~t=FsoHrX4i9)xN@Q=)j_jgz26zP8>t zNihcMZk$Y}L}pK%63HP2Lsjh-nv7nhh02z`iXlenw@8r2;*>&Dmq5a&;-;%1A)o>h z5-QZ?VbeF-4ehq+g-US&#I~rSFd~&=3xxLQ`o`+NwKJv*;`BRGz07~;W@WT({pI3( z>M{uxSbg()Xu0&}FQfJ3DX|MSvPh_}5fW;B>~HA(78(T)YgJ=$YH>YQiR}yOiLgV% z6d6?HX!(2ua})C^tc;;@mwXahUeSuQ4x=tZNmG$3p&X`#K#^uB+reg)UGv3#kUD@iNlR@whQTzrBYkz3(P=Ykt2*I_!Z>+Iz2XNmo#zoe9e>GN>$N#SKI z3M>^{zZ?m{B2nMX-z2vBC95WSs0fu2bjhO!QPfOlZq@Th{F}w$zohytH~8b?)5R7j z@rI#BZA8`xIJw3%a?eUMuoy3*%E@1KiOJ{-$cwLXWtWt<>~fP$%i7}GgLxqE-*KT4 z_>f~4b_M1ABgLjGuf5<4n)L$_T)5(jU=9F_tKMP^ll9>fadJ>7x8ld!L{dkzq%46VbVPGVfs2j?Df}Uomj|N4z4V9Hx`v!28 zMot$3-JVuOgq172(}d+-DdxHt37GLsbPJS;PB4x}6b8p6SCfomT3|sO?gLU99-J<^ zHnxaNNG?4Qo6HoOVK$^ZWa-MvCUz22xS$S7ov%m_1x2k4fD!cplhom2iwH3#VI6B0 zMkTiBFp3Bi9Y7I>iV&ZeWVC9ydX+hn9fuHDG!#ivw4(q?D>*9th4RRhq4Y=F*ALeE zT43od7Ecn{j!rUGB-Vmk5cr&$3iS!(OdZx3v5sn#H3#y#4OU*DEnl}lOOD8LHUG5~ zPpaaRBD0?rR)GD2mdh!*A(vHdBaxHV?p7;(4@l`0w^?jrs}Z-)G{~Edi`l@2|HTx% zuQ&~bGF+118<}ZQU06@?Su1Rn-_Fyr%G^h>?h~{WpEcq(H=Gk^9sl72Rx|O940$Vs z{1o=#-0-h$-LsudFiF7PAj$}%l-Qdf7^Mi19G1PO~Ea15XoWXrJ29mOGna ztAY6-qHx%kR!@YRDgmr&YBxFt?fgPc%f761w(Q)uY9IClQGG&kZOL-jcbgI41n$b9 zqSd}E*f!*)D$x_T3WMaT5{0trL*sCO+Q3!0VMcAr+r!irQ3?D@jF6U*iWSmktVBpl zCD`{jR!LY~2Pz4O>u4n}tR-=BJ6eYt8$Ijv*d+8;RDw%mB6Cjd-_^2H-bqy&8)!g< z&^EK~$mRj&Ys}`Hep&%Njj=0mdP_xOhvPQf?!J?z+l?}JX0@!vT*Vp;@3&K)MLV5m z!6an6ZMN7+Oyc8K$j?Z{&**)17JvG<5%kl?1wFh{UW)znIRpyshySnBvXXBpJs|Mc`{59$o65X!>UEmUBb?gA?)$MKWSnA3kdE}DB5D5 zPLTKVxQK~g6r1TI25296K6`g zCCPczW_$@m9X>kj*bcBKoDtnR8F1DP%`__BvlIdu-KUkSswVWAxC0msEIZ|<#IV0tRbb{y^H_yaCCJu17gtL_#D{AMiFkTy_bs4Hu;|d~w{5K)A|tK; zL!-@!6Z1x|GvAmBsJLi@s8?ERnI^RF1CzxyD59!2jfzY=y;-LNy|oLBLKbt{iK;|P ze!F|0%X~oIu&fuO1hnw;*%q1O>&i!+sKVwDv6Q+*LExbIY{V(CEq9`-FrDPV^*e)K0E46C6vfN}#Q*? ze_FK%e{kr4S7c+XHu{G{8~s=_nJEq|C%VzE52K0dvX*0zk9GPeK-{QvHGmsZv);Dq z?f-Oi`yXrSGqp$fGhqRQ0k|b}*7oQN&IgI-XtO#A0|CSnHHHM;c%v1ViO~uq6On`# zl=lTN0Z6GTS2GYnE)Ky&asX2R6)}*^A_FP=Hq;(b6eQP<=i@c~Dg;z(dRJ{D7`j#oGcZ6;c>m1=N-QK1hF@BkM0WfeV0JA+%K!Xkdc=$F8VJ3xwCmON(%X1pTJQ9!; z#{rD^B0AQ7^p*N&kJY^BS6*QN=A#t&<-oK|1TcHz0Zh60ltMJv$;(zF8^i1&53KZs zF-#dy2**(c)r^ukHjZJWL-Sw!{F$I9m{ zPxNGnbA+^2Te!le6Rx0YjaNj%LoWiyGkqW_4L*bgxm0f8L%<;+h*}mps0DRv*djO% zb+>fm@VFd?N~=2zT>^EdLzif?0V76vPB^>T*d}LU7c%?&S@fb{NTcXwm$9up91s&PBlIFiTvOC9`hJS~MRH`SUnEzu`bBOZ zJJm`fCBMSZ%TZLnKnX#_k&Rts0~WbFQtPG@t!$R`5YKUf%?ZGS)GwUe z2#;iyPmSZ3FEJk+XQPx%JUyWf;Zc2tYR&I&?ub()?Iba4lUb z{Caf54&c}dzT^1d=pf^1)d%5pLq!AhDu8~}v!Jl}cw)LR-)|Pg_{UZf0^ijJ;R1|< z7C5X3ofS=SjOU^cy-553W1TbJxH#^i2tv3VeLMNPS%2FOP*D90`d*RbY^{5G@WAC1D$d4?Sx9#Rabm= z)WH_o=%NAc>Vu0B8IJC}aN4vy-LK%F9;L}UWB!kQ! zGt+`s0+iVz?+6qWEu}8$1{$~Z&F=h4;#UkFc6v2gsiLMP*r_&F?fSeXjdj| zkvxeUSgkS~mdNhzlWC%qX3-@Y<-;XVlc^*_Oq4o*xoSse>*|ydrjCSib0sP?YoUa% zyqtFm22Wv^DLS>turWmWy9qv3Lgw>E#Kpv>1Dz81H8m=oWP16_`$i~yg=wB(@)})# zH$Q?l-2~&=9T7D06g+}uCr0ZLiusih-+d49ClHHv5<1k7)>SHqf)mzawNkpC`e=(B zyOnyL@!g0H6@hik8Qi8->sIYf^&7e)0$v`clQUfl40yp&AxNeluswidu#h~1D%43` zxFfFOv7vpj$NkQ^qj)4xMJi7QDr!vwOIn=NG~5Tk)7A&>BfiLOqk$NgHej%ET!J@c z5wSoluU9CEM=pq=%n@N8u4q~{xij9=lKn>B(jdYCdy;@CJR+soS2DtZ$qLOt;7uDK zZxNm*+a`1(Z$*G%;|gs!Gwwob1jsU7oM*9?)5gV`0Dua6Kv_GJBKAsh8|Q?P@b(@7 zNyPAR5DDJnYz4xXD)2+30-C|nH5kII3j;N4JQO(Ag!VeEfEFC{rq;Ck(tW0ME7w6NqKOw@t)g|Sh)8b&WAJXGp2eN;$;kX>81R552^?7q8x0=Co*)tXq5%gTYlLQCsR*QfUB zHmowZ7FmRD=6Wr-** z9`%!4kNlQI9sC$K*wb>R#J3~I?*|IEC=e>40{PH>y<`Wwe~fj?kc7V|a;5kEJliIX z!s?^*bR-=XMjsVOD10C^;V^>BOK3vCedTj!6qhVo2Pmu~`l<<1_&^%!FKiJ=4=AcC zs-vFzAcAabub^S6FL<<8e3N)IBQ@*^A$@w>52yF~+ZtF{!@UoF0tvE&3@>rc^eiU12Z_steh z5lOA28~T8NU9#B{WtT8pG;jT|JAwJohGQbI{Camd$gO>vMnMtmDzf6iPR6>GSVV4c z#iYjhfrl)(wp%4k7)(hmrh!M;4k&+=-ylOP0y^5GlYC0)xl}>apO#1K^!D2k`P6!whKM4`56-CE5KTk4 zEabHyeg>mal2uq|F^5%4P`=X={Nl5cK|Mm_xPw6sBYZh#T-Y}MJ(+M0#4r3ki`PoB z?=yM_TD<)b8D93(6c7YrSbvN1oOhygsgG)hnGHNNH6IAyECJ>GifmClr~HF6>}oT5S~6%Y9^oUEu;Al;(+wLa!ztwvRfX%u2ppH;7)06l5gB)D4TRv57 zcejg=ct{3$xwZl`1_$^P5#MlkL+KuL=kl`2;iM)4y*Qprd6>Wv|ByeTxz6sp8eSt& zgS+`{ ztMJ$C-Z9ls@duggEyFewiLx$}@aM@R_f@~f>av5IG~w=RnlX@bk4#C>+nxMshmhdk z>~L(@+H-ZYH~k_RhC9?-wYQcmkypc{M_vnM+3~jx1z#M{^BvGnw#AlSe$|`a_Kvr` zsd~A6i`GCSHNo~e=Up0_kq88<+1UiD znEi&`8y*jfPdn-s=a@Q&`ThxaHq$k``IuW#X=8Rc!WQ4QWif6fA4E9bYey0Z);QBW zw`oJ=lL@O$V~iz7u#+SO`nZX5nAED7mFCB!vf)FSNu}8rrDdOJBAN2_MP({a+2zSE zO{Sa3*kF^o^sBnz1E{IxZDz7_5+RHq88SY|3yMeIgY+_3^P_R& zDUzEK_2{4?{{?|#VW4O7Y7z-Wc{R~P-VI#5QjD`Fq6TV?u<;XLZ-TDreOt!)rZoO& zv#(Dll5TexdxmsG2731fpYPH`qJq@!Xbb4QqnFPKyVGwRhaDTpWO2%^kLFql9z)Hp z=Wv}|T;6NAO!Q^W7GhOb66}z0>4oHlg=;ECsvfoN)yq*#R%TW8ziZ*!$=~rSh&hvw4Ct8AbbO3 zA0KW<__&S9-~hv7U=Qt-&HT_tCYlK`OKn?rgBV+>HF!5gA^o}))GN`89#7>^Zi)!t zD#bhrwq>efpRK`r-oaPaTO&TOl2xmkIa?`_1MzTUQYAC#7;23TRL5qvQ|Bl}C z6YzI~PO9q^i_k9`HMfB*fw))b?x0)AM`kR_*Onn*kjoI9n+$Tva}zSgnRZe8<*!+_ zj~NBlUb+PUde0JpaQ`>BKU&y?&!{oJ){8fplW>_}kAJe>I?V5~^MpC2Bw_nZxsvOT z$5nkG80d^A9zRiRCpga>6fCj2$p`at-Id$H32n8%{xMC-`AqM>w6F@dM_*ziHy5S) zrhM*P{6|9t7B!qv2G2JN{d51U!>^@oRgozzp9?{)@pJ4DvorjvqNNpfyR^a*PGGVM z$+y**f!i01TX^gy?^N$fH;cAaK7bf6&pb4O;#x&G*L&&=-XzOU9=yh}TNfm+U1yrL zGzMOr)=U_re)UbuT{1YS`z{a<&V6Y^x7@|}c1ybuiNO$fN8ZHHS;@K=wo{hDJoM7l zl9E2G8!Zik7ZZKDES2Gxrm`|RB_k|^xh+10zP|~`e3&d1;Mb0_0$e5BN|h}Y3a|@i z044xn!~_cG9lTqU_`dO<7|FC!SS$iwi*12%Z}wF&Ki}}`MK5G)ake@TW;d?Cydg`0u9rpjBsEVSHic-*6gjqu)4a*r(t%( z-KORvD=wIiWa?lB)#L?B;pClCAk*n{)Nd3};_{+OSy_oO$qG9siYP?^C6-6WVo>0 zH>(fUnzi!5s{G{#3$3^mMevPE#^*F&+F-Lnnq+pRVvgyO3Z2+Mmr|KG`Kc@O4(f?r z*FGIIL?#U{I@z0(OnVHSWK^w?bR_E{Zj$66C^dJ}ZW=>qg``E7QdIgUeYU$%Co0Fqe2{Min$}b#%t=;=raa^LC2L#N;Cdfz9Me)0%5OVtEe9 z`N^#P)Ozhx)gNxS(QSzlS2x~}m-2My1{6<37pgq};XcUr-p_{#?N@qnZg+2B<98Yd zYM9G@K5{(1suyf1X)Gu!pnf4g zE9X>i7Y4P^8|cAgD_%+X(d|=ymIDjhvCzVNt3??iEQDCTcY*ybUyWzajz`00XTTX< zO&7B2YjBpF#zOmBvb?LDyd^QTunK!$e<|t%~ZxhCL>|Ub?b0S*I zHLdyEG+A{L%w`o@8{bB4+Z!j~ygGx^-fS|AOcF0zmfecdC~|ELc~5q;bhA8E-cN?x)=T zu~T+x8GCE>4pYqnkiXGTdjoEzq-ffZyp|93_7cyg1>^Mf`jmyJU})WRuN|l@Y(&vtmNX&!u9BDQO$T0?Q<*?|f8N33}>p(qL%CXH5K7BMj= zYY7bxyQVn=tr|v5KxA9%0yUCW4E%tRh{ zr#o0F+evMB%-efCCo}tC;%-*d?ChgNZPdhV!QNuXtT%Sb1+1-I?573XcDM<(@(m46 za?e?0F7Zjjx6;+eqC^#jhrL&Do}#@80L^STn!dOreK8;9J}GE?q^^Xyhav_!_@p7+ zmFDdDd0ZEst3eC_XSCT*<%<1SD@FWqjupbYK-aTKudTIq!LPh0>o57ME3Pg5A=T#u zX8tFxDyBg20avE#{89{uR>bI|Uz~^%u_W+8Am5=8%kHGvwFE|E7|xSEN5Po}ezqJk zZBBJdfXuMd5_w+n&@Di&h0p0b1Y9CPH7b|N7&jfsd@bBd&naCXi_6tZ*Sh_Ol94QY zw*{TXnBJF7m73)$q6HPYb}TMEv_Qlw9cD(T+4hxIIBJX@2x~ssq$cMn*b`rGmi!vs zCqT4=GZ%6evte<&TXE1d*K&t&^ehZ%o`I4>k`F@~s|WMFMws0ZC%p1~8Wz-cV2v&E zq$m^K-Zef)_Gt3?>H1u#r1X0&c1VCh2e>6EEaGDrz=3qWNI5}@(ugiY-E_i9@&NX|Oo^d<+$VI?5Vh(bhm z4@1%b2*9^G-b+gY=EUsNmNYqRZ?G`AmbUT0{Q7`}L{?iOcw=g=ClMGVAr6@) zz4$utfS2G84pZ3EBHY}u(_N9!+`kXagM^UsdOhK4lrh^vNeDfXV09w(sRZKYm|^SM zG}BeAeJZaOhZPu)g5D8pU-+vZkJUKrbx7KMuM{sNxQaJ_vK+v-&zU-5P4O*~V0CEw z&@wDzKUOf@?#QIIUQY(Ewgi$;sx_NuC)u!3Xql;y!+SOU3Y05F{eqQf8i{2H0BjF8n?F0&9EaH0z-{GS;tLLxrL3LxC9fEH~H*6kk-MG+R* z?gzP?W&$EZ;jh_b9nkiBCKCU>MQsz)5Vl092!{BWaLH8+!+^qFWqlpxVZ)Ry2it>^ z96*sbV#&EC!`eAA8DgN*V7h5UJK9CN;5hb!;JtEV32dpAIf}>rD3F-zV<_t)-Y+5O zo6c;F!(`Z@Ex7Fxr3X$~45WGGqM%xXT``>xcEyrQce4}2Y>6xkO=LMwnjx66RLSB> z;Zr2dSTw4?lrb_Aba66Kpf-LnG|6`g_pC8FoHzXKMW3twX0arlbqG_M?6*toC#aHG z9@~=Q42~=pnTgS^I@H!18IuiH|ECwN#&$U)={WsCHAkh&^yQ^1Y)fxs{z_MJ^~(CI z8QFLAmR|ei!P09_Wv=e+Exr2SVCmH}^;h4()&7R7Z|3S->aX5E zm~#bF;{My)>!0yg?(D6t`CjkLn&bR@PzTU$-uPH=dF$ZA{Qdp#?3E92ssGc);%_*T zar5lf(nd6FaO)t*vvFo?X$_j`F0&tRYk$Ou*!D&qAAF?u)L?nbZF7gq_lzC(#f0tV zgzb_wo7eRA!jdmnY~Cu)<&B$X*MOwq#`k+WHhb2Lf&Ps=v2~Dqt~Chc#r{VTQ9InV zYiw64!qxfnd@D$xxaraQv2t&c2lI@t%Hoe!MUwv-R#&r$o103JFLAVdJu0?a`{Js zsbP2q;{e}U@A8dXw{Et2Y~IMrT^oCQ)to(RU~Td{_?O;E%C}|OwPyD{TL!lr-ZeY8 zjDH6Q$L=|N_%`l2H2@!I!roxJbSd{YZl&^r zaO&uH-PCdTo-L;+^F3o*wj91^aPYQ!sKKtogM+&c@7l8Ep2KMk^aj4lR$4^;(4%hH zyp?8#AJ&~et$p+h*G-Ho`+?q08g(O9LZ$DfSTykocTxS}o^|C{>tZs|p@aznHlr5e zYb8Kmj`h|yOO3lI;5}m}27AU1Zy7{Y<_5bD-!?d?UML^lb;>tB>(wfB|JF5PFuSIE zGk=L?=Nj6WyjSDA25sC-Kj{WlU9->H{XlQ6zjJW&W`-rDM_qV@xm$m?uJsPiZI*)Q zl_g@Y7S_Aez^f4LWH@(}zn@nKe@R-&&rj^yZDsa{Hb7xB@q6 zZwBe$*0{v{Y45hx!i-9C(-66JkY#t2==;6L2G76kFaz_REz%GQ%jk3i^zfFWUO~`= zjhhFhhFd8k1!bSA+FNCpsymg==mq6egP;?%?8eRL_D1x=lqb~$r_1!VYwc7MtemJ- zKLc3B{2s;Zq6K#yo*nGib$H9%VCQZ3=#TQ@+oD2(1{7lX;MR>G!$!}wHdtG8c4$_i z_8P+vD~gl2b@QFxVAKZZ*7N{6RBJPKVl%B(UbAs-%`$(Dp5_U98BNdDWrg92L9J=d z3e##~jewEWJ;nuP>)C4Ry>SK;Ff&-*b=%z7iraug^kvJIU5Bk^V~6j#ZFX?UuEV#D zZ5g|5Ea>=5Zw>23Hc9_xVL5|I4DGKHT5e5N0+9{b>e|nbAzQ_bB8-`+j4lzEXJ<1 zh5EW%;Aw39@9ZtD`3}TN>>AEx5`^?KdEB`98@=^j0yk;bZ|jl4#=A@C9W2Gx&3pl3 z4X}Bn;r$Nmq72?cy96ysvYywx|9bv* z`|tho7U%o>mD~M)rE;lMTDC}wZLp{Vi#o8V1B*Jar~`{Su&4uzI=6!U5nda*B4U0>i-MSYoJ#{!_X#3ZJ@C*1WD(A4N{+o7D9gLe~rJm z{iWj{gnl2=7|_q(fusw%{(eaP|0B?kK`Wsr)BkFJwZY~7=WF>XS_AcYQv2xdUxZ!< z>DlK&(!u%4*7It=3n0mU0dys#G5C|vT1Ya2e8~>-U(fFls(m0Sl{4%8HPp97Domjr=FT9an|1>lPeGs}9`aNhHq&^oWhI?v% z)jLq&+wRYL`K#fjHrH5_zKue{9Fg!x*HoVO_}>?@{?cXX|0^KjzuH?Qd-O(Vz?1qz zV^V#wkn+|3S3#1ma%lYjCZxW8E3^TU9h6S|2K4LDLduu@QNK$Eu7Fg(b&%?<`l~JU z_nRTz`(-GM{~zUdjl*{PJv^uKUjRw>MFHnj$00~~r)zKbzlXoK@b_kDA?q*ss+ZbW zb-oUIA0%B9y%&-`UJLyJq=kD)f_(Fh1A-*`Yot;Q#CV@AH*^9`A|HhgL#*{{kq~zrybtd!jc$!u?-_ zBu_t8j@6Lv$uF9({4nmq&se_3^3OxBhF$?}gFXmp90+%%bH57-hd%^KFJ1!4_Fo7+ z9}0Zi{VDkuK^H*kf7M%UFTU@D-T}QG3b?1AqF;kHKzi=SA-$_Iv@16}7uR1ru7ra9 z7uE^$gm>zPtD&G1zs&E#3cVkAozBl#zA*odkmN}JKMZ{oQXibvgrq+~pTf_$3@_*Y zAoS~y^yY7%DNhIZ`Ts(nfj$lWEA(YZ{T|v=Wea@uQ}UXXV+GgiY1#J5_R7~P<+uOM z^uhAqY&d#h>5~0i`FQ2Tg>#je=de?qzaFTRe*f6P((iHi1%K6W_hhAG)x^MqmD1av zI9M_cch)`gmzDCs*xW>UYzUqcJtM0s72cSslt;!+gj)m0Dvr^&E9IB|%@YU9fBj;_ zU3Q?3)$Nszv5B#{f%4eMTxI#h(5iuIZkN_` zyF=VoQHBXh*0XA2C@I%;rDJ4b)gwunN;kvfW_Vm&&ttEuKXhC?W-Hwhi&J*PSFl8J zYZd;T=r$qzQW~1E3#FkGmC^y&-wFGRny??5SY_<3hyzIx;m@5Dm8C-?t5yvmxN=Tq zVq$1uNRLc#ZNzFdHZibjU}EHCrF0)M?t9|GMhWGSiDNXT+HGPiZOl`2(8Obv&JnIj z)Ql=LGF#~x8>v(VCRWW=I{0_Gu<&r0t;|kz(B-pE0i-O}^)Y)i!J2D;CX~35vDsBH zAAouDhDR;-R?0&#uMPB2wn}AUh(1esySC{V7(?+o;225hG6~ZYC9!X=8^&G*n5pzo z$Amjw<`@l344tf;L9265>>~EQ0*~kGG2ETz(UzY3$x3Yu-V-BK0+pPupy1SPtd_Ps zZPO!Bl@?O4N78)IjgFm zX=7Av)xg+sH}tQS=4XaJlKv9)Ri~obC_jq6incC|9HU?OrE5%0!_T1sL^$2=N=3|8 zN<*{mX~UksZp0o$Y_I%NW$9I0Zoc!rJ8yp1i%(qGdC|p}UiJkpCjey+>A}S-z_qmo zP4?1v-+bV{12_NHWw}jOfceHG7xV4zgEsWRl;)VvGhYnAKJ-N}zdQnjeOKCU$bow2 zVLY$in_~PID?J|L-Rq|Qf}Gr8`z0GccR5HGGM}ip!WKcveIBa2S4}W1CgwaYGZtjG z&~m#_9s}|O;U&hD!M)iHT`3Qt;f$?S5w0&C5=e>=-5lSkETRp?&jMN*q?L-t>$%EV z39f6T4lv3Xl!oOrpP+p?XqP-+t1OLBzc#Vl3_)6eX5eq)LFnVE{@ASbX#jOYv9S?Q z86NK9smMmy#qz*J*D8!nunA@(4AELv+S>(t9bf}<0^lzZ#$kt6MORM+<6+N9teL^Y zSe$Y=>ZIlxjQcVMgT_<0PET~xh-M~A;NFr|V_+e`CG&uVl2y?|MFMkmk-kk$h{>b; zz;Q4er!aO18yS1T3F7W4^hj2$Y1N7bjnjK?P>g}IpWcp4SGuvm$%kBVTp(WHp91^y0i3T1-q9q(+;{&@zR~%h8J!0m>wJ&(LmD_k z%qh-wcE;>OMTj$^GUXcyUX+h(FPfFmIH`b<_-}eK2i$pW1cPhyD&XCa89umcW39yL zy&9++0J>We0qHiXIApJSx7NVE~@w-udM+$X>SFxSg zapyBznU}{+T;v6#U=be8R@{r$sRK-_7D44X3k@orFJ1Gdx11PU`nHdL{;vD)`it#9 z(>Nh`pi;h~@91E8``yzAJMJF2qJHYKz4CRQc>U4A(#MY-Ebq7?6S2T8()|()O52HP zjMU%#d)ZJq2P0V1feB`M7Ty?H^{{3pkl5qBYm#YWg~rwfidt*#qnBrN({#6;o@43oEkt6GV%yzohx}N zJW&}zsq<&$*r^O-bE}q6C-Y&QYmMVMN=HeNVnx?v$WE5&<`Dil0do5e}!jD6w8G}qz|yg z>J!=+P&j4|`-@7>RnASES`7#3>5#gT7PoS^dM;B}`Uhc>z|4PbfSD8zod3$CE$vTv z9p<7-3jA2L{sqb$2CH3jKLzTM;w{>sG2gAF%?tk29)&C}rP5&)2Ig?fIg zz~Q|)F;3sAq;Fs@3OwGtck(^n+&6M(-{~8XHA+GzIF_r%Y7m*jMY}1j}3FU6=E!@HOcd!Z>~6NViV*{pkuDGY|OJWa5G2M%tdaf zN5u^0!ZT!+YQJG?0Bm1(i+&Tc9Wb+jJ!q>Nr*g-MRC+xR5DyTOlo?U|s&axXUdF zkpOd1h#}S|soxTV<%qXaRUgbmRf#Qh$~qeGF8cghI5ePND6oGTz!iT#SJyrwNS&!H zsc1x?2Ie?xDU&c0X0`xWbKYEn+dxEDo@qYB=DbT$EK)1SCKnj;-&NTQC;vsSV(sO; z<%AnPQkhOY65mGFa2n{mmJ5s$IWjW<WiBTbahpAi+flnb+)xq8(rIh zQV_p%i+A>}^^VqbTj`T~HCdd)1Zvq1f0HG&{P?FYv|cu&sr88&r;CJ<{{uppFLF*@ zS7SP>m%ffk zFOa915x}@3r^1grtHgqOp2&(vxn})dmJEYUgci&bMON$F3VSHy!~M`-Ny8=0qtDhr z4-`e8?TN2PVWGO{Gxu+>fZ4J97&On^Z}y;M*%g*i$HeJaQTUm6Yytf5qqMp3PV?Ab z`i2cI%a03hG!IdRH|8oU>SD%8B1Mk{kp~pdvRny+gju49E?a_?csVo#+_K3O*+@Y1 zxN|D~%xu(H7S`p+@ta>Yu2@Hm(PNCC8i|LBhH9QyUYO#^C6}Gmhb?YcKWpGgAa`!S_ ztP$KnY=lDCsFrK#@+`~<`b@t~?FXn%sa2&3J&U<( zdC`*e(MRE|=W?eXCOQ}&mfZvh&eU|`2eb6qsnJy&at`7&@9!CK>yoTiijmK|7QCZx z$!cZOkcqJ|*Vs^l+=o>zMe-z`y3j?|A0pf-k0K$|iG9|68F(C(q-I zx#yW}7sHvo@@V>WF{pU~mfPX-$-p%WRfA;n!nF)1bCqiowaR((1~$*f#*6cb7m56 z(yl0_CbWTVA17Y#`I!5bR?0B4eQ?_@_w0ez$i{OcV;^7u#xB)ZrORA1hE(G%=b62~ z?v-bX7uE>mt>Dc7>dC=dkze*H0o&J!A{5zYd+0FJ_tLLBAww6Ostff#uU~2 z2_TeqVQAVkpcS@eOI>t=u_l?xL7SWuemmx7+N-EB)1>s4?X76x#Ce7`H)0pc5YyA6 zF*~~vb|~WLwesguelry!;IIRrk{P)xB0Oi(9gD5qyObxP1Xo647wK#|;R-(LwmE7p z->aoQg?%Q$V6Xre=G0~1pym(;2MhyR>;bB<;AG8(dGG<%{VQyfL6{SxR1@d;G_Iuk z&C6tVOeDF;FZ>kP8I;m#t;}pPA9g8PL1!H}`~0nf^Z*;(ZFq>!T>NW9#CEPc<*140 zjrKjEfNb+cU3%_|=$Ez(q3~l5$v1q+zf_E-_8Mz>LOH$0Ka$0SuLZt-vC=ugY6Muo z!phkF;jI>MtGC#@%3C8t+IW-X1t;-V@^FM_kg|PUyl0kVCj(;(**$q=wo*uZm!{tQ zd_fX(&3KwB2B9j_e`N`%>$8($BrlvUgnto7X#nx0?Ti7BK0a$6YEoHRirAKK4p7ZY zC$OdH;b{TAiLHzQ7EmM>+(}ZFi5)1U283Frn~I&UL2z=3!eT#>tA15{Hpv%@gwxIn z2AJ&SNrOL0U7Mv3>c#Ul`!o~g1o0^khGN*!6@`x~<*HH^9iauC35!-0&q_;yV5OLxEgTpd7z*S6$=kSF46BZ`6AKBC z)?0!3UVr9V%%|M;ZLd6H{q<;p?Yk$keGkj_k;yW2a-sy1*d79Rjl zFS3ee!dp&c?x~y;TS39H7O*7G&@cGo$u%XN*|tbu>#@p-%9$x>_%+JhVD&u)!io74 z5T~;Rzseb3LYf^C!Iep`H4&Xmyu#B&I*aF8 z_e7@6jEXI-+nnpU7K~CAEa~22@n-Jox^=EXdVa8nzQ*muud}5&P+DmNOsFS?$ey8S#UaI%6`bMv@%xK90lPmyPum)$=#2dshY0Xi53G7 z<(Vv=B#vq^rZMv~!yDhpw^6)vQ)PKLT}qlY&5koOR8p+({A;Ci zG!+nwp3<<)4TV`bDI8WooAEF=CmhJsnUUy`g2l|hjp=~P$$(oL{r4dyYYd)9&I!p~ z){NMN+#8Z%RA0km5^0@{Q}-DTM!O+%bH+dElSX_72fdPVtScc9XW@XNc}Y}8Lr!=2 zQ$XGnr$eoIh*?en9M?0%F;P~z4t#PwO?M7iKH(CBW~;l+eOj#;WI3by+MU?VDNl)3 znid-F8duBaX^EwqFD)?hd)gW1c#SER7*G|%udxqcXb1Lz=ko4tKu5esN?=<+zD%NEu0hN2rj2CJ zG9jpX_O>yfoWZs>E!K0NuB=F1=%Uhxw7(*yZDgJ}$trYyt1AVt7_1vvuSgwXc+Zd; zt2GJ(@7l!kYz4z3c{YhJce%nwf-9%l7;AfZy-D1M6%1gz+X=}Ig2kU8pNh z1B^eS<#}@AnlD{Yw;SE|F=6q<47kb<@(_k5NTw@5@*9Cv9hpNiDe)bq)q0UQy1keW zb1`Fg1A=qLg^PwV4QD-f#BaiNvvPKiJO8)^Uhl5QYX#o}-@3ix z8hy5nxRoQkJBDVn0UQOSrqPU2j(f6U-2UoTLQF9l8^?ggr*QJUKL{XacZ=&tIr;Mi zu@JgB!;T2Q&T}CMq4L>A@nrwGKdPx6cR0h-av3pCxy7Wn+wq7qOkGRb$tGz_hR(8< zM3q|l#Puw-q7`>|v{O9o@D|I!^-XGeZOa9Q&(hClhw}`)eo9;0^N1OYLlZ|@jn6_SK)EFVwxhG zO*cDi`^RSudj*IJM{rK+3}f4V?_|+M!v!6Gyby?uJ@{M4-q4x(B&czY20Q!BZ4Ji` zoYFayi~x63wiT&1mK#<_Pxe|^9V}`P;;@`Dn}4l=sneu8`Ii7m&3U9lxlwn|nzH4v z7NR@Wg1C{fV?tT^j&A6;3HW8-9|e4yJWf7d0CqM#gBNmKl~o1PdZ)w$@J>6c*}mU4UG#OR9w=P=HS6Ui7n) zC~!zxIO}_PhYoZxmGoF`Uv5rSbZ63Qddr+CoE}967VRouiD)6afY{%LvbPa#F>%(; zn(?gyAGFoq`hmm=dWpWLn&FtJQ$h}ZWE4Gxzd}&3J!=C%7N(`sw9j1Y@B?X6zA_)1 zf>UnRWsI#chYM|qv7M(ai9Wg@_W7>=SLS6zY+}CZA#u!|ABf{=*be-&*~(G}(?DwH z1V~2AnSU`cZAa6;a(YI^#qksQGw01*G zUlID-#A{ymtC?(UAQ`68Hqv}stm|5XJG;}aS;IoxM+$f?B1ez4BrE?=4i)YJ`GbYOD(d5-o6dBJ?&O@&eAtKdZutx5f6)cv|cQ^YrbZa z(dj!ShxNlDd{0u`^u+$9r#8Wt}|)h3hk z;+$QLi8f|>CbxY9mjVb!5~mg}48p}ZU%JB(C0e+d>uDRcr59fMs@J~$wXeF=eO1qj z)R@OqzVvl7uP?vuQv32A&-|gj-!MVKM`LiY^s4FCmtGYf{MUKfI3H^Ko{#i_&ornj zLfghtpE)FiW{yTiMVx%nvzbZ(@2w`1_43;{pU1T)#OBC#@)Z;fM;)mQ`dm~|%0g6x zdD>Gpn9>BM5YZsfbdI9gnMP4N6wE8LC76eKRRMg`+!C{^m{`*R0*{ITm&Rg67|5Go zHpsW==se=72%8&t7E|21`K2$5zCxfyTkRXJO+439CJ3ywOqa-(t9^5f-ubYr4n9k^ z%Y?@905QaOh}^Flv~5g4lj0QR$3+kMY1!fxGq3r!I%=S=H9ILJy5DG{Pb7E$-mv-h zCdN5^=6IAJ$C465mz6MCk)eB=+T8d}Rz>RaA@+DhuuuWZU@<|;H_-;*-m&c7I@(vVEwDq}k#|Ll& zQZ_j|Dk@V>lAllQi*o!Zjy{O!i-Vt*Bw!xpih0`ADv%a&X%1bFsisgS{ z(^;lW@n>;XctcIwSOKFFQF`jlRsKbnP|wEXtNH?&)wQn#yXx|<#qurVD9QblABH)+g-;NY-h( zxEejW%-eL?!BZ7%ann=4q8AbqenL+-Jq0ZLG>L7PY)pqOFV)gT&329f%d+xc7?#bH z7f`F5FFTX$LUl&6mDRhE~ae6+mXPer8jU$kLn%)v&_?w1%0Kq##$No{P*pwVxQG0c>3^ zY89NRrt!)g9wTEGy-asswmJ$dhtB{rC(UF1N;pVYc*tSG<%bZyvO%&CY0O6F!qxil zUbx;YIG7J=Q3SE+>?OM2WcHHWjm{XahqmOIoj_ZBws;eVBzksvif#TV@_KhFdf0F+ z9C2djmeH3gq^C>7$DYH@Rwyxd98fXySdiM6b+By!72SAGq(p&A)Zo zi3>X~y7(ob@1!$7O9E>22&EEqPI=%#-UmhJ!f2(x4gV~QM zh{M<;7507Ds)x<-ic{haIyeeQcu2DcH|etXazWAFOFwvxemM*K~M zB_Uw56o*jOV}kj62ZKKv-tzGod4b6uC7U+V^2zE&xRA=l^Yv#bwwVEEEkB)X>kMI`W@3-IC5s?b zrbSVeva2x~Lo!&~*>BC|HmxovSF%oFVpqsVPppR;+Eth%HrvX4i>1Pl41HU7a2>3< zgi|uCB+V?jey(l?N=p*8u~O2%yrlxVN8-2-|Z`I+}8R9%XGUgwz-&=G$&XBFi4COxH&icLAiK~A<_{t}ePI{(X`KROq z%+0?jN6{ zpe&3%#QvSYzWFC*!sF<$-U(|0f@H=o!%L$$F>)>hr^N$o+o}fp)%-(2LBw3;*$kje zNP|!Zps_-Mj%2j2Ok*C2IV13(h$cq_H~kFIm1@rAiFGo#N)7}|@~!PMxlMSV_N$qa zIMko}@prTa@mQ#gX5~n5m1sMM8t6B3Fbpk{uzl`_=8d@_Ag|6;p5-}f zlc+^Yv^_L%j^ZXf9PJowt_vB~QK?mQ{?9Kp%<&*-^MY^3r_5bUC0J&3L*I)>|6GHs zb)qK%hTZ zHxbl!p&6Vefwwv{)%R#d=R(UYh2?+n9qu2~fI9AaE(M+DUw!BC8~y$+^0g}rm}q+` zH~-jw`W=7H!+Nu4P!fG&(gFKi1Cu%ghwU@vN~`FNRkdJ(WA}5TH+GjCP89c_^LCx` z%x=HwXJplPP#Zn{FU^*eoI&OJKa)>s^A^I9BLfd7FEuQSMXxYjL8m9;r<>1NOn{AI zwm?oS(ZN-~6lGVJ+vjXqv^s=cMg`Jck}k5to>wXFMH@w3;r!^1p@rC5q$Nnvcdmt0sEnv$`1x zP~Aq92Y!E=xb_h@W^jCutFj9CpuDZ}kdj{fli;pLtgK*5R4~4tO5@RU1qnqNR_1{R zR<40)v@@;Im@r=Iml*8n`X6J1^{{Dho+KZ+yEL~)I zs5JLC6WDZ~?Gx^^i32(frMX^5qxJTv)#7 z@{|{F`*2z((t2`}U~jDSTz<(#7hZJ9<(x3^oDvoLXANRvOZZtj{Q?gc$dq3(TRAK7 zFM^jXurq`TFFfgN*bgVgaDeT~;m;SxiEzQ6#EX(QXy?R?xozMJnF z>&&t2ms}dfoB3qf&bLmsgiwekyZyZ>4nA!PTX!_^dN;#|om=aU%+^Zl9<5BTE?>KE?qK&Uvwx+Aqm zE2mcXTzhcewb$OT?{KD7zMv;ZVSQx(I+eOy8-3I+eK+M-^ZdT&xt>~GzUAOoJsaG& zU3#&be=C*!bG6bgvgFp)D*J0S`@5SWP#A2MzuAc(`*p9io0Y&SSK$UF=U*!V*OEtF zg=&=*RHn9{w&dASm~`%{R7PiOOO8l{l|!YW3#|Go=)RM#dAn~}z50fO8)jE`^Y7}_ zx6BQPOR>}WgpFda83$&?dod}ZkSt54L8grwOFPKRQ4Yc&91ZR zz?XUbF4_%6Gxk)fhi0Z0+$rxr;%aecr8bHJ_?{q=y{oqCB-c<*ioJjCNY|))qetvv z)FBxR6RQQB?7G#0QmBp4ul+T;qPG8$%8AvTs>8|EXQ>J*{c5YrzS#}b;M!0FCfsTy zdv&_zB+fX^rCzS|#3mXF&p<$)H8jv;8o+?xRoOMSze`04#j|1`DJnL4D*4ANwIdH# zj;&sDgNl0XK0v0lZ*KKc>5dfXmg$3~sMKem8~m?kr{$2x3A|{(FLBfM-lt+lB_@1* zWItxPuCRq|EdKm|g2H~ka&+~wgSRkFZ_p5>tYFKE!|{f*inJRzQPWY>PGTRu|z9wqIf4fowLySlb- zc6H~$8}{8|ihS*{w4D0^6E^D{sqI>~4uE!jc>aF=+U48T;Kn0L+P}LFc#Bd#GCH@e z2h68pyGZ&scqxzWnp?NbUj&nQ#F>X|v)3xiBb;%K!5W3Gxn}CzMe(=-Ybp7z+0hav z1I(l**Dl`&O5Os%Y`Ep1>URrZGrPKHA3d|-+I<0XDAH){2vd|@v$bw?-ufK_Q0qD3 zR6RxgOyTy23YLz{@+>+B5_|-3Q*3K>v;#uBBd#TPjn!VfJ7t!O;Vl|2wS%fRlApj#eqz z&l&!HP-hA5sF4>W=N3}F>i=434YV3kyNlEgzXrV% zlFsX=`apg1WaY>GFFjCQrGKLLLmz^q`~L-!yzp~7zw6#*(2qbr4*eMPWcpw2FTEGf z7el`Qy$(`as7?Aj>2F>CMM%${52+0Em96L1eiuNJt@^(NszN^r1sRfCFaPyi6RFRh z3#slu3eC3+v3!-`QcvQmet#RZ77AlP`mb^Dc4z~n_vb4!em<73`fL122Q>aa2&s?N z=c4yQ?}Ie%bzP)>QricLdAIX>z5G|hOJhJ|>-Qnayatl)Ne_Pyx)yp5q6&N&dK0AfknZVk)m?26`v1rHeIfK;Hvc!Ew?c1+-T_I^RbTxceo7yH9a_lxYy7Eg zRfb=Jq+`-`>7n#qx~FUU`yRfB7Fj5B(hUY3No+a{enc?tlIv zKmQ#1@6bZZR~fE=g#WSwvM<8;V2AXx4_X5WqeSzSe;)6MWV7Tm>HQ0!P=Ad(l|dw| zkseCU>mbS3?vSG|OH z!arfZ+FJS`Tdcki77GLQe#~#azsK@l3a{W-{2af30Ftf?gU)I~(x0GD;b$!Wr@5~> zsLfsj{Uvl4bO8DS^gp1_KpJOryE2)lbQ5R*n^1ucu|(tJ|wztCoM` z?&(A2yWes2lG0`Sx$^PqiA(0HGb@=h^49~^()*4bD!rGxFZ!#7yChWbE;aN9Omu5QLc^l9jh9r2dm{*-2DWF zxdL%7IZ(&zj_P^qCnrbOuOBvMlk5A|k4}zOtDf6*b!p$^-KttW zx4o2Xa{NTKWBp{`T(z5*Qby&;@rOf+N}q+pXW;O{CLDMx;Q*h&;Z(K5?v#hAdTIS! z_3Ucj_~azT=CXe2o2_=cD<`U@yAW{K6PGlyuZwY*T!{?n(6NPlhx9f;r``j+{=@r$E(ZNtHnkqha>jfc&yr~OSN&U2^Hw+o1_Cr z$7ieM(Q&xumYJ95s#JNhbKG}0Z-)+7uLs`rKYtES&Q!Z4YI1b8kH28uyuB;it9z^E zahRXcw|@P&m{0aiN1W9twD;^}2i#KTR*#e7+guYI-%%8@XEZQX=gl}C9W?RD>KWrG z8)eLJcEuikJYQ#xH(EA26Ep9d9G+FTuBUD3r)m958+CErwRqYnqmz&2jV*ZJQSBU_ zWIU~}jn_<1PF9yNAk>|sC#%n9tY|P$DJjGHaj`!`y3#i+J)Eg7*A+^@I2s;4?#B6h z8pb(-ZfBg*us!2EPphA(cEgSLXmE|+6^ucr)uR&Oe>V~I1HIojI>*3Ye=Hwr5VF1c zPt~O_|1Y1p>&th2=G|8uzog@Zm%Zc*F#^~#dM*K|ANnh_*eibLv$WV}xBg^aixmL8 zwO=m4+g%WO6p+jTcpkae13dkEFXP@2{#f<9)!JyyK}9a2^YWLfOA|!Dx4MKeVUT`2 zem{TQ-e=?IE)S6oajm>XAi_%q&1VjeR>x&M91MeN0jtqX-(&m|ArGyO84MRsdF7F{@Xw(@sd>Oyq%w0&#C^_0EcGTrub-Th{Qgn@5xj5>Dm^sRoQ#3+M$FU!& zsL{z_F|ZqI6fvB)oURmEn0uXt>6V2tcTOhbEV+4ZjLEPtD$C=zYQda1(dI*%dGV6Xs)UVq^|2_1HeYaP{)8wsOS@u@Bif=WhN4o)BHIQYje z%fuoK+rC~czw84?KT*2l*rD>RFT1m0qVV-<>9@Ik8=;Du>hJzei|+I(6Xkf4KW#<}Ww@=Ux(+Xp;`xWr1Hk(t*_ zbaI@3?Qi$s$?6lID18O#Uul$HT7QCI%E{_7`4%R0a`=SM#jr$ihi;I@IkUr)K!nEa z691$ehjA`?fA?ssdJfO5m(R=GKb3Z@`fSST3a@Ygkm#LQ6GsX9dZ?1>X3}Tz3FWv@ zHSnhWE}flRn$+-#>T>!?4%e{e-gKOIVI^Z`a?ZK0UYteOy6gcuvZdZV2W?mJLTtme z>EntLSg?ntBP?R#T?Nq-v@59{;^=GcV|Jr4a&=?Z$=Aj$7GL^juDVRs@jYYmOgFea z?fh9M0?)lp96lfKQ@55Q+0`wLe7L&drT2|nh!7J}8!sV&F7-Ywp)hpR9N8WsB2hP< zK{xuxP86a{Km#XT18lrczN?dtJEM6B?mX==I?G?)r9A_!(o~cmJq(LTa+fKPJw`0> zWm{7Syr}^KCk@0NB979zW{Uyp|MmX?sQ>V{ldrD_)JZD;ZSx0XZ*X_D)~5m7>`o_j zS^r?eD+}jRic?&e|7gxny^9N8$*US2|M!CU$}N#)`c^f075tEg%stFSQArbHA?pH1piaL)gsWZcRj%2-C9)3Q z9<<-Cvy)vBTR|swEwEL5BZ2%}FFZ8pIdzbqSJvTU0oV)XQ-NuU>ja3RlBz*zfTTSY zq;T-ve7y*FDzJ3rOyN5zC%{?P?G}d!@Lc5AXL+aKEZ#0qJ#6Ya>ebZ(4YqLQaC*`8 zUwGI5sg7Uc^yli@A9!dr^<~tas&+|x*Uu=<#M(xI<~P2&!d_JXdzh6LEPd`!Y<$UA6uO3$uh!b6DJ1Y57UJZvyG7|q z7Qk#Rz3CcT=pen0*>MYOxQNom(Y`1CBbLryV`kV%jIAMK?~?Erjoi4GdYQSu~5Ea%9={R zn{XzrwSb;vD!}>!-VOcnWF5;?gwqqSDqt4-`hF?UAqN$BVdsgMySt ztGS_R9{C5e5T(8(y8kXb&Qf1`Qe zGQ3eAN@n!9ObR(KZp|c_`MYt;pE3}N&L&A0QP9ArU2xMSV&I!L4@svbI5Qheo~y1* zA_iJc!Let1}S_sT;2r@I9Jn7Qfv@XY_*k+U# zq^(P@IO!7YWU@ngMKSiLf3P{YtI)}-jmL9vUJClqHA0i4Fe5puF%5d?H=HcpQ@}93Mrg0CcFXq6h zZzkiyYMMT1VxO(ajs>t4ziu6|rT`9JI_0mKe$G~xs|3LWrK{K)k1mhT4WQ|&l^{Gw z&Se@$(SuRoq&RX-AwDPf^{Xud*Y3&5;jd=H&|LltW@?1-8R&h@ZW@v>sXx^4VqKIO zR?n0xPyGZZH?~46{*k#)T1x#!{+v7W980c~59ftVq9-5I8YvIvPC}gM#OBOZ&$87Q zpREVv&rWtSIEd+$@&YC%?kpK8MiT?j7ARM`MVydh%|f46Gz+86#>c#G1CCB{ur%Wc z?uUurDk_>2Vvbk{?kvs3(l#{O48ApRS)H*p#)3w1#V{VKSUr!KRzc);3W9wH4+^3z z5fhm?YmoYqFiR;45*v%qHzDSq@bKZD;kiE2eAIEd0b%3gogD))Fg{^p;oxptm1`OM zb&Sx4qpdQSdGcc#7voPf;Lyi3=Xku~@(&ysStf=`J^!V=7Jy}(pIk&nuIc2zL9>{NrK8m| zX$Q?ROcLiXDoJZJGZw?M>zBK9Rp;@Uk100u0<@c$a-Ev&B-=-wV;YlGYMzj`T`t)J z#XB+>F+4Uo{DFA9bMeDW@XQ-4Pxdw5bJM!~gNOfHr&U$w6C@ zFZO9ewXZ8;khi2o3EWcz2qvNCD=f)VM+99wmg{afW=iG}Qn8?MhWiE3!Jc-rID>7i zS(;O@y&-e9m1E{upQ`?N>Y0Tt5Y;g22hVDKH6@@0=glYBw(`~j^O|4!$89^BdRe;a z-8V9!ik-H=iQ&PF5y%E&B39{T4f2-mTb7&rx5;5`ej}a8r3PTFOptEbN@hp`YtfVJ z`-loia3Y;M+k`N=sl~q5&RtT@5X7JXiETy`=wzDdeJ!HiExbMB2|hkQ-7=GIEl4N8 z>nG3l>091km!uv)2QKmgKW(77R8wrPtY_ITh%+-gN?(^oQP$)M#XRUWpT1R)7GMLL z!C$nk&7NroM1FXld8*+OXL}T9y9hJc*2b#LbhSou>_hm254l&0A@tsACoi#rryuES zPqe^Pdu>$dx}yxn`(1dq1;F0RbZwHs&KznI4@erR2`zqD5=kXwrTOOQsQdsup)ncu z@%k5@6cSq*03sq^>@wBQivs{hz9qhh(B9H~2`ps`u`IlB+KBB6LFKDTl~ml-JSLl9 zF9%s9QSu4R8sfzAeYjLWF&}8Zx4L4z@{EN?0^)?tOqwh_3Qt4*9C<0~wuS#rWR>75 zIo{UP5%$MoWw&GlVzJiOr*A0k)edvb7OHAZMHpin5es*9c76Pur0wIUgPD>&Y|o;w zGi<#gB$K23t9VDomdvEd;MT?3P6Ia2YLeu-KJz%@)i7Z!d^zg2W8 z(r-lKi}dx80^}7heg3rVQz!)8>I)I2BTSS;V`18N%aF#*E#fmOI== zfWtpnZ>;8bS#L)nglCY6e5y^`_Ua?*sYeQe9Df&?wuiAf9N#fMJz2v3Ji%X#pV9G0 z3ug*{moam)Zr~?u=Cosi9akAf`BMpFlbF4uZc5>tL94@~1@nu)t2cj3P06M37TwkS zH(5taETZ!@6+~t4x0_*mqiLZL4dhm{4-;$ve1+M(C_sz}Q$X0br1K6O0WIKgh=i&p z+3b{AsTHhX`W%2DyVc~x$(E^O#nJ(B3T7VF6oN=2%&s+qV8H4`^~?maiV~X{aet>| zgviPX`n^pPz#4`|S1g4#tt1BHghNb&M{3t9LhayGiTLc(0?_O|i>6gTK}#^{V;z{P1Tet4mIF_tURs64Tg6IHWJE{?Sl zr_vjl=%GTZVJze15~Ud$%2=#gqgP-aJpriXtV9|w8<)21m~hGfrrl4D_aN+2(0VB^ zRWvmy0rKs>Aw>%uPfKQVKRdE1W#^FF`rp8;B|O)$10k8=IiT~%tTqd!YXQ0`Gpk8- zDpQKI%QahY@GHR8j?-3vnqf;}+z=5e2L0nK9uKVIX*(NQLM2>V<_g*~&kTrLs9HSL zP`SNIthacZ;HL;;+SyCr!WEx$&lm3z{8W10l6I=gg-_ngaoXwnPuW_6<(T(9ER;ME zWaW?a&u4Jb?7vG!2qCK;w{bmn-GeuubqQL5=jW^B0fzJpw^^D&8Ycs~Re;D*U%!&T zl+Mme2cyPfD@^^oN6ZzVrHx!WLN5tD;U^<_w%R4G<0bsE415$q?B^Y@xSdGqQ4TjT zyfs%W;mSPUbFI(b%LQD|*)J%{Sf$Gc0ArT5WoERuwXlxwbaoA)fwKqZcJ>$6adt=> zGV!wQ5w&s~yA10XQ{>d672jp4FKim36Z5==SPou0@Z2aP^<8a0RO0kHZI=$pL&&Di z75KG_U>(PZ+BQp1Jy;XH7$41zz);YS1J<_5a1PL&0YLrfMFn9OdyBBMo#;sLl(2s0 z#eBs6xFI%(B!|t4mK#_>$nJWq#^Z52jnPfFn>%ceRepin+uaJ7ch>_m@mb}KXh@On zu+k@J`#*iYYby-i?J?MG-8QST9M8{jt=q|+WMLOV@9r3Seg9Z21%E8w#|^yO?(4#c zhP9>nh<03w((v)(U2uj4n}{KQ(L36{)!NPVMYNMUV#m*Hu#8hEzj>w2ES zF3`{87)|4u-M_6V16tJD;cei^d@Swmc>8ve-rR=2TgMf}RE*z1GkeT{j_x4=1&QrB zysGi&k>XWax^p{yh7UhhhdMe`Y;=8>^7n<;I<fbR!ZKP)>%ly+uNJkVk7Uco|(ZvgNM1I&`VC9C`pFc8(K{n~S{Y zNT(X(x^+enLKY(|PkU~-wR%x7dV78{5bqwEpG^U7WKlS_;gO=8OJi)ALNU&_wkFfj zcMc>V-;5lR?ze45Sb?47P%s$g+Kxk~XFG^pDFf7iNT+UhF#2^kVJ%&wZ5bIqbb4kb z7Of)+JNpbdo~^>9OJA)ljuSp#i$j8cRB@SD;6mtyiPAI$h{18EB>4gNL#Jtsyy)OQ zFwc}NL9$BGcEl)1pO=|xBAV}V0G%?+?M0MK?&%mWTYyPN(;ObVj=9~Bw1D3d~BQKrLiV*%=jA)tpdFm#2PyK}J3Fq4uoA#xmxqIR|>=nn9B} ze=`_^37N?_6ZQ7DrZyLUO;{C z$BLUbxs2qyDC9gMoqXWLBA#yg8m5;P)k_Ls-}P%X$80D>+vfB*kvtuUuO`SAfOu)h zXiymn=bBmh^E0g$h}FtdeE|qE`dnab%5?2eH0x|A#5^pmiw0ZvUYK*vc$GjIG!`Ol z$WMvL7GeH|cZN;2KI&RG|8z=0llat%m9|QvZ$4P$rBxn9wqWxy%PuzScEKd`(WEqn z6?`~|{A0H#nW5Xx3^gfFLHIU$#+$#zD`sYMO?K2iP4~Y?_Zv<1iRA9z3-SK4iHS}h z0Upx?Ig*Y?S?JTzt2$V(ndOb&)S`xcm@p*D+547DK}PZ9zZRNQJJyrM3N5r)#vF58 zO{7_K{*I5)}oTlFWx-5Pr=xxaU9glhEd{0jE-fjd88(_#jgCM z2SPasg3VR0NVc{#Cfqg2x5Lt_q~}G+dv1#9vYpv)kn+P7v+XnnHtSa^buTrz#hd)2 zveKc1%m`04r0lshyf|Zz&hiDM2W=gRxf>9Rl^y1EAzPQV8y4jx)~Ih?@e;;CvjFXg zG7qU?78{kvsb)i_pB2Ww@h46)sfhH2;WzMJ;ap8vW%?+Lg?E!1y2%Z_N2-L10>0-= zZ==F!wyJ1ma<+g^;Y&*6a|7do;IC<6)O}o0ax$-5Fw~YF%O6{MA;@XfQoa6m1eO!x7HCxmS+3Uq84K^@ZE{tZxieGi5 zObq1Dukk7CIg!_h)w6DGa zAe%eYJ2#c^PfXoe`PZ=Z2YT1fHj<(y4?9egL)AD*@XG4v6S-%oGVx2;Ib^ea>l!V> zx5(K~$50NwMdbt2o#!rmYk7Ef&c|s&b1O`ea53L;e)$ouejZiK<1IMlx3HE~FRA|$5!8SJakB)Od%`l!-;{r)ql7Gwq zoDS6D1ZSn`>#T9Te7MQtNBny1%Z=;(N2<&GvPNK#zoP$-Sq%J&=ERIzCpSOaExg9( zP~8SWxeIOvr(BnFY>R;$q+x%yG(5F#q0DBjNZ70#{Oll}(izU-!p1ve-v)jr1@N9B zkT+ZXQF&50iQ%&bR)7!|VS;Mw6-yI%#fJ;gla+XK;TW#=G4~&pnw?^1=F;`0BWPuupZ%M(yfY|lua%z#flx@g=gxY>*=--YEE~3 zRgWnbe7!{=?89@3*+?oYXT6<-H>YEq)amqyuGLBmVJvE@*@L@m(`^$f-`^cPZbqh4 zM#lH69lq6$l?gI`Ld>JJ`eZjyES0?VbcI2(t-?vTB2j7z9YP%;wozo9LK$pEpyAx9 z)qA&)zs!HJ)Q5N!fpd!r>fBI*#Gq08aPZdr4BG!x(CSOl&+)If%mU!y$zk{K2kSNt z-I0F$AnyTN8D$p|#~LE7oY~c=OM=M31w}S%EXZc&^RrAuU_u zq07u$PjbJ0A;BE~=3l3YWIS7@D+yz0TwA)#nKELj4O^K$kr*xoyxoUoM#Pz(=2bBEJ}l3u7x16!W>5kJnoT@))joJ*_kCa_ zipqmO%{#%kI}77j2MIVf< zvcE}uT78Gzp0AA`bDu=YIPcv0WB)OBsuwIw5Qg{(HF#W z{bYjNe?d;{3#TtBU25s1G&a!5uqlrZo7eleKT2ejl{j~~IQR9%uzGP|_0I`*W_dl9 zT+dB!Ex+W_nM=x-z9eM@B9MyXYx8{pL|zu_jn$r)y!g^fE`9M!W~(zROVkO7Pm)tz z3T86>lM8W1m^(UO+VIFC#0!wh`r)JqQC8|t$dx9g(#S z-oG~IN&;qktNs~(<<4qH|E7MruL8?xoKvqw2d@$yZSwzD@A-5qMP*eBh~4(rJLpsl@Hu>*cUct z*|T#~wF)~{Vzy1~foplw)NDUlRsK3YPGE}>nd1J=J&#s<_Ux=yH%;w)w0df7&#i}U zz3#eOZw=gClYfB+r>3i2o2E8xb6iQ7+d1_eS3;b8#E2JTUJOsIEg!n|tG;|J!tY^s z@gAIs{ykGudp5D|v~6c~&(zLp|DL(2E@bcALqIXyT(WJC{o23R+DW2SpZ=;z-bNGH zh2${?)XqIPRHaRGQ)h453A=4mjsc8kr+T)*zPiVXK);0I-E?wo`KAMNhq|s?yY|3= znYFb8wYA+t2M!%NaNTrL@QzJW{d3iq_D^k6qxSdjeSBu{!QCdcC|Qv zxSLZ`+xn5-zt0N4zY2>@q$m2a&ux0buAHo%xh*_tEG|_0_is|8P<+p$+D}dT?LJ(n zCk3GjuA@3`Jw!>D9k^*|=+;9+Yp**rG`Dv7(4p(r4jnq6OV^$9)xaT{+DZHFoDwH6 zK_%WcwaxJ(8A^XkSNshx$W`D#wQJiRsxFPzBhsp=sZA&SWs;+|sbovkL~4o-IN6_8 z5AO8Xoo%Rx$x%sA96T+m_9)8SdF!D=HyvNwedwmOYY*Kzx3>G%Lu=RGdSG^K`PKtb z4R%gZgDIMOYUgZ!_cp4sZHnwU+N(cs-o`I5wHxKBZK3?#{hK!JoZ4o6Kym3BRs`I& zYX2-+$xtOfO}wrAQ{tlmq01&xgtxthDuxe zxWYCxGlivunZoJqUK|T5GsQ)G`K3Z{(mQ^{s_)~wCZ#@*siLIa7gAOeRLpFgKXqr^&{C;2r)Nt(@;Y*^9Q~d`F zMg9hS-8t94WYd%?HifCN!FZP557(-Cg1P{enKoZxz(V(Vjb1KAM;E{qHBoJktUwP; z(d<1ln@atURcF>dYv{mD*Ijqhp#!u%U~=7oLpRN??KpJc(CpeJz{_<**WGkeP;Y9- z@S;flJLjgl_Xr@VKnY~;b_yOrdsMQiO`&d>&Z!cx0Gmy|W@ZDq)Fn){+fuEhT>{$o zYzpHPO$BOpPEkwMigwtEcG%m~Q>9IhVUbE`d%Xp_^vbmWOVYJx%cP z0LJ`IYxg^=wSFe>{g3;fSh4;Gb-wDJo%pBd4fX8*R$|+oskFmkr?x#v(|)7j)>66& z6##_3125IM@tF=Yi{(B24+-C=;6|0|VCrP4*v1<=J%KlBD@HS{*<*PypT?|?Q!zv}5f^K%n)33Tq0 zAiW>U|5^SPT?M@dx(?b3jY7W-{T8$t+6KKBT1fdXfZxlYmqIUwUg7DL{QNmjD%;OM z`uQqoA?5!B{3J_!RsZ)vs^f1$TOif{-Ow;}J*2j|3_2fr9<&lVcb*it|BHB6^_Of> z=xgc3o1sBZ1N_|JX`$<{wpIPr4*EUxK`+0HbWim2knS&}eAT}XlJ1M7<7#`ggY^G5 zpkIgH38_ES7Yix>V)*?uB>hwSzaRPlbS?CI(C=yr4aD<>&}%)d=I0uy&y)UM3;iObaU%IY0?k*po{!~U%-=78RQC!b{;z{1`xiW^ zO!`|oc{L>cmu%HtV_?2zh~=yP`ukG<^R4_8y%Bm7^cHA6^h=O%QFy55=PNUQK9;Zg zzZ{azO9ws(eF##&UkhoxZ-d?geHa>pLjBbSqL_C(zt_uG->Tg;)}(WzkT6#|r*iy0 zBpp;)RE~wLzjROaRvTOeshx#8uZPs%p&w+Qeiiyp&_c>r`%Avs|4L{xGz>`xB=1-J z&-MJ=1Pwt8DgOoVlWbw1#=#)84jO>e7W!S+q=&x@sT^Va|0ut&gxcxz_?fu>rT_1Q zR5#UE^%Lglnn)NJaQ_;9SNkkv{Uu**tZ}7&myXHKz1Nd;QM&g#&_^KMTS)mYgkQjU zmEpHNy^EjHfB7L>JZT*0{zAyt7#8N}r`lWXuKxW)Xb1EGPqGKwp!Y#Lp+ABaLVm#i zi{bY(&}yg``ZV-8=wr~05q*^3b?+8vA?2(8e-gS1l3uTcghj7~UI(p#`k+@sx~|{n zEB`#+5uFcdyy*S7{*r$MB>N-05lMC^hsvV%3HRnJ|6JaUDVF~t?x}98AYtHkNPRE8 z*BJOc=vqkn|6%Au&`Y2ngD!xc55>IO`8}4e{#X4)s{cEocR(8R8V}*8u;JJIHQ}WC zP49}@kr_WzFJJYkLh6Hne`@PDK(YbS3H8CRKpG=@Kjt^z-(&ed1uw~xoK?^tc-qF# zvzn0fC+Ji78Ov823ZvDI>es!{0q73@^Z((e#@EfzH=u*iiy^h=MUXHd@YPSrYgUdG zT(75P+k3b7KG56o%6ENf`f&M6n~z>zuD%iOwVXWFC+u<*al%t zOi;;CKw@#o7Z34FoEv%wx9!{G+}Jf3Pn?;2b`RsYgVQ7~28kwa>~cV;FQlUat}hSU zBsS8Qo5X;zxK5B{BuoS!3X+-_g8^ZX5cBBi>8`rJ|Jr+>v+HrrsT%btAo`Q`boZ%! z)>`}ZUyr@^E}q?-tX>xn!)__;OPD#Z#*l zXjE#wRsJv;n{KvSJDQE@Bx!86#+voE-q}dT>#b>C*QaC6xzmY}`bsjk?~|ui$L@U* z#BTUl55Es3I~%R$T)p0CwUa%K=Ja&E*{UZ=Ah(|EoO7QyQ+k!xJ+@kTtwigk_TglF zt~Ixoj5V5@NvGM##5ynG<{k+mRXzxb--pEY{UkcgvyQ-yMl%!SJoF$u-B8=6X>c;9 zK2U{vyH%m}JCMB9m|jaN_dxs;5U=(U|41@E-I@#Jn~jV-oyR9@$<%bSK0V!Pwv#Iw ztwy~*N0kUuOq)9up|w2QPCe)?PSH2%@9emBxgygG9r(B{u+dbH76w<)=^gnBqsannunIKNOm^mLoh3clguf zGZR$JUhp7vuK~zM<24VPlga0jT|c()2cLN06Tko37p+}4QN6x)!yolkQpFUy?6vRa zCv@4q*M0Dw2k!ZUUwv_Impxd7{?>&B=x?8c)`FoN^rydl9e2>(Ee+2WL8T?-sG(yULkQQ*vO$z`V0wIs>>u4wz?i`R59-WUB zg|8;12~+_$NrFo9cv;%oR5eV}Hy#ok;-kXF7j&%~P`Ib(ZSqXXh6t*`)OD&Z&>n`S z#yMAISU*Q9L!2vUf*o|CDT)djYN~-^hL02kVBcu2Tb)XyfMdZl%(O^=zI9YqP#zo7 zcMTdfecG{-Rdk+_jCEn$xM;!j=@pyvL9a;9!kgifE|G?zi!@BFhOuJpNx#LM;sGpL z)t~HAGGg@XpfYGl&@6LIShbBg)nCXJevtt<$ps6}Qz9Ds^j=>Jy}nzA6~SYRT6}H)i^X z${`O`L*7F{e^`1j}VJ3vy!iO@3_TpI5z_v5ccJ`~S zAlHfcrn-p>+e;E}s|z#48&ra~4MAaV3Pv^^!iQHQ#zmNDLs9R2*|nJ#6-^cfKC-37 zcTe2Q#Tdm*i!e%19EO(GZexr^7?{ZJzpXIbKbK7G|LK47OKZn>{mMH(cHe{d{qb9- z`@Mt*ld+fn!_&vdZu!jm>iB2g^wO??hlzv9`_fmRK3;jxnbon@OYi6dz=x6w1S+=> z?|4)1r=O4tm!@f*61eb>vmNVyk*p?_{qX&j&k)=A^vio4!mbyayx3ul;gQ$B!7OU5 z>Fu9}={s@b-;)3CU&^tne>Lg2H~tB4e2h0fn*T;@-Cm-(?O@1xXwHSk4HeR0(oPUq zz~7sa4Myz3y!r8FT`IQ@^kC7TN}Y)ebo~Cq}BPOAOj9cSOGC}7-N%1Bu-MU%2G`0y{ z<3CNOfOaYKoib-+4xdRXLk+15dF-O6tbvVF62Q!`Y5erfWJ30>1!6Q_8!hHq%nvkX zAgvPMST^mxr$N7`)@)!&_(Ku8Nd%BjU?wgtvKB(zn(O;k>@2XNU`)0|{(k?^+1lD6 zelloxD>&j?D0Xz|1Pg}lHY3+{9~^smu{`G#5-VH8*09W&^_;L2<{Irf2EiQsXg3@> zbDilctcRt4;y^$i!t$hfSK>?$~+S=pdCvGTV?+jRsd}Ls< z+TSvCFJVc-Q7dzbRT1&tA>Mke!t9IS@6&JkTfOkNqK^D30hbg?TXz7ZAAQTqd!h8- znaBFoJ`1sxbhI|V()YnTg(C>o|H;;=08!csRkBrdo*=WgLmXIR-X|awB^mC&bzC*9<0eyk( zU}>k%NT~tsMJBqZnnF9lq*zv&A9R7A0raWj7lz@3H=S&BY_6M}5r(I7%2VndcNdX} zAi5y%9ZxGk^iBuSqE2I(nr_Pa&h;2Q2_^>+-i~*(y|~53{}U4L#`w>jbHASADu8{VTmGM2qa5)Lp$bMV?suxF`}ASpRN&GXHiBRY((fMATS+~EwV5pF3`ra#=tfv zTWN6iGGVrBlT2;dDhsrmg;|9}L9&)?u}KQM?v*dMhV`Eg&lVf0@GDQsuu5Hy^mqM} zD6BFtLTw%NU>u_9jZj;Sf(SLA{}v_~$#l74YO4HqQxlcuJ>D=7*z29uH~`ljqvkEQ zcm9bu?ase6I7S$~!c6oDcK(gQam@4$DUI&9a)5mH`z_Ke1=XE}afuX#qGSV8tEyM_2IZSPLoUD|{!=oAyfXiP{Q_Yv7h_Z0`nU4{{al%3*;a@Mb)O;?9R&B3uK2q9-A zvY|;EbETo6fO9%Sz`T%5pu}9!bkN2{O2`F^cWC3TJTh#AI?Q&~U12sf72jgHuc!LJ z=q*xo-|Bn(9fwGdBXnGbT1NWu$7?VtnvK863-d8VZxeK3H!9F-mA_bsV4-?5RL8+D z1~Pl&QAe9Y0EK84sLT48H2Zo=CWxI?841rkAxq|PR`OmWG%BEZI$9}a5>@6bVSFS+ zi)gT5*)N=SG$IgiTlj^T7Ev)fbO4nhKrNz@C(AIf7Ljq?QtxY0DXtlfjryKx^HiMq zmr@xO+TMl-dA>DKhnAl?nM9+a+Zz}mmcxVP@J3CY=D86diw&zcnS}OiKI);QsXR@J8+kt(7;&hOcSV2t6b_* zb4$%Pqs@^+v)?@CopDaIOPaC|oQWwUD>3B)IkUq$%?Uhqw&Bf9O>?l)^N!d@WoBI$ zJq5|3Cus@lv|Lhw3s8`sE2B@5fsj2`Jf0AVW!y+EjeKj_tl?wJ)+c4T)b8`6WOkqL zNaCQWdyQ=7>!+E-XwhOT&X;;0Ng(z(CKaQBK*8pIeuDA+dH2UtJ6FxLfm_kcB4XUcUPVG z4Y=ADdnHd({%EUiRwdA7$Ho+tG%si?kXd32DB2v|n{!eO3cs2dihHpgsVFT#ATh4c z^T!Y25@L6vBdIr$5rF0=&_X-f^81SQsj2r093+3Tri> zXQ$iKM)z{1>L?09Y_Fi9b<)M93^eYkF6iP+GfgL?oU^Fyg=!8l?<7ydH)$#1JC4{I zymz;oYX^D;`|+w6$A1sN4rTH0)-DlyqW1*MnG&XT6x|7-TucNyZDeI6*4h-kTDkxV zkp>bia*%Ci(_lBx+d4l>&M|AxP4wu6$Dy*E7?^h2f)PtJRg?l3i7{uZ9+lQ;x5m+B zt_QY8vyp_?np+(v8scmAn*O6b9?t0Q@bPCvH(zoWmS?Eg`iJpVie!bt;2xx?e%EO0mOW~CvnSA|Xs znx$y1;LThg4VLT7{$!X9yWUr9XHP?cdoRLY|nQGBp2Hzk^ zxql*wofdqS*Mi<)m3FgZGoqCmvFXO7S-|2AQe0A(oc=-)ZFM0oAOnKT5q8Q8K8y3^ zk?K>#CN;3#FVPdXCz)~uKGphZ2~g@CiEAgpeGEFTyG`Y->?CYvl0B->{iL_Kcxuvz+2I_!IHuUgQfsBwF869Jo29nX?gCZm%r)ny zpY1h~Zu2vDsNlR~ZputVS)IRh73-i@#3sVwRdOLcc!8C3cg@VE+6 zy>ChOu!THVue)>=3;x#?m1s5|&QnNmTGq7Fbt(D>z)Rm4tcZBy-Q>`?i%5iz0B%q{ zl?Hl9>Ie(m-$sRnR-$2ypi*MO#-y%&u`s_|n0qnCy`IS`6{`*-Ii`?4=CBM}k`{$* zk+QH>Qo&C273^PnQdAF_CyrD%Y})FzV=9HH-$M*>B4R1>r%+G^=RM?-7Gu#5;3>IM zl+Nf`Qv{YAd32B$L3K)yREh%l&8Ru_%WjAQ`GUPr!EncuP>4$aXf94UxOS6fhAUvT zLoRZ_RPN_Qc{`jHVe=-+!&(q74{KSaCkNzhRV$tl=scNdQ?u|O;`>6{A!iSj^kXj+ zpF@0KcKwr`h&Qu7eKTj~wnPjNd3k>%dl>$e-ivLucr&@3{}twDycK!BDo z;_H?_f5j5PDVCoBg#r`Pcv|TtO2eF5yv@DqVgL=h-Y-25$z2&K;d-m$FE9e*hdaIK zNxMA@WrD@K4Sl4Q^3s#`H+bX0cSz6^oRV1Y*>mWl?V&m(_eH9`@6=C^&`j$%G!#*e zd%FBAV;@o>UbF*ZWLybLb+%{So*5M3)W)91x^^@K}JLA(tC(P|cN>ShD)7-0W@jLG>Pc)0Ue~5xY!q|0l73 z$d8|)uMFoV*6JVg9(-RVG=n70J_ePq-|Zx z>SpYa1~C^;(p{e~i6|h!Nd`~G{$iX8!}FU+pQ%hwFwV_4_I)%?c4~*Ue^bvVA{S-U z82Km1lPAbp&fWi|D?g%$IB`3(-dK%H7PlH53JZm!)ooD3ht#(Z{G zmW*In+xZf+w%8aISy}Hzs4vo5(MaFd1SksX9ButZ_nm>B>`B8_`?OpK7!Qt0EO!a2=uiiXo#SJ-Hlbcm=qUk&2RR~g(%h% zo`nQXS#-@QiA&Z>vq`v|CC`~iZ+V6^pCS?okC*yjV)>S0Fp=n!}?r*d<{SB75%Xeo<$+U`ubZn*7DwMx427 z8b$-4%Y@lj_7_c^Pj)f)wA$w8u!iU!-YriqG5|4d(=EC+y$ryl*Z9ax*rA)Eq+#q@ zOW?!(Ek6sZCmJX#AKq%($)zXPiZhqwcqll(?UN0hBQx zQNc)sbqj#8P`5xyaqsYeNK zc{zqug><%8ge>1iNM5qmOK&TWWIOV;#aDRs>(wVnLn^rlxGu;}0;cX9QB~RrW^6-l z%1h}Nhso}|AeA|oPrl~7ll3@~=5!`*cQf*}sK}3|MN|41pVAoS#SNSIWCH`okyIz! z`ewG%rkLk&2~VEmXxb9h&rLs-E_R`b#SWYL6JEn>N9U8&@i4l$xh!nCa0U5JzHOsu z#Ay1(ed!m}5D`H&a1>{5(8zgi!-NXOZZs7b&y`dUdXBWd*xeJmQMF%JmqrP^VSWx3 zX7r4QRCmFVWktmLE==j{n)w$+Eo;Vt*05%;X{>(Jf zGR6L7mk6V1)3b_zd(RoJ=JHthpKx3_Vq+rcJFDRL zmVU8U8>2qoVkl>{SFRzoGc(>fqjiuWc1Hcw5L)PTjlR1qAjeSNX(~@qI$c!BduZEF zFqEy!a=v0Q>YxV)-~1ZY7^Jh;($D`?VDw)GsOqc=+YL&-(lHnIf^crM=jZ0ZJp=V` z{A&8GidkBnQE=H7Ut{JqzF4SQLFO#O4hL69bO@5wzlP;&Z}tXU)28`1N6)ZxIVWt+ zr1{OVX#BU+D7V?E(X0Xx!1g8kK#@i*J^9}&XLo|$v-=bD`t$RGpwH|}i4M8asfvx# z0WpUf_1$&Q$E(}6PJ-xbA@kBoB2f!+{N%Hk{`Ag^DOw^F43-oP@jTK@#1#9a$p)O; z2i9|oZd#zxD`#a^D0|RQc|dSC63FIegCjVe9OfO=U7|9Y#3dYBz?R3EG}K5lwe5{m z9zNN{i&8@g-ipkx&1pO4DYAK&8AK8>UkBzBs#{E=G@Y;%H)4Joemdml|=sQBawhv5*_(bU&Iort_5-nZc*r!$TTjSlJv8z z@^sjuNrVax^T!M1zhhGJbiMDzNoSEl)tY5g8n9p5D@t$5;}1kBk6r_7N(L?5HE_?M z=^-~q3Y#?cpuw$WUNTeVSJZ6_-3OL!Tnl$vyX71uXA(P~Jy|rjGAV6ANKEHxvpSls z7F+aP=W5*qOp(kqylvm=ZTm~#?=vX>GL>>$&+9gbs5^$SX!3pZh|uHJ^Ct^cyfQCM z#j~iCyS6%L?=_X?=J<-ZjuJUB|vVygW?HZMEpr};q-OP58&umu|9}ur62!$hsTu##%J_0pGy2^L5 zc5HX5J#xfMX|XWb^x^B;04y{>P6)NTU3|-}10-nJzMyD$*Cs#3Wgrb2F>MMrmZKn( zrI!dM8ETRpyNYeuWjz7{7lZH3vhAp41lV*af62`rgVLgC53EPLs}F}%z?D1#z5C4{XDyf zJU1Ka9Wk!i1>{j?R$orZJ7Qe(7m4?V{8H}k2!4reOW57!y`D&K-4SmP&pq7ZS&w=f z_`vh^c$(I1cW_7WmR+>19`f) zUR23p!`k+flHg3#L5~;V?$$!$yXc!-uG+tuk`2YDyI@XtcyZ3gzR|$0BGKyuExJ_H zPj@4q-Rboxc__Q)^c}(SABxlEKHUX|Wc^_xnU`;`<>I1$EyYD27$)~7oK29q#nm6$ zP;$w&Y;KIFhsv#q6Us2%8Eyc>2pS$vL(aaP7u9`R$F- z;qcnen)JqKy=9D{24hRcw(j?yxA?#rbeBUYZ*e{4%ma53WbwvD)M|sUG*V=ILDoTh z!={C}x+CefRWW8wMrPdvUb0+c3YILD73K#Dm- z1}48M4t*~4|FtO6C$&cA9x6Yv#8;4q5GV zhl2aOM4S49zthEP`#45ccks8)WOaGL?V8z1Dr`238C=G{iWRyOc*&UTIIGaT=fFxJ z<~R5Ybut#VbC9~tG7I&^_LoVAWNHkA^?vo0L7OR=8C=laTLZr-=mqM`J*jpw!R<;G zIIwnI7Pe_AjA9Oa(tTb5Ni+FiKM|3^@*8z|3{wPk1f(toa=9T;Q%~$TmE~^n8~1Ui zL6RtTpZlHlMxM^MKnAZ~*2IF0kcf3J z@h9t(Cj=o01GV%8+bBK0@lF8|u&O^ORH?3CSGnHuQW*sxa=Kv-l^MgQ{BiYGogF*> zK}jm@3n2G`j9f^H?IPENT=*bATXyV*>c(|r)f)n_zc854J-ohIkJy8ptk}0EQ#ZWe z`s=QL!3~=U7vRt~d%ru^HT4cJORWrVZ#%rx^544T*f)7WzTksG4kQ#X@3fwVT@BDW z13Y!Ng^k!|WDhuF!cavoJiffxOpp}mQ_3ck!YpPorqLuIM`jrbG5xQMoD}Q%Uw6{} zd((Ape6-q6CPB7Q|N6sZ{AI8B$p>b~fASSCTlXF9XnZKC{KRKwD?f3*>nYz){IdII zD=*vVefkQX9_)MilRW*Y-lw0M&3S^W<^KC{;_LV)cO;$tUr#pnpXKLQk~7KJ(Zj5) z6SI%-_cub_7vS`sIQV`e@h8dH{-c{GDu>C`o;@*3zUASK6P5j#?Cvqk=fuH?5EoM% zruyuo$@$r_GQj-C+ZvBO6<_jBMmeDIBA{HP~Q z#OB~(YMhvTjL%`niwD06i_Yrgt&6v2EL^Mqh?<9qJ03o||0skzhY2p9IQ%sy<{Ez+ zslO7vZzdbF_DXC#4H~2Z2QER zJ{&(f%k#?N4_SYS^(+a4;>$l`ObbIDEDh*(l0An{oH%OjIC_|uCl4oyx^rqjq>cYL z|1vtMe8<;aZ|=D3`0Vl3TQ_HS^Y85J;$5q&xAU2s23U-AVX}Mngmvux{YOuS5v>l70tb(ZwXN z>!HTO)phc#cL_`~hf*RiILfpTU6X+M!o4U*HH{|`@UF$R*{Q|VRq8%1)7259?i8;HMD%WFM%?ZtIz&lH?%d4xe}=IX64O zM7itS>=kOktc3SX**rdW*X>ygc4_7u*1PLACyyQ`TTdOR5mCn={tkWKE&d1!!nl869cNW)I zE0N4vsr+v}PxRsF;d9CEgKqjbfd}+Ai*)uxEHQuDyF>LbtCBbjEKkg?2^0^0BRMmB z&F!l!%)5?jh9E4f(=E`|w?wal3i2XP3f+Aft>0P<^(-^ z_$YJxF!RDDPc{?WTxPUgZ)Y>XbtH;~36Sv=`KgL#X zkAwsb5Ms~liNhenVNbO)+u46b=vJZje!~wF#c@1w^bW5uI#DVEarLg-H)nU=x_bNK@x|L0!yM-p9JCky(ZQp_au$;a+FuoBxpi3u zL^foPTX!O~t}=`MLzd2ov~ALl_5>HuK4rAJCO$VY2=LP}@~anwI%q>rUmOG&PU!vh z6V|B3yG(VqXDhe1S0`>izIuEUWmh>)d)-IiX{`M3AU5|k3en5`UrsRCfCenn!$<#T z(rYE~A^rMQRhjMobSI;OrZ{nwpv8V*^YeZ0kE0i*@E%Sk_e+g^KB)|}PAY>fnE_VM zU<*kW)xn>_qWYo4+Gzg0XP&hG-XN=d)Zbrl(*IW(t5hnxx65`PY|nx1Ij}tk zw&%e19N3-%+jF3Q4xH?4|F_)(+dZ(|1KT~Y-2>Y_u-yaOJ+R#a+dZ(|1KT~Y-2>Y_ zu-yaOJ+R#a+dZ(|1KT~Y-2>m5Jz&`Y`-%R)obta>o=bTu<@+etP_7!WJcs(%Ql8<9 z{{CTK{t-V_{&&hNDL+LyM46==ru;NT^+)9y*N^%C5VU@j@)FA5q%2ZyqP&*!tCZJM z-au(k!e`g% zps2r9UP1W>lo?+%9{(prW3iR|)&DP~h`;1GM){`{jrGq^>Xe_QXioeB0 zng?@~U#9#s|NK||-&@IFw8a1CD8iV3O=(hYq`cn$)cV)&Z>RhgWh?pr5cCqt-=X|% z%KIq4M|m6Nt(0ZTTPTw0J(S<3Y$g9^Ku>s9qx=X(82|Sv!lR#{9H9JN%6^KT>G!SV zul83dT6-$5pa}P+XT(oGCC86b^w~kmR`S_y`RlowGXgRoARC%n@*OjE*~_-TF@R%~Vei?`@&Ua9}zOwk(CIy^~f zP=3w-{J;2lGi59JtNm*GK8p13?@&HSc|Ya1DJvAMMe+U*l=o6{`Jb%bTpe3Ja=tn> zv%If*WO-k^IyJvst?pZ%+2prH`|VtHY;pcvweqS{_f_hrpH+Fz9aX)z_N;bw<9o>3 zG#c|8GrOxIQe9r$w{O0)+^LQmm9hE7c6E;)R_BlG+jnGnX02NJ7iaFPycSZ={^LGU z>&u?bzQyI``Kcp88lzL0X)ljekMPgp%$e%gtNvvDzOnz$Wcp|ip_A3IBg+p~cfIiV zd+zwNJKpn)e|_y)6F>OuzxKR8>aRDycw^7Q#p>kZ46UGR`ai17Z!TAkyrJinll|^iwrRNRmL=*Y}KNx?~KN$A;gKo@!l`;RJt}(Yy zAIh6teEL33(1)t4)v*`-$tgzruS4Q_ALD~`28K$jRX}g%^VQ009=osdi&Xn-dDWJ! z+Iy(>9!H8^VM;;iv4;%Q{CZKF)JtjXy5YUrk3^TGFi`8S$Lb(9s3Y% ze(`in&OVsZ2e!~BjVuTC1!NJMCERChR%)Di~F(B$F~ z?UwO;br1bW2WAcLlJs14oUU9ipHK89y$B-uzT8lUZ8CP9>exP}5FMI*P8X~d;-sIY z;AE#dwa8fd;lGqorE7VxZ+=;mYWYfGWz|aFk z_!!Y`%qpc&3f+@cAfOOOtFprs84_C)#mLK*n z6{D%WHh*3(+iU!znGRNz;OjlriRJm_eVf&Z88GWp;jI$5)mt;mM|f-gh>V3X0WH{C zo!Ga$&oH=M-K{l9kxk&%-DY+7qJc4MWh;=`q!9Z_apmU^rHH%_rdpi_&JqK7nOO$2 z5NNY{bt*>s!i7TkJs3(eutys#0$=BX2?pwhr^Bx=^)On~eHg?{{0VPnIVa zUH6@=K5FCj%>uvSu1NPiBHj1pYURke_IaqH6~4<{Hg;tPeYj&-M<61Qgn_f*`=_Z~Vhf+t$F^zOx+@h3g z*6u#GXoyVR`FXT4gezsENgGoY$Ghps$)@nMvS$NWr;b;sjmuXMlLA-oid35^mCWaQ zss*FOw#Uip8P<07nxNiniCa&X#juQZmp*fAwt{^t4{SnIvNfB=$m03r-nh&(pzodX zn3rjjZAUGHC9OM#QLqf|s4QZ!=E*FYof+QvTA_}5TXhe{*v!lk z@Qb;!UL{H)MWu=LwE~@ViyxytC>u}enfBiOja>s=_L(3zXZ zB@wZAS1*hFE1>>d)zp-Wf9-XKru0ozt4xEuTP;B=?2xB0zr2=)a59jw#)c}z`oXB- z4p<~j)cQ1n>$%P9PAQ!-_z&bPyl(By=v7_hE6_9GDi4BnQN&m{moFg{EgVo1{|XdM zfbm65k$}8CT}Z!BiD+6e9Cs1KHo%LYxpdy%LkYldaD7LyEIQ;_7YMmhd*Ycdnnw5&)mVMuRML_7x&)zO#IdZAQS$txCdp z0?=Z6{Wg!bKmZLeWwe~duCS%0R*0*K>XEVKeH#&$81xmxuaS2!)2?o^!EyvV*D|&R z9nqezfNcRw_wA%zrC8iWo6(Ry>k2{jlD9_8uP^VUBTH@WUh3=BOEVL?Ncz)5*wy{S zQzKbI=lA-|=`yhHCw*yV2t#|LdP!zNcb31`b};;$VVgpMn<0R^my6qQOXEK5U|=rq z(7f+m1V=WPCzzMpdly}Mpj#3>dakIH!MIg=Ab-c#KF{6pwND?__WYxHC{C5P3dI+J z4N!aoT;&IO2uGH`nUCc5mduD5d_BWd_aaziFXjNbe+?ualW}K~5m*{*1XH=yhv2)F zq+s)O-y-|D^FFxb5Mus_-*qdpgNE7CZNOGwEPiPcoH?ZQ=nW z8SpR~B++#Ceea+FFWCkjOqTX%^YdzEWIA235Hwp$p%l6&8DKi=^Cf%1q2@f}7lpTZ zd?R{irn3*flijVpkLH)+N8p#psUu)^aq#pEKJPB&lA zKzGxySAeK+1h({shF-r}RMf7rt6U{N0vhvkNNa@(2U^UG(d6a0%K+i@1@k=&@eCyi`5qyD`a=T#he?8&sTwkMkAaZ}K#U1Ku}AEA0!T0*P^j*^#Dz8rEOTqd z<*<+;464V&Y$OQXKnM({3ny`Y=II>Ro^_kP3_zJK_;6L^>D6BH(hDd68)4F1HnbJI z%tne)Hw#^TRJ=c&iZApgd>o7K6$Spj94OkM90%Z-cr-n9*0PJVGg_`IJ`4$r3>24b z0yB(?pRorS^oDoRG{E$Z+M;fQ#rz^Ygg1%`=7T)%(pmuvHbj`&XrT^^!a^Nx2;l4I zl3F1S2rxlhnsHVV1qMk`WF;bRF%?Y~t)*qAuJz5>A|1WQ4+M5OF4~OZIpkK+ud;n@j^oj8zae`4|>}jS2Vz7A5o6-=9EVA*Y&LSK$oVEcV z3zLoz=ELl$&;0oO!e;xsy>gvLot}bJd+elZbr2>Hpc0l!!Uz z`yLj>T>n56FFlglLdqMEBEM4F4};wT#C~_O*f06)1?Zw4&ZsgB5Yv_lFX6)s5kyK` zJ+hkW>2tV~Nv!Uc$1+ri$#`Fo{u;y^9Y{{9W*cd~6K$g?6>h8RJc4@n-*mI~7U-c?O~imSg>5GYuElf_r&Ru2s4)HS%PA>j_YgmRe-nPr12C49v$z zQIwd?I-!Hnm=Q0?TMFbyRG4OZ_HoJAn;#!hZw_ihz77@j;dLmW;d_WfN2W(F6OJn0 zqf(aaWIZ;b+T`$256h>-EDPguEZ&cswlYqC$`?#OI$!BKcYsnL#-BA{40fY&KA0X zUmQuDf&TO46SHuQYOX6Ns>7=>QKg%m2D3vBE*W6oB6cCF%*R>?uh_PW`&pi2Wur5q zdLz_`!-vVv^4+XH-RUUH7TC8)`ann`(C$xX`Fq>}#-Y8$FOIDITy)YDBjWgQuL5a{ z^Bg9g*MSi{7qAL(hw>Jk2t%vIwdyVfFwLY$`AcOx{yM&>yefuoNSD#`A6`+O)#(rO zhI{xc{27i=N`}g?p5qrs)tnq9r3-9AL;-ip`S4i{Q9lghL7D_31V$x*oi)Yp3+|(h z0pUhPdn=3aL@0M91OL$!tK&HH6r9-}Ptwc60eU;jsT0DT<)@-~@#jbJEKRQA6)*En zo+Sa+cJ z7CCZniM|DHq?Q4_EF;cQAphbB$4J>V_)?)lQh zDNy^(l&DmxkOdiC3W?=XFUlsMwP^+(u)9;%fdYrN6PKOsP{Kxmb80f>r1SYCz9^dy zaoFPv;t;D#Q?20|3lu(51Q!9Mku8o)9aK%B0~-cZ!O;OpfT>U+2T&)gBZ=UpxTdmG z%%cyQIX%v5B0IUHr6=v^Y3U^gL8`pu!Bi~&3&+d+pwVDt!VG3^D8ztz=t)0}B%&tm zrWXHFpXph!rD^k?D&h30-gD#N(`@3&Bt_gM5l5AoGA2+D1wW{MDj|d$T56FTI5^=q z>K-it-J#&)Dc_&vC|bbRQfO06?AM=@{23PScd0e*0vlUTDKYCvY4gg=mEG#x8a~Xv zsdd@F6vya9Pzq+K=L$|6E3uciw_Gn)%Fsnu z^d}2dywW6h%%d%4NXuC*T(obk?)EyJ+Q0(3c%Hr2{1ES3GZnt3+RLh)tFo;&DQuYN zs1E4^cGJ@BOMf_MLY|V@s=1fsu%JC-!emZoYD273y+(Q_J#XriWSQ1`D``f`C-Rpy zn8UYI3RVisV-;M?fyliI$0RaMWgAWkD$i7>@c88Q;f`VAI5aC&FV?Vi?OMqYn1_g( z79IZ_CS|3I2+go-0lFj^CM(5LaUL_K8W`*R>#SEWriy{Lo5uX2#VNCMmcw286~@~I zJ{XA^ZXJ;y>-W4tx*=}-g39)mSQcUQzD)#rIZw*q%U*jRKh@hl&rS8_)88_?|4crJ zQRnS|*pvgYeP@bL%<3weNuG&CV^lo{!K|`5A+|zUb5?mUfQ8DN9BuH1f{V9B&V;*D zX~^R@Z+GDNlz?HGIUlEaU!I!rg-GVx9U<8|L0Rwz^F?`ELPpwG9{Msu9?G=zGcwq3 z?tJ4=A*|3{0n5x@9(Mvk$!wLO0#O;E%LIy?hKa>#-!A6O@|G_K&%|xtWsA%uAfhk@j&Z!tayV1e6NSY`tDNPq{S7nn3)0+-Ko=6;FF(P# zSN2{mDBdR+%RrGeik~4<;YvBW=}DImPQk0v76##!a01*~ISxL_?6P-8f>Gmd7aloN zFcZLTaY#={q+t}>v%qzVQFdnt&Fn%3X%F4AH$3#-$NeA?^r{^mbIpiM4{aD0(>d!t zn>s{J%!(QZuI1?wXv%^t9;|XLPa8N7*WoR2T5vDRGd*`icbof{?o)&Za^@XhY+Qeb z<1kwkVa8;~zCBwV!|7vt#%)dnrm`ayKN)kJ=`0ewhRbNnS)(s0%PUbY&~2d7e4fPTf?}@#QTEP^xciaue5KLSXl}>He=16L)ONg+201aEK;iOO`g!USyEQ`%gIu|*e z&}}8=S_v0e<0B}y|EK`bC$0PTt(IhcGgefeU-Z?x&I|F`A7Tty6zE891$Te%y^dY) z`%<9gR`YjaozGP#UbO#}KeaZy>u2A5+s8lk@eiJSY1duI*6;_bW7i)zJv(;t&h`7o z@0`DW&{e%-*T4MqY~|)N_l-5LzoVzK-fjx<>r#b~shs4-==t6{zvp%(u<4lhUzh#< zA~^o+om}pF=SzDpwf((xBODz$s7; z(SJcQ>zC!FRh%k07i`luLArI|_7>c!&YyzC$6@i`2C`^ZuVw*t1uyn-@CP13@^rQD z&7vErIs@p5YU;MEQ?r#%!QoT=9QLHz$>1uzjF=_>urzE%2rn(|7V zaET<6QAdC_Fq#D38q93IJBKBTJ`>5lo?g$zh_{IPSvPVS=={u^Z~t$f`fne6eIMw& z)t}iif3_D`Z>e%#)G|?ad04OZ0rV|mwT#u}fW6&UK}4Udn10c(W+yKb?D|69_6r@` za-IywM8C$gQSHCTk3&=coic#UZz0$>Kl4cXQhprgomABE|K+%LuFs;{iXgJ*yHl4@ z0aNT^YPOFZff>0YV6j=^X^^obCT&u?dH6jTc6J$+?YaiU=1Ol-1r$edELyRnfXzwY z0eKERa1nQ!p=UH5j11u}{JW5;gg8dfIR*gFzU3*|tjZ(1>O=bknRHckdr`U0B;@q1FlW-)?*#!BpOk1ARLNx$iYS zZ#(awD$SNLvn#JhNTy&Otxb8#fg52Q4)@HgQ2iJ8(sjFu1&u}9O$kdx*kno znVh3!xZ0X9<@U6mT-9t{*cNRFHQ{6E9HjXt?TeP+>cmQQqs5WatK8*&fD5VHZC%64 zuq&J_q)7K|d6Fw4ZR^!wm?WJV<&=$(vkE!clKH` ztr)^ma($v*n4F^^S{bCZa#lyTXju@}d-y(PHGC3I5OlM;SB9`1{#P3E#JOxchJWqrkS2|rUHTh^z#PL62+RBaD;pKl zqhN%)LfBB>u`eju1o>hwuR{ zSEJ19AYM{@L%kPKo*lkR@JsDokxzRO@mw9GP&~{fHreJ+P?TAws}r2ior$(V*0sxk z%_J+$ehSl4fddY7b;vkkra4!tS1@Ymn--Aj3PjHKhUgXRGnefegbMwoBxc%~$yAz4 zmC2;RJg40;7h-hXW&ftfRiI8KHijgZcjw(ViplFYgVble2EnG(TQ*C2B`Z$P3Sz~# z8fcD~CwrA3BHMDZX<Q*FdXP}zB7?!%!G5( z%q;z3zxgpp>-LQ%6&1%0m}GaaYMHLxDjzo*mzkLr^`kN@^gU-TDsTDx)bRSEh$J(l{5G=_Dr0=R=Z{nLjif62R`RD(^lh)-M~S~hb(r7v?V{IG z^i8WOf6W)s{YMmitE;|kSKn-_Z(I%EzWOSDuT%8?Fnsdr#QdKPt-nF}QOb)cH&Nb5 z`Dec9o1XPetN)6k=PG}l^7N?W@yUDM%l~E2(zp5Qn^yJhy5c!Uc@0J1va4^~eJv$? z^Ym7>|GCh8A?0uSpXzUwX*ZBVkMRQGMhN5r!RbS|vfAzQ8u09Ckzg6>J-?aS;l%JuzilT2i);w2x z^?UfK`S6b^TiJfCKlQC-(6`xZj%luI9%|le?&+ES*0&Gqn}@fOzt+6ksP;<+wegoJ znghS$%Rl!&C5N7ECI9C@PkbeV##U`?QeIEdS`R;O@;`rrpTAA{e<)kYU*oTD+SWIn>l?K7&Enykr~e+m|6R%f%6^J4N@Xkg ztNmJcl0ijSqj@Mkfxmv23c49#8vD@y z8h^D*cqjZ5{;RJwAEb*l7Q*7K#(%XrjPDKn{w9j%{z;1Z`qwB8iZE%J@)pWgj=$Rf zHz{vK-;K0Jl*;?h-&fH&l9i*Q7$9<$Kht97|EI_DTs~l>t zR1WP}^74#912I>SZ>ha9wshc3ZR{8BT)%(pPLt}RJ)}<7#+DWytnK>IfA%{c|IEjK z=QY=#ea`p~KkxZ})L(7o*o{38-&EUi2w@K`jjbH$|7`34{ORWdZ|HgLB!72zP3e=W zs}a5RZTaMLwOu#-%J0&TzkA|G2K1xJ{6PM2*yj(rasQWn<8GfmlsCcn^!+wRAF8d^ z#%{Rt6a#)eG@k#lxUbV%tF_7skups9Xr4RJfzSoh}2|ds*Qt z;J{{WVuf|387ZxLs9oE6Y{|`AR-CYEVL^6)YG~E52nD{F2lm3_LSmBvsA$(Fk1g5H zX9oZVE>>8LO8|!%H47j#3zucuEyV8d!UZF?6N1LqCYO#O#JQSTOvhH}iaoxua9ued z<44^Qb;7v|gZ6uCmmXRHXaqI_;*`ur?Go2SG4!aP!*4|VcPwkza%f5G>InN|wt`)$ zhnTI6^@S^nduw}XE+bmg)KLRt9T78kZFYV9J!#*^wMW+|_i81eY*!ZeS2i_tGhMP# z+nx0|L)=;F2%9%+yO{tIq`Nxo)iE{^hEY9%`NGOVyLN>*W%@=Mpqeqa`R#0x0|$=L zX5${!KeTdz`Y8y(uzDeaUech%J+NdeebX%er+@-phEVs`CK{y(-8{LlE9Y0VZ8<>R&Mitk!CmrI2OVnD4;cUAwYN%L)3u zPD{B(Pd4O$WQ{~&tU1ICJzM7DIDVOm^ZcaDy7{>${rmuT`9tz49ZyVxQZLAJjg(u| zCf}#glYXv1a;D%MUpYKwj?&$|Y7LoF#pHj9p7itWc&}==c~y?_`BGmhur-DDY)ysO zrIP<7O4&2%m)>!0*PfnfLC3f@gqsyun;L^=xSodT9JypL(Ap(c#c3XmT#U>F?t)Xew8*~29hGWClFqznVkF*(rClZyb^ zw-j>apzDbl=3TAG05cQeGNj!jZ-E#;@T=~X6FCH+W@Hh@EfEn7^RI%=cfcx|lQtyV zP#N}Jw$!D#*id=0Myz*X=`RaV@_jgco9yZw`!c3@+tvSaAxgflwv!0bfkT)AU-u?_ z`d+@#{yy7Fz_J9?9uZ2e1z!2V>)X0;()9n7*0}8jC}cI|LjRfR9<2Fplb{SdZ>wDv z;i9uMjuAE3n_Aj#7a%g!5AF3^2iaoOS}eoV+dN`kYC#TG?jgD{3q4^cgI$}oNl{&@ zEcxxh03U@Adz*t;Tdy{vhk!;cUNgl~szmfW)s=)R@wFeR$e#h z35kA=&MP;ed+4rr?;-S2_P~5*2qU?NvP0T9_>&18_43N;QZu-RFd}Cbt@?Sl17r1p z%@FN0_!+{AIW`nL_w&eXSMAVbMz5RgGH+xdEVNf96}j2AYqvc9^ITcJC17oJ3ie{{ z^W42y`;_R#(n4+ohAKA$)*IS_Ct$g-0f2UhIPgwE*u~x=>}-8*OZ|E zBFSJg(Q*ST)Nb`+HNL1a2yAX1V#{{w(1QO{`2|yl^kE?|8_^zMCO)e)30q$)3wyPL zm;I@21O6(+U?b}6+MOPQ>C8Ra`!%XdOSMi7*Vt2CVr8-O!RB(Vb!!yO;&jmK$H!tR zz;C;DiR%VuRPNLtg%)l`&mz=PwFn@SOmUZ(Ab&ABOK9y9tj$R7kwS1P)J%JIWEV}d ze4$xt>t-~AUI2rZz4h(DH%Z|A@@{li^m@Agw=Vk*WTP0TP) z+3X_4K-07oLm_*TCel-%FW#jM6<3Ze#@;lKZ^9y4I5ep_d|<$5Oy-W3`Wt&*>v6)3 zzMiF^_Z|D>;sb2%#w~sJ5gDk&vfW0fr9#+Z@$1483;eb8 zSiaS4>k#G0vAkGB;G!+WtQBE- z@=R;VAbp2^TUo%AVxMWVNya_G|uiX-;Z_rfbGZ(zN0=q#O1tk~ep-Y7$U$AQirz(KpbqU-c4QEx(v z80ILyvu>+UmU5vM_=ty>duNG|)H8Rybaq&SPU>o0^vh zz(OB&s|l~O7nolPCTn8CfIdPd*cQjN0|(NsmfWr_eZ7H^+od%e3ym&3XcNV;0W+%?yRNez}w zD~MItXs9e;xH<5splCa+>+*~sn3QG&S)C_`F4(G8{IAt1_m8GifE$J5#ug4dT9k9i zFyHSog<_m9*Cy+=U8yn=gM8E9$PcYX*nwSH`l<-#>W=$Co(s?&#IBS9YDlLf&v8~i z3x-^cbdR<;GHzXUL24yttrXCS1BM(|OPFk%t4!nEZ#r#MjkBhpUD|MgFK{9BLPg0< zaoc=Ik`r*ZRy##8sxtDdgZY4;i7Y;W2HihQ#3wl@T;fUOw8$Oc_)ub@KL(BGx18G{`D~Hl@D8rfTC=uvTa|tQX2cQi1X4s&2jZ zw4mvv3CV_axkr)!TX1CwnXX`>4;QuyatyBm8Es)*g;}k5z)qKS&h4y}>AJg9we z&QXuX=>pUvtvj}%RJFkG%C6QGM)e||BPhkb{vc1sR(VlR4muZG-Tj8*H#%Nb6lVO=Xv%Iq#2f$0qU#6NOB};5 zU6`h0PtgL7a9KHaw$L{;4kKte9G9=y>NT>t9^#iq)ouuC$qk$Sw1!IsI7Y%3OURvR z*{od#R$;>`_^6+l)MZh~FO43BB>JUDo;2(=hR^=Ypv9M1&ZOrotn5{65fOCUaCraG zNi%}~xaIP%!?tt$sokgit{Xv9Pvx@l)D9>UqbGJWEjq?H2$M0Q46_hk16vhT@MgW z^jW_e2-gn^l^5&OFcKCM7&>O^;=cHlnRiKwoy}1G(OQUR!w{aP^~2~Yc7t%MkFWN4 znrWB#B#ONjX2#_tYho1F(*zqu0lO%yJMWTuo~bm36$ch{^v#_BS3d=~WI8qd0JHiPl}~Pl>blEo*|@;gv5Is#K1bVEjh8ad@+G znb}?bngH0|&efdZ?a@=?2t8@nDLVLR>T#TudVlIqE+R;g){q`qTG`#DQinQ!&+G|u z67Fi(t}jTf^IB4-aL|-!dP(}UC{52flP<5BlLZ+)OfY|dRQh&rx56FfIKRotepF6! zp4+WMh1xHIcm~T0=rT)8=K!%Nxno?rVLPxWFOJ_B_>vq!h>e%PWi?V~pG-gJ>)|jp z`*QkB2B{JE3n~?sUKoChQmUo;5GG9tv|MY&mia)cn4}1a0=^eIvgtr7ZkgU9;FI-I zX?zx7EQn<>@3Q?z$EWM{NSbpixbwFEUbbodTA0~(d>9oLJLF?6vN`N={Z zt_(>_XIF;g`4Y8#b8U}&G-a~mEKr>U$CXD4_C;@w6!lt-gr7sIo~xNdbrL`9e4MtE zI<|co^3?sQ(=w+t5ZWV*MrDXzZLeH6ioeXpC#M(2SV4xHYflN9%}BASSF25#hiSJ^ zIfYcFk3u)gHqaZ|mz+{2q2&*vO5EAYQdQy_w(f|iInIcQPV;aArBn?BDyUTL+f^vG zZ)cf)l4O{qlrAE&$Hv?i99r5iyYxmb>s-AEjG9%jvZT{vr21!f&kS)JS09-LQuaAI zWzeSV5(B#J7~x3UT?D1wf9YE}PfF0s-g@A1T)6dHnj5F{Aq)oZ$RNz>uIBGMTkROb zAf21nVU?YuVGC4pWG;GqVq+Tz^%s`7bmkaFQSKH9qwwi2fYT*e7*R^S=W+^^ z^&>@Ao4wwJczXZQ+HSvr5eVe$(%b7@82DLvzpPrvH^-KXUc1Dhp%BLf)!i1}mHu=K z{QWIj(9{lvvX!;>po28R&vE>ZiEy{pDERqlZ+nva>kKyu@O`qGFb5Z+lQ1cm;)>eN z#IE!S)>?>@?8RoYtB2e=_P67eVeY4uZk=JS>jf8LmvNgN*RXJhT-o)oA>l$JZX0(T z^q>>E?$#;=>M(5pYBR_zeq!yHxtN}^F_&AZ+hH3beITymaHZE}pbm}fuIIUv(kxv? zZNwEo?dKYH9z0L42*!*rFOpGwV3D2%?NY&Vsy5Qb`h0vQ zBJqQ~B(`3r*}j1sgY+yusV3pP4Cj3kw+1(Kd8*K8eYi|( zG==sb6`uN}=I7Ew#XI|q6O~tvxym=83S*=8LxiFU+u$=D$g5zc8Yhdmst|6y1ctMd zzY{g<=V}xCU-MflYwz0i+yD8l`#yW$fBkpUUAGd`u_tQ}*2Z7_%kMn%uCd$iTfcw& zzFS`0byc!ed8jt_;u}xDtMZ{U_m6$x#dq`!z}uw-|4It*m#K3*mp8wyx5@{C0wfBk zx~sLZ{bKps_i@SYeJ}65xb_3t?gFXS?gcK{eOKi_a~JJOe{HAVbUuTdntk=(qWWD_ z|F3z~Ik~J5ncpVY0rZe+t@O-EQ*Tr0=jnz3iy$@pSKx6UJpOwgkE^A+(trhXkM+(f zyG(GJ>9D<7jZ|>~VEzK$Q}3#L79OAN=YdraG?M|AmaIyeI4uo@9Zb9H#p17yVXhKx?um1@DH3*@_LYop*0~E4T;r7ygu` zDhV`LiyZQSAoS2N0X@(Z`H`GkBa>g=7GPjl%x_a5<`Rg+ip{@(`syho^=f^l^w4IJW-38QM1^j4sxeo4Cu!(UxhmdOL1ch#PfnbB@@&vaE7 zH=Dlg+SNktQS9h)lzdX+E%Ss&ZUMw)a*lnD4vwX_5 zPEpn?6AsvP$L7uA{g%HPgnLW;<6*K}A@hY4GrQ?LmOd{_U^OCO09R0X`M)7ZD9upy z?}e08mqnMldNLO-34Wrpn+&6 z<6+2Mq!d-;`STRP)l?S?3UF-)=(5{XWQl`MX-LRA=kevJBEbJlVLuXp3scP0m35oO zOLUMCq|HJ@*$aZdI7QZFW)791iU_M-Rb=!QT8l~WkE(@+x*X@iCb)~rQZefZGGi5>`Wm%^W`3(odQL!z~cM0!uaLZeK3S1Br z#=yl3vAfj?ZbYgOJhX6=yWxYVz5*K-lgK^3L9VIZ!LoD)xVtfzMaF3{R+;u$Kw9IL zhNW`c8EYtaJO-QBxh{&i$RrmTV9bvDXP%CWLlC+!)k?>xR=f6su&IK|?LFbats>;v ztt{DIiwjGmtM{5gkY=iSj%Ci07unP%|9D83QZ2?@jI+V~zwi zEJO1w>@E=4l;(jU>bIBjuZ;1c4K)dwmu?O}fJ<^SW*(3i35%YyZ#%nOuXqP&J8Il`CK zN*2knmF?G;C18T^AP2qP>xWxlK&4uPrP43(HGY0OK`)NgsU&~yPjzt{xn5$Tt~Tv@_m%Olwrm^ zt`m>H=Ks%A)HbzK?b8=#>zRtayt?ko96!}RTiJf`S08I#Y1}o(^rgK2(ihFed5XRy z`Cn7?*;exZVd%wQ68_8lt@4W$&HodW9b%6`fL%F8HvuHUzkzuGVU*Hfw#;f;!T2RS5*`X_w0mHeLzUA1i=MHqOJawA3a zUTff2DX*ny{=bRxM#}Rk-%q)g@=VHABNoa3gOqD2q5bLuwg2ZSnvYuZT9e_Yu;J(Y zGvTDhP4B8aUjAxNjiNCK_@};p1w}eQb3$VvoX{HC%KjJMms3Pv^Zz$}xrv`D8V{A% zQQkp$8)Yl`tN&h1c^Tyf%D<=l0p(qkcT>bq>rit22g>hKa`~T3-j<9tn(N7q)?6~( znrkPO`i@pTNt%t#WUAhp)^F#MvANb-Qu)PGtCgdtudCGVNKPg zjaI9fNi+_vcCw?{YSrt_cB|4jlZ?OQ7eBeaI(DxK_R$`}-jGzL$6ECVlU+Zy@CToG z;1j?9+83=|H&MO5cEca_*Q}4Vrf=+d{HCNc*O{jImF64zJ{of}ob35Pe|Ps!>65Cf z5xw@Jr)ui&e$5tz^)vV2_)lsDnQt9`pbp60e z=aR}?yEWFB-n3sPn@KX=Xt$=C)5$b*vD2Dhowyq9WM{KpXMQGi-e}f&^&V({0@~Gq zwAYiVxz^ltz1eCfS2tRXdYvUS-DI`2#HQKkOn0Ixmo^)%Ijt|2(wwM20QCn>T{n>S z`DC0my%`qwnRG?B{RdN8uT8BfrueBcQ6b0r+e|vmiG*Le$oUUC$(WF10^#dt%DOes z+tFx>o}_IwH(QeiI*4dA^&uE^KA8XtfR2*!3^cur8_A`JGCeK&A`_@~nkMNvF%iCH zlj%nX_T+jp7Iox?x(j@qb3`|@4`Bhi6`*C9!W;En(@8w=Oo0YcHW=2H$TnKLnFCoB z>sNu1BrZTuW8e|g=3tn$6Z9i@vbzPwcxyFX+z_$Ve^1i1gf?`!GS_NwMtze z_+9_x34zYHXd-?qc_>d+GYa=61pLTK?Otl<6A`9MuHt@IEPOdO9v}A!$1PWr<^T!Y25@L7KRFhgT zoJLcaC{3UzYi^6KvUaEJ>5sIk0MAsw&`9sN&Iv3Gl`~TGyYaVHGYW>Gxm>C0s|=+O z#P$jrT2Gp&PV4bZ7j$u^mrW<6oULh(OLK^MCwW@4QE!2WFz?bCUEFE+j%K50u)C^X zfQoVa_WazhYNs@nYiT6LoUM8cu|~T!P7T)sTcg?D zD=b+}hEQ+5X0MJL?QxG=@FdcaPl&cVnLMiTdbB{>-5qPYN2p!@3LfFPRt1f83fN@Q zx8}YXn}2=2gpmlE&-9%ZUj55SyFS)vwd<8>BL!+1seJSFZdMxNdR6GOpjnF6if7nI~#sR($<8JVP=sTSR3ix~td_fI6T(}K_P zTF@J;=9gfc!WuOZyq8onnguN0AjKth$!XpU%GC2N^WsSgb6lIc zpY-yRPM31TgRl|M1Ss{6#I=*)J_a4v-KO$Zc9JV2J?BPpV+jArGtQJ7GKZ1#W7++r zx4C#~QgFM?+j4x*>rrk*3Lq6zskO_!TFYkXl@^KWp1J1y^s~Jt(rtd`mPfEs=BCU< zlm+X&EIdX-VGpmcS>H)+*)#pX1h}Mrnxvnfonus(>z-$4pZ6gMR_}%HB&)jvkjdWYiHpJfzFeOg0va^pU35O}SZMB%&PmbOSfF*gWnddue3qHX9qs?#xPNme}3|6H?&aAo$s+ zCqrR%4;#0QmWFlC$L6qHT0iLx)F;_n+lK9n0Nc-%O+AMbK~%=xlY3QXFN267uy3z6(^qrQJG^LS5vHM&FE{i; z^;R!<6Me;{6gCt6*~R`t`12CQC9x7q11m-~jg^QF+GLNtsTIb;+dB=S8kdkv!C%F& zY(&lQHCR^Xs2BNH(Q!qLJ93~MQT{}==&u6%*Hg^E*bS4&$)tjuZ@T_O5$LZ%2+j!7 zSl~;_7a2e^NXoa5Nb;x2k3KFAY-B_Ou4_67B6H-_gep5H|JOl5k4ac;h`@1t>yn+|LLrk+oFoOUCxXKBXKckGiV2zGP#f9bf7C?ZY} z+QEcWy|=a8@)jDqd;n*lGN}o_DIhV~oO4Tu`TkhGVQnn5W@QG-Ld0a-@D^N#*v|4M z(Lph~$vG@Y80`TCd=x|Pi~|CX<%KVdjpFIxQ$HJ)zs-3etNq4bW^J)CDzdWPi%|a~ zSoT`cNZ;24C~5@(U;a0y{Tb-Vo-|ywPfLR9Ui@*^eGU&VzfiC#EJxE2?S`f zXkKQkdoCU9WE_FMmIMtEH1H(mzf@?2L^zbA+jW!+QLH7@S+J16DT}T-C2`4GX*LO$ zv*erS9fz~Y9x&Q^t4wc*1^axUT0P9D9vuP?=Cl$UWK(aro;pkVU=yL>%Y?*N%Qp)= z2QXe7IuPs8C&r*dq9ke`pl>xH&d4_#%qTb(Sn+-oNQ%OEhPa!6+BbmN$0NyVp_^o+>Z@+{auk$oT32!xsz^Oi5=F{*kD`)#S!1@K2go#oDL5|?h6pox-lOTN-cI+d zcd5U%qcc<(D&stY4vYIbG?*FSW}3{Ja@D3OKDugS(JPW?2~5UVeqK|dEmmN0^vXAM zRE4*mJSFHmdR4O+oreb2FvFaDKIFM#gz#1-$B?R!&i0Csa4w3|B`=u((%Z@-86olo zdkf=iYe+kUV%;%}&U}J2q>_t(>w@egB))S*Rf*kcwqc`X$xBARI81iu1*y!zeDXEt zoug{bLCwh5q9Q+<7ES46d`e@O7dLF;lMM_UM^c?^>xZF;+W z*L_VaaM;KZ@w|rDj?O2k<6(4hb6MDO;fnK}#BUUh7)`&paehISMFf2VVK}rR95iyC zTWP4!vl~qX#&adrgPtR;FLw9Toug{Mt}cxdc*Fc0D$M8^52@~gBMVr?`Yx=(Z6EMr z1vH-!4fmVGaLDq(zb^_lera?C=fjR)x8*xc@T1r#{L%#~xDa*xx=h^ZvxSb~msoHk zIEH6Ml00LU@tH#JP;^JpYetxj_6+Y`?f|J?tqEWlo6>?YN)N6OGaNd30F7s|jHvMx zlLS~&?Q^wHFd)E+*OulTJUtw09Nu@7G^1)m7rm4N5fnc9$^{E#c`GvwzsAd3?m~JI zhF6knF1U$HkqUrqZ-Mr}pP6R*WJpg^B8;Lp&njl=ePpwE0)GN;A=SY|VA&3l*x+Zy z(2Dd7$8zvk`&w^%gY5O;LNf-T4~B9s)dQnwR*8VaoT}8&0St=ymUGc8D0ef(eN;uO z@g~H2DIR8zn`twFzF>&#i058yf%?pf(cDfi*N}Rc8SmWAdVFRk^bF5H3%Q~dWf^(o z*!Dx8Sz-FS|1Qq9;}fE#|5RY~UkX(;8w*k59Bzzu_uM?Vr$qOz4N9Oh3NEkWYs|dH z7YkJ@$f#WkmrI8$tHU^i!|GpS>DimPp;iCp=(%(*yM%2RHb1gFWzNa?(==X)ooj6KFY5QFi{J#`Q)9L{`78&DO#P_x2+~+T#!&Arr0MscIdXx^xWc@7E<)e zSveHtmkyXfHa7>P07?inNt6Ky(@YwaMw*ii?nd(P$u3^h%L#so%&*O9JJ2bmQG9Jd z7|ns1gQ-Mm;$W9JvNFBrYC*?HC7Zg6g_3%nM30wWdJrVa$v8}9^1qx;hl{pKBHQIO zPRtVAcvI4JjQS#$NOdh_TY6tYCXs2}DQrQJvq5l~hxux;(Bqo zJyipVQL-bk^VxkxTPtT$qh%ZJ&Zp*&W~;?!eAfwDHvv;5GYxMWwPq}Bd*k2H-uTHv z6|Wpi%Z-TRO!FFvyy~OTo7FPu?rW3G!O-qX6Oit>(hyQ z1iKMY2@LoQZa@pZs3^D$PenW60wTDtt^P+v7$VmPr|%C+{65moC~2wI_DL7J zjYBI=}87&h>--_qKHc-B<5{OlZtcF4)?#b=#t`mkLXdm4Xsm`>O_)HZDL{VWXm z7qd{)Rhamyk0xTK1CbvxaPVYGs0qHX6P%hRkH{ zWW$X$ExUIl4$c3BV3!nx2+OAvCsb%AHuRHC%0#t%f`DxssE}mi>JJHKnI^d)uv^C+ zBw2`(lnrQkJXAGGY`^w$Ey+$4N&PKwyS*(tXRXb`4MTSA!vQQ&C*%GfC(ZpL;r>$+ z?nh$%+gggbpJ&9J&gEk7Ot+-W0v#`+*IP@zpQmlN^=s^$uG@(%S!@y3A%}8d`16b~ zB$AJ@Zu5DIoGX=!{e94=;ju#C|YZxpvG&QsLrqHwC0W;D!V zI^6mg2ndoi_CY^PRz|X!CU{aP+}18qf_AZYrW}SDsdACIHlRC|zCWk3X*1IN;Fvpz zK3P!l-WwbrCXSJ-7H-WS{>~;vAwA=;9(Hqkv$HdK?YTxxrFni*Fu75%1z7981h1RO zTNE~vfpBL$E}10m;KWXrC=e&s@TslhR$(M-QMqAxLZ!OBqNWtOt;%R70>C;8bt@~k zq`rP#LdDvlFo_bOsktfd53hEjL(GWWwFsM>uc6G(1gD{oE)fAW?XJJ~N3deSdHEVSi^xWL$Yn%AH>wHgDjCC!W0Vl*O;R_`74*jeY06 z&&ZsWY*oGPu7hXGleb2S)4lg|8_wZNTb4u5x_g>$<{_v}EjrBok#J@-x zl1tZxoGZO9pXAd)8Q$&EV#E(n;_I&E)Zd>Un?I!W)5%%{W}NaS{R_$aVvfgsZ*ywD z?2x2Ak+k0>?YB$P@`76*v)xhHY~~%5Ec)G+6tuRC_0qb(!zi!-)kcSy=h&so8( zd%#%@Q-?hyOui&a_1m-!v0fqXcm>$m&|&9KYhDPs`y(ycDGB+if$5Y~?(yL&%H0<8 zaYd&X^Xbhk59i=3iQ81xz&!T55qzw`Z`#G=XObYuau#mQ!O~)cSk?(gkcaayp_Z={e?tq0&Lw`eRmdF+8>>G zc}C)JC5_s6D&S=Eyz|#+SsoeJ;XL5OKJ+M;7vp<|lg3$Qht|%bj_C4>Tp&>{FG=2+ z^Lwn>Bz!xu*Oe10!skRcOMqExsRwLBf7|^g5OfKWI2F|6&a9f$zB0GeFmu?>>QIy8 zv$Lwn*;~psnLvqY(N`>%Vn3{TY1Y{o$`AU2a?-C^9yZ^(UnC@Mp!I9+wt39YtfO1T z(87F(M|psdmu3jx?YEz=U(LFlf6!5|tYsC#UNc#pPgdbU+jv;A`Mn7Sou=z6a+}>~ z7x5b2%to-rGr?_Ri^AL1vW}d`0vD7GTsg7lDCE^zBOkyzv;N`c?qReg))Q8sWFfW~ zaRJVFh>4k_h*u*fb_d0|TczdFF*7mtAR%U$R%@$!^DEK{Mk|J$gVz8aBAPxdDW8Vr|M%om`{Fk@=G7Ar>ns>P%LS}>;0ZQ6U;8E5 zW|k;8C63F7UyTuxu;=#c8^6!$ImQBG67y&MPDR6lsm5w{O)@ys$}zl@P_m^Fue1q- z#cDD*pAZG>SKG{+DUDrS%fPRg8&Fm7Mj&d7qh6uuK^6P=s$##UG4sO~D=p{1A`_fU z_=DhLvQhR!girZ-k-W3I2Y%Cm?{-||hU{9)58K4az%f0{0GRWfwIQ?0q8D2P&G`2? zkq{km^5POQ0;IR%MHy!+pdCVxcf7#TbN*`PI}2AkKbBT! zwelj9-Nnc%7E$w~_Hj9$SRd!X`iACC96FBd4l%2-VBIz~D<{ZbID4^MnzZtm4~)m)uI1Bxv3iJ4qqZIaaAMv|%}OtBjEQmKhM z4Pop*k&@_ITZge@du)zj%haZ$+yf_>tqlHYy;)QAQM}E>5ML&A?a(8e)WogHqcC6N zCsPPTe0iUZCoedx(gCm3+m<5ys=k|-l9Qv@ietH?zA4LTfb6Ok&N&ro{y$X&Q+KSOn>lJ;}mQ zXet-<>Ivf5Cp8lzh#P5w%z4=A1fY0WV70MW2A`M)w@my$^fA9QLzS8qMIlfD?_Ioe z$%Vb9>9G~896hZgvtnX;Ufil0Pp0~fCg!>B&`;la73g2BWu!IhH8E}4 z#Ny`L;w%;)N#I^zz@ee`WLDpU^wiQYVg4(hxE-Ff(4t%qV{R0mqyT|V>uX0_|` zKJ?(HKJ)a~=r{jc*3~sL<9>E6*R#Qs*62gd{IC07{@Fo4^jBBcn%Zk$%VmjvuR87Y zHP3#IHcyeXbm)ZB2Twcc)Yp;g^H;v``P_1pEsqW zefhfzPV=~ut48B(;AZeAa3lB)xEN5a{UTx9X!$KewYP{XE?sp}&qI z4}Eg}eID=RdLGdAZQvZBetZ`QpL_1*_hUgi@1oyIqyFtpLFMiZ)ECbIr+^`#c2IlV z0n`q^1L}vHfbRbV90}AGqC;)*IH0_gXD?8jsJu>S%hM|XB;@bU)!(8?^r{a;a~0@w z)6WIZ0%{BW)>VC?&yMSzUVq)3Iu+5L=7B@WTje|xJPqj6)^7p&+_--K3pgFT9-IaA z`SJZgdYl%O(eB<{wRO5KkB6?6K=nBSG=TV4y!;OEUhp3O_j;}u0`ZZ?XfN2D_Dz>B zew0Rf5fGn_fQ!M$fMngjdT3040_eGD))*Ggig(+!Tha5a(UxkLX9Lwm?Rgov5~x1< zeJN1A)Q+D9dM5ey2%!4x0*Yu&-&1?5-n}Vk90%F(&-^|PRKYdi2jFYq^Wd}KbN;uU z3Cn@n^9kT!@b@Si#4o)-Ja-Uy0eCrhDNudB3_c1j0ha@{vD#eqRvYX6bQ{k0ce?yT z$ZIut2@v0o0=47Uf#~=uxWePx{_nXgUu~fNQoo7cG-jRxp5(9MyOp3H{1eb~@t98ZZP-1g8SsdlfhZ=$Yv31r@NR<%>s;^-%pT0Fp_=9&hI= zxpf}+FnAxB?HJ3qPrCn=*Neb$Ky*xEB5uQV0^ACI2R48kxxXEl$M5}s+CLzlfBx@Q zV_f6>*+9Ji3~(l>dz{7f_23Oa_tg&Tz#blw8~cFG9pkO&ipclH;MG7f=*>X%NFTn= zU*E`8_umObn`FPnI0mQn8F-P0cvbhsuX?6&D;x~OlUsu>(-)6bFd?T+UqGmv`FXadIAtlqD3?X$Zio-AK4IFqrD_kRszXi@w<5G zZ15Iv8u%Ab^M9YsRkGzsk0){6TJ0se#J{5JSnviQ+RpHh&eHF*z&Swl-d}X(+e>3l zw5$bT4kvnaUv$qEU140NuUkU~t52)oML=@!C_xrJ= z-wX7num`{Q1{y2Jfm6Y1@GEd5_#g0N@E_p6{NI1%dOeWd(AXF4(sf&FtcVvSPhJK7 z7pQE}^aF6UhxEk;@C)z^Abp~-vL$pCwdY**eNo=J_ef9y>MQB7Cj;ps@$(V>Z`DhG zOLppcSzeoae;4xH4~REJ!(+g{K>e$GF9YHc=|{=0mw=ao7XZoCcXD4167Y0f=8hoy61m{M-GVFJE#-ZLj*Puhs8?57qC2`XKbj zT$ZmgWj_g`;TW(I{1bR;3cB|+@N^*h+tsnv^K|`H<`aS1UOXWE{Cw~nPzBEd&-Bn3 zTm|N`{5{A|GFat^2VM@u>l*j!1O2VB_+p?jq46-+Zsq$|}ID}eeV&?VZ!Z(Zl2e97Kkpz*IVCHF;x>aTIGI;-v)?~(Mk4xRDVJ3tG`2==w7=0 zb$>3)SN%24HQtW|k};C;Y6J1UWKYlm>Jwou$`Ado@t1CY@%Xvm4M4oE>+67cLHFMZ z)c=nFj{>`Zhs+Y9zZZn|R~zgHbUoT*fa^*RwU7Rm{5u9H?IVG7z--G_`gHkw@V9JC zjX}vm$yb#T$`3MFe;*4(gXnx1*cEIJ4e9dL2KrlLUl9Kb;&;hl@qUoI;)fRkrQe)- zhj-HDtNxNV;_E{}9h?i+f-}I`Kz%Nm7@n#9Rque1Z>QIM`A3nL+FWBz{Psp5nIlO4 z=$`0#lm9)J^%pOT|DOOP|JB}t^pWh(s)zbRV^V!Fm*uPdmjjhAIyC-Y4b;~!1*?Jd zpm^ey-~=$2UoUHPqX*lE9qbfUi(gz+Eb zoa#6PB=21Q&q0EMNS882Bgf6!1xK zCHPnHKF|Q~1)}Lv@NqDgK_4(J>gkE za$kBz<>@LqjskinyJ#-U*H}IR$o7y7Ivbn|G!7(p#dEI*lEZHU;)}-v>HZ3MEC}Pe z)2ry;4fF!lU-eeoE8juz3UC|GJn z;0xe#@Nw{Aps}d3KMO7cTT=ecyuY~+tmK+g{8q>c7zXLx6{{_C|@hz@;HU`AYfj*6?R%Pj#_`U+fyLs%x zJ;?~o5!L|ps6L(0l%_e|9%`4v!I3~R zKJbxvyAICr*K@gk5J=W*JnRZ2S42lT@1oyIw-->G^m?d0_Xg^VXM>Z$E5N;ABT!rX z8vGQfAFc!UfxAFIcrsAGNG?4NC@=!o>s+;Ux-Q}ewcAs{Q^1AbLqPm2ycfI&yc>)F$)5wkZ1_1}$9(zEBR}b=Bf%x$ zW8kAebi5ykrVGGjK=NCBtT8OvAil`w-^t%wt1YEl#gpPu(R(?#*yF=o*8|n-)8JAN z_(C$U6S*Y5R-G%L*CQ<()Rr#=Rq$Q#@8HYeO7KZ=1^5iO27CiZo~S>c2o42*kFr7a z>jjbp>ig$|mw}gn&w(!i$y&AVM}YX}5-ub15FCPzH<$p_82Yr1Czr|mAuL8ET{N?0vEYLVpz25`=6`T!*J>JPxvP=B%At0WX z?Co@n<=Y`$f5{y2pLjrYOcM*Ykn1hrX7Drc3vey>w*@`?4&{pmA)kN#?^a`cZ{C-D zc@cOvcndfiycN6&oC;0{ZvgKA(mlI-NN$M!%^l;d=!(c!a_1zVws|8EZD)YB9->L~ zybHVyNcZSH@#of}OJhVldL|HUmw-=zi#*=XwE-kIBug#__Xl07_Y1)w5I>y@-VV+N z>Pxj>XfMgO3qX+72k=|(&$b_T<{hC(_Z8jC^JOQ0??L{(K;vEQcrcux^jFC>$uZF*8Ll>bBA9KT2U^?F zrM#s(bbSSQ70`Hok;jXe=wwiaDM@2X#(0@Nm_0MVzm5lycIuLZiV=LZ6fThXRA+gj~)40*oUg`s)P7)Yqgj9QGF=7bbT{;3pfLa7U>7kCH-{{5WW52{-7)0 zUeZgVL$tjPh_=vPqPZW;1zllWrmtH|20sg${~3rUJ^`)(BOV{*`eE=P@JVnf*aM{L zYWKU9Y|&U*4gLj4o?H)Z1V01+39bg;2mcLj2EPH4E#jHS``=q@tQ<@Jk{gmA*MZ-H zAAzgDDENQi-+^fQ6;OJ~$isnX++4bf+Hs?I7`@>x2h)AB=k`D?y>wfjE- zUB3Xn3W7ZP7{4zCp8#J3p9i8-byJ-l3G(^3`#WF0#_<6_`KsMzL#Y1+^}F~%S3Mg7 zb6LLl?_dwnaJ0u!T&0%+By*kyB!5JIyE?Xdp02-Stj4;q96TSa0?z~*d(ZOFSbU+! zT$Zmfue?=`ctHFvUKb6L1u8T2#Yy~DAIx?6l6g-7vdP{I-U7t?uLm0c;(e8UCeZV_ zF29dF)%N0r72r^hCvgo>|LC{$&X$(HCwZvddx6G($Xk5)CZKw%&XPmY*}6&w=)T%! zKk#s{3)s@}w>NpH-PH!dOTbHk_(A+9ew5v!-@3mVY-#=VelJkn1+{5t=O^-8P(SFt z@DvZ}L#3O`@>PG0`2nCYuXY#I4w5;8Ks>Lj`apfLrRAslUwojtivNVSg0}(j{^>yF zh3hcC^=x182=Hj|DDaS3BH#Yvd*vy;Dmf>ar?ya=tn|>|x-S{1v^xXQFx#?~K3%@* zFWoC0DES-8P`UZ?C3^++*~5V9zAKn54e9d5e|vc-U-kRTz|%n(1LA*;gX6$zp!a86 zW;%VkeAQp$PduRUe=blTtIvfugEN7~z3vO@C$)V*I`2+?=gU8myfg+hw%!0#<{BX0 z6Ca)d)`B+yJ)6t=i}#iT$y{BZ=OLXG^wP8WEq(X`unNp&`D*`AzS{p);MG8U@M0kS zr|XNrkjGq?uez@Q;(zg)PzBEcY7g98@L4B(_o)69j8tdVD4!=JH-UH^ceDS~Rk0ZcSz~$i6K;^s}ywhLb z#r5Oh6JRdOSO3fYm;9F=kbaSj4|+(~m0$o!MhSCSzUr@WCmICF8u6jZIR>bF{T2<+ z1bRM~S@C?$Lwt8G5Fdz6jr$7d1rM1e#B-{5ufM9@)dso_d59-h z1L;CtB?FHG$Abfb$`AR>wtTf;FHqly_E-O_UXpi`f0F%bYw?40vHC)?c&_EY>Kyv_ z3H)9M#QVcQZG9#<3rHq4zylec49?1la%PYZ_l)p3Y zZ!T1>c(fmg)=vP@bp^N-eAr_>SGD6sK<}h6o3cCMEAilNpx0mfxE>Dn1=oS=!H>ZY z!S}$`;NQTnz!*^fM;?#j+OEtn?jA$hJT#V{15O361!|vr!7bnh@CSd@?^}VMT>^sq zm8>}sDBoV7da1m2G^L-X+e5siwip27u?xZb!MWh=Kz;N!AYT6n5(ZgC_&Ehv<+zkgcP~RLyH-gi^>Ha#*^({bS=MgCsmC^3rT(xz&E(bu<(LlODeDVR%0B-~D z0PpcQkL$(YA~0Ki&etnlzVebS{$g+>Sf9d2_$_(@O_%ZeQlK%QJ{Hf4FY@_!^7qzg zON}k@X?fC>CdG_}x8`Au8AT+)Jyd0>VKMzzNwebkJ1bh^zjlT}`Oz(HX z6J=@A<*y*G*qI(VS*2cmt697IycL+z|bnJH}hl6_M{t zz>vS5$@MHCT3!#%0B;0u0`CIqpZ$UQM(wk;=#p%EHBkBD$&Z6e!G}B=TtDC;`S>Yt zf6%4&dJ%XzkQ_PBl;wcnfl^&+mKQ+0Vf(0J1Ov+YO80O8>tX+AHymww*q@AOy^ zoyUNc;0O?8^+)-Ana3x&UIHXHzX)bKR(Iu{3V2Kb4&&Z4!1I8{jC8_(fv*9TrE4hn z8~pwjI2IJ;)yw_efXZvt7OlpJ#_m(VbAj4L#5Z8ZQ^fI)B~SPjIZ8rLuNe`^fsdEmi=`7OTO8gywKO2>$QRR33jHQ+Ts zbe!O!`zHg@tn_N9CxER*m+}=qizbyPT11!17hVZ;@3kP%t9LYZ)xK)8t$y>zjM6-{4bDhSP52uEupKZJ?EHS{tXdpc%`K5aFdpwz|WSRI|xRfm^vLJm?(cm0k~NP9s{gA%=zq1j+J6X$CtnTpEM0!OUE7r# zo~O$f-yaGN0ixp=@Ki7Wj`q+!wa?Q%^nS=|bFS&~#d8|#k^|zyfA)A5*XII_LH$Bg)wh;PSJn=jrn?#w#|{nZZo9r{4yLeMke2%zV4S-$GO z5{UN&@wnPv?I8Y_yg303f*_CQvi#l2SMo>vr}lp`BWdDi>bpLHY`g>>a zD6lJd$SfiHcLTjZ{HHcho|3;o<{iav$-tE!`dc#SX+YydT5Fa+kZ{5{A|WlQ#H9IOJe0jfZ4q2IbEK71h%9bx?M%I{r3Cw-ny zlkR`<{~%D^RA1Hal|c6d$w0|`VGU6G%w_#mzS>yhO8qV#lb(CChj>xE_d4))pl5Sg z{@&yllWMo(;|f9|Z3Kb6NiG z9x9>4YMGBB6rtN#xG%Ypbh=$NDVeGC`?E5VUKGD^SavV7HF zj#p7!{8hszSkHy1FQw&|8?MP;PK#5pcgzA zJY<#-{kwr)5bCcsQ2hsi_)+6s;~`un8;QRMfchZFKehF81u9SD zP;`A3TmeeUACBCA?~gWCrlZM+b{+V)y>nkQ{jBr*hV8!(^-aW7mE4aWyl=g>S?%z@ zeLbrh>%QK1lU*;#x4GqcQ{TK38;zAyeT!Cc(a&%8q50QMH@erYy2U;GXxW=98;w;{ zeGAt%*7fzRTJ`A!N zIoUTkc5B}bYAKOpIg7IChT3?B(t4n9y0HkFX^p;B<9g87wQi!Zga?oW)$3MGItr=D z%E`V35KVo@8$Ij#c(T|L$NLkFd3tBOu?^+uJ*rAv1jK>V_0Y5CCX zWcIDX_8af(8oQ-$M>4e@uohWK@$077_KJEvfa}&aR$2l4Lje?dqNPzEbAx~2vw5PV zna+^j(P_iLz5CGcE-9>1RB+v@e=8*O_k9cXJ{>&Ww}AH`alG-EwbnH2G_FnzeIJU0 zcv#RVRXGWHDvD-weJtu-b+Y8~?vCMIxXDWFGu~WT+~GI$Em+q$k^fJ-kxmuYZtB~W z8}uwa%@50le=T3NaMF4y@+is%$&U0dzeD;gdAz%wYUK$NdDDIKSE>Qa$m?3gC?u77 z%yHRt-+rs88w47cuG4*GxNfCJZHg0(-8_jWCNkuqyx}Sp-cZe^`*w{>Fg^~F!|uYV zJ@iyDk-xK1i@>v_Hr$|S<#b~qokU^Ox=Z7i&e8Z?=n7vo*+nPa?F84vjTcSnraZ39u=sTgc1s50w-juYx8Cyc505QgW#2V%&Do`LURH z!rxLO&3KxKyYT8#N2UF%(oQTMt>1Jc{j%>q_v3=X!E*nnDzG>2X}rI&FdR@&hs~}TKux}zWDv0e*X)@hkpyQvLs#?b??9Oo>kq$KNuhD`9W>} z?=+>@K#F7US=IIad&j!Z-~X!I^PXs^ac;CB>LQb_;k(DWYS|R;jJm6h@kq&T($CAH zdDTV~T_1JzQR>TnaQ9gE4-WrsCR4pqPhP42chp_0-k^V`dAV*c4^Y~9caC+PoqcuK z3i@o+-Ovk->bMGe4r#wg+An0&ektmzF+PVPNb8@97VvKrai?o&I(m42BdRqTk-t>+ zsK4H5^wfqLQ}$lh(8j1Ievt&zc6$lgxzvsNbhOP-Lx1sNZPLFr9W8X3RvG&B`{KLX z_;kFEja0WxX5y#w`WyX5nk&4!-aj67J)e4gpL%^STdyxiGxf#Q{-H)KiW);x(e8DA z)Em|Qs_yhRYV~S0T#VF4y}!SQ+CrL7wvo2u%{_V3Qp9gJs;Ztflt^q0kty|@sXxRQ z=(DdnPy@8a)=w0fOKmhCQ4y&k{TsP*^P8nj+bl-4#ycdzRDDV6(awsK#wMxTxr zh_0GQCO_q7zxt_HeJbj)e-|r>b?PFjZ{0E-^>A|&ti+p3{G0CWos?QFRjbvZ0!pe4 z7=i39lU(-I`#c@?JW1K#FdpR{@kabo4fe8LsNGZAZC`;ZXy2~iil&`wa5{JTt%hW5 z_2OSwby|HPwR1_RRdrLeohoFniD zo0cv-*0AGUqc7Z>iWZ5$A(#gyE*WB0r^#p;rC8hQS{rZ77yo7JQ>Q))Tz$~`)s4|I zwU^RcUB(+bS}!9y_`j;n?Wt%!32ODpXaUzaN2`XrXNmm7q!Ow0RB1YzuK`N?b(IK} zbk9&WBTIs!zDazRt%Y(6y>dsiZAfcXsBet6YYfp1t~27EsCL*B)@Dg1(w#>wCL%^K z;;vk(GIF59jR3M~4ApD)2QQ`TksdWQYv<}6A+=|Anrf!DtPZc$hnzsrKvAn$0hTIm z83syn*9{b<ao2vd4ROI!kyRzi zNHya8ET4n;* zM6eOG#0E3v&|rw4Sf9Q-r%#Kd9KPSN(_>hp7*8i{q%cZIJ?Opxhv}GpQv{AZ?IQx^nW=fx*aPaYrc?rXrh)%ZGV-e z&JvT)OMho`|6AX=KI%ST`DH7HSA1ke&p`+7A3OMrP#*R@{<6w&<%&wzin}X4`yP^b z0DXe46_@(wcakRm`rqQ|=d4%%CvvLnrl_2TpG1@5uPK>~f3>&%D4S$Le{V{?e^X`N z$k^EEUn)I=V*|gbbPtSm4ZhXdBwy#BM2l>o*EA$BFmt&g&K*_QKDFxYkTzMF9P1t( zyt6WYcx-rJ&=qk{rF(36qS8G$#xE6imwvymq(rl#7?QO=B~`d1DW~DfSw#K=gCk?3 zWHvJTr^-U=QmKp#ZVH8s`ocEyd~li)M_ZIQ8ExYPw=-wAshddB(D(L8RIOw8B2^H? z)R})LUE9hAb#`uTk&JZY14idODdDNcJeeaJ^fEnZ9NJ+@tv+&hrF(QF5IyFI{;O*o z=p7q;cX{JXMvs$)qGFxdC%x{BN~idvA7fJ5!ZKqa&3HEk8Il)-_5OtDm>G zo){P%8yguMl%nZDrh1yvMXJmOjdda#|A5v(Xqh+ zI!ARK8GxIH`4>L68ctP~`MOep!GVEHWyeMb1{hMR?5<<<4sk?zzwEpsOtjNb!2pEfI6s` z+f{XeT7>kK1;ehUgVa=QlddWE7U-VRbr1WBj#s)a1V!w-(94%eI>i{7?%Y1<;~_JT z-5kw0x?PuIfjZ+g)N;NmH!?mp->N7vGs;k1(4tGNo}(SsQ|aP*HtPwghOlsfLo8E#_L|WH&xXJli(c*BcV^ zRjZ-t#u80j7^zMnnxK(h>lvytk(_C4jK&+jmgcufMy1tKR&lqo!8l=tVhlSnJ=inq z#DyvHQLE&1WzmR)D{6hZGBdUV;+RCPsuf92N!^jj!5vJj+8r-;Rom_n-dd_;Uh0N> zS)rS+?bprD_>(yD4^j6}BJ4^H!l}xJ^0DZu^VevmUq;lQqxtxY`fF6q zzpfF%>m#GBO8qMwjCt@UoN3IIhJHiIpGVqT*Pyg-h<_JnGAtJ&Z=fSk@{^=@zb-2@ zYh3D9c6aykeS_JKxwr2@dAq#lz(aQXq_^8;*RMDrpQ3yJJ~u1qKJfA5Vb$Mk{=c^w z%;wRPOcS@F-})LGDOa`dTn|S#HBCbP%!G4OqpSahmJV#aSv1+;?f&WNOntigS4}eR zQzj)oCuL!JNR01h4~&~SV*szVy;$OM^Dl13B*45biJKZSBiznInEvz49X%Co<19|h zG^|rO&+#+ZwWU8grf9adzG=;=Xcu`}yzd&7T*nMVd^<;ro|+YGPVL0Y9nAk?Cvr?t z=XSW!VkS8@xSM@o3=GLiH=C4h!q)R9IZ9K1doQ&a=Ow=Sn37qT$V^b>xuo$7~EioMFMIx+z)$d&uH&Qx?}XUHuE)5)5sj zp1Vgcl>0dy37cW886i{A_OVk`z0at{muW^?1iRoY4a7{QQhNIhb}#i&imch$RQIZ$ zNESSm^BJw0yv|ocU`x%g7=a~LuPz+2am<8Q$>#BgGqT!w7=M&lJU{Kk!RXREOXR1f zG}G&$?rAVMep33}EQ%jDJ^ovJ44d`sucLVf9C*+nSK>vyWJS-x2R;72jKOeSH28x%tX83~r zdzaa5vcyCcGu)?r?b>U<_Oz@==8ImR|0+Twn_G<80mJqej>B*8Ihh+0XS6v~l^quT z;a{4%w);zmPxDto0{Nvi{B6;#T0W>%t3xa*TE0x9Z1y$ud&~Q7grdYIg)9G!m9ByD z$_(fp9MB*C<>{xGy(f<7+B;hu3*Fu%xGlO(A`NefG|w-b?Z7f;TnfTjmhYwtQ4kEkMLwc!_Q`wI7)RgrS8@CcpiyurS{=7Xia=D!*pft$@6h~FLuS&MFNXGHn>R;h1nZ535l zW)EahU9Gj7NruA5Cq&#CO_8<0oJAHb@$OGag-lfw*QZjL8;J~5Q^v0AS9wsVEDnT` zF?^VE35I&!krGBWay2^2EVESoTq2eojfF86VPSJv5{lwYm~;&xnIVg7OiLNpb+@AxdKV0IP0sD6{G@35S-j9*v5i<(7~wQr%tm#Q8uh{*>dZi;qL-B?mE zCuLFHoDqv5vQQpCSj|ef2fsX4l%gi)pzE}JB2UaP{f9%$@n}KcK{9TpB3p7XgcB&K#kfIe6C2$0R*saEjY6LKU#)mk zECdHZH1Z14If&aj z;&$)YF!tuIf&fzD*4xMG`L4!8!#o9mC1n~6wVI|>pC2{MfY!+G3ErAd4C5MYUPEsrKv%g zAEhi(oWWvqSq@PC1Rl+fU%ws8YShzNXi)8wEiM?3jL{-%kJNJabsxM}uuEerlQ;G} zI5rDILg)FD{g@cA`zE$mM+auJ+7NXgvR5$3SsLEskk}r#JT^o<2OPTl z<-Vp^?0Xz~KsE(-f8Qa|%Paf=XX14JFx%2zz z;=_mSzx9XT8zw>f6yJ5Ty;RJ|1EdZ9FV^c<((d)YC{VG{e~nGd(;aiO0*M;kHS88m z-TPS+C{Kukm)XcnwMA~208SI(Nx8W^FKH=d)!4@DLWx@ht5%>O)=z@4wRB&T&xP`O zm@7{nz5f3#sD{t+A$m?G{3GuPr9@S>D#fMLCly1C9z(3NC#?R<@~jTFcsI+6;^oFazLpuTsG8pvayZqc``kpl~ryf;Ctx%zaexpgI`P0N_KkP9|unLFO{iI>z^-_~9bm!VCLEjWSf z+$=B7u6TjLGK&}2Y(*{3O#XNtO{QxHUB!!SAtUn%BzCoyhh&5^aBV9G^)_>wR^mEe zqQ*utuc@S*$?bxYEdy(k;+3PM=)KIjA3Km3;O1_U)R3nLA?0>fjN?;U8UmT?+%s>? zWV8zjO>+80Hv3D{F9c4>E{vpbWS~vJ;<+KyOPeKf-`dpqX@Y;p9x*%Jr0%aRvXX7S z5zjesKQP^{ix=8eoLvkyA9ouh%Jy zJ2q_B-H2$4wv7yskF-T|6cp=R9KKX~dVwp`7Qxiaiu!T|wq{h`R7jC+ISBRi+X3PU zT0uQ2G1PKX5>eN|K(nzC0-&@%z&v;s;h(Q1kLa+ZUyY+f$MUK@ah)nJVJk5aJmato z!Sy!JH`Qm;cf5w?5}gp;`)|`#m$AWI)BpcAa+X1sm9<>aw-+oH@j6VB%%-4k(r{c zubJ0NRg1m88DTqK95OLpiryD3P7QE@b!Pp<4YB^Tk^?TZZo>gv>I0 z=U&B~`~8^cRocgvedbfL%o9(~WVEeKj`5_^NwiekU6Tnxvx^pIA%dncb-TUmp0HAr zX&&1q%l^=?pAribo@ufFG0-!cfS$X9VMjZNmUvmk@r;Xt*NmKp5d28A^((X1sfAC`^$oK1{4;+Y{x^Xt$LRqJCnk0h!tu`f(@rl1uLb zeR7dHac&{d=SOBeq-`SiwhtZtVbkNhvGKq$7w#7|f0gv|ZTja%Q;+wx)bb1@3%b?$ z5wO|(nmnK4IhTd4>@oc@Ujl;TJ~r6#2jMg=yb0v#19fiFf~QyXRo2;?vXxJPY&CnA zd(K7blv)86)2G8K8nD1eZn~ENqQPv?41sQB%Fpj!d$J<1W z2Z`SI^zCBw`E;T$wTEwq5aklzO@TQMk zD2_Se4UQ?!ig$|@HdSJyT9{S2N#W_Dqon8cFAVC#8jy}eCRYgvc99*yCt@kgSCWh_ zbtOB!cC@Aq2{U?~1uP$eW(;P^K3E>Dy)2$ar}y=5h%2N}SrFUHf>4(R{|T}UuL`m+ zwjsvZpXF)uvzrWUIBT5uDMgx3*UlI7KC#W65&O)C@JffHlZsC&z=9xot!~L{^^ag6 zq^*Y!(DG)J4c$p#Y53io%I!$HgEa2fhjaNnaLo+WENQV~uT1gX2ac(gZG*Y2*ZpF| zVY)F?%{$zGmHoc8g&Fr&TY>MY-jaIjR*9NhoaH8=qVjvwJotyt-GuhYh7Z&xs2I8nN*HU>%?!9X+vk>=r<~e{BD(JsYIdr zd?pmB)*oEP&M|{9L!HYtl?k7*<#S#k|kfVpWZ$n!< zOm-&awYTVED$|ad$HcMAGK{eXnEI;qEC3Ee&bccPupF5an`cVmZMKazTejy9(|h)A zoTpqnJ5;@&JbpdVKV{aPNS$E62x@~GoA=#E7o+InCZR0Xs6;~Iv0%z>(@Z(ToZSY| z>N;o)k4+VGYuue^rDUWQ(X%k^BG-~Iq>H+QLM_*rO4lhpc&gkn0GKDXYYUYuv))D8 znzFLmSgYAq<=S+ebF$3U;tXn0l#uC;Qt)K5Ceo3a=cy!cmsWHODQXTKOdyAkc0jYp zY8_@l!z_o?Cv3`4MB&hMZJxMdqOqM#Dtu2{b~@*v2gSR@%@n-5!ia2V_vMMqxq*CZ zh9x@});lGih&Ke1c8rJc&{TCNZ|Ga)Liq0lXHR&$)+(55#4;-|Pob+8Jf@Q!RA`1F zt89Og9j!s{+#`7k?J=Plu1@M_=V^jGei_9{`v*g^bTKVq#reM3cTanXG*EM++AKgA z(jvMkFyRfi=w@7JPj~j@h(--$7jrA85;4k-{N&{hY(k@TB0dm~hH%1gsRg%EN=8bW zDd=L<2|cGFlCsw$w4L)qN^ERM<>t?l82*CK(S`LduI%-sqmMoMNqf1kBSh!L_DolQj~PK3 zgJwK_9Bc2`ppmzWS*90#!F~$%45CWP)vt3k?<wf+%XIb6G7Y)!hJG=6N?lj3>=d&e2hIeRE&E}2b1 zRb0(bK>lo-W^0HZl)nmN%4@WOeP40kl4HEz%bixm$uI+U5K)foqapifNA|m%m1M?y zgu#!^l2xAGjGC>5S1z#04 zufp)KvkDBUaXY#~!_zDV>-1np-D9W7#!GuPlAR6bc>$)@1}u|Buz~ro-1$a}IC@A7 zoEvu=q*t)vpMxy9U*C!1$(Y3xc5))5Sn%uPF*!eGqG z^2}}~Cji~f&ymsMIt)jjlNkA>sc~lPNKATexWajOIoTg-ZEw_wninJJjbeqDB-fF& z&f%B5(?aEX1{sdN>>Yo{n3T2-RT42T^{#ns|7ob@#EG1Bm+Mc z7vFacpGdg+anP}^KMLQ|k;^uYj=xLA{K)oysZu zuO<7vT4s+bGpA>bJn96vnUzRz(k2eX=G+N61qZ4coJbxtt5h3d_83+WB5Q`e8Il{pW(PV)#-6%Dv>Sih z^fw*S`9bb?A@?fC-K~t=ZGtC-SUW_%Y;eD|crxmhjTn5Sm^_NH$A8Da*g;0;lsnZP zie+Ld0w0n^>wNiaxjrxeN26C$y@6#@vSSHiIr&xwz3J%WA4>tH;XV9^qgbd9|Xa@P8v1-kbpT&WA~^i z%*Ob)BaqlDnoOSrNE66t$b3Y>s51H;eVy^>BDtdIU+)*S_DgL8fHYM-*yrTTIRW_w z#2}`P$b+s<(wf=URh!g-Cf-5lyu#_+XvbFL6uvg;f?Et5k^(dk)qZZ@fIk`wpI8W{ zD(VtvRd_J$I5?DKSmkO#neo>=OL&Y64AS+s9HQr>vn3t=b zf4mpf3MHu0jc~_<+gk^yf<|FBEh2$g8=b(Lez_-30D6z_d7*tN@&kQEknJiWGXt|KHgYg4|tNWCQrd(rr&jD_)c3#?s3 zo+dKz@=6V@l?=_Qp|`P01WRfW%ytCYY3XjYeB9|6x0wM6>Y7!e)Wzd%uNSrF--_U$ z>4qeNoJu-1jjnd$(xsNI&)>LC!+~MGdF57hHaqQ$@6`0^)g}5ArM&!}l8Ho+{(qVnLn5?kg2vUM0=I%|qRAjC@*=D6Kk zGaPT;4^wp4hs+hJQ|4{Toz9z)UMeXXPAX{MDVZZa(a&TKL;lD@$%m>{ETr4Aq50X& z%fw{Egpe62TA9*P2N~CEKjNQ;^K+;mAFrRwvqVKeuGa8appra9AbN-8eEWEm8$-c( zndx8bJ}DL3Fw3O$X?}MaRuT!L2A+^;kKx&Y&ZMssP z!3(3Eu&PuIksrh^E(&jgkc)MSUjXJyTi#?rz#-|8b-@I1jw!P@ZNHkdATkx+2>wlD z7~amC_QXOsIVfh2Fgxo8Ypvj0@umv)gq2D(Yu?ma zAQxp=M$VG$mUK5pP5TRs=vo(T6E+xRLJFZc$KqKp_=O5g#Go}to(2CWH0$IjEmQ}B zHI{-IMD<+jV&WRrI*BSQ;938W!mPfMZ3z14L|tSzha5t4&LYaMKU^rg+N=UxaAsyF zR5PBuQRM7}WjS+46AawduBmN}SqDPJp?bWY+NiLdu|#ZJrP~>4C&LLjQ7HHPO3A;n z+JZpkB-f#O9R{@k0OxL#H1NieU$c*`npEosPnn#PNHb?vg|-!?{v@%?N_Cg#V%3UL zQbCFZ@;|0jb5x5^5xp^?OeV6Xk#E+-m`PD9w_luoJSEv3%Ns*rkib!$Y;{Nq4swG- zZu3S{LOydu293@vi;2$|N{$96j+;D^P#!`O=@h5yqzyw;Lv^P+A#!nz%*mVWCr`CZ zh;sWWmB`yq58kmg@^bqr)j+>4@&l!w7x;lvPd79hO7T+yM78qEKbxFA&i;jF%O{mw zLtWN4`=oivof7(oCMoB?Jx>ka8w(`8fad2_(&r?3lKwq*>TbP;scxwy$jwUv*2v&Vk1Ob+}zvE6&+%dw->jiZLC(L3H$f4v! zv%c4HZ>b2Bqf;-N5QJ3afSU!~?&pX43I^_jmeNRvW(?g`I;D$=9gc|3#B{jGIYd+U zZ}lH__)x(UJ6-vMO%EQZ((P|7r@kv*Ov@=gG|(8rlBn|ekX91wyT(U(iDmnk^>$s3 zXno-8b(&=3lp9Tiz`dX5VQm%*1!97W^&OhkU>0S96o9qOY3etoDS^?{pye zu@S~pW*Ucv#akFYkks0yy+{MbKB9}T>A<}Gun#qu z(Z{R$??FAJwvh09z1Julbfo>ncNZiu#q!6d2g)g%*8}CwR#z?mX>%VI0p-d1FNsM$ zea%07psAFl|6u0u5KEs-o6N^Tl*;wa6s6SG~t+u>^f8(vZWp}logv< zs8oVwmLRwRoma1kDqE{?R3%4zlsN7Z_4Wsu?yL}-8ZiZ}B|hk&<>Tc?yRSwt>eDC8 zr&=WrEKGEtDaAquT$%v4P)>AZn18TztOZyzf<%Lxm2g+C8{4db84=F7FQx#A?%$#w zw$HXyD|#-$6w%U9*m|Kac(Ws&b!^$?_!^U48TQDQ9i8W_sV7n`5$H(vShVAJzT3z- zBZ=<{I_Qz1&?Bgh>_hW>(KpR(T0lkzuCL+9HwfdM?ZnjFHc=Q0*!r~jYUK-Z?UFo& z2xNsj^<0t!^+z9?x=r>2nPVm}n>STkNv0iTqExYLk{Ojo1PA9;{UFx&8jPIG;@>h$ z;MVg}=acWq`Q-6w;zgvHc5d&tQY-1mJZH*kUC#Ytb-`-BKm@Dtq?MD$vU%N-AWB<~ zsU7Wzj?C&`w%Z&%GPO82sI~qc4qIi*7WQJJ!csnPcSFpT@vzmE_4TG%zG45~p}m?V zDw+|gz!)|t5c%(aT_0)5zUJbU(6ZGA8rwNQS?rUrj(2UAE9{$Pm)hQhAI85n5RN3f zj5C>)i?SwqiJ9Z3lwB-6Itg*_e*_zEXOFmzEqtn zE0zc}o)&44F>zzyJEJ$z+wta3vpd{zhZ;L*0T)`7Bz3PQyEvCgo5#z4wuDr$C)B>d zr)Ku^Rp|!_J}D<39%X}^6pLNBI`uMLitZ$Pi552japlMP$$wU6JKU@ySpAx5?Bq=a zi#-Yk!F05vk9?8~%q#z}%79bKBDpt&;0;QA&cd z%W1=j$R8uZmkP0Jbo#Tdw1VKZwI~;$j1Py(nKgbM>etPbG`B1nOJ*wK%S&t>#J+eAe=WspZ-Q?R+h>@r zyH@Qm7}X#oO6LQ$<@V!^a%`&EWq!o#8&mPJp*wZe)T<2?zvKulR0QjR+G$lxZ}U73 z>XL12UKqMlDXnU@%+|C^*6L*i1fPSiuvrQ|W4|{g>1wwx)+P_KKEjEx^o^pz%KS+; zXkAoG$)T=V)x^>4);2>e{UW6m=4SR8^UXrI6vmm_G@Gp=gEzHFgH_X9^~7b^U+SxZ z`kB?CO|{#Y>1c@v@xp!!1X95gd+&GVE=%fXtzrMfed`u9tpn|2-c5GjRAi<;;W;^{`K;~4Gbz7Z|XJX4^NFl z%NJhJM_Lc%OJVY($%$y)o?drl9l#>itZOVg#-3h!m^=5y{e73 zFQhgBhw4AZZHmf?k9A`i?dVqupCkk)xfj+vGXeQSou0G zt>L$hr0w9aj>|n(SGB4Ya-v>JuPud?WqP*QR>tblJkSqBx{n+}Gx!hem~kBLwH%Iq=FCq;-&wdBmb@+S#C)mcoks2V_Eo0R9Y^u} zZ7kZ}o9)gz<4|0Vt(VO{nX=LEbGL4c%z8(X+1D&vZ#o{1#+(s@CByqN*yaE5Ryw;h zb;okF1Ni*sE47nR_0N7y%;iOx93nh1vnAJMg5WAsyoXL#S(dT9orT_mBh1e6_7rSag`jUsS@l4a-aFS+xZl9|y{) z_=)iXg48_jI80>snWjVgIL$1PTxtwT{UZg3vP7iTO+`=xMMYAWq2zou%8tjZl;tZ)K2 z?)g}PvGu}a&1QQ~4jVB9?g`cE$kX zvcR;ET9&uoG5?IWNGy!r$bfclScv)4JzhwNl>7oI`S8O!-M(B9d5sMB*-hDiseXWv zU=c*@rC25{?^JX`hg0qC$Z#^cHL0DaNu+bp2Y{uK@nOUVQZ(%vjb*sfwf|C`ErgM< zbk}G$zv5k^sWcm+(l6CnQLL|&f2qz=wAeM8DyL}IXzFp+?76?qn13`Ag`G%4jT=&2 zS#nH@KDKCXvKDsAMi)AFJ42EID?LbrTLTdEt5wxMZh-F z0Ge*PlS;y;srh>G*zi|NivNBG28>Z)W(vzte*0iQExaUk$QLVeD%~PsVta*8(sJlX zS<(OAiPhpl53Nu+xF|H!=C&u*N5;foY+k^Zs0T-eziw5|nkocbv@}(6k%|ko&QnmV zb#)vf6BpbyGCewPWNd8Un-rb5S1j;LwqTLHf?v@VhZW?qZQ2#oTxH6JTj=IQMbpll z;(<0A8&S!hs$?szl1mL1V{dVm*=`t~TJpn=v<`N$>b9wf{>NM)wVbX&DO03&)1T&?Dz2d`dG9j9(dcE;5VjTQv z%X$>>JKzb7nZO?pH0ryexk=L2i2FJ(@?o&70n@3GVx!YzUBhK^%%!~zVcPP$yWZ^R zM6f?-$AquaTBF^cmd!tw9rJbbul;wTw}T~KYRwSusztw+*33j>u}*U}9eLws+BSE0 zZre;&m*N0&8kw^o{x}Er4x!<8ig~HMLvXw-5YC2BaSH62wfUnmTAM#?ko0Cw?sx~} zq?T%fjk1+&q`Nz^ktU)?dm`!b$KBjUc}R zlHYc!aC&3OT$*ckT6Vd)RzMgn9vQQd0P=`0La+IuhJ!mhkn8=t&5Bj~F zC+xr`zt>j2Q*JL>!Fcu#>f2}U-LLeHfK8S8d+i$?e88sAdzNZLG_(AZKE=J2o;?rk z8_ztacMmxDGN0h?O7|fL#Jz9t^ZcNFQqLc^yy^M!y~Fc~%FGicE8Y9_HKjRp_mF0? zGVhpgeB&5=7<(L&O=jyF{q4^OhOVD?U@Dq1IlDuG$@$ujj6;hWvOv7_A;BFwy{wdS zBM_q|ds=W?hnLT=)Z$Z)XfkUM+*!E=Jj5`M|43jT&I zIUv{Z=wb^IahN4?K%P9TY z&I~AX!p+Hfw6h?r17iu9p;YnNf=%Z+1P;wgkERo5168d(X|&h5CX2Kp=U!>!O)Ge# zrAIB3zO7d+lR9`WN>&I-+nHxABy6)n7?QPGA+$6tRtWv`7Au67qU{Qyr7B+`w8t4g zS|@ip@xI0Ryf0d~-=4cwcH48msc7<{UGe?*N8S7FhQYDhes+9#>VDUr;~Y!cbayxI z?v}snH#eo;F29pIRn}XE#dq&-dvVr%&{2)IZY|pF*)S4+U4F)hJ-@E`tl8LPzr!So zGc7r*Y^X6-zH#Hg3)n-Z{dM~GgjBG5O?&AT2GXeEkW&U-a+PGZ&QYkP;jSYgMEr%0TtskxyN_zw zs+TAEi1<(yIsq%)IV5apRcm7LSJKlbvSoH?up9@?Y~bJ%QZBwMY%zoC!krF|b7s`Y zESj=bt-S#j17wz5?C`R`#9B;!Xsy`hQ@j>SbR34KC0JYbt?4vYQQ&)uExNiOil@WuPqJVYHvyf-`wlz zbo`p)PVE9N+cg)sbD_D>#ho2}cgqiaYu6B&Z-MKC_A8*CVNbg%*j6p7fAgulpE3-3 zJ4exiO2hl*arAE3FLb-X-FR|xuf+$r(vnI-F*d3p*ka>#A}B46T-CpB79J-GG5U_$ zyjXp3&#AX7<8Pyu*qL&BEx&BV@QRPD=sD=X{bNUzCFfz^wk-<-;-_f9n^J$&(<-j@787@w-394XQ-Sc!p+m>&CkrZVdq51=pIGr zuqDx?mIY{NE>u+Yrkqe5llpvLl9lNW{$WV*84<#mCMw;7V_)t(Lw!axm7OFMx;B&D zX#4E8+^jJZiJ|PasVYC;?r!{tV{5yg!+{lDI>y~q_tR}_Ivs7X`C<}gJax8QwXus^ z1WfJSv{NhW>I>R`^Xejk5nrB z<=lzmm4zdtB75|gzO5%J(--m?ohF)PvM9(bb876YEFWcnnVGV%8ZqVZ_J{m1^Mnr) z%^^Yw8XLg7GZ@o780cokeIY2Kdy8x#Z%?I;*Qh3Bw{39fo^N!Ik1ZIa-A7^Y1=ip( z;d#OCrP~%6M&7uBf1P24)bJc`c32sQH#PRA$}-q`KOS!C@p@#5sg`kTZRIrO zORiRM+a*^^wV`~;)t+NsmMyu4=VeQ-;d!ei*N~>olB-Xa#Eh24<$cF2!kb;R-Jc_l zzpXa@>%@LA^f2Uu45$x~JPj_q{o^wA*xh?4H1$jOX_ z?m!U2=Ga_mXNB0Izl6vy7(;`PjBN@(Fqhn&mQ)mZnLHg2XDY2Q8sh&o8;=k0nBfR~ z+Z5me6G_Fvn09E23+2YJ9v-tz0$A7jH6Ihm-}#Ty7AbKjd0KMcI+Ax&^4>gM{ulzB z1nO7KULnbwycSJ9Iszg3H6J6#-zg^qo+7|8GIn3w$?LIvaf1ohi2?J8ch4cRJ>JJIiI#J%bLI4a+5H-h<^PivTocJL>3T02-28k-+=oUJ7|a#TTM8-F4JjWo@E=^1u5sU^bqdYSX?AOi#CKWvtUev}P| z%QdaPF0uool?@>_qca0caWq+AvZKGcN5|qHWwM5RYW3^Y?I{7sRkghBWeB_Rs@(D5B-{4EdD_sHEy%Y8dTfC zdxdDCSZSez_B=Rmh&;FtvuX9tnsD<>st1juYrpoiyu0HHZycE;sD}e1uJ4GAuaGF4 zB*K4jd@@828w~y;yU1-BZ}+|V;YfK5{azZ^*4Xs2lXSrv%6?uxIm6RlY_@((-Qi!x zw3#pGi(k(}jcP}L?Gunvj}4uc*%z5L_^d5DY*%NoG%df`ZErVtb0zmh;&@N8n!RxK zEA!1EnliO`hGNX>f%44DOb`Op6{;1P;)^ra+DMYQSM)CPtW{wR-)vRb0e)4lOmlvm z;*9h5LXvUTUSPopYLy33f4Nns;+*qa4Smi9)`0RJ@_EM&4P{#18qHhhEc+r|Pb(?n zoWP>~=pinkJn=nH2sVbSf~=Lz} zf^g!O6`?IxgK(9f36~vAplndD%4F!z8r&+KutW|YfK+oY1UJLgC6j8)qDawNrW5)$ zM1LkM#ubvBGvFNvu_vKrLB%T97sc7m{xGCuKBWqUSZbOx=P9_Rv{EIi7t?{RnvqIi zerCrVS#*kvNl{65<`E_3Tmj`JmFZy>WzVcMG*0gHa34NOQMtLkD=Mp%t(Tg$vMYn- z6{pi&*aS;C2`8{nR$M|}Jtrk()pJo1S}p3Jh`gTmMHJ}iTp?xlMcPN+$I-bo)Dh5T2BaR+N>v# zY@OzJgd@65vwv!<6f19z(x%MybgsD_A71q;-^Y$ zI_1SyT{7A|Q$$|7!;TzTxJ`1ZlCOn7xZ1vHA7IZJ@YW2(uttRWdaB-~C zQ*U)5gf8|v{g#BfFhMGpew|I*Ayt)}gkrp2_~KX0+)$WpZ3ab&5=6}vso zsObCs&Oer7f4eExsf@i@Ja4BX{>@Z6AM2F^nWMA_24?_IvCLzOW>Rr! zg)fmM*`PJtnS&bkn$dR@Kwy+1yl${hlHDE?#VsaW@l=S}Jy~XE_k}BAAv;XzgVs2#T!?ylAnv$Nxee#7R zg4$&jWKYiV<=dgio0^;eh0Bt@lMDUtQndv6yUi@|z5<(XdOIO|B95y(E1(<~nfD8n z7hYyK_|lQuQ_&Jx3#vSkq>1ei4!jA|HA>C72%5qHLRU9i5w5Y#5<&YW#l^Nne4ve1 zT;2SzxWK$kA^ulnrz(=(HA9Km6jow+4Z~qIZXt;%JGE`+wJb0&SYW~tuNYC;_i?w{ zUm@Tk9CXB9bMaKG+BU8FhbAsEImYEC(~#du9|H?V9b3=x*ETU*v$*5Nay@wJX3bOu zb_khfwm{3Ua;*?XwA@3!XnDT0A`$A|?13m_=}Tpr{3hi_urT0G*Y{~YGN{#?GO&e95);^u_D>{%Kt>fH7Q%Tn13 zf~L+h!Ly;Wb94sd=GZF6429v0Xoyh(bN65% zVIg_<2W9FbAABX6Hb^V8qEho_OHyhJv!%4M=vCJBrCr;Vn|F=)a-Cu}gTyROdM#_Y z#Qm#2j{6t&E%U}X|JoPb>@Kn5TiPxUEwWvzivxE;Kfp4v(BxT%fvHI`MZ~AYrT*`t=^QuEUcF+W9!A`G8^mVN~?U= z(1whf_&c&*%xGxgcJa?!xLqtoTepj)DtEis;|JX?a7pQrcxKM=d~ViL=Fsh;ua$OS zy0mh;xbJ?~bQZ+yOc$HWKInFd-7YqPG+QzRUobt-1z(hjc{$hGn=$bOJ?D4P**0#u z$%SH2Zini{7^AHjQ|59>eKJ0o92eOWdA)9|)5eM^_PdxXKn6uSeV#XAk|JA}Fl7~W zrDDCcE48GeZ4H>XXE9*nmABaa&_Q*#mg^;Sv8}}f3t~3hwFSNx?HEt{x;i&p9(220 zOH4baPHOK&ti$#Vn=FzeTlY;)e+|hVTrc|DnM8%>&h1lt_iyid`rEZrr*&_48lCa{ zucPkct{ETezGn4395MK9tm3RUuk_gMGUkAuE_zni0v_Y|JVF%?aDa&9j<*Ev|B zrj4A{`b~=P@85>6Pif%@k_pBw{yw&mD#y?tGK9`+Fq@r<=CSKT**2=bwLJqUF8>`O zGAup>EY5Hu9VF``W=!#gXaG}$&X>hOx(!8KMDuDxS~$^N{|Qnyw4@SR7*4`s?y=KL8+oBq>vi$Eh7a3? zSs-*K!i5n>tsEv%Lo6?@fYyi7ZBLks4#xwcPF)>5W^GSM*OHl_i!9AY3_#5*vaq*pmHnCt5zLT_^ zNNY3ZY)C^|yYuHn7c{s`k#Ked9B!@S?jGwhL48$;APm9E9UeBfPy}*fGugL!lW>HXsr}$3vTsM4nbu2xzZKbSD(~tNmDlbI>WCosUshA< z-v6~b|5)p1ELgz}|7QPY7k5im(Y~BFPHv6dCrG_&W|R z`8OFVDr6a^N@A(}SxU-2(C}+3=k_F!=)U9w>+K`+zKltcvtc;kOk)e36VR4Wgxk zZ@F`rfetU=P?5pnU`wl6*2<~0w{obN&Uk=V%B>t*AR@}*fYc$sF5;Pgy>@qhyV%}v zehOL=lSP419eyc((!O=d+<0ubtd5&$Cdr~tR9a#rZSwrd5m&mA{rq~^iiKvBk0d#UqO|8W%e+$5d6{)(`ws1( z(_doEY^6}Eeq*=yXD;B(KaR0*!z{JEYo9OwfA-!z$giuq^Zm72YRQsp`2hq>2;-2p z!L%_y9=6-Y6;;Yz=_;j?DP=1CkLUg|R~1!PaceSjM^(4_x^9hWG7GcvEM|*d4d}|!WuwIF{K;SU#hH6YHjLlAE4A?L zafU_-r1v52wZ05HIa4T2jK`E8ILv`>mZ0?mSLqOQLbkL&shN|Bzdc>BSDu$L*5kH5 z6r-3}Pq?PC%Cvcy2ZLx#ExpM?+I-)XYb>uZHqOD2w566E(5utLhR+XMrxqGA+&Tw; zq0Yg_!1~fuJr5mCfRqfaLcQ#N1<7eMqVxo(@{Zj5ypD+8PD-f=K7&q^AEz&!r>MBQ z=_j&n*-r&S9ZuX^RAUSe(n_iPu3~^TgCecP115Je9HCuz{Hy!-|J3a`{>?@k=;N{jFn#s(RS?5 zy+^*8)zlDpF>#wfp+S1%e~S|&Q$1k%wbJMiBD`-ehRVZVhCOj4kSjF~2xXyOsB-PL zC&^=+PXB)Ek(=HR z;OAg?`4GW9wWsOTj*k-*)=A^!kbeGif-jKpB+U_$z(sbfe~^fU}d z!G1~399mkPc%d%0K>nJsL_Z@y*R0BnN#_vL%bINoYZGjkNiUM6#Y9}H(sYI8i3|KY z%#;UqqX8i2*Ol#cpK!~iEf!V9F%*X(Ph7S|N!coX_|Mf&+nWPWXS!rex9JMqv$O{e zKK!Q*uUSkng9<#cuJ}{LL8-mSi$qhZx%tg-8V~G)9d{Rs149(PHVQ)MR+Mh<|C7+2 zihIAlJ8zuelwB~H$#@Q+@VTmXMreGu5pSD0?+aTko>NFAO!R7!Fz&jU?PN^UfKT5$ zV~1Az%(Y=^0uG@se?q>y$_WPVONR9){y;|_!`aG~UKIBYWBj+J7H5IZgCV&NB+D%j z7MXaSwq3l12VB;n{L-{FXde8GH9uKO9YHK0N|CPV6B@GAwT(g5=EGRylT`&|178rp%R}2>dS1hwr6-C!kxo{ z;>1;BT1o8+$LZw+lg7(54fHC(daSVHt zh%%g`wf<~Nw%fIdpE9Fw?S03EM56N%pJUj_Z$<8(pREz&8xw=!foP9BtJ$&~mRUGs zihlBa8en*(=?^`aEj7a$~L@A8o? zI-ODX{kJD}l8{ptp5_X4&}i8NPh`+&2N!!{Vws4j0MP>MyQ`19Z>O7+JA1hq4eYI4 z8CxZZ^v&9lEg*QTNBv)-bkQ%_d0qtNz({0+HDU)h+HF2>$;BTIx<)H{1+1>y70}~fhw^CE6i}n*b(H*26T9b%!Gz7@Fv#;CV zkcuJlvTvn#@W9BI?-tsT-~HcyTiW2-?)4)-S85!3z2{KF=YrV$JhHp4f~6xD_-qEk zCm3^`yXx#_rFboeKhZ}t4NI##UsAlFT=Lq^-mfrQW7hbQef=Mw+phU`eJVy{+hv!( z<`?(;;%hEXsX7l%GzOiGTt20VU2 z*(zO;708t4sNRa>Te>Qp|PN~G0*`($h{ z&6u`%VNo>PFMx5Z8n2TYVFyXC+ANNY$nEoH@Rn5zdmi)UhE+j^yDfG-k#lWs%LrCl( zs~fW;*LEho>F{oh*`wlPf+jlT+Q5;BM-P;Ka7#r0zaHp8*{*} z?0+>g?hnfrdn!+6BIZqt7?cihWrv$~i!`=osXUBLTT_f<;qZYrM&4h$m^tP(t6gWh zW8k6LcVVAqBim;z-I*qq{6YLZ4pbIOiHRL7N-KVfyGQ~T+gY7BUoc*ChMY4FH<;Vg zka7F0A@7eFMP(W_8>-b78;bqKIBD{Q1;TIboS$`RoIh*FMJf&fy)lzhu*O+C%$Ls^ zR~F-0fB^HDGwqFH;6qUiT#Oi~tS|zLg3lbPLpzv4HQh&^AD0=@L3ZYlmEQkq6AA2i ziG+(xU9Bj}tIFU>+0P$iy(R;a#?X?-QmRBq3tas+`#9 zbBE2(L`iejWyVo_EvU)g93U<%ZQ5f}%8Bv#<^Wj!f#R;U$Khj#zutCU46jSU$0#7=wom!tCZ3(S3$4T;aS)or17b`eIM*!Ksf1B-wy{CQ#$h^n zWM1k00MQUy!d;f#V`dH6_Ah)eE@&i@YBT^GM1!P5Xehg_EVh#Qs`5r$BZ%&=l_9i% z*cbVq4k)vma>EYpM)F<_6bRNpcIVilH{pX)$eg?vQ9&rYOH$t&#erJzgn||-$qK@- zX7b%G8OuZY^H#*ttKOWkA@qX}wx&#WY&NSQW~q2ZWw9kCbXF%~0ZZIlV}?qNwwa-_LjCOYC;7?KDoS35Albyc ze^!#@5jQ$9&Hti5zgB0D4b%9#LZ#5BhaW90|KEV??6v%eQa0)=PN@zPFtpS;@KLip z-3RRAQ!G`r=BE5R!K2Oc{7L=iXK`y%gTElIf0s5Z2H5>*nbeL^X?C;*c^A!Pa2Grv z7C;r)Ds@N0hk@W`$@n^HsVsus7Z_3Sa)}RPS1{&8U1GN9xracRp9xlyk*^{?l59*+ zo65@6DYz;5G@3N6%INJCeIN}iLvG3qQnS|kQX*1=hi0Qo98&Ncf9YIQGSjiBp^}wh zF^HRJrI1gNRQR`j0H&!rZYs1M=!6S4G>bl#7n*E9|B)(Z&*DBR(`tsm%82r(MIoA@ z&nYE0LG=05k=kMn%t>Vkb(;kkM^{S6nzIWnJZnItG@KQ&g^3B*Y>8D}5n7j`u`pK1 zD)*!5{bOnxXN>}xQ5nQOcT(!I=~$05I00|psXLh55jU4*X(m!1-OJI!kH?gBAX__JwA!u&JYBz zFkOyndAW+a*}Pm8dIy>}!$>O~3XI@&E!NFc(i!OM`m{L?Kka5c9QfUuH|+8w2Y#pT zMV(6c%)l^DD;m+sDTA#GI#0d#2uG&-J;G@|-&eYrK^!0}A)-J?5*hpbhxfI8&TkFuOR=!J>D@wdk26y(3$Y7bt4A@(Psj{zj4bWf- z+TR4%J`WIlVO5y<+K*AUOTPX#kS7B*&SK>aA+kafWtnAotIt|l8mQsLO=#gc6?qfo zNsZGgYshvd>AG8`LujEa9yo{D;;l+eyj|P$>%*|~|7Cdi>wUcW&jUOETFo0{=U?r6 zagLogWiPX#YO_IuJy-dvs@9J43bs<94~|P*#U58<^^oADNJ=#t5;r2m3pd>Nrdt zOu#T^y_Q-;3AGGkuFGqYm?7C2DyYwpjS9NlKr>ukiQx6~!%26W=3;spz4o;uqiBg| zbNF;$X}!o4KMbEcXDTbwJQbiE@L5a3 zMf=eBTK*+^J=!l7HRe+c-|c&}kH*G~iSZLORaltpTssR=QRznnQ}NjIFlub>oEgCF z-Xqnj&PTJB$^1=)Psv69g#rnd$KK%|hg`1m>Xtaj7t7h|%CWkRj z*{LrSJk4u8!1)Eguv8(m@P8%fJG{HiF=D+&-IPUUS6y{D)#0*BN4A1j2O`g+w$+JN z>PSj55MqYPTm@+#y}cY=uMLS!OwKA>@@R>WJSi@3CUpJC^Xv$s`pWE@XFM4r+Q6e# zJKRddvpot|J;z7ec;w3+wPv2_p`Q%mqgGLi_uAe!qC$J?E;~3=HO9i18D%~ozkz@i zY-z;~KDkYZ{S|`#&EMn|wO9hE>VvZC`5j8cU$7=gs_52Wsdiw-?8eAgUju@qwhx(& z5E|?-z8Htus;J29le-@&F0-!3mDKU!;9sB)oWNNXX8Y#mh2*7hXB+3bXvCPbTg5uM zouL{Go5qgn0Y4bB1Bqs0wZ2k6Z%%P~KOR=NF!&E>AUPa3zRV`JYa7Z(7_t@sRwo!t zMHL5AWoUpGkA;i?G=){od;(^-H|8uZR1?Wtu3FKqo8TZyXdw@J9Afd;SUn?d!-d`5 zjJx90R8F{PGob&lfTgY~vLIKC?#x+Hw~tL>Ezepo6D7=>^KC8K1p^NOK@`Q>Eq+&| zniV{=aA(zr4&V}Nv1olLk7uR!MMNxvt_uX+Y@JNf>WGbe^hrP!w|>=cHef)CZ?zCs zs~VZ7%qd4u#Db-HXXyyU_F#zC!VFemmW}ayq-6E1gU>E4eE_Us*9PIhIiiKGV~w2y zL?-1&Al&HdYaaj-oA9V6E8TzEAvJLhJGaRN=Ah1=F^K2eM=d56HxFGR$2h_M_!#jpg(g5{1_>180>y`uwNpL`~)|DaHQs6`a>X^SZ4->Z24vK7r zR<~~BA(P|D&O4-sB;`pm!X9GUv11I;mus9VLia|w5L?YpLBKvE!_U04>FIJ59`;1d znix#N0_P(Hg`uvO)ZS_)FpLo?8O#<2(VVI}`L@;2JSbP<0SRSyx$s9@gNmfALZiCmlR^5h9Rfk{du zEVgA1zp9+<8s3oXoe~Cln5d~AhX*Dhkg?$ zw9*oQJq5+x77hDu!DhdO+N{I}x~SFQyIG>y5se%Dw@v6^3EHR2ryCj2A#I#}=oIms zg!Zc04=_ISVZ9On=i)?GDS06S)n?Ex~QW2)(c+4)zvItlVzftoa<|-)8+)6j1XT;Zrmwn8@D9 z(JX3|xd}tuhJsmOr9)hnxXveaFKX2}rt+*a%~VETdDFlD52t=@+kgDM_uYBVo$oz( zLpc7N0OY}m`zA)NntJlrMh@P!bnm9S4qWw7Hc^p*MZD`cCH6e|Yn?ZpxOe3DuliWc z`wkU!4swCSf$G~&Nrnm>a0V2Xf~IHYjRU)NJgf6c+Wn7raRtv^H1Ozd93SAn zC+Qlp*R2Rdj)}owmGF2-K_P6BN9boY8$-gv0KES|(|6MJC)%36IN?}tS_}+@7R+ix zxQhAlKnQLSx=%?ViDbkwSPhem#^on|t#c18-_zgnDf+osL^lw57&EIg42o`qr*MNz zI?8Ld+=;CQ)?v?d+>Uky0F2?ewU-B$33w>C#|iL@6-*@JL!^WZ&N13hfM@qsY%(!g zj$r|K%1IyW(nHOtn>NmKjYx>^2_?8r@e`HcLGdUY0Hr1^Dm?{G3|e^4QimdPH8o6) zK0a}tp3?>XpT__itaH1Cs}v0WKCL#ha1XIblnIepD#zuq)igsE4ahA)EF5USMXAA@ z=xfc;F9K)KMz*eLVR@*YFH=8BytY^77@fsN_u_zK0=1G1ZWU)LnFOQ56)2172nB%- ziOu|vJ~mVE1IMrFS{GF()ZsC9D;9+j4t`P6a`LfC$=#u3Oj*-*Y{QM|;MuE~(?%Bf zM;glS5PlKa>CM0QH=nrY6Yu@+eeASnD(ZLOUu7ox))0R2P|X_)zj(0kg{ml5@=SU1 z6kuHp0K!%*&&EsR7+fy348rN#gapJd+P#!b-!voM#xEMdZ}CMYjgrX(TgvXk>qoW% zgsq3Z9~Aj(=9Sun5lP&(zW5SfBB zR2~1BP}w~oWJ6>|aZ!Y9+iw_K6f+kp9NJHrcf1s44h%N?jjAQPuhWScV<>-RsP)1! z!-va+TC2nkiTStXh64 z96A`s!%_{#OqS|7FQ&8cv&Gt<0_J+WML+yqu~bqN6TEBE)_}8InYb+xvn{5ChA-0z zU9{3hqe8>CkYbivooa7nw$0y)_EzP;?Nc`?HkliKcVekPBw>tf;Iz@(%)x4s;6L0{ zrSZ+bJ*}Pwa)%vZckUsbLYkg-D^VDyO)LuRm+ri?Z*6wu(`~d#l|D_*Ik^);Y%ez# zHhSH%k4nQgjORlP% zE4Ke}#G7}*ROlgr9<_W>CQ2*;drYp+a?6J`9O-)5WwDaPbrKd=`eB+aU$ z3k4<6&Vvh4H{GxpqAW#B43f(&0reKyqV@C3R%1!ncsbBmaOv=@98E!%a8EW;B>&Cx zOpMrSwavY9@n#!h+25IvgGgc&nkm(Tve(n=Z|5YSR+e zL_4)&d01KUp1Ki3u@>(B43=zf(yTL?nWJ%=+mFZz2t$zUn*OfdHmPxBs1@G@my7W{k1u8JNp*;-l$||(x9Ga z%9E!+tvTML05goQ7t=T2>DQXgCwaNU?FnXzqK{H@UH)RX6~}TeOLR)c*w99^yu@mx z_m72hF{hDt#i}uAY+S?Ac!kJ^$oh?y6Nb`w{Ke`p2rp)5;Uz`zL^LwXeFc|jJn@oO zf)fo<++WAQ+#-1;jg(key&!s%&8!#`xEFMbhxHQ!ziK(yVs#i~*(RZF2V06di~|mr zBqLT-ESE|(L*}lao<9)tW687e8dCG775WBxjnDDPKIZcVrsgni-XD9W6xe9ST8Dlz zh;dm(UkP@wfBfH`ysR_+5uT;k52ixVA!c6tzj*s|rN|I_>wbE!4XwA|QRYozU#Mn^ zCiBwYYF*K(JSfo1qiwh3%Zg1rT9j^QYM}v(?eNee_?nrj!PvuRuZrz*X{h#{M?bA| zA|IdeqL@IBujmu$6CjZOO2oW+*``or+RuLO^zyq3bQlR@KsxP>;d4qEp5r zhh%P4bWrf@z5$%g%N;oUTlse6;bCsv5Hw>;^}kZsN@w41Rz9hqFsr%56#Ji0L*=U< z$tOQ7d$Ue8vNwC%h|75U=VENfu_83e=UC`|K(pO_+~{1fx+vyXB-fjRV{N#y%oyOh zzKq;511PqITdmgp5;7}*H#_F(_!w**k=lNmV(uJpp z1FPCY=TLscEMamdTyyrDZG$GLSD2qMxwnA0I1GpsQ&|-@cHr=nd3E-p$PM0(=SuaF z$J?rdK_!jcNuY=j=8fwthif>e*4ieriUFzVFd zs^IKB6(c}f5MZbkKDq8@9x$M$f2SQXh&nL}?2!vY7*~Laffu`0+{inv`lXOAq@&z~ zLCo@x>%$(R<%`<2cQE9+L(T;bV+hY2KR)YR6XeZCexmNChO|5GW_{_%5DWhBcZ3bU z6FzF^ruG@WJaIXF#t*fH!Z(1w-py^*cq1(R^MS+n#IFXhTYbgZRlYi~PX}*;T{g3~ zdUh%g z{BD5KUYaMU^)TEv0(-aCqct|1jyo+zZ_Q5VvM2t_n#KB=60%_!lt~R1 z+T83$1%kJW6&CqPyRzfSKD&jHHKvy}&N$1WU~MaXt$yQ2H0LHZzaimq_r#?h@O*#@ zW#G=`MqTI47@y5}ULN-9qH-g0=5A7X5G8y7_U{x#0pr*?8vso@@>~PMZa``AA&BKq zPax?iD-E-t*CzUNgRV|kK5&h6Sn?*Y$hv|pAhdrb$2}4snsNr$gNgy z5Meq#naRE%NcIuQvTyN72To#VTx>}_)~Z!l6+sT-tT~`Xy7w^k>|Wcu&RM(_tH~GV zV=Ym0pDc+*xqbHD?^w~h!MBaNh`ud^qg(xg^<=ZxW+y5Gk?%ZQklRjGi2>2MFms38w1wd1%pcKO zxLC-#xtG>5Mk%$c#jb5DQ%paJJ++s_R%$Li>1z#Zoyolm6IVnMiXo!eG{i`yMj5{- z>+&9@R*Qc3HH(BO#9f$54D$n3DVxn)#PMyKId+uIX6ac?(@F7)rBO@Ub*)ckqRoVg zxzp?aw8|sogi=QSCo*6>S&?=-nAMhIP^hi2 z{s)s%G^eCIA&qWL*h8$&90rIsf?>45jUN+8>oU&qzcH?K8nV%>S*p>pKovDsD5S=C z-f^VK-91bFhN$a!<#ov6f`*3OP2iB=)NL{a5R_@tiu^#T@8xYby*F=NwxhTyhY z&8%XbPTbN`ER(}TkNMOxFg)&5Sf zf@gHHGw+7-i!Ylo)jM5hWf$z@#%$p)=cjEMQQudvP;ic{UKS}4Lkuw<5FbU{*^x0r z_otsF^?jw}OQu}EkSzd#&4<@N=Pi+t69vr;${(R5xQJc~&w(Rjc1nlGSSMOA|W_2;D|~4Et+a zwEdMQkSwB`M}6H3dFry!pMBBgSC-P5SfL*-prt)wKMlOmkB^BL zlN1DeF*s$veI*#NSNXiK@1R!eL+t3p0$?ku2T8!YRpB*D^1;SP-yui&PjHEmV#m$puRY?cN z?XN*O{$q`i8!uZ{Z$pMKi=q;7R$&O1lZb7 zCQD-=BCb~IBWamUM5&LY2Uv%{SW4}fxTZ=udE&~^gl8wkiwPg#2ClD`{yQJl`n)9O zGjOYst=56o1?oM>bTC+79S~C!OCDhUG6uzCfyhY>Ww?2Pr`^U)Mnp%z#U1Ja7uY5*#U0MFp|~}H=5P04SAd4MSYDp zFE@^-qa*Sz9yu{F%1>+^>yAkGHCo+6)zH>ZwK%#l=x})Dgb=Qop(1!V zL&#YeY%s7aWnMMan+ecYZBgD{J)>H!UUGrkUTlUjx#|`|s#hoxwVQ21W7HlnWFutP zSBiVdYF(_-ASh(Dq8<977zfxf_Gm`vq(v9W12VvLVojLgi!>)@7-t$~Kf?zZDt(kRnc?OD=9rX6Dpczk0Q2;@f23VT1Y-C4(zko2bo)9b2iR` z6}#aHI_ht25jeptG563B(?l(s&=41~WMj5n2L~O|&bgDIry=8>W|{KEjmQ*0xk;D9 z9F4iZRhC$_8locYt5ldc85RhJ^OJj}e;?Y_h^I2C@r<0GS~P*lwH3nl<4y zw75&x8DFgHjIpnV5T-}~$t++2eP>V`qirK0!wW)Sn|u=&@_@gNvEwsoy_KmSg%-)?F5tP8@kdCIPyd`caR=+`kY0y(m9mrd0mYa8OP;S=s zp;?Bi_TgnHOe2gChmK5+o-aNs(~SO;_#B{%-HFPuAzcjTVWr87@+MmqGdAy?8&u2| zEr(BS?^;x})X>mk(NrAE9vs_B7m{iu2Sqk{w@@sGRoIHP9os7n)YQ)qr3N5~IYjOknT&YD9e#IT43@WeN6};HqMkQWcpgLsooG9?(o)|*Yvv!9U za0LS)C2=`E*OrdkL|);4-zLH z46yq!7g8e1f~_Tn4*I`?W31R%-`uEp!_TV`yA{@P&i<#`IkpTBJvI62@1&-yb9H zJ5F9I6H%&W^5SeFoRK*{%W?1ew%bKaA>bwfWrjEhY)#5=DOR zqfK!$=vVJp-)wT(eS0q~i*tK9jNde@EHRl%h~sF%z!EdFiy;AXFl*0oh%Z|-dYlft ziqJ^EzBpCpi#=m!)DdptfeQ{7;Dgi}lnG42@0k#ObEbN6)&;$;g==2>3X|O8sdkqK z$n-Z(Y!5PBa&UP9S=^rQ>y3p7Kc&*``M#_)A#6x8M29(&)(iLLh7x{-hV3q4>N1De z`owc3XVQ67csfGTMJCMQv)sG(*(WY5-Mj{Ccq3s(@d|m>q)-*zs;1+Yg``5_43JcB zjF8$(UA8__h??bkfDMRd*C3D;EX_eB%jl>*Xepn_XtBZ#*^Kkf+0~eM@-cXN3y_ zEQ^C3g5eos7;Gfwv%qtaAEwzFO*7koej3LkXzKl!Cp59%d&v)ygGi&nc&>rSbZ7%h zj1A6Gh^CH~6QGrp>chnKTEw+!$W$^EyS_If&-fL5T0mIHGo3qPxJ~^_ev0^@XjfJh z0oCDL6mi8YrSu%3SslaaYxaaYCt{-#EwZ1Cc#l~z1b7V>(bm{*ZFk8=iATbk-D%n} zbE}cDf%XpX<h)SzeNFcR&7<_`IHTWX)VOF~a`Gd@Kannij%U9Ad2Fe>-+}L$g zcM3{dW3|QOU3sHezZAR;yf%)pI$>Q-HjlKlf$_t~u@yacBBJ|%I&6Q(gKcqYWrAa7 z$1I91EIPNGjw)M;sa9c+Z{U#T9WoGo#)fbA{R2!8P)zXyhePqwc_H3?5HMukmwk-| zJb&+}y}9c55{{X9!~S|^Jo$3ERJs0^AnWRVZMOtjiR0O|9F<#wc>fj?h!0B?)?Xh& zncLkf!LDR^KP)Fg%kA{HCr3n9zW(|ZtJlta$@!M*Tlr)FitrtqV->Jjs45^ z(k@Oy&W&wy6QnF#?pyG{vikdPViRiu zjUkzVo?IyHGhm=$W#XbxvkrcmT|}}b)|^>LXh%spWoO6m)4mq0>WpfUF6xmAMcp~o zR1ShL19YpQs2K*F)(VS?32A7ufUlMfLgkCf>yz@WQHS03 zPLzCFE<4Q!6q2tYnDT@vm~NUb&xwmtffF*ZxFV<{Kr4VIF>g&~vEE$~%dF2>vRf~4 ze}gvENuRlb=``Nt{>E@-%WjyevfA6ib?)G~z}6?Azs#U-Q&YM&(i!_&Ujcnk{^XhR zP#)DUb;6MsrU?zORz|OQ7Qha}bMU%G zj!jB$)e3Xmh+^^9Tu}gXGSaXm=N_ntTMg)0oz6yrZKKhp%1Hfjj8uXgtI!cEjA!?e zF=19$Qeb~WoNb}LKT6O(s|^i~oZ=I^VIR;tT*MJ|{b7XbSye{ZRuRUHs0rKM zL}V;geIs$xCjt?6D19#{=OddP6#iM`Ai zxC?Z{AI@x~D|C>qBMV(MyswK+qb+FSf~extykK!MAr({`Lu9;!7_$)1AtlK1EOOPG z$KAOZ?k#wqT9-GJc?p)J{BQ?p>v-J9jh?!yzD}G^UMeTcY{)Y>!%mu%IK^0 zAgA1*MBPChuoVz)U$fNS|);tdLV^ z-;pIU+1!;mSX!f7m4;~dUNV!Dz}(KMZGeltrs>v{(zfQE`S3 z!ij{gPF$Lfb*PVKn{f@uxTK{ANV*V^8664!p)uJ7?=nkK3}jXG>Q7gWieTq5cMLx* zHTPy~&656RCNOWXHP$B*Y;qJH;gsgVx5a(K$(0GW`!@UXVM2U%P z(@#8MOYkU1R&F{~JQHE8x=ls1)nl5@>TU^rv0ZFgwPXhE&B|3S#}2M>Eb>z3pwMDm zWB=_2===peSEo$tXb*!ehEhTn-6iU!_N~LK*jd;9ED%=qFpG{NxC~C63u=#ajihbf zr@*NdqOSdULD|6Qr-C#(eUi;%E6r7@Dq)n+O$$)9i#bIhj2CQ&lR6&l8i|VI6>hgI zXc`zxRnVl#T$FdrO^iNV_A?z<5sWd%kmxFhD)5;B(h&6;2^-UB*(%{%Dk~^!56_BZ zomVNj!1Fe2c$YoEPGPXxycboDvZVFEVn&{GXChVlScgqJRzh(cvtvcpbC+}|U-MTV4c1!QpNq+m#aE=g!HITYIM_H{IOpE%!P%Kc+udCpYn?>HE<=z241h zlcRjG=N~EA>n%=p_N?_rZ{D-#=CxjD&lC3W4{M2Dom^V@fyldMZE~v!pXA5diy=ML;dM%O5gliRY{}a;YVsIU71{2`2OT325XJM+UB%PPEz^yTYHeE?(46u zH&1FnCU05ljZ*05rQQ~ZSFd^_uf1i(No0B^HRhwY@@lEK>9v!*;Y%9~_IwYs zu&17)<;k^$hbMpDTC>*ubB&WzqXA&q@HbS82L7frZ9?%L{YuGO)_P;Fy?Kv{EJD%9 zEf99G=*!FVa&_|G8Fl%mp+f8Y%{2P=wIjDQ*;)ARSPh#Qa^yu zrsg5V`UGt(u%*eLwuhQxy|Ve@r+(Lqtow;L2xSm2xjFVF6mJ|jsDtm^x;nY}=3Duu zei?pavcnqcP>PwdwRJ0WcIYG<<5qUU&HSXM=hAw0{rMoVXGJyZq+lBtd57W$dcQV# zacIC7uYF9#Tl91fuh-eejWn_~#W$?*w{?#mxX~I&ZEg=IfJdS}%MWdCsl0F8;{_7La-hTe?*gGhJ}; z!0Gs;x9p?M^hfT#nitko6ihDrkg9#0#D{Ke*r^{fs=hdR(*AYfo{4r7Gf!oi8hCM9 z;`7J3o<5K_@uT?U%iYnNe&hAMQ*Yb$_V<7C-Y?$!Pk;PNe-Bzs$kd3wue<40|MgE# zylv!f?p<2gbnk7i`ewM_M!pM7G^|8wPP2Ksq-|imocK$0x{^p5= z&YR06=DX{2OI?-v7Qeld|JJ+rcSmkgn{U7OiG`7S_k6rmW%+}D>2`Ww=fBnPVdpn! z=KYT?bb95l4q6j`)g77XeM3JMX{7Ud%6^iv|5Psfx83um=6k*QnQnJ}ex%TZ^Sm@rgd$)Ya=$m;Tr^+nc4_{9Jc#j?X%? ztMQ|??wHp(2ltviRXkpwQv;*3-7aso%u;8!JJyZ#Y@MCAU#Hf(BUAI#IJd}X(64*x z*XPRpx}&>esy8<^HP@Tz&h+@==cf2=syFYCy0i21b2C%%AGI^1;ycyfRBW-k$-cc< z->OXdex^tN=6dwQwgy#q(6wUeQsiy|j2e+w09v(aWiB zSMtOi^j4yw>rfW^=73@lPjUOEUGcKkQd-NebG1P=^G!8)v1g1-TW-Q=+dKE zNScE-t3Ndqsy)F_6m5q>sVBud72m2hSRzv=8#mM)UfoWOpGH&vb{Bi=-hTG? z@PBq&k7a12C;A~IO~dS?#sE~(*CVAbpi%3+#y<|emR1^Io70-X*L;U%R33c(TIp_L zZ$L}NGJmPMFIe8IED5ODY(zl+oW2Po7M7813D%g1do-0a`sbLCZEON<=ULzA>;thz ztJ=yG!=E;t?E@=Sbik%WQ)=aVv&(d#H^b;RNQgVSTO*HQ1NY_`3HTV?WoDL@mwK>G zRhAi+6*&>V(fjxvoQf%rKc5{K5VI0n@`@QOIM1SZRb-MyQF~{*OXNfz%8t;kn}UPtM zV3_S?cu}u6mx-66+%~+3NTDyIkYb{p9}c z$SbaW=Zyz%{No!pUGwT!Bs-iTE?!Q)`kmtk$KO5Px$%kdO;_Jg80tcS&W-N~?;oQ~ z_4B9WEx>AS{_|Z{P8XrBjuyE*m<0D6p z-9J8ZXu(IL+S_}&+h%&&W zdU<^P=#y&aF@AZYjeLJw!aXn`(9=T&;g34e?DLt>$hQ3p`=|FGI<|1=@$r#`Ll3DB zYvY}T#d1q0d9*s9HL()IC-5b(-4^}suu=S5LTHx9n_(D^Q(+{~xa{wQ8ap$B)7z0- z!m|i3AS6gK0Y%0{-RI}gh5Zc0^uqp!#jO{;qlrI*%j%iA+E}VZz z<*CN%Wk{%OVG{-a-1@ybzH}SUN}KH-8*U~^Vv%mpD`Z&#{pRKuBWlxp!F+vs0(wMq zm>TmgM?gsLeRP0@sk<*cx-dRIy>M)Lnn}{k?4O3@V~6y&Xs5qBV}GX)EljhTeNFH3 zi99;J|JZ`{cYJ}5j`5KdvjJih;zMfoqTb_`@s-hgAp3xi6% zxl)%6=m?}rycwJ|P!OhG3A^jEza6aDn;)cBT#L;h%c>?m}{4YftZjxE+AQGa@yUHU< zR=T(+}DMptJ7oZ^pJgBIJ7#x<(SRriVuzYX~S@6Av{r;kz=8gOXHo}_^)>H zZgCE?f-W?#Wz0R=PI9uv!f@MURwsH@W5Or7`LYI{vO2QPawrQS)ov!Th>DylC9m$I$7 zMGJ1>5G#?XTN~eTjJ>G`0~YHL{iBj>0{i=i;G3P9fmy;jE>mwDZ)yUK?@GY{?+TZ) z=va;G^Bn*`^EbOXvqO4O0L$~Kmt)$uykDEz;*|l(!$Q?AGG4=`+iE+@`pYJxt6F^9 z*Iho?K+>F=r`hB-v97GW2GH|BfM;O$y>hn~88o1>rfP$rO> z<=&{ktea;#GifuTF_~q6WlvQg5$`2Z`_TUVFhiyhZhA~2oW5B%Um)HK59ROu`W4w8 zI?G4X2qf6;q1F8tO~bWRLTmtAz%hVYbzqm=vy0S_bnWSiSJ)t7(EIBUSMp0WF8|6e6wAJ z5_R^-WnW|;)hP+ot{CL4~YQOnjcYR9u>AUFdEU}sSk=|7JT+5x$ z7Y?-y$oIOVz?hlu1WVU^XX>l8{oe7d`;RhR$hFn+2Z}%HD>^8E zlT~@3DY>9&!@%FkT9bjdFq+6Nh+YD10cLfkE;Yj3BwZAZ+CaSlxFBm-Oztw>)Tv-j zk=2rH!M+Bm{;qF5NwWNCW+4t@%O8fgZuf;AJ9gbHppm)dZK z#7`Fx=$>ILiJ|=Z{Ac^jefBD1kH*)AEk4ut@zZT9>=(FS>5jhg)z{o`JNCo3-MH!c zYhQh`gc$DYZoY2vs);LZ2XVX$rEhV3^OY~_UjORFQmNzJk?XDzC{d9UKG-vI-9&tkeeDKd>s8nF)p5fWvCPW&=$;RK zXb-Bu6*uI?0GV_1f2|*n8FmvA6HVw9zx4hueBu4SR5r`JFUa#Rb-%AgNBr2Fw4EHOc-M4V9`5!_m**vHFFPJANLFoGHrhD+&1TcYmOL=&F}j8}>9T>H*dKI4~gA zeQLZjy@csZ2AS#o)B5vMfp{8u>GCghURrMKuWYLuAW%yqJ*+9z`NaSn;QQ9b6G9Av zu}jiBkAd$|2Ra7sF?Su~DGJKJgq9vJb;nz1#{}D8Hx3ER`snBZsf}R;Jov<%< zx6RJ!HSTcvvSorbtK+Pz(y)ijE6!(bcSQa2I)iIW5;dsjJ;Lkc;m(RA2lpvDygWX7 zXhG`YF05cEKPXvJWl*_TJyPD9r4$S&^_MZi?7ti|pw4e>lg%NW_$ zFUE#hU+!)dalW4T_Czpfo{4EP$Ab*WVm7T4g(bWWDsE$yi!@t;0V~QmK)(#z!T$1o zjrkfhV`bc9>^_D~-)<3q)=o|POA|d7nh5(#@6AlxGF!$+*k^cnd`-6RuL=NtZXWpJrm8g&kgpn^>0N@0$rf)> zrrP#WQJ&sQ=;hr1%<43?sf7gbUUR-J` zV!{R#M`2m&ueqbKld? z`F}8NJD-~#>3o2F)_noGe`1$EF)u(dWch(T27mf%FmUh)I1JnEZT?roy7rQWvGz;bVgoW?G= zdb2InypUn=YC>`S0i|f6{@jE@cc&2^p7p-iOxAg+zOET!7((h>>jG_s{X#cad)ukq z9--c~RJYzcPhu{PnuVySI*_qf2juCk&k;jReWp3{ysiBPo=<`XlX09<=yhFfo!KS13K=C;1qG~w zO@Oea-d3c)p3%#Wlwx3){{4InNxrfPd~tdxwN==GuPsuCC1@3yLJfo=-jjyr`fIw| zmhyx4daCL5L)}qz>Ri_M85Q>297NnfXR2CZgSX6TE4*c95i>3CJ7yts$h?yE5aqhw zdzNZ4w@C)4OUEh*<3Uqr*c1-1&8<_gKXwQQIb3P>!yE&qQT2AgL*WIH(D)p8V9MQ#_wVc**{2b|Nar>;}mUwyV zbMRELW~3;Onf#1#?u-P(9~xgOjLcfskz@ESPAWYEkJu04_3g3kH2-0Z`o# z5yubTTgp0ee+!oIuQwWrV6qa4-GW4<5eO7XEMV>6!vMo5SiZh-Z1`B?zX6z9Oi=rDwjD5Gj z9@PN(B|Dvj_@nm$kc0?&JDFxCVF{{>-EJ;Xi||8wQ*mQ3jx9eI>>CKi*#q!iB(=_CMU#SwUxe@rbK^m7mx$acl6Yw> zh%MG2R!qe(l?AONR4(s=5$)(Y&E2Ec+69sg#6f3O6yz z)06NWgbi4G5Jt;U$~y^yH>WJnTVkBqhKNxu%f;TP|5YKWfDVZO4OfXIE5mn?)M)td z$#n1$C4C@?u{zm3Pf(#eP?$N))>EOV7|Ldftc+2VbB;a~;Y6)u!ru0)L4Xq?$#7DJ z4uB&rY*sT7K(i?!QU5|yTSNaV8|B3Hw$;kY5UmoTUy;GqBy%VsgmPF{^+9(DSd zbjlI5uvI||`Lmz`4Ya?!Q5)+qlu7=1azJhYfC$BVvsSz}`^Oba%v*>SvJ*(XsmBNu zO@H*4v!F$A&!ZMk>KLe3sqL8yHPo{Lk=5H|>YqMy;8uAI&Sbxy8XyOJlcLR!kLt(6 zEkN!!fp5z_4%meczAxtoCzRI7yP@CYyJYLm%_;4H0;qF7TyY4gE-`wY*DI<+!+9j& zG^*sUzABr9jn_BDdB{-P4|FsHDTAMDM(Jwo4`cEVD}bp%jD~6m7c78Pif4|=Py)US z{Essz^jbEq?eQDNz%nV!&7Vv!eP~eQQgx%^pSxTEh2d=g$R#SxA0A9IKa)%|n7ouu z0sT$W5v}ZtU1e&K94FONhSU5^6@-SjiO`*?Le+PvLX@2|$B#`KwZS>jxnhYasur7) zw@805ZA%J0HCKx%l_jLc>r>h5K;xpNmolUnJXh9^g^Ldca}z#{vuiV(ErK97<;*di zDSS6X1q0vhwJxlgueh&7i1Z983^ zWwwY`&4}WAJ5x)&*o_KZv{_N@WD z=-{=$UbPiqnwScE6_fS>Tx^jGe^`=fG?J;U_E=>1n|Pk2=Pj= z&fb+o|Bt|vpRl7}_ltwPvkP0Eo5x{fS+81-e$5+3S?-d04@YtduRP47Z<%e1*uro0 z*Vqs^JVBLUl;!S;fLW+E$1JM$-{gWf4^&pKPG;?&{;ReK=84}6kY%NNQV8bp9KrmH zl+oh_ousHyDx>N5mO|CHjlcA!U;fo!zUj(wPg75gFb4sZ&MZ4lMqG)6fK-47;cWr{ z38~l?xWMczbwI@e7l4q1&V3;tC42&I;;-bq;slcgp^qP1DEDFH%3oRe)sbJhGW7sP zB-zoKUGMGkkeC=FBiz@AVXi1)m=*|w@{F@2+chXBSjO-MiB*Gp1x6UC z;zU+D4is!&6QJfNgHsYSmW+@B4 zvrrWT`*{yeW0mk%I$MPuSF1%CuQ=J}BtNP{QNQY>{tp8?qe665Ivpj|;-H=2pe7iE z3}Uk|o_!~$!a)sa&9GSJS>wc7XIhEJ{+iVgjyfeW4Ha!Rt7Jc+_ObyMZHJnARCJ=d zOBS_=ptKGQW>rSjKh`0rn2$*Vdh8fUQfdd(5YlEtNHvt64n#U(saXw7wH$8p2rJCp zetKT1l~%^rbwZ8~CA1W=)Qg(YQUrT_U}>fM?7|k85LVw1 z&l{7#m>igd8|lIcB{2z(i*ZE8&KfoK!NJmqcc28MBF5Sr%JT3~ zslcVpdY2u^5B$v%Pc0m(r~F`-Opo((3-Ho;J0--rVoi;cfvC(|;&j;u3UH4fNRnCR zou=}ndyS^K;;Tir*&xA3*ZsG5-}(7F z-~C@+c5-~v6<1yzlK5sL_Lc6)uiv$_Fml&_dUCvT;LPscH^fa;&wC(s8@=GAxp z8|mnOL%naST%yZE&s^X=BWyrD(b%LLhlY%MRm z2*w3Hh4Bo6F|`58NNKNsQv{p6kG1VoFT)K7(os@IT55vi&qMO(8%a*!oW)>xE0Rkf zyT&fqCK*XGYpZ*Dv^@?iQW(VrDj9b|`iPrTsJEl|h~9)HJk^rO33Ut{$_#=t(W}ZE zRiaGKh^f~YG*iaOH{Q!Et5o_qW%}HDD5yl&bHWBKN(VIobjyC}uq{R8D-MIsN5tJf zU?NL-{#j-=t*NLO0CuZrxw8G4UfN_f?nOE9IR@qyL63E_ECYrp&3>r?5NQ^S6%!8h z6L+bIV_>zYG?5iRE*qvg$FNm$7l^)*7FHz7BT3pYyc4D2C;bJEZAXTvI2IG`V;VLx z3v^AIXKhnkNHk&rAia2VM5Qd+N1`xjiZN)ejr|_Rgdkf73GXa+Sq|E=_FJ%tFUctni z&Bw6dK3sTJuxiR@&6(3VlnQ%frwWYXtr1A$xW-An6_bjMFcYM+29aVWhvlMWP?YDO zpbwFPocSm%g;+#0MKb$Vv5Dxt_WyhrqW4|DaaEJ(eI`P<(}yo-8?5}m!OH)uz5Q^P z1rS2yni0$YgmH>{%F`)ZfUa>+=ox^8@J89kSd}D?jA3)-dfS-A|1`G1S_F`=0G(NQ z?Y-GgE2vvxs3iaWK^8w(t-cAjP`PuWIVv!39g_A@V~wBDPZqxdx#>v=p3g_48M7SG zh(U61Rx(&;l`N_6>@LR=A&idgvfA4*pVCrByi!g#mBptp#Dv{y!$l`+h{S6Txes>A z7+Gijuv+YLM8V!-xKr$P=lI5F*XLhD6p0v9xc~sLI zKPdma1b}8P6>_pzyjV#QGgQSfxq*)^h<0@YP6eGoR3N8w3}Spw(La55#(+tzuOd3qe5fg3%rdrrW>P^dN&`bi$iDiSZ-u5V*9 z&1I-T)+#Tk)mcIfkr66)Z#6^HsBEI1#fg(^z8=&`O#`#-^1~pNeXBbhjL^OyKbAlR z{cIb*@}^(;)n7?Yg4>h=R+3g0G{eo-oDXV3KZae1M~@JwGOX_Ng;d*fHXj%p)4_lX z%9tn{QyTCUr_ELagvQ;*3y~}rKr|f`b1R0DtsW5?G@?w|uofuD5W3BMuqwi-95{t} zcFQDlp7>ff1r?{`8l>&YA&-W zP<51v70W^*;Pr41yvq8TqU^??T+3c#Jg%i>8KT%R1SApo<0DG+w^$hZtpryM080%+ zIp_=i&-V%(B5udB0U~ZBma-d7`ejMce+FD)LnpS$51>{}=x>b@!&$ans@OWyxYa-+ z{Loa}Sd2;B8T)~?!)8oO%`nhalVIwR0)1g)K5AYGJXjJOSSA3B!I0Z8aD~bUnX8AX ziZ?k*r$t~*m{Lv)az$fsrPuvI*!`|S^2eLhwo=LU`9I8qYeOuGUyxAu z#*R6?rSFqxDzAHbxz<0_ajkFL>^_N&_G_*D>*E>!3I-9_m!ECa*UAyhg=CG)>|+Hp zbHfkIJAQ4!u6*3c*!Vayw(xNcUvn>MG8V7dk&>i40k_N7gf;NMk47GtsH|gwU=~xF z*jhnJvNJ_}5vnQ3qHKyyd*&m?Fx6BYza(zLT2X|aUAI~dqsVU7YVOWJ#u}RuPti>Z z1y)bW2m93SLT#KOhAn5nF&k??|1CA9-X+B#G$v!cq8i#5HR~ZV>MTKOAD<2}Dd>g` z9n*PPJHOk)&OfdwiO9}EuPrKK!<4$`JO!wCJ_vzz63GZHo4*>f8MewYoe zul?<6+uKJ)z%0TTHksNAG@lj>5t304ApjnaDuZBVf=Gel;>CE~)yQvs6r?D`Xkjs# zg4vhu4_+ivOp~B>2LoG}>u;6S*+)k)5bc}S<%^7!^f|ia;*x+kf)QA2QHKPAOMh8BMGGqwX}?3__lrKGFj)tglU5J;1jWn?_Bzd&Kxdagnyq{Q3Tx~oRZ zvX8RTY1KAq9JdRDley@erDy{~7=qmi%L<(5${ZAz@^mX9hTMCKn64wsWVZ?^Pfxqt zR;D8s+LJ>lfE0X2A5}P0z~O8Q>iZ>BKA<0u=wM{ScEFSbAHwYUFY%Y-ME|f+C9UPt zU!S9*K^A?@EEH2~L-fUn*D$o~H)c!I8q~LKJtAdf{k6O>YsiDjiQqL}SFN zMGHs;OOW-_DEotFFG7G^u}BInp)U53as}IQg0=2*`cQ_~z}bM}NW(Q%FCjq|HK#mf zX^ZDGC71Ba%8B?qbvTk4|1A%Ks!NAF3w1nI*Mv|0O$g1cX!I>cDFr{C#<OUwfxgBlv&9IUK zFGXL0%%=h;l}}Zq$`DpQO=3gFU;3v>-71}Q z?VqM*IB4AhkZR{xKjfK&$Up#8bI*+i$hO-0yt2KNAR}e1U)d4ZQol-DEmoUm%LRqI zPfOd(Jg?ZtvqQ34DmIs4yy2-0!t}xJC52P7fRj3YA&xmSD`#Q)EmXJCeQEJg;H;pv zCfK=-a1f4WlEev;&-Dd<_^85IL!)X+c@5#C#G4tfOCH&ujfBR31HTPu)?(on(27ZaK_rndu#Kqn`OMwxz)r5okLCf4~kRHJ%tX^ z&5b*F)z1Q&N@}x7iwDoGV$}pEz4=SL`7%%ibaA}TFEVUu|8tHtIc6cqX?N9ygdsl0 z8V3`2Cgwz#4;QaE}*7)f9cXx^D`D}_TBDR^$(ZMKrM7#332 zhNc_~UT*N^Y!)GLKaP)=#aq{EFK3Iz>d#;%X>bs0PvhlmR>$$S%h{|%%Nfk9ow_ra z+3PZxd8*;bPaO0>A)TN5Mz$=|Re;6w=^<-t+XH1?i~GKDbGdW zGg8e>FeTMn^7+A6dpmlT5HjlgE+57BI`R)ibizH6oGOnOKvn_LUBSRsi&0Y3G71(6 z&g6sBxp*@HN=b?5^JEl@xjo_?%S!L@|21^`&WKDJ0g6))gH-&89=5q1l5%c9Fsq6X z68|YdM{(`((PMWswEKx6UmY+BdxSK;mh>8m;HUPIPA37S=QW=u` zV=E-7#IB54X0g6D-LR8FRbs1S3r81@9$h%51y)5S9)Hz{OtMIp^K&~+ZPS2!CSI${ zq~7ZIx~{wB7Ss>fP?!5_4Y%PFfdl+Y2GC?`VL%z>c_x^VjuR}10tnP?2TXB-1eOwl zAIA=P)BWJ!lf$AEJmN;k#kQz&E6Ci`rNufgU`m#sA`Am}Y`4;K*Fd1+@h+>~QYegh z)_YrfmeN}0_OgwD^bFZlcs3ofWi$;)hDBDD6XxhNsV16OQdZb6o*g+h-ClO!J+lE# z48zma`Z*NSUAeSlgZ5P7nx8Nf^8qR2pDF})#NmxlhKSPvrW8S$WgYO>MLKiyKPgo4?R8fqlVhi z4;f}%=*sq@n_uC|7_|wybtkIZr)mAHV5BDoW2EKo3j%@WM$FV(>_+pPYfKcLB`Edy z5Kv01a)+mo7qQ6@5!`wB;9L%Z1(7Rf3T!<#6xi}Lyu*{RC+adUq0UCwd6!d8*%`oN zkF?@3jRh{5Fs(LP!K-Jvb@Ou`XAZ0VKvSS>1@%^>8k*QT=D=cDAXu}?wm8E;&Zrs$ zO3A`m3mjk%~`(hU|X--RpzUwMRs zU_phkXTB?^^Bh);@aP;?bQ{IX`z&5(`AIWYw1%U0ugncs#4?2~^okqG#msesn>iU`>tQ1O`qzOl5sBtNGRt)v(Px8w zmwG=x93~{rpqfW_IN)bZv;#lhX6bZ?uyBPsn=xJxVlrLH3@|$ajhg2RQy>u{Ot_l|gvl zaAg$UPmYgVd3{-Sw>ti;hJlVhE7k1yv)3g9*)UIrF{`C|-q;MxT9A31eM6*g!n1;jE+!x= zA}(`O=e`*4vtfV)2^F1<(oSTgyq*Gr>L_qf`K4l|=a&yvcx{9eyS;Gmk;Z~zg`=c~x7@ub#ewl< z`>98*ofTaMDDzL3l$QXBfZXICO-3yJ!D!33c?zh#81FwI&PqWu7s>&~r;56VFy@v3 zF$W`*;KTIwa*s5&iV!nAGU!mGugQ3G6hKA>-$-9IaGx+&8-dxC8M*xu0JT_p-6Tpc z0ih%fh0xh}9>ODc;#o>x-CS#+h%O7`*DvfKO!E!rCgaT0d>}A`pnVre6&o`vCCG-4 zl9r4}>^Jdd(NdumJ8Y>MEJ6zc`PDvi0vpa%RtOw)jg(V(q3np+8O#viwA%e?4I}OH z+DEd#kf%zGG-^SlL2P6{6BR1AuzE63TV9MI8LI^*n*SavVZgqMv}VF&EI*&MD0{m9 zL_I9ZU}H=~s_L*9?Zf7fd0&m;S}D!-P!~(ZP3|LFIEgi)SYC;IfIqRniFl1acT`Hn zIQ(pb$4m;b0z&T^^6I#Fup=O%d8j+4$}}4f3^y6T0Z^_t;a84q)R}1sVl(w2blxlK z+X+S#8F+lmOB$6d@uBE8x+;9iBijQ^RFOo}CPb5h)&J<5iwHRFj}o>}feW zJ#nrCsv{s{r{6O~hu6Ai2)`_qvcj)-pDTApj%bt+0_ikmAuL?;VzaX2=&|wfL&u0q z;l?6ttM-eoe>rqaHv_GWZ#i_7Yp;%eC3IzVeCf7otl@Xg0J`abpC!A%nZf3g&OMqq zt4{rMjP8YnLkg*x9v|0*OVdXeAozk~JUgmqhmIXPx_>%SzB0aY8`gr-R<^D2!{Z(f z6IO`V`X|ggME_TbA9La%7Hh};@$sX_81SRV7RSdH4ng+9p@lHo%j0Xe5z5$4b5K%B zFlU2U2+Mjj_@yy7ve|kLA*y6=ak5v&w}{MzqpQ>0%C+c!9a{Kepc#$(HvX%n`Andr zEU#;s?#AIxbdQSeMFQwp-Kz_mZLA~NRW2X7rlJIML?!sKA*h6!QUYYrqzHVnIDp#a zok;efKD0Q#gP2m*v@eiBM4v&-lwm3j_l3??B8(b>_@fKvu<*q`)Q~&%KQww;R{GhP z{Z+KXwKHdi&q`^HA6nhNb(-C%J-9OdJdHJcW&ia4L;NNN!xdz$J@6Pl_~ZWNg{?caIGkQH}7T`v1%gjP4c zstTS)UNPywY~1xv0sRMx1hZY>SCPWKmJz{}@WW%nqx)O&FE@xUyXUNrX1M2OmWPa?Z#f<~R z?bj`!zw!9&lZ_--8Mw2*%+*F zos(kzCA&qGj^Wx(IX_JQtM(snT`K|n$brlv%R`oD!CD72SnBGbTJJw*5c_{ou@j;- zr+kOcj%fe!USk5ixVZL5V_^Yl7297p zMFFQE^PB@Zk0Z+v9SM|}>9$I^Z3s;T7m0H%m& z!yIfErzrMe@Jha2yuloZ0I8G-Vx-&qZpiguC@Q7}Xu?ib%hUt1^P~RH^vKlaNgX0? z(oN9XQdOMfANKJ$;UpLZj1B~}SwS=*qHN6Ff+=wWH|+-aQ@J@eEqZUE3I2fcl!i!I ztMLzBQt|j1;*l`Ta8Bh4;H;e{Op{W7A-K~8Lh@qi&ysX#uDcPV;Q6!guC7;SrY^$= zUU}cG%Vp3J2ZymPd#{urPms@d^r$-mSv8chq*mP@onL=dpjC0Axhme9S(gU-v2A+EE;6&!$Z6#1=_+92LT zWcfwF9XWE7wLua;`NlBDgU=TaaLymd~@>TGCJK)68--al0~3yaGUua7dbJ|G;j-d-3ki1Q)$ zs6`{B@0yJkZ_i|HXI4CSCVj1#ZZlKZkB=n;T5qecnvl1uWr_?+PJst-VTA*m-d0`m*cUST4mlQCB%(zmz&&!`I57?HoO8FL^&)XH`&B!jnpUe&{g#Crj<6Y zWwT_$Gtjszso~+5rY*>)^5&<2Xpe6$bnPZC@dt&Z_pcT0ENTDI0W9hdlC)nuC+(jm zY5(HBNZp1f%}TX>FwjF`rH;3FD6Bw>w2$wbq0ZF_6sC8m%jpCQ4GiuZfbB$Ct7)lQQ-wO|p4n)CUujQDfJDRaz+t z`n;8XK@Yts)ADD?T0Ym)tmsTs0vFN!U)P&HGg8)8jkLFDZo*pZ5@K)eJX>@CztpX$ z#&2XD)XDppS9r`jHlL0=rk0{EA6jZv;OW>OX<6C52a?;)FZJEZ%gb%XN}5O-TU|nkD?-C*7WFqtcCH zsjec4k2b!P{UHMrj6}f0)HeX|^L8_dXw#FV8@b+pvZD9bde2gIH9!DIE3$w~wcOu` zL{VH5JAIuyUU2&Nr|3~%f;He&zcrxN2bc(`#RqZl)|aLY-}`R)I%qwI6t3* zCqrz1xL5(k;2lCNUo8v`tK-iaK0?61@6DFJA38LEuWv69jn_f=?Qr1$_Hl$Y_m_l6 zGuJJeSf4G z)hvTTKs8EE!-bd|M>SS;hH93(%Hr0We+7@y|>AZCX|jQ;a%yhVyYaE2NVd1f{uV&bZ(F@xmr zg#@?>Oc2+a@CyyEu|hcyZbzCnBHH6{8*a!?+lFgrg<*DN7)H%T5M%Zk-3C2Bu-Ph( zDL31MV;cKAhu5Cnt37gBoo&T2X?``w;S7k0aTcDL83#Ap4`gD8Yk|!3TY${e*08t< zZ6T;;9@p1;(eVv0vJK&wVq=42(7dLwhjDZ+^`F*GeIt+#xY?xw}!7c+D)=C20C6ROXO*6p|sACcB=%R{geC-Oaftd`O=@+CPWR;|w$o?rfcpD0a9O(+q2zNpoC+6&o}BZ3xs9=2tV$`1&@^ zcg`}SvwXEDG|U)5w88aP#ze45SLTbCT%Qh(#)9X(O;54)X5*-z_W=wy2Hw z=IN(!K*BuR8DD8mm}l=B6Xx+2crTTgAMfoF95FY~9bolWA5&Pdf6F}rS;HrmFpm^^ z>jX6XfJ4E2i@hNDp(yn2=Dc}Un{ptn&gAuR>Og@z`e&BZ?F2TcR-Hwd+GglaMiNfX z)aUGqm6BzzAd!#dW?Y{`Qa-5zFJDuAQxaG@C~4Kz=O|0nm11mD7MP}ldK@pH{?+a% z*}e$)@T-x*URd=#QiKgq3iDTGK-ZULZHgdm!CmK0Y)ZIq@InkIB;OSV3`GQiG7>g5Dg|rdYAkIGz@uBW` zPo`25wGCqy1I%)X#MP$EBTWT^rd%mX)F$s=0BDK0?1`PjwXvI-+G*g^t$pgZM>oqB z(vT}Jn_~;TfwB-sq%&82x$;C9*X(v#Hw9sCUJIjUg!z+#FztvU*r!a_fb9l6RpiW| z6nRD%C&uMM+rWq!VbMrg9Re?x(ckv{Wcl z+^WW=hQ-#Wzq9cZvkycLnf}g+WM#2FwMf&MX#A!y+Y;}KOS#yv*!p4HZgk%27qidy z$nEg!cP%Z9-1VQH9PeEDkqSo{c=0+N@&Dy~=*RPkEM%{~=7!rzYWKDqH(h`2t524E zc+a%xU(Vdj&3{-w$_CP;Ba{x;zW5ILz%nfI{VuAug$DVuB7oR$e*i7bDMBa25uF^$ z`g(`NULP`18#~>cfMH7e>mlVou!|t9nMbl9qm$`gcKOW)#SvSBW!&;0t+_@YfXhQ{ zvbis)JCE=iKR{B&dEV89&UEb=LWXJs5M?Z!E>e;+Z@m$s7|T)Khj0pbxO*l3fA-!r z$g-=t^Sqf^?~+uKcoeIuI5ZK}6VrV^SRd$$aHZXv zj_8T%4;j_An|77w$~y$j6X(n8N-gpT-(UnSuKvuez z-XUMMW~O%nZ8)LjDJ-^Hpbb%~*p1d^URaz!#zhHYIvrzGPwMZ)Y$HQ zT5hGc2;bXp`jvZLf=@31~3<;1RnVgkLNOOEYtx zUZgNF)!EVs!j5kuf5&Tddbn(M3|-hER0~~*qnabN@5~%xrb;P~OI`5U@Hv#0mYFuk zn2FnOCo$XbOkDS#3xai(naEMycS7oDB#Pt6G!q<#fO>6`>ZKvBT*n=f*A@=w#q|3M`|D7Lk`N$7?w-R%6jHxtU98$YhO1i>IGT?b-8DDP9>=W)x z=k15iB2;|Zshc~8km75#02238IH#ZG1FTFOUl#Wr#U#vGBwmtDff*SOxeRzz0Nr(Onjvi6K)VMQ zqr9U&ca}IJpx78fk(Q2sK84s}NYn&_8f zlI3=tFW}JNCCRcRf^b(KThchh6NBvP*MR9c^IlFI@TuC<^=bwloel>AA0&`Dl*om& z1l%0wNA1PFxb1Wag)E~djVl5(;z@(dTqzPs>=v*8aLB(Ijh$%w+s(#K1q8tSQjWyu z+)jQnOHx)%miXz0z6ph|3#SLGBpGnjyB}8X+w~ubmJX1tqpQ-KN z8y$%o3Pq&ZoOuT$wq?x}5=w49mXofK67lFInbB9ju@$yS*!rB}|#U54J7V zpr6i=?bJFVi&xQ+s{K{n$PftKATeGw>7#cd1N7Iu4zQ;rOR}jolAo?B*7`~#Z$|w* z8Dv~n5GhIlCNkmHkj?h82HC|GvLAQ-w~p=-iofpH{Z`{vvaNcEVZ^oX-LRmA0QQG0 zDf7{i=sVv2&N4#PkgmxJUsXsy_q@H@;bV-s(eBmwkmtZTt^Rc5vGGps?X}F40fbxp zK@ItAtIQHyUizj~`F;wdsSSW?O|D zUrYpXnM(AhX{He|4L0S#u;Q`ZbsfF>-MUno^*uW^bBB1;2LenlvUk`KnR{;Ec+E98 zv53pLH0xzmsj7I;ck6k($fNnZo7V1`VmFkMY1T{gQZ0h_(%ltps^9Ny#T%thFGKyQ z7rpG|uZSk}m%JpI&@VBJe==2ua$B{b7uVH4b-&1yr`(h&z1(^}@~bj}onEebudYM= zz>g8^O*QWcjyMUtgXPzK{S{(0_G5&WZ@9L=S7)YlEE>n5gpRBtNLx>JZo(D!95({; zD_OPg7$WW~mYtWZ5uKB3!v8bJ)|U3_+8HD>mF?D58cWCOzUv(0%p*eMM-Uov)k*<5 zt%uGj3wbtTKw|^;T zx_n+dR>tL{!=GQ?ulas`GDc(H^QMo?-#mZh`OmXEZB1r11&B>N|7SLCp7@#P7bQPm z<4NxvS-ZJ&q$o2SD%P2&#LpBZ?i-G5xH-Q4!{k-{0??@@I3tyON9Gt+*`a{0tR$|@ zzfqBDkX9=4&fr08a6HQD!3tKEm#V=6tBCl9-DzJA3(6|rKK*!hB`LVPttR_4Sq98FmZ{B; z&FqB{iE|$%460=~)#Id`rs^zRH4z~m6B5){I1Juo7?W-@sD=q;9fiSAB2yewwN52s z#?(5XeoS73HH>*f1s%S7H?Nopz=fQtbmf}m=?e;@7vd-4O}|5NHAp8_{EnGt74D5f ztx9$8muG~gQQ5YShaj0lsoYWW-edG&l&j%2se!Opu0mu*-A0-pq)G|pK%Ca*No3mT zU^&qp4m5C5Gicfqdem@aOsc;nGA1h%5ZL7>t-SPHHa>M+G=D$LL5sKM&-tQs^+)S2 zrcSNA&-v)Sldia*JV_>*qY~9&F+4hgyS{&h=n3=90bb13dGa9zs)SSET4#^WaH@ET z>^Y5l_Wc;)+44eXx+W5b|Kw8H9-kmDaaa!=G%1--gSRjhjylcx>VU%sN;(QaHEr%AaHW&+l!soKpnFpNY^jbQfg zpZURp*;iH-(LU*fbl~$gD^Rq3^pKWTVD{$b-a5K_H0uxB`$}mmagVsJ#U9gf=-}1T zf-o@WGadH}Go4R&jUo`Fz|#r-SB(%ZrK-jYe>!aV@aOxU_xvM2bMw!Xj3@r)TxL!g ze$vSKv#)A7fA+qH^Ji~sOe*Q^M|{Pc1~P4*{0#qX*Yo`BgM#P7s?s+@KtKCJz)-%p zrDGqHfT%M3O396xtKruMU7DDB3KW6Mh_Q!zGH3QAu~02hV}coK_GK|THs|ib_W3SN z*gpV%qw{bkAPViEK?Dr7OPopQu4w@Zimuvd;2jpvz+RT=9Ql_CiR|T&1!t%+qLO1{ z!4@#g@sk+`JwR=hWkq^hW8@ibt{BtMT+aRj0zD8^f}*V?H3U!_wS?i;(!!CJU<_Q0 zG!HZ&WE58DLs0G)f3=u|Ds6Ej(d7lhQ!5&*YaHxk#%zf=HR_=;;1(NE))HGS$&R3f zgnkVP2tOW|bOkk3kuLjD^qOTz)@qO;tU@O@G+84mcA34;0#%lfWGx=dUl+SyaO;p3XD|efdacr@tSA z(KmVaoqEGjs==iR;WwRQAA&WVzE>8bZ#Ei^O5bfzH$feKm-0SNxEL%#I5pVzkuTYy zLf8X%GfRzJl`?K&I(S@XW2JQH2#vWNud|N=6M!QPj#z+a9X4Raze!sKmLY1f-%C0BTZFuDYG;tfvbVee# zGeqCaFp+D`s$6LpsmX7WP*|&}p`ub#!QVsYYSJug^`Xnf(==&_pfVZyj7V^-Rix`z zhN*0{1tuB`k*=MoQ14{y=R78{3kh(JnXAYv-$1}Tl`HZ->j9sJ2OW9ZL3!5CADH(fdh9E zYwez#a1&%e4$*AcV1CSqckc<7_j+Lu;FqPyXu=S29g-d=BO4{*hFXvzu))w+86LBP9Q9KdZQ`lYM37H)w#KZ1@r8?5|ExF%0*gqOG1SAb zB~SWk_7-vAEhKpmBCOk-N~t6N*%s*+$Kc@q85#P8A?CXrIC$L~v z0vFosi@z$MqO|Qeejgf+cuAA`dU*M|AKF?c71%cSdGZCSV+%`vy%vI>!BHF8SIvyw zzR`(=L=}+;jV8xfdaszM{@Zp#8^3QsFs8+0q&jNy9%Y>qTgBW{RP!8oW#r9xk4znG z*PTwy_!#YXi;+{~nXmM_?x#f?!j;v=gyWFy50M$xrJ@pfefFwH4Njf59;I5~zraBG z`A3`PY6dvfgKlN@jAM2y)gu98DZ;`ChZ|xW!>;OkrGqkukK(+n&eIrdFp^{D0p@;b zAC<}5V(SJcW0WQV2%}nlhOhP_fp_17AMn>mfr0X$C*;eAAC-I%AxuGkY zYo*O`;&raiJiD+iMgFIMj~xb8aF*5hYN4x+VuC)NA@lRqd4WcxgGO2^$yo-RpI9O*trtLdxF zc#*o^KlAJ?3e{qhbfyPo6g;SW1^Jzfp}qztOKl&}7QuKfXa`%=-b@wYcX*I|Y1r;K zA5+hCy#~HYHHcS)8h|SHCixu>1=qC{=McUcVm3%;P>#w^L#G%_%$AY7)K3poC97$$ z7?9T78F6wR*p9Wxlc5;Ztafza$90hoK1fSBmT2e2BW~>8h8xq9=z?b3n&FaK8)-HT zThMw+GC~tBSyNND*dKD()}U&lz~ACr<&8T0~x`K%FSqh zp17ZemEiR%+SEJ_R;ea0cz8p6YGJu9YId>}8rP!Z*eWB+G^^b3HPecBk0X1{WFL2NoT!6YbwCOofWa3-o0$6KUcSQX2+*^EJ2F=I#Np^y1y?LP&v^9K%ySYicl2EFZ&-x4E$A9Q*q(V# z#_A*Ycl1W%<>O*$6Mss6PCI-cwLEchaWVK0TqitQ&t*b*wq23}%6btndRt$UB#7q` zco2Ae?p_TKl~^W9i|{A}%m+T3x7jEn=w$VPf`Ga?M|Ic?dk>@TnGQ9wYvep^Zl-#= zB_GSu`2>Ulyf+F7xIGI(zGYyzHDW@ev7I*gVQV};rGWo4N(|&ibYGqn;`gRRSl(1N zTW$OJlesW43G|~;G|&@PDkGP9AmckBmx^<1L2rQFc+-X ztD!~Q{Id24=ltz9)9jmO5%VibXmEN4sd5@f)eKE3hg3mjhzAnPPzVa1#K7FlB!2~g zu+3N329cnRf*0QG$<3Uc#-#QTjX=0eh~ty_7=F;&mVGs$R0@$J8y62|+7aE8RT*ek z9Q@L^24#I{8hItu%Bz>+4a146)N0#=+3=qn`ZgGZ+g1ltP1qDHpQ|YYW3Wp!tiF?2eJ}Hpi_c4@j{M?nOXuFU@Av-OU*2{1U4QZ0bK!VdlDDU3?wy%@ z@vU!t>}?Z&de_=LlXt!8#UC1i$M?-ly!e+MeOu@KkKHrz&KG~U=6&Z@UjOOYdpd8d zzWumKPdpVs&_`h=L@6@g7%RS{fcYb8`1kHQd(XsOKV7<&1WZ@`@~lGQEFI*xh(o7?#2FZt##+P*Ph;~|J(==!WP!(((#aY97L;d2gO%7m<=II9DNNX0q`k5 z0!5Uiv$dbcH;%zUXf1_ECX;Dxf|hjX_Y zK#+T-IWw6kOk(6t_P!#Qj_Pb070nWg zamcoX%S3MAt!uM+&IO-K1Qv3oqfD(9YnM*sa&wL(x)#?Sn$KF^WedpsjOcDJ{?`Qy zeB%%cTrwv1bpk7lkrj1sEVAOOL!Vqc zTgEu{jwiFsrMIoXuY{`F{f}?YB-2-P?U;Yk?s{zes2S-tf6}OI=bvPvC^L*8&9*~~ zg)mewc~f>&z+AcNXD3lpvU?~yg9Tn_cbQ}{!4d^YlOg2oSQ=cAgkW{}QA)-@+<}5H zj9rMMI?5f+os*!6QJRE>*(zjPwW{H9cw&9RBre8uL6$pjwhQHXjn#^ELUF8iJV#`# zQ+HnEEI(E%{-4u2mOnC9TJUuuSTafpYEh+WJjZZL#wwl8f_*1CVVsp|AKNuquDf8) zs@tpvNH#53g?4DUUUpDkTx<0(_rCNzw(WH6uLjm?%a`rNadoX;yY`73S8a;v@TXVU zr!ijwlD<(P9{x52?1xjdZHjpFw_3t2+JEbZcGq%)+4xuCmTPPaQhwVIMOqD*L28{N z5VgqKgDsMhpy9(tu`-&}kwYs_g2)x-^m#FV9^*64r25xzGP@dwiU6-3*xP1th-6EJ zggr+`oB(?~=E)t6)r?+Aj^v*scHF_X$>7_G|Fd<;LDILED8}q5bo*V2^;o|~upTSZ z;ySbUjjl6$o3I*5SL@>=DE0yJYm&xYSx&Xa*e#|Uuw1o{#shp*gNIgr52;!Fq!u@h z*VNL$mx?;b-j zd1J*rLD@Q2h!ToWv_W_7ZsY)-bndiWrlg=)A@;vC~a10 z8?t*_txbQ{2;WB;!z^Np136T^6FYYr*n!oQ`{*-_)6)PU0&x{5&R)Ts{ zZ9xH98|~CwxJYwr=5P`La`*tIWL=Xs35W8X4H2@`iij+fF0(Jh;!@l_5pS(!x*!6v zi|{ogv&94K7V=ETI%vsk!jF#8tg+!3o_PgjAE=3~P)Lqn zwjs7}G*%50qvpHRq{(%YBL3^3-Gq$Qx;=E(W$}&+?)a_UfXa zDbnIf*@B7^d>T7hSTq_<)pboOB*9G9ZrYIRakm*XQp80t5yc3;qDc$N;M+!XbzOTu zB!h2Z_t5f19Qg7zOGg}9>uFKYn$;n3H(<+tJ=$Uo0nT2ggx73+ZjxqMl?2nZACr<7 zn|V}FMhd)GBh|d@Zpp@N6u2Fw64~8uxrT^$2)_Q!NW-<4TsrIq=S zm>2>$kz#CY_ozI%`I2Ke9vyY0nI>PSeR2Bi5Z8H~bdK)~J^sF9MwtF8G>`pc1jDj= zo|r`j0e5`qOD)!zHyYO>eiBQe75;Lw!H~%uDvo)eE-QLkC;q|1UN@fP+FackcW>-8uU2E1y*uht;lUdDWFNV>6dhJx}^qPmr}4y^Y3Zd)tV`c>71>#D9$*7BBU8VqFxgHw339(DX3tM%Gvp z+m5OPmUJAz^lj6$(qnD%cKDXY6H#EF3BT#QV-^~Kv`VkclW9?6Xr3cxGFIsXVw@;+ z=PH@vWUb&Xr!yKcz`fWuGX>geO>cE~tlmOsy^AE)34i<{i_HpPJRU756yRe^heG&P zD592H(rP;kv--s}_esT;F3VA%tAc#>e{^kVhwDO%5;AEpYi+5tQ|%*duTb#)$pOZ&(4nEsrK1Ph3lSV z6Mx#xyCWFvorHN3FNx1^ihBiFp~2{i=Q*BBQ{p`gG~ogrN@&+v!p*|;`h+;K(EuaD z@^$>Q{hQ}3jfq8ROxzy(terA06LBEgX)l;#I}u2g8HGy9$7P7gASo%5&7P|Ej|S~7 zZ$HagwiDKVr*1<6cZwg05vOXDjuG3LcQ|nUhV}}vFc$y!CT9Ss#CY3KXS_deR&q+^UO5%PfVh4GVB;px|3Yr$qdqZ zNtSFB!QeK<;jjn!yIBA>6Q$yGUbF=@f3)a{jT6klT_oyyA#c?6>x${N^-YrqCN4;& z&%O?d@)s}zswsS|B<3XDbiD+z zDmpR2iK|jY%>dM@Nn-C&S1B9}S|8dHyM3%G{$eK1U=k@s8z+hA8(v0Ka(%jnjW)t= zDe^Oo(mt$VW56#knU@)egAqmCKhry6LT|SNsBP}~JggHJQS`aI;Hy!}iMK6LhsV+x zaly<2SCa{%urT{*>ZclpS)H4?GO;YXbFNu|`Iv$cGASq4A7q-4weisGiG|P>okU=q zbB<}!kluw;FpVmsw^xX`(4K@@xjla}+@1_}9Iud0>1}2%#zrkDw3-RGtWV?g5|&&D zIB!=9&nQLdV^y(cLNf@a&~7HGhI`AAd=qWONg5s2@dT5(AcPUn zmv6MIOUMCLO7prk^8n-+>H^~Eo>q}$mV$c{jYI|-xxTo)1S_2BSP;^lW{ zt|+YX*iO#5WO8|O7*H96Ojc-=)F2^SW}jD>VK8h3E+giem4K-<%Y@(2ki>wBSW}5% z+WVB=1AfpldPQC8XdzG{%eVK&DbkU~Mm`=WGu;nO0F_MqVVE?k8;3pT)xjY{bs0mp z#bLa0G}8^0Sx>U8Oa-SsC~d*nZ&awpV5mj45aU}!k}s}5(y0W-syefT{FhI#U;Gp7 z`(E~M{*e1o|L|YGuyj9aW(92VTpHVMH}6{{Rbw1E6)Y2MXStWY0u&!BJ?V0hZ%HTB z1>w_o&7ghRdfi1oHDFb49Nwe)i@t0uTD+ z%Cs;e5;fI?c@(IY7SToE$oqShr=O2TimjU zcWuSBR;i;_Ke}z){-E8UVodk6GROm)-4>9du$$4X)o6$_I|LeBD6rqs+30bS>=*T! zeO6)kkmJS~95z{n{Kf2yk#E1K@}L9)U6xc(+_<`2s?(4!b&kZkMV(PDFwfi$?sb;W zZ_BpCDjETJ>uN+F3p2s|=Et|wbdSQj!?m(7W#i8lW?ZLA-7{u_eyTmiR4`J1*BLf?d9EpNudZSihbagKc!& zQuplwsMxaI(OEgvjR(X|ccU7G{7#lDQOeU4_dBt)w@*LPY+JDE&9}=wHt47Nf7mx; z;>@FXDwkws0Wt!!Avha}U^v<#7VIx#dMEownK6qa%Xo z)X0b+EA!Nl1sAIq-(8t<&(35D>_!rW3zHvei@9W)@9{{XoX?MzCTrO}2Wp^Mj9B$! zixE7qOC$xO!baI~kKC?1mmS#D6#;6TPL`fYcE6GnZjYN0%7*HK#7f>YEa%wNQR5uX z5HW@8Ym~&f=Yk{-0sdLXC1PP0F-;-B)eZ1a(qM46Ub~>!sW1vnNBDrA2`wRjhWQ&O z5mnauj>J?=)7;Ae>y%g?BUx2!_dsQoU*2OEYoC86JXO= zfvMCqdxehEbaoK5KFT#VymL{vW_O|(_7rYQu}7i+EV!ggxDT<=$4inG=@?%GGTY*H z9Z-+#0ed~_D6~$%ALhUDEm|~xSvc-o0lf6W@vLLpmbfCO?v9;FNduiBy-cdVCGf~v zxFF?A_zmC*#Le1imYR1+D32{QVJfxNH_FgEb}U0v{T7?0@O1GQ*?jchD1Gb>lU+N~ z$BG_>7OyR}*eWgYMR|)m($74rPF??Kxj{TyOBWy>>0QXO6WY7F)Von}N_PbPa0fzh zXgsk@rWqV3O3B*Xu|TY@o4i#iVy*gJ99;u$JJIj*RwWTrBrdC!Jx|XY4|~`aXGV7} z26JY@^(dJj4BKQ3<M-D}l0O1B4g zD%~K|f*Z&?VocFP0ge;!#TN1afz6pK&2IaNWbQEdr-?@#*;bqf@g3iCCny7dh_YB7PS{&mfV7a!Cn+b+eC=E5jqt8{{Nx z=7F8tG`Y&eY?}fZg+^ueyF`GlA7WjMsZB;A#ul89W3yB0`(Xm`L&ewy(J-D?Y3=V! zh?>b&KBnpjU``BCznTaihq3g_NW>2GOSk)?Qx@9gMpzO|y7of08b$>_#Ko|45xc>C z4#B=!(KLNgFeD*};;=aIri5lY-ToFX1v7bI>>t5DH z4Rl;Av+Qs^ms&Xgl{ns?wTfogV-X5Rc=1VGdP=gY6ngDa_uOzuoPBRm6GQ?peYsVn za=Zlao5jYV%}Qm)yZj9?VEejJa>lQB9vX+~Nznu8m`f0ke(8&4jt{3?QVGeC(@O`C zV}(c^>-;^dC(?9vc9@ostf}%bkm@=OQ zd3(4laD!-W)kKX}{84_t?ND%@d+QLP_KR3NlNAW`$P%-j!eS9}$I1L^PE3Rs$8UHj z@vB>{_z1qNPU`HF$>(M{9G4~%bhqrmDW=b8u-p7plSC>_24eUPey`$EO(psuCVg%% z^pY3)j-Uvyccc^2CsKAxoLTXL0V;R1vkXNpJ~ud*+1@a7O_XeI239E0 z9@8)_3zZ9`QSvAbGn{I#zEDWb9yq^L8jG*%#-BYF9MCdSXbH*1KM>$O}97Vn@YeH<>z6lXJV_ zVwblB-f1|~&gvw{emH~m#cpZkWJVu3${nMNlZ{M>-AI>93>idHEr6_aT5%jJRT?fJ zlm!+G+qPt`9x+29MRIXIJfml{wJ0M-oXha!E1v9S9h>t|lwu)#36t z+Q*rv+dHXK9tuS(+uzc^k=m0O0H$JYEu^`N^qtu~*PqWV(mJY?gY6F(04jepcbu13BatzkcC0TaH)LQf07ffR#u8Dr?0HR=FeCM6RxTzQ}7)e>rrBV}Tn|4^fw`QOtC zA1OT6IrbB==!GvKbvPL&(xPTlu&Bp#AY_AWvRm7EN*;N4&L7|k1K)6==j$PeTaz1y z+_(5i>wQe7wKIYC9+{^;sr7mKzV;JE&`aT^<6iieb48w4?=LPiXetmdH6T?XtyL=+ z4<~;=O4d;~^DufB;lB9alob4?1YrHmJhbx8C;+hns_bgZjXYLdha+@wZx5~!`2KEM(n}Ow@?o_9x(}q7^pfT3~^KaZjvUeTF(M6$|OnS zrS0!D;1DVgnxD_GX(|nL8?y~Y@5Xy?(%e#el;MoI4YN(H26{@PQ@l=GROo<+u9jV* zg^UfmfG280m#-s^3h|J=SKa$1joijUjB(4A>pm`IXo-v7XrxWfq%2KJWbfY8mUO0!<+n#hv7Fy(>cqy(vx22LxKbmxCVJ96h^jN0 zJR{p~%9}oj>H*_rIs&{?OoP41As;G)zanEIb7@r&{!@xPQeC!PjTiIV9ysP{IFhWg zV}%{j-=)k$m{oRcX_Csw{s^VxLHXZ`_`E{YUa@fvCLJ8(kO?GNP5LUw2>L{er{tFquS@GBSid9Mi^M+pWVJ=H_@$ZcV^hZzQg}?+ z8Sg8*hd(jX8sfrAnF8<~v#8Vi3Wu#c9-kNy?-IY|;8s9+WudzB--wOb zaeq_?5&#s(Ht?%JDfGH0W^3m9=v0BZS5J79FPM(1(P4@0!nze&9HlJT+}Ij0)E`*7 zgsN!-A~=(#CSCb4baC`p)t6??`X-N*7Mie?SB~sSO&SejSLtVmSv{xq$(eZOKMG~c)PhLR`DCN;$wmYPG zNG=^jx{l6xRBE8dhlXxh#}YjwgPw|!0hFCX?Up+r(xZVbB(!Ulta|qi!6IUas;?uD zOU>z#o2^XGh^##YH8SYA>jq>?(6x0Rcn~8yebCFq$Y$%t>s99)!5oG2_4>^?OYCcTd^>-q1Zaz17|Lq0aUG_o?o8=gH&Ut^d70 zd&>Uzmf7`0Rm1b^E;v}i+p1%3bv`h=J?PxJ!OvZ{-aHuG z`u^F8TW;GLOx$+sH)f~wpy@NJKD9Z!=a#|X=Gj|r`RMHA&4W|tW+zV#1{;IUZI9UB zo3q=uytSd($y*15O_jfGWtQJhou8fJ$!%LVPf^8f-?3+Jsr`0yc5U?`Bkq@0L{&310x8vKLXZnnQ>XCdsi*;#sU3vX{$oi}fK-#WKK*I>6w+;Z#2V10IL(3#zw zy_z!iu@|15<=wW8&Q|F=f9=gNOn+WWbGZ~!5A4OktmU|HQ0O0EZv@+J+(yx zyXf`o?D@eIWlpU#bm|j72c4VO2OG1yGzU<(8*1t3`N71^v+G9J6n};f&JQMU7P+0< z>ZzfNtKXX4Yc0{TTKEUI`q&sHHi?75DaOhu-WpuXq^dz$rw4p^%PhmR_qJR3mm+Jk zyEJ;D%jo0Xf$)W1YkaS)etab)>Kn#@dAYfs(zV&n>NjWihG}C`wJ!DD)~RRT#)o>r zLc0ahY&;-uYj*E#j3#AnR`E&b-D2RhJ_|DUIhjTANG7W%et9KdT6eANEzH2F57bWX zmuB}+xdzP|q=xg%$Td8>b-*UN&4yD|ZKH1MS7FCy_Moc=4r; zhGzZNO}1?P_y%UkiSo{wiz*>d@ZulpzZdqJ89<`KW&J8%#)F!aqeC~doEV1NSP`sCZQ`xLvu>#@J=@`NnV|E;sP&=<{26LpgM&t_cpx@Pxsn*Gg+y)5yIFptZeW4`MZC13L2?cTsiQaiQ8y;KVQ)u4VDj~ zYAJKH&Z+g;UC?{m&1;E?tD@bvhO+zYrIta7qp2b5v@!lu4LkGwM$+B0kK4a4!ZQJG z!sN*;Qv)I{NJxG^*E0m=uKQkm^0(coBmew0C(ixCzJK%9kKA?dT_1Yg+@FI<6aF-! z@9j?f#Q*W=FHF4Yb8D-UpL^|3d}ye|eU$jQM}ML7`;Vx_6?;IxzP&p&=ykiR-OdqO{WqUGyE^gNpZ-XxQaA`1hAVp=hYUU?$)O& zvfrO~?TRfkTK}+FC%om+c`ns?xJsZmHYOd?tz8D!W`suyNi7~x4%=%o&AN*z4Y$ha_|1XIPTEp^D$UdZJXUa zq7-U2yOZ{FH-9rZ4EO@`U_~Yd3(T8+w%bd^ytqpcnd$ORO?6RJ$v8d1aI4$Wp6f5{HKAD4yBa`^&r!p*#zNqQ04Fv(vyuVlQk;SU}p~YWKX)gbiMGI_4fRMqtY= zygT3Bzu4ClXd<>?ehjPT)TmY6jk6GDKJP&&?>*R1KVWYe5B=ZDo8&z-$1>!HdfQ)M zCDMMi1HL&}G+H7L$ATiCzagL9z%(rMwdp4YOb%;L@6rPI#rc>w=HI1KaTR4R^++?Y z-kn$&F#ZiP<2~KT7Z?Fp0$&|m7%ajb7NIolh<&0Zu&x8Vh(#WcAN_y|#HV7$`ddH6 z!gd)qGTvaUk{+t&U8<0ojuhlY_uD%y%j~u7mIHLEy8zo_T40??UjCh;SXCv4*~V*n$6F3 zS)TnxCbf~iPj`VZEN5|!LGN4o>Z`&UYx?ti@%`UVcTQ}rc20bAdSdm=>h#3QvX4i# zzn|{zTkNy%76xMMz@k!>LPY3^36U*mA zGb`TAx#@`$%bPUV-WF_F3>vP(4m}_M9DpKF)HvFrvk-VQ?3JGktq&-S4t@ss+@l)$ zi+nFhEPOf1?v5~$L81E_)7z_Orzg&=e$~lcc5<13mF08O+snV!JRa-a9}8d#i6QI; zi3u4RiC{aBgV;6Gu`oaYh{FAPC#Jg4KWr2x4Coj!)P|soBr=>Qwx;);SXpK6rl*<8 zsWa2_%UjIo{FY{tuAEujnx0xcGrzLA+L_;oGka!h`oQw)>dO4;iRtN;Wv#AV%hS^; zwQqh}^RseBD{gsXdQT{~Y(3tbUVAgErnJl8c8mS>?mi(j`miw2^6dxMH&|Hf?lJah z?0c{ndaKDYiQ8G&?Y*_JFdog1g#p~o`?)@Scoo{t(24n#Rfs&ZI!|xsS5C~&udd|% z+za9JE6elq>)y{p>d5lyiTN`t*3Z?$d~;%TMITdY+B>@H54WcG#-iTUjp>ayZ`5}c zSZ`ew{?pb)CL1JCXAi2g-9FRHO3gaU<1P5Rca{%qP*{dQk^m!PcXzMQT}_^ClryX6 zruVRK{E^M4Jzt3%NPo?*GNXIWcrU}Ovrbrvt*0wt`WI2K!9W0a=S(>4&D&plnSqH%w;~%*=bq`rVwj?vB+*`6>~cWTQF!&$27I6mrZktYVS}q zc5;f9dt%M@))^*Ya(EIH(ux(mtYyu{0l}cm-nuIl1OD0{a4VBV0h_U@ z1+Y1QI8LMQ%-+yqrN{#15(i?uPfRo3@NzMlE7*|iE1Q?ZeTG-7P0)_#v9^a>J=r4I zS*Ei(=42k7-)?meGIPubT-XX}rwR8Xw0Z~KreKhHkUDxbQ|nxKE+E*{TTP$y8|^%G zmmjvVm`|<3i4~p=_ty8O2Fgk`tyMtNMBqZObOBk*;mY{>wde1c)hN)HMdSo!SY#y2hXf7!!MU1T)n;a1X2d(D^|2D zW=tuhPvo&KTsBTz*U$C|3 zsO1c7{=~}G>h2XN(o}TLY^_c$&x`gBQgD)AO*|k05s@cg=F97=Qzzi9LHwmj5isGI zO1V&gK7VH7uW?q4zONh3fIyiDMBqEMQci46uiC#YJ^N;Ndv2mX_jwB!cztOi#S@hAJALyy2BEST4}~OJDVqh#f$RRARS!eFC&Aey92Z-NvM7);3+Rxp8G0b%GPh%3RYNK`aYC#!Q(1nNz~iKHrO2U`sh?mqk%z; za;;X-Fef|1gpX?|vUrL2uz!SBJ{vm&e7H= zGvb{I_z=&~P~(&JZzGZze*N7x4Gv4$&v&O@@l!V*eFx^kx7{>( zs(%S0emxy2#);R_1Q= zcrDz`0w*$S@rz!MHgqo z!#-Y|TSGGAkdtyXr!Cz_*PQJ4P_*{+*z=%oDPcYP%`61QUwg?hE-_-JMSkHU^IltR z67YzBP)CI$n{*ivF@f-6+jCOfmQEy=Libx|E&^48DOBiyF~xb9`e^17Y1J%SRxzE#&>1`VaK?3PuWIAe%Ks z`SS?TPXzH?D>f5)twFhy7#u^lnSQ}rge1~izwLAQ0Y$`Z%P=|IX?N0Fr$N&;gJr0U zmLUnMSTSQ&9mKHOl=gw(bn9kOWN5Nkx#FnXE8FJ!z^x5R% ztK+`z#C>Z?un_f{a0hGV-l`ntEkG~_75tM()PaJ(kg7Q|6^nuwUuZsG> zjX#z20ef9iAf6&mzSMo|{3-k2VE(bF*Zf%hQ&-@!c#o&Z7<@nW>u+UC>Y<9GqOF)F zp3loyU}zgK&mMtZ3e0LN2QmVWZuh>?SQjnzx8~#>Tm1XhLd26%2+mBC#;6Y((;i5y zNV_3AjOS7&_h9CLuwa{8xTmHEY86K@raQjTkA;oFWWS42ioY$iK(&}mWHFK4P}|Kl zU8{lc4=D&4)I!{ca8P(I6el7N$kXS~7VmDRtf&v6BI_P=L5B`Pcc5>MNuV+UR{N^4 z*Id~_y^g&iO4$gdvcst|3iKBjj4XaKqW!;aBu&w0K1Qhn1b z=I3hqW=q;b{H7?*%pWAoTq}Xz`10bpIW7rX0-|d{^oDEtgeHpUC|MdlJJgQ9{hHZ~ z7n)vw1HA?^`*$^b{tb^&_{`Aj??+bi-KTk!r_1Efy?Hog^~8mh07j$;(#nYo-oI0L z|7(U2JH1D{j|d|A0gFaEG+%ut*n4%5qQCfcxltGAh~$yGyfZgRNSXAmP!T#_lQYb! zDx6{R!@4SlDYiGjb|fcPuhX66@I<-BdPjlPr*By7a)*JZMIK5acv`A!)<4LqcX||+ zKm)8XoX{ZdW6-lb2QN1T*+SqHZf@L0yAqFJ2V00W#VD|`)5mTl(DzhI+x3p0*!H?d z@5``*iAcQSS#B(n-A6ne4rzv-weFR{`U7vr{pHrA_3pu>$JqBl*U=|xz1Hznv~3aN z$=H%Y(SnM|pep807K31pv5*!`eRq#Fn=6)-LYqbx8>7!2&mIpexG^Q1AV`Xs8DXN4 zB+RRph_%enZqDrw0Z1$$TE-JMa;AxCmY(k?3#?Z$=zpkLvtFd-v`gLPyM2m%3c*{U z#Ze2?JXw$^GcD^h1?dm9Xn}F5#n4SYlV+ZGvDjnf=>0gYW>@V?2UG-)1S2*piD};@ zZf(LkSDIB@$zf7um*4}RP)53)LGWdAR9&64aO9S)bZUjft;SBIB*g!6OwsM+X!Yp90$VAlx~SMbDkh6xwfU+PAMM;TBPEMn2pA zgC4G{<`{Mw|A0pEj*)(+qNIdPI!U+V$1bY!@1L|M=Bg=Cf3co03e{fJ>u2>(hrho3 zq`byXX5`MMuB67nCOmcsBG@r9AK<9Hk7J=(^4H+h&OKB8+2{nwF&ET{Y8Sy9uT zu7G1BrFsG~ji)ee;!V_y8FI4@;uHcBzQc}b0>ivaCY+EYJ$DvegTN>q#B7PVDTvrX z%*_-|PRZ0llo%N%ml3a077eRh13lRp%GRKpf{+~r-2`uiNi{oMiNDoxDzMOmeW2#5 z;GlszI}PbJ1i{!*`@k>@Qgp0vZ=4K^7#uV*78FdMgZpJ@bhh)ejjXg@YamV>p90X} z;BbcqQ_&QheHL>1PL7>MQ&bKM#ZGK9I&5s=gU#-h!Wb-95S@-HvfEoiav~`S>5Lym zt%?`7dTeOg(;yvYSZEk{gkeIuM7F1P1s8Cz=C}=JbYzZ^xAVvxNRyobLt0qbHee|> zn$Ze42rlHF1*QTH#0%p?`gp`aKPdZ@1cQYp-40xr`5aAIcS*B|&H1vp}0h#z&ah!r*?B`wwURG$OyL&Yr`{ z02XNk0ak&!fRsL9yF*ezdkKe}u{v2fl5znXN;ZQ++NUw064{#jR)@iZJ@6?+;Q(ag zuFH_v0Tvw!w&~r0x@{BHSGuT<(Ii-bOyWN?SGpwNgGs^^IGGayb%$fQ1x)m?v|ykR zc^0W+CW!bn=zl8OY>f!i5sPRX8SV`SN5b2177!pQr6%`{iKj<0JOujEGcOi!L*#JA zg-o!N4u{AD4F_vsYld0~na?199jUlZ-5TW>BV}p@yvVDP*jc|MaN?zsh59G5htT06V~3h$8-we*0Dn zto!%odGE;85XX|@N~8g?^FctUbm z^~LYSRj-Zk%s`vmObTO8ub*X8C^FsfW2kIy?vQ0@5S; zC3e$r1R2c9c*$TpM^lDvj5YMdm%haCItB%Qi?!z9X?$RJosZyVF9yI$5QGd2EMGyD zZL1WqV?n{lK9^~lcC!N&QeWAp7Pk7kh0#s!+0yV)TN~djXoqaj-?n9J`OK_e|OK1jQVV1#=Q!=idGRXbXs%4`CDZD^nO2 zO|S~lM7|KwL$wgZZkSAsc`?fn=rDDodqt!}6VIXpBcSB%mjWZQ(|4l*;Ltk!$676! zc?jlbrw6>|=wO3~$<1xnFtt`dIl()Yi{AcVqz9Uc8qJ(k8pz^fsd+6p(1>L_hoP~N zl!|+WN2~_7xq<2e{F(VqmOBQ+Mn(f{CM2mWyb!`(?_QzT8a(|+oqMcKH!;Cy^;8`V z9|z>v3JA?ZH69dHUt!3cgC^HdY5JD@h%ua%5a9t`&6#bLHVn) z$~n0;e`5ZR+rpdGfB=me*k1fjhHgHgebT$HAeBRP^Ev{y@+YA}k6zz5{lC8YU;f;` zeD%z<=dC}Jph~AdF$84n6oR3gB)P`~G9JvqT%_{VqhXUUk8SzB0{2MqG-i3Wyrmp; zve%j z?aG!r7sj{mkZG47lhIp%A|a}Pw|=x4QAI>3ii&RqsQ6Y!ysKrzD`40V=>yotgkk`n zA@U>8i|3idHaMVT$+0*Y`0f$|%sL?`g{2pyr9m%4t%$@f2x`%bWad*$LiLnVT-_xu zZlCDTzvDQ}pqdCf!l|G2y*SnV6XPWJz-t$zrt{5SCCt*fqB6sb9k)+d(ZwfG;4PO0 zUh%c*~;nbuuM*M-xFJAoVuLBT%Nl+%zpiCci#>F?p>ew z{3rh8|98a~pF!QpI0XQ47d%Ke_|M^d@txkOMUvW%s=H(%!a8`m9|MFjcY_;?6 zdH>@t|FGMp)B8I^_&W~W!NRAALE|4-($91M02Ov-%H?0{V9WBK6FBclpdJY!@ZZq4 zoXuTSo=zp;nfqE7189hc$BuEsC%L2G&KFVb%R-LrKt{RRA}0Q?M91Z`uZNR5gveuVN_d|J1BAs`rnq|LvEEwL z;VeF}YE@RULT~q~8Pz1q)D=oKVa5W%DmCs}0`z_YdOr@m*VWSdOrsZfpJLLIAv9P= z4ohMOFE{l9CulQ;x)t>9MF?3i{yHP&0`-5wQmcVTYC{Ot_u7=o<{H1xz)(nDCnSF! zl0ScTx|U!cU{4II@d{}aFrIj9MyaI|bw&jE_}-ETjHb|M5Tmw=Zgxz!Ld*dy_^6#V(Rb z#3S9BvCD60+Zv-rim+Z30lbBA)6egHGOWf$C7_f*4KerS+S@=3^&5xaj4Ab-&TRFI z5#33GbG9glR0nepvW1IC{A&G880I(3pTfcyK9O<9?6M1kJI#!RB0A_Z0Q3q;ULBKW zS@9d)XNkSD)y+PTj0FAd-uB?2ZJUX?s_2;yJLcQ(6HqIKxgq#7Of0hl?+G$f^?t+ZgS(`o4Z$tc0&p}(H`pg>nVIbumhDZ=R_S{y8uX%5Dj6hO%5wqIE`Ms&}7 zvf*e!Xa`at8fu0YdD#U1W-|dv4({R!$`DlHGJ{RS@hzW@bpNi!_Af3P##DJ@e{+@pJzo`5xXxsKAy+7!#*DT9B;W zWGKlf#=KU7KRncAhOxFpP;5v;S4N?}eylj7aEL!M{8Soe?OAKv2RT#XB5VqNk~hiM z(x+9tIbwv7R`DjCx(tI0Y5J{Vsx(T;i)5*tB-s1Gt{*A2ePVpuffNi@B!dt_w+5xS z#2PVBkSW!aS?g=z7gUzeQXJI`-=vkmPz!4W$VDteV(l5t!N3V?19a$98{@3H#lsob zsD>@pBB{`UH!_|;WqB_O@~ge z8hM@W!Rq`?%SZUO{g_3qfx+*`jkXHF{=N3*S3`Tr*1W zxb+97`DNEzAZTiIzf{SoF4oM&{v(YFU{>;*w#we(YGC%97#TUQesk!>gF*vXHiq9k zRr%ic00&#q(kyW>yG8&rur3B^<7FSod6}#Yma+INS|5Df@A1QKL~Gn&AIUhI>xgVN zJBoakq%3yVS>q=EaN=?HWdn;-zkpm4_?GL?Et+|-N`6aOBS-pB!^G2DA;k1U`yI!S?u#i@sWV zGn&7KX5gbmbgRL&sI@rD(M7FoQe6#16Az?6*N%Rjw*9ZPFoPd&ON>jmzo7 z1;4h@Yhc%TTQL@-)HMV4Lgp=8owc91x;0kI)Tu+$Xew(qS>VaoEyMo^hDP4MqV*7Y zKeeIJ)Up21QnC8d01jWi)CQtYb>Rnvn4rO0DPhf}Q$5MF>o}P|Wn~nA)`{O%d9tJt z;=CjrV+;WN+a^&Iw4k(RXAvOTffAt7z$MF?dBPUHGxYwgLBM=<=#6SB*Y#9+@}!8E zkBRYs$z;On{gpE&Ry`LlH7;!8ECF_KWjit}gA8bR>RaUWG9*9#RC z0?Bf8NCNGGuZcZ#Nsf|&6&_C)PzuFQhC=1XH@0D1-H1=YWpzhC8kxP3BS|9bSP_Z% zT%6IET}6;%>Z(uks#w7Nl)?TtM3fvz=C~xXQRzNt#7umCh_^{S@VQr(G~pB#Hg99x5#AuW!I+0TX->M$MIc(e)CFd~WrOr|hf1oCK` zLT8lNxG>kI$^yHJ#OKTr)JjXU9WzV_wJ|ZwXPe0NEi?Bc*xUu!O1{CKwhRAJg-l(f zC9Nq?n82*&l#;tJ=}&=gDy%_FCAtAK{z8fsw*^+-i@{V4 zT(V0RF2rHV#7Bb>i!P5eV#N~_`x@MXsTZeo?v}crvL`4m7Myre#5YoRu<&R4@sJL5 zHpp!Dg?qSqpGd#mr$D2{frU5$3I`J4!E%cDRDEp7cJcic{C<9-K?!I5xBEDy5YjbM z2^IHyocrt{FbbnG{>V_j9r0}7ZzQ*6;r^xlyhpX_5QGJFeE|)V$SEWR9DmRc)vY#) zcB={Bf_Bx_66GFfma+~FBR8byvc^$7d(W8z~2=Dm-0iQJsQaG!HG$I>25*@ zv6XmuR1s1zLcDbJ);WW=yJ+19tuCblCl^XHFRtoS2~&+D)tLMm#O7BBVpUMWvm!JI zzQceJU=!)Lbkr1G%D&kiTm>H$LycBME(VPC_-7qVsAf?Y6TbpHQ9dbAcT9DwdsW08 zs+SfJ(eQY#hft4W{qf&83j2f;OcTFq0XDA3B7vy@y~GNU5T7qaUj^Rv6_BdRn1Bbj z;4YD@j?O}AbFX2It1;Ym6M~gW@CL7$)Lw}_xp?RVK+%;%RhT4MwRYB&Fsf!a0yJHrjZCmNH&tq+VON0lj}o zt=Q!*p|iqUlPL>q>}K?7YHZDJk-;~eJY65yR*a`YhWZFW*`bbjLNe>1En)Sju7eH> zv5+ITgT+JK$35n89-0)K`^~vYwZ&`(N2Zu;n8x4%)g0>L?qu*T$k`;l5`D}M=Nfk^ zCNVn%5^9e9voC|wwV{7t;Bq; zZwSV810pKCExg5uB%61>Kbm>jf;`a%3-Ob5`NZDj3ZcG&1>0L5(4 zndkBaTc^5K8JtLbyuj88As45UtD$;<6Lg7k7IQX(Lpe`N2Z5RHk8EoHu7G=megS4; zjxzm;mB0-wO3I%NLtOxjVbKx^Rh$ck;Yg+5<=9L^Oo;3MBF`LSLWki+hNBsGLMf~d zW}OWL!Yd33{8^J=mw7d{|LLwJyu))N3~8MQHJb}AHs6K?86N>RUG$JwE`SPtqi$T zJTxefVDA&_s+t9AYjUY5SQJgI-R}DiXht$V!2y_H(d8KT9)THj}w#zXIImNP)1{nonDJ{x6k&qb(Moe6F2w;-53wWd8S zi*m}ymWEOc0_b+PGkaJMWp&f{o`%6Q8#F z>d%vAW$vpxPg;6kd!95a(Q=+ND%s0`)e1{h&|3y0>TlOR)xBdZfMO^6JY?me*n-llbZ&ZRdTajA>Q8p3h35vv zCa_|4o4!E~x-=&7er?aLa^ijEWBKK(o1u#_Q<$_3NwOy@qT`_F$CQ4R1g7Z_o)IP8 zcs-@_@$oLqDo?*-1aJw>A4Gy@raVrb_U3qI(-hi2kgRMmk%_|N9!CiNdp z`oauN;%*kk=qoBF-a);GJE!ND&x8e4#wh>29izl6m8F3a_%YZcug-9*W)HGFBNz{2 zvwKN@u(G_edPb|Pic<*jXvZlQv?6QhRVCZcP={&Swt!s!v1M{K=+fWiRbSub9;@Xh zsNx$^3tNBW*moXzVU|2wFHUgt*k*04NS^T92ub`j}#ow^*+3I^e+jpJuAT5G$MK5VUnmA1c zMK-7R=t5rRZj8cy0dHqHGRZ0r@p?zzxEmnHI4u1#hKU!_KIy3DX@+6`OxigSOycZg z0U4rPC52n8D*`g>%2MFsiRhyX!!>8e$2A*0u21O)Y1mt|nA!`*I)sG7ep|5)Hgz%Q zMQ`ask&iVr0{M^x%q6@sKPZkL+X7~7Z29hwHS_hQgGXfEz@o!gG}v_vo2+&1egx<& z<$6G#63C)cn1RSk1)|Q51){VlStUN2L9hxpdW^K4qAOyMFAmIlWE_|!nWyDj5a#x( zNli>|FE{7tIO;7&#t8QE?6=2q0apdixz}e}E zqpwJ_Y87Z!U!1-FC$mHEXI~WGuTO8^NaDX250`o63uBp$>8V%We*3G@q+a;Sa#b*q z!NTZN!I1U2G4NrGtIJaQ7S`WdGnZ97jvsCf&^VMYc%+4k>PcDHg8Cc{W=Vs`F>b|L zn<1Ws3E?n{fpRdies3WUhZ`sN?--UY8^2Ld&fgb7^H<=;DhH*FlfHM9)yqg3?Wv1* zTMcKs@U#kT8F|ei(QE*Ng1bf|vnP^T*9h2}ZZw8L!Kd4dVNWPgZfLyOBu4987T97E zyYRHPq3vd)SZKQmPd$2}Ic$rD+iX#^{?}u|CNvwNswbYAb|;jL1CihsDn^K~N3&jN zvRR{Rgwc%g`ek#9D^wzU&}ujv{-D)(Rw_QyfL1C!T40Q4M59tGIKmMai?uldtxSs} zFuZSZ1X_uajzBBb>mPsTB{rFzKG@UrW#o4)S)mu+@8eyEe4lOEz_*MTyw zdzs}C&z^U#Uz_e+KlJoEp1z>^G@KdAzHWX}Nh|AKrR(dTKG`U7$8#`Nk1uU6MxDPf z67P+NTsF*}J>@@Oj|RM31{QZ#V#lk*Y-g-l~A2oB9W zHj_?bICC?f>F%m3qB7IR@teWb)GM39K!#E4RBsc`amj!dS9UP4G z(h6q>2gEcL;IRH8t(@SZY|QwY?p<6YHcV(9&0an)s>kuh35oIv3#*Kn`r@#HDrh@u z>5Ij$)B;Om<%l;U$kLZgN9Hb8{2oU#DdB*UKwmzw0GdN`h6Q(SABzc-mdY?`+2`EX zC~s^!Xh02o%OE!#Fz{9A_i7Pjqwa@81H(rFFl(84b-hO%TI@#*jos=Vk}p<4MT?gD zw7(E53Pt=3r`530vz8QI7Sh3L*Fa^%xd5Mc+9&;s%}_e9S$D5i+>07L`EAp!VfZt* zy3Z7u@=|M^_Uw;RDL>-r9Tg-FvHkXKpt9kpQ%2=AzK*1>IK4Vok%i=2*4FhdV9p%Y zu~adb&o#pGJ6Q`)u=!v`S*XQ{tPEwwcq%DzGBRTdWA>hWy%x4mEK1KUO9-E+Oi}vY zx-Cl*x5^flZfGr+!pN?Zq09#Rro1Hit~t=YydT^H~7RWX5W6(shfWLrtKS&)hoW5 z{YhD*{t%<)+3Crb933)dx(i+JAK|}bsS2NeH{O2KaERRzx~<(uJ{nfXBq0?XaNs~h zGfl*c*J2rB)CUVz*Q2_%gU)Xkc~;@WgJqV!SJ)+DDHkr9Q|p5Gbo` z`{?C3=Luq$gl&wr9}quG@$R03!hR}>C5+yl)icx6D`!q{BiXWU5n5SYUB;#{F~7XE zI9sdkk3f9=Vj!D{C$x6tkV!blgj0FS4;s;{D+;Mu!SJPv zrMOv2CNQ26fG4t-SI?Z7k7RF5Z@d}XKxy~-V!H@%r%JlP3Y}4_S*^RBbVmOS^m6$a zzpb8Go5p@N&qS=w-xCIUeR}K7>$Ma+K!1YhheLP?7{wtsy2B|3fM;o!Io-=dGKtU= zt0y++Csvl%{Lkr?<+}sfXxMM&znX!*NO&mAlmViNH^bUthL!<`@Lfju+UoA*>FN39 zmCe;%8t_DT11oyM@Cfl;psPr*VKH+%>RtOt&#z5ip_o#Q`ZyF{ER@7Wpc#r1<(4BS zsYi{AJ1&yxRn~{ylf?!dhw_U9l@Nag+7j9DLO+3EC-H~K-Z-&$e%f{=gdessKEqvV z^Cy;1=$fnf`7^8S)O$c4OmTUAb?=E(m0zwkae~VpcX4CZ^qH;Iy~~79wkr~1U7NwPnIEA$#6A} zVeq1sX?Ct!Gb5d=R_eYM=c*NGajwSqP0rQ$zRkHB%ZzZYhGGusTCQL{)%`FcT{f<- z@~zL9cTc?c2!{?!4FAJInH#;Ybc;)szQOk%k-PY9>VPrK zpWwod`4jfrU$AmSPt)l|tMGoS6-&-Hy5HfLqN+ha>MqsgbKze$q5b{QP+v86*6IP8 zRgF@nV|f;ZWDS#Ard*a}DA2Jbe%tFYe~OKp{6D4h%6=oXy)nIKnT?H9T$?@=ew&^S zzueJA%aAH6dsEOH4|u4yDa4pYaF1FJu&(Y>;^6`+uW*uOzASPE1MDV=if3|`SJuO? zyO&p{O#tNr7LPYJ;xW*#!UOTqU)mg% zqv>s}m?yq!BnnhyHyRbD9Xl$(8WQx@Qw~aCGb4?cA@0~-0|~!Xw~rzTB@>X5P`bG& zlCaS|fY`RB0Revvqei4-k3h10|xvzJuU6$ zQ2HzU(oz$s|K6@=lU7x*R8+r?2w{`>@A2Ozw)#iu2G7rTL;mSUsY;i4p5;INJBq{q zk&jzv@o&2^QMIZV;dhO4@5oFHDta2nrP*LSnPBQNbW#8$o1+AN-jSe_nTn&{MAfYtFOlfwk3@v-M~h(M`w2XFba8errh zV;K7ddbn058Nc?Jx9>PlJ!3-wfhzX`mzx-3<&Jk03r6;qxho9J6fU|0?xHh{<5E0f zo91SkaZHQ@vk>mw$2KGrnrm;wCPjKK3tNY+3IQ;5vGOE+{j%k0Raa3&sp=Ancuc9Bt>*HrhdU&@4k4)OeyBP#fV9;-Ed7o0p(P{f zPu~}am*OT4L_2vvap`8p3d242Q0P1p^{vxdBi3mqML+E!=NxXP!nPoXX~;m7N%5v8 zxMl*6&m+bP*epRVx0Gf9dFd#ToA&N+Ch7aI)!uSnNVF-*#2G;ww?Y4$-N%5U6y~^Y^5M0ms=@1eJ(%lb+{u@ zTT~xEoGcR`8ey5RN;t|$6<<%E$8c>oMnJO}B|g$%2(T(>b=WAOS~1j{8G=(;?l%q! zZ3@F4GB~WXwKK#`T>yJaDLrTTD#4Ts$Dw*eGH2PhAz+z0T-9!362G2= z{CR6w;mZ>AqxjRWM?rt?vY;m>ra6xJ(rM2>Ca_Qf3=L13^=bQHq$|QowYeg!K#MCP zzHf3x#P@B2K9(8bilEqQ<(acww|!2wj}rEL@TWo8KY-vKU}&rTxM#;&=+a_Ykw+-nv7sTJD>;v$ z9`56IX(>*F!J(KpJbD+3U=%l5x9i*1T9cgjquWQ}vOh z2xN<;V>*K2UBS*4e-UlLfT+||vl<4+I99vSAmCHYf-2}woDY7 z04A&J(2%Gv+N#7)2W4GBXZsc7?8}Z|DH2fOI#6TQtE9c}WIa%}D(ht;QLOcTetKgI zaX(pO)-x&bmXKJDCHs4=E>6dmY<=0S2D0OgP~QCmR$Ka@Rez`W+mdMihIo?N7^%YB zXJ(t|EE31$Uqx-HnFWrg#Z$Qz9C1h~7Hd1CWMvRZue?4UJ;v#K{m~Qv5Z<>OQnC^w z4=GuxX5ntH#}UDouFTU+xc^5j%8e4{tXJZhnm-S6odY%DdNPY4-M|y%xkzOF9=*8# z-1Ygt@1~2%QZ)#EPtYTw_RXZ+|3#Z}Z-nvT{gNFEq~%b5EIWtk5N0QEMgQ?}q7Pzq zu$*B~j1HLY>bLC8!~vP127dDUPNI_+Kr_H_U(ahLbvE|1O2sWZ^- zvOzx=BLUh&0_gqQ4W#^?FbLtOqdbU9LS7qCt~4 zEowA|`CvVUSqFG<^QU;2-E_YL3}ZEB7-qdoIyRW#Bk-7=!56D(O!z_zgUNE{!0rCS zG`Vx!V$BZmb(u4Uaf@Xy6o=>TQPj(TTU;kp>+w>Doj?|!+|iKbAhJyIOpv9!oiK}; z9!ON31lss;B`k)zK*(XZqOJ?B&~(5nCgF+3)D4t=AZaIp+!~MYp%jo%MlA<3)I!?< zwiu41ZSIl=JSTYu0SW@FhF(^oOR4R4=rY`Gq_{4HVE2w{wrVX2D~&JRP{m9FM?kwJ z>=NhMtP6hr1e?h@Z7PK&jMMBecnM7x2;A=ZZ3Zuug${b)IH>Lc>1l6g9pB+<1&LNDgjXfeNp_buiZD>2giVx^kRFZTMKG7s#uo%l4OW8LA@G>Tyhq{Y46L-_8?U2$*qG+h{OjNBshr$?Y#g7Lf7fOIRM` zp_v-vi!2g$r~GK+Ko(kw;$#hvfn*x&FSIMMUfjYkCWt9D+YVytd#hXHlPqm$v#NL$8j`zHkipP(4 zahEdxaIMzQpIzXCIZes)th_J@D^!1Yiz^jxA_Qbdu4zKDkz?mAIbJv4=Uf z!tWd(94xBJ?L~raWN5&yf<7)g3zgO96AP6UakCIp99v135>q_}qL{00YmpFO4q9+n zk;ogl;*`%N9C}g7hT0ZNNfVZ0UyS5`uh9-pS9Mz-u<5T9*+kzj9@;0-`;CI>shDg{5*?tIXPAXy8(VX z*`2U@$nP*vn602#1>83E>xOFG9W15eUYxxFGoTDT$&*3!Y-G*I?vy@rDf>tlJ{x!< z@~u|M)gt>w!qX3Cfal}iJ-zq%Gk1Kl_w?jYUHat0a01cP5)(WbOAnSOXDhIvPMk2b zC(qF`jwuOoGE6IY^Na&S`{M<<(!=t{lT0*Q=GmM(B0vymF6l5x6Zl zLHtuI{#7wTLbCmd0O~~R03)ts3jdJ`+5R$_|^ zYUPuH+6>=W6Tp)sS~1h_X+_hT`>SU-^s);J~9Rle&A{(mQmhk*WZVi z`++78`TWE`|Lob*haNRk`q&0pnSMo`$;AI^UiO3e$q$+3376M;@sNJBeYykAv)}7T zBY!zV>6Ip?cc%dJRA%4v$Mq)?O9~QtZY!&+2j~hX8l_mJ(m44o2am(ErHgR5t)6S1 zS;u4c=C{2$zscQOuHr9Ju7iovUZP`yO>aPmO~E z#R@&pA8Dy|3lg-IgmXNFEGtDS$k(uhgUbr!DZE(<L?U_|JXe%24dF+U3OK7wsoBn& zQ@1Io73ZM^w5eC<^OQa{vTY|NR&6UAe6sk5k%_S$6u&fRhJy{D-Ur>V3ZshY}80$e?nyucQu zERi$v_hvVfFkXp_Jv-AbguKRtsY|`po=|R$f{vX%xid{Y=$>SA(vhn;Mu4k`3|CCGoOq5uN)8! zVKGXHN4%6SQ^eD)T|BV#vGbnVYAsYEu_Ui+8-WNisO9iUaW9iB+ z_x~UFR3!<&G1E<-^U!aBH4t$Du!Hr9R7pp`6r&=Yf4-zN;fj**GEMFy?yC*}*$2sR zDbT4v;Q`fGbCJSF$Fc?Pe7{9{TUIpCfn*fY8go?8%AktuMDE*wXapq zSlBm{l~aBD!#YV4tD!~wx<{HwF2WcS>10s!PvqX2#qxwRWraScF)f)&U~e z0BSWjflcZ5{ULBuNdjz|sSvrD4YschQ*ZptvbNejU$Gyl0y!V{hPqLAYhGQ+^%`Z) zAzq?K44RYUfQ9_ZwlG0xa?ZA{ORMzXcV<{*Z7+2?ZL=gWUx1n-B{L)cRNG@KXhMnx z%{4NU&rOWCX|Xvw%D*AaJ1ZCAoL`k{y|;qr#EVl+;*6F$?_M%asCcHPcCM2z(?7Ah zXAg^TJ!FaGd{w^V^r!BSPlTHUf>H6#qldVczvyzl4#x&f&_ke~DhYTViXX~&`R13BZXV-}|&`Fo28HeFnI zMj!^IHQ{dSp6~yBb`AnN@a2;#q+r%F)cr{cm#oDr57x)RK9Wc>i={m{v^uY_3&maQQk5Q{v(pe z)6^H9%Ze{q!u6sLfHYpl)ClT*gkN2R1o>taVBnMceLa(tY_4uGZ~gR2?%|q3>5(Km-P194^-QId3b?+@_ z@7jAy)9Q(ysItAEq0L+CHk~ktyYjdHwRm2YC0qq^{CEl*DlLDf@tr!McrzHKH2k0h zxy4ri*9oPm+8hw>KIEEo&=yx=4|1?!x6U6oLr3^DiWz{Sz)yrV~~(~B9Wjzp(tmiR?F-s4lpB(>?&&73$-HIz_ov6 zE>#}fCCQ&C>Lz2%t<*KI>gLBS3&tE6wgWx8=y)5Tt>7lmZbW-&hl@2BZ$?QLu)i~V zP4Rz#Lk{f;EtCbu7i61~9+5n@gcIo-!l!b}1;>EDIHr!c|#jRDOP>GHcRKr%#bB`puzPOq)!dP5Q)ku`FMl2}h59=p`bhg>K zyJ!6rwr73+o688v;4AvHUO@H~3&B-fVT6QG z+^#sfLZ*`;d6H-|3dHnG6*qzTm8CF&;>`}+zIg0ynFbG%ocXyRN`och0x#BM6ub)? zN^-CY&~Pk7<)hj)K6O<&NF^g2tn%YF9^;7Q)iJ`J*Qp)(p+qK@37PPO)3Q6m*i&or z&O8)TF-htb=*5mV3PK~>(dnfA#dah)ezcSTlUytl#%uz zI`bee8#s(xgK&z+iT_7tuPekqE}f2U94t(~oT!U)%!&1`u-*A=CDJb;9-&|>M!+Q( zIlr}Ba*Y=X8TU+C)XDvILF;3tz=b&`0uXFKCfxOU9)C>mg#V(&czgzx`$zxkcR%y^ zXa4)Y`1@z>ICAITe&dh-{stRJEjPKtZXaL0yyS}T3F?`PNaEe(!Ms6n<-^bkrP?pQ zE0vsQdcQuw6+T?O#71l`hw5vRxd$aUPN;~*0i=w}^VL!LJhc_cgs?zwL5SPHb0HjS zn{!##t38Ck;)UdGH8gO)U_2qQd%SbA+e3?%XwEf{$8B{jBe(X} zB&lWc9s$p2jB*=Rh3(Lvv0`Dv`>E6CZX&UQ`Nydw=YzbPJ*T}%PmK5@_QI=_okft>ab95P zeXoioeIp$&Gsk)>Zq|mkoi_)I1Hv1pl!APf<+Bw%xBq0ZM)a37$WDpO4NlVN61bvu={wU$|? z2K+>iNv8dMhY1w;pUg~v3%j0wVRi)S38Aj;PPWTbU780uIYKM-TDe!}LRWnfEBL>C zTwt@=4bUS|J_IjO`r|?AYeJvHO$aREgr_GpXR||vRkR!QGlTZ9=Vq@KGw`Sty>F5G z+h77#3>s~~9n275S{G-xbXs)GI-A4hP}f-}>N+zDX$qD@r5_vt!+oT&OsJagdNhXN zu_R*mT78nrAmu>G2ZVt_DyoCl8oSMeqaBIKexQfRPZ}m|J`+dfUrB+QVh`QB;R!Ju|0>@y>;sr;}CfTS8{Y zs?;8V^(rRBJStJO#UjYP&{Y)hx+rY zBTVHzm1aTT6)&8XyeS@R_Vb0SIch|&!6_Yy_hfbB~NQfA6_ zRpU$6BoQtsKNn_1`T(RDtA^bVHmyX6qOCWW>l>=@H#3BWtEDi>wx{AE>XMKyJTO`f zDL)%Hub3x%U3of8SS$@Gy5!~*wa3&+OqHF$r$CPgoa?f?vx%ZRXfa}nf;t9hi6(=V zv`yS@5=tx0KT%O}f}9F&*;u?X4EW&2mjyR|@8gbH0aBP&jU2}+=iNXi$N8vFw6^;M z=qVJ9WT%+4nQ%`o&<2LAp|v52PB~OgGfNyb0b`wXC=_mp{j@QKWju#1c=a+e;W;*k zFl1`A%xpHZ!+Y0KkHS|OK2>mLW98$xs4o*l7uN>#AUa|RtT7G7jh?Glr4!tZRPipF zEG5=w6n`XxM)(3Ft!FV4CTN^&M^yJAN&jB$vBog5`%uM2h=h-q649jNS2}4aKvy%u z`T8qW8wRm|h4&|8qlE@;U4dIf3=as*35#SwT*AT;nIkz(^r~03&sAl~jGK;nZ9>Yz zNIHOD$oSFdtu4tRVipMU;K-^Q_RQ8%h|@i3*i1Oz4XP+6zcgalEG>O%7Qf^;hmucD z_|w7cfYibDyE|VTb6~`N_X|lWRehDKD1_?!E`!`XdoU}se>6k5UC&AUZtOrEUG~9B z@c4>4tmrVT#y*%ujNV{_a#T_?Xv#KH1%^IbG9^*x+i*m@NOwU|0h^Be_BiKeM`5U= z(!g<8w(OOdAF*JfrM@zVg)=FZ)mVxQdsRP$yn%iH96faq+)_qsz^h?vkdz5H9Utc?-Ovqrg1 zTBEJ`O$>0`2E*A-o6I+pz>5j?5TmsD12Pm! zemg=JdEVe^rQh9oT@i}@%OZT|W)!i&ul#h^WmU+<`ylS;B7f|htCo>lt3IfjBSijv zrrJsh(kN0JO1I&w?M}395Tp9~X2?Q?7^m*+%muYYTNz6(5z});Ng`;XSWHv&H0mat zR|UP6=@B@S6g!sbpo5MiJ7@wbm|lh(r_5#1HgORUs}QeX;Q`khLol^40s=+0uM5&S zNoWVwrQo7NfYgZ;J8rnE;fUu*)nK2>!ibVjTI6aVlDLmVVWsvajrs65SI5T$nz+WJ z=GsTvBOe#DY5178~?LSuqs&GBrZ={~0 zdqRND&!25Nu9}X+RPF;JjZbf2I9L=hkAqB_&0S5*PSWF!BDtExgbzQda^rHWv8W&C zxKZ>j|6AguS8A<4NS^m%sT%gK#9F2z)wg6|>A#4oumW9sprWet%Q!hSiq)fER79yj zV)&2^fKQ+w7xoFWn-|sq> zS_f2b3WA(H0Zl{{L$q@k$^tL|wDI{FD+w{jX5Xx&*OT-Ho5|(cMgmLz0gKQW5@mKB zMIP9&nkBivP!jBrP0)*$s5L?=943>hE!-yAY#$@^uRUzf%fkpc zLa#>foCtl|6Zrnq0r-cQVUBba=oHGUlmi*YE2DP>Iw8ORz4{pET!$iJKBR+}16&20 zKXC`}_BpB(+!WcO7_0Nz=as>Y{oSGK2G$>Gg|#k;;8jW>0j2WUysAXQR;FcS+MxGZ z{2SSrhU$-dqPf{6qIJnFNXdYlS5ftx43Uh%z5tR#G>W#LQ>12O4`RX}EGf#2u1V1^ zS1J1L8Pr;2Xn^{&d5;Et*E4yKazGT?N_hLX5X+$2_S=lu2tM0T`$tqqFR1b^?d zhp+GFe3Skl6Zhu>*D-qXIXjJSN={)!6AXSk~8VCZy?dE@U@`Mu=_QAhwVNaI6ar`M)W1gfe^| z7l^^l1&D_i5t4k#4~n9Q7C8GMeMF_9hEb%?tgJ({Q_e(@-zR2USVK;U5F>KAM_9PV zl?}s$B0g1B;tOjMrtA)OLyeq?B0cJn2U&*KxndatplUG3SVa3;l?6xH4~+MUja3P6 zR+(CH{$pgsK`x@Gi_Aqb={ws>je}*lXbWPyh7xT&XB$ZWUO zh{Lc%+NQNM1T#xvR!<6!S(b6^R)4m|WHiu^6-9yBBxh)ecgo*+F)7ZQ|4u{Ss{KxG z(tKIQIS*8&a2}_m1j7;MA~Lbcs^cUlCgZVzn*K~f2P2Z=+}zV^>?o%Nhw@STRWJ3E zDP_cL{#2F&E;*?7DUngqyN3DEI~sn(VNe-J^+0YMVMFhfYh-m4A!^B^*~L&jCOf`M z^%xejz-Nr-yvusW3njr>RvOVC*`~)x=r79cfmHp%EayY$FNFoj8cojuT2DV9t6xz2 z#>k35Ix(O-9#TPwAleat$mI=-@z^wtF2i0oE9q&`8>&=#57JOpQv^9j8$oWus#CgF zyVs$K-irBVXBN-73!{gHjfb5!DPrfNv}#`EaT>)*t7w!+ao$=E+%+2WQqY(qKl#%? z`?fQ0Kk@VTfAXH*=@EaOhsL&W)O>kt4?!+y| zB{YH?qxgy2kXVv$EhYJev}+g9Yq*{z2@J`mIN_do``#(WKGhw2Z+T|@!t4f%93q*> zyt&YN5Cp}_Eko>;ycXBiB7BnykR)Sb`zK~O2Te=`&1mHLr$UReHzDbUw~omwE>c49 z#eEh9YF7rwrB~`bY_+9f@=&=@PjLB+5C9^ymS9EV*CgMv^BQq)etxYYb=7zrX&RKX%VgZIaUeWR3Ny zPSnLZ0yUoOd~tsY)aZV5sY0dtwQ2Xu?UO4c_VRR^e9|1zF+b*SX>ZM({tTrr_ZatJ z4)qx}yA1Xi)XAG3H8*OkC{U6UDON+5uH+RbYs{F?T7zy_O=Tm|9ioziZ;ozQHl#G1 zWJr+yEesOkBsTaua=w&}pwckHbk=0IabyOb!7LI$ZnW(nVjTcX`wL!Mx-#pjw~GK7 ztcd4<%n*U6%^MBTAC$xsR9+%z5q%Ncer&h$Y$m9Mv|~(4^vggcey{{gJ+0}qhqK1B zqTvNkX-e&VSN$I-c0;1O<$j77S+A`~boEd{7!=~jro~M(`kJ@%rKIy$h|>0yZYZaM zfVo6pEnA_aTI{pUTa0(a!qDk@Q*@QZd$Cqt%P_(1^bGPtAkx( zFP7s5tPj5o(L9U1nHDHxN-ul*`W>ODM=_r0<3P{dCz&xFBz5&1<@(FWT2^Iss{QQP z9O}NswFl~wzL9t3E8DC9(sPXPNoUuc`=)?kOi&}VsTmso!_tlmOx!+%i?O%+Y=Pqz z4V028=v~4kzKUM_YYCX1*A(G#qf=v+O}D`6F!C<25?ZprHYnl&=OJqh^0Mmsb6q6v z?IiO71P?NtE1%Yt+y?zX253?n1S%gO?5q-;bzAlvpiUKt<4%!txsist7LVMEmlCU? z6u?2zSIl~4q{}HZRwEr<;^)(gQkO}DtUx0~t&l!r5|>Y+tVZyTuuhP`vQC#t!mLIC zwhG*)K`y7jxj6`@T~0F1<#I`&?ICPU!wTXdJd?{Tk}_QT=1Z;N{+I2!%t9*TO$TMT zQI}r+Fn>~+ReCMdUb0iQiDuJ6?G_^zYQFz>h+qqsqU^VD(c}we6ML&il3*ZWuRd6r z8v|V1Moq8qoqt9#06FX~b?UbfR$VxWDZnoE=(l5*9%348yK)Y~AkskIF*B%k6vlNq zT(^fg^w5dtio1H2G0riC?r|~hP4TT zHW88$F?|XbiG+H0wyeBqs+ipKW?Y-ROC~+m08Ggqx`bq4c=1AWu$&+7zD-BvzU z5eLr(szEhm#Bq$+vU|t-Q5%CxjD`#$$^Mn2GR&x6m}#mNpEAbIR1f=h+gLJW&jy7c zHaYUo$I5e7s787dCOf>@jIeHp$cbM@drZ3=L#VAv78W(EO)4XHZIGb2H0S3llZNeR z%FchKZNKL8582L-Hn;k6&v!vGc|y&mQSvb<}+w=VJUw_GLBuXBZX|L zc2nhQnx>;AYH~9aYYwL=;H6ZK$zZtg;thCiE~%J{!B{AVHQ?RTopBOPL;vNaf)fnZ zB5Oc!^n+6e1nyhdJp^GqwR;1G9#TtaR6wSxmTUl#kFW%kH`1NN58(;IvN}X=r$lV_%=?ke+)a z=Y6m9@edqDvazZ~SGWFTifS3qi?`Pxd99XTA2Rc?MgLx;3$;^*RyY3B`arj9VpPqQ zv*+e0_#<_N9U&Q;mI5>^Aq!5kqa-)=zo?~pQ}2-{Sr zYT)RmSl-=RIADAyik4PbFf7WcUaTjz6HTk2SPt!hvISAApbX)%4Oy$e#IjJ1cw`LGQihh`|D7C(>qM&i#*f{Csj6jCP`K!1@I$`f?pkP1vBLrBZI*Q43al z{BBEVkoCRQFLb_20$Ph`&}W16ZS%?2q^33274P-p37t`XV%RX9z8`jF{I+P^soCja z$_5BGqRD)T`C-r-lUg09(V(-(jqqEAP!`ge6c1ShjuR4t_KovN51eJOZL&6b@p~9{ zoeoVdRV3V%3=L?To*8Z=h8xEVk+)%!a%lN2(Y)s>!7IMV&j*i-a(P9a!Dv}dPx7Li zHgcRUW-`Y}p&A$KHsQ%gPJdx5-TSB=^P*Y~6i{_2V zeHm3VvIrJtMX`ex^*RUDl}KW^=!g`U0iK@|Ojks7Hs1Mim2$jXUr#-@riqp1(JJB9 zLL>^R2uoCnIJGJ@#Tm_Srp8;TsRjFQlf|^i2>#P{S~vRslB$>6=vRbvCRzN6AsLZ< zc~mie*x8N{ptS!@$%^`c06$Jq-3`~DLO9iJ72Pmljnmji2^;TN&gV7MvwSp0 zaUY#sT<&4pJuxTp5>g;a>r}bym?KV8V#a!Isgk4Xv@sbatp!~U$}F@)*0_n%t;Par z6D!@tS#5qb8nSz>)TE%{_l90P2^SLAQ#zI?%sxqWj`G8$o#M#py|F2xK(1+~hL5eXQP< z9rr5YnpcF|-939+`!!Za?$b55<88e4{7E#z7bpsJe)bGxlS98=j2D$Nh|KxS?_?{P z|M~3VT=@v|Ju(dd1=TXBVRhrv+%(WltT4EsB}LC-tmxdQ6GuF1j(E|^$WhXkRZJYs zLl%}|G|o(th%UVgLw?PCeUy0?E_%Y`8ww)XaJ*cTFb*#GhQtMvz?y9?3=NyecILtv zEdgt6D8+Si;hA`+{6Feba%zSmp*8Z!iuK82Qv~ezrTQd%l4VpV7Otj-a7~qbioqI= z2YNN@O2(dwnQ2XI6Y(6C_*l~?af80+_KJ8O<5jHAd9YIxkPvpksL%*0KvkZHCSHW+0H>mmuEqD&kFDo_j^O)qBOOUYIG_dr9f(!B|~vsj6Oe zES`Hz9niQ&LcQf~M~AwmVy9IxE1|Ca#grmrBjJBBb-~>4K^c4;5%`d+m50;sZ_jCuhW4 ztS>!><@g8Wfsi!#mypaed8A9|MR|D`L|c1;37&SmEk!EZ>ewMB^F$LFeoe}Kvx*_Rpl?0SW@o08BYWU)-^;C`odN*7%~FM z73_R#Q+dCV52@Ni`chCXp%7~V9X<;e$g8{!9nibfWZi&#cEjh;ft^V8HU(NcpjmY@ zH$-q3W6BFsuk>^-V+ZVwm8dJY*9U19y?zn3TQ`OYH(D|4ki*}I!`OTBp*K;l114DwvyH)wjH`FfLh=aeZ%bq=}Ic$4a_ ztN$Bnv6To8+~kIc&((EP7I8#^`}XBn+Ht|xKrPprENgMJ_WYD}To&UhgPcEMEeiJ@ zk$)4!h8V{-2^rKr7QD6TxEfRO(k|nH^ z0Bv%d(S+$vPYnQ88G>4_Kc28CT`Neda}3{TqK-+QKm^u#(=#sQyQh>~*8Tz7MuYovR+D+!Z2W4peYC=&HY+FnuKS z4@2z-#z^>!3c5xVmRAz*Rk#^Dx2QYjP#HLI#Vv^6>@}pPQ55g&QcatikvK%=z(;Xo zi-qnH2nTZvuVa*g9TeG{A%t*Qtk#(ly1Z?_T465d%99i65hxK3jrM9y@eS<N%$X$3a0ZyX-46c2J@5wjZvry;u9_+fHF5H4WOB)~TKi3d1PbnOyn5Y@Wl zwa*o4o*EG=T4SJV=kBK^A}ES%7=XtClb9)3x6cotG5}Ju=B_^y$Y3hu<3rpG@8nFdFK%`lU$N|hcAg`_K!2n zIUnXe?!-Am#BEPwn2QShZd|m$NBAtvblbouZww>u#5!^7TWn`e^_W`+JZX-*aZ7YQ zD*f!WhRahNG3#MQPGfD)9YZIXqhYj0izsYIzmCQ`X}n!HVs-rLwM-Xk$|9I1xQjB^ zw{vMU$on`8OvCNQ0_(F<_+T25*^hHSE$6P>ueGFA0B=5@TbUWtz+1ArtjKaBYJQiG z=rtYir803|5f1lnvEiV^qu-Ai8^5tTgG*+|Z>u=Vav$TzxK8+uOJs1_>iBKlZ(a*S ziyJgFeuE3Q1AF5g21x6Zy2j6qYKMZm3tux}mAxx0En)`<^;#c+3?oyLCqvxTf}O!a zxOMOV9M8Dy$njKBAHq_wc~uH9z`%;uR^kp`o0A&1*Byn;uG}!Jmr@{55pA}GUnv$r z)btQR(8}si#Wa0CtwJUgwr7%O!nlb_Q4m13x1l|c&q*^s*;11f3cK*l=Vh}*UG0pI z;Vp+c7=?IwYKoDjQ?WH8eJ)Dfbw;;u5MLi!JbRGWU@PTPE3gY^6$&WKg{9^VU{kDH zE~-;75hRgjzbm8Feq&<25e;)g&GboNE!ZNzWp%q;py;7JGCm{wIv_s#E05B zhceV^rx6Njp*$MBQkE&lH9hq8dmMoHUwIDTvVL+!xbz>282ztN7L8*8_JJwUfpe%a z^6tescw~b2p6LsqGlYn%_zOrk=aU(nWL$ zZkQ6uEJ-H4L!&6>V53a~t{RR?JU$gi-7?3Y6O-_4hvNNMHxw@={)=oRKA91Hy}WW! z=_I-P;H}V*ip5sZB)DFe^Xumgn2XB!z=#Wk316Z2b10fm+KKsRQd7)mm9cN@wjwSF zC=u?+Co5b?;Xc#nwqx3)n3%I-C=@4XsyyadOlNaRvP}Xfek$rNB;X|Ru%Jz|eB59| zixQLV9t9u1IYCEto}rgW{JOC3gie7SFI$jzQ=VQA$PSa3?eJX^L)k8Sa*y!aSSBSrsh~RDCM?1} z@tgv2T-=YFi&PyVSa3c+38D0wr0{9=Pw13WBouVYEZhxyMiVNV!Hs{d3T{jsSVuA& ze_I>(*L6~odMt)bz{`oto-H{FSi)7oln(x?h+k|oR9YvIbSi8z7Rq)bZTw~ zP9mJ~tqj^YfQ6Eo!`o4--u~;FNA^q={J4!Rd7Cy@gwNkS%HkDcX%^3=Qk2^1Q7`Mg zbur!*%?b7yuL^c=X5!D&cDyK9YI-6PmAKAC)QPQd`8dldrS&i;c|122x|bm-K85~@ zh`F5`tXu4|hdFgKvO6|_vY)KvQ<~CUGbQe5O58e>e2RD((5W29 zbBRyvHpRvJBb*rIS8EF9qT*GwRXa|^t-IyK`;B{UoHP)-8eFfuU*~Ar?pPIkFk$Cc zgKq9x;k!4~FHbwfcM-Ctc(yLCBlC27CoErvV|L+Z>T58%zLqk!iiF6^wRKVL@g0iV z(Upj589Ec#$v}k$o0vcAV9B(BQdPblIfk5-9jjOmMbfn~68qbtAoXy-9N?zI0oXf&!~JVwNF*P^ko9>-&JEJVF9snibTOHLiKjtQ(Yp#3tSILpmr(@F;>I{! z62(2mBZ?Y*MXu_Fn6YiBTZ8v?Nf>M_;IEOC(InGkOA3SAcTw3*PLz6Gx93tv;IpO6 z!YJI_5+jWR;tq1CB&g=~Mwvt)$B<`-Tk}Wyn;~d*wv0@ZgO%g$wg`613ty#*d%{rGzHzgALZe2SxveONJY_hO zs(Wu0>NYg)z$>bQ7(;8V&lE%+0D`?4dX6 zKPaP4(hZEb%d9X0cQ+!d&7}~EN#bPrvX;;I$*hm(W06T?SUj__Wc(~-=&7V7nUbKd z8JMTUJ3(#C1s%^2q!qhub1>Vl^W?q7R#Mhf(tsb8$E*^IZu;3Y$g~{Ctqm+AH^k~l zb0UBd7A9B|>ByNuR1F0CdN9uxZ4A#t&+KH}al*(Nm()T01^_-kJ5dP#Asg%bwV<2S zXN%0p13G|zpTtJes4SsWWM}Ak_MdtD}q)6 z!wa1zR|^&2oceUiKO1uQ?8Vx0lroH1`L&^JH3qpqG#W_aH>2^N44b3fyis4~OG>T? z{+|p*Yti91lGbuiH6GMl+?abz3etu3^^_u_TB6hy$T%?(F__W;E7z}Y!+71q`>kG_ zpS>peX~X|oEYn0bNl{T+XU_v}L*||PD}{l3rr@TaAP75HAd$dSutb^w*M}NRZfOYo=N)?SK>dC-Y5wq*_5eQM2m&>=lVub4*^R4K*FlPQ;4Bj+lUc zqe#kDCOCS20}p~*9Y3Uban@Y~WYW5nB*uptT;&hUxK&oeUylF|^i?e2Y z_JsdGyV*Jof2lFA34y}1IAiTo0GmZTv7E1bNz%+32B*ele9o&6Z4>r95%9{;Uk~fi zX7DP-;rp%ys>YnGNk#g+q!F)ynAjgQu#REnJ+Wj(qFPzfz_oA6r39;<9(j3Qbkr+2 zU1PB?R~Gv}b!Q$K@wB{yBXW)!@DFDblW*B*xa*ztnIGo7so=ZIMLto-$!NUsI2lgN zVKe}Ap5+taE=jfqbsPzrN&TqE7ygiB@HkjmWpVX)-}8&Jo3io}4Y>j0Tg538vH}*A z9OPXbEbVu(Q63CH@!(;_+Wxh^glvlQz`r5giK64O)s(uE1zks_W*19Bx9beY#2jy8 zC0~r1r27WbeeH4+Q35Nf~TVv#}LI?Oa7M6o9= z6E`SLFe7B+;aE^?bO~X{ch;!YBtSV7)7uOA+>3<6{rj20r7F zSp}INEvhO&lJ+XG7qhDF6D&31gq|DeDQWZG0RCwE&SJ5syphBb`nG0>^N|M8{n!%0 zMU&m>J;;PD3zPL<*~DEu>A0g@XUnRR0tg1zS6*6PL>Y7P(=hz1%s97dqF;q7+6Dx# W{e?~d Date: Thu, 23 Mar 2023 10:43:27 +0000 Subject: [PATCH 639/898] Fix representation hardcoded to png --- openpype/hosts/maya/plugins/publish/extract_playblast.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_playblast.py b/openpype/hosts/maya/plugins/publish/extract_playblast.py index 31cb3435acc..f8bc6987c6b 100644 --- a/openpype/hosts/maya/plugins/publish/extract_playblast.py +++ b/openpype/hosts/maya/plugins/publish/extract_playblast.py @@ -207,9 +207,9 @@ def process(self, instance): collected_files = collected_files[0] representation = { - 'name': 'png', - 'ext': 'png', - 'files': collected_files, + "name": self.capture_preset["Codec"]["compression"], + "ext": self.capture_preset["Codec"]["compression"], + "files": collected_files, "stagingDir": stagingdir, "frameStart": start, "frameEnd": end, From 6eeed5d8e72031acb1b7238cc04083821c633262 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 23 Mar 2023 10:43:36 +0000 Subject: [PATCH 640/898] Code cosmetics --- .../maya/plugins/publish/extract_playblast.py | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_playblast.py b/openpype/hosts/maya/plugins/publish/extract_playblast.py index f8bc6987c6b..ab1e1a65c6f 100644 --- a/openpype/hosts/maya/plugins/publish/extract_playblast.py +++ b/openpype/hosts/maya/plugins/publish/extract_playblast.py @@ -43,7 +43,7 @@ def process(self, instance): self.log.info("start: {}, end: {}".format(start, end)) # get cameras - camera = instance.data['review_camera'] + camera = instance.data["review_camera"] preset = lib.load_capture_preset(data=self.capture_preset) # Grab capture presets from the project settings @@ -57,23 +57,23 @@ def process(self, instance): asset_height = asset_data.get("resolutionHeight") review_instance_width = instance.data.get("review_width") review_instance_height = instance.data.get("review_height") - preset['camera'] = camera + preset["camera"] = camera # Tests if project resolution is set, # if it is a value other than zero, that value is # used, if not then the asset resolution is # used if review_instance_width and review_instance_height: - preset['width'] = review_instance_width - preset['height'] = review_instance_height + preset["width"] = review_instance_width + preset["height"] = review_instance_height elif width_preset and height_preset: - preset['width'] = width_preset - preset['height'] = height_preset + preset["width"] = width_preset + preset["height"] = height_preset elif asset_width and asset_height: - preset['width'] = asset_width - preset['height'] = asset_height - preset['start_frame'] = start - preset['end_frame'] = end + preset["width"] = asset_width + preset["height"] = asset_height + preset["start_frame"] = start + preset["end_frame"] = end # Enforce persisting camera depth of field camera_options = preset.setdefault("camera_options", {}) @@ -86,8 +86,8 @@ def process(self, instance): self.log.info("Outputting images to %s" % path) - preset['filename'] = path - preset['overwrite'] = True + preset["filename"] = path + preset["overwrite"] = True pm.refresh(f=True) @@ -139,7 +139,7 @@ def process(self, instance): ) override_viewport_options = ( - capture_presets['Viewport Options']['override_viewport_options'] + capture_presets["Viewport Options"]["override_viewport_options"] ) with lib.maintained_time(): filename = preset.get("filename", "%TEMP%") @@ -147,7 +147,7 @@ def process(self, instance): # Force viewer to False in call to capture because we have our own # viewer opening call to allow a signal to trigger between # playblast and viewer - preset['viewer'] = False + preset["viewer"] = False # Update preset with current panel setting # if override_viewport_options is turned off @@ -183,7 +183,7 @@ def process(self, instance): self.log.debug("filename {}".format(filename)) frame_collection = None for collection in collections: - filebase = collection.format('{head}').rstrip(".") + filebase = collection.format("{head}").rstrip(".") self.log.debug("collection head {}".format(filebase)) if filebase in filename: frame_collection = collection @@ -213,9 +213,9 @@ def process(self, instance): "stagingDir": stagingdir, "frameStart": start, "frameEnd": end, - 'fps': fps, - 'preview': True, - 'tags': tags, - 'camera_name': camera_node_name + "fps": fps, + "preview": True, + "tags": tags, + "camera_name": camera_node_name } instance.data["representations"].append(representation) From 81b659e933591e3fbabc9ea1b57ce99a25ef5396 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= <33513211+antirotor@users.noreply.github.com> Date: Thu, 23 Mar 2023 12:06:01 +0100 Subject: [PATCH 641/898] Update openpype/hosts/max/plugins/publish/increment_workfile_version.py --- .../hosts/max/plugins/publish/increment_workfile_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/plugins/publish/increment_workfile_version.py b/openpype/hosts/max/plugins/publish/increment_workfile_version.py index 7b4f4e238d6..3dec214f777 100644 --- a/openpype/hosts/max/plugins/publish/increment_workfile_version.py +++ b/openpype/hosts/max/plugins/publish/increment_workfile_version.py @@ -16,4 +16,4 @@ def process(self, context): filepath = version_up(path) rt.saveMaxFile(filepath) - self.log.info('Incrementing file version') + self.log.info("Incrementing file version") From 0a085c7001db46671d26beb0c8a59de1a37a58a2 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 23 Mar 2023 12:06:05 +0100 Subject: [PATCH 642/898] Kitsu: Slightly less strict with instance data (#4678) * Match family and families * Allow kitsu note to not have set comment and capture it without erroring in IntegrateKitsuReview * Allow fallback to context for instance `task` * Shush hound * Refactor variable names --- .../kitsu/plugins/publish/collect_kitsu_entities.py | 2 +- .../modules/kitsu/plugins/publish/integrate_kitsu_note.py | 5 ++++- .../kitsu/plugins/publish/integrate_kitsu_review.py | 8 ++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py index a0bd2b305b1..4ea8135620e 100644 --- a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py +++ b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py @@ -29,7 +29,7 @@ def process(self, context): if not zou_asset_data: raise ValueError("Zou asset data not found in OpenPype!") - task_name = instance.data.get("task") + task_name = instance.data.get("task", context.data.get("task")) if not task_name: continue diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 6fda32d85f5..6be14b3bdf1 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -48,7 +48,10 @@ def replace_missing_key(match): def process(self, context): for instance in context: # Check if instance is a review by checking its family - if "review" not in instance.data["families"]: + # Allow a match to primary family or any of families + families = set([instance.data["family"]] + + instance.data.get("families", [])) + if "review" not in families: continue kitsu_task = instance.data.get("kitsu_task") diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py index 12482b56573..e05ff05f50a 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py @@ -12,17 +12,17 @@ class IntegrateKitsuReview(pyblish.api.InstancePlugin): optional = True def process(self, instance): - task = instance.data["kitsu_task"]["id"] - comment = instance.data["kitsu_comment"]["id"] # Check comment has been created - if not comment: + comment_id = instance.data.get("kitsu_comment", {}).get("id") + if not comment_id: self.log.debug( "Comment not created, review not pushed to preview." ) return # Add review representations as preview of comment + task_id = instance.data["kitsu_task"]["id"] for representation in instance.data.get("representations", []): # Skip if not tagged as review if "kitsureview" not in representation.get("tags", []): @@ -31,6 +31,6 @@ def process(self, instance): self.log.debug("Found review at: {}".format(review_path)) gazu.task.add_preview( - task, comment, review_path, normalize_movie=True + task_id, comment_id, review_path, normalize_movie=True ) self.log.info("Review upload on comment") From 5197aa2ce7737dd15aa6941515a4fc0669edd046 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 23 Mar 2023 11:51:49 +0000 Subject: [PATCH 643/898] Suggestion to change labels. --- .../schemas/projects_schema/schemas/schema_maya_capture.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json index 1f0e4eeffbd..cec4b6eb909 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json @@ -19,12 +19,12 @@ { "type": "text", "key": "compression", - "label": "Compression type" + "label": "Encoding" }, { "type": "text", "key": "format", - "label": "Data format" + "label": "Format" }, { "type": "number", From d0f083ec195a0e4ac639865c14d50635d318bb6e Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 23 Mar 2023 12:52:25 +0100 Subject: [PATCH 644/898] Publisher: Explicit save (#4676) * added save button class * added save button to window * workfiles is also part of context in CreateContext to be able check if context changed * window cares about trigger of convertors * use abstractproperty with property and abstractmethod decorators * save changes happens using main window and can be blocked * fix pyside compatibility * use create context to get current context names * Fix docstring label * added shortcuts for save and reset * change control string matching for macos * added 'publish_has_started' property * allow save only if publishing did not start yet * rename 'get_selected_convertors' to 'get_selected_legacy_convertors' and added docstrings * Added Saved changes * disable instances toggle when publishing started * Fix reset button tooltip Co-authored-by: Roy Nieterau * Use QKeySequence to string for tooltips * added example output * use predefined method to emit card message --------- Co-authored-by: Roy Nieterau --- openpype/pipeline/create/context.py | 91 +++++++-- openpype/tools/publisher/constants.py | 5 +- openpype/tools/publisher/control.py | 185 +++++++++++++----- openpype/tools/publisher/widgets/__init__.py | 6 +- .../publisher/widgets/card_view_widgets.py | 19 ++ .../tools/publisher/widgets/images/save.png | Bin 0 -> 3961 bytes .../publisher/widgets/list_view_widgets.py | 27 +++ .../publisher/widgets/overview_widget.py | 38 +++- openpype/tools/publisher/widgets/widgets.py | 34 +++- openpype/tools/publisher/window.py | 127 ++++++++++-- openpype/tools/traypublisher/window.py | 2 +- 11 files changed, 450 insertions(+), 84 deletions(-) create mode 100644 openpype/tools/publisher/widgets/images/save.png diff --git a/openpype/pipeline/create/context.py b/openpype/pipeline/create/context.py index acc2bb054fe..22cab28e4b9 100644 --- a/openpype/pipeline/create/context.py +++ b/openpype/pipeline/create/context.py @@ -22,7 +22,7 @@ deserialize_attr_defs, get_default_values, ) -from openpype.host import IPublishHost +from openpype.host import IPublishHost, IWorkfileHost from openpype.pipeline import legacy_io from openpype.pipeline.plugin_discover import DiscoverResult @@ -1374,6 +1374,7 @@ def __init__( self._current_project_name = None self._current_asset_name = None self._current_task_name = None + self._current_workfile_path = None self._host_is_valid = host_is_valid # Currently unused variable @@ -1503,14 +1504,62 @@ def host_name(self): return os.environ["AVALON_APP"] def get_current_project_name(self): + """Project name which was used as current context on context reset. + + Returns: + Union[str, None]: Project name. + """ + return self._current_project_name def get_current_asset_name(self): + """Asset name which was used as current context on context reset. + + Returns: + Union[str, None]: Asset name. + """ + return self._current_asset_name def get_current_task_name(self): + """Task name which was used as current context on context reset. + + Returns: + Union[str, None]: Task name. + """ + return self._current_task_name + def get_current_workfile_path(self): + """Workfile path which was opened on context reset. + + Returns: + Union[str, None]: Workfile path. + """ + + return self._current_workfile_path + + @property + def context_has_changed(self): + """Host context has changed. + + As context is used project, asset, task name and workfile path if + host does support workfiles. + + Returns: + bool: Context changed. + """ + + project_name, asset_name, task_name, workfile_path = ( + self._get_current_host_context() + ) + return ( + self._current_project_name != project_name + or self._current_asset_name != asset_name + or self._current_task_name != task_name + or self._current_workfile_path != workfile_path + ) + project_name = property(get_current_project_name) @property @@ -1575,6 +1624,28 @@ def reset_finalization(self): self._collection_shared_data = None self.refresh_thumbnails() + def _get_current_host_context(self): + project_name = asset_name = task_name = workfile_path = None + if hasattr(self.host, "get_current_context"): + host_context = self.host.get_current_context() + if host_context: + project_name = host_context.get("project_name") + asset_name = host_context.get("asset_name") + task_name = host_context.get("task_name") + + if isinstance(self.host, IWorkfileHost): + workfile_path = self.host.get_current_workfile() + + # --- TODO remove these conditions --- + if not project_name: + project_name = legacy_io.Session.get("AVALON_PROJECT") + if not asset_name: + asset_name = legacy_io.Session.get("AVALON_ASSET") + if not task_name: + task_name = legacy_io.Session.get("AVALON_TASK") + # --- + return project_name, asset_name, task_name, workfile_path + def reset_current_context(self): """Refresh current context. @@ -1593,24 +1664,14 @@ def reset_current_context(self): are stored. We should store the workfile (if is available) too. """ - project_name = asset_name = task_name = None - if hasattr(self.host, "get_current_context"): - host_context = self.host.get_current_context() - if host_context: - project_name = host_context.get("project_name") - asset_name = host_context.get("asset_name") - task_name = host_context.get("task_name") - - if not project_name: - project_name = legacy_io.Session.get("AVALON_PROJECT") - if not asset_name: - asset_name = legacy_io.Session.get("AVALON_ASSET") - if not task_name: - task_name = legacy_io.Session.get("AVALON_TASK") + project_name, asset_name, task_name, workfile_path = ( + self._get_current_host_context() + ) self._current_project_name = project_name self._current_asset_name = asset_name self._current_task_name = task_name + self._current_workfile_path = workfile_path def reset_plugins(self, discover_publish_plugins=True): """Reload plugins. diff --git a/openpype/tools/publisher/constants.py b/openpype/tools/publisher/constants.py index b2bfd7dd5cd..5d23886aa81 100644 --- a/openpype/tools/publisher/constants.py +++ b/openpype/tools/publisher/constants.py @@ -1,4 +1,4 @@ -from qtpy import QtCore +from qtpy import QtCore, QtGui # ID of context item in instance view CONTEXT_ID = "context" @@ -26,6 +26,9 @@ CONVERTER_IDENTIFIER_ROLE = QtCore.Qt.UserRole + 8 CREATOR_SORT_ROLE = QtCore.Qt.UserRole + 9 +ResetKeySequence = QtGui.QKeySequence( + QtCore.Qt.ControlModifier | QtCore.Qt.Key_R +) __all__ = ( "CONTEXT_ID", diff --git a/openpype/tools/publisher/control.py b/openpype/tools/publisher/control.py index 49e7eeb4f7f..b62ae7ecc15 100644 --- a/openpype/tools/publisher/control.py +++ b/openpype/tools/publisher/control.py @@ -6,7 +6,7 @@ import uuid import tempfile import shutil -from abc import ABCMeta, abstractmethod, abstractproperty +from abc import ABCMeta, abstractmethod import six import pyblish.api @@ -964,7 +964,8 @@ class AbstractPublisherController(object): access objects directly but by using wrappers that can be serialized. """ - @abstractproperty + @property + @abstractmethod def log(self): """Controller's logger object. @@ -974,13 +975,15 @@ def log(self): pass - @abstractproperty + @property + @abstractmethod def event_system(self): """Inner event system for publisher controller.""" pass - @abstractproperty + @property + @abstractmethod def project_name(self): """Current context project name. @@ -990,7 +993,8 @@ def project_name(self): pass - @abstractproperty + @property + @abstractmethod def current_asset_name(self): """Current context asset name. @@ -1000,7 +1004,8 @@ def current_asset_name(self): pass - @abstractproperty + @property + @abstractmethod def current_task_name(self): """Current context task name. @@ -1010,7 +1015,21 @@ def current_task_name(self): pass - @abstractproperty + @property + @abstractmethod + def host_context_has_changed(self): + """Host context changed after last reset. + + 'CreateContext' has this option available using 'context_has_changed'. + + Returns: + bool: Context has changed. + """ + + pass + + @property + @abstractmethod def host_is_valid(self): """Host is valid for creation part. @@ -1023,7 +1042,8 @@ def host_is_valid(self): pass - @abstractproperty + @property + @abstractmethod def instances(self): """Collected/created instances. @@ -1134,7 +1154,13 @@ def create( @abstractmethod def save_changes(self): - """Save changes in create context.""" + """Save changes in create context. + + Save can crash because of unexpected errors. + + Returns: + bool: Save was successful. + """ pass @@ -1145,7 +1171,19 @@ def remove_instances(self, instance_ids): pass - @abstractproperty + @property + @abstractmethod + def publish_has_started(self): + """Has publishing finished. + + Returns: + bool: If publishing finished and all plugins were iterated. + """ + + pass + + @property + @abstractmethod def publish_has_finished(self): """Has publishing finished. @@ -1155,7 +1193,8 @@ def publish_has_finished(self): pass - @abstractproperty + @property + @abstractmethod def publish_is_running(self): """Publishing is running right now. @@ -1165,7 +1204,8 @@ def publish_is_running(self): pass - @abstractproperty + @property + @abstractmethod def publish_has_validated(self): """Publish validation passed. @@ -1175,7 +1215,8 @@ def publish_has_validated(self): pass - @abstractproperty + @property + @abstractmethod def publish_has_crashed(self): """Publishing crashed for any reason. @@ -1185,7 +1226,8 @@ def publish_has_crashed(self): pass - @abstractproperty + @property + @abstractmethod def publish_has_validation_errors(self): """During validation happened at least one validation error. @@ -1195,7 +1237,8 @@ def publish_has_validation_errors(self): pass - @abstractproperty + @property + @abstractmethod def publish_max_progress(self): """Get maximum possible progress number. @@ -1205,7 +1248,8 @@ def publish_max_progress(self): pass - @abstractproperty + @property + @abstractmethod def publish_progress(self): """Current progress number. @@ -1215,7 +1259,8 @@ def publish_progress(self): pass - @abstractproperty + @property + @abstractmethod def publish_error_msg(self): """Current error message which cause fail of publishing. @@ -1267,7 +1312,8 @@ def run_action(self, plugin_id, action_id): pass - @abstractproperty + @property + @abstractmethod def convertor_items(self): pass @@ -1356,6 +1402,7 @@ def __init__(self): self._publish_has_validation_errors = False self._publish_has_crashed = False # All publish plugins are processed + self._publish_has_started = False self._publish_has_finished = False self._publish_max_progress = 0 self._publish_progress = 0 @@ -1386,7 +1433,8 @@ def event_system(self): "show.card.message" - Show card message request (UI related). "instances.refresh.finished" - Instances are refreshed. "plugins.refresh.finished" - Plugins refreshed. - "publish.reset.finished" - Publish context reset finished. + "publish.reset.finished" - Reset finished. + "controller.reset.started" - Controller reset started. "controller.reset.finished" - Controller reset finished. "publish.process.started" - Publishing started. Can be started from paused state. @@ -1425,7 +1473,16 @@ def _get_host_is_valid(self): def _set_host_is_valid(self, value): if self._host_is_valid != value: self._host_is_valid = value - self._emit_event("publish.host_is_valid.changed", {"value": value}) + self._emit_event( + "publish.host_is_valid.changed", {"value": value} + ) + + def _get_publish_has_started(self): + return self._publish_has_started + + def _set_publish_has_started(self, value): + if value != self._publish_has_started: + self._publish_has_started = value def _get_publish_has_finished(self): return self._publish_has_finished @@ -1449,7 +1506,9 @@ def _get_publish_has_validated(self): def _set_publish_has_validated(self, value): if self._publish_has_validated != value: self._publish_has_validated = value - self._emit_event("publish.has_validated.changed", {"value": value}) + self._emit_event( + "publish.has_validated.changed", {"value": value} + ) def _get_publish_has_crashed(self): return self._publish_has_crashed @@ -1497,6 +1556,9 @@ def _set_publish_error_msg(self, value): host_is_valid = property( _get_host_is_valid, _set_host_is_valid ) + publish_has_started = property( + _get_publish_has_started, _set_publish_has_started + ) publish_has_finished = property( _get_publish_has_finished, _set_publish_has_finished ) @@ -1526,6 +1588,7 @@ def _reset_attributes(self): """Reset most of attributes that can be reset.""" self.publish_is_running = False + self.publish_has_started = False self.publish_has_validated = False self.publish_has_crashed = False self.publish_has_validation_errors = False @@ -1645,10 +1708,7 @@ def project_name(self): str: Project name. """ - if not hasattr(self._host, "get_current_context"): - return legacy_io.active_project() - - return self._host.get_current_context()["project_name"] + return self._create_context.get_current_project_name() @property def current_asset_name(self): @@ -1658,10 +1718,7 @@ def current_asset_name(self): Union[str, None]: Asset name or None if asset is not set. """ - if not hasattr(self._host, "get_current_context"): - return legacy_io.Session["AVALON_ASSET"] - - return self._host.get_current_context()["asset_name"] + return self._create_context.get_current_asset_name() @property def current_task_name(self): @@ -1671,10 +1728,11 @@ def current_task_name(self): Union[str, None]: Task name or None if task is not set. """ - if not hasattr(self._host, "get_current_context"): - return legacy_io.Session["AVALON_TASK"] + return self._create_context.get_current_task_name() - return self._host.get_current_context()["task_name"] + @property + def host_context_has_changed(self): + return self._create_context.context_has_changed @property def instances(self): @@ -1751,6 +1809,8 @@ def reset(self): """Reset everything related to creation and publishing.""" self.stop_publish() + self._emit_event("controller.reset.started") + self.host_is_valid = self._create_context.host_is_valid self._create_context.reset_preparation() @@ -1992,7 +2052,15 @@ def get_subset_name( ) def trigger_convertor_items(self, convertor_identifiers): - self.save_changes() + """Trigger legacy item convertors. + + This functionality requires to save and reset CreateContext. The reset + is needed so Creators can collect converted items. + + Args: + convertor_identifiers (list[str]): Identifiers of convertor + plugins. + """ success = True try: @@ -2039,13 +2107,33 @@ def create( self._on_create_instance_change() return success - def save_changes(self): - """Save changes happened during creation.""" + def save_changes(self, show_message=True): + """Save changes happened during creation. + + Trigger save of changes using host api. This functionality does not + validate anything. It is required to do checks before this method is + called to be able to give user actionable response e.g. check of + context using 'host_context_has_changed'. + + Args: + show_message (bool): Show message that changes were + saved successfully. + + Returns: + bool: Save of changes was successful. + """ + if not self._create_context.host_is_valid: - return + # TODO remove + # Fake success save when host is not valid for CreateContext + # this is for testing as experimental feature + return True try: self._create_context.save_changes() + if show_message: + self.emit_card_message("Saved changes..") + return True except CreatorsOperationFailed as exc: self._emit_event( @@ -2056,16 +2144,17 @@ def save_changes(self): } ) + return False + def remove_instances(self, instance_ids): """Remove instances based on instance ids. Args: instance_ids (List[str]): List of instance ids to remove. """ - # QUESTION Expect that instances are really removed? In that case save - # reset is not required and save changes too. - self.save_changes() + # QUESTION Expect that instances are really removed? In that case reset + # is not required. self._remove_instances_from_context(instance_ids) self._on_create_instance_change() @@ -2136,12 +2225,22 @@ def set_comment(self, comment): self._publish_comment_is_set = True def publish(self): - """Run publishing.""" + """Run publishing. + + Make sure all changes are saved before method is called (Call + 'save_changes' and check output). + """ + self._publish_up_validation = False self._start_publish() def validate(self): - """Run publishing and stop after Validation.""" + """Run publishing and stop after Validation. + + Make sure all changes are saved before method is called (Call + 'save_changes' and check output). + """ + if self.publish_has_validated: return self._publish_up_validation = True @@ -2152,10 +2251,8 @@ def _start_publish(self): if self.publish_is_running: return - # Make sure changes are saved - self.save_changes() - self.publish_is_running = True + self.publish_has_started = True self._emit_event("publish.process.started") diff --git a/openpype/tools/publisher/widgets/__init__.py b/openpype/tools/publisher/widgets/__init__.py index 042985b007e..f18e6cc61e0 100644 --- a/openpype/tools/publisher/widgets/__init__.py +++ b/openpype/tools/publisher/widgets/__init__.py @@ -4,8 +4,9 @@ get_icon ) from .widgets import ( - StopBtn, + SaveBtn, ResetBtn, + StopBtn, ValidateBtn, PublishBtn, CreateNextPageOverlay, @@ -25,8 +26,9 @@ "get_pixmap", "get_icon", - "StopBtn", + "SaveBtn", "ResetBtn", + "StopBtn", "ValidateBtn", "PublishBtn", "CreateNextPageOverlay", diff --git a/openpype/tools/publisher/widgets/card_view_widgets.py b/openpype/tools/publisher/widgets/card_view_widgets.py index 3fd5243ce94..0734e1bc274 100644 --- a/openpype/tools/publisher/widgets/card_view_widgets.py +++ b/openpype/tools/publisher/widgets/card_view_widgets.py @@ -164,6 +164,11 @@ def _update_ordered_item_ids(self): def _on_widget_selection(self, instance_id, group_id, selection_type): self.selected.emit(instance_id, group_id, selection_type) + def set_active_toggle_enabled(self, enabled): + for widget in self._widgets_by_id.values(): + if isinstance(widget, InstanceCardWidget): + widget.set_active_toggle_enabled(enabled) + class ConvertorItemsGroupWidget(BaseGroupWidget): def update_items(self, items_by_id): @@ -437,6 +442,9 @@ def __init__(self, instance, group_icon, parent): self.update_instance_values() + def set_active_toggle_enabled(self, enabled): + self._active_checkbox.setEnabled(enabled) + def set_active(self, new_value): """Set instance as active.""" checkbox_value = self._active_checkbox.isChecked() @@ -551,6 +559,7 @@ def __init__(self, controller, parent): self._context_widget = None self._convertor_items_group = None + self._active_toggle_enabled = True self._widgets_by_group = {} self._ordered_groups = [] @@ -667,6 +676,9 @@ def refresh(self): group_widget.update_instances( instances_by_group[group_name] ) + group_widget.set_active_toggle_enabled( + self._active_toggle_enabled + ) self._update_ordered_group_names() @@ -1091,3 +1103,10 @@ def set_selected_items( self._explicitly_selected_groups = selected_groups self._explicitly_selected_instance_ids = selected_instances + + def set_active_toggle_enabled(self, enabled): + if self._active_toggle_enabled is enabled: + return + self._active_toggle_enabled = enabled + for group_widget in self._widgets_by_group.values(): + group_widget.set_active_toggle_enabled(enabled) diff --git a/openpype/tools/publisher/widgets/images/save.png b/openpype/tools/publisher/widgets/images/save.png new file mode 100644 index 0000000000000000000000000000000000000000..0db48d74ae2660e8766fc2bcd30ed794fd067068 GIT binary patch literal 3961 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 0: dialog_x -= diff @@ -549,6 +633,14 @@ def _on_context_or_active_change(self): def _on_create_request(self): self._go_to_create_tab() + def _on_convert_requested(self): + if not self._save_changes(False): + return + convertor_identifiers = ( + self._overview_widget.get_selected_legacy_convertors() + ) + self._controller.trigger_convertor_items(convertor_identifiers) + def _set_current_tab(self, identifier): self._tabs_widget.set_current_tab(identifier) @@ -599,8 +691,10 @@ def _set_publish_visibility(self, visible): self._publish_frame.setVisible(visible) self._update_publish_frame_rect() + def _on_save_clicked(self): + self._save_changes(True) + def _on_reset_clicked(self): - self.save_changes() self.reset() def _on_stop_clicked(self): @@ -610,14 +704,17 @@ def _set_publish_comment(self): self._controller.set_comment(self._comment_input.text()) def _on_validate_clicked(self): - self._set_publish_comment() - self._controller.validate() + if self._save_changes(False): + self._set_publish_comment() + self._controller.validate() def _on_publish_clicked(self): - self._set_publish_comment() - self._controller.publish() + if self._save_changes(False): + self._set_publish_comment() + self._controller.publish() def _set_footer_enabled(self, enabled): + self._save_btn.setEnabled(True) self._reset_btn.setEnabled(True) if enabled: self._stop_btn.setEnabled(False) diff --git a/openpype/tools/traypublisher/window.py b/openpype/tools/traypublisher/window.py index 3007fa66a51..3ac1b4c4adf 100644 --- a/openpype/tools/traypublisher/window.py +++ b/openpype/tools/traypublisher/window.py @@ -247,7 +247,7 @@ def resizeEvent(self, event): def _on_project_select(self, project_name): # TODO register project specific plugin paths - self._controller.save_changes() + self._controller.save_changes(False) self._controller.reset_project_data_cache() self.reset() From 79eb8f105f02c9309949d64d425f64095ac6e7c5 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 23 Mar 2023 12:54:55 +0100 Subject: [PATCH 645/898] celaction: make parameters enumerator --- .../celaction/hooks/pre_celaction_setup.py | 16 ++++++++++++++-- .../defaults/project_settings/celaction.json | 10 ++++------ .../schema_project_celaction.json | 19 +++++++++++++++---- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/openpype/hosts/celaction/hooks/pre_celaction_setup.py b/openpype/hosts/celaction/hooks/pre_celaction_setup.py index 7506f1a52cb..81f5f2bf11f 100644 --- a/openpype/hosts/celaction/hooks/pre_celaction_setup.py +++ b/openpype/hosts/celaction/hooks/pre_celaction_setup.py @@ -56,8 +56,20 @@ def execute(self): ] # Add custom parameters from workfile settings - if workfile_settings["parameters"]: - parameters += workfile_settings["parameters"] + if "render_chunk" in workfile_settings["submission_overrides"]: + parameters += [ + "--chunk *CHUNK*" + ] + elif "resolution" in workfile_settings["submission_overrides"]: + parameters += [ + "--resolutionWidth *X*", + "--resolutionHeight *Y*" + ] + elif "frame_range" in workfile_settings["submission_overrides"]: + parameters += [ + "--frameStart *START*", + "--frameEnd *END*" + ] winreg.SetValueEx( hKey, "SubmitParametersTitle", 0, winreg.REG_SZ, diff --git a/openpype/settings/defaults/project_settings/celaction.json b/openpype/settings/defaults/project_settings/celaction.json index 0194b2c48c3..822604fd2f2 100644 --- a/openpype/settings/defaults/project_settings/celaction.json +++ b/openpype/settings/defaults/project_settings/celaction.json @@ -10,12 +10,10 @@ } }, "workfile": { - "parameters": [ - "--chunk *CHUNK*", - "--frameStart *START*", - "--frameEnd *END*", - "--resolutionWidth *X*", - "--resolutionHeight *Y*" + "submission_overrides": [ + "render_chunk", + "frame_range", + "resolution" ] }, "publish": { diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_celaction.json b/openpype/settings/entities/schemas/projects_schema/schema_project_celaction.json index 4ca3cbb4da2..c5ca3eb9f56 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_celaction.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_celaction.json @@ -29,10 +29,21 @@ "label": "Workfile", "children": [ { - "key": "parameters", - "label": "Parameters", - "type": "list", - "object_type": "text" + "key": "submission_overrides", + "label": "Submission workfile overrides", + "type": "enum", + "multiselection": true, + "enum_items": [ + { + "render_chunk": "Pass chunk size" + }, + { + "frame_range": "Pass frame range" + }, + { + "resolution": "Pass resolution" + } + ] } ] }, From 011e635c1f91a3e49b282aaf3bf935da3ba31bd0 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 23 Mar 2023 12:56:54 +0100 Subject: [PATCH 646/898] hound --- openpype/hosts/celaction/hooks/pre_celaction_setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/celaction/hooks/pre_celaction_setup.py b/openpype/hosts/celaction/hooks/pre_celaction_setup.py index 81f5f2bf11f..c7e8bc5d0c8 100644 --- a/openpype/hosts/celaction/hooks/pre_celaction_setup.py +++ b/openpype/hosts/celaction/hooks/pre_celaction_setup.py @@ -58,8 +58,8 @@ def execute(self): # Add custom parameters from workfile settings if "render_chunk" in workfile_settings["submission_overrides"]: parameters += [ - "--chunk *CHUNK*" - ] + "--chunk *CHUNK*" + ] elif "resolution" in workfile_settings["submission_overrides"]: parameters += [ "--resolutionWidth *X*", From 54d566a4ee76924a2d091d4c3fbf7e0f076749df Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Thu, 23 Mar 2023 12:17:02 +0000 Subject: [PATCH 647/898] Update website/docs/admin_hosts_maya.md Co-authored-by: Roy Nieterau --- website/docs/admin_hosts_maya.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/admin_hosts_maya.md b/website/docs/admin_hosts_maya.md index fe30703c2e4..716bbadd881 100644 --- a/website/docs/admin_hosts_maya.md +++ b/website/docs/admin_hosts_maya.md @@ -139,7 +139,7 @@ Most settings to override in the viewport are self explanatory and can be found #### Camera Options -These camera options can be overridden when publishing the review. They can be found on the camera shape node. +These options are set on the camera shape when publishing the review. They correspond to attributes on the Maya camera shape node. ![Extract Playblast Settings](assets/maya-admin_extract_playblast_settings_camera_options.png) From f5117f4593f62b086e6af1809331c5d3580af73c Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 23 Mar 2023 14:28:05 +0100 Subject: [PATCH 648/898] celaction: fixes after testing --- .../hosts/celaction/hooks/pre_celaction_setup.py | 16 +++++++++------- .../plugins/publish/submit_celaction_deadline.py | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/celaction/hooks/pre_celaction_setup.py b/openpype/hosts/celaction/hooks/pre_celaction_setup.py index c7e8bc5d0c8..96e784875c2 100644 --- a/openpype/hosts/celaction/hooks/pre_celaction_setup.py +++ b/openpype/hosts/celaction/hooks/pre_celaction_setup.py @@ -58,17 +58,17 @@ def execute(self): # Add custom parameters from workfile settings if "render_chunk" in workfile_settings["submission_overrides"]: parameters += [ - "--chunk *CHUNK*" + "--chunk", "*CHUNK*" ] - elif "resolution" in workfile_settings["submission_overrides"]: + if "resolution" in workfile_settings["submission_overrides"]: parameters += [ - "--resolutionWidth *X*", - "--resolutionHeight *Y*" + "--resolutionWidth", "*X*", + "--resolutionHeight", "*Y*" ] - elif "frame_range" in workfile_settings["submission_overrides"]: + if "frame_range" in workfile_settings["submission_overrides"]: parameters += [ - "--frameStart *START*", - "--frameEnd *END*" + "--frameStart", "*START*", + "--frameEnd", "*END*" ] winreg.SetValueEx( @@ -76,6 +76,8 @@ def execute(self): subprocess.list2cmdline(parameters) ) + self.log.debug(f"__ parameters: \"{parameters}\"") + # setting resolution parameters path_submit = "\\".join([ path_user_settings, "Dialogs", "SubmitOutput" diff --git a/openpype/modules/deadline/plugins/publish/submit_celaction_deadline.py b/openpype/modules/deadline/plugins/publish/submit_celaction_deadline.py index 038ee4fc034..bcf08507687 100644 --- a/openpype/modules/deadline/plugins/publish/submit_celaction_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_celaction_deadline.py @@ -106,7 +106,7 @@ def payload_submit(self, # define chunk and priority chunk_size = instance.context.data.get("chunk") - if chunk_size == 0: + if not chunk_size: chunk_size = self.deadline_chunk_size # search for %02d pattern in name, and padding number From cc7a9f32c1efd58d89f18f0da4101d9df44666c6 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Thu, 23 Mar 2023 14:30:51 +0100 Subject: [PATCH 649/898] :art: add OP startup script for max to cmdline args --- openpype/settings/defaults/system_settings/applications.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/settings/defaults/system_settings/applications.json b/openpype/settings/defaults/system_settings/applications.json index 5fd9b926fb1..eb3a88ce665 100644 --- a/openpype/settings/defaults/system_settings/applications.json +++ b/openpype/settings/defaults/system_settings/applications.json @@ -133,7 +133,7 @@ "linux": [] }, "arguments": { - "windows": [], + "windows": ["-U MAXScript {OPENPYPE_ROOT}\\openpype\\hosts\\max\\startup\\startup.ms"], "darwin": [], "linux": [] }, From 0f6d969867821c077486cd685bb0c8efbeabac21 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 23 Mar 2023 14:35:58 +0100 Subject: [PATCH 650/898] fix shortcut key sequence check (#4694) --- openpype/tools/publisher/window.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/tools/publisher/window.py b/openpype/tools/publisher/window.py index c72b60d8261..8826e0f8495 100644 --- a/openpype/tools/publisher/window.py +++ b/openpype/tools/publisher/window.py @@ -439,7 +439,9 @@ def keyPressEvent(self, event): event.accept() return - if event.matches(ResetKeySequence): + if ResetKeySequence.matches( + QtGui.QKeySequence(event.key() | event.modifiers()) + ): if not self.controller.publish_is_running: self.reset() event.accept() From 93ad644f7488dcb0d10e6183618a85b0016850d3 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 23 Mar 2023 15:36:04 +0000 Subject: [PATCH 651/898] Use pan zoom in capture instead of collect/restore. --- openpype/hosts/maya/plugins/publish/extract_playblast.py | 9 ++------- openpype/hosts/maya/plugins/publish/extract_thumbnail.py | 9 ++------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_playblast.py b/openpype/hosts/maya/plugins/publish/extract_playblast.py index ab1e1a65c6f..bdb34474e83 100644 --- a/openpype/hosts/maya/plugins/publish/extract_playblast.py +++ b/openpype/hosts/maya/plugins/publish/extract_playblast.py @@ -113,11 +113,8 @@ def process(self, instance): preset["viewport_options"] = {"imagePlane": image_plane} # Disable Pan/Zoom. - pan_zoom = cmds.getAttr("{}.panZoomEnabled".format(preset["camera"])) - cmds.setAttr( - "{}.panZoomEnabled".format(preset["camera"]), - instance.data["panZoom"] - ) + preset.pop("pan_zoom", None) + preset["camera_options"]["panZoomEnabled"] = instance.data["panZoom"] # Need to explicitly enable some viewport changes so the viewport is # refreshed ahead of playblasting. @@ -170,8 +167,6 @@ def process(self, instance): instance.data["panel"], edit=True, **viewport_defaults ) - cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), pan_zoom) - self.log.debug("playblast path {}".format(path)) collected_files = os.listdir(stagingdir) diff --git a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py index 2d3daa53c6c..f2d084b8281 100644 --- a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py +++ b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py @@ -123,11 +123,8 @@ def process(self, instance): preset["viewport_options"] = {"imagePlane": image_plane} # Disable Pan/Zoom. - pan_zoom = cmds.getAttr("{}.panZoomEnabled".format(preset["camera"])) - cmds.setAttr( - "{}.panZoomEnabled".format(preset["camera"]), - instance.data["panZoom"] - ) + preset.pop("pan_zoom", None) + preset["camera_options"]["panZoomEnabled"] = instance.data["panZoom"] with lib.maintained_time(): # Force viewer to False in call to capture because we have our own @@ -148,8 +145,6 @@ def process(self, instance): _, thumbnail = os.path.split(playblast) - cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), pan_zoom) - self.log.info("file list {}".format(thumbnail)) if "representations" not in instance.data: From e7b2e0026f2769e5b1100af1a72e260f17404b65 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 23 Mar 2023 15:36:57 +0000 Subject: [PATCH 652/898] BigRoy feedback --- website/docs/admin_hosts_maya.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/website/docs/admin_hosts_maya.md b/website/docs/admin_hosts_maya.md index fe30703c2e4..6271feda15e 100644 --- a/website/docs/admin_hosts_maya.md +++ b/website/docs/admin_hosts_maya.md @@ -113,6 +113,8 @@ This is useful to fix some specific renderer glitches and advanced hacking of Ma ### Extract Playblast Settings (review) These settings provide granular control over how the playblasts or reviews are produced in Maya. +Some of these settings are also available on the instance itself, in which case these settings will become the default value when creating the review instance. + ![Extract Playblast Settings](assets/maya-admin_extract_playblast_settings.png) - **Compression type** which file encoding to use. @@ -126,8 +128,8 @@ These settings provide granular control over how the playblasts or reviews are p - **Off Screen** records the playblast hidden from the user. - **2D Pan/Zoom** enables the 2D Pan/Zoom functionality of the camera. - **Renderer name** which renderer to use for playblasting. -- **Width** width of the output resolution. -- **Height** height of the output resolution. +- **Width** width of the output resolution. If this value is `0`, the asset's width is used. +- **Height** height of the output resolution. If this value is `0`, the asset's height is used. #### Viewport Options From 525db92e4aaf083d6c92b08edde1ed84c0ed1710 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Thu, 23 Mar 2023 15:43:19 +0000 Subject: [PATCH 653/898] Update openpype/settings/defaults/project_settings/maya.json --- openpype/settings/defaults/project_settings/maya.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index 7757f201ad6..7b3d54f869c 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -926,7 +926,7 @@ "ogsfx_path": "/maya2glTF/PBR/shaders/glTF_PBR.ogsfx" }, "ExtractGPUCache": { - "enabled": true, + "enabled": false, "families": [ "model", "animation", From 8b9a3547d9feeb9516a119f08b6b3e5964abcee9 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 23 Mar 2023 17:15:40 +0100 Subject: [PATCH 654/898] adding project actions --- .github/workflows/project_actions.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/project_actions.yml diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml new file mode 100644 index 00000000000..9c8c9da7dda --- /dev/null +++ b/.github/workflows/project_actions.yml @@ -0,0 +1,23 @@ +name: project-actions + +on: + pull_request: + types: [review_requested, closed] + pull_request_review: + types: [submitted] + +jobs: + pr_review_requested: + name: pr_review_requested + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' && github.event.action == 'review_requested' + steps: + - name: Move PR to 'Change Requested' + uses: leonsteinhaeuser/project-beta-automations@v2.1.0 + with: + gh_token: ${{ secrets.YNPUT_BOT_TOKEN }} + user: ${{ secrets.CI_USER }} + organization: ynput + project_id: 11 + resource_node_id: ${{ github.event.pull_request.node_id }} + status_value: Change Requested From d88cd48b8eda227873191b830a5792f3403b1abf Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 24 Mar 2023 07:48:28 +0000 Subject: [PATCH 655/898] Refactor to nested/stacked contextlib --- .../maya/plugins/publish/extract_playblast.py | 85 ++++++++++++------- 1 file changed, 53 insertions(+), 32 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_playblast.py b/openpype/hosts/maya/plugins/publish/extract_playblast.py index a652db2eb5e..9d35789343a 100644 --- a/openpype/hosts/maya/plugins/publish/extract_playblast.py +++ b/openpype/hosts/maya/plugins/publish/extract_playblast.py @@ -1,5 +1,6 @@ import os import json +import contextlib import clique import capture @@ -11,6 +12,16 @@ import pymel.core as pm +@contextlib.contextmanager +def panel_camera(panel, camera): + original_camera = cmds.modelPanel(panel, query=True, camera=True) + try: + cmds.modelPanel(panel, edit=True, camera=camera) + yield + finally: + cmds.modelPanel(panel, edit=True, camera=original_camera) + + class ExtractPlayblast(publish.Extractor): """Extract viewport playblast. @@ -25,6 +36,31 @@ class ExtractPlayblast(publish.Extractor): optional = True capture_preset = {} + def _capture(self, preset, override_viewport_options, instance): + filename = preset.get("filename", "%TEMP%") + + # Force viewer to False in call to capture because we have our own + # viewer opening call to allow a signal to trigger between + # playblast and viewer + preset['viewer'] = False + + # Update preset with current panel setting + # if override_viewport_options is turned off + if not override_viewport_options: + panel_preset = capture.parse_view(instance.data["panel"]) + panel_preset.pop("camera") + preset.update(panel_preset) + + self.log.info( + "Using preset:\n{}".format( + json.dumps(preset, sort_keys=True, indent=4) + ) + ) + + path = capture.capture(log=self.log, **preset) + + return filename, path + def process(self, instance): self.log.info("Extracting capture..") @@ -112,15 +148,6 @@ def process(self, instance): else: preset["viewport_options"] = {"imagePlane": image_plane} - # Image planes do not update the file sequence unless the active panel - # is viewing through the camera. - panel_camera = cmds.modelPanel( - instance.data["panel"], query=True, camera=True - ) - cmds.modelPanel( - instance.data["panel"], edit=True, camera=preset["camera"] - ) - # Disable Pan/Zoom. pan_zoom = cmds.getAttr("{}.panZoomEnabled".format(preset["camera"])) cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), False) @@ -147,28 +174,25 @@ def process(self, instance): override_viewport_options = ( capture_presets['Viewport Options']['override_viewport_options'] ) - with lib.maintained_time(): - filename = preset.get("filename", "%TEMP%") - - # Force viewer to False in call to capture because we have our own - # viewer opening call to allow a signal to trigger between - # playblast and viewer - preset['viewer'] = False - - # Update preset with current panel setting - # if override_viewport_options is turned off - if not override_viewport_options: - panel_preset = capture.parse_view(instance.data["panel"]) - panel_preset.pop("camera") - preset.update(panel_preset) - - self.log.info( - "Using preset:\n{}".format( - json.dumps(preset, sort_keys=True, indent=4) + + if getattr(contextlib, "nested", None): + with contextlib.nested( + lib.maintained_time(), + panel_camera(instance.data["panel"], preset["camera"]) + ): + filename, path = self._capture( + preset, override_viewport_options, instance + ) + else: + with contextlib.ExitStack() as stack: + stack.enter_context(lib.maintained_time()) + stack.enter_context( + panel_camera(instance.data["panel"], preset["camera"]) ) - ) - path = capture.capture(log=self.log, **preset) + filename, path = self._capture( + preset, override_viewport_options, instance + ) # Restoring viewport options. if viewport_defaults: @@ -178,9 +202,6 @@ def process(self, instance): cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), pan_zoom) - # Restore panel camera. - cmds.modelPanel(instance.data["panel"], edit=True, camera=panel_camera) - self.log.debug("playblast path {}".format(path)) collected_files = os.listdir(stagingdir) From 4d42e58074c873f2247fa31e4d86b51c6c1b4262 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Fri, 24 Mar 2023 09:37:05 +0000 Subject: [PATCH 656/898] Update openpype/hosts/maya/plugins/publish/extract_playblast.py --- openpype/hosts/maya/plugins/publish/extract_playblast.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openpype/hosts/maya/plugins/publish/extract_playblast.py b/openpype/hosts/maya/plugins/publish/extract_playblast.py index 9d35789343a..e7dc42d2c00 100644 --- a/openpype/hosts/maya/plugins/publish/extract_playblast.py +++ b/openpype/hosts/maya/plugins/publish/extract_playblast.py @@ -175,7 +175,10 @@ def process(self, instance): capture_presets['Viewport Options']['override_viewport_options'] ) + # Need to ensure Python 2 compatibility. + # TODO: Remove once dropping Python 2. if getattr(contextlib, "nested", None): + # Python 3 compatibility. with contextlib.nested( lib.maintained_time(), panel_camera(instance.data["panel"], preset["camera"]) @@ -184,6 +187,7 @@ def process(self, instance): preset, override_viewport_options, instance ) else: + # Python 2 compatibility. with contextlib.ExitStack() as stack: stack.enter_context(lib.maintained_time()) stack.enter_context( From d1038ace686dea66069319b2a8e0df7df3c4e4c7 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 24 Mar 2023 09:44:39 +0000 Subject: [PATCH 657/898] Refactor _capture --- .../maya/plugins/publish/extract_playblast.py | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_playblast.py b/openpype/hosts/maya/plugins/publish/extract_playblast.py index e7dc42d2c00..9bd859ade18 100644 --- a/openpype/hosts/maya/plugins/publish/extract_playblast.py +++ b/openpype/hosts/maya/plugins/publish/extract_playblast.py @@ -37,29 +37,13 @@ class ExtractPlayblast(publish.Extractor): capture_preset = {} def _capture(self, preset, override_viewport_options, instance): - filename = preset.get("filename", "%TEMP%") - - # Force viewer to False in call to capture because we have our own - # viewer opening call to allow a signal to trigger between - # playblast and viewer - preset['viewer'] = False - - # Update preset with current panel setting - # if override_viewport_options is turned off - if not override_viewport_options: - panel_preset = capture.parse_view(instance.data["panel"]) - panel_preset.pop("camera") - preset.update(panel_preset) - self.log.info( "Using preset:\n{}".format( json.dumps(preset, sort_keys=True, indent=4) ) ) - path = capture.capture(log=self.log, **preset) - - return filename, path + return capture.capture(log=self.log, **preset) def process(self, instance): self.log.info("Extracting capture..") @@ -175,6 +159,18 @@ def process(self, instance): capture_presets['Viewport Options']['override_viewport_options'] ) + # Force viewer to False in call to capture because we have our own + # viewer opening call to allow a signal to trigger between + # playblast and viewer + preset['viewer'] = False + + # Update preset with current panel setting + # if override_viewport_options is turned off + if not override_viewport_options: + panel_preset = capture.parse_view(instance.data["panel"]) + panel_preset.pop("camera") + preset.update(panel_preset) + # Need to ensure Python 2 compatibility. # TODO: Remove once dropping Python 2. if getattr(contextlib, "nested", None): @@ -183,7 +179,7 @@ def process(self, instance): lib.maintained_time(), panel_camera(instance.data["panel"], preset["camera"]) ): - filename, path = self._capture( + path = self._capture( preset, override_viewport_options, instance ) else: @@ -194,7 +190,7 @@ def process(self, instance): panel_camera(instance.data["panel"], preset["camera"]) ) - filename, path = self._capture( + path = self._capture( preset, override_viewport_options, instance ) @@ -214,6 +210,7 @@ def process(self, instance): minimum_items=1, patterns=patterns) + filename = preset.get("filename", "%TEMP%") self.log.debug("filename {}".format(filename)) frame_collection = None for collection in collections: From 799a6b6cc457d4ef6b4b28f18fe6c831521376ea Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 24 Mar 2023 10:02:48 +0000 Subject: [PATCH 658/898] Remove path variable and _capture arguments. --- .../maya/plugins/publish/extract_playblast.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_playblast.py b/openpype/hosts/maya/plugins/publish/extract_playblast.py index 9bd859ade18..41e4f3a7c25 100644 --- a/openpype/hosts/maya/plugins/publish/extract_playblast.py +++ b/openpype/hosts/maya/plugins/publish/extract_playblast.py @@ -36,14 +36,15 @@ class ExtractPlayblast(publish.Extractor): optional = True capture_preset = {} - def _capture(self, preset, override_viewport_options, instance): + def _capture(self, preset): self.log.info( "Using preset:\n{}".format( json.dumps(preset, sort_keys=True, indent=4) ) ) - return capture.capture(log=self.log, **preset) + path = capture.capture(log=self.log, **preset) + self.log.debug("playblast path {}".format(path)) def process(self, instance): self.log.info("Extracting capture..") @@ -179,9 +180,7 @@ def process(self, instance): lib.maintained_time(), panel_camera(instance.data["panel"], preset["camera"]) ): - path = self._capture( - preset, override_viewport_options, instance - ) + self._capture(preset) else: # Python 2 compatibility. with contextlib.ExitStack() as stack: @@ -190,9 +189,7 @@ def process(self, instance): panel_camera(instance.data["panel"], preset["camera"]) ) - path = self._capture( - preset, override_viewport_options, instance - ) + self._capture(preset) # Restoring viewport options. if viewport_defaults: @@ -202,8 +199,6 @@ def process(self, instance): cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), pan_zoom) - self.log.debug("playblast path {}".format(path)) - collected_files = os.listdir(stagingdir) patterns = [clique.PATTERNS["frames"]] collections, remainder = clique.assemble(collected_files, From de4b3e4d659e38715a78290fc1c05e00fedb7432 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 24 Mar 2023 15:25:49 +0100 Subject: [PATCH 659/898] Ftrack: Hierarchical <> Non-Hierarchical attributes sync fix (#4635) * modify action to use 'CustomAttributeValue' and fix bugs * modify and fix event handler to push hierarchical values * added few smaller comments * removed unused variables --- .../action_push_frame_values_to_task.py | 316 +++-- .../event_push_frame_values_to_task.py | 1102 ++++++----------- 2 files changed, 549 insertions(+), 869 deletions(-) diff --git a/openpype/modules/ftrack/event_handlers_server/action_push_frame_values_to_task.py b/openpype/modules/ftrack/event_handlers_server/action_push_frame_values_to_task.py index 1209375f821..a698195c59d 100644 --- a/openpype/modules/ftrack/event_handlers_server/action_push_frame_values_to_task.py +++ b/openpype/modules/ftrack/event_handlers_server/action_push_frame_values_to_task.py @@ -9,7 +9,7 @@ class PushHierValuesToNonHier(ServerAction): - """Action push hierarchical custom attribute values to non hierarchical. + """Action push hierarchical custom attribute values to non-hierarchical. Hierarchical value is also pushed to their task entities. @@ -119,17 +119,109 @@ def attrs_configurations(self, session, object_ids, interest_attributes): self.join_query_keys(object_ids) )).all() - output = {} + attrs_by_obj_id = collections.defaultdict(list) hiearchical = [] for attr in attrs: if attr["is_hierarchical"]: hiearchical.append(attr) continue obj_id = attr["object_type_id"] - if obj_id not in output: - output[obj_id] = [] - output[obj_id].append(attr) - return output, hiearchical + attrs_by_obj_id[obj_id].append(attr) + return attrs_by_obj_id, hiearchical + + def query_attr_value( + self, + session, + hier_attrs, + attrs_by_obj_id, + dst_object_type_ids, + task_entity_ids, + non_task_entity_ids, + parent_id_by_entity_id + ): + all_non_task_ids_with_parents = set() + for entity_id in non_task_entity_ids: + all_non_task_ids_with_parents.add(entity_id) + _entity_id = entity_id + while True: + parent_id = parent_id_by_entity_id.get(_entity_id) + if ( + parent_id is None + or parent_id in all_non_task_ids_with_parents + ): + break + all_non_task_ids_with_parents.add(parent_id) + _entity_id = parent_id + + all_entity_ids = ( + set(all_non_task_ids_with_parents) + | set(task_entity_ids) + ) + attr_ids = {attr["id"] for attr in hier_attrs} + for obj_id in dst_object_type_ids: + attrs = attrs_by_obj_id.get(obj_id) + if attrs is not None: + for attr in attrs: + attr_ids.add(attr["id"]) + + real_values_by_entity_id = { + entity_id: {} + for entity_id in all_entity_ids + } + + attr_values = query_custom_attributes( + session, attr_ids, all_entity_ids, True + ) + for item in attr_values: + entity_id = item["entity_id"] + attr_id = item["configuration_id"] + real_values_by_entity_id[entity_id][attr_id] = item["value"] + + # Fill hierarchical values + hier_attrs_key_by_id = { + hier_attr["id"]: hier_attr + for hier_attr in hier_attrs + } + hier_values_per_entity_id = {} + for entity_id in all_non_task_ids_with_parents: + real_values = real_values_by_entity_id[entity_id] + hier_values_per_entity_id[entity_id] = {} + for attr_id, attr in hier_attrs_key_by_id.items(): + key = attr["key"] + hier_values_per_entity_id[entity_id][key] = ( + real_values.get(attr_id) + ) + + output = {} + for entity_id in non_task_entity_ids: + output[entity_id] = {} + for attr in hier_attrs_key_by_id.values(): + key = attr["key"] + value = hier_values_per_entity_id[entity_id][key] + tried_ids = set() + if value is None: + tried_ids.add(entity_id) + _entity_id = entity_id + while value is None: + parent_id = parent_id_by_entity_id.get(_entity_id) + if not parent_id: + break + value = hier_values_per_entity_id[parent_id][key] + if value is not None: + break + _entity_id = parent_id + tried_ids.add(parent_id) + + if value is None: + value = attr["default"] + + if value is not None: + for ent_id in tried_ids: + hier_values_per_entity_id[ent_id][key] = value + + output[entity_id][key] = value + + return real_values_by_entity_id, output def propagate_values(self, session, event, selected_entities): ftrack_settings = self.get_ftrack_settings( @@ -156,29 +248,24 @@ def propagate_values(self, session, event, selected_entities): } task_object_type = object_types_by_low_name["task"] - destination_object_types = [task_object_type] + dst_object_type_ids = {task_object_type["id"]} for ent_type in interest_entity_types: obj_type = object_types_by_low_name.get(ent_type) - if obj_type and obj_type not in destination_object_types: - destination_object_types.append(obj_type) - - destination_object_type_ids = set( - obj_type["id"] - for obj_type in destination_object_types - ) + if obj_type: + dst_object_type_ids.add(obj_type["id"]) interest_attributes = action_settings["interest_attributes"] # Find custom attributes definitions attrs_by_obj_id, hier_attrs = self.attrs_configurations( - session, destination_object_type_ids, interest_attributes + session, dst_object_type_ids, interest_attributes ) # Filter destination object types if they have any object specific # custom attribute - for obj_id in tuple(destination_object_type_ids): + for obj_id in tuple(dst_object_type_ids): if obj_id not in attrs_by_obj_id: - destination_object_type_ids.remove(obj_id) + dst_object_type_ids.remove(obj_id) - if not destination_object_type_ids: + if not dst_object_type_ids: # TODO report that there are not matching custom attributes return { "success": True, @@ -192,14 +279,14 @@ def propagate_values(self, session, event, selected_entities): session, selected_ids, project_entity, - destination_object_type_ids + dst_object_type_ids ) self.log.debug("Preparing whole project hierarchy by ids.") entities_by_obj_id = { obj_id: [] - for obj_id in destination_object_type_ids + for obj_id in dst_object_type_ids } self.log.debug("Filtering Task entities.") @@ -223,10 +310,16 @@ def propagate_values(self, session, event, selected_entities): "message": "Nothing to do in your selection." } - self.log.debug("Getting Hierarchical custom attribute values parents.") - hier_values_by_entity_id = self.get_hier_values( + self.log.debug("Getting Custom attribute values.") + ( + real_values_by_entity_id, + hier_values_by_entity_id + ) = self.query_attr_value( session, hier_attrs, + attrs_by_obj_id, + dst_object_type_ids, + task_entity_ids, non_task_entity_ids, parent_id_by_entity_id ) @@ -237,7 +330,8 @@ def propagate_values(self, session, event, selected_entities): hier_attrs, task_entity_ids, hier_values_by_entity_id, - parent_id_by_entity_id + parent_id_by_entity_id, + real_values_by_entity_id ) self.log.debug("Setting values to entities themselves.") @@ -245,7 +339,8 @@ def propagate_values(self, session, event, selected_entities): session, entities_by_obj_id, attrs_by_obj_id, - hier_values_by_entity_id + hier_values_by_entity_id, + real_values_by_entity_id ) return True @@ -322,112 +417,64 @@ def all_hierarchy_entities( return parent_id_by_entity_id, filtered_entities - def get_hier_values( - self, - session, - hier_attrs, - focus_entity_ids, - parent_id_by_entity_id - ): - all_ids_with_parents = set() - for entity_id in focus_entity_ids: - all_ids_with_parents.add(entity_id) - _entity_id = entity_id - while True: - parent_id = parent_id_by_entity_id.get(_entity_id) - if ( - not parent_id - or parent_id in all_ids_with_parents - ): - break - all_ids_with_parents.add(parent_id) - _entity_id = parent_id - - hier_attr_ids = tuple(hier_attr["id"] for hier_attr in hier_attrs) - hier_attrs_key_by_id = { - hier_attr["id"]: hier_attr["key"] - for hier_attr in hier_attrs - } - - values_per_entity_id = {} - for entity_id in all_ids_with_parents: - values_per_entity_id[entity_id] = {} - for key in hier_attrs_key_by_id.values(): - values_per_entity_id[entity_id][key] = None - - values = query_custom_attributes( - session, hier_attr_ids, all_ids_with_parents, True - ) - for item in values: - entity_id = item["entity_id"] - key = hier_attrs_key_by_id[item["configuration_id"]] - - values_per_entity_id[entity_id][key] = item["value"] - - output = {} - for entity_id in focus_entity_ids: - output[entity_id] = {} - for key in hier_attrs_key_by_id.values(): - value = values_per_entity_id[entity_id][key] - tried_ids = set() - if value is None: - tried_ids.add(entity_id) - _entity_id = entity_id - while value is None: - parent_id = parent_id_by_entity_id.get(_entity_id) - if not parent_id: - break - value = values_per_entity_id[parent_id][key] - if value is not None: - break - _entity_id = parent_id - tried_ids.add(parent_id) - - if value is not None: - for ent_id in tried_ids: - values_per_entity_id[ent_id][key] = value - - output[entity_id][key] = value - return output - def set_task_attr_values( self, session, hier_attrs, task_entity_ids, hier_values_by_entity_id, - parent_id_by_entity_id + parent_id_by_entity_id, + real_values_by_entity_id ): hier_attr_id_by_key = { attr["key"]: attr["id"] for attr in hier_attrs } + filtered_task_ids = set() for task_id in task_entity_ids: - parent_id = parent_id_by_entity_id.get(task_id) or {} + parent_id = parent_id_by_entity_id.get(task_id) parent_values = hier_values_by_entity_id.get(parent_id) - if not parent_values: - continue + if parent_values: + filtered_task_ids.add(task_id) + + if not filtered_task_ids: + return + for task_id in filtered_task_ids: + parent_id = parent_id_by_entity_id[task_id] + parent_values = hier_values_by_entity_id[parent_id] hier_values_by_entity_id[task_id] = {} + real_task_attr_values = real_values_by_entity_id[task_id] for key, value in parent_values.items(): hier_values_by_entity_id[task_id][key] = value + if value is None: + continue + configuration_id = hier_attr_id_by_key[key] _entity_key = collections.OrderedDict([ ("configuration_id", configuration_id), ("entity_id", task_id) ]) - - session.recorded_operations.push( - ftrack_api.operation.UpdateEntityOperation( - "ContextCustomAttributeValue", + op = None + if configuration_id not in real_task_attr_values: + op = ftrack_api.operation.CreateEntityOperation( + "CustomAttributeValue", + _entity_key, + {"value": value} + ) + elif real_task_attr_values[configuration_id] != value: + op = ftrack_api.operation.UpdateEntityOperation( + "CustomAttributeValue", _entity_key, "value", - ftrack_api.symbol.NOT_SET, + real_task_attr_values[configuration_id], value ) - ) - if len(session.recorded_operations) > 100: - session.commit() + + if op is not None: + session.recorded_operations.push(op) + if len(session.recorded_operations) > 100: + session.commit() session.commit() @@ -436,39 +483,68 @@ def push_values_to_entities( session, entities_by_obj_id, attrs_by_obj_id, - hier_values_by_entity_id + hier_values_by_entity_id, + real_values_by_entity_id ): + """Push values from hierarchical custom attributes to non-hierarchical. + + Args: + session (ftrack_api.Sessison): Session which queried entities, + values and which is used for change propagation. + entities_by_obj_id (dict[str, list[str]]): TypedContext + ftrack entity ids where the attributes are propagated by their + object ids. + attrs_by_obj_id (dict[str, ftrack_api.Entity]): Objects of + 'CustomAttributeConfiguration' by their ids. + hier_values_by_entity_id (doc[str, dict[str, Any]]): Attribute + values by entity id and by their keys. + real_values_by_entity_id (doc[str, dict[str, Any]]): Real attribute + values of entities. + """ + for object_id, entity_ids in entities_by_obj_id.items(): attrs = attrs_by_obj_id.get(object_id) if not attrs or not entity_ids: continue - for attr in attrs: - for entity_id in entity_ids: - value = ( - hier_values_by_entity_id - .get(entity_id, {}) - .get(attr["key"]) - ) + for entity_id in entity_ids: + real_values = real_values_by_entity_id.get(entity_id) + hier_values = hier_values_by_entity_id.get(entity_id) + if hier_values is None: + continue + + for attr in attrs: + attr_id = attr["id"] + attr_key = attr["key"] + value = hier_values.get(attr_key) if value is None: continue _entity_key = collections.OrderedDict([ - ("configuration_id", attr["id"]), + ("configuration_id", attr_id), ("entity_id", entity_id) ]) - session.recorded_operations.push( - ftrack_api.operation.UpdateEntityOperation( - "ContextCustomAttributeValue", + op = None + if attr_id not in real_values: + op = ftrack_api.operation.CreateEntityOperation( + "CustomAttributeValue", + _entity_key, + {"value": value} + ) + elif real_values[attr_id] != value: + op = ftrack_api.operation.UpdateEntityOperation( + "CustomAttributeValue", _entity_key, "value", - ftrack_api.symbol.NOT_SET, + real_values[attr_id], value ) - ) - if len(session.recorded_operations) > 100: - session.commit() + + if op is not None: + session.recorded_operations.push(op) + if len(session.recorded_operations) > 100: + session.commit() session.commit() diff --git a/openpype/modules/ftrack/event_handlers_server/event_push_frame_values_to_task.py b/openpype/modules/ftrack/event_handlers_server/event_push_frame_values_to_task.py index dc76920a57c..0f10145c066 100644 --- a/openpype/modules/ftrack/event_handlers_server/event_push_frame_values_to_task.py +++ b/openpype/modules/ftrack/event_handlers_server/event_push_frame_values_to_task.py @@ -1,6 +1,6 @@ import collections -import datetime import copy +from typing import Any import ftrack_api from openpype_modules.ftrack.lib import ( @@ -9,13 +9,30 @@ ) -class PushFrameValuesToTaskEvent(BaseEvent): +class PushHierValuesToNonHierEvent(BaseEvent): + """Push value changes between hierarchical and non-hierarchical attributes. + + Changes of non-hierarchical attributes are pushed to hierarchical and back. + The attributes must have same definition of custom attribute. + + Handler does not handle changes of hierarchical parents. So if entity does + not have explicitly set value of hierarchical attribute and any parent + would change it the change would not be propagated. + + The handler also push the value to task entity on task creation + and movement. To push values between hierarchical & non-hierarchical + add 'Task' to entity types in settings. + + Todos: + Task attribute values push on create/move should be possible to + enabled by settings. + """ + # Ignore event handler by default cust_attrs_query = ( "select id, key, object_type_id, is_hierarchical, default" " from CustomAttributeConfiguration" - " where key in ({}) and" - " (object_type_id in ({}) or is_hierarchical is true)" + " where key in ({})" ) _cached_task_object_id = None @@ -26,35 +43,35 @@ class PushFrameValuesToTaskEvent(BaseEvent): settings_key = "sync_hier_entity_attributes" - def session_user_id(self, session): - if self._cached_user_id is None: - user = session.query( - "User where username is \"{}\"".format(session.api_user) - ).one() - self._cached_user_id = user["id"] - return self._cached_user_id + def filter_entities_info( + self, event: ftrack_api.event.base.Event + ) -> dict[str, list[dict[str, Any]]]: + """Basic entities filter info we care about. - def launch(self, session, event): - filtered_entities_info = self.filter_entities_info(event) - if not filtered_entities_info: - return + This filtering is first of many filters. This does not query anything + from ftrack nor use settings. - for project_id, entities_info in filtered_entities_info.items(): - self.process_by_project(session, event, project_id, entities_info) + Args: + event (ftrack_api.event.base.Event): Ftrack event with update + information. + + Returns: + dict[str, list[dict[str, Any]]]: Filtered entity changes by + project id. + """ - def filter_entities_info(self, event): # Filter if event contain relevant data entities_info = event["data"].get("entities") if not entities_info: return - entities_info_by_project_id = {} + entities_info_by_project_id = collections.defaultdict(list) for entity_info in entities_info: - # Care only about tasks - if entity_info.get("entityType") != "task": + # Ignore removed entities + if entity_info.get("action") == "remove": continue - # Care only about changes of status + # Care only about information with changes of entities changes = entity_info.get("changes") if not changes: continue @@ -69,367 +86,287 @@ def filter_entities_info(self, event): if project_id is None: continue - # Skip `Task` entity type if parent didn't change - if entity_info["entity_type"].lower() == "task": - if ( - "parent_id" not in changes - or changes["parent_id"]["new"] is None - ): - continue - - if project_id not in entities_info_by_project_id: - entities_info_by_project_id[project_id] = [] entities_info_by_project_id[project_id].append(entity_info) return entities_info_by_project_id - def process_by_project(self, session, event, project_id, entities_info): - project_name = self.get_project_name_from_event( + def _get_attrs_configurations(self, session, interest_attributes): + """Get custom attribute configurations by name. + + Args: + session (ftrack_api.Session): Ftrack sesson. + interest_attributes (list[str]): Names of custom attributes + that should be synchronized. + + Returns: + tuple[dict[str, list], list]: Attributes by object id and + hierarchical attributes. + """ + + attrs = session.query(self.cust_attrs_query.format( + self.join_query_keys(interest_attributes) + )).all() + + attrs_by_obj_id = collections.defaultdict(list) + hier_attrs = [] + for attr in attrs: + if attr["is_hierarchical"]: + hier_attrs.append(attr) + continue + obj_id = attr["object_type_id"] + attrs_by_obj_id[obj_id].append(attr) + return attrs_by_obj_id, hier_attrs + + def _get_handler_project_settings( + self, + session: ftrack_api.Session, + event: ftrack_api.event.base.Event, + project_id: str + ) -> tuple[set[str], set[str]]: + """Get handler settings based on the project. + + Args: + session (ftrack_api.Session): Ftrack session. + event (ftrack_api.event.base.Event): Ftrack event which triggered + the changes. + project_id (str): Project id where the current changes are handled. + + Returns: + tuple[set[str], set[str]]: Attribute names we care about and + entity types we care about. + """ + + project_name: str = self.get_project_name_from_event( session, event, project_id ) # Load settings - project_settings = self.get_project_settings_from_event( - event, project_name + project_settings: dict[str, Any] = ( + self.get_project_settings_from_event(event, project_name) ) # Load status mapping from presets - event_settings = ( + event_settings: dict[str, Any] = ( project_settings ["ftrack"] ["events"] - ["sync_hier_entity_attributes"] + [self.settings_key] ) # Skip if event is not enabled if not event_settings["enabled"]: self.log.debug("Project \"{}\" has disabled {}".format( project_name, self.__class__.__name__ )) - return + return set(), set() - interest_attributes = event_settings["interest_attributes"] + interest_attributes: list[str] = event_settings["interest_attributes"] if not interest_attributes: self.log.info(( "Project \"{}\" does not have filled 'interest_attributes'," " skipping." )) - return - interest_entity_types = event_settings["interest_entity_types"] + + interest_entity_types: list[str] = ( + event_settings["interest_entity_types"]) if not interest_entity_types: self.log.info(( "Project \"{}\" does not have filled 'interest_entity_types'," " skipping." )) - return - - interest_attributes = set(interest_attributes) - interest_entity_types = set(interest_entity_types) - # Separate value changes and task parent changes - _entities_info = [] - added_entities = [] - added_entity_ids = set() - task_parent_changes = [] - for entity_info in entities_info: - if entity_info["entity_type"].lower() == "task": - task_parent_changes.append(entity_info) - elif entity_info.get("action") == "add": - added_entities.append(entity_info) - added_entity_ids.add(entity_info["entityId"]) - else: - _entities_info.append(entity_info) - entities_info = _entities_info - - # Filter entities info with changes - interesting_data, changed_keys_by_object_id = self.filter_changes( - session, event, entities_info, interest_attributes - ) - self.interesting_data_for_added( - session, - added_entities, - interest_attributes, - interesting_data, - changed_keys_by_object_id - ) - if not interesting_data and not task_parent_changes: - return - - # Prepare object types - object_types = session.query("select id, name from ObjectType").all() - object_types_by_name = {} - for object_type in object_types: - name_low = object_type["name"].lower() - object_types_by_name[name_low] = object_type - - # NOTE it would be nice to check if `interesting_data` do not contain - # value changs of tasks that were created or moved - # - it is a complex way how to find out - if interesting_data: - self.process_attribute_changes( - session, - object_types_by_name, - interesting_data, - changed_keys_by_object_id, - interest_entity_types, - interest_attributes, - added_entity_ids - ) - - if task_parent_changes: - self.process_task_parent_change( - session, object_types_by_name, task_parent_changes, - interest_entity_types, interest_attributes - ) + # Unify possible issues from settings ('Asset Build' -> 'assetbuild') + interest_entity_types: set[str] = { + entity_type.replace(" ", "").lower() + for entity_type in interest_entity_types + } + return set(interest_attributes), interest_entity_types - def process_task_parent_change( + def _entities_filter_by_settings( self, - session, - object_types_by_name, - task_parent_changes, - interest_entity_types, - interest_attributes + entities_info: list[dict[str, Any]], + interest_attributes: set[str], + interest_entity_types: set[str] ): - """Push custom attribute values if task parent has changed. - - Parent is changed if task is created or if is moved under different - entity. We don't care about all task changes only about those that - have it's parent in interest types (from settings). + new_entities_info = [] + for entity_info in entities_info: + entity_type_low = entity_info["entity_type"].lower() - Tasks hierarchical value should be unset or set based on parents - real hierarchical value and non hierarchical custom attribute value - should be set to hierarchical value. - """ + changes = entity_info["changes"] + # SPECIAL CASE: Capture changes of task created/moved under + # interested entity type + if ( + entity_type_low == "task" + and "parent_id" in changes + ): + # Direct parent is always second item in 'parents' and 'Task' + # must have at least one parent + parent_info = entity_info["parents"][1] + parent_entity_type = ( + parent_info["entity_type"] + .replace(" ", "") + .lower() + ) + if parent_entity_type in interest_entity_types: + new_entities_info.append(entity_info) + continue - # Store task ids which were created or moved under parent with entity - # type defined in settings (interest_entity_types). - task_ids = set() - # Store parent ids of matching task ids - matching_parent_ids = set() - # Store all entity ids of all entities to be able query hierarchical - # values. - whole_hierarchy_ids = set() - # Store parent id of each entity id - parent_id_by_entity_id = {} - for entity_info in task_parent_changes: - # Ignore entities with less parents than 2 - # NOTE entity itself is also part of "parents" value - parents = entity_info.get("parents") or [] - if len(parents) < 2: + # Skip if entity type is not enabled for attr value sync + if entity_type_low not in interest_entity_types: continue - parent_info = parents[1] - # Check if parent has entity type we care about. - if parent_info["entity_type"] not in interest_entity_types: - continue + valid_attr_change = entity_info.get("action") == "add" + for attr_key in interest_attributes: + if valid_attr_change: + break - task_ids.add(entity_info["entityId"]) - matching_parent_ids.add(parent_info["entityId"]) + if attr_key not in changes: + continue - # Store whole hierarchi of task entity - prev_id = None - for item in parents: - item_id = item["entityId"] - whole_hierarchy_ids.add(item_id) + if changes[attr_key]["new"] is not None: + valid_attr_change = True - if prev_id is None: - prev_id = item_id - continue + if not valid_attr_change: + continue - parent_id_by_entity_id[prev_id] = item_id - if item["entityType"] == "show": - break - prev_id = item_id + new_entities_info.append(entity_info) - # Just skip if nothing is interesting for our settings - if not matching_parent_ids: - return + return new_entities_info - # Query object type ids of parent ids for custom attribute - # definitions query - entities = session.query( - "select object_type_id from TypedContext where id in ({})".format( - self.join_query_keys(matching_parent_ids) - ) - ) + def propagate_attribute_changes( + self, + session, + interest_attributes, + entities_info, + attrs_by_obj_id, + hier_attrs, + real_values_by_entity_id, + hier_values_by_entity_id, + ): + hier_attr_ids_by_key = { + attr["key"]: attr["id"] + for attr in hier_attrs + } + filtered_interest_attributes = { + attr_name + for attr_name in interest_attributes + if attr_name in hier_attr_ids_by_key + } + attrs_keys_by_obj_id = {} + for obj_id, attrs in attrs_by_obj_id.items(): + attrs_keys_by_obj_id[obj_id] = { + attr["key"]: attr["id"] + for attr in attrs + } - # Prepare task object id - task_object_id = object_types_by_name["task"]["id"] + op_changes = [] + for entity_info in entities_info: + entity_id = entity_info["entityId"] + obj_id = entity_info["objectTypeId"] + # Skip attributes sync if does not have object specific custom + # attribute + if obj_id not in attrs_keys_by_obj_id: + continue + attr_keys = attrs_keys_by_obj_id[obj_id] + real_values = real_values_by_entity_id[entity_id] + hier_values = hier_values_by_entity_id[entity_id] + + changes = copy.deepcopy(entity_info["changes"]) + obj_id_attr_keys = { + attr_key + for attr_key in filtered_interest_attributes + if attr_key in attr_keys + } + if not obj_id_attr_keys: + continue - # All object ids for which we're querying custom attribute definitions - object_type_ids = set() - object_type_ids.add(task_object_id) - for entity in entities: - object_type_ids.add(entity["object_type_id"]) + value_by_key = {} + is_new_entity = entity_info.get("action") == "add" + for attr_key in obj_id_attr_keys: + if ( + attr_key in changes + and changes[attr_key]["new"] is not None + ): + value_by_key[attr_key] = changes[attr_key]["new"] - attrs_by_obj_id, hier_attrs = self.attrs_configurations( - session, object_type_ids, interest_attributes - ) + if not is_new_entity: + continue - # Skip if all task attributes are not available - task_attrs = attrs_by_obj_id.get(task_object_id) - if not task_attrs: - return + hier_attr_id = hier_attr_ids_by_key[attr_key] + attr_id = attr_keys[attr_key] + if hier_attr_id in real_values or attr_id in real_values: + continue - # Skip attributes that is not in both hierarchical and nonhierarchical - # TODO be able to push values if hierarchical is available - for key in interest_attributes: - if key not in hier_attrs: - task_attrs.pop(key, None) + value_by_key[attr_key] = hier_values[hier_attr_id] - elif key not in task_attrs: - hier_attrs.pop(key) + for key, new_value in value_by_key.items(): + if new_value is None: + continue - # Skip if nothing remained - if not task_attrs: - return + hier_id = hier_attr_ids_by_key[key] + std_id = attr_keys[key] + real_hier_value = real_values.get(hier_id) + real_std_value = real_values.get(std_id) + hier_value = hier_values[hier_id] + # Get right type of value for conversion + # - values in event are strings + type_value = real_hier_value + if type_value is None: + type_value = real_std_value + if type_value is None: + type_value = hier_value + # Skip if current values are not set + if type_value is None: + continue - # Do some preparations for custom attribute values query - attr_key_by_id = {} - nonhier_id_by_key = {} - hier_attr_ids = [] - for key, attr_id in hier_attrs.items(): - attr_key_by_id[attr_id] = key - hier_attr_ids.append(attr_id) - - conf_ids = list(hier_attr_ids) - task_conf_ids = [] - for key, attr_id in task_attrs.items(): - attr_key_by_id[attr_id] = key - nonhier_id_by_key[key] = attr_id - conf_ids.append(attr_id) - task_conf_ids.append(attr_id) - - # Query custom attribute values - # - result does not contain values for all entities only result of - # query callback to ftrack server - result = query_custom_attributes( - session, list(hier_attr_ids), whole_hierarchy_ids, True - ) - result.extend( - query_custom_attributes( - session, task_conf_ids, whole_hierarchy_ids, False - ) - ) + try: + new_value = type(type_value)(new_value) + except Exception: + self.log.warning(( + "Couldn't convert from {} to {}." + " Skipping update values." + ).format(type(new_value), type(type_value))) + continue - # Prepare variables where result will be stored - # - hierachical values should not contain attribute with value by - # default - hier_values_by_entity_id = { - entity_id: {} - for entity_id in whole_hierarchy_ids - } - # - real values of custom attributes - values_by_entity_id = { - entity_id: { - attr_id: None - for attr_id in conf_ids - } - for entity_id in whole_hierarchy_ids - } - for item in result: - attr_id = item["configuration_id"] - entity_id = item["entity_id"] - value = item["value"] - - values_by_entity_id[entity_id][attr_id] = value - - if attr_id in hier_attr_ids and value is not None: - hier_values_by_entity_id[entity_id][attr_id] = value - - # Prepare values for all task entities - # - going through all parents and storing first value value - # - store None to those that are already known that do not have set - # value at all - for task_id in tuple(task_ids): - for attr_id in hier_attr_ids: - entity_ids = [] - value = None - entity_id = task_id - while value is None: - entity_value = hier_values_by_entity_id[entity_id] - if attr_id in entity_value: - value = entity_value[attr_id] - if value is None: - break - - if value is None: - entity_ids.append(entity_id) - - entity_id = parent_id_by_entity_id.get(entity_id) - if entity_id is None: - break - - for entity_id in entity_ids: - hier_values_by_entity_id[entity_id][attr_id] = value - - # Prepare changes to commit - changes = [] - for task_id in tuple(task_ids): - parent_id = parent_id_by_entity_id[task_id] - for attr_id in hier_attr_ids: - attr_key = attr_key_by_id[attr_id] - nonhier_id = nonhier_id_by_key[attr_key] - - # Real value of hierarchical attribute on parent - # - If is none then should be unset - real_parent_value = values_by_entity_id[parent_id][attr_id] - # Current hierarchical value of a task - # - Will be compared to real parent value - hier_value = hier_values_by_entity_id[task_id][attr_id] - - # Parent value that can be inherited from it's parent entity - parent_value = hier_values_by_entity_id[parent_id][attr_id] - # Task value of nonhierarchical custom attribute - nonhier_value = values_by_entity_id[task_id][nonhier_id] - - if real_parent_value != hier_value: - changes.append({ - "new_value": real_parent_value, - "attr_id": attr_id, - "entity_id": task_id, - "attr_key": attr_key - }) - - if parent_value != nonhier_value: - changes.append({ - "new_value": parent_value, - "attr_id": nonhier_id, - "entity_id": task_id, - "attr_key": attr_key - }) - - self._commit_changes(session, changes) - - def _commit_changes(self, session, changes): - uncommited_changes = False - for idx, item in enumerate(changes): - new_value = item["new_value"] - old_value = item["old_value"] - attr_id = item["attr_id"] - entity_id = item["entity_id"] - attr_key = item["attr_key"] + real_std_value_is_same = new_value == real_std_value + real_hier_value_is_same = new_value == real_hier_value + # New value does not match anything in current entity values + if ( + not is_new_entity + and not real_std_value_is_same + and not real_hier_value_is_same + ): + continue - entity_key = collections.OrderedDict(( + if not real_std_value_is_same: + op_changes.append(( + std_id, + entity_id, + new_value, + real_values.get(std_id), + std_id in real_values + )) + + if not real_hier_value_is_same: + op_changes.append(( + hier_id, + entity_id, + new_value, + real_values.get(hier_id), + hier_id in real_values + )) + + for change in op_changes: + ( + attr_id, + entity_id, + new_value, + old_value, + do_update + ) = change + + entity_key = collections.OrderedDict([ ("configuration_id", attr_id), ("entity_id", entity_id) - )) - self._cached_changes.append({ - "attr_key": attr_key, - "entity_id": entity_id, - "value": new_value, - "time": datetime.datetime.now() - }) - old_value_is_set = ( - old_value is not ftrack_api.symbol.NOT_SET - and old_value is not None - ) - if new_value is None: - if not old_value_is_set: - continue - op = ftrack_api.operation.DeleteEntityOperation( - "CustomAttributeValue", - entity_key - ) - - elif old_value_is_set: + ]) + if do_update: op = ftrack_api.operation.UpdateEntityOperation( "CustomAttributeValue", entity_key, @@ -446,449 +383,116 @@ def _commit_changes(self, session, changes): ) session.recorded_operations.push(op) - self.log.info(( - "Changing Custom Attribute \"{}\" to value" - " \"{}\" on entity: {}" - ).format(attr_key, new_value, entity_id)) - - if (idx + 1) % 20 == 0: - uncommited_changes = False - try: - session.commit() - except Exception: - session.rollback() - self.log.warning( - "Changing of values failed.", exc_info=True - ) - else: - uncommited_changes = True - if uncommited_changes: - try: + if len(session.recorded_operations) > 100: session.commit() - except Exception: - session.rollback() - self.log.warning("Changing of values failed.", exc_info=True) + session.commit() - def process_attribute_changes( + def process_by_project( self, - session, - object_types_by_name, - interesting_data, - changed_keys_by_object_id, - interest_entity_types, - interest_attributes, - added_entity_ids + session: ftrack_api.Session, + event: ftrack_api.event.base.Event, + project_id: str, + entities_info: list[dict[str, Any]] ): - # Prepare task object id - task_object_id = object_types_by_name["task"]["id"] - - # Collect object type ids based on settings - interest_object_ids = [] - for entity_type in interest_entity_types: - _entity_type = entity_type.lower() - object_type = object_types_by_name.get(_entity_type) - if not object_type: - self.log.warning("Couldn't find object type \"{}\"".format( - entity_type - )) - - interest_object_ids.append(object_type["id"]) - - # Query entities by filtered data and object ids - entities = self.get_entities( - session, interesting_data, interest_object_ids - ) - if not entities: - return - - # Pop not found entities from interesting data - entity_ids = set( - entity["id"] - for entity in entities - ) - for entity_id in tuple(interesting_data.keys()): - if entity_id not in entity_ids: - interesting_data.pop(entity_id) - - # Add task object type to list - attr_obj_ids = list(interest_object_ids) - attr_obj_ids.append(task_object_id) - - attrs_by_obj_id, hier_attrs = self.attrs_configurations( - session, attr_obj_ids, interest_attributes - ) - - task_attrs = attrs_by_obj_id.get(task_object_id) - - changed_keys = set() - # Skip keys that are not both in hierachical and type specific - for object_id, keys in changed_keys_by_object_id.items(): - changed_keys |= set(keys) - object_id_attrs = attrs_by_obj_id.get(object_id) - for key in keys: - if key not in hier_attrs: - attrs_by_obj_id[object_id].pop(key) - continue + """Proces changes in single project. + + Args: + session (ftrack_api.Session): Ftrack session. + event (ftrack_api.event.base.Event): Event which has all changes + information. + project_id (str): Project id related to changes. + entities_info (list[dict[str, Any]]): Changes of entities. + """ - if ( - (not object_id_attrs or key not in object_id_attrs) - and (not task_attrs or key not in task_attrs) - ): - hier_attrs.pop(key) - - # Clean up empty values - for key, value in tuple(attrs_by_obj_id.items()): - if not value: - attrs_by_obj_id.pop(key) - - if not attrs_by_obj_id: - self.log.warning(( - "There is not created Custom Attributes {} " - " for entity types: {}" - ).format( - self.join_query_keys(interest_attributes), - self.join_query_keys(interest_entity_types) - )) + ( + interest_attributes, + interest_entity_types + ) = self._get_handler_project_settings(session, event, project_id) + if not interest_attributes or not interest_entity_types: return - # Prepare task entities - task_entities = [] - # If task entity does not contain changed attribute then skip - if task_attrs: - task_entities = self.get_task_entities(session, interesting_data) - - task_entity_ids = set() - parent_id_by_task_id = {} - for task_entity in task_entities: - task_id = task_entity["id"] - task_entity_ids.add(task_id) - parent_id_by_task_id[task_id] = task_entity["parent_id"] - - self.finalize_attribute_changes( - session, - interesting_data, - changed_keys, - attrs_by_obj_id, - hier_attrs, - task_entity_ids, - parent_id_by_task_id, - added_entity_ids - ) - - def finalize_attribute_changes( - self, - session, - interesting_data, - changed_keys, - attrs_by_obj_id, - hier_attrs, - task_entity_ids, - parent_id_by_task_id, - added_entity_ids - ): - attr_id_to_key = {} - for attr_confs in attrs_by_obj_id.values(): - for key in changed_keys: - custom_attr_id = attr_confs.get(key) - if custom_attr_id: - attr_id_to_key[custom_attr_id] = key - - for key in changed_keys: - custom_attr_id = hier_attrs.get(key) - if custom_attr_id: - attr_id_to_key[custom_attr_id] = key - - entity_ids = ( - set(interesting_data.keys()) | task_entity_ids - ) - attr_ids = set(attr_id_to_key.keys()) - - current_values_by_id = self.get_current_values( - session, - attr_ids, - entity_ids, - task_entity_ids, - hier_attrs + entities_info: list[dict[str, Any]] = ( + self._entities_filter_by_settings( + entities_info, + interest_attributes, + interest_entity_types + ) ) - - changes = [] - for entity_id, current_values in current_values_by_id.items(): - parent_id = parent_id_by_task_id.get(entity_id) - if not parent_id: - parent_id = entity_id - values = interesting_data[parent_id] - - added_entity = entity_id in added_entity_ids - for attr_id, old_value in current_values.items(): - if added_entity and attr_id in hier_attrs: - continue - - attr_key = attr_id_to_key.get(attr_id) - if not attr_key: - continue - - # Convert new value from string - new_value = values.get(attr_key) - new_value_is_valid = ( - old_value is not ftrack_api.symbol.NOT_SET - and new_value is not None - ) - if added_entity and not new_value_is_valid: - continue - - if new_value is not None and new_value_is_valid: - try: - new_value = type(old_value)(new_value) - except Exception: - self.log.warning(( - "Couldn't convert from {} to {}." - " Skipping update values." - ).format(type(new_value), type(old_value))) - if new_value == old_value: - continue - - changes.append({ - "new_value": new_value, - "attr_id": attr_id, - "old_value": old_value, - "entity_id": entity_id, - "attr_key": attr_key - }) - self._commit_changes(session, changes) - - def filter_changes( - self, session, event, entities_info, interest_attributes - ): - session_user_id = self.session_user_id(session) - user_data = event["data"].get("user") - changed_by_session = False - if user_data and user_data.get("userid") == session_user_id: - changed_by_session = True - - current_time = datetime.datetime.now() - - interesting_data = {} - changed_keys_by_object_id = {} - - for entity_info in entities_info: - # Care only about changes if specific keys - entity_changes = {} - changes = entity_info["changes"] - for key in interest_attributes: - if key in changes: - entity_changes[key] = changes[key]["new"] - - entity_id = entity_info["entityId"] - if changed_by_session: - for key, new_value in tuple(entity_changes.items()): - for cached in tuple(self._cached_changes): - if ( - cached["entity_id"] != entity_id - or cached["attr_key"] != key - ): - continue - - cached_value = cached["value"] - try: - new_value = type(cached_value)(new_value) - except Exception: - pass - - if cached_value == new_value: - self._cached_changes.remove(cached) - entity_changes.pop(key) - break - - delta = (current_time - cached["time"]).seconds - if delta > self._max_delta: - self._cached_changes.remove(cached) - - if not entity_changes: - continue - - entity_id = entity_info["entityId"] - object_id = entity_info["objectTypeId"] - interesting_data[entity_id] = entity_changes - if object_id not in changed_keys_by_object_id: - changed_keys_by_object_id[object_id] = set() - changed_keys_by_object_id[object_id] |= set(entity_changes.keys()) - - return interesting_data, changed_keys_by_object_id - - def interesting_data_for_added( - self, - session, - added_entities, - interest_attributes, - interesting_data, - changed_keys_by_object_id - ): - if not added_entities or not interest_attributes: + if not entities_info: return - object_type_ids = set() - entity_ids = set() - all_entity_ids = set() - object_id_by_entity_id = {} - project_id = None - entity_ids_by_parent_id = collections.defaultdict(set) - for entity_info in added_entities: - object_id = entity_info["objectTypeId"] - entity_id = entity_info["entityId"] - object_type_ids.add(object_id) - entity_ids.add(entity_id) - object_id_by_entity_id[entity_id] = object_id - - for item in entity_info["parents"]: - entity_id = item["entityId"] - all_entity_ids.add(entity_id) - parent_id = item["parentId"] - if not parent_id: - project_id = entity_id - else: - entity_ids_by_parent_id[parent_id].add(entity_id) - - hier_attrs = self.get_hierarchical_configurations( + attrs_by_obj_id, hier_attrs = self._get_attrs_configurations( session, interest_attributes ) - if not hier_attrs: + # Skip if attributes are not available + # - there is nothing to sync + if not attrs_by_obj_id or not hier_attrs: return - hier_attrs_key_by_id = { - attr_conf["id"]: attr_conf["key"] - for attr_conf in hier_attrs - } - default_values_by_key = { - attr_conf["key"]: attr_conf["default"] - for attr_conf in hier_attrs - } - - values = query_custom_attributes( - session, list(hier_attrs_key_by_id.keys()), all_entity_ids, True + entity_ids_by_parent_id = collections.defaultdict(set) + all_entity_ids = set() + for entity_info in entities_info: + entity_id = None + for item in entity_info["parents"]: + item_id = item["entityId"] + all_entity_ids.add(item_id) + if entity_id is not None: + entity_ids_by_parent_id[item_id].add(entity_id) + entity_id = item_id + + attr_ids = {attr["id"] for attr in hier_attrs} + for attrs in attrs_by_obj_id.values(): + attr_ids |= {attr["id"] for attr in attrs} + + # Query real custom attribute values + # - we have to know what are the real values, if are set and to what + # value + value_items = query_custom_attributes( + session, attr_ids, all_entity_ids, True ) - values_per_entity_id = {} - for entity_id in all_entity_ids: - values_per_entity_id[entity_id] = {} - for attr_name in interest_attributes: - values_per_entity_id[entity_id][attr_name] = None - - for item in values: + real_values_by_entity_id = collections.defaultdict(dict) + for item in value_items: entity_id = item["entity_id"] - key = hier_attrs_key_by_id[item["configuration_id"]] - values_per_entity_id[entity_id][key] = item["value"] - - fill_queue = collections.deque() - fill_queue.append((project_id, default_values_by_key)) - while fill_queue: - item = fill_queue.popleft() - entity_id, values_by_key = item - entity_values = values_per_entity_id[entity_id] - new_values_by_key = copy.deepcopy(values_by_key) - for key, value in values_by_key.items(): - current_value = entity_values[key] - if current_value is None: - entity_values[key] = value - else: - new_values_by_key[key] = current_value - - for child_id in entity_ids_by_parent_id[entity_id]: - fill_queue.append((child_id, new_values_by_key)) - - for entity_id in entity_ids: - entity_changes = {} - for key, value in values_per_entity_id[entity_id].items(): - if value is not None: - entity_changes[key] = value - - if not entity_changes: - continue - - interesting_data[entity_id] = entity_changes - object_id = object_id_by_entity_id[entity_id] - if object_id not in changed_keys_by_object_id: - changed_keys_by_object_id[object_id] = set() - changed_keys_by_object_id[object_id] |= set(entity_changes.keys()) + attr_id = item["configuration_id"] + real_values_by_entity_id[entity_id][attr_id] = item["value"] - def get_current_values( - self, - session, - attr_ids, - entity_ids, - task_entity_ids, - hier_attrs - ): - current_values_by_id = {} - if not attr_ids or not entity_ids: - return current_values_by_id - - for entity_id in entity_ids: - current_values_by_id[entity_id] = {} - for attr_id in attr_ids: - current_values_by_id[entity_id][attr_id] = ( - ftrack_api.symbol.NOT_SET + hier_values_by_entity_id = {} + default_values = { + attr["id"]: attr["default"] + for attr in hier_attrs + } + hier_queue = collections.deque() + hier_queue.append((default_values, [project_id])) + while hier_queue: + parent_values, entity_ids = hier_queue.popleft() + for entity_id in entity_ids: + entity_values = copy.deepcopy(parent_values) + real_values = real_values_by_entity_id[entity_id] + for attr_id, value in real_values.items(): + entity_values[attr_id] = value + hier_values_by_entity_id[entity_id] = entity_values + hier_queue.append( + (entity_values, entity_ids_by_parent_id[entity_id]) ) - values = query_custom_attributes( - session, attr_ids, entity_ids, True + self.propagate_attribute_changes( + session, + interest_attributes, + entities_info, + attrs_by_obj_id, + hier_attrs, + real_values_by_entity_id, + hier_values_by_entity_id, ) - for item in values: - entity_id = item["entity_id"] - attr_id = item["configuration_id"] - if entity_id in task_entity_ids and attr_id in hier_attrs: - continue - - if entity_id not in current_values_by_id: - current_values_by_id[entity_id] = {} - current_values_by_id[entity_id][attr_id] = item["value"] - return current_values_by_id - - def get_entities(self, session, interesting_data, interest_object_ids): - return session.query(( - "select id from TypedContext" - " where id in ({}) and object_type_id in ({})" - ).format( - self.join_query_keys(interesting_data.keys()), - self.join_query_keys(interest_object_ids) - )).all() - - def get_task_entities(self, session, interesting_data): - return session.query( - "select id, parent_id from Task where parent_id in ({})".format( - self.join_query_keys(interesting_data.keys()) - ) - ).all() - - def attrs_configurations(self, session, object_ids, interest_attributes): - attrs = session.query(self.cust_attrs_query.format( - self.join_query_keys(interest_attributes), - self.join_query_keys(object_ids) - )).all() + def launch(self, session, event): + filtered_entities_info = self.filter_entities_info(event) + if not filtered_entities_info: + return - output = {} - hiearchical = {} - for attr in attrs: - if attr["is_hierarchical"]: - hiearchical[attr["key"]] = attr["id"] - continue - obj_id = attr["object_type_id"] - if obj_id not in output: - output[obj_id] = {} - output[obj_id][attr["key"]] = attr["id"] - return output, hiearchical - - def get_hierarchical_configurations(self, session, interest_attributes): - hier_attr_query = ( - "select id, key, object_type_id, is_hierarchical, default" - " from CustomAttributeConfiguration" - " where key in ({}) and is_hierarchical is true" - ) - if not interest_attributes: - return [] - return list(session.query(hier_attr_query.format( - self.join_query_keys(interest_attributes), - )).all()) + for project_id, entities_info in filtered_entities_info.items(): + self.process_by_project(session, event, project_id, entities_info) def register(session): - PushFrameValuesToTaskEvent(session).register() + PushHierValuesToNonHierEvent(session).register() From 0cc5f3ee37e08aa5516d0ca11bebf1c7fea6fd0e Mon Sep 17 00:00:00 2001 From: Sharkitty Date: Fri, 24 Mar 2023 15:44:29 +0100 Subject: [PATCH 660/898] Changed logic as suggested --- .../modules/kitsu/plugins/publish/integrate_kitsu_note.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 6a1b09dde19..571ed683bb4 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -82,8 +82,6 @@ def process(self, context): if instance.data.get("publish") } - allow_status_change = False - # Check if any family requirement is met for family_requirement in self.status_change_conditions[ "family_requirements" @@ -92,8 +90,8 @@ def process(self, context): for family in families: match = family_requirement["family"].lower() == family - if match and condition or not condition and not match: - allow_status_change = True + if match and not condition or condition and not match: + allow_status_change = False break if allow_status_change: From aceaef0b213833214472643f580a01121778f143 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 24 Mar 2023 16:24:33 +0100 Subject: [PATCH 661/898] hiero: correct container colors if UpToDate --- openpype/hosts/hiero/api/lib.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/hiero/api/lib.py b/openpype/hosts/hiero/api/lib.py index bbd1edc14a3..0d4368529f5 100644 --- a/openpype/hosts/hiero/api/lib.py +++ b/openpype/hosts/hiero/api/lib.py @@ -1221,7 +1221,7 @@ def set_track_color(track_item, color): def check_inventory_versions(track_items=None): """ - Actual version color idetifier of Loaded containers + Actual version color identifier of Loaded containers Check all track items and filter only Loader nodes for its version. It will get all versions from database @@ -1249,10 +1249,10 @@ def check_inventory_versions(track_items=None): project_name = legacy_io.active_project() filter_result = filter_containers(containers, project_name) for container in filter_result.latest: - set_track_color(container["_item"], clip_color) + set_track_color(container["_item"], clip_color_last) for container in filter_result.outdated: - set_track_color(container["_item"], clip_color_last) + set_track_color(container["_item"], clip_color) def selection_changed_timeline(event): From 1531708236cf9f27e459c2b20cd642e5f08905af Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 24 Mar 2023 16:30:46 +0100 Subject: [PATCH 662/898] Global: persistent staging directory for renders (#4583) * OP-4258 - Settings for transient template * OP-4258 - added collector for transient staging dir Allows setting profiles to create persistent stagingDir. * OP-4258 - implemented persistent stagingDir in cleanup * OP-4258 - updated logging * OP-4258 - updated settings * OP-4258 - Hound * OP-4258 - renamed class to better name * OP-4258 - changed location of Settings Should be used in create and collecting phase also. * OP-4258 - remove version placeholder from transient template It was discussed that it shouldn't be used for now. * OP-4258 - extracted transient dir query logic This should be used in collection and creation phase for DCCs which are storing staging dir path directly into nodes. * OP-4258 - added use of scene_name placeholder in collector DCC dependent, way how to implement versioning, might not be used. * OP-4258 - fix scene_name * OP-4258 - remove wrong defaults * OP-4258 - added possibility of different template name Studio might want to put renders to different place from caches. * OP-4258 - renamed according to GH comments * OP-4258 - use is active filter * OP-4258 - use is active filter * OP-4793 - added project_settings to signature * OP-4793 - updated logging message * OP-4793 - added documentation * OP-4258 - fix function arguments * OP-4258 - updates to documentation * OP-4258 - added known issues to documentation --------- Co-authored-by: Roy Nieterau --- openpype/pipeline/publish/contants.py | 1 + openpype/pipeline/publish/lib.py | 80 +++++++++++++++++- openpype/plugins/publish/cleanup.py | 4 + openpype/plugins/publish/cleanup_farm.py | 2 +- .../publish/collect_custom_staging_dir.py | 67 +++++++++++++++ .../defaults/project_anatomy/templates.json | 6 +- .../defaults/project_settings/global.json | 3 +- .../schemas/schema_global_tools.json | 65 ++++++++++++++ .../global_tools_custom_staging_dir.png | Bin 0 -> 9940 bytes .../settings_project_global.md | 29 ++++++- 10 files changed, 249 insertions(+), 8 deletions(-) create mode 100644 openpype/plugins/publish/collect_custom_staging_dir.py create mode 100644 website/docs/project_settings/assets/global_tools_custom_staging_dir.png diff --git a/openpype/pipeline/publish/contants.py b/openpype/pipeline/publish/contants.py index 169eca2e5c3..c5296afe9ac 100644 --- a/openpype/pipeline/publish/contants.py +++ b/openpype/pipeline/publish/contants.py @@ -1,2 +1,3 @@ DEFAULT_PUBLISH_TEMPLATE = "publish" DEFAULT_HERO_PUBLISH_TEMPLATE = "hero" +TRANSIENT_DIR_TEMPLATE = "transient" diff --git a/openpype/pipeline/publish/lib.py b/openpype/pipeline/publish/lib.py index 1ec641bac45..81913bcdd56 100644 --- a/openpype/pipeline/publish/lib.py +++ b/openpype/pipeline/publish/lib.py @@ -20,13 +20,15 @@ get_system_settings, ) from openpype.pipeline import ( - tempdir + tempdir, + Anatomy ) from openpype.pipeline.plugin_discover import DiscoverResult from .contants import ( DEFAULT_PUBLISH_TEMPLATE, DEFAULT_HERO_PUBLISH_TEMPLATE, + TRANSIENT_DIR_TEMPLATE ) @@ -690,3 +692,79 @@ def get_publish_repre_path(instance, repre, only_published=False): if os.path.exists(src_path): return src_path return None + + +def get_custom_staging_dir_info(project_name, host_name, family, task_name, + task_type, subset_name, + project_settings=None, + anatomy=None, log=None): + """Checks profiles if context should use special custom dir as staging. + + Args: + project_name (str) + host_name (str) + family (str) + task_name (str) + task_type (str) + subset_name (str) + project_settings(Dict[str, Any]): Prepared project settings. + anatomy (Dict[str, Any]) + log (Logger) (optional) + + Returns: + (tuple) + Raises: + ValueError - if misconfigured template should be used + """ + settings = project_settings or get_project_settings(project_name) + custom_staging_dir_profiles = (settings["global"] + ["tools"] + ["publish"] + ["custom_staging_dir_profiles"]) + if not custom_staging_dir_profiles: + return None, None + + if not log: + log = Logger.get_logger("get_custom_staging_dir_info") + + filtering_criteria = { + "hosts": host_name, + "families": family, + "task_names": task_name, + "task_types": task_type, + "subsets": subset_name + } + profile = filter_profiles(custom_staging_dir_profiles, + filtering_criteria, + logger=log) + + if not profile or not profile["active"]: + return None, None + + if not anatomy: + anatomy = Anatomy(project_name) + + template_name = profile["template_name"] or TRANSIENT_DIR_TEMPLATE + _validate_transient_template(project_name, template_name, anatomy) + + custom_staging_dir = anatomy.templates[template_name]["folder"] + is_persistent = profile["custom_staging_dir_persistent"] + + return custom_staging_dir, is_persistent + + +def _validate_transient_template(project_name, template_name, anatomy): + """Check that transient template is correctly configured. + + Raises: + ValueError - if misconfigured template + """ + if template_name not in anatomy.templates: + raise ValueError(("Anatomy of project \"{}\" does not have set" + " \"{}\" template key!" + ).format(project_name, template_name)) + + if "folder" not in anatomy.templates[template_name]: + raise ValueError(("There is not set \"folder\" template in \"{}\" anatomy" # noqa + " for project \"{}\"." + ).format(template_name, project_name)) diff --git a/openpype/plugins/publish/cleanup.py b/openpype/plugins/publish/cleanup.py index ef312e391f8..b90c88890da 100644 --- a/openpype/plugins/publish/cleanup.py +++ b/openpype/plugins/publish/cleanup.py @@ -93,6 +93,10 @@ def process(self, instance): self.log.info("No staging directory found: %s" % staging_dir) return + if instance.data.get("stagingDir_persistent"): + self.log.info("Staging dir: %s should be persistent" % staging_dir) + return + self.log.info("Removing staging directory {}".format(staging_dir)) shutil.rmtree(staging_dir) diff --git a/openpype/plugins/publish/cleanup_farm.py b/openpype/plugins/publish/cleanup_farm.py index b87d4698a27..8052f137346 100644 --- a/openpype/plugins/publish/cleanup_farm.py +++ b/openpype/plugins/publish/cleanup_farm.py @@ -37,7 +37,7 @@ def process(self, context): dirpaths_to_remove = set() for instance in context: staging_dir = instance.data.get("stagingDir") - if staging_dir: + if staging_dir and not instance.data.get("stagingDir_persistent"): dirpaths_to_remove.add(os.path.normpath(staging_dir)) if "representations" in instance.data: diff --git a/openpype/plugins/publish/collect_custom_staging_dir.py b/openpype/plugins/publish/collect_custom_staging_dir.py new file mode 100644 index 00000000000..72ab0fe34d2 --- /dev/null +++ b/openpype/plugins/publish/collect_custom_staging_dir.py @@ -0,0 +1,67 @@ +""" +Requires: + anatomy + + +Provides: + instance.data -> stagingDir (folder path) + -> stagingDir_persistent (bool) +""" +import copy +import os.path + +import pyblish.api + +from openpype.pipeline.publish.lib import get_custom_staging_dir_info + + +class CollectCustomStagingDir(pyblish.api.InstancePlugin): + """Looks through profiles if stagingDir should be persistent and in special + location. + + Transient staging dir could be useful in specific use cases where is + desirable to have temporary renders in specific, persistent folders, could + be on disks optimized for speed for example. + + It is studio responsibility to clean up obsolete folders with data. + + Location of the folder is configured in `project_anatomy/templates/others`. + ('transient' key is expected, with 'folder' key) + + Which family/task type/subset is applicable is configured in: + `project_settings/global/tools/publish/custom_staging_dir_profiles` + + """ + label = "Collect Custom Staging Directory" + order = pyblish.api.CollectorOrder + 0.4990 + + template_key = "transient" + + def process(self, instance): + family = instance.data["family"] + subset_name = instance.data["subset"] + host_name = instance.context.data["hostName"] + project_name = instance.context.data["projectName"] + + anatomy = instance.context.data["anatomy"] + anatomy_data = copy.deepcopy(instance.data["anatomyData"]) + task = anatomy_data.get("task", {}) + + transient_tml, is_persistent = get_custom_staging_dir_info( + project_name, host_name, family, task.get("name"), + task.get("type"), subset_name, anatomy=anatomy, log=self.log) + result_str = "Not adding" + if transient_tml: + anatomy_data["root"] = anatomy.roots + scene_name = instance.context.data.get("currentFile") + if scene_name: + anatomy_data["scene_name"] = os.path.basename(scene_name) + transient_dir = transient_tml.format(**anatomy_data) + instance.data["stagingDir"] = transient_dir + + instance.data["stagingDir_persistent"] = is_persistent + result_str = "Adding '{}' as".format(transient_dir) + + self.log.info("{} custom staging dir for instance with '{}'".format( + result_str, family + )) diff --git a/openpype/settings/defaults/project_anatomy/templates.json b/openpype/settings/defaults/project_anatomy/templates.json index 02c0e353773..e5e535bf193 100644 --- a/openpype/settings/defaults/project_anatomy/templates.json +++ b/openpype/settings/defaults/project_anatomy/templates.json @@ -58,12 +58,16 @@ "file": "{originalBasename}.{ext}", "path": "{@folder}/{@file}" }, + "transient": { + "folder": "{root[work]}/{project[name]}/{hierarchy}/{asset}/work/{family}/{subset}" + }, "__dynamic_keys_labels__": { "maya2unreal": "Maya to Unreal", "simpleUnrealTextureHero": "Simple Unreal Texture - Hero", "simpleUnrealTexture": "Simple Unreal Texture", "online": "online", - "source": "source" + "source": "source", + "transient": "transient" } } } diff --git a/openpype/settings/defaults/project_settings/global.json b/openpype/settings/defaults/project_settings/global.json index aad17d54daa..aba840da786 100644 --- a/openpype/settings/defaults/project_settings/global.json +++ b/openpype/settings/defaults/project_settings/global.json @@ -591,7 +591,8 @@ "task_names": [], "template_name": "simpleUnrealTextureHero" } - ] + ], + "custom_staging_dir_profiles": [] } }, "project_folder_structure": "{\"__project_root__\": {\"prod\": {}, \"resources\": {\"footage\": {\"plates\": {}, \"offline\": {}}, \"audio\": {}, \"art_dept\": {}}, \"editorial\": {}, \"assets\": {\"characters\": {}, \"locations\": {}}, \"shots\": {}}}", diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json index 962008d4764..85ec482e735 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json @@ -408,6 +408,71 @@ } ] } + }, + { + "type": "list", + "key": "custom_staging_dir_profiles", + "label": "Custom Staging Dir Profiles", + "use_label_wrap": true, + "docstring": "Profiles to specify special location and persistence for staging dir. Could be used in Creators and Publish phase!", + "object_type": { + "type": "dict", + "children": [ + { + "type": "boolean", + "key": "active", + "label": "Is active", + "default": true + }, + { + "type": "separator" + }, + { + "key": "hosts", + "label": "Host names", + "type": "hosts-enum", + "multiselection": true + }, + { + "key": "task_types", + "label": "Task types", + "type": "task-types-enum" + }, + { + "key": "task_names", + "label": "Task names", + "type": "list", + "object_type": "text" + }, + { + "key": "families", + "label": "Families", + "type": "list", + "object_type": "text" + }, + { + "key": "subsets", + "label": "Subset names", + "type": "list", + "object_type": "text" + }, + { + "type": "separator" + }, + { + "key": "custom_staging_dir_persistent", + "label": "Custom Staging Folder Persistent", + "type": "boolean", + "default": false + }, + { + "key": "template_name", + "label": "Template Name", + "type": "text", + "placeholder": "transient" + } + ] + } } ] } diff --git a/website/docs/project_settings/assets/global_tools_custom_staging_dir.png b/website/docs/project_settings/assets/global_tools_custom_staging_dir.png new file mode 100644 index 0000000000000000000000000000000000000000..f7e8660a8863239310a1934a49c2811b4e0c031b GIT binary patch literal 9940 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 VmwKMN3A}U$l9y4I&XY9q`!5KAZJhuB literal 0 HcmV?d00001 diff --git a/website/docs/project_settings/settings_project_global.md b/website/docs/project_settings/settings_project_global.md index b6d624caa85..821585ae21d 100644 --- a/website/docs/project_settings/settings_project_global.md +++ b/website/docs/project_settings/settings_project_global.md @@ -230,10 +230,10 @@ Applicable context filters: ## Tools Settings for OpenPype tools. -## Creator +### Creator Settings related to [Creator tool](artist_tools_creator). -### Subset name profiles +#### Subset name profiles ![global_tools_creator_subset_template](assets/global_tools_creator_subset_template.png) Subset name helps to identify published content. More specific name helps with organization and avoid mixing of published content. Subset name is defined using one of templates defined in **Subset name profiles settings**. The template is filled with context information at the time of creation. @@ -263,10 +263,31 @@ Template may look like `"{family}{Task}{Variant}"`. Some creators may have other keys as their context may require more information or more specific values. Make sure you've read documentation of host you're using. -## Workfiles +### Publish + +#### Custom Staging Directory Profiles +With this feature, users can specify a custom data folder path based on presets, which can be used during the creation and publishing stages. + +![global_tools_custom_staging_dir](assets/global_tools_custom_staging_dir.png) + +Staging directories are used as a destination for intermediate files (as renders) before they are renamed and copied to proper location during the integration phase. They could be created completely dynamically in the temp folder or for some DCCs in the `work` area. +Example could be Nuke where artist might want to temporarily render pictures into `work` area to check them before they get published with the choice of "Use existing frames" on the write node. + +One of the key advantages of this feature is that it allows users to choose the folder for writing such intermediate files to take advantage of faster storage for rendering, which can help improve workflow efficiency. Additionally, this feature allows users to keep their intermediate extracted data persistent, and use their own infrastructure for regular cleaning. + +In some cases, these DCCs (Nuke, Houdini, Maya) automatically add a rendering path during the creation stage, which is then used in publishing. Creators and extractors of such DCCs need to use these profiles to fill paths in DCC's nodes to use this functionality. + +The custom staging folder uses a path template configured in `project_anatomy/templates/others` with `transient` being a default example path that could be used. The template requires a 'folder' key for it to be usable as custom staging folder. + +##### Known issues +- Any DCC that uses prefilled paths and store them inside of workfile nodes needs to implement resolving these paths with a configured profiles. +- If studio uses Site Sync remote artists need to have access to configured custom staging folder! +- Each node on the rendering farm must have access to configured custom staging folder! + +### Workfiles All settings related to Workfile tool. -### Open last workfile at launch +#### Open last workfile at launch This feature allows you to define a rule for each task/host or toggle the feature globally to all tasks as they are visible in the picture. ![global_tools_workfile_open_last_version](assets/global_tools_workfile_open_last_version.png) From 09faa840aeff7b479c865fe04185689b1aa75f5f Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 24 Mar 2023 17:18:33 +0100 Subject: [PATCH 663/898] updating project_action --- .github/workflows/project_actions.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index 9c8c9da7dda..ec5578d2fef 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -2,9 +2,7 @@ name: project-actions on: pull_request: - types: [review_requested, closed] - pull_request_review: - types: [submitted] + types: [review_requested] jobs: pr_review_requested: @@ -16,7 +14,6 @@ jobs: uses: leonsteinhaeuser/project-beta-automations@v2.1.0 with: gh_token: ${{ secrets.YNPUT_BOT_TOKEN }} - user: ${{ secrets.CI_USER }} organization: ynput project_id: 11 resource_node_id: ${{ github.event.pull_request.node_id }} From 3253c03e3b147c69609e1faf0730f955e32add86 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 24 Mar 2023 17:29:34 +0100 Subject: [PATCH 664/898] returning trigger to project action --- .github/workflows/project_actions.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index ec5578d2fef..ca94f3ae772 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -3,6 +3,8 @@ name: project-actions on: pull_request: types: [review_requested] + pull_request_review: + types: [submitted] jobs: pr_review_requested: From 2baabed6be7eb6977cb7fcb0d69b7c79e1b18327 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 24 Mar 2023 18:50:09 +0100 Subject: [PATCH 665/898] Work in progress extract look cleanup - Fix file hashing so it includes arguments to maketx - Fix maketx destination colorspace when OCIO is enabled - Use pre-collected colorspaces of the resources instead of trying to retrieve again - Fix colorspace attributes being reinterpreted by maya on export (fix remapping) - Fix support for checking config path of maya default OCIO config (due to using `lib.get_color_management_preferences` which remaps that path) --- .../maya/plugins/publish/extract_look.py | 397 ++++++++++-------- 1 file changed, 212 insertions(+), 185 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 447c9a615cc..5c03aa5a5a1 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -149,22 +149,6 @@ class ExtractLook(publish.Extractor): scene_type = "ma" look_data_type = "json" - @staticmethod - def get_renderer_name(): - """Get renderer name from Maya. - - Returns: - str: Renderer name. - - """ - renderer = cmds.getAttr( - "defaultRenderGlobals.currentRenderer" - ).lower() - # handle various renderman names - if renderer.startswith("renderman"): - renderer = "renderman" - return renderer - def get_maya_scene_type(self, instance): """Get Maya scene type from settings. @@ -209,11 +193,9 @@ def process(self, instance): maya_path = os.path.join(dir_path, maya_fname) json_path = os.path.join(dir_path, json_fname) - self.log.info("Performing extraction..") - # Remove all members of the sets so they are not included in the # exported file by accident - self.log.info("Extract sets (%s) ..." % _scene_type) + self.log.info("Processing sets..") lookdata = instance.data["lookData"] relationships = lookdata["relationships"] sets = list(relationships.keys()) @@ -221,6 +203,7 @@ def process(self, instance): self.log.info("No sets found") return + self.log.debug("Processing resources..") results = self.process_resources(instance, staging_dir=dir_path) transfers = results["fileTransfers"] hardlinks = results["fileHardlinks"] @@ -228,6 +211,7 @@ def process(self, instance): remap = results["attrRemap"] # Extract in correct render layer + self.log.info("Extracting look maya scene file: {}".format(maya_path)) layer = instance.data.get("renderlayer", "defaultRenderLayer") with lib.renderlayer(layer): # TODO: Ensure membership edits don't become renderlayer overrides @@ -299,40 +283,39 @@ def process(self, instance): # Source hash for the textures instance.data["sourceHashes"] = hashes - """ - self.log.info("Returning colorspaces to their original values ...") - for attr, value in remap.items(): - self.log.info(" - {}: {}".format(attr, value)) - cmds.setAttr(attr, value, type="string") - """ self.log.info("Extracted instance '%s' to: %s" % (instance.name, maya_path)) + def _set_resource_result_colorspace(self, resource, colorspace): + """Update resource resulting colorspace after texture processing""" + if "result_colorspace" in resource: + if resource["result_colorspace"] == colorspace: + return + + self.log.warning( + "Resource already has a resulting colorspace but is now " + "being overridden to a new one: {} -> {}".format( + resource["result_colorspace"], colorspace + ) + ) + resource["result_colorspace"] = colorspace + def process_resources(self, instance, staging_dir): + """Process all resources in the instance. - # Extract the textures to transfer, possibly convert with maketx and - # remap the node paths to the destination path. Note that a source - # might be included more than once amongst the resources as they could - # be the input file to multiple nodes. - resources = instance.data["resources"] - do_maketx = instance.data.get("maketx", False) + It is assumed that all resources are nodes using file textures. - # Collect all unique files used in the resources - files_metadata = {} - for resource in resources: - # Preserve color space values (force value after filepath change) - # This will also trigger in the same order at end of context to - # ensure after context it's still the original value. - color_space = resource.get("color_space") + Extract the textures to transfer, possibly convert with maketx and + remap the node paths to the destination path. Note that a source + might be included more than once amongst the resources as they could + be the input file to multiple nodes. - for f in resource["files"]: - files_metadata[os.path.normpath(f)] = { - "color_space": color_space} + """ + + resources = instance.data["resources"] + do_maketx = instance.data.get("maketx", False) + color_management = lib.get_color_management_preferences() - # Process the resource files - transfers = [] - hardlinks = [] - hashes = {} # Temporary fix to NOT create hardlinks on windows machines if platform.system().lower() == "windows": self.log.info( @@ -342,58 +325,83 @@ def process_resources(self, instance, staging_dir): else: force_copy = instance.data.get("forceCopy", False) - for filepath in files_metadata: + # Process all resource's individual files + processed_files = {} + transfers = [] + hardlinks = [] + hashes = {} + destinations = {} + remap = OrderedDict() + for resource in resources: + colorspace = resource["color_space"] + + for filepath in resource["files"]: + filepath = os.path.normpath(filepath) + + if filepath in processed_files: + # The file was already processed, likely due to usage by + # another resource in the scene. We confirm here it + # didn't do color spaces different than the current + # resource. + processed_file = processed_files[filepath] + processed_colorspace = processed_file["color_space"] + processed_result_colorspace = processed_file["result_color_space"] + self.log.debug( + "File was already processed. Likely used by another " + "resource too: {}".format(filepath) + ) + + if colorspace != processed_file["color_space"]: + self.log.warning( + "File was already processed but using another" + "colorspace: {} <-> {}" + "".format(colorspace, processed_colorspace)) + + self._set_resource_result_colorspace( + resource, colorspace=processed_result_colorspace + ) + continue + + texture_result = self._process_texture( + filepath, + do_maketx=do_maketx, + staging_dir=staging_dir, + force_copy=force_copy, + color_management=color_management, + colorspace=colorspace + ) + source, mode, texture_hash, result_colorspace = texture_result + destination = self.resource_destination(instance, + source, + do_maketx) + + # Set the resulting color space on the resource + self._set_resource_result_colorspace( + resource, colorspace=result_colorspace + ) - linearize = False - # if OCIO color management enabled - # it won't take the condition of the files_metadata + processed_files[filepath] = { + "color_space": colorspace, + "result_color_space": result_colorspace, + } - ocio_maya = cmds.colorManagementPrefs(q=True, - cmConfigFileEnabled=True, - cmEnabled=True) + # Force copy is specified. + if force_copy: + mode = COPY - if do_maketx and not ocio_maya: - if files_metadata[filepath]["color_space"].lower() == "srgb": # noqa: E501 - linearize = True - # set its file node to 'raw' as tx will be linearized - files_metadata[filepath]["color_space"] = "Raw" + if mode == COPY: + transfers.append((source, destination)) + self.log.info('file will be copied {} -> {}'.format( + source, destination)) + elif mode == HARDLINK: + hardlinks.append((source, destination)) + self.log.info('file will be hardlinked {} -> {}'.format( + source, destination)) - # if do_maketx: - # color_space = "Raw" + # Store the hashes from hash to destination to include in the + # database + hashes[texture_hash] = destination - source, mode, texture_hash = self._process_texture( - filepath, - resource, - do_maketx, - staging=staging_dir, - linearize=linearize, - force=force_copy - ) - destination = self.resource_destination(instance, - source, - do_maketx) - - # Force copy is specified. - if force_copy: - mode = COPY - - if mode == COPY: - transfers.append((source, destination)) - self.log.info('file will be copied {} -> {}'.format( - source, destination)) - elif mode == HARDLINK: - hardlinks.append((source, destination)) - self.log.info('file will be hardlinked {} -> {}'.format( - source, destination)) - - # Store the hashes from hash to destination to include in the - # database - hashes[texture_hash] = destination - - # Remap the resources to the destination path (change node attributes) - destinations = {} - remap = OrderedDict() # needs to be ordered, see color space values - for resource in resources: source = os.path.normpath(resource["source"]) if source not in destinations: # Cache destination as source resource might be included @@ -402,35 +410,23 @@ def process_resources(self, instance, staging_dir): instance, source, do_maketx ) + # Set up remapping attributes for the node during the publish + # The order of these can be important if one attribute directly + # affects another, e.g. we set colorspace after filepath because + # maya sometimes tries to guess the colorspace when changing + # filepaths (which is avoidable, but we don't want to have those + # attributes changed in the resulting publish) + # Remap filepath to publish destination + filepath_attr = resource["attribute"] + remap[filepath_attr] = destinations[source] + # Preserve color space values (force value after filepath change) # This will also trigger in the same order at end of context to # ensure after context it's still the original value. - color_space_attr = resource["node"] + ".colorSpace" - try: - color_space = cmds.getAttr(color_space_attr) - except ValueError: - # node doesn't have color space attribute - color_space = "Raw" - else: - # get the resolved files - metadata = files_metadata.get(source) - # if the files are unresolved from `source` - # assume color space from the first file of - # the resource - if not metadata: - first_file = next(iter(resource.get( - "files", [])), None) - if not first_file: - continue - first_filepath = os.path.normpath(first_file) - metadata = files_metadata[first_filepath] - if metadata["color_space"] == "Raw": - # set color space to raw if we linearized it - color_space = "Raw" - # Remap file node filename to destination - remap[color_space_attr] = color_space - attr = resource["attribute"] - remap[attr] = destinations[source] + node = resource["node"] + if cmds.attributeQuery("colorSpace", node=node, exists=True): + color_space_attr = "{}.colorSpace".format(node) + remap[color_space_attr] = resource["result_color_space"] self.log.info("Finished remapping destinations ...") @@ -469,91 +465,115 @@ def resource_destination(self, instance, filepath, do_maketx): resources_dir, basename + ext ) - def _process_texture(self, filepath, resource, - do_maketx, staging, linearize, force): + def _get_existing_hashed_texture(self, texture_hash): + """Return the first found filepath from a texture hash""" + + # If source has been published before with the same settings, + # then don't reprocess but hardlink from the original + existing = find_paths_by_hash(texture_hash) + if existing: + self.log.info("Found hash in database, preparing hardlink..") + source = next((p for p in existing if os.path.exists(p)), None) + if source: + return source, HARDLINK, texture_hash + else: + self.log.warning( + "Paths not found on disk, " + "skipping hardlink: {}".format(existing) + ) + + def _process_texture(self, + filepath, + do_maketx, + staging_dir, + force_copy, + color_management, + colorspace): """Process a single texture file on disk for publishing. This will: 1. Check whether it's already published, if so it will do hardlink 2. If not published and maketx is enabled, generate a new .tx file. 3. Compute the destination path for the source file. + Args: filepath (str): The source file path to process. do_maketx (bool): Whether to produce a .tx file + staging_dir (str): The staging directory to write to. + force_copy (bool): Whether to force a copy even if a file hash + might have existed already in the project, otherwise + hardlinking the existing file is allowed. + color_management (dict): Maya's Color Management settings from + `lib.get_color_management_preferences` + colorspace (str): The source colorspace of the resources this + texture belongs to. + Returns: + tuple: (filepath, copy_mode, texture_hash, result_colorspace) """ fname, ext = os.path.splitext(os.path.basename(filepath)) + # Note: The texture hash is only reliable if we include any potential + # conversion arguments provide to e.g. `maketx` args = [] - if do_maketx: - args.append("maketx") - texture_hash = source_hash(filepath, *args) + hash_args = [] + + if do_maketx and ext != ".tx": + # Define .tx filepath in staging if source file is not .tx + converted = os.path.join(staging_dir, "resources", fname + ".tx") + + if color_management["enabled"]: + config_path = color_management["config"] + if not os.path.exists(config_path): + raise RuntimeError("OCIO config not found at: " + "{}".format(config_path)) + + render_colorspace = color_management["rendering_space"] + + self.log.info("tx: converting colorspace {0} " + "-> {1}".format(colorspace, render_colorspace)) + args.extend(["--colorconvert", colorspace, render_colorspace]) + args.extend(["--colorconfig", config_path]) - # If source has been published before with the same settings, - # then don't reprocess but hardlink from the original - existing = find_paths_by_hash(texture_hash) - if existing and not force: - self.log.info("Found hash in database, preparing hardlink..") - source = next((p for p in existing if os.path.exists(p)), None) - if source: - return source, HARDLINK, texture_hash else: - self.log.warning( - ("Paths not found on disk, " - "skipping hardlink: %s") % (existing,) - ) + # We can't rely on the colorspace attribute when not + # in color managed mode because the collected color space + # is the color space attribute of the file node which can be + # any string whatsoever but only appears disabled in Attribute + # Editor. We assume we're always converting to linear/Raw if + # the source file is assumed to be sRGB. + render_colorspace = "linear" + if _has_arnold(): + img_info = image_info(filepath) + color_space = guess_colorspace(img_info) + if color_space.lower() == "sRGB": + self.log.info("tx: converting sRGB -> linear") + args.extend(["--colorconvert", "sRGB", "Raw"]) + else: + self.log.info("tx: texture's colorspace " + "is already linear") + else: + self.log.warning("tx: cannot guess the colorspace, " + "color conversion won't be available!") - if do_maketx and ext != ".tx": - # Produce .tx file in staging if source file is not .tx - converted = os.path.join(staging, "resources", fname + ".tx") - additional_args = [ + hash_args.append("maketx") + hash_args.extend(args) + + texture_hash = source_hash(filepath, *args) + + if not force_copy: + existing = self._get_existing_hashed_texture(filepath) + if existing: + return existing + + # Exclude these additional arguments from the hashing because + # it is the hash itself + args.extend([ "--sattrib", "sourceHash", texture_hash - ] - if linearize: - if cmds.colorManagementPrefs(query=True, cmEnabled=True): - render_colorspace = cmds.colorManagementPrefs(query=True, - renderingSpaceName=True) # noqa - config_path = cmds.colorManagementPrefs(query=True, - configFilePath=True) # noqa - if not os.path.exists(config_path): - raise RuntimeError("No OCIO config path found!") - - color_space_attr = resource["node"] + ".colorSpace" - try: - color_space = cmds.getAttr(color_space_attr) - except ValueError: - # node doesn't have color space attribute - if _has_arnold(): - img_info = image_info(filepath) - color_space = guess_colorspace(img_info) - else: - color_space = "Raw" - self.log.info("tx: converting {0} -> {1}".format(color_space, render_colorspace)) # noqa - - additional_args.extend(["--colorconvert", - color_space, - render_colorspace]) - else: + ]) - if _has_arnold(): - img_info = image_info(filepath) - color_space = guess_colorspace(img_info) - if color_space == "sRGB": - self.log.info("tx: converting sRGB -> linear") - additional_args.extend(["--colorconvert", - "sRGB", - "Raw"]) - else: - self.log.info("tx: texture's colorspace " - "is already linear") - else: - self.log.warning("cannot guess the colorspace" - "color conversion won't be available!") # noqa - - - additional_args.extend(["--colorconfig", config_path]) # Ensure folder exists if not os.path.exists(os.path.dirname(converted)): os.makedirs(os.path.dirname(converted)) @@ -562,13 +582,20 @@ def _process_texture(self, filepath, resource, maketx( filepath, converted, - additional_args, + args, self.log ) - return converted, COPY, texture_hash + return converted, COPY, texture_hash, render_colorspace + + # No special treatment for this file + texture_hash = source_hash(filepath) + if not force_copy: + existing = self._get_existing_hashed_texture(filepath) + if existing: + return existing - return filepath, COPY, texture_hash + return filepath, COPY, texture_hash, colorspace class ExtractModelRenderSets(ExtractLook): From c7e12b5184b39738d9225504de89054938754720 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 24 Mar 2023 19:39:51 +0100 Subject: [PATCH 666/898] Cosmetics --- openpype/hosts/maya/plugins/publish/extract_look.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 5c03aa5a5a1..a067e63339a 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -344,8 +344,6 @@ def process_resources(self, instance, staging_dir): # didn't do color spaces different than the current # resource. processed_file = processed_files[filepath] - processed_colorspace = processed_file["color_space"] - processed_result_colorspace = processed_file["result_color_space"] self.log.debug( "File was already processed. Likely used by another " "resource too: {}".format(filepath) @@ -355,10 +353,12 @@ def process_resources(self, instance, staging_dir): self.log.warning( "File was already processed but using another" "colorspace: {} <-> {}" - "".format(colorspace, processed_colorspace)) + "".format(colorspace, + processed_file["color_space"])) self._set_resource_result_colorspace( - resource, colorspace=processed_result_colorspace + resource, + colorspace=processed_file["result_color_space"] ) continue From 4ea987fb1f442069a3127bdf046c57bf2f8393af Mon Sep 17 00:00:00 2001 From: Ynbot Date: Sat, 25 Mar 2023 03:26:01 +0000 Subject: [PATCH 667/898] [Automated] Bump version --- openpype/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/version.py b/openpype/version.py index 5b6db12b5e4..bc5ea7fe7ca 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.15.3-nightly.3" +__version__ = "3.15.3-nightly.4" From b37c15f58215bbdb51227e690cf3dde0cd0fdd96 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 25 Mar 2023 10:52:44 +0100 Subject: [PATCH 668/898] More WIP refactoring for TextureProcessors --- .../maya/plugins/publish/extract_look.py | 299 +++++++++--------- 1 file changed, 150 insertions(+), 149 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index b21ce722963..7515fdeb8c9 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -26,37 +26,6 @@ HARDLINK = 2 -def _has_arnold(): - """Return whether the arnold package is available and can be imported.""" - try: - import arnold # noqa: F401 - return True - except (ImportError, ModuleNotFoundError): - return False - - -def get_redshift_tool(tool_name): - """Path to redshift texture processor. - - On Windows it adds .exe extension if missing from tool argument. - - Args: - tool (string): Tool name. - - Returns: - str: Full path to redshift texture processor executable. - """ - redshift_os_path = os.environ["REDSHIFT_COREDATAPATH"] - - redshift_tool_path = os.path.join( - redshift_os_path, - "bin", - tool_name - ) - - return find_executable(redshift_tool_path) - - def find_paths_by_hash(texture_hash): """Find the texture hash key in the dictionary. @@ -75,17 +44,26 @@ def find_paths_by_hash(texture_hash): @six.add_metaclass(ABCMeta) class TextureProcessor: - def __init__(self, log=None): if log is None: log = logging.getLogger(self.__class___.__name__) + self.log = log @abstractmethod - def process(self, filepath): + def apply_settings(self, system_settings, project_settings): + pass + @abstractmethod + def process(self, + source, + colorspace, + color_management, + staging_dir): pass + # TODO: Warning this only supports Py3.3+ @staticmethod + @abstractmethod def get_extension(): pass @@ -93,10 +71,11 @@ def get_extension(): class MakeRSTexBin(TextureProcessor): """Make `.rstexbin` using `redshiftTextureProcessor`""" - def __init__(self): - super(MakeRSTexBin, self).__init__() - - def process(self, source, *args): + def process(self, + source, + colorspace, + color_management, + staging_dir): """ with some default settings. @@ -105,24 +84,22 @@ def process(self, source, *args): Args: source (str): Path to source file. - *args: Additional arguments for `redshiftTextureProcessor`. """ if "REDSHIFT_COREDATAPATH" not in os.environ: raise RuntimeError("Must have Redshift available.") - texture_processor_path = get_redshift_tool("redshiftTextureProcessor") + texture_processor_path = self.get_redshift_tool( + "redshiftTextureProcessor" + ) if not texture_processor_path: - raise KnownPublishError("Must have Redshift available.", - title="Make RSTexBin texture") + raise KnownPublishError("Must have Redshift available.") subprocess_args = [ texture_processor_path, source ] - subprocess_args.extend(args) - self.log.debug(" ".join(subprocess_args)) try: out = run_subprocess(subprocess_args) @@ -131,18 +108,43 @@ def process(self, source, *args): exc_info=True) raise + # TODO: Implement correct return values return out @staticmethod def get_extension(): return ".rstexbin" + @staticmethod + def get_redshift_tool(tool_name): + """Path to redshift texture processor. + + On Windows it adds .exe extension if missing from tool argument. + + Args: + tool (string): Tool name. + + Returns: + str: Full path to redshift texture processor executable. + """ + redshift_os_path = os.environ["REDSHIFT_COREDATAPATH"] + + redshift_tool_path = os.path.join( + redshift_os_path, + "bin", + tool_name + ) + + return find_executable(redshift_tool_path) + class MakeTX(TextureProcessor): - def __init__(self): - super(MakeTX, self).__init__() - def process(self, source, destination, *args): + def process(self, + source, + colorspace, + color_management, + staging_dir): """Make `.tx` using `maketx` with some default settings. The settings are based on default as used in Arnold's @@ -152,8 +154,6 @@ def process(self, source, destination, *args): Args: source (str): Path to source file. - destination (str): Writing destination path. - *args: Additional arguments for `maketx`. Returns: str: Output of `maketx` command. @@ -164,9 +164,78 @@ def process(self, source, destination, *args): maketx_path = get_oiio_tools_path("maketx") if not maketx_path: - print( - "OIIO tool not found in {}".format(maketx_path)) - raise AssertionError("OIIO tool not found") + raise AssertionError( + "OIIO 'maketx' tool not found. Result: {}".format(maketx_path) + ) + + # Define .tx filepath in staging if source file is not .tx + fname, ext = os.path.splitext(os.path.basename(source)) + if ext == ".tx": + # TODO: Implement this fallback + # Do nothing if the source file is already a .tx file. + # return source, COPY, texture_hash, render_colorspace + pass + + args = [] + if color_management["enabled"]: + config_path = color_management["config"] + if not os.path.exists(config_path): + raise RuntimeError("OCIO config not found at: " + "{}".format(config_path)) + + render_colorspace = color_management["rendering_space"] + + self.log.info("tx: converting colorspace {0} " + "-> {1}".format(colorspace, + render_colorspace)) + args.extend(["--colorconvert", colorspace, render_colorspace]) + args.extend(["--colorconfig", config_path]) + + else: + # We can't rely on the colorspace attribute when not in color + # managed mode because the collected color space is the color space + # attribute of the file node which can be any string whatsoever + # but only appears disabled in Attribute Editor. We assume we're + # always converting to linear/Raw if the source file is assumed to + # be sRGB. + # TODO Without color management do we even know we can do + # "colorconvert" and what config does that end up using since + # colorconvert is a OCIO command line flag for maketx. + # Also, Raw != linear? + render_colorspace = "linear" + if self._has_arnold(): + img_info = image_info(source) + color_space = guess_colorspace(img_info) + if color_space.lower() == "sRGB": + self.log.info("tx: converting sRGB -> linear") + args.extend(["--colorconvert", "sRGB", "Raw"]) + else: + self.log.info("tx: texture's colorspace " + "is already linear") + else: + self.log.warning("tx: cannot guess the colorspace, " + "color conversion won't be " + "available!") + + args.append("maketx") + args.extend(args) + + texture_hash = source_hash(source, *args) + + # Exclude these additional arguments from the hashing because + # it is the hash itself + args.extend([ + "--sattrib", + "sourceHash", + texture_hash + ]) + + # Ensure folder exists + converted = os.path.join(staging_dir, "resources", fname + ".tx") + if not os.path.exists(os.path.dirname(converted)): + os.makedirs(os.path.dirname(converted)) + + self.log.info("Generating .tx file for %s .." % source) subprocess_args = [ maketx_path, @@ -186,18 +255,27 @@ def process(self, source, destination, *args): self.log.debug(" ".join(subprocess_args)) try: - out = run_subprocess(subprocess_args) + run_subprocess(subprocess_args) except Exception: self.log.error("Texture maketx conversion failed", exc_info=True) raise - return out + return converted, COPY, texture_hash, render_colorspace @staticmethod def get_extension(): return ".tx" + @staticmethod + def _has_arnold(): + """Return whether the arnold package is available and importable.""" + try: + import arnold # noqa: F401 + return True + except (ImportError, ModuleNotFoundError): + return False + @contextlib.contextmanager def no_workspace_dir(): @@ -565,7 +643,7 @@ def resource_destination(self, instance, filepath, processors): basename, ext = os.path.splitext(os.path.basename(filepath)) # Get extension from the last processor - for processors in reversed(processors): + for processor in reversed(processors): ext = processor.get_extension() self.log.debug("Processor {} defined extension: " "{}".format(processor, ext)) @@ -620,7 +698,6 @@ def _process_texture(self, Returns: tuple: (filepath, copy_mode, texture_hash, result_colorspace) """ - fname, ext = os.path.splitext(os.path.basename(filepath)) # Note: The texture hash is only reliable if we include any potential # conversion arguments provide to e.g. `maketx` @@ -629,104 +706,28 @@ def _process_texture(self, if len(processors) > 1: raise KnownPublishError( - "More than one texture processor not supported" + "More than one texture processor not supported. " + "Current processors enabled: {}".format(processors) ) # TODO: Make all processors take the same arguments for processor in processors: - if processor is MakeTX: - processed_path = processor().process(filepath, - converted, - "--sattrib", - "sourceHash", - escape_space(texture_hash), # noqa - colorconvert, - color_config, - ) - self.log.info("Generating texture file for %s .." % filepath) # noqa - self.log.info(converted) - if processed_path: - return processed_path, COPY, texture_hash - else: - self.log.info("maketx has returned nothing") - elif processor is MakeRSTexBin: - processed_path = processor().process(filepath) - self.log.info("Generating texture file for %s .." % filepath) # noqa - if processed_path: - return processed_path, COPY, texture_hash - else: - self.log.info("redshift texture converter has returned nothing") # noqa - - # TODO: continue this refactoring to processor - if do_maketx and ext != ".tx": - # Define .tx filepath in staging if source file is not .tx - converted = os.path.join(staging_dir, "resources", fname + ".tx") - - if color_management["enabled"]: - config_path = color_management["config"] - if not os.path.exists(config_path): - raise RuntimeError("OCIO config not found at: " - "{}".format(config_path)) - - render_colorspace = color_management["rendering_space"] - - self.log.info("tx: converting colorspace {0} " - "-> {1}".format(colorspace, render_colorspace)) - args.extend(["--colorconvert", colorspace, render_colorspace]) - args.extend(["--colorconfig", config_path]) - - else: - # We can't rely on the colorspace attribute when not - # in color managed mode because the collected color space - # is the color space attribute of the file node which can be - # any string whatsoever but only appears disabled in Attribute - # Editor. We assume we're always converting to linear/Raw if - # the source file is assumed to be sRGB. - render_colorspace = "linear" - if _has_arnold(): - img_info = image_info(filepath) - color_space = guess_colorspace(img_info) - if color_space.lower() == "sRGB": - self.log.info("tx: converting sRGB -> linear") - args.extend(["--colorconvert", "sRGB", "Raw"]) - else: - self.log.info("tx: texture's colorspace " - "is already linear") - else: - self.log.warning("tx: cannot guess the colorspace, " - "color conversion won't be available!") - - hash_args.append("maketx") - hash_args.extend(args) - - texture_hash = source_hash(filepath, *args) - - if not force_copy: - existing = self._get_existing_hashed_texture(filepath) - if existing: - return existing - - # Exclude these additional arguments from the hashing because - # it is the hash itself - args.extend([ - "--sattrib", - "sourceHash", - texture_hash - ]) - - # Ensure folder exists - if not os.path.exists(os.path.dirname(converted)): - os.makedirs(os.path.dirname(converted)) - - self.log.info("Generating .tx file for %s .." % filepath) - maketx( - filepath, - converted, - args, - self.log - ) - - return converted, COPY, texture_hash, render_colorspace + self.log.debug("Processing texture {} with processor {}".format( + filepath, processor + )) + + processed_result = processor.process(filepath, + colorspace, + color_management) + if not processed_result: + raise RuntimeError("Texture Processor {} returned " + "no result.".format(processor)) + + processed_path, processed_texture_hash = processed_result + self.log.info("Generated processed " + "texture: {}".format(processed_path)) + + return processed_path, COPY, processed_texture_hash # No special treatment for this file texture_hash = source_hash(filepath) From a6a392e9640b1028fe5f1e199df5bb0d96c4f570 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 25 Mar 2023 12:32:35 +0100 Subject: [PATCH 669/898] Allow maketx with color management enabled --- .../publish/validate_look_color_space.py | 26 ------------------- 1 file changed, 26 deletions(-) delete mode 100644 openpype/hosts/maya/plugins/publish/validate_look_color_space.py diff --git a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py deleted file mode 100644 index b1bdeb7541b..00000000000 --- a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py +++ /dev/null @@ -1,26 +0,0 @@ -from maya import cmds - -import pyblish.api -from openpype.pipeline.publish import ValidateContentsOrder -from openpype.pipeline import PublishValidationError - - -class ValidateMayaColorSpace(pyblish.api.InstancePlugin): - """ - Check if the OCIO Color Management and maketx options - enabled at the same time - """ - - order = ValidateContentsOrder - families = ['look'] - hosts = ['maya'] - label = 'Color Management with maketx' - - def process(self, instance): - ocio_maya = cmds.colorManagementPrefs(q=True, - cmConfigFileEnabled=True, - cmEnabled=True) - maketx = instance.data["maketx"] - - if ocio_maya and maketx: - raise PublishValidationError("Maya is color managed and maketx option is on. OpenPype doesn't support this combination yet.") # noqa From 6b841253d7e33d194db4e4cd3804952a819631b9 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 25 Mar 2023 14:26:22 +0100 Subject: [PATCH 670/898] Fix hash args --- openpype/hosts/maya/plugins/publish/extract_look.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 7515fdeb8c9..c8339a13355 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -217,10 +217,9 @@ def process(self, "color conversion won't be " "available!") - args.append("maketx") - args.extend(args) - - texture_hash = source_hash(source, *args) + hash_args = ["maketx"] + hash_args.extend(args) + texture_hash = source_hash(source, *hash_args) # Exclude these additional arguments from the hashing because # it is the hash itself From 44c0009e728921076bbfdad59fca0b834261b01c Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 25 Mar 2023 14:37:33 +0100 Subject: [PATCH 671/898] Allow to configure extra arguments in OP settings for `maketx` --- .../maya/plugins/publish/extract_look.py | 34 ++++++++++++++++--- .../defaults/project_settings/maya.json | 3 ++ .../schemas/schema_maya_publish.json | 16 +++++++++ 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index c8339a13355..2951261cd6e 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -139,13 +139,31 @@ def get_redshift_tool(tool_name): class MakeTX(TextureProcessor): + """Make `.tx` using `maketx` with some default settings.""" + + def __init__(self, log=None): + super(MakeTX, self).__init__(log=log) + self.extra_args = [] + + def apply_settings(self, system_settings, project_settings): + # Allow extra maketx arguments from project settings + extra_args_dict = ( + project_settings["maya"]["publish"] + .get("ExtractLook", {}) + .get("maketx_arguments", {}) + ) + extra_args = [] + for flag, value in extra_args_dict.items(): + extra_args.append(flag) + extra_args.append(value) + self.extra_args = extra_args def process(self, source, colorspace, color_management, staging_dir): - """Make `.tx` using `maketx` with some default settings. + """ The settings are based on default as used in Arnold's txManager in the scene. @@ -154,6 +172,10 @@ def process(self, Args: source (str): Path to source file. + colorspace (str): Colorspace of the source file. + color_management (dict): Maya Color management data from + `lib.get_color_management_preferences` + staging_dir (str): Output directory to write to. Returns: str: Output of `maketx` command. @@ -230,9 +252,9 @@ def process(self, ]) # Ensure folder exists - converted = os.path.join(staging_dir, "resources", fname + ".tx") - if not os.path.exists(os.path.dirname(converted)): - os.makedirs(os.path.dirname(converted)) + destination = os.path.join(staging_dir, "resources", fname + ".tx") + if not os.path.exists(os.path.dirname(destination)): + os.makedirs(os.path.dirname(destination)) self.log.info("Generating .tx file for %s .." % source) @@ -250,6 +272,8 @@ def process(self, ] subprocess_args.extend(args) + if self.extra_args: + subprocess_args.extend(self.extra_args) subprocess_args.extend(["-o", destination]) self.log.debug(" ".join(subprocess_args)) @@ -260,7 +284,7 @@ def process(self, exc_info=True) raise - return converted, COPY, texture_hash, render_colorspace + return destination, COPY, texture_hash, render_colorspace @staticmethod def get_extension(): diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index ef327fbd6b2..502dbda8707 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -925,6 +925,9 @@ "enabled": true, "active": true, "ogsfx_path": "/maya2glTF/PBR/shaders/glTF_PBR.ogsfx" + }, + "ExtractLook": { + "maketx_arguments": {} } }, "load": { diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json index 5a66f8a5130..da12dde6b26 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json @@ -996,6 +996,22 @@ "label": "GLSL Shader Directory" } ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ExtractLook", + "label": "Extract Look", + "children": [ + { + "key": "maketx_arguments", + "label": "Extra arguments for maketx command line", + "type": "dict-modifiable", + "object_type": { + "type": "text" + } + } + ] } ] } From c181d3ff2e14a3797a274ce9e90c1c08f21cac5f Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 25 Mar 2023 14:54:19 +0100 Subject: [PATCH 672/898] Intialize texture processors with applied settings --- .../maya/plugins/publish/extract_look.py | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 2951261cd6e..9777f14f11a 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -402,6 +402,25 @@ def process(self, instance): self.log.info("No sets found") return + # Specify texture processing executables to activate + # TODO: Load these more dynamically once we support more processors + processors = [] + context = instance.context + for key, Processor in { + # Instance data key to texture processor mapping + "maketx": MakeTX, + "rstex": MakeRSTexBin + }.items(): + if instance.data.get(key, False): + processor = Processor() + processor.apply_settings(context.data["system_settings"], + context.data["project_settings"]) + processors.append(processor) + + if processors: + self.log.debug("Collected texture processors: " + "{}".format(processors)) + self.log.debug("Processing resources..") results = self.process_resources(instance, staging_dir=dir_path) transfers = results["fileTransfers"] @@ -499,7 +518,7 @@ def _set_resource_result_colorspace(self, resource, colorspace): ) resource["result_colorspace"] = colorspace - def process_resources(self, instance, staging_dir): + def process_resources(self, instance, staging_dir, processors): """Process all resources in the instance. It is assumed that all resources are nodes using file textures. @@ -512,7 +531,6 @@ def process_resources(self, instance, staging_dir): """ resources = instance.data["resources"] - do_maketx = instance.data.get("maketx", False) color_management = lib.get_color_management_preferences() # Temporary fix to NOT create hardlinks on windows machines @@ -532,14 +550,6 @@ def process_resources(self, instance, staging_dir): destinations = {} remap = OrderedDict() - # Specify texture processing executables to activate - processors = [] - if instance.data.get("maketx", False): - processors.append(MakeTX) - # Option to convert textures to native redshift textures - if instance.data.get("rstex", False): - processors.append(MakeRSTexBin) - for resource in resources: colorspace = resource["color_space"] @@ -724,9 +734,6 @@ def _process_texture(self, # Note: The texture hash is only reliable if we include any potential # conversion arguments provide to e.g. `maketx` - args = [] - hash_args = [] - if len(processors) > 1: raise KnownPublishError( "More than one texture processor not supported. " @@ -741,7 +748,8 @@ def _process_texture(self, processed_result = processor.process(filepath, colorspace, - color_management) + color_management, + staging_dir) if not processed_result: raise RuntimeError("Texture Processor {} returned " "no result.".format(processor)) From e83708a3fb5da5710142578a4d433643ef529c89 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 25 Mar 2023 14:54:52 +0100 Subject: [PATCH 673/898] Cosmetics --- openpype/hosts/maya/plugins/publish/extract_look.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 9777f14f11a..632c64014f9 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -149,8 +149,7 @@ def apply_settings(self, system_settings, project_settings): # Allow extra maketx arguments from project settings extra_args_dict = ( project_settings["maya"]["publish"] - .get("ExtractLook", {}) - .get("maketx_arguments", {}) + .get("ExtractLook", {}).get("maketx_arguments", {}) ) extra_args = [] for flag, value in extra_args_dict.items(): From d8c763c191f46448cfdbbc17c8939f1c6bf7f9fd Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 25 Mar 2023 14:56:15 +0100 Subject: [PATCH 674/898] Include extra args in maketx texture hash --- openpype/hosts/maya/plugins/publish/extract_look.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 632c64014f9..41377bb8f6e 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -238,8 +238,11 @@ def process(self, "color conversion won't be " "available!") + # Note: The texture hash is only reliable if we include any potential + # conversion arguments provide to e.g. `maketx` hash_args = ["maketx"] hash_args.extend(args) + hash_args.extend(self.extra_args) texture_hash = source_hash(source, *hash_args) # Exclude these additional arguments from the hashing because @@ -731,8 +734,6 @@ def _process_texture(self, tuple: (filepath, copy_mode, texture_hash, result_colorspace) """ - # Note: The texture hash is only reliable if we include any potential - # conversion arguments provide to e.g. `maketx` if len(processors) > 1: raise KnownPublishError( "More than one texture processor not supported. " From ba1d0c570ab4a20417a450dd2c5c030ac3f4901d Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 25 Mar 2023 15:01:03 +0100 Subject: [PATCH 675/898] Fix arguments --- openpype/hosts/maya/plugins/publish/extract_look.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 41377bb8f6e..77cf0d8a831 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -424,7 +424,9 @@ def process(self, instance): "{}".format(processors)) self.log.debug("Processing resources..") - results = self.process_resources(instance, staging_dir=dir_path) + results = self.process_resources(instance, + staging_dir=dir_path, + processors=processors) transfers = results["fileTransfers"] hardlinks = results["fileHardlinks"] hashes = results["fileHashes"] From 0fa5eab7c904ab497274c37c6d0a8dfc38015f36 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 25 Mar 2023 20:29:49 +0100 Subject: [PATCH 676/898] Implement TextureResult dataclass + fix publishing with and without `maketx` --- .../maya/plugins/publish/extract_look.py | 106 ++++++++++++------ 1 file changed, 72 insertions(+), 34 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 77cf0d8a831..b166e85e7af 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -10,6 +10,7 @@ import platform import contextlib from collections import OrderedDict +import attr from maya import cmds # noqa @@ -26,6 +27,19 @@ HARDLINK = 2 +@attr.s +class TextureResult: + # Path to the file + path = attr.ib() + # Colorspace of the resulting texture. This might not be the input + # colorspace of the texture if a TextureProcessor has processed the file. + colorspace = attr.ib() + # Hash generated for the texture using openpype.lib.source_hash + file_hash = attr.ib() + # The transfer mode, e.g. COPY or HARDLINK + transfer_mode = attr.ib() + + def find_paths_by_hash(texture_hash): """Find the texture hash key in the dictionary. @@ -46,7 +60,7 @@ def find_paths_by_hash(texture_hash): class TextureProcessor: def __init__(self, log=None): if log is None: - log = logging.getLogger(self.__class___.__name__) + log = logging.getLogger(self.__class__.__name__) self.log = log @abstractmethod @@ -67,6 +81,10 @@ def process(self, def get_extension(): pass + def __repr__(self): + # Log instance as class name + return self.__class__.__name__ + class MakeRSTexBin(TextureProcessor): """Make `.rstexbin` using `redshiftTextureProcessor`""" @@ -100,6 +118,9 @@ def process(self, source ] + hash_args = ["rstex"] + texture_hash = source_hash(source, *hash_args) + self.log.debug(" ".join(subprocess_args)) try: out = run_subprocess(subprocess_args) @@ -108,8 +129,12 @@ def process(self, exc_info=True) raise - # TODO: Implement correct return values - return out + return TextureResult( + path=out, + file_hash=texture_hash, + colorspace=colorspace, + transfer_mode=COPY + ) @staticmethod def get_extension(): @@ -192,10 +217,13 @@ def process(self, # Define .tx filepath in staging if source file is not .tx fname, ext = os.path.splitext(os.path.basename(source)) if ext == ".tx": - # TODO: Implement this fallback # Do nothing if the source file is already a .tx file. - # return source, COPY, texture_hash, render_colorspace - pass + return TextureResult( + path=source, + file_hash=None, # todo: unknown texture hash? + colorspace=colorspace, + transfer_mode=COPY + ) args = [] if color_management["enabled"]: @@ -286,7 +314,12 @@ def process(self, exc_info=True) raise - return destination, COPY, texture_hash, render_colorspace + return TextureResult( + path=destination, + file_hash=texture_hash, + colorspace=render_colorspace, + transfer_mode=COPY + ) @staticmethod def get_extension(): @@ -510,17 +543,17 @@ def process(self, instance): def _set_resource_result_colorspace(self, resource, colorspace): """Update resource resulting colorspace after texture processing""" - if "result_colorspace" in resource: - if resource["result_colorspace"] == colorspace: + if "result_color_space" in resource: + if resource["result_color_space"] == colorspace: return self.log.warning( "Resource already has a resulting colorspace but is now " "being overridden to a new one: {} -> {}".format( - resource["result_colorspace"], colorspace + resource["result_color_space"], colorspace ) ) - resource["result_colorspace"] = colorspace + resource["result_color_space"] = colorspace def process_resources(self, instance, staging_dir, processors): """Process all resources in the instance. @@ -592,37 +625,33 @@ def process_resources(self, instance, staging_dir, processors): color_management=color_management, colorspace=colorspace ) - source, mode, texture_hash, result_colorspace = texture_result + source = texture_result.path destination = self.resource_destination(instance, - source, + texture_result.path, processors) # Set the resulting color space on the resource self._set_resource_result_colorspace( - resource, colorspace=result_colorspace + resource, colorspace=texture_result.colorspace ) processed_files[filepath] = { "color_space": colorspace, - "result_color_space": result_colorspace, + "result_color_space": texture_result.colorspace, } - # Force copy is specified. - if force_copy: - mode = COPY - - if mode == COPY: + if force_copy or texture_result.transfer_mode == COPY: transfers.append((source, destination)) self.log.info('file will be copied {} -> {}'.format( source, destination)) - elif mode == HARDLINK: + elif texture_result.transfer_mode == HARDLINK: hardlinks.append((source, destination)) self.log.info('file will be hardlinked {} -> {}'.format( source, destination)) # Store the hashes from hash to destination to include in the # database - hashes[texture_hash] = destination + hashes[texture_result.file_hash] = destination source = os.path.normpath(resource["source"]) if source not in destinations: @@ -697,10 +726,9 @@ def _get_existing_hashed_texture(self, texture_hash): # then don't reprocess but hardlink from the original existing = find_paths_by_hash(texture_hash) if existing: - self.log.info("Found hash in database, preparing hardlink..") source = next((p for p in existing if os.path.exists(p)), None) if source: - return source, HARDLINK, texture_hash + return source else: self.log.warning( "Paths not found on disk, " @@ -722,7 +750,7 @@ def _process_texture(self, Args: filepath (str): The source file path to process. - processors (list): List of TexProcessor processing the texture + processors (list): List of TextureProcessor processing the texture staging_dir (str): The staging directory to write to. force_copy (bool): Whether to force a copy even if a file hash might have existed already in the project, otherwise @@ -733,7 +761,7 @@ def _process_texture(self, texture belongs to. Returns: - tuple: (filepath, copy_mode, texture_hash, result_colorspace) + TextureResult: The texture result information. """ if len(processors) > 1: @@ -742,7 +770,6 @@ def _process_texture(self, "Current processors enabled: {}".format(processors) ) - # TODO: Make all processors take the same arguments for processor in processors: self.log.debug("Processing texture {} with processor {}".format( filepath, processor @@ -755,21 +782,32 @@ def _process_texture(self, if not processed_result: raise RuntimeError("Texture Processor {} returned " "no result.".format(processor)) - - processed_path, processed_texture_hash = processed_result self.log.info("Generated processed " - "texture: {}".format(processed_path)) + "texture: {}".format(processed_result.path)) - return processed_path, COPY, processed_texture_hash + # TODO: Currently all processors force copy instead of allowing + # hardlinks using source hashes. This should be refactored + return processed_result - # No special treatment for this file + # No texture processing for this file texture_hash = source_hash(filepath) if not force_copy: existing = self._get_existing_hashed_texture(filepath) if existing: - return existing + self.log.info("Found hash in database, preparing hardlink..") + return TextureResult( + path=filepath, + file_hash=texture_hash, + colorspace=colorspace, + transfer_mode=HARDLINK + ) - return filepath, COPY, texture_hash, colorspace + return TextureResult( + path=filepath, + file_hash=texture_hash, + colorspace=colorspace, + transfer_mode=COPY + ) class ExtractModelRenderSets(ExtractLook): From 81b5d771270b27849ee322d09c06e9ee75cd4f73 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 25 Mar 2023 20:42:34 +0100 Subject: [PATCH 677/898] Cleanup, fix Py2 compatibility --- .../maya/plugins/publish/extract_look.py | 47 ++++++++++++++----- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index b166e85e7af..dd59cd7dcc2 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -63,7 +63,6 @@ def __init__(self, log=None): log = logging.getLogger(self.__class__.__name__) self.log = log - @abstractmethod def apply_settings(self, system_settings, project_settings): pass @@ -73,11 +72,28 @@ def process(self, colorspace, color_management, staging_dir): + """Process the `source` texture. + + Must be implemented on inherited class. + + This must always return a TextureResult even when it does not generate + a texture. If it doesn't generate a texture then it should return a + TextureResult using the input path and colorspace. + + Args: + source (str): Path to source file. + colorspace (str): Colorspace of the source file. + color_management (dict): Maya Color management data from + `lib.get_color_management_preferences` + staging_dir (str): Output directory to write to. + + Returns: + TextureResult: The resulting texture information. + + """ pass - # TODO: Warning this only supports Py3.3+ @staticmethod - @abstractmethod def get_extension(): pass @@ -164,7 +180,12 @@ def get_redshift_tool(tool_name): class MakeTX(TextureProcessor): - """Make `.tx` using `maketx` with some default settings.""" + """Make `.tx` using `maketx` with some default settings. + + Some hardcoded arguments passed to `maketx` are based on the defaults used + in Arnold's txManager tool. + + """ def __init__(self, log=None): super(MakeTX, self).__init__(log=log) @@ -187,12 +208,10 @@ def process(self, colorspace, color_management, staging_dir): - """ + """Process the texture. - The settings are based on default as used in Arnold's - txManager in the scene. This function requires the `maketx` executable to be - on the `PATH`. + available in the OIIO tool. Args: source (str): Path to source file. @@ -202,7 +221,7 @@ def process(self, staging_dir (str): Output directory to write to. Returns: - str: Output of `maketx` command. + TextureResult: The resulting texture information. """ from openpype.lib import get_oiio_tools_path @@ -474,7 +493,7 @@ def process(self, instance): # To avoid Maya trying to automatically remap the file # textures relative to the `workspace -directory` we force # it to a fake temporary workspace. This fixes textures - # getting incorrectly remapped. (LKD-17, PLN-101) + # getting incorrectly remapped. with no_workspace_dir(): with lib.attribute_values(remap): with lib.maintained_selection(): @@ -710,9 +729,11 @@ def resource_destination(self, instance, filepath, processors): # Get extension from the last processor for processor in reversed(processors): - ext = processor.get_extension() - self.log.debug("Processor {} defined extension: " - "{}".format(processor, ext)) + processor_ext = processor.get_extension() + if processor_ext: + self.log.debug("Processor {} defined extension: " + "{}".format(processor, ext)) + ext = processor_ext break return os.path.join( From 7e92f2184e52f2b75f8f85e930bb8974f8e4289c Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Sun, 26 Mar 2023 09:43:27 +0100 Subject: [PATCH 678/898] Default playblast compression to PNG --- openpype/settings/defaults/project_settings/maya.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index 4a97ea8a09c..e914eb29f98 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -790,7 +790,7 @@ "ExtractPlayblast": { "capture_preset": { "Codec": { - "compression": "jpg", + "compression": "png", "format": "image", "quality": 95 }, From 16e5bb630f015f7deaa9a86e592cfe8f34fb94ac Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 26 Mar 2023 20:30:35 +0200 Subject: [PATCH 679/898] Cleanup --- openpype/hosts/maya/plugins/publish/extract_look.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index dd59cd7dcc2..2368295bf4b 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -441,8 +441,6 @@ def process(self, instance): dir_path = self.staging_dir(instance) maya_fname = "{0}.{1}".format(instance.name, self.scene_type) json_fname = "{0}.{1}".format(instance.name, self.look_data_type) - - # Make texture dump folder maya_path = os.path.join(dir_path, maya_fname) json_path = os.path.join(dir_path, json_fname) From b340f6a57ca0ae9c22c29e0e2efebe23e8685df8 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 26 Mar 2023 20:51:10 +0200 Subject: [PATCH 680/898] Clarify more about the issue in logging message + minor cleanup --- .../hosts/maya/plugins/publish/extract_look.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 2368295bf4b..b68d8ae5455 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -623,10 +623,14 @@ def process_resources(self, instance, staging_dir, processors): if colorspace != processed_file["color_space"]: self.log.warning( - "File was already processed but using another" - "colorspace: {} <-> {}" - "".format(colorspace, - processed_file["color_space"])) + "File '{}' was already processed using colorspace " + "'{}' instead of the current resource's " + "colorspace '{}'. The already processed texture " + "result's colorspace '{}' will be used." + "".format(filepath, + colorspace, + processed_file["color_space"], + processed_file["result_color_space"])) self._set_resource_result_colorspace( resource, @@ -642,7 +646,6 @@ def process_resources(self, instance, staging_dir, processors): color_management=color_management, colorspace=colorspace ) - source = texture_result.path destination = self.resource_destination(instance, texture_result.path, processors) @@ -657,6 +660,7 @@ def process_resources(self, instance, staging_dir, processors): "result_color_space": texture_result.colorspace, } + source = texture_result.path if force_copy or texture_result.transfer_mode == COPY: transfers.append((source, destination)) self.log.info('file will be copied {} -> {}'.format( From 81e25eb3a30a4ad801f09ff528458f5ba309e4fb Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 26 Mar 2023 21:06:50 +0200 Subject: [PATCH 681/898] Move caching into one place --- .../maya/plugins/publish/extract_look.py | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index b68d8ae5455..2e268749a0f 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -596,14 +596,23 @@ def process_resources(self, instance, staging_dir, processors): else: force_copy = instance.data.get("forceCopy", False) + destinations_cache = {} + + def get_resource_destination_cached(path): + """Get resource destination with cached result per filepath""" + if path not in destinations_cache: + self.get_resource_destination(path, + instance.data["resourcesDir"], + processors) + destinations_cache[path] = destination + return destinations_cache[path] + # Process all resource's individual files processed_files = {} transfers = [] hardlinks = [] hashes = {} - destinations = {} remap = OrderedDict() - for resource in resources: colorspace = resource["color_space"] @@ -646,9 +655,6 @@ def process_resources(self, instance, staging_dir, processors): color_management=color_management, colorspace=colorspace ) - destination = self.resource_destination(instance, - texture_result.path, - processors) # Set the resulting color space on the resource self._set_resource_result_colorspace( @@ -661,6 +667,7 @@ def process_resources(self, instance, staging_dir, processors): } source = texture_result.path + destination = get_resource_destination_cached(source) if force_copy or texture_result.transfer_mode == COPY: transfers.append((source, destination)) self.log.info('file will be copied {} -> {}'.format( @@ -674,14 +681,6 @@ def process_resources(self, instance, staging_dir, processors): # database hashes[texture_result.file_hash] = destination - source = os.path.normpath(resource["source"]) - if source not in destinations: - # Cache destination as source resource might be included - # multiple times - destinations[source] = self.resource_destination( - instance, source, processors - ) - # Set up remapping attributes for the node during the publish # The order of these can be important if one attribute directly # affects another, e.g. we set colorspace after filepath because @@ -690,7 +689,9 @@ def process_resources(self, instance, staging_dir, processors): # attributes changed in the resulting publish) # Remap filepath to publish destination filepath_attr = resource["attribute"] - remap[filepath_attr] = destinations[source] + remap[filepath_attr] = get_resource_destination_cached( + resource["source"] + ) # Preserve color space values (force value after filepath change) # This will also trigger in the same order at end of context to @@ -709,23 +710,21 @@ def process_resources(self, instance, staging_dir, processors): "attrRemap": remap, } - def resource_destination(self, instance, filepath, processors): + def get_resource_destination(self, filepath, resources_dir, processors): """Get resource destination path. This is utility function to change path if resource file name is changed by some external tool like `maketx`. Args: - instance: Current Instance. - filepath (str): Resource path - processor: Texture processors converting resource. + filepath (str): Resource source path + resources_dir (str): Destination dir for resources in publish. + processors (list): Texture processors converting resource. Returns: str: Path to resource file """ - resources_dir = instance.data["resourcesDir"] - # Compute destination location basename, ext = os.path.splitext(os.path.basename(filepath)) From 03e5ff92ea3d6d229d7b91640852eead7628a356 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 26 Mar 2023 21:07:38 +0200 Subject: [PATCH 682/898] Fix typo --- openpype/hosts/maya/plugins/publish/extract_look.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 2e268749a0f..f846b4ee3da 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -601,9 +601,8 @@ def process_resources(self, instance, staging_dir, processors): def get_resource_destination_cached(path): """Get resource destination with cached result per filepath""" if path not in destinations_cache: - self.get_resource_destination(path, - instance.data["resourcesDir"], - processors) + destination = self.get_resource_destination( + path, instance.data["resourcesDir"], processors) destinations_cache[path] = destination return destinations_cache[path] From 2917ee27750384a3c952ced17e257fa99d48aeb8 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 26 Mar 2023 21:10:57 +0200 Subject: [PATCH 683/898] Fix logging --- openpype/hosts/maya/plugins/publish/extract_look.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index f846b4ee3da..d5d8da04e78 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -730,9 +730,11 @@ def get_resource_destination(self, filepath, resources_dir, processors): # Get extension from the last processor for processor in reversed(processors): processor_ext = processor.get_extension() - if processor_ext: - self.log.debug("Processor {} defined extension: " - "{}".format(processor, ext)) + if processor_ext and ext != processor_ext: + self.log.debug("Processor {} overrides extension to '{}' " + "for path: {}".format(processor, + processor_ext, + filepath)) ext = processor_ext break From 00e5f220f4fd664ecd00cc7cae4fefab6984f89c Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 26 Mar 2023 21:12:37 +0200 Subject: [PATCH 684/898] Add todo --- openpype/hosts/maya/plugins/publish/extract_look.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index d5d8da04e78..33ba4cc7a34 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -687,6 +687,11 @@ def get_resource_destination_cached(path): # filepaths (which is avoidable, but we don't want to have those # attributes changed in the resulting publish) # Remap filepath to publish destination + # TODO It would be much better if we could use the destination path + # from the actual processed texture results, but since the + # attribute will need to preserve tokens like , etc for + # now we will define the output path from the attribute value + # including the tokens to persist them. filepath_attr = resource["attribute"] remap[filepath_attr] = get_resource_destination_cached( resource["source"] From 09e0ba54f24c73a721f6f4d31ce23c3d786178c6 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 27 Mar 2023 09:57:37 +0200 Subject: [PATCH 685/898] TVPaint: Optional Validation plugins can be de/activated by user (#4674) * fix TVPaint validation plugins so they can be enabled/disabled * add missing 'is_active' method usage * added option to enable auto detet render creator * added fps to instance data * safe access to layers * fix handling of missing render layer * render passes are safer * fix convertor plugin --- .../tvpaint/plugins/create/convert_legacy.py | 4 ++-- .../hosts/tvpaint/plugins/create/create_render.py | 15 ++++++++------- .../plugins/publish/collect_instance_frames.py | 2 ++ .../plugins/publish/validate_asset_name.py | 12 ++++++++++-- .../plugins/publish/validate_layers_visibility.py | 2 +- .../tvpaint/plugins/publish/validate_marks.py | 13 +++++++++++-- .../plugins/publish/validate_scene_settings.py | 13 +++++++++++-- .../plugins/publish/validate_start_frame.py | 13 +++++++++++-- .../defaults/project_settings/tvpaint.json | 1 + .../projects_schema/schema_project_tvpaint.json | 6 ++++++ 10 files changed, 63 insertions(+), 18 deletions(-) diff --git a/openpype/hosts/tvpaint/plugins/create/convert_legacy.py b/openpype/hosts/tvpaint/plugins/create/convert_legacy.py index 538c6e4c5e8..5cfa1faa506 100644 --- a/openpype/hosts/tvpaint/plugins/create/convert_legacy.py +++ b/openpype/hosts/tvpaint/plugins/create/convert_legacy.py @@ -55,7 +55,7 @@ def convert(self): self._convert_render_layers( to_convert["renderLayer"], current_instances) self._convert_render_passes( - to_convert["renderpass"], current_instances) + to_convert["renderPass"], current_instances) self._convert_render_scenes( to_convert["renderScene"], current_instances) self._convert_workfiles( @@ -116,7 +116,7 @@ def _convert_render_passes(self, render_passes, current_instances): render_layers_by_group_id = {} for instance in current_instances: if instance.get("creator_identifier") == "render.layer": - group_id = instance["creator_identifier"]["group_id"] + group_id = instance["creator_attributes"]["group_id"] render_layers_by_group_id[group_id] = instance for render_pass in render_passes: diff --git a/openpype/hosts/tvpaint/plugins/create/create_render.py b/openpype/hosts/tvpaint/plugins/create/create_render.py index 9711024c79c..2369c7329f6 100644 --- a/openpype/hosts/tvpaint/plugins/create/create_render.py +++ b/openpype/hosts/tvpaint/plugins/create/create_render.py @@ -415,11 +415,11 @@ def collect_instances(self): .get("creator_attributes", {}) .get("render_layer_instance_id") ) - render_layer_info = render_layers.get(render_layer_instance_id) + render_layer_info = render_layers.get(render_layer_instance_id, {}) self.update_instance_labels( instance_data, - render_layer_info["variant"], - render_layer_info["template_data"] + render_layer_info.get("variant"), + render_layer_info.get("template_data") ) instance = CreatedInstance.from_existing(instance_data, self) self._add_instance_to_context(instance) @@ -607,11 +607,11 @@ def get_pre_create_attr_defs(self): current_instances = self.host.list_instances() render_layers = [ { - "value": instance["instance_id"], - "label": instance["subset"] + "value": inst["instance_id"], + "label": inst["subset"] } - for instance in current_instances - if instance["creator_identifier"] == CreateRenderlayer.identifier + for inst in current_instances + if inst.get("creator_identifier") == CreateRenderlayer.identifier ] if not render_layers: render_layers.append({"value": None, "label": "N/A"}) @@ -697,6 +697,7 @@ def apply_settings(self, project_settings, system_settings): ["create"] ["auto_detect_render"] ) + self.enabled = plugin_settings.get("enabled", False) self.allow_group_rename = plugin_settings["allow_group_rename"] self.group_name_template = plugin_settings["group_name_template"] self.group_idx_offset = plugin_settings["group_idx_offset"] diff --git a/openpype/hosts/tvpaint/plugins/publish/collect_instance_frames.py b/openpype/hosts/tvpaint/plugins/publish/collect_instance_frames.py index 5eb702a1da4..63f04cf3ce6 100644 --- a/openpype/hosts/tvpaint/plugins/publish/collect_instance_frames.py +++ b/openpype/hosts/tvpaint/plugins/publish/collect_instance_frames.py @@ -22,9 +22,11 @@ def process(self, instance): context = instance.context frame_start = asset_doc["data"]["frameStart"] + fps = asset_doc["data"]["fps"] frame_end = frame_start + ( context.data["sceneMarkOut"] - context.data["sceneMarkIn"] ) + instance.data["fps"] = fps instance.data["frameStart"] = frame_start instance.data["frameEnd"] = frame_end self.log.info( diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_asset_name.py b/openpype/hosts/tvpaint/plugins/publish/validate_asset_name.py index 7e35726030d..d7984ce9719 100644 --- a/openpype/hosts/tvpaint/plugins/publish/validate_asset_name.py +++ b/openpype/hosts/tvpaint/plugins/publish/validate_asset_name.py @@ -1,5 +1,8 @@ import pyblish.api -from openpype.pipeline import PublishXmlValidationError +from openpype.pipeline import ( + PublishXmlValidationError, + OptionalPyblishPluginMixin, +) from openpype.hosts.tvpaint.api.pipeline import ( list_instances, write_instances, @@ -31,7 +34,10 @@ def process(self, context, plugin): write_instances(new_instance_items) -class ValidateAssetNames(pyblish.api.ContextPlugin): +class ValidateAssetName( + OptionalPyblishPluginMixin, + pyblish.api.ContextPlugin +): """Validate assset name present on instance. Asset name on instance should be the same as context's. @@ -43,6 +49,8 @@ class ValidateAssetNames(pyblish.api.ContextPlugin): actions = [FixAssetNames] def process(self, context): + if not self.is_active(context.data): + return context_asset_name = context.data["asset"] for instance in context: asset_name = instance.data.get("asset") diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_layers_visibility.py b/openpype/hosts/tvpaint/plugins/publish/validate_layers_visibility.py index 6a496a2e496..8e52a636f4f 100644 --- a/openpype/hosts/tvpaint/plugins/publish/validate_layers_visibility.py +++ b/openpype/hosts/tvpaint/plugins/publish/validate_layers_visibility.py @@ -11,7 +11,7 @@ class ValidateLayersVisiblity(pyblish.api.InstancePlugin): families = ["review", "render"] def process(self, instance): - layers = instance.data["layers"] + layers = instance.data.get("layers") # Instance have empty layers # - it is not job of this validator to check that if not layers: diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_marks.py b/openpype/hosts/tvpaint/plugins/publish/validate_marks.py index 0030b0fd1ce..7b2cc62bb5a 100644 --- a/openpype/hosts/tvpaint/plugins/publish/validate_marks.py +++ b/openpype/hosts/tvpaint/plugins/publish/validate_marks.py @@ -1,7 +1,10 @@ import json import pyblish.api -from openpype.pipeline import PublishXmlValidationError +from openpype.pipeline import ( + PublishXmlValidationError, + OptionalPyblishPluginMixin, +) from openpype.hosts.tvpaint.api.lib import execute_george @@ -23,7 +26,10 @@ def process(self, context, plugin): ) -class ValidateMarks(pyblish.api.ContextPlugin): +class ValidateMarks( + OptionalPyblishPluginMixin, + pyblish.api.ContextPlugin +): """Validate mark in and out are enabled and it's duration. Mark In/Out does not have to match frameStart and frameEnd but duration is @@ -59,6 +65,9 @@ def get_expected_data(context): } def process(self, context): + if not self.is_active(context.data): + return + current_data = { "markIn": context.data["sceneMarkIn"], "markInState": context.data["sceneMarkInState"], diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_scene_settings.py b/openpype/hosts/tvpaint/plugins/publish/validate_scene_settings.py index 4473e4b1b79..0ab8e811f58 100644 --- a/openpype/hosts/tvpaint/plugins/publish/validate_scene_settings.py +++ b/openpype/hosts/tvpaint/plugins/publish/validate_scene_settings.py @@ -1,11 +1,17 @@ import json import pyblish.api -from openpype.pipeline import PublishXmlValidationError +from openpype.pipeline import ( + PublishXmlValidationError, + OptionalPyblishPluginMixin, +) # TODO @iLliCiTiT add fix action for fps -class ValidateProjectSettings(pyblish.api.ContextPlugin): +class ValidateProjectSettings( + OptionalPyblishPluginMixin, + pyblish.api.ContextPlugin +): """Validate scene settings against database.""" label = "Validate Scene Settings" @@ -13,6 +19,9 @@ class ValidateProjectSettings(pyblish.api.ContextPlugin): optional = True def process(self, context): + if not self.is_active(context.data): + return + expected_data = context.data["assetEntity"]["data"] scene_data = { "fps": context.data.get("sceneFps"), diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_start_frame.py b/openpype/hosts/tvpaint/plugins/publish/validate_start_frame.py index 066e54c6707..229ccfcd18f 100644 --- a/openpype/hosts/tvpaint/plugins/publish/validate_start_frame.py +++ b/openpype/hosts/tvpaint/plugins/publish/validate_start_frame.py @@ -1,5 +1,8 @@ import pyblish.api -from openpype.pipeline import PublishXmlValidationError +from openpype.pipeline import ( + PublishXmlValidationError, + OptionalPyblishPluginMixin, +) from openpype.hosts.tvpaint.api.lib import execute_george @@ -14,7 +17,10 @@ def process(self, context, plugin): execute_george("tv_startframe 0") -class ValidateStartFrame(pyblish.api.ContextPlugin): +class ValidateStartFrame( + OptionalPyblishPluginMixin, + pyblish.api.ContextPlugin +): """Validate start frame being at frame 0.""" label = "Validate Start Frame" @@ -24,6 +30,9 @@ class ValidateStartFrame(pyblish.api.ContextPlugin): optional = True def process(self, context): + if not self.is_active(context.data): + return + start_frame = execute_george("tv_startframe") if start_frame == 0: return diff --git a/openpype/settings/defaults/project_settings/tvpaint.json b/openpype/settings/defaults/project_settings/tvpaint.json index 9173a8c3d5a..1671748e977 100644 --- a/openpype/settings/defaults/project_settings/tvpaint.json +++ b/openpype/settings/defaults/project_settings/tvpaint.json @@ -42,6 +42,7 @@ "default_variants": [] }, "auto_detect_render": { + "enabled": false, "allow_group_rename": true, "group_name_template": "L{group_index}", "group_idx_offset": 10, diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json b/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json index 708b688ba5f..10945958513 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json @@ -202,7 +202,13 @@ "key": "auto_detect_render", "label": "Auto-Detect Create Render", "is_group": true, + "checkbox_key": "enabled", "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, { "type": "label", "label": "The creator tries to auto-detect Render Layers and Render Passes in scene. For Render Layers is used group name as a variant and for Render Passes is used TVPaint layer name.

    Group names can be renamed by their used order in scene. The renaming template where can be used {group_index} formatting key which is filled by \"used position index of group\".
    - Template: L{group_index}
    - Group offset: 10
    - Group padding: 3
    Would create group names \"L010\", \"L020\", ..." From 35f76a2365d76aa97ca32a5591e831662dcd4029 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 27 Mar 2023 10:20:02 +0200 Subject: [PATCH 686/898] Fix Redshift .rstexbin support --- openpype/hosts/maya/plugins/publish/extract_look.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 33ba4cc7a34..46eb940879e 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -137,16 +137,21 @@ def process(self, hash_args = ["rstex"] texture_hash = source_hash(source, *hash_args) + # Redshift stores the output texture next to the input but with + # the extension replaced to `.rstexbin + basename, ext = os.path.splitext(source) + destination = "{}{}".format(basename, self.get_extension()) + self.log.debug(" ".join(subprocess_args)) try: - out = run_subprocess(subprocess_args) + run_subprocess(subprocess_args) except Exception: self.log.error("Texture .rstexbin conversion failed", exc_info=True) raise return TextureResult( - path=out, + path=destination, file_hash=texture_hash, colorspace=colorspace, transfer_mode=COPY From 95fcce48bd3a2476a89bf2823fb1abcaa8b1d056 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 27 Mar 2023 10:22:33 +0200 Subject: [PATCH 687/898] Move `REDSHIFT_COREDATAPATH` environment check to `get_redshift_tool` --- openpype/hosts/maya/plugins/publish/extract_look.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 46eb940879e..ad9ba342245 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -120,9 +120,6 @@ def process(self, source (str): Path to source file. """ - if "REDSHIFT_COREDATAPATH" not in os.environ: - raise RuntimeError("Must have Redshift available.") - texture_processor_path = self.get_redshift_tool( "redshiftTextureProcessor" ) @@ -173,10 +170,11 @@ def get_redshift_tool(tool_name): Returns: str: Full path to redshift texture processor executable. """ - redshift_os_path = os.environ["REDSHIFT_COREDATAPATH"] + if "REDSHIFT_COREDATAPATH" not in os.environ: + raise RuntimeError("Must have Redshift available.") redshift_tool_path = os.path.join( - redshift_os_path, + os.environ["REDSHIFT_COREDATAPATH"], "bin", tool_name ) From 9773cbbedc5224b130badee8a734d090c76aee33 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 27 Mar 2023 10:27:13 +0200 Subject: [PATCH 688/898] Cleanup --- .../maya/plugins/publish/extract_look.py | 92 ++++++++++--------- 1 file changed, 47 insertions(+), 45 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index ad9ba342245..4e04999e7e7 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -29,6 +29,7 @@ @attr.s class TextureResult: + """The resulting texture of a processed file for a resource""" # Path to the file path = attr.ib() # Colorspace of the resulting texture. This might not be the input @@ -56,6 +57,38 @@ def find_paths_by_hash(texture_hash): return legacy_io.distinct(key, {"type": "version"}) +@contextlib.contextmanager +def no_workspace_dir(): + """Force maya to a fake temporary workspace directory. + + Note: This is not maya.cmds.workspace 'rootDirectory' but the 'directory' + + This helps to avoid Maya automatically remapping image paths to files + relative to the currently set directory. + + """ + + # Store current workspace + original = cmds.workspace(query=True, directory=True) + + # Set a fake workspace + fake_workspace_dir = tempfile.mkdtemp() + cmds.workspace(directory=fake_workspace_dir) + + try: + yield + finally: + try: + cmds.workspace(directory=original) + except RuntimeError: + # If the original workspace directory didn't exist either + # ignore the fact that it fails to reset it to the old path + pass + + # Remove the temporary directory + os.rmdir(fake_workspace_dir) + + @six.add_metaclass(ABCMeta) class TextureProcessor: def __init__(self, log=None): @@ -64,6 +97,16 @@ def __init__(self, log=None): self.log = log def apply_settings(self, system_settings, project_settings): + """Apply OpenPype system/project settings to the TextureProcessor + + Args: + system_settings (dict): OpenPype system settings + project_settings (dict): OpenPype project settings + + Returns: + None + + """ pass @abstractmethod @@ -110,16 +153,7 @@ def process(self, colorspace, color_management, staging_dir): - """ - with some default settings. - - This function requires the `REDSHIFT_COREDATAPATH` - to be in `PATH`. - - Args: - source (str): Path to source file. - """ texture_processor_path = self.get_redshift_tool( "redshiftTextureProcessor" ) @@ -135,7 +169,7 @@ def process(self, texture_hash = source_hash(source, *hash_args) # Redshift stores the output texture next to the input but with - # the extension replaced to `.rstexbin + # the extension replaced to `.rstexbin` basename, ext = os.path.splitext(source) destination = "{}{}".format(basename, self.get_extension()) @@ -165,7 +199,7 @@ def get_redshift_tool(tool_name): On Windows it adds .exe extension if missing from tool argument. Args: - tool (string): Tool name. + tool_name (string): Tool name. Returns: str: Full path to redshift texture processor executable. @@ -213,8 +247,8 @@ def process(self, staging_dir): """Process the texture. - This function requires the `maketx` executable to be - available in the OIIO tool. + This function requires the `maketx` executable to be available in an + OpenImageIO toolset detectable by OpenPype. Args: source (str): Path to source file. @@ -357,38 +391,6 @@ def _has_arnold(): return False -@contextlib.contextmanager -def no_workspace_dir(): - """Force maya to a fake temporary workspace directory. - - Note: This is not maya.cmds.workspace 'rootDirectory' but the 'directory' - - This helps to avoid Maya automatically remapping image paths to files - relative to the currently set directory. - - """ - - # Store current workspace - original = cmds.workspace(query=True, directory=True) - - # Set a fake workspace - fake_workspace_dir = tempfile.mkdtemp() - cmds.workspace(directory=fake_workspace_dir) - - try: - yield - finally: - try: - cmds.workspace(directory=original) - except RuntimeError: - # If the original workspace directory didn't exist either - # ignore the fact that it fails to reset it to the old path - pass - - # Remove the temporary directory - os.rmdir(fake_workspace_dir) - - class ExtractLook(publish.Extractor): """Extract Look (Maya Scene + JSON) From 52511c1e3f8924c89a100cdbe2f2d2c34923ef4f Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Mon, 27 Mar 2023 10:07:54 +0100 Subject: [PATCH 689/898] Update openpype/scripts/otio_burnin.py Co-authored-by: Roy Nieterau --- openpype/scripts/otio_burnin.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index afae4f9e08f..1f151b5dc61 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -42,7 +42,22 @@ def convert_list_to_commands(list_to_convert, fps, label=""): - path = None + """Convert a list of values to a drawtext command file for ffmpeg `sendcmd` + + The list of values is expected to have a value per frame. If the video + file ends up being longer than the amount of samples per frame than the + last value will be held. + + Args: + list_to_convert (list): List of values per frame. + fps (float or int): The expected frame per seconds of the output file + label (str): Label for the + + Returns: + str: Filepath to the temporary drawtext command file. + + """ + with tempfile.NamedTemporaryFile(mode="w", delete=False) as f: for i, value in enumerate(list_to_convert): seconds = i / fps @@ -61,9 +76,7 @@ def convert_list_to_commands(list_to_convert, fps, label=""): f.write(line) f.flush() - path = f.name - - return path + return f.name def _get_ffprobe_data(source): From 28a4f09625f6dc7f9aad7c8cd6a26bfe25c4f370 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Mon, 27 Mar 2023 10:10:21 +0100 Subject: [PATCH 690/898] Finish method description --- openpype/scripts/otio_burnin.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index 1f151b5dc61..ca0930537c2 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -50,8 +50,9 @@ def convert_list_to_commands(list_to_convert, fps, label=""): Args: list_to_convert (list): List of values per frame. - fps (float or int): The expected frame per seconds of the output file - label (str): Label for the + fps (float or int): The expected frame per seconds of the output file. + label (str): Label for the drawtext, if specific drawtext filter is + required Returns: str: Filepath to the temporary drawtext command file. From eaca4f5551032ebea9a0790c331109ce88005290 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Mon, 27 Mar 2023 10:10:31 +0100 Subject: [PATCH 691/898] Change method name --- openpype/scripts/otio_burnin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index ca0930537c2..57a1dcfaffc 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -41,7 +41,7 @@ SOURCE_TIMECODE_KEY = "{source_timecode}" -def convert_list_to_commands(list_to_convert, fps, label=""): +def convert_list_to_command(list_to_convert, fps, label=""): """Convert a list of values to a drawtext command file for ffmpeg `sendcmd` The list of values is expected to have a value per frame. If the video @@ -627,7 +627,7 @@ def burnins_from_data( if list_to_convert: value = list_to_convert[0] - path = convert_list_to_commands( + path = convert_list_to_command( list_to_convert, data["fps"], label=align ) cmd = "sendcmd=f='{}'".format(path) From a178ca1569a43c1becfba3db0209ba3f982d4959 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 27 Mar 2023 17:35:45 +0800 Subject: [PATCH 692/898] remove duplicated imported function --- openpype/hosts/max/api/menu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/api/menu.py b/openpype/hosts/max/api/menu.py index b52acc3c38a..066cc900394 100644 --- a/openpype/hosts/max/api/menu.py +++ b/openpype/hosts/max/api/menu.py @@ -5,7 +5,7 @@ from openpype.tools.utils import host_tools from openpype.hosts.max.api import lib -from openpype.hosts.max.api import lib + class OpenPypeMenu(object): """Object representing OpenPype menu. From 9fbd84b0ee5c620b4992bb104b72033042719f78 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 27 Mar 2023 11:36:48 +0200 Subject: [PATCH 693/898] nuke, dl: returning `suspende_publish` attribute --- .../deadline/plugins/publish/submit_nuke_deadline.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py index cc069cf51a8..fe7db9fbb90 100644 --- a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py @@ -76,6 +76,11 @@ def get_attribute_defs(cls): "use_gpu", default=cls.use_gpu, label="Use GPU" + ), + BoolDef( + "suspend_publish", + default=False, + label="Suspend publish" ) ] @@ -87,6 +92,10 @@ def process(self, instance): instance.data["attributeValues"] = self.get_attr_values_from_data( instance.data) + # add suspend_publish attributeValue to instance data + instance.data["suspend_publish"] = instance.data["attributeValues"][ + "suspend_publish"] + instance.data["toBeRenderedOn"] = "deadline" families = instance.data["families"] From 7f4fe957bc43d6290b63cdc86d4b4844fcd435c4 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 27 Mar 2023 12:02:44 +0200 Subject: [PATCH 694/898] Move `get_oiio_tools_path` import to top of file --- openpype/hosts/maya/plugins/publish/extract_look.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 4e04999e7e7..e0869b73e62 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -17,7 +17,7 @@ import pyblish.api from openpype.lib.vendor_bin_utils import find_executable -from openpype.lib import source_hash, run_subprocess +from openpype.lib import source_hash, run_subprocess, get_oiio_tools_path from openpype.pipeline import legacy_io, publish, KnownPublishError from openpype.hosts.maya.api import lib from openpype.hosts.maya.api.lib import image_info, guess_colorspace @@ -261,7 +261,6 @@ def process(self, TextureResult: The resulting texture information. """ - from openpype.lib import get_oiio_tools_path maketx_path = get_oiio_tools_path("maketx") From 39d68780670c2333c0d39ef083331723b501c28d Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 27 Mar 2023 12:30:31 +0200 Subject: [PATCH 695/898] Support flags without values for extra `maketx` arguments - Add todo for hardcoded maketx arguments - Add sourceHash argument at end to increase readability of the log --- .../maya/plugins/publish/extract_look.py | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index e0869b73e62..41d34a7ead4 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -236,8 +236,16 @@ def apply_settings(self, system_settings, project_settings): ) extra_args = [] for flag, value in extra_args_dict.items(): + if not flag: + self.log.debug("Ignoring empty flag from `maketx_arguments` " + "setting..") + continue + extra_args.append(flag) - extra_args.append(value) + if value.strip(): + # There might be flags without values like --opaque-detect + extra_args.append(value) + self.extra_args = extra_args def process(self, @@ -328,14 +336,6 @@ def process(self, hash_args.extend(self.extra_args) texture_hash = source_hash(source, *hash_args) - # Exclude these additional arguments from the hashing because - # it is the hash itself - args.extend([ - "--sattrib", - "sourceHash", - texture_hash - ]) - # Ensure folder exists destination = os.path.join(staging_dir, "resources", fname + ".tx") if not os.path.exists(os.path.dirname(destination)): @@ -347,9 +347,12 @@ def process(self, maketx_path, "-v", # verbose "-u", # update mode + # --checknan doesn't influence the output file but aborts the + # conversion if it finds any. So we can avoid need + "--checknan", + # todo: --unpremult, --oiio, --filter should be in the file hash # unpremultiply before conversion (recommended when alpha present) "--unpremult", - "--checknan", # use oiio-optimized settings for tile-size, planarconfig, metadata "--oiio", "--filter", "lanczos3", @@ -359,6 +362,15 @@ def process(self, subprocess_args.extend(args) if self.extra_args: subprocess_args.extend(self.extra_args) + + # Add source hash attribute after other arguments for log readability + # Note: argument is excluding from the hash since it is the hash itself + subprocess_args.extend([ + "--sattrib", + "sourceHash", + texture_hash + ]) + subprocess_args.extend(["-o", destination]) self.log.debug(" ".join(subprocess_args)) From db27765637f0213cab4d4d2b8a89d2fb2f147ecd Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 27 Mar 2023 12:31:01 +0200 Subject: [PATCH 696/898] Grammar --- openpype/hosts/maya/plugins/publish/extract_look.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 41d34a7ead4..f3d0790e225 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -364,7 +364,7 @@ def process(self, subprocess_args.extend(self.extra_args) # Add source hash attribute after other arguments for log readability - # Note: argument is excluding from the hash since it is the hash itself + # Note: argument is excluded from the hash since it is the hash itself subprocess_args.extend([ "--sattrib", "sourceHash", From 7dfaa5b4f4cbf4b8e821d0b4af2e78bc5d7bee97 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 27 Mar 2023 12:36:59 +0200 Subject: [PATCH 697/898] Add maketx hardcoded flags to the file hash --- .../hosts/maya/plugins/publish/extract_look.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index f3d0790e225..be3de13b37f 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -288,7 +288,15 @@ def process(self, transfer_mode=COPY ) - args = [] + # Hardcoded default arguments for maketx conversion based on Arnold's + # txManager in Maya + args = [ + # unpremultiply before conversion (recommended when alpha present) + "--unpremult", + # use oiio-optimized settings for tile-size, planarconfig, metadata + "--oiio", + "--filter", "lanczos3", + ] if color_management["enabled"]: config_path = color_management["config"] if not os.path.exists(config_path): @@ -348,14 +356,8 @@ def process(self, "-v", # verbose "-u", # update mode # --checknan doesn't influence the output file but aborts the - # conversion if it finds any. So we can avoid need + # conversion if it finds any. So we can avoid it for the file hash "--checknan", - # todo: --unpremult, --oiio, --filter should be in the file hash - # unpremultiply before conversion (recommended when alpha present) - "--unpremult", - # use oiio-optimized settings for tile-size, planarconfig, metadata - "--oiio", - "--filter", "lanczos3", source ] From b9d1d560a78950142a145588ea46ed54d03415dd Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Mon, 27 Mar 2023 12:59:53 +0200 Subject: [PATCH 698/898] :bug: pass zoom settings if review is attached --- openpype/hosts/maya/plugins/publish/collect_review.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/maya/plugins/publish/collect_review.py b/openpype/hosts/maya/plugins/publish/collect_review.py index 548b1c996aa..5d5ec294b14 100644 --- a/openpype/hosts/maya/plugins/publish/collect_review.py +++ b/openpype/hosts/maya/plugins/publish/collect_review.py @@ -79,6 +79,7 @@ def process(self, instance): data['review_width'] = instance.data['review_width'] data['review_height'] = instance.data['review_height'] data["isolate"] = instance.data["isolate"] + data["panZoom"] = instance.data.get("panZoom", False) cmds.setAttr(str(instance) + '.active', 1) self.log.debug('data {}'.format(instance.context[i].data)) instance.context[i].data.update(data) From 5b4b0e601b0f2a4adefc56ba2251a487e4818253 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Mon, 27 Mar 2023 13:12:36 +0200 Subject: [PATCH 699/898] :bug: pass panel too --- openpype/hosts/maya/plugins/publish/collect_review.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/maya/plugins/publish/collect_review.py b/openpype/hosts/maya/plugins/publish/collect_review.py index 5d5ec294b14..71c65cc47e9 100644 --- a/openpype/hosts/maya/plugins/publish/collect_review.py +++ b/openpype/hosts/maya/plugins/publish/collect_review.py @@ -80,6 +80,7 @@ def process(self, instance): data['review_height'] = instance.data['review_height'] data["isolate"] = instance.data["isolate"] data["panZoom"] = instance.data.get("panZoom", False) + data["panel"] =instance.data["panel"] cmds.setAttr(str(instance) + '.active', 1) self.log.debug('data {}'.format(instance.context[i].data)) instance.context[i].data.update(data) From 5805e7d90041938da22eb63844679db433415d62 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Mon, 27 Mar 2023 13:13:09 +0200 Subject: [PATCH 700/898] :rotating_light: add space --- openpype/hosts/maya/plugins/publish/collect_review.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_review.py b/openpype/hosts/maya/plugins/publish/collect_review.py index 71c65cc47e9..36affe852b1 100644 --- a/openpype/hosts/maya/plugins/publish/collect_review.py +++ b/openpype/hosts/maya/plugins/publish/collect_review.py @@ -80,7 +80,7 @@ def process(self, instance): data['review_height'] = instance.data['review_height'] data["isolate"] = instance.data["isolate"] data["panZoom"] = instance.data.get("panZoom", False) - data["panel"] =instance.data["panel"] + data["panel"] = instance.data["panel"] cmds.setAttr(str(instance) + '.active', 1) self.log.debug('data {}'.format(instance.context[i].data)) instance.context[i].data.update(data) From 3444660a982b13cf798b575e9ebecf8f85f49f05 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 27 Mar 2023 13:20:26 +0200 Subject: [PATCH 701/898] Convert to "linear" because it's always available in OIIO if OCIO is disabled or no valid config is found - If OCIO is not enabled (or cannot find a valid configuration, OIIO will at least be able to convert among linear, sRGB, and Rec709.) --- openpype/hosts/maya/plugins/publish/extract_look.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index be3de13b37f..5b9b0777a03 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -316,19 +316,15 @@ def process(self, # managed mode because the collected color space is the color space # attribute of the file node which can be any string whatsoever # but only appears disabled in Attribute Editor. We assume we're - # always converting to linear/Raw if the source file is assumed to + # always converting to linear if the source file is assumed to # be sRGB. - # TODO Without color management do we even know we can do - # "colorconvert" and what config does that end up using since - # colorconvert is a OCIO command line flag for maketx. - # Also, Raw != linear? render_colorspace = "linear" if self._has_arnold(): img_info = image_info(source) color_space = guess_colorspace(img_info) if color_space.lower() == "sRGB": self.log.info("tx: converting sRGB -> linear") - args.extend(["--colorconvert", "sRGB", "Raw"]) + args.extend(["--colorconvert", "sRGB", render_colorspace]) else: self.log.info("tx: texture's colorspace " "is already linear") From 6f015d6d64278b696f861b0b85284ed9e4ca9417 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 27 Mar 2023 13:31:33 +0200 Subject: [PATCH 702/898] Cleanup/refactor based on @fabiaserra comments --- .../maya/plugins/publish/extract_look.py | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 5b9b0777a03..daf6735660c 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -91,6 +91,9 @@ def no_workspace_dir(): @six.add_metaclass(ABCMeta) class TextureProcessor: + + extension = None + def __init__(self, log=None): if log is None: log = logging.getLogger(self.__class__.__name__) @@ -136,10 +139,6 @@ def process(self, """ pass - @staticmethod - def get_extension(): - pass - def __repr__(self): # Log instance as class name return self.__class__.__name__ @@ -148,6 +147,8 @@ def __repr__(self): class MakeRSTexBin(TextureProcessor): """Make `.rstexbin` using `redshiftTextureProcessor`""" + extension = ".rstexbin" + def process(self, source, colorspace, @@ -171,7 +172,7 @@ def process(self, # Redshift stores the output texture next to the input but with # the extension replaced to `.rstexbin` basename, ext = os.path.splitext(source) - destination = "{}{}".format(basename, self.get_extension()) + destination = "{}{}".format(basename, self.extension) self.log.debug(" ".join(subprocess_args)) try: @@ -188,10 +189,6 @@ def process(self, transfer_mode=COPY ) - @staticmethod - def get_extension(): - return ".rstexbin" - @staticmethod def get_redshift_tool(tool_name): """Path to redshift texture processor. @@ -224,6 +221,8 @@ class MakeTX(TextureProcessor): """ + extension = ".tx" + def __init__(self, log=None): super(MakeTX, self).__init__(log=log) self.extra_args = [] @@ -335,15 +334,13 @@ def process(self, # Note: The texture hash is only reliable if we include any potential # conversion arguments provide to e.g. `maketx` - hash_args = ["maketx"] - hash_args.extend(args) - hash_args.extend(self.extra_args) + hash_args = ["maketx"] + args + self.extra_args texture_hash = source_hash(source, *hash_args) # Ensure folder exists - destination = os.path.join(staging_dir, "resources", fname + ".tx") - if not os.path.exists(os.path.dirname(destination)): - os.makedirs(os.path.dirname(destination)) + resources_dir = os.path.join(staging_dir, "resources") + if not os.path.exists(resources_dir): + os.makedirs(resources_dir) self.log.info("Generating .tx file for %s .." % source) @@ -369,6 +366,7 @@ def process(self, texture_hash ]) + destination = os.path.join(resources_dir, fname + ".tx") subprocess_args.extend(["-o", destination]) self.log.debug(" ".join(subprocess_args)) @@ -386,10 +384,6 @@ def process(self, transfer_mode=COPY ) - @staticmethod - def get_extension(): - return ".tx" - @staticmethod def _has_arnold(): """Return whether the arnold package is available and importable.""" @@ -748,7 +742,7 @@ def get_resource_destination(self, filepath, resources_dir, processors): # Get extension from the last processor for processor in reversed(processors): - processor_ext = processor.get_extension() + processor_ext = processor.extension if processor_ext and ext != processor_ext: self.log.debug("Processor {} overrides extension to '{}' " "for path: {}".format(processor, @@ -785,9 +779,12 @@ def _process_texture(self, color_management, colorspace): """Process a single texture file on disk for publishing. + This will: 1. Check whether it's already published, if so it will do hardlink - 2. If not published and maketx is enabled, generate a new .tx file. + (if the texture hash is found and force copy is not enabled) + 2. It will process the texture using the supplied texture + processors like MakeTX and MakeRSTexBin if enabled. 3. Compute the destination path for the source file. Args: From e11d1f279ac03da71158075b1793b7b673303cab Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 27 Mar 2023 13:46:33 +0200 Subject: [PATCH 703/898] Add assumption for some file formats to be sRGB: `.png`, `.jpeg` and `.jpg` --- .../maya/plugins/publish/extract_look.py | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index daf6735660c..9c360c8dd4e 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -26,6 +26,10 @@ COPY = 1 HARDLINK = 2 +# File formats we will assume are sRGB when Maya Color Management is disabled +# Currently only used for `maketx` color conversion logic +NONLINEAR_FILE_FORMATS = {".png", ".jpeg", ".jpg"} + @attr.s class TextureResult: @@ -311,6 +315,7 @@ def process(self, args.extend(["--colorconfig", config_path]) else: + self.log.debug("Maya color management is disabled..") # We can't rely on the colorspace attribute when not in color # managed mode because the collected color space is the color space # attribute of the file node which can be any string whatsoever @@ -318,19 +323,28 @@ def process(self, # always converting to linear if the source file is assumed to # be sRGB. render_colorspace = "linear" - if self._has_arnold(): + assumed_input_colorspace = "linear" + if ext.lower() in NONLINEAR_FILE_FORMATS: + assumed_input_colorspace = "sRGB" + elif self._has_arnold(): + # Assume colorspace based on input image bit-depth img_info = image_info(source) - color_space = guess_colorspace(img_info) - if color_space.lower() == "sRGB": - self.log.info("tx: converting sRGB -> linear") - args.extend(["--colorconvert", "sRGB", render_colorspace]) - else: - self.log.info("tx: texture's colorspace " - "is already linear") + assumed_input_colorspace = guess_colorspace(img_info) + else: + self.log.warning("tx: cannot guess the colorspace, a linear " + "colorspace will be assumed for file: " + "{}".format(source)) + + if assumed_input_colorspace == "sRGB": + self.log.info("tx: converting sRGB -> linear") + args.extend(["--colorconvert", "sRGB", render_colorspace]) + elif assumed_input_colorspace == "linear": + self.log.info("tx: texture's colorspace " + "is already linear") else: - self.log.warning("tx: cannot guess the colorspace, " - "color conversion won't be " - "available!") + self.log.warning("Unexpected texture color space: {} " + "(expected either 'linear' or 'sRGB')" + "".format(assumed_input_colorspace)) # Note: The texture hash is only reliable if we include any potential # conversion arguments provide to e.g. `maketx` From bf60e7370453831d4ee3f89a32fd435091450ef3 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 27 Mar 2023 13:47:26 +0200 Subject: [PATCH 704/898] Remove `.png` from nonlinear formats assumption because apparently they can be 32-bit --- openpype/hosts/maya/plugins/publish/extract_look.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 9c360c8dd4e..c68ce56fccf 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -28,7 +28,7 @@ # File formats we will assume are sRGB when Maya Color Management is disabled # Currently only used for `maketx` color conversion logic -NONLINEAR_FILE_FORMATS = {".png", ".jpeg", ".jpg"} +NONLINEAR_FILE_FORMATS = {".jpeg", ".jpg"} @attr.s From 5ed6c29eee6531eaa5dde107a98a777ce091f232 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 27 Mar 2023 15:23:14 +0200 Subject: [PATCH 705/898] Mimic Arnold tx manager behavior whenever maya color management is disabled - Do no color conversion when color management is disabled --- .../maya/plugins/publish/extract_look.py | 42 +++++-------------- 1 file changed, 11 insertions(+), 31 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index c68ce56fccf..7405eb1a9f5 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -315,36 +315,10 @@ def process(self, args.extend(["--colorconfig", config_path]) else: - self.log.debug("Maya color management is disabled..") - # We can't rely on the colorspace attribute when not in color - # managed mode because the collected color space is the color space - # attribute of the file node which can be any string whatsoever - # but only appears disabled in Attribute Editor. We assume we're - # always converting to linear if the source file is assumed to - # be sRGB. - render_colorspace = "linear" - assumed_input_colorspace = "linear" - if ext.lower() in NONLINEAR_FILE_FORMATS: - assumed_input_colorspace = "sRGB" - elif self._has_arnold(): - # Assume colorspace based on input image bit-depth - img_info = image_info(source) - assumed_input_colorspace = guess_colorspace(img_info) - else: - self.log.warning("tx: cannot guess the colorspace, a linear " - "colorspace will be assumed for file: " - "{}".format(source)) - - if assumed_input_colorspace == "sRGB": - self.log.info("tx: converting sRGB -> linear") - args.extend(["--colorconvert", "sRGB", render_colorspace]) - elif assumed_input_colorspace == "linear": - self.log.info("tx: texture's colorspace " - "is already linear") - else: - self.log.warning("Unexpected texture color space: {} " - "(expected either 'linear' or 'sRGB')" - "".format(assumed_input_colorspace)) + # Maya Color management is disabled. We cannot rely on an OCIO + self.log.debug("tx: Maya color management is disabled. No color " + "conversion will be applied to .tx conversion for: " + "{}".format(source)) # Note: The texture hash is only reliable if we include any potential # conversion arguments provide to e.g. `maketx` @@ -383,9 +357,15 @@ def process(self, destination = os.path.join(resources_dir, fname + ".tx") subprocess_args.extend(["-o", destination]) + # We want to make sure we are explicit about what OCIO config gets + # used. So when we supply no --colorconfig flag that no fallback to + # an OCIO env var occurs. + env = os.environ.copy() + env.pop("OCIO", None) + self.log.debug(" ".join(subprocess_args)) try: - run_subprocess(subprocess_args) + run_subprocess(subprocess_args, env=env) except Exception: self.log.error("Texture maketx conversion failed", exc_info=True) From 2cb03b75b74ee145dba5f28b90f09861fe7b350a Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 27 Mar 2023 15:35:03 +0200 Subject: [PATCH 706/898] Clean up imports a bit. --- .../hosts/maya/plugins/publish/extract_look.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 7405eb1a9f5..e9399924540 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -1,26 +1,24 @@ # -*- coding: utf-8 -*- """Maya look extractor.""" -import logging from abc import ABCMeta, abstractmethod - -import six -import os +from collections import OrderedDict +import contextlib import json -import tempfile +import logging +import os import platform -import contextlib -from collections import OrderedDict +import tempfile +import six import attr -from maya import cmds # noqa - import pyblish.api +from maya import cmds # noqa + from openpype.lib.vendor_bin_utils import find_executable from openpype.lib import source_hash, run_subprocess, get_oiio_tools_path from openpype.pipeline import legacy_io, publish, KnownPublishError from openpype.hosts.maya.api import lib -from openpype.hosts.maya.api.lib import image_info, guess_colorspace # Modes for transfer COPY = 1 From 108bcd8f27acd3d6b632c9df969357f1cee9773b Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 27 Mar 2023 15:37:27 +0200 Subject: [PATCH 707/898] Fix missing variable declaration --- openpype/hosts/maya/plugins/publish/extract_look.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index e9399924540..9599f9f8099 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -317,6 +317,8 @@ def process(self, self.log.debug("tx: Maya color management is disabled. No color " "conversion will be applied to .tx conversion for: " "{}".format(source)) + # Assume linear + render_colorspace = "linear" # Note: The texture hash is only reliable if we include any potential # conversion arguments provide to e.g. `maketx` From 22dbc4e4fa5227db80fda932f4b9b10a76ba64bd Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 27 Mar 2023 15:40:33 +0200 Subject: [PATCH 708/898] Remove unused variable `NONLINEAR_FILE_FORMATS` --- openpype/hosts/maya/plugins/publish/extract_look.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 9599f9f8099..1e339542d78 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -24,10 +24,6 @@ COPY = 1 HARDLINK = 2 -# File formats we will assume are sRGB when Maya Color Management is disabled -# Currently only used for `maketx` color conversion logic -NONLINEAR_FILE_FORMATS = {".jpeg", ".jpg"} - @attr.s class TextureResult: From 2244a634b25a4191349db3d994c909359bed9c86 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 27 Mar 2023 16:06:52 +0200 Subject: [PATCH 709/898] change minimum frame start/end to '0' (#4719) --- openpype/tools/project_manager/project_manager/view.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/tools/project_manager/project_manager/view.py b/openpype/tools/project_manager/project_manager/view.py index b35491c5b21..2cf11b702d8 100644 --- a/openpype/tools/project_manager/project_manager/view.py +++ b/openpype/tools/project_manager/project_manager/view.py @@ -72,8 +72,8 @@ class HierarchyView(QtWidgets.QTreeView): column_delegate_defs = { "name": NameDef(), "type": TypeDef(), - "frameStart": NumberDef(1), - "frameEnd": NumberDef(1), + "frameStart": NumberDef(0), + "frameEnd": NumberDef(0), "fps": NumberDef(1, decimals=3, step=1), "resolutionWidth": NumberDef(0), "resolutionHeight": NumberDef(0), From be3251d007c2dd151078af62527889d2cb89d851 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 27 Mar 2023 16:32:34 +0200 Subject: [PATCH 710/898] Cleanup Collect Review code --- .../maya/plugins/publish/collect_review.py | 112 ++++++++++-------- 1 file changed, 61 insertions(+), 51 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_review.py b/openpype/hosts/maya/plugins/publish/collect_review.py index 36affe852b1..713bda25ba8 100644 --- a/openpype/hosts/maya/plugins/publish/collect_review.py +++ b/openpype/hosts/maya/plugins/publish/collect_review.py @@ -4,7 +4,7 @@ import pyblish.api from openpype.client import get_subset_by_name -from openpype.pipeline import legacy_io +from openpype.pipeline import legacy_io, KnownPublishError class CollectReview(pyblish.api.InstancePlugin): @@ -15,7 +15,6 @@ class CollectReview(pyblish.api.InstancePlugin): order = pyblish.api.CollectorOrder + 0.3 label = 'Collect Review Data' families = ["review"] - legacy = True def process(self, instance): @@ -35,57 +34,68 @@ def process(self, instance): self.log.debug('members: {}'.format(members)) # validate required settings - assert len(cameras) == 1, "Not a single camera found in extraction" + if len(cameras) == 0: + raise KnownPublishError("Not camera found in review " + "instance: {}".format(instance)) + elif len(cameras) > 2: + raise KnownPublishError( + "Only a single camera is allowed for a review instance but " + "more than one camera found in review instance: {}. " + "Cameras found: {}".format(instance, ", ".join(cameras))) + camera = cameras[0] self.log.debug('camera: {}'.format(camera)) - objectset = instance.context.data['objectsets'] - - reviewable_subset = None - reviewable_subset = list(set(members) & set(objectset)) - if reviewable_subset: - assert len(reviewable_subset) <= 1, "Multiple subsets for review" - self.log.debug('subset for review: {}'.format(reviewable_subset)) - - i = 0 - for inst in instance.context: - - self.log.debug('filtering {}'.format(inst)) - data = instance.context[i].data - - if inst.name != reviewable_subset[0]: - self.log.debug('subset name does not match {}'.format( - reviewable_subset[0])) - i += 1 - continue - - if data.get('families'): - data['families'].append('review') - else: - data['families'] = ['review'] - self.log.debug('adding review family to {}'.format( - reviewable_subset)) - data['review_camera'] = camera - # data["publish"] = False - data['frameStartFtrack'] = instance.data["frameStartHandle"] - data['frameEndFtrack'] = instance.data["frameEndHandle"] - data['frameStartHandle'] = instance.data["frameStartHandle"] - data['frameEndHandle'] = instance.data["frameEndHandle"] - data["frameStart"] = instance.data["frameStart"] - data["frameEnd"] = instance.data["frameEnd"] - data['handles'] = instance.data.get('handles', None) - data['step'] = instance.data['step'] - data['fps'] = instance.data['fps'] - data['review_width'] = instance.data['review_width'] - data['review_height'] = instance.data['review_height'] - data["isolate"] = instance.data["isolate"] - data["panZoom"] = instance.data.get("panZoom", False) - data["panel"] = instance.data["panel"] - cmds.setAttr(str(instance) + '.active', 1) - self.log.debug('data {}'.format(instance.context[i].data)) - instance.context[i].data.update(data) - instance.data['remove'] = True - self.log.debug('isntance data {}'.format(instance.data)) + context = instance.context + objectset = context.data['objectsets'] + + reviewable_subsets = list(set(members) & set(objectset)) + if reviewable_subsets: + if len(reviewable_subsets) > 1: + raise KnownPublishError( + "Multiple attached subsets for review are not supported. " + "Attached: {}".format(", ".join(reviewable_subsets)) + ) + + reviewable_subset = reviewable_subsets[0] + self.log.debug( + "Subset attached to review: {}".format(reviewable_subset) + ) + + # Find the relevant publishing instance in the current context + reviewable_inst = next(inst for inst in context + if inst.name == reviewable_subset) + data = reviewable_inst.data + + self.log.debug( + 'Adding review family to {}'.format(reviewable_subset) + ) + if data.get('families'): + data['families'].append('review') + else: + data['families'] = ['review'] + + data['review_camera'] = camera + data['frameStartFtrack'] = instance.data["frameStartHandle"] + data['frameEndFtrack'] = instance.data["frameEndHandle"] + data['frameStartHandle'] = instance.data["frameStartHandle"] + data['frameEndHandle'] = instance.data["frameEndHandle"] + data["frameStart"] = instance.data["frameStart"] + data["frameEnd"] = instance.data["frameEnd"] + data['handles'] = instance.data.get('handles', None) + data['step'] = instance.data['step'] + data['fps'] = instance.data['fps'] + data['review_width'] = instance.data['review_width'] + data['review_height'] = instance.data['review_height'] + data["isolate"] = instance.data["isolate"] + data["panZoom"] = instance.data.get("panZoom", False) + data["panel"] = instance.data["panel"] + + # The review instance must be active + cmds.setAttr(str(instance) + '.active', 1) + + instance.data['remove'] = True + else: legacy_subset_name = task + 'Review' asset_doc = instance.context.data['assetEntity'] @@ -107,7 +117,7 @@ def process(self, instance): instance.data["frameEndHandle"] # make ftrack publishable - instance.data["families"] = ['ftrack'] + instance.data.setdefault("families", []).append(['ftrack']) cmds.setAttr(str(instance) + '.active', 1) From 63851a6bd00fb1b52d255e5c7295cfc5c6c51b50 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 27 Mar 2023 16:36:54 +0200 Subject: [PATCH 711/898] Fix typo --- openpype/hosts/maya/plugins/publish/collect_review.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_review.py b/openpype/hosts/maya/plugins/publish/collect_review.py index 713bda25ba8..47071631a2c 100644 --- a/openpype/hosts/maya/plugins/publish/collect_review.py +++ b/openpype/hosts/maya/plugins/publish/collect_review.py @@ -117,7 +117,7 @@ def process(self, instance): instance.data["frameEndHandle"] # make ftrack publishable - instance.data.setdefault("families", []).append(['ftrack']) + instance.data.setdefault("families", []).append('ftrack') cmds.setAttr(str(instance) + '.active', 1) From 0778dd3ec763aa2257f235b310041aed18902b30 Mon Sep 17 00:00:00 2001 From: Ynbot Date: Mon, 27 Mar 2023 15:28:21 +0000 Subject: [PATCH 712/898] [Automated] Release --- CHANGELOG.md | 668 ++++++++++++++++++++++++++++++++++++++++++++ openpype/version.py | 2 +- pyproject.toml | 2 +- 3 files changed, 670 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 145c2e2c1ac..78ea53f3d0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,674 @@ # Changelog +[Full Changelog](https://github.com/ynput/OpenPype/compare/3.15.2...3.15.3) + +### **🆕 New features** + + +

    +Data Exchanges: Point Cloud for 3dsMax #4532 + +Publish PRT format with tyFlow in 3dsmax + +Publish PRT format with tyFlow in 3dsmax and possibly set up loader to load the format too. +- [x] creator +- [x] extractor +- [x] validator +- [x] loader + + +___ + +
    + + +
    +MaxScene Family #4615 + +Introduction of the Max Scene Family + + +___ + +
    + + +
    +Blender: Extract Review #3616 + +Added Review to Blender. + +This implementation is based on #3508 but made compatible for the current implementation of OpenPype for Blender. + + +___ + +
    + + +
    +Global: persistent staging directory for renders #4583 + +Allows configure if staging directory (`stagingDir`) should be persistent with use of profiles. + +With this feature, users can specify a transient data folder path based on presets, which can be used during the creation and publishing stages. In some cases, these DCCs automatically add a rendering path during the creation stage, which is then used in publishing.One of the key advantages of this feature is that it allows users to take advantage of faster storages for rendering, which can help improve workflow efficiency. Additionally, this feature allows users to keep their rendered data persistent, and use their own infrastructure for regular cleaning.However, it should be noted that some productions may want to use this feature without persistency. Furthermore, there may be a need for retargeting the rendering folder to faster storages, which is also not supported at the moment.It is studio responsibility to clean up obsolete folders with data.Location of the folder is configured in `project_anatomy/templates/others`. ('transient' key is expected, with 'folder' key, could be more templates)Which family/task type/subset is applicable is configured in:`project_settings/global/tools/publish/transient_dir_profiles` + + +___ + +
    + +### **🚀 Enhancements** + + +
    +Maya: Multiple values on single render attribute - OP-4131 #4631 + +When validating render attributes, this adds support for multiple values. When repairing first value in list is used. + + +___ + +
    + + +
    +Maya: enable 2D Pan/Zoom for playblasts - OP-5213 #4687 + +Setting for enabling 2D Pan/Zoom on reviews. + + +___ + +
    + + +
    +Houdini: Create button open new publisher's "create" tab #4601 + +During a talk with @maxpareschi he mentioned that the new publisher in Houdini felt super confusing due to "Create" going to the older creator but now being completely empty and the publish button directly went to the publish tab.This resolves that by fixing the Create button to now open the new publisher but on the Create tab.Also made publish button enforce going to the "publish" tab for consistency in usage.@antirotor I think changing the Create button's callback was just missed in this commit or was there a specific reason to not change that around yet? + + +___ + +
    + + +
    +Resolution settings referenced from DB record for 3dsMax #4652 + +- Add Callback for setting the resolution according to DB after the new scene is created. +- Add a new Action into openpype menu which allows the user to reset the resolution in 3dsMax + + +___ + +
    + + +
    +scene length setting referenced from DB record for 3dsMax #4665 + +Setting the timeline length based on DB record in 3dsMax Hosts + + +___ + +
    + + +
    +increment workfile version 3dsmax #4685 + +increment workfile version in 3dsmax as if in blender and maya hosts. + + +___ + +
    + + +
    +Copy existing or generate new Fusion profile on prelaunch #4572 + +Fusion preferences will be copied to the predefined `~/.openpype/hosts/fusion/prefs` folder (or any other folder set in system settings) on launch. + +The idea is to create a copy of existing Fusion profile, adding an OpenPype menu to the Fusion instance.By default the copy setting is turned off, so no file copying is performed. Instead the clean Fusion profile is created by Fusion in the predefined folder. The default locaion is set to `~/.openpype/hosts/fusion/prefs`, to better comply with the other os platforms. After creating the default profile, some modifications are applied: +- forced Python3 +- forced English interface +- setup Openpype specific path maps.If the `copy_prefs` checkbox is toggled, a copy of existing Fusion profile folder will be placed in the mentioned location. Then they are altered the same way as described above. The operation is run only once, on the first launch, unless the `force_sync [Resync profile on each launch]` is toggled.English interface is forced because the `FUSION16_PROFILE_DIR` environment variable is not read otherwise (seems to be a Fusion bug). + + +___ + +
    + + +
    +Fusion publish existing frames #4611 + +This PR adds the function to publish existing frames instead of having to re-render all of them for each new publish.I have split the render_locally plugin so the review-part is its own plugin now.I also change the saver-creator-plugin's label from Saver to Render (saver) as I intend to add a Prerender creator like in Nuke. + + +___ + +
    + + +
    +Clockify: refresh and fix the integration #4607 + +Due to recent API changes, Clockify requires `user_id` to operate with the timers. I updated this part and currently it is a WIP for making it fully functional. Most functions, such as start and stop timer, and projects sync are currently working. For the rate limiting task new dependency is added: https://pypi.org/project/ratelimiter/ + + +___ + +
    + + +
    +Publisher: Windows reduce command window pop-ups during Publishing #4672 + +Reduce the command line pop-ups that show on Windows during publishing. + + +___ + +
    + + +
    +CelAction: conditional workfile parameters from settings #4677 + +Since some productions were requesting excluding some workfile parameters from publishing submission, we needed to move them to settings so those could be altered per project. + + +___ + +
    + + +
    +Fix name and docstring for Create Workdir Extra Folders prelaunch hook #4683 + +Fix class name and docstring for Create Workdir Extra Folders prelaunch hookThe class name and docstring were originally copied from another plug-in and didn't match the plug-in logic.This also fixes potentially seeing this twice in your logs. Before:After:Where it was actually running both this prelaunch hook and the actual `AddLastWorkfileToLaunchArgs` plugin. + + +___ + +
    + +### **🐛 Bug fixes** + + +
    +Maya: Fix getting non-active model panel. #2968 + +When capturing multiple cameras with image planes that have file sequences playing, only the active (first) camera will play through the file sequence. + + +___ + +
    + + +
    +Maya: Fix broken review publishing. #4549 + +Resolves #4547 + + +___ + +
    + + +
    +Maya: Avoid error on right click in Loader if `mtoa` is not loaded #4616 + +Fix an error on right clicking in the Loader when `mtoa` is not a loaded plug-in.Additionally if `mtoa` isn't loaded the loader will now load the plug-in before trying to create the arnold standin. + + +___ + +
    + + +
    +Maya: Fix extract look colorspace detection #4618 + +Fix the logic which guesses the colorspace using `arnold` python library. +- Previously it'd error if `mtoa` was not available on path so it still required `mtoa` to be available. +- The guessing colorspace logic doesn't actually require `mtoa` to be loaded, but just the `arnold` python library to be available. This changes the logic so it doesn't require the `mtoa` plugin to get loaded to guess the colorspace. +- The if/else branch was likely not doing what was intended `cmds.loadPlugin("mtoa", quiet=True)` returns None if the plug-in was already loaded. So this would only ever be true if it ends up loading the `mtoa` plugin the first time. +```python +# Tested in Maya 2022.1 +print(cmds.loadPlugin("mtoa", quiet=True)) +# ['mtoa'] +print(cmds.loadPlugin("mtoa", quiet=True)) +# None +``` + + +___ + +
    + + +
    +Maya: Maya Playblast Options overrides - OP-3847 #4634 + +When publishing a review in Maya, the extractor would fail due to wrong (long) panel name. + + +___ + +
    + + +
    +Bugfix/op 2834 fix extract playblast #4701 + +Paragraphs contain detailed information on the changes made to the product or service, providing an in-depth description of the updates and enhancements. They can be used to explain the reasoning behind the changes, or to highlight the importance of the new features. Paragraphs can often include links to further information or support documentation. + + +___ + +
    + + +
    +Bugfix/op 2834 fix extract playblast #4704 + +Paragraphs contain detailed information on the changes made to the product or service, providing an in-depth description of the updates and enhancements. They can be used to explain the reasoning behind the changes, or to highlight the importance of the new features. Paragraphs can often include links to further information or support documentation. + + +___ + +
    + + +
    +Maya: bug fix for passing zoom settings if review is attached to subset #4716 + +Fix for attaching review to subset with pan/zoom option. + + +___ + +
    + + +
    +Fixed a bug where a QThread in the splash screen could be destroyed before finishing execution #4647 + +This should fix the occasional behavior of the QThread being destroyed before even its worker returns from the `run()` function.After quiting, it should wait for the QThread object to properly close itself. + + +___ + +
    + + +
    +Max: fix the bug of removing an instance #4617 + +fix the bug of removing an instance in 3dsMax + + +___ + +
    + + +
    +bugfix for 3dsmax publishing error #4637 + +fix the bug of failing publishing job in 3dsMax + + +___ + +
    + + +
    +3dsmax: opening last workfile #4644 + +Supports opening last saved workfile in 3dsmax host. + + +___ + +
    + + +
    +Global | Nuke: fixing farm publishing workflow #4623 + +After Nuke had adopted new publisher with new creators new issues were introduced. Those issues were addressed with this PR. Those are for example broken reviewable video files publishing if published via farm. Also fixed local publishing. + + +___ + +
    + + +
    +Nuke: Nukenodes family instance without frame range #4669 + +No need to add frame range data into `nukenodes` (backdrop) family publishes - since those are timeless. + + +___ + +
    + + +
    +TVPaint: Optional Validation plugins can be de/activated by user #4674 + +Added `OptionalPyblishPluginMixin` to TVpaint plugins that can be optional. + + +___ + +
    + + +
    +Hiero: Creator with correct workfile numeric padding input #4666 + +Creator was showing 99 in workfile input for long time, even if users set default value to 1001 in studio settings. This has been fixed now. + + +___ + +
    + + +
    +Hiero: correct container colors if UpToDate #4708 + +Colors on loaded containers are now correctly identifying real state of version. `Red` for out of date and `green` for up to date. + + +___ + +
    + + +
    +Maya: tile assembly fail in draft - OP-4820 #4416 + +Tile assembly in Deadline was broken. + +Initial bug report revealed other areas of the tile assembly that needed fixing. + + +___ + +
    + + +
    +Scene inventory: Fix code errors when "not found" entries are found #4594 + +Whenever a "NOT FOUND" entry is present a lot of errors happened in the Scene Inventory: +- It started spamming a lot of errors for the VersionDelegate since it had no numeric version (no version at all).Error reported on Discord: +```python +Traceback (most recent call last): + File "C:\Users\videopro\Documents\github\OpenPype\openpype\tools\utils\delegates.py", line 65, in paint + text = self.displayText( + File "C:\Users\videopro\Documents\github\OpenPype\openpype\tools\utils\delegates.py", line 33, in displayText + assert isinstance(value, numbers.Integral), ( +AssertionError: Version is not integer. "None" +``` +- Right click menu would error on NOT FOUND entries, and thus not show. With this PR it will now _disregard_ not found items for "Set version" and "Remove" but still allow actions.This PR resolves those. + + +___ + +
    + + +
    +Ftrack: Ftrack additional families filtering #4633 + +Ftrack family collector makes sure the subset family is also in instance families for additional families filtering. + + +___ + +
    + + +
    +General: Use right validation for ffmpeg executable #4640 + +Use ffmpeg exec validation for ffmpeg executables instead of oiio exec validation. The validation is used as last possible source of ffmpeg from `PATH` environment variables, which is an edge case but can cause issues. + + +___ + +
    + + +
    +Global: add tags field to thumbnail representation #4660 + +Thumbnail representation might be missing tags field. + + +___ + +
    + + +
    +Kitsu: Slightly less strict with instance data #4678 + +- Allow to take task name from context if asset doesn't have any. Fixes an issue with Photoshop's review instance not having `task` in data. +- Allow to match "review" against both `instance.data["family"]` and `instance.data["families"]` because some instances don't have the primary family in families, e.g. in Photoshop and TVPaint. +- Do not error on Integrate Kitsu Review whenever for whatever reason Integrate Kitsu Note did not created a comment but just log the message that it was unable to connect a review. + + +___ + +
    + + +
    +Refactor _capture #4702 + +Paragraphs contain detailed information on the changes made to the product or service, providing an in-depth description of the updates and enhancements. They can be used to explain the reasoning behind the changes, or to highlight the importance of the new features. Paragraphs can often include links to further information or support documentation. + + +___ + +
    + +### **🔀 Refactored code** + + +
    +Look Assigner: Move Look Assigner tool since it's Maya only #4604 + +Fix #4357: Move Look Assigner tool to maya since it's Maya only + + +___ + +
    + + +
    +Maya: Remove unused functions from Extract Look #4671 + +Remove unused functions from Maya Extract Look plug-in + + +___ + +
    + + +
    +Extract Review code refactor #3930 + +Trying to reduce complexity of Extract Review plug-in +- Re-use profile filtering from lib +- Remove "combination families" additional filtering which supposedly was from OP v2 +- Simplify 'formatting' for filling gaps +- Use `legacy_io.Session` over `os.environ` + + +___ + +
    + + +
    +Update tests and documentation for `ColormanagedPyblishPluginMixin` #4612 + +Refactor `ExtractorColormanaged` to `ColormanagedPyblishPluginMixin` in tests and documentation. + + +___ + +
    + +### **📃 Documentation** + + +
    +Docs/add architecture document #4344 + +Add `ARCHITECTURE.md` document. + +his document attemps to give a quick overview of the project to help onboarding, it's not an extensive documentation but more of a elevator pitch one-line descriptions of files/directories and what the attempt to do. + + +___ + +
    + + +
    +Docs: Fix some minor grammar/typos #4680 + +Typo/grammar fixes in documentation. + + +___ + +
    + +### **Merged pull requests** + + +
    +Maya: Implement image file node loader #4313 + +Implements a loader for loading texture image into a `file` node in Maya. + +Similar to Maya's hypershade creation of textures on load you have the option to choose for three modes of creating: +- Texture +- Projection +- StencilThese should match what Maya generates if you create those in Maya. +- [x] Load and manage file nodes +- [x] Apply color spaces after #4195 +- [x] Support for _either_ UDIM or image sequence - currently it seems to always load sequences as UDIM automatically. +- [ ] Add support for animation sequences of UDIM textures using the `..exr` path format? + + +___ + +
    + + +
    +Maya Look Assigner: Don't rely on containers for get all assets #4600 + +This resolves #4044 by not actually relying on containers in the scene but instead just rely on finding nodes with `cbId` attributes. As such, imported nodes would also be found and a shader can be assigned (similar to when using get from selection).**Please take into consideration the potential downsides below**Potential downsides would be: +- IF an already loaded look has any dagNodes, say a 3D Projection node - then that will also show up as a loaded asset where previously nodes from loaded looks were ignored. +- If any dag nodes were created locally - they would have gotten `cbId` attributes on scene save and thus the current asset would almost always show? + + +___ + +
    + + +
    +Maya: Unify menu labels for "Set Frame Range" and "Set Resolution" #4605 + +Fix #4109: Unify menu labels for "Set Frame Range" and "Set Resolution"This also tweaks it in Houdini from Reset Frame Range to Set Frame Range. + + +___ + +
    + + +
    +3dsmax: make sure that startup script executes #4695 + +Fixing reliability of OpenPype startup in 3dsmax. + + +___ + +
    + + +
    +Resolve missing OPENPYPE_MONGO in deadline global job preload #4484 + +In the GlobalJobPreLoad plugin, we propose to replace the SpawnProcess by a sub-process and to pass the environment variables in the parameters, since the SpawnProcess under Centos Linux does not pass the environment variables. + +In the GlobalJobPreLoad plugin, the Deadline SpawnProcess is used to start the OpenPype process. The problem is that the SpawnProcess does not pass environment variables, including OPENPYPE_MONGO, to the process when it is under Centos7 linux, and the process gets stuck. We propose to replace it by a subprocess and to pass the variable in the parameters. + + +___ + +
    + + +
    +Maya: Arnold don't reset maya timeline frame range on render creation (or setting render settings) #4603 + +Fix #4429: Do not reset fps or playback timeline on applying or creating render settings + + +___ + +
    + + +
    +Update artist_hosts_maya_arnold.md #4626 + +Correct Arnold docs. +___ + +
    + + +
    +General: Filter available applications #4667 + +Added option to filter applications that don't have valid executable available in settings in launcher and ftrack actions. This option can be disabled in new settings category `Applications`. The filtering is by default disabled. + + +___ + +
    + + + + [Full Changelog](https://github.com/ynput/OpenPype/compare/3.15.1...3.15.2) ### **🆕 New features** diff --git a/openpype/version.py b/openpype/version.py index bc5ea7fe7ca..b20b1339144 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.15.3-nightly.4" +__version__ = "3.15.3" diff --git a/pyproject.toml b/pyproject.toml index 02370a4f10d..42ce5aa32c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "OpenPype" -version = "3.15.2" # OpenPype +version = "3.15.3" # OpenPype description = "Open VFX and Animation pipeline with support." authors = ["OpenPype Team "] license = "MIT License" From 85196b68f4273518d62f83473df228487e3082d2 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Mon, 27 Mar 2023 17:06:13 +0100 Subject: [PATCH 713/898] Add maya specific burnin profile. --- .../defaults/project_settings/global.json | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/openpype/settings/defaults/project_settings/global.json b/openpype/settings/defaults/project_settings/global.json index aad17d54daa..eb74078cf0c 100644 --- a/openpype/settings/defaults/project_settings/global.json +++ b/openpype/settings/defaults/project_settings/global.json @@ -249,6 +249,29 @@ } } } + }, + { + "families": [], + "hosts": [ + "maya" + ], + "task_types": [], + "task_names": [], + "subsets": [], + "burnins": { + "maya_burnin": { + "TOP_LEFT": "{yy}-{mm}-{dd}", + "TOP_CENTERED": "{focalLength:.2f} mm", + "TOP_RIGHT": "{anatomy[version]}", + "BOTTOM_LEFT": "{username}", + "BOTTOM_CENTERED": "{asset}", + "BOTTOM_RIGHT": "{frame_start}-{current_frame}-{frame_end}", + "filter": { + "families": [], + "tags": [] + } + } + } } ] }, From c758ec151fa93c8d43e3a0adc95d8cc6326edd7a Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 28 Mar 2023 12:57:44 +0200 Subject: [PATCH 714/898] fix action trigger to be only changes_requested --- .github/workflows/project_actions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index ca94f3ae772..26bc2b8a1f2 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -10,7 +10,7 @@ jobs: pr_review_requested: name: pr_review_requested runs-on: ubuntu-latest - if: github.event_name == 'pull_request' && github.event.action == 'review_requested' + if: github.event_name == 'pull_request_review' && github.event.review.state == 'changes_requested' steps: - name: Move PR to 'Change Requested' uses: leonsteinhaeuser/project-beta-automations@v2.1.0 From 51cf5d2436932988fc1c2218ed1c1aec537b065a Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 28 Mar 2023 15:16:57 +0200 Subject: [PATCH 715/898] updating changelog.md --- CHANGELOG.md | 402 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 330 insertions(+), 72 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78ea53f3d0e..4e22b783c4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,26 @@ # Changelog +## [3.15.3](https://github.com/ynput/OpenPype/tree/3.15.3) + [Full Changelog](https://github.com/ynput/OpenPype/compare/3.15.2...3.15.3) ### **🆕 New features** +
    +Blender: Extract Review #3616 + +Added Review to Blender. + +This implementation is based on #3508 but made compatible for the current implementation of OpenPype for Blender. + + +___ + +
    + +
    Data Exchanges: Point Cloud for 3dsMax #4532 @@ -24,9 +39,11 @@ ___
    -MaxScene Family #4615 +Global: persistent staging directory for renders #4583 -Introduction of the Max Scene Family +Allows configure if staging directory (`stagingDir`) should be persistent with use of profiles. + +With this feature, users can specify a transient data folder path based on presets, which can be used during the creation and publishing stages. In some cases, these DCCs automatically add a rendering path during the creation stage, which is then used in publishing.One of the key advantages of this feature is that it allows users to take advantage of faster storages for rendering, which can help improve workflow efficiency. Additionally, this feature allows users to keep their rendered data persistent, and use their own infrastructure for regular cleaning.However, it should be noted that some productions may want to use this feature without persistency. Furthermore, there may be a need for retargeting the rendering folder to faster storages, which is also not supported at the moment.It is studio responsibility to clean up obsolete folders with data.Location of the folder is configured in `project_anatomy/templates/others`. ('transient' key is expected, with 'folder' key, could be more templates)Which family/task type/subset is applicable is configured in:`project_settings/global/tools/publish/transient_dir_profiles` ___ @@ -35,11 +52,9 @@ ___
    -Blender: Extract Review #3616 +Kitsu custom comment template #4599 -Added Review to Blender. - -This implementation is based on #3508 but made compatible for the current implementation of OpenPype for Blender. +Kitsu allows to write markdown in its comment field. This can be something very powerful to deliver dynamic comments with the help the data from the instance.This feature is defaults to off so the admin have to manually set up the comment field the way they want.I have added a basic example on how the comment can look like as the comment-fields default value.To this I want to add some documentation also but that's on its way when the code itself looks good for the reviewers. ___ @@ -48,11 +63,9 @@ ___
    -Global: persistent staging directory for renders #4583 - -Allows configure if staging directory (`stagingDir`) should be persistent with use of profiles. +MaxScene Family #4615 -With this feature, users can specify a transient data folder path based on presets, which can be used during the creation and publishing stages. In some cases, these DCCs automatically add a rendering path during the creation stage, which is then used in publishing.One of the key advantages of this feature is that it allows users to take advantage of faster storages for rendering, which can help improve workflow efficiency. Additionally, this feature allows users to keep their rendered data persistent, and use their own infrastructure for regular cleaning.However, it should be noted that some productions may want to use this feature without persistency. Furthermore, there may be a need for retargeting the rendering folder to faster storages, which is also not supported at the moment.It is studio responsibility to clean up obsolete folders with data.Location of the folder is configured in `project_anatomy/templates/others`. ('transient' key is expected, with 'folder' key, could be more templates)Which family/task type/subset is applicable is configured in:`project_settings/global/tools/publish/transient_dir_profiles` +Introduction of the Max Scene Family ___ @@ -84,6 +97,22 @@ ___
    +
    +Copy existing or generate new Fusion profile on prelaunch #4572 + +Fusion preferences will be copied to the predefined `~/.openpype/hosts/fusion/prefs` folder (or any other folder set in system settings) on launch. + +The idea is to create a copy of existing Fusion profile, adding an OpenPype menu to the Fusion instance.By default the copy setting is turned off, so no file copying is performed. Instead the clean Fusion profile is created by Fusion in the predefined folder. The default locaion is set to `~/.openpype/hosts/fusion/prefs`, to better comply with the other os platforms. After creating the default profile, some modifications are applied: +- forced Python3 +- forced English interface +- setup Openpype specific path maps.If the `copy_prefs` checkbox is toggled, a copy of existing Fusion profile folder will be placed in the mentioned location. Then they are altered the same way as described above. The operation is run only once, on the first launch, unless the `force_sync [Resync profile on each launch]` is toggled.English interface is forced because the `FUSION16_PROFILE_DIR` environment variable is not read otherwise (seems to be a Fusion bug). + + +___ + +
    + +
    Houdini: Create button open new publisher's "create" tab #4601 @@ -95,6 +124,28 @@ ___
    +
    +Clockify: refresh and fix the integration #4607 + +Due to recent API changes, Clockify requires `user_id` to operate with the timers. I updated this part and currently it is a WIP for making it fully functional. Most functions, such as start and stop timer, and projects sync are currently working. For the rate limiting task new dependency is added: https://pypi.org/project/ratelimiter/ + + +___ + +
    + + +
    +Fusion publish existing frames #4611 + +This PR adds the function to publish existing frames instead of having to re-render all of them for each new publish.I have split the render_locally plugin so the review-part is its own plugin now.I also change the saver-creator-plugin's label from Saver to Render (saver) as I intend to add a Prerender creator like in Nuke. + + +___ + +
    + +
    Resolution settings referenced from DB record for 3dsMax #4652 @@ -107,6 +158,17 @@ ___
    +
    +3dsmax: render instance settings in Publish tab #4658 + +Allows user preset the pools, group and use_published settings in Render Creator in the Max Hosts.User can set the settings before or after creating instance in the new publisher + + +___ + +
    + +
    scene length setting referenced from DB record for 3dsMax #4665 @@ -119,9 +181,9 @@ ___
    -increment workfile version 3dsmax #4685 +Publisher: Windows reduce command window pop-ups during Publishing #4672 -increment workfile version in 3dsmax as if in blender and maya hosts. +Reduce the command line pop-ups that show on Windows during publishing. ___ @@ -130,14 +192,9 @@ ___
    -Copy existing or generate new Fusion profile on prelaunch #4572 +Publisher: Explicit save #4676 -Fusion preferences will be copied to the predefined `~/.openpype/hosts/fusion/prefs` folder (or any other folder set in system settings) on launch. - -The idea is to create a copy of existing Fusion profile, adding an OpenPype menu to the Fusion instance.By default the copy setting is turned off, so no file copying is performed. Instead the clean Fusion profile is created by Fusion in the predefined folder. The default locaion is set to `~/.openpype/hosts/fusion/prefs`, to better comply with the other os platforms. After creating the default profile, some modifications are applied: -- forced Python3 -- forced English interface -- setup Openpype specific path maps.If the `copy_prefs` checkbox is toggled, a copy of existing Fusion profile folder will be placed in the mentioned location. Then they are altered the same way as described above. The operation is run only once, on the first launch, unless the `force_sync [Resync profile on each launch]` is toggled.English interface is forced because the `FUSION16_PROFILE_DIR` environment variable is not read otherwise (seems to be a Fusion bug). +Publisher have explicit button to save changes, so reset can happen without saving any changes. Save still happens automatically when publishing is started or on publisher window close. But a popup is shown if context of host has changed. Important context was enhanced by workfile path (if host integration supports it) so workfile changes are captured too. In that case a dialog with confirmation is shown to user. All callbacks that may require save of context were moved to main window to be able handle dialog show at one place. Save changes now returns success so the rest of logic is skipped -> publishing won't start, when save of instances fails.Save and reset buttons have shortcuts (Ctrl + s and Ctrls + r). ___ @@ -146,9 +203,9 @@ ___
    -Fusion publish existing frames #4611 +CelAction: conditional workfile parameters from settings #4677 -This PR adds the function to publish existing frames instead of having to re-render all of them for each new publish.I have split the render_locally plugin so the review-part is its own plugin now.I also change the saver-creator-plugin's label from Saver to Render (saver) as I intend to add a Prerender creator like in Nuke. +Since some productions were requesting excluding some workfile parameters from publishing submission, we needed to move them to settings so those could be altered per project. ___ @@ -157,9 +214,9 @@ ___
    -Clockify: refresh and fix the integration #4607 +Improve logging of used app + tool envs on application launch #4682 -Due to recent API changes, Clockify requires `user_id` to operate with the timers. I updated this part and currently it is a WIP for making it fully functional. Most functions, such as start and stop timer, and projects sync are currently working. For the rate limiting task new dependency is added: https://pypi.org/project/ratelimiter/ +Improve logging of what apps + tool environments got loaded for an application launch. ___ @@ -168,9 +225,9 @@ ___
    -Publisher: Windows reduce command window pop-ups during Publishing #4672 +Fix name and docstring for Create Workdir Extra Folders prelaunch hook #4683 -Reduce the command line pop-ups that show on Windows during publishing. +Fix class name and docstring for Create Workdir Extra Folders prelaunch hookThe class name and docstring were originally copied from another plug-in and didn't match the plug-in logic.This also fixes potentially seeing this twice in your logs. Before:After:Where it was actually running both this prelaunch hook and the actual `AddLastWorkfileToLaunchArgs` plugin. ___ @@ -179,9 +236,9 @@ ___
    -CelAction: conditional workfile parameters from settings #4677 +Application launch context: Include app group name in logger #4684 -Since some productions were requesting excluding some workfile parameters from publishing submission, we needed to move them to settings so those could be altered per project. +Clarify in logs better what app group the ApplicationLaunchContext belongs to and what application is being launched.Before:After: ___ @@ -190,9 +247,9 @@ ___
    -Fix name and docstring for Create Workdir Extra Folders prelaunch hook #4683 +increment workfile version 3dsmax #4685 -Fix class name and docstring for Create Workdir Extra Folders prelaunch hookThe class name and docstring were originally copied from another plug-in and didn't match the plug-in logic.This also fixes potentially seeing this twice in your logs. Before:After:Where it was actually running both this prelaunch hook and the actual `AddLastWorkfileToLaunchArgs` plugin. +increment workfile version in 3dsmax as if in blender and maya hosts. ___ @@ -301,9 +358,11 @@ ___
    -Fixed a bug where a QThread in the splash screen could be destroyed before finishing execution #4647 +Maya: tile assembly fail in draft - OP-4820 #4416 -This should fix the occasional behavior of the QThread being destroyed before even its worker returns from the `run()` function.After quiting, it should wait for the QThread object to properly close itself. +Tile assembly in Deadline was broken. + +Initial bug report revealed other areas of the tile assembly that needed fixing. ___ @@ -312,9 +371,11 @@ ___
    -Max: fix the bug of removing an instance #4617 +Maya: Yeti Validate Rig Input - OP-3454 #4554 -fix the bug of removing an instance in 3dsMax +Fix Yeti Validate Rig Input + +Existing workflow was broken due to this #3297. ___ @@ -323,9 +384,19 @@ ___
    -bugfix for 3dsmax publishing error #4637 +Scene inventory: Fix code errors when "not found" entries are found #4594 -fix the bug of failing publishing job in 3dsMax +Whenever a "NOT FOUND" entry is present a lot of errors happened in the Scene Inventory: +- It started spamming a lot of errors for the VersionDelegate since it had no numeric version (no version at all).Error reported on Discord: +```python +Traceback (most recent call last): + File "C:\Users\videopro\Documents\github\OpenPype\openpype\tools\utils\delegates.py", line 65, in paint + text = self.displayText( + File "C:\Users\videopro\Documents\github\OpenPype\openpype\tools\utils\delegates.py", line 33, in displayText + assert isinstance(value, numbers.Integral), ( +AssertionError: Version is not integer. "None" +``` +- Right click menu would error on NOT FOUND entries, and thus not show. With this PR it will now _disregard_ not found items for "Set version" and "Remove" but still allow actions.This PR resolves those. ___ @@ -334,9 +405,28 @@ ___
    -3dsmax: opening last workfile #4644 +Kitsu: Sync OP with zou, make sure value-data is int or float #4596 + +Currently the data zou pulls is a string and not a value causing some bugs in the pipe where a value is expected (like `Set frame range` in Fusion). + + + +This PR makes sure each value is set with int() or float() so these bugs can't happen later on. -Supports opening last saved workfile in 3dsmax host. + + +_(A request to cgwire has also bin sent to allow force values only for some metadata columns, but currently the user can enter what ever they want in there)_ + + +___ + +
    + + +
    +Max: fix the bug of removing an instance #4617 + +fix the bug of removing an instance in 3dsMax ___ @@ -356,9 +446,9 @@ ___
    -Nuke: Nukenodes family instance without frame range #4669 +Ftrack: Ftrack additional families filtering #4633 -No need to add frame range data into `nukenodes` (backdrop) family publishes - since those are timeless. +Ftrack family collector makes sure the subset family is also in instance families for additional families filtering. ___ @@ -367,9 +457,9 @@ ___
    -TVPaint: Optional Validation plugins can be de/activated by user #4674 +Ftrack: Hierarchical <> Non-Hierarchical attributes sync fix #4635 -Added `OptionalPyblishPluginMixin` to TVpaint plugins that can be optional. +Sync between hierarchical and non-hierarchical attributes should be fixed and work as expected. Action should sync the values as expected and event handler should do it too and only on newly created entities. ___ @@ -378,9 +468,9 @@ ___
    -Hiero: Creator with correct workfile numeric padding input #4666 +bugfix for 3dsmax publishing error #4637 -Creator was showing 99 in workfile input for long time, even if users set default value to 1001 in studio settings. This has been fixed now. +fix the bug of failing publishing job in 3dsMax ___ @@ -389,9 +479,9 @@ ___
    -Hiero: correct container colors if UpToDate #4708 +General: Use right validation for ffmpeg executable #4640 -Colors on loaded containers are now correctly identifying real state of version. `Red` for out of date and `green` for up to date. +Use ffmpeg exec validation for ffmpeg executables instead of oiio exec validation. The validation is used as last possible source of ffmpeg from `PATH` environment variables, which is an edge case but can cause issues. ___ @@ -400,11 +490,20 @@ ___
    -Maya: tile assembly fail in draft - OP-4820 #4416 +3dsmax: opening last workfile #4644 -Tile assembly in Deadline was broken. +Supports opening last saved workfile in 3dsmax host. -Initial bug report revealed other areas of the tile assembly that needed fixing. + +___ + +
    + + +
    +Fixed a bug where a QThread in the splash screen could be destroyed before finishing execution #4647 + +This should fix the occasional behavior of the QThread being destroyed before even its worker returns from the `run()` function.After quiting, it should wait for the QThread object to properly close itself. ___ @@ -413,19 +512,9 @@ ___
    -Scene inventory: Fix code errors when "not found" entries are found #4594 +General: Use right plugin class for Collect Comment #4653 -Whenever a "NOT FOUND" entry is present a lot of errors happened in the Scene Inventory: -- It started spamming a lot of errors for the VersionDelegate since it had no numeric version (no version at all).Error reported on Discord: -```python -Traceback (most recent call last): - File "C:\Users\videopro\Documents\github\OpenPype\openpype\tools\utils\delegates.py", line 65, in paint - text = self.displayText( - File "C:\Users\videopro\Documents\github\OpenPype\openpype\tools\utils\delegates.py", line 33, in displayText - assert isinstance(value, numbers.Integral), ( -AssertionError: Version is not integer. "None" -``` -- Right click menu would error on NOT FOUND entries, and thus not show. With this PR it will now _disregard_ not found items for "Set version" and "Remove" but still allow actions.This PR resolves those. +Collect Comment plugin is instance plugin so should inherit from `InstancePlugin` instead of `ContextPlugin`. ___ @@ -434,9 +523,9 @@ ___
    -Ftrack: Ftrack additional families filtering #4633 +Global: add tags field to thumbnail representation #4660 -Ftrack family collector makes sure the subset family is also in instance families for additional families filtering. +Thumbnail representation might be missing tags field. ___ @@ -445,9 +534,9 @@ ___
    -General: Use right validation for ffmpeg executable #4640 +Integrator: Enforce unique destination transfers, disallow overwrites in queued transfers #4662 -Use ffmpeg exec validation for ffmpeg executables instead of oiio exec validation. The validation is used as last possible source of ffmpeg from `PATH` environment variables, which is an edge case but can cause issues. +Fix #4656 by enforcing unique destination transfers in the Integrator. It's now disallowed to a destination in the file transaction queue with a new source path during the publish. ___ @@ -456,9 +545,31 @@ ___
    -Global: add tags field to thumbnail representation #4660 +Hiero: Creator with correct workfile numeric padding input #4666 -Thumbnail representation might be missing tags field. +Creator was showing 99 in workfile input for long time, even if users set default value to 1001 in studio settings. This has been fixed now. + + +___ + +
    + + +
    +Nuke: Nukenodes family instance without frame range #4669 + +No need to add frame range data into `nukenodes` (backdrop) family publishes - since those are timeless. + + +___ + +
    + + +
    +TVPaint: Optional Validation plugins can be de/activated by user #4674 + +Added `OptionalPyblishPluginMixin` to TVpaint plugins that can be optional. ___ @@ -479,12 +590,34 @@ ___
    +
    +Publisher: Fix reset shortcut sequence #4694 + +Fix bug created in https://github.com/ynput/OpenPype/pull/4676 where key sequence is checked using unsupported method. The check was changed to convert event into `QKeySequence` object which can be compared to prepared sequence. + + +___ + +
    + +
    Refactor _capture #4702 Paragraphs contain detailed information on the changes made to the product or service, providing an in-depth description of the updates and enhancements. They can be used to explain the reasoning behind the changes, or to highlight the importance of the new features. Paragraphs can often include links to further information or support documentation. +___ + +
    + + +
    +Hiero: correct container colors if UpToDate #4708 + +Colors on loaded containers are now correctly identifying real state of version. `Red` for out of date and `green` for up to date. + + ___
    @@ -529,12 +662,34 @@ ___
    +
    +Maya: Replace last usages of Qt module #4610 + +Replace last usage of `Qt` module with `qtpy`. This change is needed for `PySide6` support. All changes happened in Maya loader plugins. + + +___ + +
    + +
    Update tests and documentation for `ColormanagedPyblishPluginMixin` #4612 Refactor `ExtractorColormanaged` to `ColormanagedPyblishPluginMixin` in tests and documentation. +___ + +
    + + +
    +Improve logging of used app + tool envs on application launch (minor tweak) #4686 + +Use `app.full_name` for change done in #4682 + + ___
    @@ -555,6 +710,17 @@ ___
    +
    +Documentation: Tweak grammar and fix some typos #4613 + +This resolves some grammar and typos in the documentation.Also fixes the extension of some images in after effects docs which used uppercase extension even though files were lowercase extension. + + +___ + +
    + +
    Docs: Fix some minor grammar/typos #4680 @@ -613,9 +779,11 @@ ___
    -3dsmax: make sure that startup script executes #4695 +Resolve missing OPENPYPE_MONGO in deadline global job preload #4484 -Fixing reliability of OpenPype startup in 3dsmax. +In the GlobalJobPreLoad plugin, we propose to replace the SpawnProcess by a sub-process and to pass the environment variables in the parameters, since the SpawnProcess under Centos Linux does not pass the environment variables. + +In the GlobalJobPreLoad plugin, the Deadline SpawnProcess is used to start the OpenPype process. The problem is that the SpawnProcess does not pass environment variables, including OPENPYPE_MONGO, to the process when it is under Centos7 linux, and the process gets stuck. We propose to replace it by a subprocess and to pass the variable in the parameters. ___ @@ -624,11 +792,9 @@ ___
    -Resolve missing OPENPYPE_MONGO in deadline global job preload #4484 +Tests: Added setup_only to tests #4591 -In the GlobalJobPreLoad plugin, we propose to replace the SpawnProcess by a sub-process and to pass the environment variables in the parameters, since the SpawnProcess under Centos Linux does not pass the environment variables. - -In the GlobalJobPreLoad plugin, the Deadline SpawnProcess is used to start the OpenPype process. The problem is that the SpawnProcess does not pass environment variables, including OPENPYPE_MONGO, to the process when it is under Centos7 linux, and the process gets stuck. We propose to replace it by a subprocess and to pass the variable in the parameters. +Allows to download test zip, unzip and restore DB in preparation for new test. ___ @@ -647,6 +813,64 @@ ___
    +
    +Bump @sideway/formula from 3.0.0 to 3.0.1 in /website #4609 + +Bumps [@sideway/formula](https://github.com/sideway/formula) from 3.0.0 to 3.0.1. +
    +Commits + +
    +
    +Maintainer changes +

    This version was pushed to npm by marsup, a new releaser for @​sideway/formula since your current version.

    +
    +
    + + +[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@sideway/formula&package-manager=npm_and_yarn&previous-version=3.0.0&new-version=3.0.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) + +Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. + +[//]: # (dependabot-automerge-start) +[//]: # (dependabot-automerge-end) + +--- + +
    +Dependabot commands and options +
    + +You can trigger Dependabot actions by commenting on this PR: +- `@dependabot rebase` will rebase this PR +- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it +- `@dependabot merge` will merge this PR after your CI passes on it +- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it +- `@dependabot cancel merge` will cancel a previously requested merge and block automerging +- `@dependabot reopen` will reopen this PR if it is closed +- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually +- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) +- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) +- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) +- `@dependabot use these labels` will set the current labels as the default for future PRs for this repo and language +- `@dependabot use these reviewers` will set the current reviewers as the default for future PRs for this repo and language +- `@dependabot use these assignees` will set the current assignees as the default for future PRs for this repo and language +- `@dependabot use this milestone` will set the current milestone as the default for future PRs for this repo and language + +You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/ynput/OpenPype/network/alerts). + +
    +___ + +
    + +
    Update artist_hosts_maya_arnold.md #4626 @@ -656,6 +880,17 @@ ___
    +
    +Maya: Add "Include Parent Hierarchy" option in animation creator plugin #4645 + +Add an option in Project Settings > Maya > Creator Plugins > Create Animation to include (or not) parent hierarchy. This is to avoid artists to check manually the option for all create animation. + + +___ + +
    + +
    General: Filter available applications #4667 @@ -667,7 +902,30 @@ ___
    +
    +3dsmax: make sure that startup script executes #4695 + +Fixing reliability of OpenPype startup in 3dsmax. + + +___ + +
    + + +
    +Project Manager: Change minimum frame start/end to '0' #4719 + +Project manager can have frame start/end set to `0`. + + +___ + +
    + + +## [3.15.2](https://github.com/ynput/OpenPype/tree/3.15.2) [Full Changelog](https://github.com/ynput/OpenPype/compare/3.15.1...3.15.2) From ba1e033815f25d9d9f30a110b3a0cdfc81f3ae36 Mon Sep 17 00:00:00 2001 From: Ynbot Date: Wed, 29 Mar 2023 03:26:05 +0000 Subject: [PATCH 716/898] [Automated] Bump version --- openpype/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/version.py b/openpype/version.py index b20b1339144..4d6ee5590e3 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.15.3" +__version__ = "3.15.4-nightly.1" From 7264ce3aafd51c8fbd81dd1803a9242c161ad75b Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Wed, 29 Mar 2023 09:17:20 +0100 Subject: [PATCH 717/898] Update openpype/lib/execute.py --- openpype/lib/execute.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/lib/execute.py b/openpype/lib/execute.py index 5ba62f177f4..eba75389f15 100644 --- a/openpype/lib/execute.py +++ b/openpype/lib/execute.py @@ -199,7 +199,7 @@ def run_openpype_process(*args, **kwargs): # - fill more if you find more env = clean_envs_for_openpype_process(os.environ) - # Add OpenPype version if we are running from build. + # Only keep OpenPype version if we are running from build. if not is_running_from_build(): env.pop("OPENPYPE_VERSION", None) From 2d92deae1694fb7761032518b672b647890d5b5e Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 29 Mar 2023 11:31:49 +0100 Subject: [PATCH 718/898] Fixes --- openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py index 6d7be80060d..449eacb40fb 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py +++ b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py @@ -118,6 +118,7 @@ def shading_engine_assignments(shading_engine, attribute, nodes, assignments): shading_engine, attribute ) ) + return # Strip off component assignments for i, node in enumerate(nodes): @@ -261,4 +262,4 @@ def assign_look(standin, subset): index += 1 - cmds.sets(operator, edit=True, addElement=container_node[0]) + cmds.sets(operator, edit=True, addElement=container_node) From 57bbf946fda65a0e0b6ce3fce04de0f0f8dabf16 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 29 Mar 2023 11:31:55 +0100 Subject: [PATCH 719/898] Code cosmetics --- .../hosts/maya/tools/mayalookassigner/arnold_standin.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py index 449eacb40fb..dfffbc59615 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py +++ b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py @@ -111,7 +111,8 @@ def get_standin_path(node): def shading_engine_assignments(shading_engine, attribute, nodes, assignments): shader_inputs = cmds.listConnections( - shading_engine + "." + attribute, source=True) + shading_engine + "." + attribute, source=True + ) if not shader_inputs: log.info( "Shading engine \"{}\" missing input \"{}\"".format( @@ -124,9 +125,9 @@ def shading_engine_assignments(shading_engine, attribute, nodes, assignments): for i, node in enumerate(nodes): if "." in node: log.warning( - ("Converting face assignment to full object " - "assignment. This conversion can be lossy: " - "{}").format(node)) + "Converting face assignment to full object assignment. This " + "conversion can be lossy: {}".format(node) + ) nodes[i] = node.split(".")[0] shader_type = "shader" if attribute == "surfaceShader" else "disp_map" From 421048083164e549a69bdc16e248b33d7cc0c71f Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 29 Mar 2023 12:51:07 +0200 Subject: [PATCH 720/898] Refactor ExtractLook maketx argument in settings to more structured arguments/parameters --- .../maya/plugins/publish/extract_look.py | 20 +++++++++---------- .../defaults/project_settings/maya.json | 2 +- .../schemas/schema_maya_publish.json | 17 ++++++++++++++-- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 1e339542d78..93054e5fbb7 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -227,21 +227,21 @@ def __init__(self, log=None): def apply_settings(self, system_settings, project_settings): # Allow extra maketx arguments from project settings - extra_args_dict = ( + args_settings = ( project_settings["maya"]["publish"] - .get("ExtractLook", {}).get("maketx_arguments", {}) + .get("ExtractLook", {}).get("maketx_arguments", []) ) extra_args = [] - for flag, value in extra_args_dict.items(): - if not flag: - self.log.debug("Ignoring empty flag from `maketx_arguments` " - "setting..") + for arg_data in args_settings: + argument = arg_data["argument"] + parameters = arg_data["parameters"] + if not argument: + self.log.debug("Ignoring empty parameter from " + "`maketx_arguments` setting..") continue - extra_args.append(flag) - if value.strip(): - # There might be flags without values like --opaque-detect - extra_args.append(value) + extra_args.append(argument) + extra_args.extend(parameters) self.extra_args = extra_args diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index 26dd66770f5..8f5a3c75ab6 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -928,7 +928,7 @@ "ogsfx_path": "/maya2glTF/PBR/shaders/glTF_PBR.ogsfx" }, "ExtractLook": { - "maketx_arguments": {} + "maketx_arguments": [] } }, "load": { diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json index da12dde6b26..7ced375cb51 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json @@ -1004,11 +1004,24 @@ "label": "Extract Look", "children": [ { + "type": "list", "key": "maketx_arguments", "label": "Extra arguments for maketx command line", - "type": "dict-modifiable", "object_type": { - "type": "text" + "type": "dict", + "children": [ + { + "key": "argument", + "label": "Argument", + "type": "text" + }, + { + "key": "parameters", + "label": "Parameters", + "type": "list", + "object_type": "text" + } + ] } } ] From 3fa284f16ca8ac21fef535467289e1ca3e6607ac Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 29 Mar 2023 14:09:52 +0200 Subject: [PATCH 721/898] adding size labeling to project workflow --- .github/workflows/project_actions.yml | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index 26bc2b8a1f2..dc68a9dc0ef 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -2,7 +2,7 @@ name: project-actions on: pull_request: - types: [review_requested] + types: [opened, synchronize, assigned, review_requested] pull_request_review: types: [submitted] @@ -20,3 +20,26 @@ jobs: project_id: 11 resource_node_id: ${{ github.event.pull_request.node_id }} status_value: Change Requested + size-label: + name: pr_size_label + runs-on: ubuntu-latest + if: | + ${{(github.event_name == 'pull_request' && github.event.action == 'synchronize') + || (github.event_name == 'pull_request' && github.event.action == 'assigned')}} + + steps: + - name: Add size label + uses: "pascalgn/size-label-action@v0.4.3" + env: + GITHUB_TOKEN: "${{ secrets.YNPUT_BOT_TOKEN }}" + IGNORED: ".gitignore\n*.md\n*.json" + with: + sizes: > + { + "0": "XS", + "100": "S", + "500": "M", + "1000": "L", + "1500": "XL", + "2500": "XXL" + } \ No newline at end of file From 669a2256ef4093a399b6e9615c28da0094de7419 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 29 Mar 2023 14:46:41 +0200 Subject: [PATCH 722/898] Merge develop --- .github/workflows/project_actions.yml | 22 + ARCHITECTURE.md | 77 + CHANGELOG.md | 1774 +++ openpype/cli.py | 8 +- openpype/hooks/pre_add_last_workfile_arg.py | 1 + .../hooks/pre_create_extra_workdir_folders.py | 9 +- openpype/hooks/pre_foundry_apps.py | 4 +- openpype/host/dirmap.py | 63 +- openpype/hosts/blender/api/__init__.py | 5 + openpype/hosts/blender/api/capture.py | 278 + openpype/hosts/blender/api/lib.py | 10 + openpype/hosts/blender/api/ops.py | 8 +- openpype/hosts/blender/api/plugin.py | 7 +- .../blender/plugins/create/create_review.py | 47 + .../blender/plugins/publish/collect_review.py | 64 + .../plugins/publish/extract_playblast.py | 123 + .../plugins/publish/extract_thumbnail.py | 99 + .../celaction/hooks/pre_celaction_setup.py | 36 +- .../publish/collect_celaction_cli_kwargs.py | 2 +- openpype/hosts/fusion/__init__.py | 4 + openpype/hosts/fusion/addon.py | 52 +- openpype/hosts/fusion/api/action.py | 13 +- openpype/hosts/fusion/api/lib.py | 14 +- openpype/hosts/fusion/api/menu.py | 13 - .../hosts/fusion/deploy/fusion_shared.prefs | 28 +- .../fusion/hooks/pre_fusion_profile_hook.py | 161 + .../hosts/fusion/hooks/pre_fusion_setup.py | 56 +- .../fusion/plugins/create/create_saver.py | 81 +- .../publish/collect_expected_frames.py | 50 + .../plugins/publish/collect_render_target.py | 44 - .../fusion/plugins/publish/collect_renders.py | 25 + .../plugins/publish/extract_render_local.py | 109 + .../fusion/plugins/publish/render_local.py | 100 - .../publish/validate_create_folder_checked.py | 14 +- .../validate_expected_frames_existence.py | 78 + .../hosts/fusion/scripts/set_rendermode.py | 112 - openpype/hosts/hiero/api/lib.py | 6 +- openpype/hosts/hiero/api/plugin.py | 20 +- .../hosts/houdini/startup/MainMenuCommon.xml | 8 +- openpype/hosts/max/api/lib.py | 111 + openpype/hosts/max/api/lib_renderproducts.py | 48 +- openpype/hosts/max/api/menu.py | 20 + openpype/hosts/max/api/pipeline.py | 5 + openpype/hosts/max/api/plugin.py | 4 +- .../max/plugins/create/create_maxScene.py | 26 + .../max/plugins/create/create_pointcloud.py | 26 + .../hosts/max/plugins/load/load_max_scene.py | 6 +- .../hosts/max/plugins/load/load_pointcloud.py | 51 + .../max/plugins/publish/collect_render.py | 2 +- .../plugins/publish/extract_max_scene_raw.py | 3 +- .../max/plugins/publish/extract_pointcloud.py | 207 + .../publish/increment_workfile_version.py | 19 + .../publish/validate_no_max_content.py | 23 + .../plugins/publish/validate_pointcloud.py | 191 + openpype/hosts/maya/api/customize.py | 3 +- openpype/hosts/maya/api/lib.py | 100 +- openpype/hosts/maya/api/lib_rendersettings.py | 5 +- openpype/hosts/maya/api/menu.py | 7 +- .../maya/plugins/create/create_animation.py | 3 +- .../maya/plugins/create/create_review.py | 2 + .../plugins/inventory/connect_geometry.py | 2 +- .../maya/plugins/inventory/connect_xgen.py | 2 +- .../plugins/inventory/connect_yeti_rig.py | 178 + .../maya/plugins/load/load_arnold_standin.py | 6 +- .../hosts/maya/plugins/load/load_image.py | 332 + openpype/hosts/maya/plugins/load/load_xgen.py | 2 +- .../hosts/maya/plugins/load/load_yeti_rig.py | 94 +- .../maya/plugins/publish/collect_review.py | 26 + .../maya/plugins/publish/extract_look.py | 101 +- .../maya/plugins/publish/extract_playblast.py | 132 +- .../maya/plugins/publish/extract_thumbnail.py | 52 +- .../publish/validate_look_color_space.py | 26 + .../publish/validate_rendersettings.py | 109 +- .../validate_yeti_renderscript_callbacks.py | 12 + openpype/hosts/maya/tools/__init__.py | 27 + .../maya}/tools/mayalookassigner/LICENSE | 0 .../maya}/tools/mayalookassigner/__init__.py | 0 .../maya}/tools/mayalookassigner/app.py | 0 .../maya}/tools/mayalookassigner/commands.py | 16 +- .../maya}/tools/mayalookassigner/models.py | 0 .../maya}/tools/mayalookassigner/views.py | 0 .../tools/mayalookassigner/vray_proxies.py | 0 .../maya}/tools/mayalookassigner/widgets.py | 0 openpype/hosts/nuke/api/lib.py | 54 +- .../hosts/nuke/plugins/load/load_backdrop.py | 22 +- .../nuke/plugins/publish/collect_backdrop.py | 32 +- .../plugins/publish/extract_review_data.py | 2 +- .../publish/extract_review_data_lut.py | 7 +- .../publish/extract_review_data_mov.py | 5 +- .../nuke/plugins/publish/extract_thumbnail.py | 2 +- openpype/hosts/photoshop/api/launch_logic.py | 4 +- openpype/hosts/resolve/api/menu.py | 8 +- .../hosts/tvpaint/api/communication_server.py | 4 +- .../tvpaint/plugins/create/convert_legacy.py | 4 +- .../tvpaint/plugins/create/create_render.py | 15 +- .../publish/collect_instance_frames.py | 2 + .../plugins/publish/validate_asset_name.py | 12 +- .../publish/validate_layers_visibility.py | 2 +- .../tvpaint/plugins/publish/validate_marks.py | 13 +- .../publish/validate_scene_settings.py | 13 +- .../plugins/publish/validate_start_frame.py | 13 +- openpype/hosts/unreal/ue_workers.py | 142 +- openpype/lib/applications.py | 18 +- openpype/lib/execute.py | 11 + openpype/lib/file_transaction.py | 22 +- openpype/lib/vendor_bin_utils.py | 14 +- openpype/modules/clockify/clockify_api.py | 359 +- openpype/modules/clockify/clockify_module.py | 177 +- openpype/modules/clockify/constants.py | 2 +- .../server/action_clockify_sync_server.py | 25 +- .../ftrack/user/action_clockify_sync_local.py | 26 +- .../launcher_actions/ClockifyStart.py | 46 +- .../clockify/launcher_actions/ClockifySync.py | 55 +- openpype/modules/clockify/widgets.py | 16 +- .../deadline/plugins/publish/collect_pools.py | 47 +- .../publish/submit_celaction_deadline.py | 2 +- .../plugins/publish/submit_max_deadline.py | 72 +- .../plugins/publish/submit_maya_deadline.py | 63 +- .../plugins/publish/submit_nuke_deadline.py | 10 +- .../plugins/publish/submit_publish_job.py | 4 + .../publish/validate_deadline_pools.py | 10 +- .../validate_expected_and_rendered_files.py | 11 +- .../custom/plugins/GlobalJobPreLoad.py | 8 +- .../OpenPypeTileAssembler.py | 97 +- .../example_addons/example_addon/addon.py | 2 +- .../action_push_frame_values_to_task.py | 316 +- .../event_push_frame_values_to_task.py | 1102 +- .../action_applications.py | 9 + .../plugins/publish/collect_ftrack_family.py | 87 +- .../plugins/publish/collect_kitsu_entities.py | 2 +- .../plugins/publish/integrate_kitsu_note.py | 107 +- .../plugins/publish/integrate_kitsu_review.py | 8 +- .../modules/kitsu/utils/update_op_with_zou.py | 34 +- .../modules/sync_server/sync_server_module.py | 20 +- .../modules/timers_manager/timers_manager.py | 4 +- openpype/pipeline/create/context.py | 91 +- openpype/pipeline/publish/contants.py | 1 + openpype/pipeline/publish/lib.py | 80 +- openpype/plugins/publish/cleanup.py | 4 + openpype/plugins/publish/cleanup_farm.py | 2 +- openpype/plugins/publish/collect_comment.py | 2 +- .../publish/collect_custom_staging_dir.py | 67 + openpype/plugins/publish/extract_burnin.py | 42 +- openpype/plugins/publish/integrate.py | 18 +- openpype/plugins/publish/integrate_legacy.py | 2 + .../preintegrate_thumbnail_representation.py | 2 + openpype/pype_commands.py | 5 +- openpype/scripts/otio_burnin.py | 125 +- .../defaults/project_anatomy/templates.json | 6 +- .../project_settings/applications.json | 3 + .../defaults/project_settings/blender.json | 88 + .../defaults/project_settings/celaction.json | 7 + .../defaults/project_settings/deadline.json | 7 +- .../defaults/project_settings/fusion.json | 5 + .../defaults/project_settings/global.json | 26 +- .../defaults/project_settings/kitsu.json | 10 +- .../defaults/project_settings/max.json | 15 + .../defaults/project_settings/maya.json | 11 +- .../defaults/project_settings/tvpaint.json | 1 + .../system_settings/applications.json | 2 +- openpype/settings/entities/schemas/README.md | 2 +- .../schemas/projects_schema/schema_main.json | 4 + .../schema_project_applications.json | 14 + .../schema_project_celaction.json | 25 + .../schema_project_deadline.json | 19 +- .../schema_project_fusion.json | 23 + .../projects_schema/schema_project_kitsu.json | 84 +- .../projects_schema/schema_project_max.json | 24 +- .../schema_project_tvpaint.json | 6 + .../schemas/schema_blender_publish.json | 62 +- .../schemas/schema_global_tools.json | 65 + .../schemas/schema_maya_capture.json | 11 +- .../schemas/schema_maya_create.json | 5 + .../schemas/schema_maya_publish.json | 16 +- openpype/tools/launcher/models.py | 6 + openpype/tools/loader/widgets.py | 6 +- .../project_manager/project_manager/view.py | 4 +- openpype/tools/publisher/constants.py | 5 +- openpype/tools/publisher/control.py | 185 +- openpype/tools/publisher/widgets/__init__.py | 6 +- .../publisher/widgets/card_view_widgets.py | 19 + .../tools/publisher/widgets/images/save.png | Bin 0 -> 3961 bytes .../publisher/widgets/list_view_widgets.py | 27 + .../publisher/widgets/overview_widget.py | 38 +- openpype/tools/publisher/widgets/widgets.py | 34 +- openpype/tools/publisher/window.py | 129 +- openpype/tools/sceneinventory/model.py | 22 +- openpype/tools/sceneinventory/view.py | 7 + openpype/tools/sceneinventory/window.py | 6 +- .../local_settings/projects_widget.py | 2 +- .../tools/settings/settings/search_dialog.py | 12 +- .../model_filter_proxy_recursive_sort.py | 6 +- openpype/tools/traypublisher/window.py | 2 +- openpype/tools/utils/delegates.py | 8 +- openpype/tools/utils/host_tools.py | 32 - openpype/tools/utils/lib.py | 4 +- openpype/tools/utils/models.py | 20 +- openpype/version.py | 2 +- openpype/widgets/splash_screen.py | 11 +- pyproject.toml | 2 +- tests/conftest.py | 10 + .../nuke/test_deadline_publish_in_nuke.py | 18 + .../hosts/nuke/test_publish_in_nuke.py | 20 +- tests/lib/testing_classes.py | 22 +- .../pipeline/publish/test_publish_plugins.py | 6 +- website/docs/admin_environment.md | 2 +- website/docs/admin_hosts_maya.md | 56 +- website/docs/admin_settings.md | 11 +- website/docs/admin_use.md | 2 +- website/docs/artist_hosts_3dsmax.md | 4 +- website/docs/artist_hosts_aftereffects.md | 6 +- website/docs/artist_hosts_harmony.md | 2 +- website/docs/artist_hosts_hiero.md | 6 +- website/docs/artist_hosts_maya.md | 24 +- website/docs/artist_hosts_maya_arnold.md | 2 +- website/docs/artist_hosts_maya_yeti.md | 83 +- website/docs/artist_hosts_photoshop.md | 2 +- website/docs/artist_tools_sync_queu.md | 2 +- ...armony_creator.PNG => harmony_creator.png} | Bin .../assets/integrate_kitsu_note_settings.png | Bin 0 -> 48874 bytes .../maya-admin_extract_playblast_settings.png | Bin 0 -> 26814 bytes ...ract_playblast_settings_camera_options.png | Bin 0 -> 16732 bytes ...ct_playblast_settings_viewport_options.png | Bin 0 -> 1064191 bytes .../maya-admin_render_settings_validator.png | Bin 11220 -> 11855 bytes website/docs/assets/maya-yeti_hair_setup.png | Bin 0 -> 138812 bytes .../assets/maya-yeti_load_connections.png | Bin 0 -> 125692 bytes .../docs/assets/maya-yeti_publish_setup.png | Bin 0 -> 133890 bytes website/docs/assets/maya-yeti_rig.jpg | Bin 59405 -> 0 bytes website/docs/assets/maya-yeti_rig_setup.png | Bin 0 -> 111360 bytes website/docs/assets/maya-yeti_simple_rig.png | Bin 0 -> 96188 bytes website/docs/dev_colorspace.md | 6 +- website/docs/dev_host_implementation.md | 4 +- website/docs/dev_publishing.md | 2 +- website/docs/dev_settings.md | 6 +- website/docs/dev_testing.md | 2 +- website/docs/manager_ftrack.md | 2 +- website/docs/module_deadline.md | 4 + website/docs/module_ftrack.md | 2 +- website/docs/module_kitsu.md | 17 +- website/docs/module_site_sync.md | 2 +- .../global_tools_custom_staging_dir.png | Bin 0 -> 9940 bytes .../settings_project_global.md | 45 +- .../project_settings/settings_project_nuke.md | 2 +- .../settings_project_standalone.md | 2 +- website/docs/pype2/admin_ftrack.md | 2 +- website/docs/pype2/admin_presets_plugins.md | 4 +- website/docs/system_introduction.md | 4 +- website/yarn.lock | 12882 ++++++++-------- 248 files changed, 14531 insertions(+), 9058 deletions(-) create mode 100644 .github/workflows/project_actions.yml create mode 100644 ARCHITECTURE.md create mode 100644 openpype/hosts/blender/api/capture.py create mode 100644 openpype/hosts/blender/plugins/create/create_review.py create mode 100644 openpype/hosts/blender/plugins/publish/collect_review.py create mode 100644 openpype/hosts/blender/plugins/publish/extract_playblast.py create mode 100644 openpype/hosts/blender/plugins/publish/extract_thumbnail.py create mode 100644 openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py create mode 100644 openpype/hosts/fusion/plugins/publish/collect_expected_frames.py delete mode 100644 openpype/hosts/fusion/plugins/publish/collect_render_target.py create mode 100644 openpype/hosts/fusion/plugins/publish/collect_renders.py create mode 100644 openpype/hosts/fusion/plugins/publish/extract_render_local.py delete mode 100644 openpype/hosts/fusion/plugins/publish/render_local.py create mode 100644 openpype/hosts/fusion/plugins/publish/validate_expected_frames_existence.py delete mode 100644 openpype/hosts/fusion/scripts/set_rendermode.py create mode 100644 openpype/hosts/max/plugins/create/create_maxScene.py create mode 100644 openpype/hosts/max/plugins/create/create_pointcloud.py create mode 100644 openpype/hosts/max/plugins/load/load_pointcloud.py create mode 100644 openpype/hosts/max/plugins/publish/extract_pointcloud.py create mode 100644 openpype/hosts/max/plugins/publish/increment_workfile_version.py create mode 100644 openpype/hosts/max/plugins/publish/validate_no_max_content.py create mode 100644 openpype/hosts/max/plugins/publish/validate_pointcloud.py create mode 100644 openpype/hosts/maya/plugins/inventory/connect_yeti_rig.py create mode 100644 openpype/hosts/maya/plugins/load/load_image.py create mode 100644 openpype/hosts/maya/plugins/publish/validate_look_color_space.py create mode 100644 openpype/hosts/maya/tools/__init__.py rename openpype/{ => hosts/maya}/tools/mayalookassigner/LICENSE (100%) rename openpype/{ => hosts/maya}/tools/mayalookassigner/__init__.py (100%) rename openpype/{ => hosts/maya}/tools/mayalookassigner/app.py (100%) rename openpype/{ => hosts/maya}/tools/mayalookassigner/commands.py (93%) rename openpype/{ => hosts/maya}/tools/mayalookassigner/models.py (100%) rename openpype/{ => hosts/maya}/tools/mayalookassigner/views.py (100%) rename openpype/{ => hosts/maya}/tools/mayalookassigner/vray_proxies.py (100%) rename openpype/{ => hosts/maya}/tools/mayalookassigner/widgets.py (100%) create mode 100644 openpype/plugins/publish/collect_custom_staging_dir.py create mode 100644 openpype/settings/defaults/project_settings/applications.json create mode 100644 openpype/settings/entities/schemas/projects_schema/schema_project_applications.json create mode 100644 openpype/tools/publisher/widgets/images/save.png rename website/docs/assets/{harmony_creator.PNG => harmony_creator.png} (100%) create mode 100644 website/docs/assets/integrate_kitsu_note_settings.png create mode 100644 website/docs/assets/maya-admin_extract_playblast_settings.png create mode 100644 website/docs/assets/maya-admin_extract_playblast_settings_camera_options.png create mode 100644 website/docs/assets/maya-admin_extract_playblast_settings_viewport_options.png create mode 100644 website/docs/assets/maya-yeti_hair_setup.png create mode 100644 website/docs/assets/maya-yeti_load_connections.png create mode 100644 website/docs/assets/maya-yeti_publish_setup.png delete mode 100644 website/docs/assets/maya-yeti_rig.jpg create mode 100644 website/docs/assets/maya-yeti_rig_setup.png create mode 100644 website/docs/assets/maya-yeti_simple_rig.png create mode 100644 website/docs/project_settings/assets/global_tools_custom_staging_dir.png diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml new file mode 100644 index 00000000000..26bc2b8a1f2 --- /dev/null +++ b/.github/workflows/project_actions.yml @@ -0,0 +1,22 @@ +name: project-actions + +on: + pull_request: + types: [review_requested] + pull_request_review: + types: [submitted] + +jobs: + pr_review_requested: + name: pr_review_requested + runs-on: ubuntu-latest + if: github.event_name == 'pull_request_review' && github.event.review.state == 'changes_requested' + steps: + - name: Move PR to 'Change Requested' + uses: leonsteinhaeuser/project-beta-automations@v2.1.0 + with: + gh_token: ${{ secrets.YNPUT_BOT_TOKEN }} + organization: ynput + project_id: 11 + resource_node_id: ${{ github.event.pull_request.node_id }} + status_value: Change Requested diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 00000000000..912780d803b --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,77 @@ +# Architecture + +OpenPype is a monolithic Python project that bundles several parts, this document will try to give a birds eye overview of the project and, to a certain degree, each of the sub-projects. +The current file structure looks like this: + +``` +. +├── common - Code in this folder is backend portion of Addon distribution logic for v4 server. +├── docs - Documentation of the source code. +├── igniter - The OpenPype bootstrapper, deals with running version resolution and setting up the connection to the mongodb. +├── openpype - The actual OpenPype core package. +├── schema - Collection of JSON files describing schematics of objects. This follows Avalon's convention. +├── tests - Integration and unit tests. +├── tools - Conveninece scripts to perform common actions (in both bash and ps1). +├── vendor - When using the igniter, it deploys third party tools in here, such as ffmpeg. +└── website - Source files for https://openpype.io/ which is Docusaursus (https://docusaurus.io/). +``` + +The core functionality of the pipeline can be found in `igniter` and `openpype`, which in turn rely on the `schema` files, whenever you build (or download a pre-built) version of OpenPype, these two are bundled in there, and `Igniter` is the entry point. + + +## Igniter + +It's the setup and update tool for OpenPype, unless you want to package `openpype` separately and deal with all the config manually, this will most likely be your entry point. + +``` +igniter/ +├── bootstrap_repos.py - Module that will find or install OpenPype versions in the system. +├── __init__.py - Igniter entry point. +├── install_dialog.py- Show dialog for choosing central pype repository. +├── install_thread.py - Threading helpers for the install process. +├── __main__.py - Like `__init__.py` ? +├── message_dialog.py - Qt Dialog with a message and "Ok" button. +├── nice_progress_bar.py - Fancy Qt progress bar. +├── splash.txt - ASCII art for the terminal installer. +├── stylesheet.css - Installer Qt styles. +├── terminal_splash.py - Terminal installer animation, relies in `splash.txt`. +├── tools.py - Collection of methods that don't fit in other modules. +├── update_thread.py - Threading helper to update existing OpenPype installs. +├── update_window.py - Qt UI to update OpenPype installs. +├── user_settings.py - Interface for the OpenPype user settings. +└── version.py - Igniter's version number. +``` + +## OpenPype + +This is the main package of the OpenPype logic, it could be loosely described as a combination of [Avalon](https://getavalon.github.io), [Pyblish](https://pyblish.com/) and glue around those with custom OpenPype only elements, things are in progress of being moved around to better prepare for V4, which will be released under a new name AYON. + +``` +openpype/ +├── client - Interface for the MongoDB. +├── hooks - Hooks to be executed on certain OpenPype Applications defined in `openpype.lib.applications`. +├── host - Base class for the different hosts. +├── hosts - Integration with the different DCCs (hosts) using the `host` base class. +├── lib - Libraries that stitch together the package, some have been moved into other parts. +├── modules - OpenPype modules should contain separated logic of specific kind of implementation, such as Ftrack connection and its python API. +├── pipeline - Core of the OpenPype pipeline, handles creation of data, publishing, etc. +├── plugins - Global/core plugins for loader and publisher tool. +├── resources - Icons, fonts, etc. +├── scripts - Loose scipts that get run by tools/publishers. +├── settings - OpenPype settings interface. +├── style - Qt styling. +├── tests - Unit tests. +├── tools - Core tools, check out https://openpype.io/docs/artist_tools. +├── vendor - Vendoring of needed required Python packes. +├── widgets - Common re-usable Qt Widgets. +├── action.py - LEGACY: Lives now in `openpype.pipeline.publish.action` Pyblish actions. +├── cli.py - Command line interface, leverages `click`. +├── __init__.py - Sets two constants. +├── __main__.py - Entry point, calls the `cli.py` +├── plugin.py - Pyblish plugins. +├── pype_commands.py - Implementation of OpenPype commands. +└── version.py - Current version number. +``` + + + diff --git a/CHANGELOG.md b/CHANGELOG.md index c7ecbc83bf0..4e22b783c4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,1779 @@ # Changelog +## [3.15.3](https://github.com/ynput/OpenPype/tree/3.15.3) + + +[Full Changelog](https://github.com/ynput/OpenPype/compare/3.15.2...3.15.3) + +### **🆕 New features** + + +
    +Blender: Extract Review #3616 + +Added Review to Blender. + +This implementation is based on #3508 but made compatible for the current implementation of OpenPype for Blender. + + +___ + +
    + + +
    +Data Exchanges: Point Cloud for 3dsMax #4532 + +Publish PRT format with tyFlow in 3dsmax + +Publish PRT format with tyFlow in 3dsmax and possibly set up loader to load the format too. +- [x] creator +- [x] extractor +- [x] validator +- [x] loader + + +___ + +
    + + +
    +Global: persistent staging directory for renders #4583 + +Allows configure if staging directory (`stagingDir`) should be persistent with use of profiles. + +With this feature, users can specify a transient data folder path based on presets, which can be used during the creation and publishing stages. In some cases, these DCCs automatically add a rendering path during the creation stage, which is then used in publishing.One of the key advantages of this feature is that it allows users to take advantage of faster storages for rendering, which can help improve workflow efficiency. Additionally, this feature allows users to keep their rendered data persistent, and use their own infrastructure for regular cleaning.However, it should be noted that some productions may want to use this feature without persistency. Furthermore, there may be a need for retargeting the rendering folder to faster storages, which is also not supported at the moment.It is studio responsibility to clean up obsolete folders with data.Location of the folder is configured in `project_anatomy/templates/others`. ('transient' key is expected, with 'folder' key, could be more templates)Which family/task type/subset is applicable is configured in:`project_settings/global/tools/publish/transient_dir_profiles` + + +___ + +
    + + +
    +Kitsu custom comment template #4599 + +Kitsu allows to write markdown in its comment field. This can be something very powerful to deliver dynamic comments with the help the data from the instance.This feature is defaults to off so the admin have to manually set up the comment field the way they want.I have added a basic example on how the comment can look like as the comment-fields default value.To this I want to add some documentation also but that's on its way when the code itself looks good for the reviewers. + + +___ + +
    + + +
    +MaxScene Family #4615 + +Introduction of the Max Scene Family + + +___ + +
    + +### **🚀 Enhancements** + + +
    +Maya: Multiple values on single render attribute - OP-4131 #4631 + +When validating render attributes, this adds support for multiple values. When repairing first value in list is used. + + +___ + +
    + + +
    +Maya: enable 2D Pan/Zoom for playblasts - OP-5213 #4687 + +Setting for enabling 2D Pan/Zoom on reviews. + + +___ + +
    + + +
    +Copy existing or generate new Fusion profile on prelaunch #4572 + +Fusion preferences will be copied to the predefined `~/.openpype/hosts/fusion/prefs` folder (or any other folder set in system settings) on launch. + +The idea is to create a copy of existing Fusion profile, adding an OpenPype menu to the Fusion instance.By default the copy setting is turned off, so no file copying is performed. Instead the clean Fusion profile is created by Fusion in the predefined folder. The default locaion is set to `~/.openpype/hosts/fusion/prefs`, to better comply with the other os platforms. After creating the default profile, some modifications are applied: +- forced Python3 +- forced English interface +- setup Openpype specific path maps.If the `copy_prefs` checkbox is toggled, a copy of existing Fusion profile folder will be placed in the mentioned location. Then they are altered the same way as described above. The operation is run only once, on the first launch, unless the `force_sync [Resync profile on each launch]` is toggled.English interface is forced because the `FUSION16_PROFILE_DIR` environment variable is not read otherwise (seems to be a Fusion bug). + + +___ + +
    + + +
    +Houdini: Create button open new publisher's "create" tab #4601 + +During a talk with @maxpareschi he mentioned that the new publisher in Houdini felt super confusing due to "Create" going to the older creator but now being completely empty and the publish button directly went to the publish tab.This resolves that by fixing the Create button to now open the new publisher but on the Create tab.Also made publish button enforce going to the "publish" tab for consistency in usage.@antirotor I think changing the Create button's callback was just missed in this commit or was there a specific reason to not change that around yet? + + +___ + +
    + + +
    +Clockify: refresh and fix the integration #4607 + +Due to recent API changes, Clockify requires `user_id` to operate with the timers. I updated this part and currently it is a WIP for making it fully functional. Most functions, such as start and stop timer, and projects sync are currently working. For the rate limiting task new dependency is added: https://pypi.org/project/ratelimiter/ + + +___ + +
    + + +
    +Fusion publish existing frames #4611 + +This PR adds the function to publish existing frames instead of having to re-render all of them for each new publish.I have split the render_locally plugin so the review-part is its own plugin now.I also change the saver-creator-plugin's label from Saver to Render (saver) as I intend to add a Prerender creator like in Nuke. + + +___ + +
    + + +
    +Resolution settings referenced from DB record for 3dsMax #4652 + +- Add Callback for setting the resolution according to DB after the new scene is created. +- Add a new Action into openpype menu which allows the user to reset the resolution in 3dsMax + + +___ + +
    + + +
    +3dsmax: render instance settings in Publish tab #4658 + +Allows user preset the pools, group and use_published settings in Render Creator in the Max Hosts.User can set the settings before or after creating instance in the new publisher + + +___ + +
    + + +
    +scene length setting referenced from DB record for 3dsMax #4665 + +Setting the timeline length based on DB record in 3dsMax Hosts + + +___ + +
    + + +
    +Publisher: Windows reduce command window pop-ups during Publishing #4672 + +Reduce the command line pop-ups that show on Windows during publishing. + + +___ + +
    + + +
    +Publisher: Explicit save #4676 + +Publisher have explicit button to save changes, so reset can happen without saving any changes. Save still happens automatically when publishing is started or on publisher window close. But a popup is shown if context of host has changed. Important context was enhanced by workfile path (if host integration supports it) so workfile changes are captured too. In that case a dialog with confirmation is shown to user. All callbacks that may require save of context were moved to main window to be able handle dialog show at one place. Save changes now returns success so the rest of logic is skipped -> publishing won't start, when save of instances fails.Save and reset buttons have shortcuts (Ctrl + s and Ctrls + r). + + +___ + +
    + + +
    +CelAction: conditional workfile parameters from settings #4677 + +Since some productions were requesting excluding some workfile parameters from publishing submission, we needed to move them to settings so those could be altered per project. + + +___ + +
    + + +
    +Improve logging of used app + tool envs on application launch #4682 + +Improve logging of what apps + tool environments got loaded for an application launch. + + +___ + +
    + + +
    +Fix name and docstring for Create Workdir Extra Folders prelaunch hook #4683 + +Fix class name and docstring for Create Workdir Extra Folders prelaunch hookThe class name and docstring were originally copied from another plug-in and didn't match the plug-in logic.This also fixes potentially seeing this twice in your logs. Before:After:Where it was actually running both this prelaunch hook and the actual `AddLastWorkfileToLaunchArgs` plugin. + + +___ + +
    + + +
    +Application launch context: Include app group name in logger #4684 + +Clarify in logs better what app group the ApplicationLaunchContext belongs to and what application is being launched.Before:After: + + +___ + +
    + + +
    +increment workfile version 3dsmax #4685 + +increment workfile version in 3dsmax as if in blender and maya hosts. + + +___ + +
    + +### **🐛 Bug fixes** + + +
    +Maya: Fix getting non-active model panel. #2968 + +When capturing multiple cameras with image planes that have file sequences playing, only the active (first) camera will play through the file sequence. + + +___ + +
    + + +
    +Maya: Fix broken review publishing. #4549 + +Resolves #4547 + + +___ + +
    + + +
    +Maya: Avoid error on right click in Loader if `mtoa` is not loaded #4616 + +Fix an error on right clicking in the Loader when `mtoa` is not a loaded plug-in.Additionally if `mtoa` isn't loaded the loader will now load the plug-in before trying to create the arnold standin. + + +___ + +
    + + +
    +Maya: Fix extract look colorspace detection #4618 + +Fix the logic which guesses the colorspace using `arnold` python library. +- Previously it'd error if `mtoa` was not available on path so it still required `mtoa` to be available. +- The guessing colorspace logic doesn't actually require `mtoa` to be loaded, but just the `arnold` python library to be available. This changes the logic so it doesn't require the `mtoa` plugin to get loaded to guess the colorspace. +- The if/else branch was likely not doing what was intended `cmds.loadPlugin("mtoa", quiet=True)` returns None if the plug-in was already loaded. So this would only ever be true if it ends up loading the `mtoa` plugin the first time. +```python +# Tested in Maya 2022.1 +print(cmds.loadPlugin("mtoa", quiet=True)) +# ['mtoa'] +print(cmds.loadPlugin("mtoa", quiet=True)) +# None +``` + + +___ + +
    + + +
    +Maya: Maya Playblast Options overrides - OP-3847 #4634 + +When publishing a review in Maya, the extractor would fail due to wrong (long) panel name. + + +___ + +
    + + +
    +Bugfix/op 2834 fix extract playblast #4701 + +Paragraphs contain detailed information on the changes made to the product or service, providing an in-depth description of the updates and enhancements. They can be used to explain the reasoning behind the changes, or to highlight the importance of the new features. Paragraphs can often include links to further information or support documentation. + + +___ + +
    + + +
    +Bugfix/op 2834 fix extract playblast #4704 + +Paragraphs contain detailed information on the changes made to the product or service, providing an in-depth description of the updates and enhancements. They can be used to explain the reasoning behind the changes, or to highlight the importance of the new features. Paragraphs can often include links to further information or support documentation. + + +___ + +
    + + +
    +Maya: bug fix for passing zoom settings if review is attached to subset #4716 + +Fix for attaching review to subset with pan/zoom option. + + +___ + +
    + + +
    +Maya: tile assembly fail in draft - OP-4820 #4416 + +Tile assembly in Deadline was broken. + +Initial bug report revealed other areas of the tile assembly that needed fixing. + + +___ + +
    + + +
    +Maya: Yeti Validate Rig Input - OP-3454 #4554 + +Fix Yeti Validate Rig Input + +Existing workflow was broken due to this #3297. + + +___ + +
    + + +
    +Scene inventory: Fix code errors when "not found" entries are found #4594 + +Whenever a "NOT FOUND" entry is present a lot of errors happened in the Scene Inventory: +- It started spamming a lot of errors for the VersionDelegate since it had no numeric version (no version at all).Error reported on Discord: +```python +Traceback (most recent call last): + File "C:\Users\videopro\Documents\github\OpenPype\openpype\tools\utils\delegates.py", line 65, in paint + text = self.displayText( + File "C:\Users\videopro\Documents\github\OpenPype\openpype\tools\utils\delegates.py", line 33, in displayText + assert isinstance(value, numbers.Integral), ( +AssertionError: Version is not integer. "None" +``` +- Right click menu would error on NOT FOUND entries, and thus not show. With this PR it will now _disregard_ not found items for "Set version" and "Remove" but still allow actions.This PR resolves those. + + +___ + +
    + + +
    +Kitsu: Sync OP with zou, make sure value-data is int or float #4596 + +Currently the data zou pulls is a string and not a value causing some bugs in the pipe where a value is expected (like `Set frame range` in Fusion). + + + +This PR makes sure each value is set with int() or float() so these bugs can't happen later on. + + + +_(A request to cgwire has also bin sent to allow force values only for some metadata columns, but currently the user can enter what ever they want in there)_ + + +___ + +
    + + +
    +Max: fix the bug of removing an instance #4617 + +fix the bug of removing an instance in 3dsMax + + +___ + +
    + + +
    +Global | Nuke: fixing farm publishing workflow #4623 + +After Nuke had adopted new publisher with new creators new issues were introduced. Those issues were addressed with this PR. Those are for example broken reviewable video files publishing if published via farm. Also fixed local publishing. + + +___ + +
    + + +
    +Ftrack: Ftrack additional families filtering #4633 + +Ftrack family collector makes sure the subset family is also in instance families for additional families filtering. + + +___ + +
    + + +
    +Ftrack: Hierarchical <> Non-Hierarchical attributes sync fix #4635 + +Sync between hierarchical and non-hierarchical attributes should be fixed and work as expected. Action should sync the values as expected and event handler should do it too and only on newly created entities. + + +___ + +
    + + +
    +bugfix for 3dsmax publishing error #4637 + +fix the bug of failing publishing job in 3dsMax + + +___ + +
    + + +
    +General: Use right validation for ffmpeg executable #4640 + +Use ffmpeg exec validation for ffmpeg executables instead of oiio exec validation. The validation is used as last possible source of ffmpeg from `PATH` environment variables, which is an edge case but can cause issues. + + +___ + +
    + + +
    +3dsmax: opening last workfile #4644 + +Supports opening last saved workfile in 3dsmax host. + + +___ + +
    + + +
    +Fixed a bug where a QThread in the splash screen could be destroyed before finishing execution #4647 + +This should fix the occasional behavior of the QThread being destroyed before even its worker returns from the `run()` function.After quiting, it should wait for the QThread object to properly close itself. + + +___ + +
    + + +
    +General: Use right plugin class for Collect Comment #4653 + +Collect Comment plugin is instance plugin so should inherit from `InstancePlugin` instead of `ContextPlugin`. + + +___ + +
    + + +
    +Global: add tags field to thumbnail representation #4660 + +Thumbnail representation might be missing tags field. + + +___ + +
    + + +
    +Integrator: Enforce unique destination transfers, disallow overwrites in queued transfers #4662 + +Fix #4656 by enforcing unique destination transfers in the Integrator. It's now disallowed to a destination in the file transaction queue with a new source path during the publish. + + +___ + +
    + + +
    +Hiero: Creator with correct workfile numeric padding input #4666 + +Creator was showing 99 in workfile input for long time, even if users set default value to 1001 in studio settings. This has been fixed now. + + +___ + +
    + + +
    +Nuke: Nukenodes family instance without frame range #4669 + +No need to add frame range data into `nukenodes` (backdrop) family publishes - since those are timeless. + + +___ + +
    + + +
    +TVPaint: Optional Validation plugins can be de/activated by user #4674 + +Added `OptionalPyblishPluginMixin` to TVpaint plugins that can be optional. + + +___ + +
    + + +
    +Kitsu: Slightly less strict with instance data #4678 + +- Allow to take task name from context if asset doesn't have any. Fixes an issue with Photoshop's review instance not having `task` in data. +- Allow to match "review" against both `instance.data["family"]` and `instance.data["families"]` because some instances don't have the primary family in families, e.g. in Photoshop and TVPaint. +- Do not error on Integrate Kitsu Review whenever for whatever reason Integrate Kitsu Note did not created a comment but just log the message that it was unable to connect a review. + + +___ + +
    + + +
    +Publisher: Fix reset shortcut sequence #4694 + +Fix bug created in https://github.com/ynput/OpenPype/pull/4676 where key sequence is checked using unsupported method. The check was changed to convert event into `QKeySequence` object which can be compared to prepared sequence. + + +___ + +
    + + +
    +Refactor _capture #4702 + +Paragraphs contain detailed information on the changes made to the product or service, providing an in-depth description of the updates and enhancements. They can be used to explain the reasoning behind the changes, or to highlight the importance of the new features. Paragraphs can often include links to further information or support documentation. + + +___ + +
    + + +
    +Hiero: correct container colors if UpToDate #4708 + +Colors on loaded containers are now correctly identifying real state of version. `Red` for out of date and `green` for up to date. + + +___ + +
    + +### **🔀 Refactored code** + + +
    +Look Assigner: Move Look Assigner tool since it's Maya only #4604 + +Fix #4357: Move Look Assigner tool to maya since it's Maya only + + +___ + +
    + + +
    +Maya: Remove unused functions from Extract Look #4671 + +Remove unused functions from Maya Extract Look plug-in + + +___ + +
    + + +
    +Extract Review code refactor #3930 + +Trying to reduce complexity of Extract Review plug-in +- Re-use profile filtering from lib +- Remove "combination families" additional filtering which supposedly was from OP v2 +- Simplify 'formatting' for filling gaps +- Use `legacy_io.Session` over `os.environ` + + +___ + +
    + + +
    +Maya: Replace last usages of Qt module #4610 + +Replace last usage of `Qt` module with `qtpy`. This change is needed for `PySide6` support. All changes happened in Maya loader plugins. + + +___ + +
    + + +
    +Update tests and documentation for `ColormanagedPyblishPluginMixin` #4612 + +Refactor `ExtractorColormanaged` to `ColormanagedPyblishPluginMixin` in tests and documentation. + + +___ + +
    + + +
    +Improve logging of used app + tool envs on application launch (minor tweak) #4686 + +Use `app.full_name` for change done in #4682 + + +___ + +
    + +### **📃 Documentation** + + +
    +Docs/add architecture document #4344 + +Add `ARCHITECTURE.md` document. + +his document attemps to give a quick overview of the project to help onboarding, it's not an extensive documentation but more of a elevator pitch one-line descriptions of files/directories and what the attempt to do. + + +___ + +
    + + +
    +Documentation: Tweak grammar and fix some typos #4613 + +This resolves some grammar and typos in the documentation.Also fixes the extension of some images in after effects docs which used uppercase extension even though files were lowercase extension. + + +___ + +
    + + +
    +Docs: Fix some minor grammar/typos #4680 + +Typo/grammar fixes in documentation. + + +___ + +
    + +### **Merged pull requests** + + +
    +Maya: Implement image file node loader #4313 + +Implements a loader for loading texture image into a `file` node in Maya. + +Similar to Maya's hypershade creation of textures on load you have the option to choose for three modes of creating: +- Texture +- Projection +- StencilThese should match what Maya generates if you create those in Maya. +- [x] Load and manage file nodes +- [x] Apply color spaces after #4195 +- [x] Support for _either_ UDIM or image sequence - currently it seems to always load sequences as UDIM automatically. +- [ ] Add support for animation sequences of UDIM textures using the `..exr` path format? + + +___ + +
    + + +
    +Maya Look Assigner: Don't rely on containers for get all assets #4600 + +This resolves #4044 by not actually relying on containers in the scene but instead just rely on finding nodes with `cbId` attributes. As such, imported nodes would also be found and a shader can be assigned (similar to when using get from selection).**Please take into consideration the potential downsides below**Potential downsides would be: +- IF an already loaded look has any dagNodes, say a 3D Projection node - then that will also show up as a loaded asset where previously nodes from loaded looks were ignored. +- If any dag nodes were created locally - they would have gotten `cbId` attributes on scene save and thus the current asset would almost always show? + + +___ + +
    + + +
    +Maya: Unify menu labels for "Set Frame Range" and "Set Resolution" #4605 + +Fix #4109: Unify menu labels for "Set Frame Range" and "Set Resolution"This also tweaks it in Houdini from Reset Frame Range to Set Frame Range. + + +___ + +
    + + +
    +Resolve missing OPENPYPE_MONGO in deadline global job preload #4484 + +In the GlobalJobPreLoad plugin, we propose to replace the SpawnProcess by a sub-process and to pass the environment variables in the parameters, since the SpawnProcess under Centos Linux does not pass the environment variables. + +In the GlobalJobPreLoad plugin, the Deadline SpawnProcess is used to start the OpenPype process. The problem is that the SpawnProcess does not pass environment variables, including OPENPYPE_MONGO, to the process when it is under Centos7 linux, and the process gets stuck. We propose to replace it by a subprocess and to pass the variable in the parameters. + + +___ + +
    + + +
    +Tests: Added setup_only to tests #4591 + +Allows to download test zip, unzip and restore DB in preparation for new test. + + +___ + +
    + + +
    +Maya: Arnold don't reset maya timeline frame range on render creation (or setting render settings) #4603 + +Fix #4429: Do not reset fps or playback timeline on applying or creating render settings + + +___ + +
    + + +
    +Bump @sideway/formula from 3.0.0 to 3.0.1 in /website #4609 + +Bumps [@sideway/formula](https://github.com/sideway/formula) from 3.0.0 to 3.0.1. +
    +Commits + +
    +
    +Maintainer changes +

    This version was pushed to npm by marsup, a new releaser for @​sideway/formula since your current version.

    +
    +
    + + +[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@sideway/formula&package-manager=npm_and_yarn&previous-version=3.0.0&new-version=3.0.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) + +Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. + +[//]: # (dependabot-automerge-start) +[//]: # (dependabot-automerge-end) + +--- + +
    +Dependabot commands and options +
    + +You can trigger Dependabot actions by commenting on this PR: +- `@dependabot rebase` will rebase this PR +- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it +- `@dependabot merge` will merge this PR after your CI passes on it +- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it +- `@dependabot cancel merge` will cancel a previously requested merge and block automerging +- `@dependabot reopen` will reopen this PR if it is closed +- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually +- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) +- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) +- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) +- `@dependabot use these labels` will set the current labels as the default for future PRs for this repo and language +- `@dependabot use these reviewers` will set the current reviewers as the default for future PRs for this repo and language +- `@dependabot use these assignees` will set the current assignees as the default for future PRs for this repo and language +- `@dependabot use this milestone` will set the current milestone as the default for future PRs for this repo and language + +You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/ynput/OpenPype/network/alerts). + +
    +___ + +
    + + +
    +Update artist_hosts_maya_arnold.md #4626 + +Correct Arnold docs. +___ + +
    + + +
    +Maya: Add "Include Parent Hierarchy" option in animation creator plugin #4645 + +Add an option in Project Settings > Maya > Creator Plugins > Create Animation to include (or not) parent hierarchy. This is to avoid artists to check manually the option for all create animation. + + +___ + +
    + + +
    +General: Filter available applications #4667 + +Added option to filter applications that don't have valid executable available in settings in launcher and ftrack actions. This option can be disabled in new settings category `Applications`. The filtering is by default disabled. + + +___ + +
    + + +
    +3dsmax: make sure that startup script executes #4695 + +Fixing reliability of OpenPype startup in 3dsmax. + + +___ + +
    + + +
    +Project Manager: Change minimum frame start/end to '0' #4719 + +Project manager can have frame start/end set to `0`. + + +___ + +
    + + + +## [3.15.2](https://github.com/ynput/OpenPype/tree/3.15.2) + +[Full Changelog](https://github.com/ynput/OpenPype/compare/3.15.1...3.15.2) + +### **🆕 New features** + + +
    +maya gltf texture convertor and validator #4261 + +Continuity of the gltf extractor implementation + +Continuity of the gltf extractor https://github.com/pypeclub/OpenPype/pull/4192UPDATE:**Validator for GLSL Shader**: Validate whether the mesh uses GLSL Shader. If not it will error out. The user can choose to perform the repair action and it will help to assign glsl shader. If the mesh with Stringray PBS, the repair action will also check to see if there is any linked texture such as Color, Occulsion, and Normal Map. If yes, it will help to relink the related textures to the glsl shader.*****If the mesh uses the PBS Shader, + + +___ + +
    + + +
    +Unreal: New Publisher #4370 + +Implementation of the new publisher for Unreal. + +The implementation of the new publisher for Unreal. This PR includes the changes for all the existing creators to be compatible with the new publisher.The basic creator has been split in two distinct creators: +- `UnrealAssetCreator`, works with assets in the Content Browser. +- `UnrealActorCreator` that works with actors in the scene. + + +___ + +
    + + +
    +Implementation of a new splash screen #4592 + +Implemented a new splash screen widget to reflect a process running in the background. This widget can be used for other tasks than UE. **Also fixed the compilation error of the AssetContainer.cpp when trying to build the plugin in UE 5.0** + + +___ + +
    + + +
    +Deadline for 3dsMax #4439 + +Setting up deadline for 3dsmax + +Setting up deadline for 3dsmax by setting render outputs and viewport camera + + +___ + +
    + + +
    +Nuke: adding nukeassist #4494 + +Adding support for NukeAssist + +For support of NukeAssist we had to limit some Nuke features since NukeAssist itself Nuke with limitations. We do not support Creator and Publisher. User can only Load versions with version control. User can also set Framerange and Colorspace. + + +___ + +
    + +### **🚀 Enhancements** + + +
    +Maya: OP-2630 acescg maya #4340 + +Resolves #2712 + + +___ + +
    + + +
    +Default Ftrack Family on RenderLayer #4458 + +With default settings, renderlayers in Maya were not being tagged with the Ftrack family leading to confusion when doing reviews. + + +___ + +
    + + +
    +Maya: Maya Playblast Options - OP-3783 #4487 + +Replacement PR for #3912. Adds more options for playblasts to preferences/settings. + +Adds the following as options in generating playblasts, matching viewport settings. +- Use default material +- Wireframe on shaded +- X-ray +- X-ray Joints +- X-ray active component + + +___ + +
    + + +
    +Maya: Passing custom attributes to alembic - OP-4111 #4516 + +Passing custom attributes to alembic + +This PR makes it possible to pass all user defined attributes along to the alembic representation. + + +___ + +
    + + +
    +Maya: Options for VrayProxy output - OP-2010 #4525 + +Options for output of VrayProxy. + +Client requested more granular control of output from VrayProxy instance. Exposed options on the instance and settings for vrmesh and alembic. + + +___ + +
    + + +
    +Maya: Validate missing instance attributes #4559 + +Validate missing instance attributes. + +New attributes can be introduced as new features come in. Old instances will need to be updated with these attributes for the documentation to make sense, and users do not have to recreate the instances. + + +___ + +
    + + +
    +Refactored Generation of UE Projects, installation of plugins moved to the engine #4369 + +Improved the way how OpenPype works with generation of UE projects. Also the installation of the plugin has been altered to install into the engine + +OpenPype now uses the appropriate tools to generate UE projects. Unreal Build Tool (UBT) and a "Commandlet Project" is needed to properly generate a BP project, or C++ code in case that `dev_mode = True`, folders, the .uproject file and many other resources.On the plugin's side, it is built seperately with the UnrealAutomationTool (UAT) and then it's contents are moved under the `Engine/Plugins/Marketplace/OpenPype` directory. + + +___ + +
    + + +
    +Unreal: Use client functions in Layout loader #4578 + +Use 'get_representations' instead of 'legacy_io' query in layout loader. + +This is removing usage of `find_one` called on `legacy_io` and use rather client functions as preparation for AYON connection. Also all representations are queried at once instead of one by one. + + +___ + +
    + + +
    +General: Support for extensions filtering in loaders #4492 + +Added extensions filtering support to loader plugins. + +To avoid possible backwards compatibility break is filtering exactly the same and filtering by extensions is enabled only if class attribute 'extensions' is set. + + +___ + +
    + + +
    +Nuke: multiple reformat in baking review profiles #4514 + +Added support for multiple reformat nodes in baking profiles. + +Old settings for single reformat node is supported and prioritised just in case studios are using it and backward compatibility is needed. Warnings in Nuke terminal are notifying users to switch settings to new workflow. Settings are also explaining the migration way. + + +___ + +
    + + +
    +Nuke: Add option to use new creating system in workfile template builder #4545 + +Nuke workfile template builder can use new creators instead of legacy creators. + +Modified workfile template builder to have option to say if legacy creators should be used or new creators. Legacy creators are disabled by default, so Maya has changed the value. + + +___ + +
    + + +
    +Global, Nuke: Workfile first version with template processing #4579 + +Supporting new template workfile builder with toggle for creation of first version of workfile in case there is none yet. + + +___ + +
    + + +
    +Fusion: New Publisher #4523 + +This is an updated PR for @BigRoy 's old PR (https://github.com/ynput/OpenPype/pull/3892).I have merged it with code from OP 3.15.1-nightly.6 and made sure it works as expected.This converts the old publishing system to the new one. It implements Fusion as a new host addon. + + +- Create button removed in OpenPype menu in favor of the new Publisher +- Draft refactor validations to raise PublishValidationError +- Implement Creator for New Publisher +- Implement Fusion as Host addon + + +___ + +
    + + +
    +TVPaint: Use Publisher tool #4471 + +Use Publisher tool and new creation system in TVPaint integration. + +Using new creation system makes TVPaint integration a little bit easier to maintain for artists. Removed unneeded tools Creator and Subset Manager tools. Goal is to keep the integration work as close as possible to previous integration. Some changes were made but primarilly because they were not right using previous system.All creators create instance with final family instead of changing the family during extraction. Render passes are not related to group id but to render layer instance. Render layer is still related to group. Workfile, review and scene render instances are created using autocreators instead of auto-collection during publishing. Subset names are fully filled during publishing but instance labels are filled on refresh with the last known right value. Implemented basic of legacy convertor which should convert render layers and render passes. + + +___ + +
    + + +
    +TVPaint: Auto-detect render creation #4496 + +Create plugin which will create Render Layer and Render Pass instances based on information in the scene. + +Added new creator that must be triggered by artist. The create plugin will first create Render Layer instances if were not created yet. For variant is used color group name. The creator has option to rename color groups by template defined in settings -> Template may use index of group by it's usage in scene (from bottom to top). After Render Layers will create Render Passes. Render Pass is created for each individual TVPaint layer in any group that had created Render Layer. It's name is used as variant (pass). + + +___ + +
    + + +
    +TVPaint: Small enhancements #4501 + +Small enhancements in TVPaint integration which did not get to https://github.com/ynput/OpenPype/pull/4471. + +It was found out that `opacity` returned from `tv_layerinfo` is always empty and is dangerous to add it to layer information. Added information about "current" layer to layers information. Disable review of Render Layer and Render Pass instances by default. In most of productions is used only "scene review". Skip usage of `"enabled"` key from settings in automated layer/pass creation. + + +___ + +
    + + +
    +Global: color v3 global oiio transcoder plugin #4291 + +Implements possibility to use `oiiotool` to transcode image sequences from one color space to another(s). + +Uses collected `colorspaceData` information about source color spaces, these information needs to be collected previously in each DCC interested in color management.Uses profiles configured in Settings to create single or multiple new representations (and file extensions) with different color spaces.New representations might replace existing one, each new representation might contain different tags and custom tags to control its integration step. + + +___ + +
    + + +
    +Deadline: Added support for multiple install dirs in Deadline #4451 + +SearchDirectoryList returns FIRST existing so if you would have multiple OP install dirs, it won't search for appropriate version in later ones. + + +___ + +
    + + +
    +Ftrack: Upload reviewables with original name #4483 + +Ftrack can integrate reviewables with original filenames. + +As ftrack have restrictions about names of components the only way how to achieve the result was to upload the same file twice, one with required name and one with origin name. + + +___ + +
    + + +
    +TVPaint: Ignore transparency in Render Pass #4499 + +It is possible to ignore layers transparency during Render Pass extraction. + +Render pass extraction does not respect opacity of TVPaint layers set in scene during extraction. It can be enabled/disabled in settings. + + +___ + +
    + + +
    +Anatomy: Preparation for different root overrides #4521 + +Prepare Anatomy to handle only 'studio' site override on it's own. + +Change how Anatomy fill root overrides based on requested site name. The logic which decide what is active site was moved to sync server addon and the same for receiving root overrides of local site. The Anatomy resolve only studio site overrides anything else is handled by sync server. BaseAnatomy only expect root overrides value and does not need site name. Validation of site name happens in sync server same as resolving if site name is local or not. + + +___ + +
    + + +
    +Nuke | Global: colormanaged plugin in collection #4556 + +Colormanaged extractor had changed to Mixin class so it can be added to any stage of publishing rather then just to Exctracting.Nuke is no collecting colorspaceData to representation collected on already rendered images. + +Mixin class can no be used as secondary parent in publishing plugins. + + +___ + +
    + +### **🐛 Bug fixes** + + +
    +look publishing and srgb colorspace in maya #4276 + +Check the OCIO color management is enabled before doing linearize colorspace for converting the texture maps into tx files. + +Check whether the OCIO color management is enabled before the condition of converting the texture to tx extension. + + +___ + +
    + + +
    +Maya: extract Thumbnail "No active model panel found" - OP-3849 #4421 + +Error when extracting playblast with no model panel. + +If `project_settings/maya/publish/ExtractPlayblast/capture_preset/Viewport Options/override_viewport_options` were off and publishing without showing any model panel, the extraction would fail. + + +___ + +
    + + +
    +Maya: Fix setting scene fps with float input #4488 + +Returned value of float fps on integer values would return float. + +This PR fixes the case when switching between integer fps values for example 24 > 25. Issue was when setting the scene fps, the original float value was used which makes it unpredictable whether the value is float or integer when mapping the fps values. + + +___ + +
    + + +
    +Maya: Multipart fix #4497 + +Fix multipart logic in render products. + +Each renderer has a different way of defining whether output images is multipart, so we need to define it for each renderer. Also before the `multipart` class variable was defined multiple times in several places, which made it tricky to debug where `multipart` was defined. Now its created on initialization and referenced as `self.multipart` + + +___ + +
    + + +
    +Maya: Set pool on tile assembly - OP-2012 #4520 + +Set pool on tile assembly + +Pool for publishing and tiling jobs, need to use the settings (`project_settings/deadline/publish/ProcessSubmittedJobOnFarm/deadline_pool`) else fallback on primary pool (`project_settings/deadline/publish/CollectDeadlinePools/primary_pool`) + + +___ + +
    + + +
    +Maya: Extract review with handles #4527 + +Review was not extracting properly with/without handles. + +Review instance was not created properly resulting in the frame range on the instance including handles. + + +___ + +
    + + +
    +Maya: Fix broken lib. #4529 + +Fix broken lib. + +This commit from this PR broke the Maya lib module. + + +___ + +
    + + +
    +Maya: Validate model name - OP-4983 #4539 + +Validate model name issues. + +Couple of issues with validate model name; +- missing platform extraction from settings +- map function should be list comprehension +- code cosmetics + + +___ + +
    + + +
    +Maya: SkeletalMesh family loadable as reference #4573 + +In Maya, fix the SkeletalMesh family not loadable as reference. + + +___ + +
    + + +
    +Unreal: fix loaders because of missing AssetContainer #4536 + +Fixing Unreal loaders, where changes in OpenPype Unreal integration plugin deleted AssetContainer. + +`AssetContainer` and `AssetContainerFactory` are still used to mark loaded instances. Because of optimizations in Integration plugin we've accidentally removed them but that broke loader. + + +___ + +
    + + +
    +3dsmax unable to delete loaded asset in the scene inventory #4507 + +Fix the bug of being unable to delete loaded asset in the Scene Inventory + +Fix the bug of being unable to delete loaded asset in the Scene Inventory + + +___ + +
    + + +
    +Hiero/Nuke: originalBasename editorial publishing and loading #4453 + +Publishing and loading `originalBasename` is working as expected + +Frame-ranges on version document is now correctly defined to fit original media frame range which is published. It means loading is now correctly identifying frame start and end on clip loader in Nuke. + + +___ + +
    + + +
    +Nuke: Fix workfile template placeholder creation #4512 + +Template placeholder creation was erroring out in Nuke due to the Workfile template builder not being able to find any of the plugins for the Nuke host. + +Move `get_workfile_build_placeholder_plugins` function to NukeHost class as workfile template builder expects. + + +___ + +
    + + +
    +Nuke: creator farm attributes from deadline submit plugin settings #4519 + +Defaults in farm attributes are sourced from settings. + +Settings for deadline nuke submitter are now used during nuke render and prerender creator plugins. + + +___ + +
    + + +
    +Nuke: fix clip sequence loading #4574 + +Nuke is loading correctly clip from image sequence created without "{originalBasename}" token in anatomy template. + + +___ + +
    + + +
    +Fusion: Fix files collection and small bug-fixes #4423 + +Fixed Fusion review-representation and small bug-fixes + +This fixes the problem with review-file generation that stopped the publishing on second publish before the fix.The problem was that Fusion simply looked at all the files in the render-folder instead of only gathering the needed frames for the review.Also includes a fix to get the handle start/end that before throw an error if the data didn't exist (like from a kitsu sync). + + +___ + +
    + + +
    +Fusion: Updated render_local.py to not only process the first instance #4522 + +Moved the `__hasRun` to `render_once()` so the check only happens with the rendering. Currently only the first render node gets the representations added.Critical PR + + +___ + +
    + + +
    +Fusion: Load sequence fix filepath resolving from representation #4580 + +Resolves issue mentioned on discord by @movalex:The loader was incorrectly trying to find the file in the publish folder which resulted in just picking 'any first file'. + +This gets the filepath from representation instead of taking the first file from listing files from publish folder. + + +___ + +
    + + +
    +Fusion: Fix review burnin start and end frame #4590 + +Fix the burnin start and end frame for reviews. Without this the asset document's start and end handle would've been added to the _burnin_ frame range even though that would've been incorrect since the handles are based on the comp saver's render range instead. + + +___ + +
    + + +
    +Harmony: missing set of frame range when opening scene #4485 + +Frame range gets set from DB everytime scene is opened. + +Added also check for not up-to-date loaded containers. + + +___ + +
    + + +
    +Photoshop: context is not changed in publisher #4570 + +When PS is already open and artists launch new task, it should keep only opened PS open, but change context. + +Problem were occurring in Workfile app where under new task files from old task were shown. This fixes this and adds opening of last workfile for new context if workfile exists. + + +___ + +
    + + +
    +hiero: fix effect item node class #4543 + +Collected effect name after renaming is saving correct class name. + + +___ + +
    + + +
    +Bugfix/OP-4616 vray multipart #4297 + +This fixes a bug where multipart vray renders would not make a review in Ftrack. + + +___ + +
    + + +
    +Maya: Fix changed location of reset_frame_range #4491 + +Location in commands caused cyclic import + + +___ + +
    + + +
    +global: source template fixed frame duplication #4503 + +Duplication is not happening. + +Template is using `originalBasename` which already assume all necessary elements are part of the file name so there was no need for additional optional name elements. + + +___ + +
    + + +
    +Deadline: Hint to use Python 3 #4518 + +Added shebank to give deadline hint which python should be used. + +Deadline has issues with Python 2 (especially with `os.scandir`). When a shebank is added to file header deadline will use python 3 mode instead of python 2 which fix the issue. + + +___ + +
    + + +
    +Publisher: Prevent access to create tab after publish start #4528 + +Prevent access to create tab after publish start. + +Disable create button in instance view on publish start and enable it again on reset. Even with that make sure that it is not possible to go to create tab if the tab is disabled. + + +___ + +
    + + +
    +Color Transcoding: store target_colorspace as new colorspace #4544 + +When transcoding into new colorspace, representation must carry this information instead original color space. + + +___ + +
    + + +
    +Deadline: fix submit_publish_job #4552 + +Fix submit_publish_job + +Resolves #4541 + + +___ + +
    + + +
    +Kitsu: Fix task itteration in update-op-with-zou #4577 + +From the last PR (https://github.com/ynput/OpenPype/pull/4425) a comment-commit last second messed up the code and resulted in two lines being the same, crashing the script. This PR fixes that. +___ + +
    + + +
    +AttrDefs: Fix type for PySide6 #4584 + +Use right type in signal emit for value change of attribute definitions. + +Changed `UUID` type to `str`. This is not an issue with PySide2 but it is with PySide6. + + +___ + +
    + +### **🔀 Refactored code** + + +
    +Scene Inventory: Avoid using ObjectId #4524 + +Avoid using conversion to ObjectId type in scene inventory tool. + +Preparation for AYON compatibility where ObjectId won't be used for ids. Representation ids from loaded containers are not converted to ObjectId but kept as strings which also required some changes when working with representation documents. + + +___ + +
    + +### **Merged pull requests** + + +
    +SiteSync: host dirmap is not working properly #4563 + +If artists uses SiteSync with real remote (gdrive, dropbox, sftp) drive, Local Settings were throwing error `string indices must be integers`. + +Logic was reworked to provide only `local_drive` values to be overrriden by Local Settings. If remote site is `gdrive` etc. mapping to `studio` is provided as it is expected that workfiles will have imported from `studio` location and not from `gdrive` folder.Also Nuke dirmap was reworked to be less verbose and much faster. + + +___ + +
    + + +
    +General: Input representation ids are not ObjectIds #4576 + +Don't use `ObjectId` as representation ids during publishing. + +Representation ids are kept as strings during publishing instead of converting them to `ObjectId`. This change is pre-requirement for AYON connection.Inputs are used for integration of links and for farm publishing (or at least it looks like). + + +___ + +
    + + +
    +Shotgrid: Fixes on Deadline submissions #4498 + +A few other bug fixes for getting Nuke submission to Deadline work smoothly using Shotgrid integration. + +Continuing on the work done on this other PR this fixes a few other bugs I came across with further tests. + + +___ + +
    + + +
    +Fusion: New Publisher #3892 + +This converts the old publishing system to the new one. It implements Fusion as a new host addon. + + +- Create button removed in OpenPype menu in favor of the new Publisher +- Draft refactor validations to raise `PublishValidationError` +- Implement Creator for New Publisher +- Implement Fusion as Host addon + + +___ + +
    + + +
    +Make Kitsu work with Tray Publisher, added kitsureview tag, fixed sync-problems. #4425 + +Make Kitsu work with Tray Publisher, added kitsureview tag, fixed sync-problems. + +This PR updates the way the module gather info for the current publish so it now works with Tray Publisher.It fixes the data that gets synced from Kitsu to OP so all needed data gets registered even if it doesn't exist on Kitsus side.It also adds the tag "Add review to Kitsu" and adds it to Burn In so previews gets generated by default to Kitsu. + + +___ + +
    + + +
    +Maya: V-Ray Set Image Format from settings #4566 + +Resolves #4565 + +Set V-Ray Image Format using settings. + + +___ + +
    + + + ## [3.15.1](https://github.com/ynput/OpenPype/tree/3.15.1) diff --git a/openpype/cli.py b/openpype/cli.py index 5c47088a44f..a650a9fdcc7 100644 --- a/openpype/cli.py +++ b/openpype/cli.py @@ -367,11 +367,15 @@ def run(script): "--timeout", help="Provide specific timeout value for test case", default=None) +@click.option("-so", + "--setup_only", + help="Only create dbs, do not run tests", + default=None) def runtests(folder, mark, pyargs, test_data_folder, persist, app_variant, - timeout): + timeout, setup_only): """Run all automatic tests after proper initialization via start.py""" PypeCommands().run_tests(folder, mark, pyargs, test_data_folder, - persist, app_variant, timeout) + persist, app_variant, timeout, setup_only) @main.command() diff --git a/openpype/hooks/pre_add_last_workfile_arg.py b/openpype/hooks/pre_add_last_workfile_arg.py index 1c8746c559e..2558daef303 100644 --- a/openpype/hooks/pre_add_last_workfile_arg.py +++ b/openpype/hooks/pre_add_last_workfile_arg.py @@ -14,6 +14,7 @@ class AddLastWorkfileToLaunchArgs(PreLaunchHook): # Execute after workfile template copy order = 10 app_groups = [ + "3dsmax", "maya", "nuke", "nukex", diff --git a/openpype/hooks/pre_create_extra_workdir_folders.py b/openpype/hooks/pre_create_extra_workdir_folders.py index c5af620c877..8856281120f 100644 --- a/openpype/hooks/pre_create_extra_workdir_folders.py +++ b/openpype/hooks/pre_create_extra_workdir_folders.py @@ -3,10 +3,13 @@ from openpype.pipeline.workfile import create_workdir_extra_folders -class AddLastWorkfileToLaunchArgs(PreLaunchHook): - """Add last workfile path to launch arguments. +class CreateWorkdirExtraFolders(PreLaunchHook): + """Create extra folders for the work directory. + + Based on setting `project_settings/global/tools/Workfiles/extra_folders` + profile filtering will decide whether extra folders need to be created in + the work directory. - This is not possible to do for all applications the same way. """ # Execute after workfile template copy diff --git a/openpype/hooks/pre_foundry_apps.py b/openpype/hooks/pre_foundry_apps.py index 2092d5025dc..21ec8e78814 100644 --- a/openpype/hooks/pre_foundry_apps.py +++ b/openpype/hooks/pre_foundry_apps.py @@ -7,7 +7,7 @@ class LaunchFoundryAppsWindows(PreLaunchHook): Nuke is executed "like" python process so it is required to pass `CREATE_NEW_CONSOLE` flag on windows to trigger creation of new console. - At the same time the newly created console won't create it's own stdout + At the same time the newly created console won't create its own stdout and stderr handlers so they should not be redirected to DEVNULL. """ @@ -18,7 +18,7 @@ class LaunchFoundryAppsWindows(PreLaunchHook): def execute(self): # Change `creationflags` to CREATE_NEW_CONSOLE - # - on Windows will nuke create new window using it's console + # - on Windows nuke will create new window using its console # Set `stdout` and `stderr` to None so new created console does not # have redirected output to DEVNULL in build self.launch_context.kwargs.update({ diff --git a/openpype/host/dirmap.py b/openpype/host/dirmap.py index 347c5fbf851..1d084cccad5 100644 --- a/openpype/host/dirmap.py +++ b/openpype/host/dirmap.py @@ -39,7 +39,6 @@ def __init__( self._project_settings = project_settings self._sync_module = sync_module # to limit reinit of Modules self._log = None - self._mapping = None # cache mapping @property def sync_module(self): @@ -70,29 +69,28 @@ def dirmap_routine(self, source_path, destination_path): """Run host dependent remapping from source_path to destination_path""" pass - def process_dirmap(self): + def process_dirmap(self, mapping=None): # type: (dict) -> None """Go through all paths in Settings and set them using `dirmap`. If artists has Site Sync enabled, take dirmap mapping directly from Local Settings when artist is syncing workfile locally. - Args: - project_settings (dict): Settings for current project. """ - if not self._mapping: - self._mapping = self.get_mappings(self.project_settings) - if not self._mapping: + if not mapping: + mapping = self.get_mappings() + if not mapping: return - self.log.info("Processing directory mapping ...") self.on_enable_dirmap() - self.log.info("mapping:: {}".format(self._mapping)) - for k, sp in enumerate(self._mapping["source-path"]): - dst = self._mapping["destination-path"][k] + for k, sp in enumerate(mapping["source-path"]): + dst = mapping["destination-path"][k] try: + # add trailing slash if missing + sp = os.path.join(sp, '') + dst = os.path.join(dst, '') print("{} -> {}".format(sp, dst)) self.dirmap_routine(sp, dst) except IndexError: @@ -110,28 +108,24 @@ def process_dirmap(self): ) continue - def get_mappings(self, project_settings): + def get_mappings(self): """Get translation from source-path to destination-path. It checks if Site Sync is enabled and user chose to use local site, in that case configuration in Local Settings takes precedence """ - local_mapping = self._get_local_sync_dirmap(project_settings) dirmap_label = "{}-dirmap".format(self.host_name) - if ( - not self.project_settings[self.host_name].get(dirmap_label) - and not local_mapping - ): - return {} - mapping_settings = self.project_settings[self.host_name][dirmap_label] - mapping_enabled = mapping_settings["enabled"] or bool(local_mapping) + mapping_sett = self.project_settings[self.host_name].get(dirmap_label, + {}) + local_mapping = self._get_local_sync_dirmap() + mapping_enabled = mapping_sett.get("enabled") or bool(local_mapping) if not mapping_enabled: return {} mapping = ( local_mapping - or mapping_settings["paths"] + or mapping_sett["paths"] or {} ) @@ -141,28 +135,27 @@ def get_mappings(self, project_settings): or not mapping.get("source-path") ): return {} + self.log.info("Processing directory mapping ...") + self.log.info("mapping:: {}".format(mapping)) return mapping - def _get_local_sync_dirmap(self, project_settings): + def _get_local_sync_dirmap(self): """ Returns dirmap if synch to local project is enabled. Only valid mapping is from roots of remote site to local site set in Local Settings. - Args: - project_settings (dict) Returns: dict : { "source-path": [XXX], "destination-path": [YYYY]} """ + project_name = os.getenv("AVALON_PROJECT") mapping = {} - - if not project_settings["global"]["sync_server"]["enabled"]: + if (not self.sync_module.enabled or + project_name not in self.sync_module.get_enabled_projects()): return mapping - project_name = os.getenv("AVALON_PROJECT") - active_site = self.sync_module.get_local_normalized_site( self.sync_module.get_active_site(project_name)) remote_site = self.sync_module.get_local_normalized_site( @@ -171,11 +164,7 @@ def _get_local_sync_dirmap(self, project_settings): "active {} - remote {}".format(active_site, remote_site) ) - if ( - active_site == "local" - and project_name in self.sync_module.get_enabled_projects() - and active_site != remote_site - ): + if active_site == "local" and active_site != remote_site: sync_settings = self.sync_module.get_sync_project_setting( project_name, exclude_locals=False, @@ -188,7 +177,15 @@ def _get_local_sync_dirmap(self, project_settings): self.log.debug("local overrides {}".format(active_overrides)) self.log.debug("remote overrides {}".format(remote_overrides)) + current_platform = platform.system().lower() + remote_provider = self.sync_module.get_provider_for_site( + project_name, remote_site + ) + # dirmap has sense only with regular disk provider, in the workfile + # wont be root on cloud or sftp provider + if remote_provider != "local_drive": + remote_site = "studio" for root_name, active_site_dir in active_overrides.items(): remote_site_dir = ( remote_overrides.get(root_name) diff --git a/openpype/hosts/blender/api/__init__.py b/openpype/hosts/blender/api/__init__.py index e017d74d912..75a11affde6 100644 --- a/openpype/hosts/blender/api/__init__.py +++ b/openpype/hosts/blender/api/__init__.py @@ -31,10 +31,13 @@ lsattrs, read, maintained_selection, + maintained_time, get_selection, # unique_name, ) +from .capture import capture + __all__ = [ "install", @@ -56,9 +59,11 @@ # Utility functions "maintained_selection", + "maintained_time", "lsattr", "lsattrs", "read", "get_selection", + "capture", # "unique_name", ] diff --git a/openpype/hosts/blender/api/capture.py b/openpype/hosts/blender/api/capture.py new file mode 100644 index 00000000000..849f8ee6298 --- /dev/null +++ b/openpype/hosts/blender/api/capture.py @@ -0,0 +1,278 @@ + +"""Blender Capture +Playblasting with independent viewport, camera and display options +""" +import contextlib +import bpy + +from .lib import maintained_time +from .plugin import deselect_all, create_blender_context + + +def capture( + camera=None, + width=None, + height=None, + filename=None, + start_frame=None, + end_frame=None, + step_frame=None, + sound=None, + isolate=None, + maintain_aspect_ratio=True, + overwrite=False, + image_settings=None, + display_options=None +): + """Playblast in an independent windows + Arguments: + camera (str, optional): Name of camera, defaults to "Camera" + width (int, optional): Width of output in pixels + height (int, optional): Height of output in pixels + filename (str, optional): Name of output file path. Defaults to current + render output path. + start_frame (int, optional): Defaults to current start frame. + end_frame (int, optional): Defaults to current end frame. + step_frame (int, optional): Defaults to 1. + sound (str, optional): Specify the sound node to be used during + playblast. When None (default) no sound will be used. + isolate (list): List of nodes to isolate upon capturing + maintain_aspect_ratio (bool, optional): Modify height in order to + maintain aspect ratio. + overwrite (bool, optional): Whether or not to overwrite if file + already exists. If disabled and file exists and error will be + raised. + image_settings (dict, optional): Supplied image settings for render, + using `ImageSettings` + display_options (dict, optional): Supplied display options for render + """ + + scene = bpy.context.scene + camera = camera or "Camera" + + # Ensure camera exists. + if camera not in scene.objects and camera != "AUTO": + raise RuntimeError("Camera does not exist: {0}".format(camera)) + + # Ensure resolution. + if width and height: + maintain_aspect_ratio = False + width = width or scene.render.resolution_x + height = height or scene.render.resolution_y + if maintain_aspect_ratio: + ratio = scene.render.resolution_x / scene.render.resolution_y + height = round(width / ratio) + + # Get frame range. + if start_frame is None: + start_frame = scene.frame_start + if end_frame is None: + end_frame = scene.frame_end + if step_frame is None: + step_frame = 1 + frame_range = (start_frame, end_frame, step_frame) + + if filename is None: + filename = scene.render.filepath + + render_options = { + "filepath": "{}.".format(filename.rstrip(".")), + "resolution_x": width, + "resolution_y": height, + "use_overwrite": overwrite, + } + + with _independent_window() as window: + + applied_view(window, camera, isolate, options=display_options) + + with contextlib.ExitStack() as stack: + stack.enter_context(maintain_camera(window, camera)) + stack.enter_context(applied_frame_range(window, *frame_range)) + stack.enter_context(applied_render_options(window, render_options)) + stack.enter_context(applied_image_settings(window, image_settings)) + stack.enter_context(maintained_time()) + + bpy.ops.render.opengl( + animation=True, + render_keyed_only=False, + sequencer=False, + write_still=False, + view_context=True + ) + + return filename + + +ImageSettings = { + "file_format": "FFMPEG", + "color_mode": "RGB", + "ffmpeg": { + "format": "QUICKTIME", + "use_autosplit": False, + "codec": "H264", + "constant_rate_factor": "MEDIUM", + "gopsize": 18, + "use_max_b_frames": False, + }, +} + + +def isolate_objects(window, objects): + """Isolate selection""" + deselect_all() + + for obj in objects: + obj.select_set(True) + + context = create_blender_context(selected=objects, window=window) + + bpy.ops.view3d.view_axis(context, type="FRONT") + bpy.ops.view3d.localview(context) + + deselect_all() + + +def _apply_options(entity, options): + for option, value in options.items(): + if isinstance(value, dict): + _apply_options(getattr(entity, option), value) + else: + setattr(entity, option, value) + + +def applied_view(window, camera, isolate=None, options=None): + """Apply view options to window.""" + area = window.screen.areas[0] + space = area.spaces[0] + + area.ui_type = "VIEW_3D" + + meshes = [obj for obj in window.scene.objects if obj.type == "MESH"] + + if camera == "AUTO": + space.region_3d.view_perspective = "ORTHO" + isolate_objects(window, isolate or meshes) + else: + isolate_objects(window, isolate or meshes) + space.camera = window.scene.objects.get(camera) + space.region_3d.view_perspective = "CAMERA" + + if isinstance(options, dict): + _apply_options(space, options) + else: + space.shading.type = "SOLID" + space.shading.color_type = "MATERIAL" + space.show_gizmo = False + space.overlay.show_overlays = False + + +@contextlib.contextmanager +def applied_frame_range(window, start, end, step): + """Context manager for setting frame range.""" + # Store current frame range + current_frame_start = window.scene.frame_start + current_frame_end = window.scene.frame_end + current_frame_step = window.scene.frame_step + # Apply frame range + window.scene.frame_start = start + window.scene.frame_end = end + window.scene.frame_step = step + try: + yield + finally: + # Restore frame range + window.scene.frame_start = current_frame_start + window.scene.frame_end = current_frame_end + window.scene.frame_step = current_frame_step + + +@contextlib.contextmanager +def applied_render_options(window, options): + """Context manager for setting render options.""" + render = window.scene.render + + # Store current settings + original = {} + for opt in options.copy(): + try: + original[opt] = getattr(render, opt) + except ValueError: + options.pop(opt) + + # Apply settings + _apply_options(render, options) + + try: + yield + finally: + # Restore previous settings + _apply_options(render, original) + + +@contextlib.contextmanager +def applied_image_settings(window, options): + """Context manager to override image settings.""" + + options = options or ImageSettings.copy() + ffmpeg = options.pop("ffmpeg", {}) + render = window.scene.render + + # Store current image settings + original = {} + for opt in options.copy(): + try: + original[opt] = getattr(render.image_settings, opt) + except ValueError: + options.pop(opt) + + # Store current ffmpeg settings + original_ffmpeg = {} + for opt in ffmpeg.copy(): + try: + original_ffmpeg[opt] = getattr(render.ffmpeg, opt) + except ValueError: + ffmpeg.pop(opt) + + # Apply image settings + for opt, value in options.items(): + setattr(render.image_settings, opt, value) + + # Apply ffmpeg settings + for opt, value in ffmpeg.items(): + setattr(render.ffmpeg, opt, value) + + try: + yield + finally: + # Restore previous settings + for opt, value in original.items(): + setattr(render.image_settings, opt, value) + for opt, value in original_ffmpeg.items(): + setattr(render.ffmpeg, opt, value) + + +@contextlib.contextmanager +def maintain_camera(window, camera): + """Context manager to override camera.""" + current_camera = window.scene.camera + if camera in window.scene.objects: + window.scene.camera = window.scene.objects.get(camera) + try: + yield + finally: + window.scene.camera = current_camera + + +@contextlib.contextmanager +def _independent_window(): + """Create capture-window context.""" + context = create_blender_context() + current_windows = set(bpy.context.window_manager.windows) + bpy.ops.wm.window_new(context) + window = list(set(bpy.context.window_manager.windows) - current_windows)[0] + context["window"] = window + try: + yield window + finally: + bpy.ops.wm.window_close(context) diff --git a/openpype/hosts/blender/api/lib.py b/openpype/hosts/blender/api/lib.py index 05912885f74..6526f1fb870 100644 --- a/openpype/hosts/blender/api/lib.py +++ b/openpype/hosts/blender/api/lib.py @@ -284,3 +284,13 @@ def maintained_selection(): # This could happen if the active node was deleted during the # context. log.exception("Failed to set active object.") + + +@contextlib.contextmanager +def maintained_time(): + """Maintain current frame during context.""" + current_time = bpy.context.scene.frame_current + try: + yield + finally: + bpy.context.scene.frame_current = current_time diff --git a/openpype/hosts/blender/api/ops.py b/openpype/hosts/blender/api/ops.py index 481c199db29..158c32fb5a2 100644 --- a/openpype/hosts/blender/api/ops.py +++ b/openpype/hosts/blender/api/ops.py @@ -84,11 +84,11 @@ def __init__(self, callback, *args, **kwargs): self.kwargs = kwargs def execute(self): - """Execute callback and store it's result. + """Execute callback and store its result. Method must be called from main thread. Item is marked as `done` when callback execution finished. Store output of callback of exception - information when callback raise one. + information when callback raises one. """ print("Executing process in main thread") if self.done: @@ -382,8 +382,8 @@ def draw(self, context): layout.operator(LaunchLibrary.bl_idname, text="Library...") layout.separator() layout.operator(LaunchWorkFiles.bl_idname, text="Work Files...") - # TODO (jasper): maybe add 'Reload Pipeline', 'Reset Frame Range' and - # 'Reset Resolution'? + # TODO (jasper): maybe add 'Reload Pipeline', 'Set Frame Range' and + # 'Set Resolution'? def draw_avalon_menu(self, context): diff --git a/openpype/hosts/blender/api/plugin.py b/openpype/hosts/blender/api/plugin.py index c59be8d7ff9..1274795c6be 100644 --- a/openpype/hosts/blender/api/plugin.py +++ b/openpype/hosts/blender/api/plugin.py @@ -62,7 +62,8 @@ def prepare_data(data, container_name=None): def create_blender_context(active: Optional[bpy.types.Object] = None, - selected: Optional[bpy.types.Object] = None,): + selected: Optional[bpy.types.Object] = None, + window: Optional[bpy.types.Window] = None): """Create a new Blender context. If an object is passed as parameter, it is set as selected and active. """ @@ -72,7 +73,9 @@ def create_blender_context(active: Optional[bpy.types.Object] = None, override_context = bpy.context.copy() - for win in bpy.context.window_manager.windows: + windows = [window] if window else bpy.context.window_manager.windows + + for win in windows: for area in win.screen.areas: if area.type == 'VIEW_3D': for region in area.regions: diff --git a/openpype/hosts/blender/plugins/create/create_review.py b/openpype/hosts/blender/plugins/create/create_review.py new file mode 100644 index 00000000000..bf4ea6a7cd6 --- /dev/null +++ b/openpype/hosts/blender/plugins/create/create_review.py @@ -0,0 +1,47 @@ +"""Create review.""" + +import bpy + +from openpype.pipeline import legacy_io +from openpype.hosts.blender.api import plugin, lib, ops +from openpype.hosts.blender.api.pipeline import AVALON_INSTANCES + + +class CreateReview(plugin.Creator): + """Single baked camera""" + + name = "reviewDefault" + label = "Review" + family = "review" + icon = "video-camera" + + def process(self): + """ Run the creator on Blender main thread""" + mti = ops.MainThreadItem(self._process) + ops.execute_in_main_thread(mti) + + def _process(self): + # Get Instance Container or create it if it does not exist + instances = bpy.data.collections.get(AVALON_INSTANCES) + if not instances: + instances = bpy.data.collections.new(name=AVALON_INSTANCES) + bpy.context.scene.collection.children.link(instances) + + # Create instance object + asset = self.data["asset"] + subset = self.data["subset"] + name = plugin.asset_name(asset, subset) + asset_group = bpy.data.collections.new(name=name) + instances.children.link(asset_group) + self.data['task'] = legacy_io.Session.get('AVALON_TASK') + lib.imprint(asset_group, self.data) + + if (self.options or {}).get("useSelection"): + selected = lib.get_selection() + for obj in selected: + asset_group.objects.link(obj) + elif (self.options or {}).get("asset_group"): + obj = (self.options or {}).get("asset_group") + asset_group.objects.link(obj) + + return asset_group diff --git a/openpype/hosts/blender/plugins/publish/collect_review.py b/openpype/hosts/blender/plugins/publish/collect_review.py new file mode 100644 index 00000000000..d6abd9d967a --- /dev/null +++ b/openpype/hosts/blender/plugins/publish/collect_review.py @@ -0,0 +1,64 @@ +import bpy + +import pyblish.api +from openpype.pipeline import legacy_io + + +class CollectReview(pyblish.api.InstancePlugin): + """Collect Review data + + """ + + order = pyblish.api.CollectorOrder + 0.3 + label = "Collect Review Data" + families = ["review"] + + def process(self, instance): + + self.log.debug(f"instance: {instance}") + + # get cameras + cameras = [ + obj + for obj in instance + if isinstance(obj, bpy.types.Object) and obj.type == "CAMERA" + ] + + assert len(cameras) == 1, ( + f"Not a single camera found in extraction: {cameras}" + ) + camera = cameras[0].name + self.log.debug(f"camera: {camera}") + + # get isolate objects list from meshes instance members . + isolate_objects = [ + obj + for obj in instance + if isinstance(obj, bpy.types.Object) and obj.type == "MESH" + ] + + if not instance.data.get("remove"): + + task = legacy_io.Session.get("AVALON_TASK") + + instance.data.update({ + "subset": f"{task}Review", + "review_camera": camera, + "frameStart": instance.context.data["frameStart"], + "frameEnd": instance.context.data["frameEnd"], + "fps": instance.context.data["fps"], + "isolate": isolate_objects, + }) + + self.log.debug(f"instance data: {instance.data}") + + # TODO : Collect audio + audio_tracks = [] + instance.data["audio"] = [] + for track in audio_tracks: + instance.data["audio"].append( + { + "offset": track.offset.get(), + "filename": track.filename.get(), + } + ) diff --git a/openpype/hosts/blender/plugins/publish/extract_playblast.py b/openpype/hosts/blender/plugins/publish/extract_playblast.py new file mode 100644 index 00000000000..8dc2f66c22a --- /dev/null +++ b/openpype/hosts/blender/plugins/publish/extract_playblast.py @@ -0,0 +1,123 @@ +import os +import clique + +import bpy + +import pyblish.api +from openpype.pipeline import publish +from openpype.hosts.blender.api import capture +from openpype.hosts.blender.api.lib import maintained_time + + +class ExtractPlayblast(publish.Extractor): + """ + Extract viewport playblast. + + Takes review camera and creates review Quicktime video based on viewport + capture. + """ + + label = "Extract Playblast" + hosts = ["blender"] + families = ["review"] + optional = True + order = pyblish.api.ExtractorOrder + 0.01 + + def process(self, instance): + self.log.info("Extracting capture..") + + self.log.info(instance.data) + + # get scene fps + fps = instance.data.get("fps") + if fps is None: + fps = bpy.context.scene.render.fps + instance.data["fps"] = fps + + self.log.info(f"fps: {fps}") + + # If start and end frames cannot be determined, + # get them from Blender timeline. + start = instance.data.get("frameStart", bpy.context.scene.frame_start) + end = instance.data.get("frameEnd", bpy.context.scene.frame_end) + + self.log.info(f"start: {start}, end: {end}") + assert end > start, "Invalid time range !" + + # get cameras + camera = instance.data("review_camera", None) + + # get isolate objects list + isolate = instance.data("isolate", None) + + # get ouput path + stagingdir = self.staging_dir(instance) + filename = instance.name + path = os.path.join(stagingdir, filename) + + self.log.info(f"Outputting images to {path}") + + project_settings = instance.context.data["project_settings"]["blender"] + presets = project_settings["publish"]["ExtractPlayblast"]["presets"] + preset = presets.get("default") + preset.update({ + "camera": camera, + "start_frame": start, + "end_frame": end, + "filename": path, + "overwrite": True, + "isolate": isolate, + }) + preset.setdefault( + "image_settings", + { + "file_format": "PNG", + "color_mode": "RGB", + "color_depth": "8", + "compression": 15, + }, + ) + + with maintained_time(): + path = capture(**preset) + + self.log.debug(f"playblast path {path}") + + collected_files = os.listdir(stagingdir) + collections, remainder = clique.assemble( + collected_files, + patterns=[f"{filename}\\.{clique.DIGITS_PATTERN}\\.png$"], + ) + + if len(collections) > 1: + raise RuntimeError( + f"More than one collection found in stagingdir: {stagingdir}" + ) + elif len(collections) == 0: + raise RuntimeError( + f"No collection found in stagingdir: {stagingdir}" + ) + + frame_collection = collections[0] + + self.log.info(f"We found collection of interest {frame_collection}") + + instance.data.setdefault("representations", []) + + tags = ["review"] + if not instance.data.get("keepImages"): + tags.append("delete") + + representation = { + "name": "png", + "ext": "png", + "files": list(frame_collection), + "stagingDir": stagingdir, + "frameStart": start, + "frameEnd": end, + "fps": fps, + "preview": True, + "tags": tags, + "camera_name": camera + } + instance.data["representations"].append(representation) diff --git a/openpype/hosts/blender/plugins/publish/extract_thumbnail.py b/openpype/hosts/blender/plugins/publish/extract_thumbnail.py new file mode 100644 index 00000000000..65c3627375e --- /dev/null +++ b/openpype/hosts/blender/plugins/publish/extract_thumbnail.py @@ -0,0 +1,99 @@ +import os +import glob + +import pyblish.api +from openpype.pipeline import publish +from openpype.hosts.blender.api import capture +from openpype.hosts.blender.api.lib import maintained_time + +import bpy + + +class ExtractThumbnail(publish.Extractor): + """Extract viewport thumbnail. + + Takes review camera and creates a thumbnail based on viewport + capture. + + """ + + label = "Extract Thumbnail" + hosts = ["blender"] + families = ["review"] + order = pyblish.api.ExtractorOrder + 0.01 + presets = {} + + def process(self, instance): + self.log.info("Extracting capture..") + + stagingdir = self.staging_dir(instance) + filename = instance.name + path = os.path.join(stagingdir, filename) + + self.log.info(f"Outputting images to {path}") + + camera = instance.data.get("review_camera", "AUTO") + start = instance.data.get("frameStart", bpy.context.scene.frame_start) + family = instance.data.get("family") + isolate = instance.data("isolate", None) + + preset = self.presets.get(family, {}) + + preset.update({ + "camera": camera, + "start_frame": start, + "end_frame": start, + "filename": path, + "overwrite": True, + "isolate": isolate, + }) + preset.setdefault( + "image_settings", + { + "file_format": "JPEG", + "color_mode": "RGB", + "quality": 100, + }, + ) + + with maintained_time(): + path = capture(**preset) + + thumbnail = os.path.basename(self._fix_output_path(path)) + + self.log.info(f"thumbnail: {thumbnail}") + + instance.data.setdefault("representations", []) + + representation = { + "name": "thumbnail", + "ext": "jpg", + "files": thumbnail, + "stagingDir": stagingdir, + "thumbnail": True + } + instance.data["representations"].append(representation) + + def _fix_output_path(self, filepath): + """"Workaround to return correct filepath. + + To workaround this we just glob.glob() for any file extensions and + assume the latest modified file is the correct file and return it. + + """ + # Catch cancelled playblast + if filepath is None: + self.log.warning( + "Playblast did not result in output path. " + "Playblast is probably interrupted." + ) + return None + + if not os.path.exists(filepath): + files = glob.glob(f"{filepath}.*.jpg") + + if not files: + raise RuntimeError(f"Couldn't find playblast from: {filepath}") + filepath = max(files, key=os.path.getmtime) + + return filepath diff --git a/openpype/hosts/celaction/hooks/pre_celaction_setup.py b/openpype/hosts/celaction/hooks/pre_celaction_setup.py index 62cebf99ed2..96e784875c2 100644 --- a/openpype/hosts/celaction/hooks/pre_celaction_setup.py +++ b/openpype/hosts/celaction/hooks/pre_celaction_setup.py @@ -38,8 +38,9 @@ def execute(self): ) path_to_cli = os.path.join(CELACTION_SCRIPTS_DIR, "publish_cli.py") - subproces_args = get_openpype_execute_args("run", path_to_cli) - openpype_executable = subproces_args.pop(0) + subprocess_args = get_openpype_execute_args("run", path_to_cli) + openpype_executable = subprocess_args.pop(0) + workfile_settings = self.get_workfile_settings() winreg.SetValueEx( hKey, @@ -49,20 +50,34 @@ def execute(self): openpype_executable ) - parameters = subproces_args + [ - "--currentFile", "*SCENE*", - "--chunk", "*CHUNK*", - "--frameStart", "*START*", - "--frameEnd", "*END*", - "--resolutionWidth", "*X*", - "--resolutionHeight", "*Y*" + # add required arguments for workfile path + parameters = subprocess_args + [ + "--currentFile", "*SCENE*" ] + # Add custom parameters from workfile settings + if "render_chunk" in workfile_settings["submission_overrides"]: + parameters += [ + "--chunk", "*CHUNK*" + ] + if "resolution" in workfile_settings["submission_overrides"]: + parameters += [ + "--resolutionWidth", "*X*", + "--resolutionHeight", "*Y*" + ] + if "frame_range" in workfile_settings["submission_overrides"]: + parameters += [ + "--frameStart", "*START*", + "--frameEnd", "*END*" + ] + winreg.SetValueEx( hKey, "SubmitParametersTitle", 0, winreg.REG_SZ, subprocess.list2cmdline(parameters) ) + self.log.debug(f"__ parameters: \"{parameters}\"") + # setting resolution parameters path_submit = "\\".join([ path_user_settings, "Dialogs", "SubmitOutput" @@ -135,3 +150,6 @@ def workfile_path(self): self.log.info(f"Workfile to open: \"{workfile_path}\"") return workfile_path + + def get_workfile_settings(self): + return self.data["project_settings"]["celaction"]["workfile"] diff --git a/openpype/hosts/celaction/plugins/publish/collect_celaction_cli_kwargs.py b/openpype/hosts/celaction/plugins/publish/collect_celaction_cli_kwargs.py index 43b81b83e7e..54dea15dffc 100644 --- a/openpype/hosts/celaction/plugins/publish/collect_celaction_cli_kwargs.py +++ b/openpype/hosts/celaction/plugins/publish/collect_celaction_cli_kwargs.py @@ -39,7 +39,7 @@ def process(self, context): passing_kwargs[key] = value if missing_kwargs: - raise RuntimeError("Missing arguments {}".format( + self.log.debug("Missing arguments {}".format( ", ".join( [f'"{key}"' for key in missing_kwargs] ) diff --git a/openpype/hosts/fusion/__init__.py b/openpype/hosts/fusion/__init__.py index ddae01890b2..1da11ba9d13 100644 --- a/openpype/hosts/fusion/__init__.py +++ b/openpype/hosts/fusion/__init__.py @@ -1,10 +1,14 @@ from .addon import ( + get_fusion_version, FusionAddon, FUSION_HOST_DIR, + FUSION_VERSIONS_DICT, ) __all__ = ( + "get_fusion_version", "FusionAddon", "FUSION_HOST_DIR", + "FUSION_VERSIONS_DICT", ) diff --git a/openpype/hosts/fusion/addon.py b/openpype/hosts/fusion/addon.py index d1bd1566b7e..45683cfbde1 100644 --- a/openpype/hosts/fusion/addon.py +++ b/openpype/hosts/fusion/addon.py @@ -1,8 +1,52 @@ import os +import re from openpype.modules import OpenPypeModule, IHostAddon +from openpype.lib import Logger FUSION_HOST_DIR = os.path.dirname(os.path.abspath(__file__)) +# FUSION_VERSIONS_DICT is used by the pre-launch hooks +# The keys correspond to all currently supported Fusion versions +# Each value is a list of corresponding Python home variables and a profile +# number, which is used by the profile hook to set Fusion profile variables. +FUSION_VERSIONS_DICT = { + 9: ("FUSION_PYTHON36_HOME", 9), + 16: ("FUSION16_PYTHON36_HOME", 16), + 17: ("FUSION16_PYTHON36_HOME", 16), + 18: ("FUSION_PYTHON3_HOME", 16), +} + + +def get_fusion_version(app_name): + """ + The function is triggered by the prelaunch hooks to get the fusion version. + + `app_name` is obtained by prelaunch hooks from the + `launch_context.env.get("AVALON_APP_NAME")`. + + To get a correct Fusion version, a version number should be present + in the `applications/fusion/variants` key + of the Blackmagic Fusion Application Settings. + """ + + log = Logger.get_logger(__name__) + + if not app_name: + return + + app_version_candidates = re.findall(r"\d+", app_name) + if not app_version_candidates: + return + for app_version in app_version_candidates: + if int(app_version) in FUSION_VERSIONS_DICT: + return int(app_version) + else: + log.info( + "Unsupported Fusion version: {app_version}".format( + app_version=app_version + ) + ) + class FusionAddon(OpenPypeModule, IHostAddon): name = "fusion" @@ -14,15 +58,11 @@ def initialize(self, module_settings): def get_launch_hook_paths(self, app): if app.host_name != self.host_name: return [] - return [ - os.path.join(FUSION_HOST_DIR, "hooks") - ] + return [os.path.join(FUSION_HOST_DIR, "hooks")] def add_implementation_envs(self, env, _app): # Set default values if are not already set via settings - defaults = { - "OPENPYPE_LOG_NO_COLORS": "Yes" - } + defaults = {"OPENPYPE_LOG_NO_COLORS": "Yes"} for key, value in defaults.items(): if not env.get(key): env[key] = value diff --git a/openpype/hosts/fusion/api/action.py b/openpype/hosts/fusion/api/action.py index 17509209504..ff5dd14caa3 100644 --- a/openpype/hosts/fusion/api/action.py +++ b/openpype/hosts/fusion/api/action.py @@ -6,12 +6,13 @@ class SelectInvalidAction(pyblish.api.Action): - """Select invalid nodes in Maya when plug-in failed. + """Select invalid nodes in Fusion when plug-in failed. To retrieve the invalid nodes this assumes a static `get_invalid()` method is available on the plugin. """ + label = "Select invalid" on = "failed" # This action is only available on a failed plug-in icon = "search" # Icon from Awesome Icon @@ -31,8 +32,10 @@ def process(self, context, plugin): if isinstance(invalid_nodes, (list, tuple)): invalid.extend(invalid_nodes) else: - self.log.warning("Plug-in returned to be invalid, " - "but has no selectable nodes.") + self.log.warning( + "Plug-in returned to be invalid, " + "but has no selectable nodes." + ) if not invalid: # Assume relevant comp is current comp and clear selection @@ -51,4 +54,6 @@ def process(self, context, plugin): for tool in invalid: flow.Select(tool, True) names.add(tool.Name) - self.log.info("Selecting invalid tools: %s" % ", ".join(sorted(names))) + self.log.info( + "Selecting invalid tools: %s" % ", ".join(sorted(names)) + ) diff --git a/openpype/hosts/fusion/api/lib.py b/openpype/hosts/fusion/api/lib.py index 88a3f0b49bd..40cc4d2963e 100644 --- a/openpype/hosts/fusion/api/lib.py +++ b/openpype/hosts/fusion/api/lib.py @@ -303,10 +303,18 @@ def get_frame_path(path): return filename, padding, ext -def get_current_comp(): - """Hack to get current comp in this session""" +def get_fusion_module(): + """Get current Fusion instance""" fusion = getattr(sys.modules["__main__"], "fusion", None) - return fusion.CurrentComp if fusion else None + return fusion + + +def get_current_comp(): + """Get current comp in this session""" + fusion = get_fusion_module() + if fusion is not None: + comp = fusion.CurrentComp + return comp @contextlib.contextmanager diff --git a/openpype/hosts/fusion/api/menu.py b/openpype/hosts/fusion/api/menu.py index 343f5f803ad..92f38a64c2a 100644 --- a/openpype/hosts/fusion/api/menu.py +++ b/openpype/hosts/fusion/api/menu.py @@ -6,7 +6,6 @@ from openpype.style import load_stylesheet from openpype.lib import register_event_callback from openpype.hosts.fusion.scripts import ( - set_rendermode, duplicate_with_inputs, ) from openpype.hosts.fusion.api.lib import ( @@ -60,7 +59,6 @@ def __init__(self, *args, **kwargs): publish_btn = QtWidgets.QPushButton("Publish...", self) manager_btn = QtWidgets.QPushButton("Manage...", self) libload_btn = QtWidgets.QPushButton("Library...", self) - rendermode_btn = QtWidgets.QPushButton("Set render mode...", self) set_framerange_btn = QtWidgets.QPushButton("Set Frame Range", self) set_resolution_btn = QtWidgets.QPushButton("Set Resolution", self) duplicate_with_inputs_btn = QtWidgets.QPushButton( @@ -91,7 +89,6 @@ def __init__(self, *args, **kwargs): layout.addWidget(set_framerange_btn) layout.addWidget(set_resolution_btn) - layout.addWidget(rendermode_btn) layout.addSpacing(20) @@ -108,7 +105,6 @@ def __init__(self, *args, **kwargs): load_btn.clicked.connect(self.on_load_clicked) manager_btn.clicked.connect(self.on_manager_clicked) libload_btn.clicked.connect(self.on_libload_clicked) - rendermode_btn.clicked.connect(self.on_rendermode_clicked) duplicate_with_inputs_btn.clicked.connect( self.on_duplicate_with_inputs_clicked ) @@ -162,15 +158,6 @@ def on_manager_clicked(self): def on_libload_clicked(self): host_tools.show_library_loader() - def on_rendermode_clicked(self): - if self.render_mode_widget is None: - window = set_rendermode.SetRenderMode() - window.setStyleSheet(load_stylesheet()) - window.show() - self.render_mode_widget = window - else: - self.render_mode_widget.show() - def on_duplicate_with_inputs_clicked(self): duplicate_with_inputs.duplicate_with_input_connections() diff --git a/openpype/hosts/fusion/deploy/fusion_shared.prefs b/openpype/hosts/fusion/deploy/fusion_shared.prefs index 998c6a6d663..b379ea7c660 100644 --- a/openpype/hosts/fusion/deploy/fusion_shared.prefs +++ b/openpype/hosts/fusion/deploy/fusion_shared.prefs @@ -1,19 +1,19 @@ { Locked = true, Global = { - Paths = { - Map = { - ["OpenPype:"] = "$(OPENPYPE_FUSION)/deploy", - ["Reactor:"] = "$(REACTOR)", - - ["Config:"] = "UserPaths:Config;OpenPype:Config", - ["Scripts:"] = "UserPaths:Scripts;Reactor:System/Scripts;OpenPype:Scripts", - ["UserPaths:"] = "UserData:;AllData:;Fusion:;Reactor:Deploy" + Paths = { + Map = { + ["OpenPype:"] = "$(OPENPYPE_FUSION)/deploy", + ["Config:"] = "UserPaths:Config;OpenPype:Config", + ["Scripts:"] = "UserPaths:Scripts;Reactor:System/Scripts;OpenPype:Scripts", + }, }, - }, - Script = { - PythonVersion = 3, - Python3Forced = true - }, + Script = { + PythonVersion = 3, + Python3Forced = true + }, + UserInterface = { + Language = "en_US" }, -} \ No newline at end of file + }, +} diff --git a/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py new file mode 100644 index 00000000000..fd726ccda14 --- /dev/null +++ b/openpype/hosts/fusion/hooks/pre_fusion_profile_hook.py @@ -0,0 +1,161 @@ +import os +import shutil +import platform +from pathlib import Path +from openpype.lib import PreLaunchHook, ApplicationLaunchFailed +from openpype.hosts.fusion import ( + FUSION_HOST_DIR, + FUSION_VERSIONS_DICT, + get_fusion_version, +) + + +class FusionCopyPrefsPrelaunch(PreLaunchHook): + """ + Prepares local Fusion profile directory, copies existing Fusion profile. + This also sets FUSION MasterPrefs variable, which is used + to apply Master.prefs file to override some Fusion profile settings to: + - enable the OpenPype menu + - force Python 3 over Python 2 + - force English interface + Master.prefs is defined in openpype/hosts/fusion/deploy/fusion_shared.prefs + """ + + app_groups = ["fusion"] + order = 2 + + def get_fusion_profile_name(self, profile_version) -> str: + # Returns 'Default', unless FUSION16_PROFILE is set + return os.getenv(f"FUSION{profile_version}_PROFILE", "Default") + + def get_fusion_profile_dir(self, profile_version) -> Path: + # Get FUSION_PROFILE_DIR variable + fusion_profile = self.get_fusion_profile_name(profile_version) + fusion_var_prefs_dir = os.getenv( + f"FUSION{profile_version}_PROFILE_DIR" + ) + + # Check if FUSION_PROFILE_DIR exists + if fusion_var_prefs_dir and Path(fusion_var_prefs_dir).is_dir(): + fu_prefs_dir = Path(fusion_var_prefs_dir, fusion_profile) + self.log.info(f"{fusion_var_prefs_dir} is set to {fu_prefs_dir}") + return fu_prefs_dir + + def get_profile_source(self, profile_version) -> Path: + """Get Fusion preferences profile location. + See Per-User_Preferences_and_Paths on VFXpedia for reference. + """ + fusion_profile = self.get_fusion_profile_name(profile_version) + profile_source = self.get_fusion_profile_dir(profile_version) + if profile_source: + return profile_source + # otherwise get default location of the profile folder + fu_prefs_dir = f"Blackmagic Design/Fusion/Profiles/{fusion_profile}" + if platform.system() == "Windows": + profile_source = Path(os.getenv("AppData"), fu_prefs_dir) + elif platform.system() == "Darwin": + profile_source = Path( + "~/Library/Application Support/", fu_prefs_dir + ).expanduser() + elif platform.system() == "Linux": + profile_source = Path("~/.fusion", fu_prefs_dir).expanduser() + self.log.info( + f"Locating source Fusion prefs directory: {profile_source}" + ) + return profile_source + + def get_copy_fusion_prefs_settings(self): + # Get copy preferences options from the global application settings + + copy_fusion_settings = self.data["project_settings"]["fusion"].get( + "copy_fusion_settings", {} + ) + if not copy_fusion_settings: + self.log.error("Copy prefs settings not found") + copy_status = copy_fusion_settings.get("copy_status", False) + force_sync = copy_fusion_settings.get("force_sync", False) + copy_path = copy_fusion_settings.get("copy_path") or None + if copy_path: + copy_path = Path(copy_path).expanduser() + return copy_status, copy_path, force_sync + + def copy_fusion_profile( + self, copy_from: Path, copy_to: Path, force_sync: bool + ) -> None: + """On the first Fusion launch copy the contents of Fusion profile + directory to the working predefined location. If the Openpype profile + folder exists, skip copying, unless re-sync is checked. + If the prefs were not copied on the first launch, + clean Fusion profile will be created in fu_profile_dir. + """ + if copy_to.exists() and not force_sync: + self.log.info( + "Destination Fusion preferences folder already exists: " + f"{copy_to} " + ) + return + self.log.info("Starting copying Fusion preferences") + self.log.debug(f"force_sync option is set to {force_sync}") + try: + copy_to.mkdir(exist_ok=True, parents=True) + except PermissionError: + self.log.warning(f"Creating the folder not permitted at {copy_to}") + return + if not copy_from.exists(): + self.log.warning(f"Fusion preferences not found in {copy_from}") + return + for file in copy_from.iterdir(): + if file.suffix in ( + ".prefs", + ".def", + ".blocklist", + ".fu", + ".toolbars", + ): + # convert Path to str to be compatible with Python 3.6+ + shutil.copy(str(file), str(copy_to)) + self.log.info( + f"Successfully copied preferences: {copy_from} to {copy_to}" + ) + + def execute(self): + ( + copy_status, + fu_profile_dir, + force_sync, + ) = self.get_copy_fusion_prefs_settings() + + # Get launched application context and return correct app version + app_name = self.launch_context.env.get("AVALON_APP_NAME") + app_version = get_fusion_version(app_name) + if app_version is None: + version_names = ", ".join(str(x) for x in FUSION_VERSIONS_DICT) + raise ApplicationLaunchFailed( + "Unable to detect valid Fusion version number from app " + f"name: {app_name}.\nMake sure to include at least a digit " + "to indicate the Fusion version like '18'.\n" + f"Detectable Fusion versions are: {version_names}" + ) + + _, profile_version = FUSION_VERSIONS_DICT[app_version] + fu_profile = self.get_fusion_profile_name(profile_version) + + # do a copy of Fusion profile if copy_status toggle is enabled + if copy_status and fu_profile_dir is not None: + profile_source = self.get_profile_source(profile_version) + dest_folder = Path(fu_profile_dir, fu_profile) + self.copy_fusion_profile(profile_source, dest_folder, force_sync) + + # Add temporary profile directory variables to customize Fusion + # to define where it can read custom scripts and tools from + fu_profile_dir_variable = f"FUSION{profile_version}_PROFILE_DIR" + self.log.info(f"Setting {fu_profile_dir_variable}: {fu_profile_dir}") + self.launch_context.env[fu_profile_dir_variable] = str(fu_profile_dir) + + # Add custom Fusion Master Prefs and the temporary + # profile directory variables to customize Fusion + # to define where it can read custom scripts and tools from + master_prefs_variable = f"FUSION{profile_version}_MasterPrefs" + master_prefs = Path(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") + self.log.info(f"Setting {master_prefs_variable}: {master_prefs}") + self.launch_context.env[master_prefs_variable] = str(master_prefs) diff --git a/openpype/hosts/fusion/hooks/pre_fusion_setup.py b/openpype/hosts/fusion/hooks/pre_fusion_setup.py index 323b8b0029b..f27cd1674ba 100644 --- a/openpype/hosts/fusion/hooks/pre_fusion_setup.py +++ b/openpype/hosts/fusion/hooks/pre_fusion_setup.py @@ -1,32 +1,43 @@ import os from openpype.lib import PreLaunchHook, ApplicationLaunchFailed -from openpype.hosts.fusion import FUSION_HOST_DIR +from openpype.hosts.fusion import ( + FUSION_HOST_DIR, + FUSION_VERSIONS_DICT, + get_fusion_version, +) class FusionPrelaunch(PreLaunchHook): - """Prepares OpenPype Fusion environment - - Requires FUSION_PYTHON3_HOME to be defined in the environment for Fusion - to point at a valid Python 3 build for Fusion. That is Python 3.3-3.10 - for Fusion 18 and Fusion 3.6 for Fusion 16 and 17. - - This also sets FUSION16_MasterPrefs to apply the fusion master prefs - as set in openpype/hosts/fusion/deploy/fusion_shared.prefs to enable - the OpenPype menu and force Python 3 over Python 2. - """ + Prepares OpenPype Fusion environment. + Requires correct Python home variable to be defined in the environment + settings for Fusion to point at a valid Python 3 build for Fusion. + Python3 versions that are supported by Fusion: + Fusion 9, 16, 17 : Python 3.6 + Fusion 18 : Python 3.6 - 3.10 + """ + app_groups = ["fusion"] + order = 1 def execute(self): # making sure python 3 is installed at provided path # Py 3.3-3.10 for Fusion 18+ or Py 3.6 for Fu 16-17 - py3_var = "FUSION_PYTHON3_HOME" + app_data = self.launch_context.env.get("AVALON_APP_NAME") + app_version = get_fusion_version(app_data) + if not app_version: + raise ApplicationLaunchFailed( + "Fusion version information not found in System settings.\n" + "The key field in the 'applications/fusion/variants' should " + "consist a number, corresponding to major Fusion version." + ) + py3_var, _ = FUSION_VERSIONS_DICT[app_version] fusion_python3_home = self.launch_context.env.get(py3_var, "") - self.log.info(f"Looking for Python 3 in: {fusion_python3_home}") for path in fusion_python3_home.split(os.pathsep): - # Allow defining multiple paths to allow "fallback" to other - # path. But make to set only a single path as final variable. + # Allow defining multiple paths, separated by os.pathsep, + # to allow "fallback" to other path. + # But make to set only a single path as final variable. py3_dir = os.path.normpath(path) if os.path.isdir(py3_dir): break @@ -43,19 +54,10 @@ def execute(self): self.launch_context.env[py3_var] = py3_dir # Fusion 18+ requires FUSION_PYTHON3_HOME to also be on PATH - self.launch_context.env["PATH"] += ";" + py3_dir + if app_version >= 18: + self.launch_context.env["PATH"] += os.pathsep + py3_dir - # Fusion 16 and 17 use FUSION16_PYTHON36_HOME instead of - # FUSION_PYTHON3_HOME and will only work with a Python 3.6 version - # TODO: Detect Fusion version to only set for specific Fusion build - self.launch_context.env["FUSION16_PYTHON36_HOME"] = py3_dir + self.launch_context.env[py3_var] = py3_dir - # Add our Fusion Master Prefs which is the only way to customize - # Fusion to define where it can read custom scripts and tools from self.log.info(f"Setting OPENPYPE_FUSION: {FUSION_HOST_DIR}") self.launch_context.env["OPENPYPE_FUSION"] = FUSION_HOST_DIR - - pref_var = "FUSION16_MasterPrefs" # used by Fusion 16, 17 and 18 - prefs = os.path.join(FUSION_HOST_DIR, "deploy", "fusion_shared.prefs") - self.log.info(f"Setting {pref_var}: {prefs}") - self.launch_context.env[pref_var] = prefs diff --git a/openpype/hosts/fusion/plugins/create/create_saver.py b/openpype/hosts/fusion/plugins/create/create_saver.py index e581bac20ff..56085b0a06b 100644 --- a/openpype/hosts/fusion/plugins/create/create_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_saver.py @@ -4,29 +4,34 @@ from openpype.hosts.fusion.api import ( get_current_comp, - comp_lock_and_undo_chunk + comp_lock_and_undo_chunk, ) -from openpype.lib import BoolDef +from openpype.lib import ( + BoolDef, + EnumDef, +) from openpype.pipeline import ( legacy_io, Creator, - CreatedInstance + CreatedInstance, +) +from openpype.client import ( + get_asset_by_name, ) -from openpype.client import get_asset_by_name class CreateSaver(Creator): identifier = "io.openpype.creators.fusion.saver" - name = "saver" - label = "Saver" + label = "Render (saver)" + name = "render" family = "render" - default_variants = ["Main"] - + default_variants = ["Main", "Mask"] description = "Fusion Saver to generate image sequence" - def create(self, subset_name, instance_data, pre_create_data): + instance_attributes = ["reviewable"] + def create(self, subset_name, instance_data, pre_create_data): # TODO: Add pre_create attributes to choose file format? file_format = "OpenEXRFormat" @@ -58,7 +63,8 @@ def create(self, subset_name, instance_data, pre_create_data): family=self.family, subset_name=subset_name, data=instance_data, - creator=self) + creator=self, + ) # Insert the transient data instance.transient_data["tool"] = saver @@ -68,11 +74,9 @@ def create(self, subset_name, instance_data, pre_create_data): return instance def collect_instances(self): - comp = get_current_comp() tools = comp.GetToolList(False, "Saver").values() for tool in tools: - data = self.get_managed_tool_data(tool) if not data: data = self._collect_unmanaged_saver(tool) @@ -90,7 +94,6 @@ def get_icon(self): def update_instances(self, update_list): for created_inst, _changes in update_list: - new_data = created_inst.data_to_store() tool = created_inst.transient_data["tool"] self._update_tool_with_data(tool, new_data) @@ -139,7 +142,6 @@ def _update_tool_with_data(self, tool, data): tool.SetAttrs({"TOOLS_Name": subset}) def _collect_unmanaged_saver(self, tool): - # TODO: this should not be done this way - this should actually # get the data as stored on the tool explicitly (however) # that would disallow any 'regular saver' to be collected @@ -153,8 +155,7 @@ def _collect_unmanaged_saver(self, tool): asset = legacy_io.Session["AVALON_ASSET"] task = legacy_io.Session["AVALON_TASK"] - asset_doc = get_asset_by_name(project_name=project, - asset_name=asset) + asset_doc = get_asset_by_name(project_name=project, asset_name=asset) path = tool["Clip"][comp.TIME_UNDEFINED] fname = os.path.basename(path) @@ -178,21 +179,20 @@ def _collect_unmanaged_saver(self, tool): "variant": variant, "active": not passthrough, "family": self.family, - # Unique identifier for instance and this creator "id": "pyblish.avalon.instance", - "creator_identifier": self.identifier + "creator_identifier": self.identifier, } def get_managed_tool_data(self, tool): """Return data of the tool if it matches creator identifier""" - data = tool.GetData('openpype') + data = tool.GetData("openpype") if not isinstance(data, dict): return required = { "id": "pyblish.avalon.instance", - "creator_identifier": self.identifier + "creator_identifier": self.identifier, } for key, value in required.items(): if key not in data or data[key] != value: @@ -205,11 +205,40 @@ def get_managed_tool_data(self, tool): return data + def get_pre_create_attr_defs(self): + """Settings for create page""" + attr_defs = [ + self._get_render_target_enum(), + self._get_reviewable_bool(), + ] + return attr_defs + def get_instance_attr_defs(self): - return [ - BoolDef( - "review", - default=True, - label="Review" - ) + """Settings for publish page""" + attr_defs = [ + self._get_render_target_enum(), + self._get_reviewable_bool(), ] + return attr_defs + + # These functions below should be moved to another file + # so it can be used by other plugins. plugin.py ? + + def _get_render_target_enum(self): + rendering_targets = { + "local": "Local machine rendering", + "frames": "Use existing frames", + } + if "farm_rendering" in self.instance_attributes: + rendering_targets["farm"] = "Farm rendering" + + return EnumDef( + "render_target", items=rendering_targets, label="Render target" + ) + + def _get_reviewable_bool(self): + return BoolDef( + "review", + default=("reviewable" in self.instance_attributes), + label="Review", + ) diff --git a/openpype/hosts/fusion/plugins/publish/collect_expected_frames.py b/openpype/hosts/fusion/plugins/publish/collect_expected_frames.py new file mode 100644 index 00000000000..0ba777629fa --- /dev/null +++ b/openpype/hosts/fusion/plugins/publish/collect_expected_frames.py @@ -0,0 +1,50 @@ +import pyblish.api +from openpype.pipeline import publish +import os + + +class CollectFusionExpectedFrames( + pyblish.api.InstancePlugin, publish.ColormanagedPyblishPluginMixin +): + """Collect all frames needed to publish expected frames""" + + order = pyblish.api.CollectorOrder + 0.5 + label = "Collect Expected Frames" + hosts = ["fusion"] + families = ["render"] + + def process(self, instance): + context = instance.context + + frame_start = context.data["frameStartHandle"] + frame_end = context.data["frameEndHandle"] + path = instance.data["path"] + output_dir = instance.data["outputDir"] + + basename = os.path.basename(path) + head, ext = os.path.splitext(basename) + files = [ + f"{head}{str(frame).zfill(4)}{ext}" + for frame in range(frame_start, frame_end + 1) + ] + repre = { + "name": ext[1:], + "ext": ext[1:], + "frameStart": f"%0{len(str(frame_end))}d" % frame_start, + "files": files, + "stagingDir": output_dir, + } + + self.set_representation_colorspace( + representation=repre, + context=context, + ) + + # review representation + if instance.data.get("review", False): + repre["tags"] = ["review"] + + # add the repre to the instance + if "representations" not in instance.data: + instance.data["representations"] = [] + instance.data["representations"].append(repre) diff --git a/openpype/hosts/fusion/plugins/publish/collect_render_target.py b/openpype/hosts/fusion/plugins/publish/collect_render_target.py deleted file mode 100644 index 39017f32e02..00000000000 --- a/openpype/hosts/fusion/plugins/publish/collect_render_target.py +++ /dev/null @@ -1,44 +0,0 @@ -import pyblish.api - - -class CollectFusionRenderMode(pyblish.api.InstancePlugin): - """Collect current comp's render Mode - - Options: - local - farm - - Note that this value is set for each comp separately. When you save the - comp this information will be stored in that file. If for some reason the - available tool does not visualize which render mode is set for the - current comp, please run the following line in the console (Py2) - - comp.GetData("openpype.rendermode") - - This will return the name of the current render mode as seen above under - Options. - - """ - - order = pyblish.api.CollectorOrder + 0.4 - label = "Collect Render Mode" - hosts = ["fusion"] - families = ["render"] - - def process(self, instance): - """Collect all image sequence tools""" - options = ["local", "farm"] - - comp = instance.context.data.get("currentComp") - if not comp: - raise RuntimeError("No comp previously collected, unable to " - "retrieve Fusion version.") - - rendermode = comp.GetData("openpype.rendermode") or "local" - assert rendermode in options, "Must be supported render mode" - - self.log.info("Render mode: {0}".format(rendermode)) - - # Append family - family = "render.{0}".format(rendermode) - instance.data["families"].append(family) diff --git a/openpype/hosts/fusion/plugins/publish/collect_renders.py b/openpype/hosts/fusion/plugins/publish/collect_renders.py new file mode 100644 index 00000000000..7f38e68447d --- /dev/null +++ b/openpype/hosts/fusion/plugins/publish/collect_renders.py @@ -0,0 +1,25 @@ +import pyblish.api + + +class CollectFusionRenders(pyblish.api.InstancePlugin): + """Collect current saver node's render Mode + + Options: + local (Render locally) + frames (Use existing frames) + + """ + + order = pyblish.api.CollectorOrder + 0.4 + label = "Collect Renders" + hosts = ["fusion"] + families = ["render"] + + def process(self, instance): + render_target = instance.data["render_target"] + family = instance.data["family"] + + # add targeted family to families + instance.data["families"].append( + "{}.{}".format(family, render_target) + ) diff --git a/openpype/hosts/fusion/plugins/publish/extract_render_local.py b/openpype/hosts/fusion/plugins/publish/extract_render_local.py new file mode 100644 index 00000000000..5a0140c5258 --- /dev/null +++ b/openpype/hosts/fusion/plugins/publish/extract_render_local.py @@ -0,0 +1,109 @@ +import logging +import contextlib +import pyblish.api +from openpype.hosts.fusion.api import comp_lock_and_undo_chunk + + +log = logging.getLogger(__name__) + + +@contextlib.contextmanager +def enabled_savers(comp, savers): + """Enable only the `savers` in Comp during the context. + + Any Saver tool in the passed composition that is not in the savers list + will be set to passthrough during the context. + + Args: + comp (object): Fusion composition object. + savers (list): List of Saver tool objects. + + """ + passthrough_key = "TOOLB_PassThrough" + original_states = {} + enabled_save_names = {saver.Name for saver in savers} + try: + all_savers = comp.GetToolList(False, "Saver").values() + for saver in all_savers: + original_state = saver.GetAttrs()[passthrough_key] + original_states[saver] = original_state + + # The passthrough state we want to set (passthrough != enabled) + state = saver.Name not in enabled_save_names + if state != original_state: + saver.SetAttrs({passthrough_key: state}) + yield + finally: + for saver, original_state in original_states.items(): + saver.SetAttrs({"TOOLB_PassThrough": original_state}) + + +class FusionRenderLocal(pyblish.api.InstancePlugin): + """Render the current Fusion composition locally.""" + + order = pyblish.api.ExtractorOrder - 0.2 + label = "Render Local" + hosts = ["fusion"] + families = ["render.local"] + + def process(self, instance): + context = instance.context + + # Start render + self.render_once(context) + + # Log render status + self.log.info( + "Rendered '{nm}' for asset '{ast}' under the task '{tsk}'".format( + nm=instance.data["name"], + ast=instance.data["asset"], + tsk=instance.data["task"], + ) + ) + + def render_once(self, context): + """Render context comp only once, even with more render instances""" + + # This plug-in assumes all render nodes get rendered at the same time + # to speed up the rendering. The check below makes sure that we only + # execute the rendering once and not for each instance. + key = f"__hasRun{self.__class__.__name__}" + + savers_to_render = [ + # Get the saver tool from the instance + instance[0] for instance in context if + # Only active instances + instance.data.get("publish", True) and + # Only render.local instances + "render.local" in instance.data["families"] + ] + + if key not in context.data: + # We initialize as false to indicate it wasn't successful yet + # so we can keep track of whether Fusion succeeded + context.data[key] = False + + current_comp = context.data["currentComp"] + frame_start = context.data["frameStartHandle"] + frame_end = context.data["frameEndHandle"] + + self.log.info("Starting Fusion render") + self.log.info(f"Start frame: {frame_start}") + self.log.info(f"End frame: {frame_end}") + saver_names = ", ".join(saver.Name for saver in savers_to_render) + self.log.info(f"Rendering tools: {saver_names}") + + with comp_lock_and_undo_chunk(current_comp): + with enabled_savers(current_comp, savers_to_render): + result = current_comp.Render( + { + "Start": frame_start, + "End": frame_end, + "Wait": True, + } + ) + + context.data[key] = bool(result) + + if context.data[key] is False: + raise RuntimeError("Comp render failed") diff --git a/openpype/hosts/fusion/plugins/publish/render_local.py b/openpype/hosts/fusion/plugins/publish/render_local.py deleted file mode 100644 index 7d5f1a40c72..00000000000 --- a/openpype/hosts/fusion/plugins/publish/render_local.py +++ /dev/null @@ -1,100 +0,0 @@ -import os -import pyblish.api -from openpype.pipeline import publish -from openpype.hosts.fusion.api import comp_lock_and_undo_chunk - - -class Fusionlocal(pyblish.api.InstancePlugin, - publish.ColormanagedPyblishPluginMixin): - """Render the current Fusion composition locally. - - Extract the result of savers by starting a comp render - This will run the local render of Fusion. - - """ - - order = pyblish.api.ExtractorOrder - 0.1 - label = "Render Local" - hosts = ["fusion"] - families = ["render.local"] - - def process(self, instance): - context = instance.context - - # Start render - self.render_once(context) - - # Log render status - self.log.info( - "Rendered '{nm}' for asset '{ast}' under the task '{tsk}'".format( - nm=instance.data["name"], - ast=instance.data["asset"], - tsk=instance.data["task"], - ) - ) - - frame_start = context.data["frameStartHandle"] - frame_end = context.data["frameEndHandle"] - path = instance.data["path"] - output_dir = instance.data["outputDir"] - - basename = os.path.basename(path) - head, ext = os.path.splitext(basename) - files = [ - f"{head}{str(frame).zfill(4)}{ext}" - for frame in range(frame_start, frame_end + 1) - ] - repre = { - "name": ext[1:], - "ext": ext[1:], - "frameStart": f"%0{len(str(frame_end))}d" % frame_start, - "files": files, - "stagingDir": output_dir, - } - - self.set_representation_colorspace( - representation=repre, - context=context, - ) - - if "representations" not in instance.data: - instance.data["representations"] = [] - instance.data["representations"].append(repre) - - # review representation - if instance.data.get("review", False): - repre["tags"] = ["review", "ftrackreview"] - - def render_once(self, context): - """Render context comp only once, even with more render instances""" - - # This plug-in assumes all render nodes get rendered at the same time - # to speed up the rendering. The check below makes sure that we only - # execute the rendering once and not for each instance. - key = f"__hasRun{self.__class__.__name__}" - if key not in context.data: - # We initialize as false to indicate it wasn't successful yet - # so we can keep track of whether Fusion succeeded - context.data[key] = False - - current_comp = context.data["currentComp"] - frame_start = context.data["frameStartHandle"] - frame_end = context.data["frameEndHandle"] - - self.log.info("Starting Fusion render") - self.log.info(f"Start frame: {frame_start}") - self.log.info(f"End frame: {frame_end}") - - with comp_lock_and_undo_chunk(current_comp): - result = current_comp.Render( - { - "Start": frame_start, - "End": frame_end, - "Wait": True, - } - ) - - context.data[key] = bool(result) - - if context.data[key] is False: - raise RuntimeError("Comp render failed") diff --git a/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py b/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py index ba943abacb0..8a91f23578c 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py +++ b/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py @@ -14,22 +14,19 @@ class ValidateCreateFolderChecked(pyblish.api.InstancePlugin): """ order = pyblish.api.ValidatorOrder - actions = [RepairAction] label = "Validate Create Folder Checked" families = ["render"] hosts = ["fusion"] - actions = [SelectInvalidAction] + actions = [RepairAction, SelectInvalidAction] @classmethod def get_invalid(cls, instance): - active = instance.data.get("active", instance.data.get("publish")) - if not active: - return [] - tool = instance[0] create_dir = tool.GetInput("CreateDir") if create_dir == 0.0: - cls.log.error("%s has Create Folder turned off" % instance[0].Name) + cls.log.error( + "%s has Create Folder turned off" % instance[0].Name + ) return [tool] def process(self, instance): @@ -37,7 +34,8 @@ def process(self, instance): if invalid: raise PublishValidationError( "Found Saver with Create Folder During Render checked off", - title=self.label) + title=self.label, + ) @classmethod def repair(cls, instance): diff --git a/openpype/hosts/fusion/plugins/publish/validate_expected_frames_existence.py b/openpype/hosts/fusion/plugins/publish/validate_expected_frames_existence.py new file mode 100644 index 00000000000..c208b8ef159 --- /dev/null +++ b/openpype/hosts/fusion/plugins/publish/validate_expected_frames_existence.py @@ -0,0 +1,78 @@ +import os +import pyblish.api + +from openpype.pipeline.publish import RepairAction +from openpype.pipeline import PublishValidationError + +from openpype.hosts.fusion.api.action import SelectInvalidAction + + +class ValidateLocalFramesExistence(pyblish.api.InstancePlugin): + """Checks if files for savers that's set + to publish expected frames exists + """ + + order = pyblish.api.ValidatorOrder + label = "Validate Expected Frames Exists" + families = ["render"] + hosts = ["fusion"] + actions = [RepairAction, SelectInvalidAction] + + @classmethod + def get_invalid(cls, instance, non_existing_frames=None): + if non_existing_frames is None: + non_existing_frames = [] + + if instance.data.get("render_target") == "frames": + tool = instance[0] + + frame_start = instance.data["frameStart"] + frame_end = instance.data["frameEnd"] + path = instance.data["path"] + output_dir = instance.data["outputDir"] + + basename = os.path.basename(path) + head, ext = os.path.splitext(basename) + files = [ + f"{head}{str(frame).zfill(4)}{ext}" + for frame in range(frame_start, frame_end + 1) + ] + + for file in files: + if not os.path.exists(os.path.join(output_dir, file)): + cls.log.error( + f"Missing file: {os.path.join(output_dir, file)}" + ) + non_existing_frames.append(file) + + if len(non_existing_frames) > 0: + cls.log.error(f"Some of {tool.Name}'s files does not exist") + return [tool] + + def process(self, instance): + non_existing_frames = [] + invalid = self.get_invalid(instance, non_existing_frames) + if invalid: + raise PublishValidationError( + "{} is set to publish existing frames but " + "some frames are missing. " + "The missing file(s) are:\n\n{}".format( + invalid[0].Name, + "\n\n".join(non_existing_frames), + ), + title=self.label, + ) + + @classmethod + def repair(cls, instance): + invalid = cls.get_invalid(instance) + if invalid: + tool = invalid[0] + + # Change render target to local to render locally + tool.SetData("openpype.creator_attributes.render_target", "local") + + cls.log.info( + f"Reload the publisher and {tool.Name} " + "will be set to render locally" + ) diff --git a/openpype/hosts/fusion/scripts/set_rendermode.py b/openpype/hosts/fusion/scripts/set_rendermode.py deleted file mode 100644 index 9d2bfef3107..00000000000 --- a/openpype/hosts/fusion/scripts/set_rendermode.py +++ /dev/null @@ -1,112 +0,0 @@ -from qtpy import QtWidgets -import qtawesome -from openpype.hosts.fusion.api import get_current_comp - - -_help = {"local": "Render the comp on your own machine and publish " - "it from that the destination folder", - "farm": "Submit a Fusion render job to a Render farm to use all other" - " computers and add a publish job"} - - -class SetRenderMode(QtWidgets.QWidget): - - def __init__(self, parent=None): - QtWidgets.QWidget.__init__(self, parent) - - self._comp = get_current_comp() - self._comp_name = self._get_comp_name() - - self.setWindowTitle("Set Render Mode") - self.setFixedSize(300, 175) - - layout = QtWidgets.QVBoxLayout() - - # region comp info - comp_info_layout = QtWidgets.QHBoxLayout() - - update_btn = QtWidgets.QPushButton(qtawesome.icon("fa.refresh", - color="white"), "") - update_btn.setFixedWidth(25) - update_btn.setFixedHeight(25) - - comp_information = QtWidgets.QLineEdit() - comp_information.setEnabled(False) - - comp_info_layout.addWidget(comp_information) - comp_info_layout.addWidget(update_btn) - # endregion comp info - - # region modes - mode_options = QtWidgets.QComboBox() - mode_options.addItems(_help.keys()) - - mode_information = QtWidgets.QTextEdit() - mode_information.setReadOnly(True) - # endregion modes - - accept_btn = QtWidgets.QPushButton("Accept") - - layout.addLayout(comp_info_layout) - layout.addWidget(mode_options) - layout.addWidget(mode_information) - layout.addWidget(accept_btn) - - self.setLayout(layout) - - self.comp_information = comp_information - self.update_btn = update_btn - - self.mode_options = mode_options - self.mode_information = mode_information - - self.accept_btn = accept_btn - - self.connections() - self.update() - - # Force updated render mode help text - self._update_rendermode_info() - - def connections(self): - """Build connections between code and buttons""" - - self.update_btn.clicked.connect(self.update) - self.accept_btn.clicked.connect(self._set_comp_rendermode) - self.mode_options.currentIndexChanged.connect( - self._update_rendermode_info) - - def update(self): - """Update all information in the UI""" - - self._comp = get_current_comp() - self._comp_name = self._get_comp_name() - self.comp_information.setText(self._comp_name) - - # Update current comp settings - mode = self._get_comp_rendermode() - index = self.mode_options.findText(mode) - self.mode_options.setCurrentIndex(index) - - def _update_rendermode_info(self): - rendermode = self.mode_options.currentText() - self.mode_information.setText(_help[rendermode]) - - def _get_comp_name(self): - return self._comp.GetAttrs("COMPS_Name") - - def _get_comp_rendermode(self): - return self._comp.GetData("openpype.rendermode") or "local" - - def _set_comp_rendermode(self): - rendermode = self.mode_options.currentText() - self._comp.SetData("openpype.rendermode", rendermode) - - self._comp.Print("Updated render mode to '%s'\n" % rendermode) - self.hide() - - def _validation(self): - ui_mode = self.mode_options.currentText() - comp_mode = self._get_comp_rendermode() - - return comp_mode == ui_mode diff --git a/openpype/hosts/hiero/api/lib.py b/openpype/hosts/hiero/api/lib.py index bbd1edc14a3..0d4368529f5 100644 --- a/openpype/hosts/hiero/api/lib.py +++ b/openpype/hosts/hiero/api/lib.py @@ -1221,7 +1221,7 @@ def set_track_color(track_item, color): def check_inventory_versions(track_items=None): """ - Actual version color idetifier of Loaded containers + Actual version color identifier of Loaded containers Check all track items and filter only Loader nodes for its version. It will get all versions from database @@ -1249,10 +1249,10 @@ def check_inventory_versions(track_items=None): project_name = legacy_io.active_project() filter_result = filter_containers(containers, project_name) for container in filter_result.latest: - set_track_color(container["_item"], clip_color) + set_track_color(container["_item"], clip_color_last) for container in filter_result.outdated: - set_track_color(container["_item"], clip_color_last) + set_track_color(container["_item"], clip_color) def selection_changed_timeline(event): diff --git a/openpype/hosts/hiero/api/plugin.py b/openpype/hosts/hiero/api/plugin.py index 07457db1a40..5ca901caaa2 100644 --- a/openpype/hosts/hiero/api/plugin.py +++ b/openpype/hosts/hiero/api/plugin.py @@ -146,6 +146,8 @@ def camel_case_split(self, text): return " ".join([str(m.group(0)).capitalize() for m in matches]) def create_row(self, layout, type, text, **kwargs): + value_keys = ["setText", "setCheckState", "setValue", "setChecked"] + # get type attribute from qwidgets attr = getattr(QtWidgets, type) @@ -167,14 +169,27 @@ def create_row(self, layout, type, text, **kwargs): # assign the created attribute to variable item = getattr(self, attr_name) + + # set attributes to item which are not values for func, val in kwargs.items(): + if func in value_keys: + continue + if getattr(item, func): + log.debug("Setting {} to {}".format(func, val)) func_attr = getattr(item, func) if isinstance(val, tuple): func_attr(*val) else: func_attr(val) + # set values to item + for value_item in value_keys: + if value_item not in kwargs: + continue + if getattr(item, value_item): + getattr(item, value_item)(kwargs[value_item]) + # add to layout layout.addRow(label, item) @@ -276,8 +291,11 @@ def populate_widgets(self, data, content_layout=None): elif v["type"] == "QSpinBox": data[k]["value"] = self.create_row( content_layout, "QSpinBox", v["label"], - setValue=v["value"], setMinimum=0, + setValue=v["value"], + setDisplayIntegerBase=10000, + setRange=(0, 99999), setMinimum=0, setMaximum=100000, setToolTip=tool_tip) + return data diff --git a/openpype/hosts/houdini/startup/MainMenuCommon.xml b/openpype/hosts/houdini/startup/MainMenuCommon.xml index c08114b71bc..47a4653d5d7 100644 --- a/openpype/hosts/houdini/startup/MainMenuCommon.xml +++ b/openpype/hosts/houdini/startup/MainMenuCommon.xml @@ -10,7 +10,7 @@ import hou from openpype.tools.utils import host_tools parent = hou.qt.mainWindow() -host_tools.show_creator(parent) +host_tools.show_publisher(parent, tab="create") ]]> @@ -30,7 +30,7 @@ host_tools.show_loader(parent=parent, use_context=True) import hou from openpype.tools.utils import host_tools parent = hou.qt.mainWindow() -host_tools.show_publisher(parent) +host_tools.show_publisher(parent, tab="publish") ]]> @@ -66,8 +66,8 @@ host_tools.show_workfiles(parent) ]]> - - + + dict: + """Get the current assets frame range and handles. + + Returns: + dict: with frame start, frame end, handle start, handle end. + """ + # Set frame start/end + asset = get_current_project_asset() + frame_start = asset["data"].get("frameStart") + frame_end = asset["data"].get("frameEnd") + # Backwards compatibility + if frame_start is None or frame_end is None: + frame_start = asset["data"].get("edit_in") + frame_end = asset["data"].get("edit_out") + if frame_start is None or frame_end is None: + return + handles = asset["data"].get("handles") or 0 + handle_start = asset["data"].get("handleStart") + if handle_start is None: + handle_start = handles + handle_end = asset["data"].get("handleEnd") + if handle_end is None: + handle_end = handles + return { + "frameStart": frame_start, + "frameEnd": frame_end, + "handleStart": handle_start, + "handleEnd": handle_end + } + + +def reset_frame_range(fps: bool = True): + """Set frame range to current asset. + This is part of 3dsmax documentation: + + animationRange: A System Global variable which lets you get and + set an Interval value that defines the start and end frames + of the Active Time Segment. + frameRate: A System Global variable which lets you get + and set an Integer value that defines the current + scene frame rate in frames-per-second. + """ + if fps: + data_fps = get_current_project(fields=["data.fps"]) + fps_number = float(data_fps["data"]["fps"]) + rt.frameRate = fps_number + frame_range = get_frame_range() + frame_start = frame_range["frameStart"] - int(frame_range["handleStart"]) + frame_end = frame_range["frameEnd"] + int(frame_range["handleEnd"]) + frange_cmd = f"animationRange = interval {frame_start} {frame_end}" + rt.execute(frange_cmd) + + +def set_context_setting(): + """Apply the project settings from the project definition + + Settings can be overwritten by an asset if the asset.data contains + any information regarding those settings. + + Examples of settings: + frame range + resolution + + Returns: + None + """ + reset_scene_resolution() + + def get_max_version(): """ Args: diff --git a/openpype/hosts/max/api/lib_renderproducts.py b/openpype/hosts/max/api/lib_renderproducts.py index a74a6a74263..350eb976619 100644 --- a/openpype/hosts/max/api/lib_renderproducts.py +++ b/openpype/hosts/max/api/lib_renderproducts.py @@ -8,6 +8,7 @@ get_current_renderer, get_default_render_folder ) +from openpype.pipeline.context_tools import get_current_project_asset from openpype.settings import get_project_settings from openpype.pipeline import legacy_io @@ -34,14 +35,20 @@ def render_product(self, container): filename, container) + context = get_current_project_asset() + startFrame = context["data"].get("frameStart") + endFrame = context["data"].get("frameEnd") + 1 + img_fmt = self._project_settings["max"]["RenderSettings"]["image_format"] # noqa - full_render_list = [] - beauty = self.beauty_render_product(output_file, img_fmt) - full_render_list.append(beauty) + full_render_list = self.beauty_render_product(output_file, + startFrame, + endFrame, + img_fmt) renderer_class = get_current_renderer() renderer = str(renderer_class).split(":")[0] + if renderer == "VUE_File_Renderer": return full_render_list @@ -54,6 +61,8 @@ def render_product(self, container): "Quicksilver_Hardware_Renderer", ]: render_elem_list = self.render_elements_product(output_file, + startFrame, + endFrame, img_fmt) if render_elem_list: full_render_list.extend(iter(render_elem_list)) @@ -61,18 +70,24 @@ def render_product(self, container): if renderer == "Arnold": aov_list = self.arnold_render_product(output_file, + startFrame, + endFrame, img_fmt) if aov_list: full_render_list.extend(iter(aov_list)) return full_render_list - def beauty_render_product(self, folder, fmt): - beauty_output = f"{folder}.####.{fmt}" - beauty_output = beauty_output.replace("\\", "/") - return beauty_output + def beauty_render_product(self, folder, startFrame, endFrame, fmt): + beauty_frame_range = [] + for f in range(startFrame, endFrame): + beauty_output = f"{folder}.{f}.{fmt}" + beauty_output = beauty_output.replace("\\", "/") + beauty_frame_range.append(beauty_output) + + return beauty_frame_range # TODO: Get the arnold render product - def arnold_render_product(self, folder, fmt): + def arnold_render_product(self, folder, startFrame, endFrame, fmt): """Get all the Arnold AOVs""" aovs = [] @@ -85,15 +100,17 @@ def arnold_render_product(self, folder, fmt): for i in range(aov_group_num): # get the specific AOV group for aov in aov_mgr.drivers[i].aov_list: - render_element = f"{folder}_{aov.name}.####.{fmt}" - render_element = render_element.replace("\\", "/") - aovs.append(render_element) + for f in range(startFrame, endFrame): + render_element = f"{folder}_{aov.name}.{f}.{fmt}" + render_element = render_element.replace("\\", "/") + aovs.append(render_element) + # close the AOVs manager window amw.close() return aovs - def render_elements_product(self, folder, fmt): + def render_elements_product(self, folder, startFrame, endFrame, fmt): """Get all the render element output files. """ render_dirname = [] @@ -104,9 +121,10 @@ def render_elements_product(self, folder, fmt): renderlayer_name = render_elem.GetRenderElement(i) target, renderpass = str(renderlayer_name).split(":") if renderlayer_name.enabled: - render_element = f"{folder}_{renderpass}.####.{fmt}" - render_element = render_element.replace("\\", "/") - render_dirname.append(render_element) + for f in range(startFrame, endFrame): + render_element = f"{folder}_{renderpass}.{f}.{fmt}" + render_element = render_element.replace("\\", "/") + render_dirname.append(render_element) return render_dirname diff --git a/openpype/hosts/max/api/menu.py b/openpype/hosts/max/api/menu.py index 5c273b49b4c..066cc900394 100644 --- a/openpype/hosts/max/api/menu.py +++ b/openpype/hosts/max/api/menu.py @@ -4,6 +4,7 @@ from pymxs import runtime as rt from openpype.tools.utils import host_tools +from openpype.hosts.max.api import lib class OpenPypeMenu(object): @@ -107,6 +108,17 @@ def build_openpype_menu(self) -> QtWidgets.QAction: workfiles_action = QtWidgets.QAction("Work Files...", openpype_menu) workfiles_action.triggered.connect(self.workfiles_callback) openpype_menu.addAction(workfiles_action) + + openpype_menu.addSeparator() + + res_action = QtWidgets.QAction("Set Resolution", openpype_menu) + res_action.triggered.connect(self.resolution_callback) + openpype_menu.addAction(res_action) + + frame_action = QtWidgets.QAction("Set Frame Range", openpype_menu) + frame_action.triggered.connect(self.frame_range_callback) + openpype_menu.addAction(frame_action) + return openpype_menu def load_callback(self): @@ -128,3 +140,11 @@ def library_callback(self): def workfiles_callback(self): """Callback to show Workfiles tool.""" host_tools.show_workfiles(parent=self.main_widget) + + def resolution_callback(self): + """Callback to reset scene resolution""" + return lib.reset_scene_resolution() + + def frame_range_callback(self): + """Callback to reset frame range""" + return lib.reset_frame_range() diff --git a/openpype/hosts/max/api/pipeline.py b/openpype/hosts/max/api/pipeline.py index f8a7b8ea5c1..dacc402318d 100644 --- a/openpype/hosts/max/api/pipeline.py +++ b/openpype/hosts/max/api/pipeline.py @@ -50,6 +50,11 @@ def install(self): self._has_been_setup = True + def context_setting(): + return lib.set_context_setting() + rt.callbacks.addScript(rt.Name('systemPostNew'), + context_setting) + def has_unsaved_changes(self): # TODO: how to get it from 3dsmax? return True diff --git a/openpype/hosts/max/api/plugin.py b/openpype/hosts/max/api/plugin.py index c16d9e61ecd..b54568b360c 100644 --- a/openpype/hosts/max/api/plugin.py +++ b/openpype/hosts/max/api/plugin.py @@ -101,7 +101,9 @@ def remove_instances(self, instances): instance_node = rt.getNodeByName( instance.data.get("instance_node")) if instance_node: - rt.delete(rt.getNodeByName(instance_node)) + rt.select(instance_node) + rt.execute(f'for o in selection do for c in o.children do c.parent = undefined') # noqa + rt.delete(instance_node) self._remove_instance_from_context(instance) diff --git a/openpype/hosts/max/plugins/create/create_maxScene.py b/openpype/hosts/max/plugins/create/create_maxScene.py new file mode 100644 index 00000000000..7900336f32a --- /dev/null +++ b/openpype/hosts/max/plugins/create/create_maxScene.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +"""Creator plugin for creating raw max scene.""" +from openpype.hosts.max.api import plugin +from openpype.pipeline import CreatedInstance + + +class CreateMaxScene(plugin.MaxCreator): + identifier = "io.openpype.creators.max.maxScene" + label = "Max Scene" + family = "maxScene" + icon = "gear" + + def create(self, subset_name, instance_data, pre_create_data): + from pymxs import runtime as rt + sel_obj = list(rt.selection) + instance = super(CreateMaxScene, self).create( + subset_name, + instance_data, + pre_create_data) # type: CreatedInstance + container = rt.getNodeByName(instance.data.get("instance_node")) + # TODO: Disable "Add to Containers?" Panel + # parent the selected cameras into the container + for obj in sel_obj: + obj.parent = container + # for additional work on the node: + # instance_node = rt.getNodeByName(instance.get("instance_node")) diff --git a/openpype/hosts/max/plugins/create/create_pointcloud.py b/openpype/hosts/max/plugins/create/create_pointcloud.py new file mode 100644 index 00000000000..c83acac3dfe --- /dev/null +++ b/openpype/hosts/max/plugins/create/create_pointcloud.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +"""Creator plugin for creating point cloud.""" +from openpype.hosts.max.api import plugin +from openpype.pipeline import CreatedInstance + + +class CreatePointCloud(plugin.MaxCreator): + identifier = "io.openpype.creators.max.pointcloud" + label = "Point Cloud" + family = "pointcloud" + icon = "gear" + + def create(self, subset_name, instance_data, pre_create_data): + from pymxs import runtime as rt + sel_obj = list(rt.selection) + instance = super(CreatePointCloud, self).create( + subset_name, + instance_data, + pre_create_data) # type: CreatedInstance + container = rt.getNodeByName(instance.data.get("instance_node")) + # TODO: Disable "Add to Containers?" Panel + # parent the selected cameras into the container + for obj in sel_obj: + obj.parent = container + # for additional work on the node: + # instance_node = rt.getNodeByName(instance.get("instance_node")) diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index b863b9363f5..460f4822a64 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -9,7 +9,8 @@ class MaxSceneLoader(load.LoaderPlugin): """Max Scene Loader""" - families = ["camera"] + families = ["camera", + "maxScene"] representations = ["max"] order = -8 icon = "code-fork" @@ -46,8 +47,7 @@ def update(self, container, representation): path = get_representation_path(representation) node = rt.getNodeByName(container["instance_node"]) - - max_objects = self.get_container_children(node) + max_objects = node.Children for max_object in max_objects: max_object.source = path diff --git a/openpype/hosts/max/plugins/load/load_pointcloud.py b/openpype/hosts/max/plugins/load/load_pointcloud.py new file mode 100644 index 00000000000..27bc88b4f32 --- /dev/null +++ b/openpype/hosts/max/plugins/load/load_pointcloud.py @@ -0,0 +1,51 @@ +import os +from openpype.pipeline import ( + load, get_representation_path +) +from openpype.hosts.max.api.pipeline import containerise +from openpype.hosts.max.api import lib + + +class PointCloudLoader(load.LoaderPlugin): + """Point Cloud Loader""" + + families = ["pointcloud"] + representations = ["prt"] + order = -8 + icon = "code-fork" + color = "green" + + def load(self, context, name=None, namespace=None, data=None): + """load point cloud by tyCache""" + from pymxs import runtime as rt + + filepath = os.path.normpath(self.fname) + obj = rt.tyCache() + obj.filename = filepath + + prt_container = rt.getNodeByName(f"{obj.name}") + + return containerise( + name, [prt_container], context, loader=self.__class__.__name__) + + def update(self, container, representation): + """update the container""" + from pymxs import runtime as rt + + path = get_representation_path(representation) + node = rt.getNodeByName(container["instance_node"]) + + prt_objects = self.get_container_children(node) + for prt_object in prt_objects: + prt_object.source = path + + lib.imprint(container["instance_node"], { + "representation": str(representation["_id"]) + }) + + def remove(self, container): + """remove the container""" + from pymxs import runtime as rt + + node = rt.getNodeByName(container["instance_node"]) + rt.delete(node) diff --git a/openpype/hosts/max/plugins/publish/collect_render.py b/openpype/hosts/max/plugins/publish/collect_render.py index 7c9e311c2fb..63e4108c849 100644 --- a/openpype/hosts/max/plugins/publish/collect_render.py +++ b/openpype/hosts/max/plugins/publish/collect_render.py @@ -61,7 +61,7 @@ def process(self, instance): "plugin": "3dsmax", "frameStart": context.data['frameStart'], "frameEnd": context.data['frameEnd'], - "version": version_int + "version": version_int, } self.log.info("data: {0}".format(data)) instance.data.update(data) diff --git a/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py b/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py index cacc84c5912..969f87be481 100644 --- a/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py +++ b/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py @@ -20,7 +20,8 @@ class ExtractMaxSceneRaw(publish.Extractor, order = pyblish.api.ExtractorOrder - 0.2 label = "Extract Max Scene (Raw)" hosts = ["max"] - families = ["camera"] + families = ["camera", + "maxScene"] optional = True def process(self, instance): diff --git a/openpype/hosts/max/plugins/publish/extract_pointcloud.py b/openpype/hosts/max/plugins/publish/extract_pointcloud.py new file mode 100644 index 00000000000..e8d58ab7134 --- /dev/null +++ b/openpype/hosts/max/plugins/publish/extract_pointcloud.py @@ -0,0 +1,207 @@ +import os +import pyblish.api +from openpype.pipeline import publish +from pymxs import runtime as rt +from openpype.hosts.max.api import ( + maintained_selection +) +from openpype.settings import get_project_settings +from openpype.pipeline import legacy_io + + +def get_setting(project_setting=None): + project_setting = get_project_settings( + legacy_io.Session["AVALON_PROJECT"] + ) + return (project_setting["max"]["PointCloud"]) + + +class ExtractPointCloud(publish.Extractor): + """ + Extract PRT format with tyFlow operators + + Notes: + Currently only works for the default partition setting + + Args: + export_particle(): sets up all job arguments for attributes + to be exported in MAXscript + + get_operators(): get the export_particle operator + + get_custom_attr(): get all custom channel attributes from Openpype + setting and sets it as job arguments before exporting + + get_files(): get the files with tyFlow naming convention + before publishing + + partition_output_name(): get the naming with partition settings. + get_partition(): get partition value + + """ + + order = pyblish.api.ExtractorOrder - 0.2 + label = "Extract Point Cloud" + hosts = ["max"] + families = ["pointcloud"] + + def process(self, instance): + start = int(instance.context.data.get("frameStart")) + end = int(instance.context.data.get("frameEnd")) + container = instance.data["instance_node"] + self.log.info("Extracting PRT...") + + stagingdir = self.staging_dir(instance) + filename = "{name}.prt".format(**instance.data) + path = os.path.join(stagingdir, filename) + + with maintained_selection(): + job_args = self.export_particle(container, + start, + end, + path) + for job in job_args: + rt.execute(job) + + self.log.info("Performing Extraction ...") + if "representations" not in instance.data: + instance.data["representations"] = [] + + self.log.info("Writing PRT with TyFlow Plugin...") + filenames = self.get_files(container, path, start, end) + self.log.debug("filenames: {0}".format(filenames)) + + partition = self.partition_output_name(container) + + representation = { + 'name': 'prt', + 'ext': 'prt', + 'files': filenames if len(filenames) > 1 else filenames[0], + "stagingDir": stagingdir, + "outputName": partition # partition value + } + instance.data["representations"].append(representation) + self.log.info("Extracted instance '%s' to: %s" % (instance.name, + path)) + + def export_particle(self, + container, + start, + end, + filepath): + job_args = [] + opt_list = self.get_operators(container) + for operator in opt_list: + start_frame = "{0}.frameStart={1}".format(operator, + start) + job_args.append(start_frame) + end_frame = "{0}.frameEnd={1}".format(operator, + end) + job_args.append(end_frame) + filepath = filepath.replace("\\", "/") + prt_filename = '{0}.PRTFilename="{1}"'.format(operator, + filepath) + + job_args.append(prt_filename) + # Partition + mode = "{0}.PRTPartitionsMode=2".format(operator) + job_args.append(mode) + + additional_args = self.get_custom_attr(operator) + for args in additional_args: + job_args.append(args) + + prt_export = "{0}.exportPRT()".format(operator) + job_args.append(prt_export) + + return job_args + + def get_operators(self, container): + """Get Export Particles Operator""" + + opt_list = [] + node = rt.getNodebyName(container) + selection_list = list(node.Children) + for sel in selection_list: + obj = sel.baseobject + # TODO: to see if it can be used maxscript instead + anim_names = rt.getsubanimnames(obj) + for anim_name in anim_names: + sub_anim = rt.getsubanim(obj, anim_name) + boolean = rt.isProperty(sub_anim, "Export_Particles") + event_name = sub_anim.name + if boolean: + opt = "${0}.{1}.export_particles".format(sel.name, + event_name) + opt_list.append(opt) + + return opt_list + + def get_custom_attr(self, operator): + """Get Custom Attributes""" + + custom_attr_list = [] + attr_settings = get_setting()["attribute"] + for key, value in attr_settings.items(): + custom_attr = "{0}.PRTChannels_{1}=True".format(operator, + value) + self.log.debug( + "{0} will be added as custom attribute".format(key) + ) + custom_attr_list.append(custom_attr) + + return custom_attr_list + + def get_files(self, + container, + path, + start_frame, + end_frame): + """ + Note: + Set the filenames accordingly to the tyFlow file + naming extension for the publishing purpose + + Actual File Output from tyFlow: + __partof..prt + e.g. tyFlow_cloth_CCCS_blobbyFill_001__part1of1_00004.prt + """ + filenames = [] + filename = os.path.basename(path) + orig_name, ext = os.path.splitext(filename) + partition_count, partition_start = self.get_partition(container) + for frame in range(int(start_frame), int(end_frame) + 1): + actual_name = "{}__part{:03}of{}_{:05}".format(orig_name, + partition_start, + partition_count, + frame) + actual_filename = path.replace(orig_name, actual_name) + filenames.append(os.path.basename(actual_filename)) + + return filenames + + def partition_output_name(self, container): + """ + Notes: + Partition output name set for mapping + the published file output + + todo: + Customizes the setting for the output + """ + partition_count, partition_start = self.get_partition(container) + partition = "_part{:03}of{}".format(partition_start, + partition_count) + + return partition + + def get_partition(self, container): + """ + Get Partition Value + """ + opt_list = self.get_operators(container) + for operator in opt_list: + count = rt.execute(f'{operator}.PRTPartitionsCount') + start = rt.execute(f'{operator}.PRTPartitionsFrom') + + return count, start diff --git a/openpype/hosts/max/plugins/publish/increment_workfile_version.py b/openpype/hosts/max/plugins/publish/increment_workfile_version.py new file mode 100644 index 00000000000..3dec214f777 --- /dev/null +++ b/openpype/hosts/max/plugins/publish/increment_workfile_version.py @@ -0,0 +1,19 @@ +import pyblish.api +from openpype.lib import version_up +from pymxs import runtime as rt + + +class IncrementWorkfileVersion(pyblish.api.ContextPlugin): + """Increment current workfile version.""" + + order = pyblish.api.IntegratorOrder + 0.9 + label = "Increment Workfile Version" + hosts = ["max"] + families = ["workfile"] + + def process(self, context): + path = context.data["currentFile"] + filepath = version_up(path) + + rt.saveMaxFile(filepath) + self.log.info("Incrementing file version") diff --git a/openpype/hosts/max/plugins/publish/validate_no_max_content.py b/openpype/hosts/max/plugins/publish/validate_no_max_content.py new file mode 100644 index 00000000000..c20a1968ede --- /dev/null +++ b/openpype/hosts/max/plugins/publish/validate_no_max_content.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +import pyblish.api +from openpype.pipeline import PublishValidationError +from pymxs import runtime as rt + + +class ValidateMaxContents(pyblish.api.InstancePlugin): + """Validates Max contents. + + Check if MaxScene container includes any contents underneath. + """ + + order = pyblish.api.ValidatorOrder + families = ["camera", + "maxScene", + "maxrender"] + hosts = ["max"] + label = "Max Scene Contents" + + def process(self, instance): + container = rt.getNodeByName(instance.data["instance_node"]) + if not list(container.Children): + raise PublishValidationError("No content found in the container") diff --git a/openpype/hosts/max/plugins/publish/validate_pointcloud.py b/openpype/hosts/max/plugins/publish/validate_pointcloud.py new file mode 100644 index 00000000000..f6540586483 --- /dev/null +++ b/openpype/hosts/max/plugins/publish/validate_pointcloud.py @@ -0,0 +1,191 @@ +import pyblish.api +from openpype.pipeline import PublishValidationError +from pymxs import runtime as rt +from openpype.settings import get_project_settings +from openpype.pipeline import legacy_io + + +def get_setting(project_setting=None): + project_setting = get_project_settings( + legacy_io.Session["AVALON_PROJECT"] + ) + return (project_setting["max"]["PointCloud"]) + + +class ValidatePointCloud(pyblish.api.InstancePlugin): + """Validate that workfile was saved.""" + + order = pyblish.api.ValidatorOrder + families = ["pointcloud"] + hosts = ["max"] + label = "Validate Point Cloud" + + def process(self, instance): + """ + Notes: + + 1. Validate the container only include tyFlow objects + 2. Validate if tyFlow operator Export Particle exists + 3. Validate if the export mode of Export Particle is at PRT format + 4. Validate the partition count and range set as default value + Partition Count : 100 + Partition Range : 1 to 1 + 5. Validate if the custom attribute(s) exist as parameter(s) + of export_particle operator + + """ + invalid = self.get_tyFlow_object(instance) + if invalid: + raise PublishValidationError("Non tyFlow object " + "found: {}".format(invalid)) + invalid = self.get_tyFlow_operator(instance) + if invalid: + raise PublishValidationError("tyFlow ExportParticle operator " + "not found: {}".format(invalid)) + + invalid = self.validate_export_mode(instance) + if invalid: + raise PublishValidationError("The export mode is not at PRT") + + invalid = self.validate_partition_value(instance) + if invalid: + raise PublishValidationError("tyFlow Partition setting is " + "not at the default value") + invalid = self.validate_custom_attribute(instance) + if invalid: + raise PublishValidationError("Custom Attribute not found " + ":{}".format(invalid)) + + def get_tyFlow_object(self, instance): + invalid = [] + container = instance.data["instance_node"] + self.log.info("Validating tyFlow container " + "for {}".format(container)) + + con = rt.getNodeByName(container) + selection_list = list(con.Children) + for sel in selection_list: + sel_tmp = str(sel) + if rt.classOf(sel) in [rt.tyFlow, + rt.Editable_Mesh]: + if "tyFlow" not in sel_tmp: + invalid.append(sel) + else: + invalid.append(sel) + + return invalid + + def get_tyFlow_operator(self, instance): + invalid = [] + container = instance.data["instance_node"] + self.log.info("Validating tyFlow object " + "for {}".format(container)) + + con = rt.getNodeByName(container) + selection_list = list(con.Children) + bool_list = [] + for sel in selection_list: + obj = sel.baseobject + anim_names = rt.getsubanimnames(obj) + for anim_name in anim_names: + # get all the names of the related tyFlow nodes + sub_anim = rt.getsubanim(obj, anim_name) + # check if there is export particle operator + boolean = rt.isProperty(sub_anim, "Export_Particles") + bool_list.append(str(boolean)) + # if the export_particles property is not there + # it means there is not a "Export Particle" operator + if "True" not in bool_list: + self.log.error("Operator 'Export Particles' not found!") + invalid.append(sel) + + return invalid + + def validate_custom_attribute(self, instance): + invalid = [] + container = instance.data["instance_node"] + self.log.info("Validating tyFlow custom " + "attributes for {}".format(container)) + + con = rt.getNodeByName(container) + selection_list = list(con.Children) + for sel in selection_list: + obj = sel.baseobject + anim_names = rt.getsubanimnames(obj) + for anim_name in anim_names: + # get all the names of the related tyFlow nodes + sub_anim = rt.getsubanim(obj, anim_name) + # check if there is export particle operator + boolean = rt.isProperty(sub_anim, "Export_Particles") + event_name = sub_anim.name + if boolean: + opt = "${0}.{1}.export_particles".format(sel.name, + event_name) + attributes = get_setting()["attribute"] + for key, value in attributes.items(): + custom_attr = "{0}.PRTChannels_{1}".format(opt, + value) + try: + rt.execute(custom_attr) + except RuntimeError: + invalid.add(key) + + return invalid + + def validate_partition_value(self, instance): + invalid = [] + container = instance.data["instance_node"] + self.log.info("Validating tyFlow partition " + "value for {}".format(container)) + + con = rt.getNodeByName(container) + selection_list = list(con.Children) + for sel in selection_list: + obj = sel.baseobject + anim_names = rt.getsubanimnames(obj) + for anim_name in anim_names: + # get all the names of the related tyFlow nodes + sub_anim = rt.getsubanim(obj, anim_name) + # check if there is export particle operator + boolean = rt.isProperty(sub_anim, "Export_Particles") + event_name = sub_anim.name + if boolean: + opt = "${0}.{1}.export_particles".format(sel.name, + event_name) + count = rt.execute(f'{opt}.PRTPartitionsCount') + if count != 100: + invalid.append(count) + start = rt.execute(f'{opt}.PRTPartitionsFrom') + if start != 1: + invalid.append(start) + end = rt.execute(f'{opt}.PRTPartitionsTo') + if end != 1: + invalid.append(end) + + return invalid + + def validate_export_mode(self, instance): + invalid = [] + container = instance.data["instance_node"] + self.log.info("Validating tyFlow export " + "mode for {}".format(container)) + + con = rt.getNodeByName(container) + selection_list = list(con.Children) + for sel in selection_list: + obj = sel.baseobject + anim_names = rt.getsubanimnames(obj) + for anim_name in anim_names: + # get all the names of the related tyFlow nodes + sub_anim = rt.getsubanim(obj, anim_name) + # check if there is export particle operator + boolean = rt.isProperty(sub_anim, "Export_Particles") + event_name = sub_anim.name + if boolean: + opt = "${0}.{1}.export_particles".format(sel.name, + event_name) + export_mode = rt.execute(f'{opt}.exportMode') + if export_mode != 1: + invalid.append(export_mode) + + return invalid diff --git a/openpype/hosts/maya/api/customize.py b/openpype/hosts/maya/api/customize.py index f66858dfb6b..f4c4d6ed887 100644 --- a/openpype/hosts/maya/api/customize.py +++ b/openpype/hosts/maya/api/customize.py @@ -11,6 +11,7 @@ from openpype import resources from openpype.tools.utils import host_tools from .lib import get_main_window +from ..tools import show_look_assigner log = logging.getLogger(__name__) @@ -112,7 +113,7 @@ def override_toolbox_ui(): annotation="Look Manager", label="Look Manager", image=os.path.join(icons, "lookmanager.png"), - command=host_tools.show_look_assigner, + command=show_look_assigner, width=icon_size, height=icon_size, parent=parent diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index 954576f02ec..aa1e501578c 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -2099,29 +2099,40 @@ def get_frame_range(): } -def reset_frame_range(): - """Set frame range to current asset""" +def reset_frame_range(playback=True, render=True, fps=True): + """Set frame range to current asset - fps = convert_to_maya_fps( - float(legacy_io.Session.get("AVALON_FPS", 25)) - ) - set_scene_fps(fps) + Args: + playback (bool, Optional): Whether to set the maya timeline playback + frame range. Defaults to True. + render (bool, Optional): Whether to set the maya render frame range. + Defaults to True. + fps (bool, Optional): Whether to set scene FPS. Defaults to True. + """ + + if fps: + fps = convert_to_maya_fps( + float(legacy_io.Session.get("AVALON_FPS", 25)) + ) + set_scene_fps(fps) frame_range = get_frame_range() frame_start = frame_range["frameStart"] - int(frame_range["handleStart"]) frame_end = frame_range["frameEnd"] + int(frame_range["handleEnd"]) - cmds.playbackOptions(minTime=frame_start) - cmds.playbackOptions(maxTime=frame_end) - cmds.playbackOptions(animationStartTime=frame_start) - cmds.playbackOptions(animationEndTime=frame_end) - cmds.playbackOptions(minTime=frame_start) - cmds.playbackOptions(maxTime=frame_end) - cmds.currentTime(frame_start) + if playback: + cmds.playbackOptions(minTime=frame_start) + cmds.playbackOptions(maxTime=frame_end) + cmds.playbackOptions(animationStartTime=frame_start) + cmds.playbackOptions(animationEndTime=frame_end) + cmds.playbackOptions(minTime=frame_start) + cmds.playbackOptions(maxTime=frame_end) + cmds.currentTime(frame_start) - cmds.setAttr("defaultRenderGlobals.startFrame", frame_start) - cmds.setAttr("defaultRenderGlobals.endFrame", frame_end) + if render: + cmds.setAttr("defaultRenderGlobals.startFrame", frame_start) + cmds.setAttr("defaultRenderGlobals.endFrame", frame_end) def reset_scene_resolution(): @@ -3576,6 +3587,65 @@ def get_color_management_output_transform(): return colorspace +def image_info(file_path): + # type: (str) -> dict + """Based on tha texture path, get its bit depth and format information. + Take reference from makeTx.py in Arnold: + ImageInfo(filename): Get Image Information for colorspace + AiTextureGetFormat(filename): Get Texture Format + AiTextureGetBitDepth(filename): Get Texture bit depth + Args: + file_path (str): Path to the texture file. + Returns: + dict: Dictionary with the information about the texture file. + """ + from arnold import ( + AiTextureGetBitDepth, + AiTextureGetFormat + ) + # Get Texture Information + img_info = {'filename': file_path} + if os.path.isfile(file_path): + img_info['bit_depth'] = AiTextureGetBitDepth(file_path) # noqa + img_info['format'] = AiTextureGetFormat(file_path) # noqa + else: + img_info['bit_depth'] = 8 + img_info['format'] = "unknown" + return img_info + + +def guess_colorspace(img_info): + # type: (dict) -> str + """Guess the colorspace of the input image filename. + Note: + Reference from makeTx.py + Args: + img_info (dict): Image info generated by :func:`image_info` + Returns: + str: color space name use in the `--colorconvert` + option of maketx. + """ + from arnold import ( + AiTextureInvalidate, + # types + AI_TYPE_BYTE, + AI_TYPE_INT, + AI_TYPE_UINT + ) + try: + if img_info['bit_depth'] <= 16: + if img_info['format'] in (AI_TYPE_BYTE, AI_TYPE_INT, AI_TYPE_UINT): # noqa + return 'sRGB' + else: + return 'linear' + # now discard the image file as AiTextureGetFormat has loaded it + AiTextureInvalidate(img_info['filename']) # noqa + except ValueError: + print(("[maketx] Error: Could not guess" + "colorspace for {}").format(img_info["filename"])) + return "linear" + + def len_flattened(components): """Return the length of the list as if it was flattened. diff --git a/openpype/hosts/maya/api/lib_rendersettings.py b/openpype/hosts/maya/api/lib_rendersettings.py index f19deb03517..eaa728a2f68 100644 --- a/openpype/hosts/maya/api/lib_rendersettings.py +++ b/openpype/hosts/maya/api/lib_rendersettings.py @@ -158,7 +158,7 @@ def _set_arnold_settings(self, width, height): cmds.setAttr( "defaultArnoldDriver.mergeAOVs", multi_exr) self._additional_attribs_setter(additional_options) - reset_frame_range() + reset_frame_range(playback=False, fps=False, render=True) def _set_redshift_settings(self, width, height): """Sets settings for Redshift.""" @@ -336,7 +336,8 @@ def _set_vray_settings(self, aov_separator, width, height): ) # Set render file format to exr - cmds.setAttr("{}.imageFormatStr".format(node), "exr", type="string") + ext = vray_render_presets["image_format"] + cmds.setAttr("{}.imageFormatStr".format(node), ext, type="string") # animType cmds.setAttr("{}.animType".format(node), 1) diff --git a/openpype/hosts/maya/api/menu.py b/openpype/hosts/maya/api/menu.py index 0f48a133a61..5284c0249d3 100644 --- a/openpype/hosts/maya/api/menu.py +++ b/openpype/hosts/maya/api/menu.py @@ -12,6 +12,7 @@ from openpype.tools.utils import host_tools from openpype.hosts.maya.api import lib, lib_rendersettings from .lib import get_main_window, IS_HEADLESS +from ..tools import show_look_assigner from .workfile_template_builder import ( create_placeholder, @@ -111,12 +112,12 @@ def deferred(): ) cmds.menuItem( - "Reset Frame Range", + "Set Frame Range", command=lambda *args: lib.reset_frame_range() ) cmds.menuItem( - "Reset Resolution", + "Set Resolution", command=lambda *args: lib.reset_scene_resolution() ) @@ -139,7 +140,7 @@ def deferred(): cmds.menuItem( "Look assigner...", - command=lambda *args: host_tools.show_look_assigner( + command=lambda *args: show_look_assigner( parent_widget ) ) diff --git a/openpype/hosts/maya/plugins/create/create_animation.py b/openpype/hosts/maya/plugins/create/create_animation.py index a4b6e865982..f992ff2c1af 100644 --- a/openpype/hosts/maya/plugins/create/create_animation.py +++ b/openpype/hosts/maya/plugins/create/create_animation.py @@ -13,6 +13,7 @@ class CreateAnimation(plugin.Creator): icon = "male" write_color_sets = False write_face_sets = False + include_parent_hierarchy = False include_user_defined_attributes = False def __init__(self, *args, **kwargs): @@ -37,7 +38,7 @@ def __init__(self, *args, **kwargs): self.data["visibleOnly"] = False # Include the groups above the out_SET content - self.data["includeParentHierarchy"] = False # Include parent groups + self.data["includeParentHierarchy"] = self.include_parent_hierarchy # Default to exporting world-space self.data["worldSpace"] = True diff --git a/openpype/hosts/maya/plugins/create/create_review.py b/openpype/hosts/maya/plugins/create/create_review.py index f1b626c06b9..e709239ae78 100644 --- a/openpype/hosts/maya/plugins/create/create_review.py +++ b/openpype/hosts/maya/plugins/create/create_review.py @@ -26,6 +26,7 @@ class CreateReview(plugin.Creator): "alpha cut" ] useMayaTimeline = True + panZoom = False def __init__(self, *args, **kwargs): super(CreateReview, self).__init__(*args, **kwargs) @@ -45,5 +46,6 @@ def __init__(self, *args, **kwargs): data["keepImages"] = self.keepImages data["imagePlane"] = self.imagePlane data["transparency"] = self.transparency + data["panZoom"] = self.panZoom self.data = data diff --git a/openpype/hosts/maya/plugins/inventory/connect_geometry.py b/openpype/hosts/maya/plugins/inventory/connect_geometry.py index a12487cf7ef..03154b7afe2 100644 --- a/openpype/hosts/maya/plugins/inventory/connect_geometry.py +++ b/openpype/hosts/maya/plugins/inventory/connect_geometry.py @@ -134,7 +134,7 @@ def display_warning(self, message, show_cancel=False): bool """ - from Qt import QtWidgets + from qtpy import QtWidgets accept = QtWidgets.QMessageBox.Ok if show_cancel: diff --git a/openpype/hosts/maya/plugins/inventory/connect_xgen.py b/openpype/hosts/maya/plugins/inventory/connect_xgen.py index 933a1b4025b..177971f176f 100644 --- a/openpype/hosts/maya/plugins/inventory/connect_xgen.py +++ b/openpype/hosts/maya/plugins/inventory/connect_xgen.py @@ -149,7 +149,7 @@ def display_warning(self, message, show_cancel=False): bool """ - from Qt import QtWidgets + from qtpy import QtWidgets accept = QtWidgets.QMessageBox.Ok if show_cancel: diff --git a/openpype/hosts/maya/plugins/inventory/connect_yeti_rig.py b/openpype/hosts/maya/plugins/inventory/connect_yeti_rig.py new file mode 100644 index 00000000000..924a1a46277 --- /dev/null +++ b/openpype/hosts/maya/plugins/inventory/connect_yeti_rig.py @@ -0,0 +1,178 @@ +import os +import json +from collections import defaultdict + +from maya import cmds + +from openpype.pipeline import ( + InventoryAction, get_representation_context, get_representation_path +) +from openpype.hosts.maya.api.lib import get_container_members, get_id + + +class ConnectYetiRig(InventoryAction): + """Connect Yeti Rig with an animation or pointcache.""" + + label = "Connect Yeti Rig" + icon = "link" + color = "white" + + def process(self, containers): + # Validate selection is more than 1. + message = ( + "Only 1 container selected. 2+ containers needed for this action." + ) + if len(containers) == 1: + self.display_warning(message) + return + + # Categorize containers by family. + containers_by_family = defaultdict(list) + for container in containers: + family = get_representation_context( + container["representation"] + )["subset"]["data"]["family"] + containers_by_family[family].append(container) + + # Validate to only 1 source container. + source_containers = containers_by_family.get("animation", []) + source_containers += containers_by_family.get("pointcache", []) + source_container_namespaces = [ + x["namespace"] for x in source_containers + ] + message = ( + "{} animation containers selected:\n\n{}\n\nOnly select 1 of type " + "\"animation\" or \"pointcache\".".format( + len(source_containers), source_container_namespaces + ) + ) + if len(source_containers) != 1: + self.display_warning(message) + return + + source_container = source_containers[0] + source_ids = self.nodes_by_id(source_container) + + # Target containers. + target_ids = {} + inputs = [] + + yeti_rig_containers = containers_by_family.get("yetiRig") + if not yeti_rig_containers: + self.display_warning( + "Select at least one yetiRig container" + ) + return + + for container in yeti_rig_containers: + target_ids.update(self.nodes_by_id(container)) + + maya_file = get_representation_path( + get_representation_context( + container["representation"] + )["representation"] + ) + _, ext = os.path.splitext(maya_file) + settings_file = maya_file.replace(ext, ".rigsettings") + if not os.path.exists(settings_file): + continue + + with open(settings_file) as f: + inputs.extend(json.load(f)["inputs"]) + + # Compare loaded connections to scene. + for input in inputs: + source_node = source_ids.get(input["sourceID"]) + target_node = target_ids.get(input["destinationID"]) + + if not source_node or not target_node: + self.log.debug( + "Could not find nodes for input:\n" + + json.dumps(input, indent=4, sort_keys=True) + ) + continue + source_attr, target_attr = input["connections"] + + if not cmds.attributeQuery( + source_attr, node=source_node, exists=True + ): + self.log.debug( + "Could not find attribute {} on node {} for " + "input:\n{}".format( + source_attr, + source_node, + json.dumps(input, indent=4, sort_keys=True) + ) + ) + continue + + if not cmds.attributeQuery( + target_attr, node=target_node, exists=True + ): + self.log.debug( + "Could not find attribute {} on node {} for " + "input:\n{}".format( + target_attr, + target_node, + json.dumps(input, indent=4, sort_keys=True) + ) + ) + continue + + source_plug = "{}.{}".format( + source_node, source_attr + ) + target_plug = "{}.{}".format( + target_node, target_attr + ) + if cmds.isConnected( + source_plug, target_plug, ignoreUnitConversion=True + ): + self.log.debug( + "Connection already exists: {} -> {}".format( + source_plug, target_plug + ) + ) + continue + + cmds.connectAttr(source_plug, target_plug, force=True) + self.log.debug( + "Connected attributes: {} -> {}".format( + source_plug, target_plug + ) + ) + + def nodes_by_id(self, container): + ids = {} + for member in get_container_members(container): + id = get_id(member) + if not id: + continue + ids[id] = member + + return ids + + def display_warning(self, message, show_cancel=False): + """Show feedback to user. + + Returns: + bool + """ + + from qtpy import QtWidgets + + accept = QtWidgets.QMessageBox.Ok + if show_cancel: + buttons = accept | QtWidgets.QMessageBox.Cancel + else: + buttons = accept + + state = QtWidgets.QMessageBox.warning( + None, + "", + message, + buttons=buttons, + defaultButton=accept + ) + + return state == accept diff --git a/openpype/hosts/maya/plugins/load/load_arnold_standin.py b/openpype/hosts/maya/plugins/load/load_arnold_standin.py index ab69d62ef58..11a2bd19669 100644 --- a/openpype/hosts/maya/plugins/load/load_arnold_standin.py +++ b/openpype/hosts/maya/plugins/load/load_arnold_standin.py @@ -2,7 +2,6 @@ import clique import maya.cmds as cmds -import mtoa.ui.arnoldmenu from openpype.settings import get_project_settings from openpype.pipeline import ( @@ -36,6 +35,11 @@ class ArnoldStandinLoader(load.LoaderPlugin): color = "orange" def load(self, context, name, namespace, options): + + # Make sure to load arnold before importing `mtoa.ui.arnoldmenu` + cmds.loadPlugin("mtoa", quiet=True) + import mtoa.ui.arnoldmenu + version = context['version'] version_data = version.get("data", {}) diff --git a/openpype/hosts/maya/plugins/load/load_image.py b/openpype/hosts/maya/plugins/load/load_image.py new file mode 100644 index 00000000000..b464c268fcb --- /dev/null +++ b/openpype/hosts/maya/plugins/load/load_image.py @@ -0,0 +1,332 @@ +import os +import copy + +from openpype.lib import EnumDef +from openpype.pipeline import ( + load, + get_representation_context +) +from openpype.pipeline.load.utils import get_representation_path_from_context +from openpype.pipeline.colorspace import ( + get_imageio_colorspace_from_filepath, + get_imageio_config, + get_imageio_file_rules +) +from openpype.settings import get_project_settings + +from openpype.hosts.maya.api.pipeline import containerise +from openpype.hosts.maya.api.lib import ( + unique_namespace, + namespaced +) + +from maya import cmds + + +def create_texture(): + """Create place2dTexture with file node with uv connections + + Mimics Maya "file [Texture]" creation. + """ + + place = cmds.shadingNode("place2dTexture", asUtility=True, name="place2d") + file = cmds.shadingNode("file", asTexture=True, name="file") + + connections = ["coverage", "translateFrame", "rotateFrame", "rotateUV", + "mirrorU", "mirrorV", "stagger", "wrapV", "wrapU", + "repeatUV", "offset", "noiseUV", "vertexUvThree", + "vertexUvTwo", "vertexUvOne", "vertexCameraOne"] + for attr in connections: + src = "{}.{}".format(place, attr) + dest = "{}.{}".format(file, attr) + cmds.connectAttr(src, dest) + + cmds.connectAttr(place + '.outUV', file + '.uvCoord') + cmds.connectAttr(place + '.outUvFilterSize', file + '.uvFilterSize') + + return file, place + + +def create_projection(): + """Create texture with place3dTexture and projection + + Mimics Maya "file [Projection]" creation. + """ + + file, place = create_texture() + projection = cmds.shadingNode("projection", asTexture=True, + name="projection") + place3d = cmds.shadingNode("place3dTexture", asUtility=True, + name="place3d") + + cmds.connectAttr(place3d + '.worldInverseMatrix[0]', + projection + ".placementMatrix") + cmds.connectAttr(file + '.outColor', projection + ".image") + + return file, place, projection, place3d + + +def create_stencil(): + """Create texture with extra place2dTexture offset and stencil + + Mimics Maya "file [Stencil]" creation. + """ + + file, place = create_texture() + + place_stencil = cmds.shadingNode("place2dTexture", asUtility=True, + name="place2d_stencil") + stencil = cmds.shadingNode("stencil", asTexture=True, name="stencil") + + for src_attr, dest_attr in [ + ("outUV", "uvCoord"), + ("outUvFilterSize", "uvFilterSize") + ]: + src_plug = "{}.{}".format(place_stencil, src_attr) + cmds.connectAttr(src_plug, "{}.{}".format(place, dest_attr)) + cmds.connectAttr(src_plug, "{}.{}".format(stencil, dest_attr)) + + return file, place, stencil, place_stencil + + +class FileNodeLoader(load.LoaderPlugin): + """File node loader.""" + + families = ["image", "plate", "render"] + label = "Load file node" + representations = ["exr", "tif", "png", "jpg"] + icon = "image" + color = "orange" + order = 2 + + options = [ + EnumDef( + "mode", + items={ + "texture": "Texture", + "projection": "Projection", + "stencil": "Stencil" + }, + default="texture", + label="Texture Mode" + ) + ] + + def load(self, context, name, namespace, data): + + asset = context['asset']['name'] + namespace = namespace or unique_namespace( + asset + "_", + prefix="_" if asset[0].isdigit() else "", + suffix="_", + ) + + with namespaced(namespace, new=True) as namespace: + # Create the nodes within the namespace + nodes = { + "texture": create_texture, + "projection": create_projection, + "stencil": create_stencil + }[data.get("mode", "texture")]() + + file_node = cmds.ls(nodes, type="file")[0] + + self._apply_representation_context(context, file_node) + + # For ease of access for the user select all the nodes and select + # the file node last so that UI shows its attributes by default + cmds.select(list(nodes) + [file_node], replace=True) + + return containerise( + name=name, + namespace=namespace, + nodes=nodes, + context=context, + loader=self.__class__.__name__ + ) + + def update(self, container, representation): + + members = cmds.sets(container['objectName'], query=True) + file_node = cmds.ls(members, type="file")[0] + + context = get_representation_context(representation) + self._apply_representation_context(context, file_node) + + # Update representation + cmds.setAttr( + container["objectName"] + ".representation", + str(representation["_id"]), + type="string" + ) + + def switch(self, container, representation): + self.update(container, representation) + + def remove(self, container): + members = cmds.sets(container['objectName'], query=True) + cmds.lockNode(members, lock=False) + cmds.delete([container['objectName']] + members) + + # Clean up the namespace + try: + cmds.namespace(removeNamespace=container['namespace'], + deleteNamespaceContent=True) + except RuntimeError: + pass + + def _apply_representation_context(self, context, file_node): + """Update the file node to match the context. + + This sets the file node's attributes for: + - file path + - udim tiling mode (if it is an udim tile) + - use frame extension (if it is a sequence) + - colorspace + + """ + + repre_context = context["representation"]["context"] + has_frames = repre_context.get("frame") is not None + has_udim = repre_context.get("udim") is not None + + # Set UV tiling mode if UDIM tiles + if has_udim: + cmds.setAttr(file_node + ".uvTilingMode", 3) # UDIM-tiles + else: + cmds.setAttr(file_node + ".uvTilingMode", 0) # off + + # Enable sequence if publish has `startFrame` and `endFrame` and + # `startFrame != endFrame` + if has_frames and self._is_sequence(context): + # When enabling useFrameExtension maya automatically + # connects an expression to .frameExtension to set + # the current frame. However, this expression is generated + # with some delay and thus it'll show a warning if frame 0 + # doesn't exist because we're explicitly setting the + # token. + cmds.setAttr(file_node + ".useFrameExtension", True) + else: + cmds.setAttr(file_node + ".useFrameExtension", False) + + # Set the file node path attribute + path = self._format_path(context) + cmds.setAttr(file_node + ".fileTextureName", path, type="string") + + # Set colorspace + colorspace = self._get_colorspace(context) + if colorspace: + cmds.setAttr(file_node + ".colorSpace", colorspace, type="string") + else: + self.log.debug("Unknown colorspace - setting colorspace skipped.") + + def _is_sequence(self, context): + """Check whether frameStart and frameEnd are not the same.""" + version = context.get("version", {}) + representation = context.get("representation", {}) + + for doc in [representation, version]: + # Frame range can be set on version or representation. + # When set on representation it overrides version data. + data = doc.get("data", {}) + start = data.get("frameStartHandle", data.get("frameStart", None)) + end = data.get("frameEndHandle", data.get("frameEnd", None)) + + if start is None or end is None: + continue + + if start != end: + return True + else: + return False + + return False + + def _get_colorspace(self, context): + """Return colorspace of the file to load. + + Retrieves the explicit colorspace from the publish. If no colorspace + data is stored with published content then project imageio settings + are used to make an assumption of the colorspace based on the file + rules. If no file rules match then None is returned. + + Returns: + str or None: The colorspace of the file or None if not detected. + + """ + + # We can't apply color spaces if management is not enabled + if not cmds.colorManagementPrefs(query=True, cmEnabled=True): + return + + representation = context["representation"] + colorspace_data = representation.get("data", {}).get("colorspaceData") + if colorspace_data: + return colorspace_data["colorspace"] + + # Assume colorspace from filepath based on project settings + project_name = context["project"]["name"] + host_name = os.environ.get("AVALON_APP") + project_settings = get_project_settings(project_name) + + config_data = get_imageio_config( + project_name, host_name, + project_settings=project_settings + ) + file_rules = get_imageio_file_rules( + project_name, host_name, + project_settings=project_settings + ) + + path = get_representation_path_from_context(context) + colorspace = get_imageio_colorspace_from_filepath( + path=path, + host_name=host_name, + project_name=project_name, + config_data=config_data, + file_rules=file_rules, + project_settings=project_settings + ) + + return colorspace + + def _format_path(self, context): + """Format the path with correct tokens for frames and udim tiles.""" + + context = copy.deepcopy(context) + representation = context["representation"] + template = representation.get("data", {}).get("template") + if not template: + # No template to find token locations for + return get_representation_path_from_context(context) + + def _placeholder(key): + # Substitute with a long placeholder value so that potential + # custom formatting with padding doesn't find its way into + # our formatting, so that wouldn't be padded as 0 + return "___{}___".format(key) + + # We format UDIM and Frame numbers with their specific tokens. To do so + # we in-place change the representation context data to format the path + # with our own data + tokens = { + "frame": "", + "udim": "" + } + has_tokens = False + repre_context = representation["context"] + for key, _token in tokens.items(): + if key in repre_context: + repre_context[key] = _placeholder(key) + has_tokens = True + + # Replace with our custom template that has the tokens set + representation["data"]["template"] = template + path = get_representation_path_from_context(context) + + if has_tokens: + for key, token in tokens.items(): + if key in repre_context: + path = path.replace(_placeholder(key), token) + + return path diff --git a/openpype/hosts/maya/plugins/load/load_xgen.py b/openpype/hosts/maya/plugins/load/load_xgen.py index 1600cd49bd0..7e6cabc77ce 100644 --- a/openpype/hosts/maya/plugins/load/load_xgen.py +++ b/openpype/hosts/maya/plugins/load/load_xgen.py @@ -3,7 +3,7 @@ import maya.cmds as cmds import xgenm -from Qt import QtWidgets +from qtpy import QtWidgets import openpype.hosts.maya.api.plugin from openpype.hosts.maya.api.lib import ( diff --git a/openpype/hosts/maya/plugins/load/load_yeti_rig.py b/openpype/hosts/maya/plugins/load/load_yeti_rig.py index 651607de8a5..6a13d2e145a 100644 --- a/openpype/hosts/maya/plugins/load/load_yeti_rig.py +++ b/openpype/hosts/maya/plugins/load/load_yeti_rig.py @@ -1,17 +1,12 @@ -import os -from collections import defaultdict +import maya.cmds as cmds -from openpype.settings import get_project_settings +from openpype.settings import get_current_project_settings import openpype.hosts.maya.api.plugin from openpype.hosts.maya.api import lib class YetiRigLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): - """ - This loader will load Yeti rig. You can select something in scene and if it - has same ID as mesh published with rig, their shapes will be linked - together. - """ + """This loader will load Yeti rig.""" families = ["yetiRig"] representations = ["ma"] @@ -22,72 +17,31 @@ class YetiRigLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): color = "orange" def process_reference( - self, context, name=None, namespace=None, options=None): + self, context, name=None, namespace=None, options=None + ): - import maya.cmds as cmds - - # get roots of selected hierarchies - selected_roots = [] - for sel in cmds.ls(sl=True, long=True): - selected_roots.append(sel.split("|")[1]) - - # get all objects under those roots - selected_hierarchy = [] - for root in selected_roots: - selected_hierarchy.append(cmds.listRelatives( - root, - allDescendents=True) or []) - - # flatten the list and filter only shapes - shapes_flat = [] - for root in selected_hierarchy: - shapes = cmds.ls(root, long=True, type="mesh") or [] - for shape in shapes: - shapes_flat.append(shape) - - # create dictionary of cbId and shape nodes - scene_lookup = defaultdict(list) - for node in shapes_flat: - cb_id = lib.get_id(node) - scene_lookup[cb_id] = node - - # load rig + group_name = "{}:{}".format(namespace, name) with lib.maintained_selection(): - file_url = self.prepare_root_value(self.fname, - context["project"]["name"]) - nodes = cmds.file(file_url, - namespace=namespace, - reference=True, - returnNewNodes=True, - groupReference=True, - groupName="{}:{}".format(namespace, name)) - - # for every shape node we've just loaded find matching shape by its - # cbId in selection. If found outMesh of scene shape will connect to - # inMesh of loaded shape. - for destination_node in nodes: - source_node = scene_lookup[lib.get_id(destination_node)] - if source_node: - self.log.info("found: {}".format(source_node)) - self.log.info( - "creating connection to {}".format(destination_node)) - - cmds.connectAttr("{}.outMesh".format(source_node), - "{}.inMesh".format(destination_node), - force=True) - - groupName = "{}:{}".format(namespace, name) - - settings = get_project_settings(os.environ['AVALON_PROJECT']) - colors = settings['maya']['load']['colors'] + file_url = self.prepare_root_value( + self.fname, context["project"]["name"] + ) + nodes = cmds.file( + file_url, + namespace=namespace, + reference=True, + returnNewNodes=True, + groupReference=True, + groupName=group_name + ) - c = colors.get('yetiRig') + settings = get_current_project_settings() + colors = settings["maya"]["load"]["colors"] + c = colors.get("yetiRig") if c is not None: - cmds.setAttr(groupName + ".useOutlinerColor", 1) - cmds.setAttr(groupName + ".outlinerColor", - (float(c[0])/255), - (float(c[1])/255), - (float(c[2])/255) + cmds.setAttr(group_name + ".useOutlinerColor", 1) + cmds.setAttr( + group_name + ".outlinerColor", + (float(c[0]) / 255), (float(c[1]) / 255), (float(c[2]) / 255) ) self[:] = nodes diff --git a/openpype/hosts/maya/plugins/publish/collect_review.py b/openpype/hosts/maya/plugins/publish/collect_review.py index eb872c29358..00565c5819b 100644 --- a/openpype/hosts/maya/plugins/publish/collect_review.py +++ b/openpype/hosts/maya/plugins/publish/collect_review.py @@ -5,6 +5,7 @@ from openpype.client import get_subset_by_name from openpype.pipeline import legacy_io +from openpype.hosts.maya.api.lib import get_attribute_input class CollectReview(pyblish.api.InstancePlugin): @@ -23,6 +24,11 @@ def process(self, instance): task = legacy_io.Session["AVALON_TASK"] + # Get panel. + instance.data["panel"] = cmds.playblast( + activeEditor=True + ).split("|")[-1] + # get cameras members = instance.data['setMembers'] cameras = cmds.ls(members, long=True, @@ -74,6 +80,8 @@ def process(self, instance): data['review_width'] = instance.data['review_width'] data['review_height'] = instance.data['review_height'] data["isolate"] = instance.data["isolate"] + data["panZoom"] = instance.data.get("panZoom", False) + data["panel"] = instance.data["panel"] cmds.setAttr(str(instance) + '.active', 1) self.log.debug('data {}'.format(instance.context[i].data)) instance.context[i].data.update(data) @@ -139,3 +147,21 @@ def process(self, instance): "filename": node.filename.get() } ) + + # Collect focal length. + attr = camera + ".focalLength" + focal_length = None + if get_attribute_input(attr): + start = instance.data["frameStart"] + end = instance.data["frameEnd"] + 1 + focal_length = [ + cmds.getAttr(attr, time=t) for t in range(int(start), int(end)) + ] + else: + focal_length = cmds.getAttr(attr) + + key = "focalLength" + try: + instance.data["burninDataMembers"][key] = focal_length + except KeyError: + instance.data["burninDataMembers"] = {key: focal_length} diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index df07a674dcb..447c9a615cc 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -1,12 +1,10 @@ # -*- coding: utf-8 -*- """Maya look extractor.""" import os -import sys import json import tempfile import platform import contextlib -import subprocess from collections import OrderedDict from maya import cmds # noqa @@ -16,40 +14,20 @@ from openpype.lib import source_hash, run_subprocess from openpype.pipeline import legacy_io, publish from openpype.hosts.maya.api import lib +from openpype.hosts.maya.api.lib import image_info, guess_colorspace # Modes for transfer COPY = 1 HARDLINK = 2 -def escape_space(path): - """Ensure path is enclosed by quotes to allow paths with spaces""" - return '"{}"'.format(path) if " " in path else path - - -def get_ocio_config_path(profile_folder): - """Path to OpenPype vendorized OCIO. - - Vendorized OCIO config file path is grabbed from the specific path - hierarchy specified below. - - "{OPENPYPE_ROOT}/vendor/OpenColorIO-Configs/{profile_folder}/config.ocio" - Args: - profile_folder (str): Name of folder to grab config file from. - - Returns: - str: Path to vendorized config file. - """ - - return os.path.join( - os.environ["OPENPYPE_ROOT"], - "vendor", - "bin", - "ocioconfig", - "OpenColorIOConfigs", - profile_folder, - "config.ocio" - ) +def _has_arnold(): + """Return whether the arnold package is available and can be imported.""" + try: + import arnold # noqa: F401 + return True + except (ImportError, ModuleNotFoundError): + return False def find_paths_by_hash(texture_hash): @@ -367,16 +345,25 @@ def process_resources(self, instance, staging_dir): for filepath in files_metadata: linearize = False - if do_maketx and files_metadata[filepath]["color_space"].lower() == "srgb": # noqa: E501 - linearize = True - # set its file node to 'raw' as tx will be linearized - files_metadata[filepath]["color_space"] = "Raw" + # if OCIO color management enabled + # it won't take the condition of the files_metadata + + ocio_maya = cmds.colorManagementPrefs(q=True, + cmConfigFileEnabled=True, + cmEnabled=True) + + if do_maketx and not ocio_maya: + if files_metadata[filepath]["color_space"].lower() == "srgb": # noqa: E501 + linearize = True + # set its file node to 'raw' as tx will be linearized + files_metadata[filepath]["color_space"] = "Raw" # if do_maketx: # color_space = "Raw" source, mode, texture_hash = self._process_texture( filepath, + resource, do_maketx, staging=staging_dir, linearize=linearize, @@ -482,7 +469,8 @@ def resource_destination(self, instance, filepath, do_maketx): resources_dir, basename + ext ) - def _process_texture(self, filepath, do_maketx, staging, linearize, force): + def _process_texture(self, filepath, resource, + do_maketx, staging, linearize, force): """Process a single texture file on disk for publishing. This will: 1. Check whether it's already published, if so it will do hardlink @@ -524,10 +512,47 @@ def _process_texture(self, filepath, do_maketx, staging, linearize, force): texture_hash ] if linearize: - self.log.info("tx: converting sRGB -> linear") - additional_args.extend(["--colorconvert", "sRGB", "linear"]) + if cmds.colorManagementPrefs(query=True, cmEnabled=True): + render_colorspace = cmds.colorManagementPrefs(query=True, + renderingSpaceName=True) # noqa + config_path = cmds.colorManagementPrefs(query=True, + configFilePath=True) # noqa + if not os.path.exists(config_path): + raise RuntimeError("No OCIO config path found!") + + color_space_attr = resource["node"] + ".colorSpace" + try: + color_space = cmds.getAttr(color_space_attr) + except ValueError: + # node doesn't have color space attribute + if _has_arnold(): + img_info = image_info(filepath) + color_space = guess_colorspace(img_info) + else: + color_space = "Raw" + self.log.info("tx: converting {0} -> {1}".format(color_space, render_colorspace)) # noqa + + additional_args.extend(["--colorconvert", + color_space, + render_colorspace]) + else: + + if _has_arnold(): + img_info = image_info(filepath) + color_space = guess_colorspace(img_info) + if color_space == "sRGB": + self.log.info("tx: converting sRGB -> linear") + additional_args.extend(["--colorconvert", + "sRGB", + "Raw"]) + else: + self.log.info("tx: texture's colorspace " + "is already linear") + else: + self.log.warning("cannot guess the colorspace" + "color conversion won't be available!") # noqa + - config_path = get_ocio_config_path("nuke-default") additional_args.extend(["--colorconfig", config_path]) # Ensure folder exists if not os.path.exists(os.path.dirname(converted)): diff --git a/openpype/hosts/maya/plugins/publish/extract_playblast.py b/openpype/hosts/maya/plugins/publish/extract_playblast.py index 1966ad7b669..72b14895222 100644 --- a/openpype/hosts/maya/plugins/publish/extract_playblast.py +++ b/openpype/hosts/maya/plugins/publish/extract_playblast.py @@ -1,5 +1,6 @@ import os import json +import contextlib import clique import capture @@ -11,6 +12,16 @@ import pymel.core as pm +@contextlib.contextmanager +def panel_camera(panel, camera): + original_camera = cmds.modelPanel(panel, query=True, camera=True) + try: + cmds.modelPanel(panel, edit=True, camera=camera) + yield + finally: + cmds.modelPanel(panel, edit=True, camera=original_camera) + + class ExtractPlayblast(publish.Extractor): """Extract viewport playblast. @@ -25,6 +36,16 @@ class ExtractPlayblast(publish.Extractor): optional = True capture_preset = {} + def _capture(self, preset): + self.log.info( + "Using preset:\n{}".format( + json.dumps(preset, sort_keys=True, indent=4) + ) + ) + + path = capture.capture(log=self.log, **preset) + self.log.debug("playblast path {}".format(path)) + def process(self, instance): self.log.info("Extracting capture..") @@ -43,7 +64,7 @@ def process(self, instance): self.log.info("start: {}, end: {}".format(start, end)) # get cameras - camera = instance.data['review_camera'] + camera = instance.data["review_camera"] preset = lib.load_capture_preset(data=self.capture_preset) # Grab capture presets from the project settings @@ -57,23 +78,23 @@ def process(self, instance): asset_height = asset_data.get("resolutionHeight") review_instance_width = instance.data.get("review_width") review_instance_height = instance.data.get("review_height") - preset['camera'] = camera + preset["camera"] = camera # Tests if project resolution is set, # if it is a value other than zero, that value is # used, if not then the asset resolution is # used if review_instance_width and review_instance_height: - preset['width'] = review_instance_width - preset['height'] = review_instance_height + preset["width"] = review_instance_width + preset["height"] = review_instance_height elif width_preset and height_preset: - preset['width'] = width_preset - preset['height'] = height_preset + preset["width"] = width_preset + preset["height"] = height_preset elif asset_width and asset_height: - preset['width'] = asset_width - preset['height'] = asset_height - preset['start_frame'] = start - preset['end_frame'] = end + preset["width"] = asset_width + preset["height"] = asset_height + preset["start_frame"] = start + preset["end_frame"] = end # Enforce persisting camera depth of field camera_options = preset.setdefault("camera_options", {}) @@ -86,8 +107,8 @@ def process(self, instance): self.log.info("Outputting images to %s" % path) - preset['filename'] = path - preset['overwrite'] = True + preset["filename"] = path + preset["overwrite"] = True pm.refresh(f=True) @@ -114,11 +135,11 @@ def process(self, instance): # Disable Pan/Zoom. pan_zoom = cmds.getAttr("{}.panZoomEnabled".format(preset["camera"])) - cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), False) + preset.pop("pan_zoom", None) + preset["camera_options"]["panZoomEnabled"] = instance.data["panZoom"] # Need to explicitly enable some viewport changes so the viewport is # refreshed ahead of playblasting. - panel = cmds.getPanel(withFocus=True) keys = [ "useDefaultMaterial", "wireframeOnShaded", @@ -129,56 +150,67 @@ def process(self, instance): viewport_defaults = {} for key in keys: viewport_defaults[key] = cmds.modelEditor( - panel, query=True, **{key: True} + instance.data["panel"], query=True, **{key: True} ) if preset["viewport_options"][key]: - cmds.modelEditor(panel, edit=True, **{key: True}) + cmds.modelEditor( + instance.data["panel"], edit=True, **{key: True} + ) override_viewport_options = ( - capture_presets['Viewport Options']['override_viewport_options'] + capture_presets["Viewport Options"]["override_viewport_options"] ) - with lib.maintained_time(): - filename = preset.get("filename", "%TEMP%") - - # Force viewer to False in call to capture because we have our own - # viewer opening call to allow a signal to trigger between - # playblast and viewer - preset['viewer'] = False - - # Update preset with current panel setting - # if override_viewport_options is turned off - panel = cmds.getPanel(withFocus=True) or "" - if not override_viewport_options and "modelPanel" in panel: - panel_preset = capture.parse_active_view() - panel_preset.pop("camera") - preset.update(panel_preset) - cmds.setFocus(panel) - - self.log.info( - "Using preset:\n{}".format( - json.dumps(preset, sort_keys=True, indent=4) + + # Force viewer to False in call to capture because we have our own + # viewer opening call to allow a signal to trigger between + # playblast and viewer + preset["viewer"] = False + + # Update preset with current panel setting + # if override_viewport_options is turned off + if not override_viewport_options: + panel_preset = capture.parse_view(instance.data["panel"]) + panel_preset.pop("camera") + preset.update(panel_preset) + + # Need to ensure Python 2 compatibility. + # TODO: Remove once dropping Python 2. + if getattr(contextlib, "nested", None): + # Python 3 compatibility. + with contextlib.nested( + lib.maintained_time(), + panel_camera(instance.data["panel"], preset["camera"]) + ): + self._capture(preset) + else: + # Python 2 compatibility. + with contextlib.ExitStack() as stack: + stack.enter_context(lib.maintained_time()) + stack.enter_context( + panel_camera(instance.data["panel"], preset["camera"]) ) - ) - path = capture.capture(log=self.log, **preset) + self._capture(preset) # Restoring viewport options. - cmds.modelEditor(panel, edit=True, **viewport_defaults) + if viewport_defaults: + cmds.modelEditor( + instance.data["panel"], edit=True, **viewport_defaults + ) cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), pan_zoom) - self.log.debug("playblast path {}".format(path)) - collected_files = os.listdir(stagingdir) patterns = [clique.PATTERNS["frames"]] collections, remainder = clique.assemble(collected_files, minimum_items=1, patterns=patterns) + filename = preset.get("filename", "%TEMP%") self.log.debug("filename {}".format(filename)) frame_collection = None for collection in collections: - filebase = collection.format('{head}').rstrip(".") + filebase = collection.format("{head}").rstrip(".") self.log.debug("collection head {}".format(filebase)) if filebase in filename: frame_collection = collection @@ -202,15 +234,15 @@ def process(self, instance): collected_files = collected_files[0] representation = { - 'name': 'png', - 'ext': 'png', - 'files': collected_files, + "name": self.capture_preset["Codec"]["compression"], + "ext": self.capture_preset["Codec"]["compression"], + "files": collected_files, "stagingDir": stagingdir, "frameStart": start, "frameEnd": end, - 'fps': fps, - 'preview': True, - 'tags': tags, - 'camera_name': camera_node_name + "fps": fps, + "preview": True, + "tags": tags, + "camera_name": camera_node_name } instance.data["representations"].append(representation) diff --git a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py index 1d94bd58c56..f2d084b8281 100644 --- a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py +++ b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py @@ -26,28 +26,28 @@ class ExtractThumbnail(publish.Extractor): def process(self, instance): self.log.info("Extracting capture..") - camera = instance.data['review_camera'] + camera = instance.data["review_camera"] - capture_preset = ( - instance.context.data["project_settings"]['maya']['publish']['ExtractPlayblast']['capture_preset'] - ) + maya_setting = instance.context.data["project_settings"]["maya"] + plugin_setting = maya_setting["publish"]["ExtractPlayblast"] + capture_preset = plugin_setting["capture_preset"] override_viewport_options = ( - capture_preset['Viewport Options']['override_viewport_options'] + capture_preset["Viewport Options"]["override_viewport_options"] ) try: preset = lib.load_capture_preset(data=capture_preset) except KeyError as ke: - self.log.error('Error loading capture presets: {}'.format(str(ke))) + self.log.error("Error loading capture presets: {}".format(str(ke))) preset = {} - self.log.info('Using viewport preset: {}'.format(preset)) + self.log.info("Using viewport preset: {}".format(preset)) # preset["off_screen"] = False - preset['camera'] = camera - preset['start_frame'] = instance.data["frameStart"] - preset['end_frame'] = instance.data["frameStart"] - preset['camera_options'] = { + preset["camera"] = camera + preset["start_frame"] = instance.data["frameStart"] + preset["end_frame"] = instance.data["frameStart"] + preset["camera_options"] = { "displayGateMask": False, "displayResolution": False, "displayFilmGate": False, @@ -74,14 +74,14 @@ def process(self, instance): # used, if not then the asset resolution is # used if review_instance_width and review_instance_height: - preset['width'] = review_instance_width - preset['height'] = review_instance_height + preset["width"] = review_instance_width + preset["height"] = review_instance_height elif width_preset and height_preset: - preset['width'] = width_preset - preset['height'] = height_preset + preset["width"] = width_preset + preset["height"] = height_preset elif asset_width and asset_height: - preset['width'] = asset_width - preset['height'] = asset_height + preset["width"] = asset_width + preset["height"] = asset_height # Create temp directory for thumbnail # - this is to avoid "override" of source file @@ -96,8 +96,8 @@ def process(self, instance): self.log.info("Outputting images to %s" % path) - preset['filename'] = path - preset['overwrite'] = True + preset["filename"] = path + preset["overwrite"] = True pm.refresh(f=True) @@ -123,14 +123,14 @@ def process(self, instance): preset["viewport_options"] = {"imagePlane": image_plane} # Disable Pan/Zoom. - pan_zoom = cmds.getAttr("{}.panZoomEnabled".format(preset["camera"])) - cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), False) + preset.pop("pan_zoom", None) + preset["camera_options"]["panZoomEnabled"] = instance.data["panZoom"] with lib.maintained_time(): # Force viewer to False in call to capture because we have our own # viewer opening call to allow a signal to trigger between # playblast and viewer - preset['viewer'] = False + preset["viewer"] = False # Update preset with current panel setting # if override_viewport_options is turned off @@ -145,17 +145,15 @@ def process(self, instance): _, thumbnail = os.path.split(playblast) - cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), pan_zoom) - self.log.info("file list {}".format(thumbnail)) if "representations" not in instance.data: instance.data["representations"] = [] representation = { - 'name': 'thumbnail', - 'ext': 'jpg', - 'files': thumbnail, + "name": "thumbnail", + "ext": "jpg", + "files": thumbnail, "stagingDir": dst_staging, "thumbnail": True } diff --git a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py new file mode 100644 index 00000000000..b1bdeb7541b --- /dev/null +++ b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py @@ -0,0 +1,26 @@ +from maya import cmds + +import pyblish.api +from openpype.pipeline.publish import ValidateContentsOrder +from openpype.pipeline import PublishValidationError + + +class ValidateMayaColorSpace(pyblish.api.InstancePlugin): + """ + Check if the OCIO Color Management and maketx options + enabled at the same time + """ + + order = ValidateContentsOrder + families = ['look'] + hosts = ['maya'] + label = 'Color Management with maketx' + + def process(self, instance): + ocio_maya = cmds.colorManagementPrefs(q=True, + cmConfigFileEnabled=True, + cmEnabled=True) + maketx = instance.data["maketx"] + + if ocio_maya and maketx: + raise PublishValidationError("Maya is color managed and maketx option is on. OpenPype doesn't support this combination yet.") # noqa diff --git a/openpype/hosts/maya/plugins/publish/validate_rendersettings.py b/openpype/hosts/maya/plugins/publish/validate_rendersettings.py index 94e26335936..53f340cd2c0 100644 --- a/openpype/hosts/maya/plugins/publish/validate_rendersettings.py +++ b/openpype/hosts/maya/plugins/publish/validate_rendersettings.py @@ -13,6 +13,22 @@ from openpype.hosts.maya.api import lib +def convert_to_int_or_float(string_value): + # Order of types are important here since float can convert string + # representation of integer. + types = [int, float] + for t in types: + try: + result = t(string_value) + except ValueError: + continue + else: + return result + + # Neither integer or float. + return string_value + + def get_redshift_image_format_labels(): """Return nice labels for Redshift image formats.""" var = "$g_redshiftImageFormatLabels" @@ -242,10 +258,6 @@ def get_invalid(cls, instance): cls.DEFAULT_PADDING, "0" * cls.DEFAULT_PADDING)) # load validation definitions from settings - validation_settings = ( - instance.context.data["project_settings"]["maya"]["publish"]["ValidateRenderSettings"].get( # noqa: E501 - "{}_render_attributes".format(renderer)) or [] - ) settings_lights_flag = instance.context.data["project_settings"].get( "maya", {}).get( "RenderSettings", {}).get( @@ -253,47 +265,82 @@ def get_invalid(cls, instance): instance_lights_flag = instance.data.get("renderSetupIncludeLights") if settings_lights_flag != instance_lights_flag: - cls.log.warning('Instance flag for "Render Setup Include Lights" is set to {0} and Settings flag is set to {1}'.format(instance_lights_flag, settings_lights_flag)) # noqa + cls.log.warning( + "Instance flag for \"Render Setup Include Lights\" is set to " + "{} and Settings flag is set to {}".format( + instance_lights_flag, settings_lights_flag + ) + ) # go through definitions and test if such node.attribute exists. # if so, compare its value from the one required. - for attr, value in OrderedDict(validation_settings).items(): - cls.log.debug("{}: {}".format(attr, value)) - if "." not in attr: - cls.log.warning("Skipping invalid attribute defined in " - "validation settings: '{}'".format(attr)) - continue - - node_type, attribute_name = attr.split(".", 1) - - # first get node of that type - nodes = cmds.ls(type=node_type) - - if not nodes: - cls.log.warning( - "No nodes of type '{}' found.".format(node_type)) + for attribute, data in cls.get_nodes(instance, renderer).items(): + # Validate the settings has values. + if not data["values"]: + cls.log.error( + "Settings for {}.{} is missing values.".format( + node, attribute + ) + ) continue - for node in nodes: + for node in data["nodes"]: try: render_value = cmds.getAttr( - "{}.{}".format(node, attribute_name)) + "{}.{}".format(node, attribute) + ) except RuntimeError: invalid = True cls.log.error( - "Cannot get value of {}.{}".format( - node, attribute_name)) + "Cannot get value of {}.{}".format(node, attribute) + ) else: - if str(value) != str(render_value): + if render_value not in data["values"]: invalid = True cls.log.error( - ("Invalid value {} set on {}.{}. " - "Expecting {}").format( - render_value, node, attribute_name, value) + "Invalid value {} set on {}.{}. Expecting " + "{}".format( + render_value, node, attribute, data["values"] + ) ) return invalid + @classmethod + def get_nodes(cls, instance, renderer): + maya_settings = instance.context.data["project_settings"]["maya"] + validation_settings = ( + maya_settings["publish"]["ValidateRenderSettings"].get( + "{}_render_attributes".format(renderer) + ) or [] + ) + result = {} + for attr, values in OrderedDict(validation_settings).items(): + cls.log.debug("{}: {}".format(attr, values)) + if "." not in attr: + cls.log.warning( + "Skipping invalid attribute defined in validation " + "settings: \"{}\"".format(attr) + ) + continue + + values = [convert_to_int_or_float(v) for v in values] + + node_type, attribute_name = attr.split(".", 1) + + # first get node of that type + nodes = cmds.ls(type=node_type) + + if not nodes: + cls.log.warning( + "No nodes of type \"{}\" found.".format(node_type) + ) + continue + + result[attribute_name] = {"nodes": nodes, "values": values} + + return result + @classmethod def repair(cls, instance): renderer = instance.data['renderer'] @@ -305,6 +352,12 @@ def repair(cls, instance): "{aov_separator}", instance.data.get("aovSeparator", "_") ) + for attribute, data in cls.get_nodes(instance, renderer).items(): + if not data["values"]: + continue + for node in data["nodes"]: + lib.set_attribute(attribute, data["values"][0], node) + with lib.renderlayer(layer_node): default = lib.RENDER_ATTRS['default'] render_attrs = lib.RENDER_ATTRS.get(renderer, default) diff --git a/openpype/hosts/maya/plugins/publish/validate_yeti_renderscript_callbacks.py b/openpype/hosts/maya/plugins/publish/validate_yeti_renderscript_callbacks.py index a864a18cee9..06250f57795 100644 --- a/openpype/hosts/maya/plugins/publish/validate_yeti_renderscript_callbacks.py +++ b/openpype/hosts/maya/plugins/publish/validate_yeti_renderscript_callbacks.py @@ -48,6 +48,18 @@ def get_invalid(cls, instance): yeti_loaded = cmds.pluginInfo("pgYetiMaya", query=True, loaded=True) + if not yeti_loaded and not cmds.ls(type="pgYetiMaya"): + # The yeti plug-in is available and loaded so at + # this point we don't really care whether the scene + # has any yeti callback set or not since if the callback + # is there it wouldn't error and if it weren't then + # nothing happens because there are no yeti nodes. + cls.log.info( + "Yeti is loaded but no yeti nodes were found. " + "Callback validation skipped.." + ) + return False + renderer = instance.data["renderer"] if renderer == "redshift": cls.log.info("Redshift ignores any pre and post render callbacks") diff --git a/openpype/hosts/maya/tools/__init__.py b/openpype/hosts/maya/tools/__init__.py new file mode 100644 index 00000000000..bd1e302cd2b --- /dev/null +++ b/openpype/hosts/maya/tools/__init__.py @@ -0,0 +1,27 @@ +from openpype.tools.utils.host_tools import qt_app_context + + +class MayaToolsSingleton: + _look_assigner = None + + +def get_look_assigner_tool(parent): + """Create, cache and return look assigner tool window.""" + if MayaToolsSingleton._look_assigner is None: + from .mayalookassigner import MayaLookAssignerWindow + mayalookassigner_window = MayaLookAssignerWindow(parent) + MayaToolsSingleton._look_assigner = mayalookassigner_window + return MayaToolsSingleton._look_assigner + + +def show_look_assigner(parent=None): + """Look manager is Maya specific tool for look management.""" + + with qt_app_context(): + look_assigner_tool = get_look_assigner_tool(parent) + look_assigner_tool.show() + + # Pull window to the front. + look_assigner_tool.raise_() + look_assigner_tool.activateWindow() + look_assigner_tool.showNormal() diff --git a/openpype/tools/mayalookassigner/LICENSE b/openpype/hosts/maya/tools/mayalookassigner/LICENSE similarity index 100% rename from openpype/tools/mayalookassigner/LICENSE rename to openpype/hosts/maya/tools/mayalookassigner/LICENSE diff --git a/openpype/tools/mayalookassigner/__init__.py b/openpype/hosts/maya/tools/mayalookassigner/__init__.py similarity index 100% rename from openpype/tools/mayalookassigner/__init__.py rename to openpype/hosts/maya/tools/mayalookassigner/__init__.py diff --git a/openpype/tools/mayalookassigner/app.py b/openpype/hosts/maya/tools/mayalookassigner/app.py similarity index 100% rename from openpype/tools/mayalookassigner/app.py rename to openpype/hosts/maya/tools/mayalookassigner/app.py diff --git a/openpype/tools/mayalookassigner/commands.py b/openpype/hosts/maya/tools/mayalookassigner/commands.py similarity index 93% rename from openpype/tools/mayalookassigner/commands.py rename to openpype/hosts/maya/tools/mayalookassigner/commands.py index 2e7a51efded..3d9746511d9 100644 --- a/openpype/tools/mayalookassigner/commands.py +++ b/openpype/hosts/maya/tools/mayalookassigner/commands.py @@ -80,21 +80,7 @@ def get_all_asset_nodes(): Returns: list: list of dictionaries """ - - host = registered_host() - - nodes = [] - for container in host.ls(): - # We are not interested in looks but assets! - if container["loader"] == "LookLoader": - continue - - # Gather all information - container_name = container["objectName"] - nodes += lib.get_container_members(container_name) - - nodes = list(set(nodes)) - return nodes + return cmds.ls(dag=True, noIntermediate=True, long=True) def create_asset_id_hash(nodes): diff --git a/openpype/tools/mayalookassigner/models.py b/openpype/hosts/maya/tools/mayalookassigner/models.py similarity index 100% rename from openpype/tools/mayalookassigner/models.py rename to openpype/hosts/maya/tools/mayalookassigner/models.py diff --git a/openpype/tools/mayalookassigner/views.py b/openpype/hosts/maya/tools/mayalookassigner/views.py similarity index 100% rename from openpype/tools/mayalookassigner/views.py rename to openpype/hosts/maya/tools/mayalookassigner/views.py diff --git a/openpype/tools/mayalookassigner/vray_proxies.py b/openpype/hosts/maya/tools/mayalookassigner/vray_proxies.py similarity index 100% rename from openpype/tools/mayalookassigner/vray_proxies.py rename to openpype/hosts/maya/tools/mayalookassigner/vray_proxies.py diff --git a/openpype/tools/mayalookassigner/widgets.py b/openpype/hosts/maya/tools/mayalookassigner/widgets.py similarity index 100% rename from openpype/tools/mayalookassigner/widgets.py rename to openpype/hosts/maya/tools/mayalookassigner/widgets.py diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index a5a631cc70f..2a14096f0eb 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -2861,10 +2861,10 @@ def on_enable_dirmap(self): pass def dirmap_routine(self, source_path, destination_path): - log.debug("{}: {}->{}".format(self.file_name, - source_path, destination_path)) source_path = source_path.lower().replace(os.sep, '/') destination_path = destination_path.lower().replace(os.sep, '/') + log.debug("Map: {} with: {}->{}".format(self.file_name, + source_path, destination_path)) if platform.system().lower() == "windows": self.file_name = self.file_name.lower().replace( source_path, destination_path) @@ -2878,6 +2878,7 @@ class DirmapCache: _project_name = None _project_settings = None _sync_module = None + _mapping = None @classmethod def project_name(cls): @@ -2897,6 +2898,36 @@ def sync_module(cls): cls._sync_module = ModulesManager().modules_by_name["sync_server"] return cls._sync_module + @classmethod + def mapping(cls): + return cls._mapping + + @classmethod + def set_mapping(cls, mapping): + cls._mapping = mapping + + +def dirmap_file_name_filter(file_name): + """Nuke callback function with single full path argument. + + Checks project settings for potential mapping from source to dest. + """ + + dirmap_processor = NukeDirmap( + file_name, + "nuke", + DirmapCache.project_name(), + DirmapCache.project_settings(), + DirmapCache.sync_module(), + ) + if not DirmapCache.mapping(): + DirmapCache.set_mapping(dirmap_processor.get_mappings()) + + dirmap_processor.process_dirmap(DirmapCache.mapping()) + if os.path.exists(dirmap_processor.file_name): + return dirmap_processor.file_name + return file_name + @contextlib.contextmanager def node_tempfile(): @@ -2942,25 +2973,6 @@ def duplicate_node(node): return dupli_node -def dirmap_file_name_filter(file_name): - """Nuke callback function with single full path argument. - - Checks project settings for potential mapping from source to dest. - """ - - dirmap_processor = NukeDirmap( - file_name, - "nuke", - DirmapCache.project_name(), - DirmapCache.project_settings(), - DirmapCache.sync_module(), - ) - dirmap_processor.process_dirmap() - if os.path.exists(dirmap_processor.file_name): - return dirmap_processor.file_name - return file_name - - def get_group_io_nodes(nodes): """Get the input and the output of a group of nodes.""" diff --git a/openpype/hosts/nuke/plugins/load/load_backdrop.py b/openpype/hosts/nuke/plugins/load/load_backdrop.py index f227aa161ab..67c7877e609 100644 --- a/openpype/hosts/nuke/plugins/load/load_backdrop.py +++ b/openpype/hosts/nuke/plugins/load/load_backdrop.py @@ -54,22 +54,19 @@ def load(self, context, name, namespace, data): version = context['version'] version_data = version.get("data", {}) vname = version.get("name", None) - first = version_data.get("frameStart", None) - last = version_data.get("frameEnd", None) namespace = namespace or context['asset']['name'] colorspace = version_data.get("colorspace", None) object_name = "{}_{}".format(name, namespace) # prepare data for imprinting # add additional metadata from the version to imprint to Avalon knob - add_keys = ["frameStart", "frameEnd", "handleStart", "handleEnd", - "source", "author", "fps"] + add_keys = ["source", "author", "fps"] - data_imprint = {"frameStart": first, - "frameEnd": last, - "version": vname, - "colorspaceInput": colorspace, - "objectName": object_name} + data_imprint = { + "version": vname, + "colorspaceInput": colorspace, + "objectName": object_name + } for k in add_keys: data_imprint.update({k: version_data[k]}) @@ -204,18 +201,13 @@ def update(self, container, representation): name = container['name'] version_data = version_doc.get("data", {}) vname = version_doc.get("name", None) - first = version_data.get("frameStart", None) - last = version_data.get("frameEnd", None) namespace = container['namespace'] colorspace = version_data.get("colorspace", None) object_name = "{}_{}".format(name, namespace) - add_keys = ["frameStart", "frameEnd", "handleStart", "handleEnd", - "source", "author", "fps"] + add_keys = ["source", "author", "fps"] data_imprint = {"representation": str(representation["_id"]), - "frameStart": first, - "frameEnd": last, "version": vname, "colorspaceInput": colorspace, "objectName": object_name} diff --git a/openpype/hosts/nuke/plugins/publish/collect_backdrop.py b/openpype/hosts/nuke/plugins/publish/collect_backdrop.py index 8eaefa68541..7d51af7e9e4 100644 --- a/openpype/hosts/nuke/plugins/publish/collect_backdrop.py +++ b/openpype/hosts/nuke/plugins/publish/collect_backdrop.py @@ -51,38 +51,10 @@ def process(self, instance): instance.data["label"] = "{0} ({1} nodes)".format( bckn.name(), len(instance.data["transientData"]["childNodes"])) - instance.data["families"].append(instance.data["family"]) - - # Get frame range - handle_start = instance.context.data["handleStart"] - handle_end = instance.context.data["handleEnd"] - first_frame = int(nuke.root()["first_frame"].getValue()) - last_frame = int(nuke.root()["last_frame"].getValue()) - # get version version = instance.context.data.get('version') - if not version: - raise RuntimeError("Script name has no version in the name.") - - instance.data['version'] = version - - # Add version data to instance - version_data = { - "handles": handle_start, - "handleStart": handle_start, - "handleEnd": handle_end, - "frameStart": first_frame + handle_start, - "frameEnd": last_frame - handle_end, - "version": int(version), - "families": [instance.data["family"]] + instance.data["families"], - "subset": instance.data["subset"], - "fps": instance.context.data["fps"] - } + if version: + instance.data['version'] = version - instance.data.update({ - "versionData": version_data, - "frameStart": first_frame, - "frameEnd": last_frame - }) self.log.info("Backdrop instance collected: `{}`".format(instance)) diff --git a/openpype/hosts/nuke/plugins/publish/extract_review_data.py b/openpype/hosts/nuke/plugins/publish/extract_review_data.py index dee82482957..c221af40fba 100644 --- a/openpype/hosts/nuke/plugins/publish/extract_review_data.py +++ b/openpype/hosts/nuke/plugins/publish/extract_review_data.py @@ -25,7 +25,7 @@ def process(self, instance): # review can be removed since `ProcessSubmittedJobOnFarm` will create # reviewable representation if needed if ( - "render.farm" in instance.data["families"] + instance.data.get("farm") and "review" in instance.data["families"] ): instance.data["families"].remove("review") diff --git a/openpype/hosts/nuke/plugins/publish/extract_review_data_lut.py b/openpype/hosts/nuke/plugins/publish/extract_review_data_lut.py index 67779e9599e..e4b7b155cd1 100644 --- a/openpype/hosts/nuke/plugins/publish/extract_review_data_lut.py +++ b/openpype/hosts/nuke/plugins/publish/extract_review_data_lut.py @@ -49,7 +49,12 @@ def process(self, instance): exporter.stagingDir, exporter.file).replace("\\", "/") instance.data["representations"] += data["representations"] - if "render.farm" in families: + # review can be removed since `ProcessSubmittedJobOnFarm` will create + # reviewable representation if needed + if ( + instance.data.get("farm") + and "review" in instance.data["families"] + ): instance.data["families"].remove("review") self.log.debug( diff --git a/openpype/hosts/nuke/plugins/publish/extract_review_data_mov.py b/openpype/hosts/nuke/plugins/publish/extract_review_data_mov.py index 3fcfc2a4b51..956d1a54a34 100644 --- a/openpype/hosts/nuke/plugins/publish/extract_review_data_mov.py +++ b/openpype/hosts/nuke/plugins/publish/extract_review_data_mov.py @@ -105,10 +105,7 @@ def process(self, instance): self, instance, o_name, o_data["extension"], multiple_presets) - if ( - "render.farm" in families or - "prerender.farm" in families - ): + if instance.data.get("farm"): if "review" in instance.data["families"]: instance.data["families"].remove("review") diff --git a/openpype/hosts/nuke/plugins/publish/extract_thumbnail.py b/openpype/hosts/nuke/plugins/publish/extract_thumbnail.py index a1a0e241c07..f391ca1e7c2 100644 --- a/openpype/hosts/nuke/plugins/publish/extract_thumbnail.py +++ b/openpype/hosts/nuke/plugins/publish/extract_thumbnail.py @@ -31,7 +31,7 @@ class ExtractThumbnail(publish.Extractor): def process(self, instance): - if "render.farm" in instance.data["families"]: + if instance.data.get("farm"): return with napi.maintained_selection(): diff --git a/openpype/hosts/photoshop/api/launch_logic.py b/openpype/hosts/photoshop/api/launch_logic.py index 89ba6ad4e6c..25732446b51 100644 --- a/openpype/hosts/photoshop/api/launch_logic.py +++ b/openpype/hosts/photoshop/api/launch_logic.py @@ -66,11 +66,11 @@ def result(self): return self._result def execute(self): - """Execute callback and store it's result. + """Execute callback and store its result. Method must be called from main thread. Item is marked as `done` when callback execution finished. Store output of callback of exception - information when callback raise one. + information when callback raises one. """ log.debug("Executing process in main thread") if self.done: diff --git a/openpype/hosts/resolve/api/menu.py b/openpype/hosts/resolve/api/menu.py index eeb9e65dec7..b3717e01ea6 100644 --- a/openpype/hosts/resolve/api/menu.py +++ b/openpype/hosts/resolve/api/menu.py @@ -69,7 +69,7 @@ def __init__(self, *args, **kwargs): # "Set colorspace from presets", self # ) # reset_resolution_btn = QtWidgets.QPushButton( - # "Reset Resolution from peresets", self + # "Set Resolution from presets", self # ) layout = QtWidgets.QVBoxLayout(self) @@ -108,7 +108,7 @@ def __init__(self, *args, **kwargs): libload_btn.clicked.connect(self.on_libload_clicked) # rename_btn.clicked.connect(self.on_rename_clicked) # set_colorspace_btn.clicked.connect(self.on_set_colorspace_clicked) - # reset_resolution_btn.clicked.connect(self.on_reset_resolution_clicked) + # reset_resolution_btn.clicked.connect(self.on_set_resolution_clicked) experimental_btn.clicked.connect(self.on_experimental_clicked) def on_workfile_clicked(self): @@ -145,8 +145,8 @@ def on_rename_clicked(self): def on_set_colorspace_clicked(self): print("Clicked Set Colorspace") - def on_reset_resolution_clicked(self): - print("Clicked Reset Resolution") + def on_set_resolution_clicked(self): + print("Clicked Set Resolution") def on_experimental_clicked(self): host_tools.show_experimental_tools_dialog() diff --git a/openpype/hosts/tvpaint/api/communication_server.py b/openpype/hosts/tvpaint/api/communication_server.py index e94e64e04a6..6f76c25e0ce 100644 --- a/openpype/hosts/tvpaint/api/communication_server.py +++ b/openpype/hosts/tvpaint/api/communication_server.py @@ -389,11 +389,11 @@ def __init__(self, callback, *args, **kwargs): self.kwargs = kwargs def execute(self): - """Execute callback and store it's result. + """Execute callback and store its result. Method must be called from main thread. Item is marked as `done` when callback execution finished. Store output of callback of exception - information when callback raise one. + information when callback raises one. """ log.debug("Executing process in main thread") if self.done: diff --git a/openpype/hosts/tvpaint/plugins/create/convert_legacy.py b/openpype/hosts/tvpaint/plugins/create/convert_legacy.py index 538c6e4c5e8..5cfa1faa506 100644 --- a/openpype/hosts/tvpaint/plugins/create/convert_legacy.py +++ b/openpype/hosts/tvpaint/plugins/create/convert_legacy.py @@ -55,7 +55,7 @@ def convert(self): self._convert_render_layers( to_convert["renderLayer"], current_instances) self._convert_render_passes( - to_convert["renderpass"], current_instances) + to_convert["renderPass"], current_instances) self._convert_render_scenes( to_convert["renderScene"], current_instances) self._convert_workfiles( @@ -116,7 +116,7 @@ def _convert_render_passes(self, render_passes, current_instances): render_layers_by_group_id = {} for instance in current_instances: if instance.get("creator_identifier") == "render.layer": - group_id = instance["creator_identifier"]["group_id"] + group_id = instance["creator_attributes"]["group_id"] render_layers_by_group_id[group_id] = instance for render_pass in render_passes: diff --git a/openpype/hosts/tvpaint/plugins/create/create_render.py b/openpype/hosts/tvpaint/plugins/create/create_render.py index 9711024c79c..2369c7329f6 100644 --- a/openpype/hosts/tvpaint/plugins/create/create_render.py +++ b/openpype/hosts/tvpaint/plugins/create/create_render.py @@ -415,11 +415,11 @@ def collect_instances(self): .get("creator_attributes", {}) .get("render_layer_instance_id") ) - render_layer_info = render_layers.get(render_layer_instance_id) + render_layer_info = render_layers.get(render_layer_instance_id, {}) self.update_instance_labels( instance_data, - render_layer_info["variant"], - render_layer_info["template_data"] + render_layer_info.get("variant"), + render_layer_info.get("template_data") ) instance = CreatedInstance.from_existing(instance_data, self) self._add_instance_to_context(instance) @@ -607,11 +607,11 @@ def get_pre_create_attr_defs(self): current_instances = self.host.list_instances() render_layers = [ { - "value": instance["instance_id"], - "label": instance["subset"] + "value": inst["instance_id"], + "label": inst["subset"] } - for instance in current_instances - if instance["creator_identifier"] == CreateRenderlayer.identifier + for inst in current_instances + if inst.get("creator_identifier") == CreateRenderlayer.identifier ] if not render_layers: render_layers.append({"value": None, "label": "N/A"}) @@ -697,6 +697,7 @@ def apply_settings(self, project_settings, system_settings): ["create"] ["auto_detect_render"] ) + self.enabled = plugin_settings.get("enabled", False) self.allow_group_rename = plugin_settings["allow_group_rename"] self.group_name_template = plugin_settings["group_name_template"] self.group_idx_offset = plugin_settings["group_idx_offset"] diff --git a/openpype/hosts/tvpaint/plugins/publish/collect_instance_frames.py b/openpype/hosts/tvpaint/plugins/publish/collect_instance_frames.py index 5eb702a1da4..63f04cf3ce6 100644 --- a/openpype/hosts/tvpaint/plugins/publish/collect_instance_frames.py +++ b/openpype/hosts/tvpaint/plugins/publish/collect_instance_frames.py @@ -22,9 +22,11 @@ def process(self, instance): context = instance.context frame_start = asset_doc["data"]["frameStart"] + fps = asset_doc["data"]["fps"] frame_end = frame_start + ( context.data["sceneMarkOut"] - context.data["sceneMarkIn"] ) + instance.data["fps"] = fps instance.data["frameStart"] = frame_start instance.data["frameEnd"] = frame_end self.log.info( diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_asset_name.py b/openpype/hosts/tvpaint/plugins/publish/validate_asset_name.py index 7e35726030d..d7984ce9719 100644 --- a/openpype/hosts/tvpaint/plugins/publish/validate_asset_name.py +++ b/openpype/hosts/tvpaint/plugins/publish/validate_asset_name.py @@ -1,5 +1,8 @@ import pyblish.api -from openpype.pipeline import PublishXmlValidationError +from openpype.pipeline import ( + PublishXmlValidationError, + OptionalPyblishPluginMixin, +) from openpype.hosts.tvpaint.api.pipeline import ( list_instances, write_instances, @@ -31,7 +34,10 @@ def process(self, context, plugin): write_instances(new_instance_items) -class ValidateAssetNames(pyblish.api.ContextPlugin): +class ValidateAssetName( + OptionalPyblishPluginMixin, + pyblish.api.ContextPlugin +): """Validate assset name present on instance. Asset name on instance should be the same as context's. @@ -43,6 +49,8 @@ class ValidateAssetNames(pyblish.api.ContextPlugin): actions = [FixAssetNames] def process(self, context): + if not self.is_active(context.data): + return context_asset_name = context.data["asset"] for instance in context: asset_name = instance.data.get("asset") diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_layers_visibility.py b/openpype/hosts/tvpaint/plugins/publish/validate_layers_visibility.py index 6a496a2e496..8e52a636f4f 100644 --- a/openpype/hosts/tvpaint/plugins/publish/validate_layers_visibility.py +++ b/openpype/hosts/tvpaint/plugins/publish/validate_layers_visibility.py @@ -11,7 +11,7 @@ class ValidateLayersVisiblity(pyblish.api.InstancePlugin): families = ["review", "render"] def process(self, instance): - layers = instance.data["layers"] + layers = instance.data.get("layers") # Instance have empty layers # - it is not job of this validator to check that if not layers: diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_marks.py b/openpype/hosts/tvpaint/plugins/publish/validate_marks.py index 0030b0fd1ce..7b2cc62bb5a 100644 --- a/openpype/hosts/tvpaint/plugins/publish/validate_marks.py +++ b/openpype/hosts/tvpaint/plugins/publish/validate_marks.py @@ -1,7 +1,10 @@ import json import pyblish.api -from openpype.pipeline import PublishXmlValidationError +from openpype.pipeline import ( + PublishXmlValidationError, + OptionalPyblishPluginMixin, +) from openpype.hosts.tvpaint.api.lib import execute_george @@ -23,7 +26,10 @@ def process(self, context, plugin): ) -class ValidateMarks(pyblish.api.ContextPlugin): +class ValidateMarks( + OptionalPyblishPluginMixin, + pyblish.api.ContextPlugin +): """Validate mark in and out are enabled and it's duration. Mark In/Out does not have to match frameStart and frameEnd but duration is @@ -59,6 +65,9 @@ def get_expected_data(context): } def process(self, context): + if not self.is_active(context.data): + return + current_data = { "markIn": context.data["sceneMarkIn"], "markInState": context.data["sceneMarkInState"], diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_scene_settings.py b/openpype/hosts/tvpaint/plugins/publish/validate_scene_settings.py index 4473e4b1b79..0ab8e811f58 100644 --- a/openpype/hosts/tvpaint/plugins/publish/validate_scene_settings.py +++ b/openpype/hosts/tvpaint/plugins/publish/validate_scene_settings.py @@ -1,11 +1,17 @@ import json import pyblish.api -from openpype.pipeline import PublishXmlValidationError +from openpype.pipeline import ( + PublishXmlValidationError, + OptionalPyblishPluginMixin, +) # TODO @iLliCiTiT add fix action for fps -class ValidateProjectSettings(pyblish.api.ContextPlugin): +class ValidateProjectSettings( + OptionalPyblishPluginMixin, + pyblish.api.ContextPlugin +): """Validate scene settings against database.""" label = "Validate Scene Settings" @@ -13,6 +19,9 @@ class ValidateProjectSettings(pyblish.api.ContextPlugin): optional = True def process(self, context): + if not self.is_active(context.data): + return + expected_data = context.data["assetEntity"]["data"] scene_data = { "fps": context.data.get("sceneFps"), diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_start_frame.py b/openpype/hosts/tvpaint/plugins/publish/validate_start_frame.py index 066e54c6707..229ccfcd18f 100644 --- a/openpype/hosts/tvpaint/plugins/publish/validate_start_frame.py +++ b/openpype/hosts/tvpaint/plugins/publish/validate_start_frame.py @@ -1,5 +1,8 @@ import pyblish.api -from openpype.pipeline import PublishXmlValidationError +from openpype.pipeline import ( + PublishXmlValidationError, + OptionalPyblishPluginMixin, +) from openpype.hosts.tvpaint.api.lib import execute_george @@ -14,7 +17,10 @@ def process(self, context, plugin): execute_george("tv_startframe 0") -class ValidateStartFrame(pyblish.api.ContextPlugin): +class ValidateStartFrame( + OptionalPyblishPluginMixin, + pyblish.api.ContextPlugin +): """Validate start frame being at frame 0.""" label = "Validate Start Frame" @@ -24,6 +30,9 @@ class ValidateStartFrame(pyblish.api.ContextPlugin): optional = True def process(self, context): + if not self.is_active(context.data): + return + start_frame = execute_george("tv_startframe") if start_frame == 0: return diff --git a/openpype/hosts/unreal/ue_workers.py b/openpype/hosts/unreal/ue_workers.py index 00f83a7d7a4..d1740124a87 100644 --- a/openpype/hosts/unreal/ue_workers.py +++ b/openpype/hosts/unreal/ue_workers.py @@ -5,29 +5,38 @@ import subprocess from distutils import dir_util from pathlib import Path -from typing import List +from typing import List, Union import openpype.hosts.unreal.lib as ue_lib from qtpy import QtCore -def parse_comp_progress(line: str, progress_signal: QtCore.Signal(int)) -> int: - match = re.search('\[[1-9]+/[0-9]+\]', line) +def parse_comp_progress(line: str, progress_signal: QtCore.Signal(int)): + match = re.search(r"\[[1-9]+/[0-9]+]", line) if match is not None: - split: list[str] = match.group().split('/') + split: list[str] = match.group().split("/") curr: float = float(split[0][1:]) total: float = float(split[1][:-1]) progress_signal.emit(int((curr / total) * 100.0)) -def parse_prj_progress(line: str, progress_signal: QtCore.Signal(int)) -> int: - match = re.search('@progress', line) +def parse_prj_progress(line: str, progress_signal: QtCore.Signal(int)): + match = re.search("@progress", line) if match is not None: - percent_match = re.search('\d{1,3}', line) + percent_match = re.search(r"\d{1,3}", line) progress_signal.emit(int(percent_match.group())) +def retrieve_exit_code(line: str): + match = re.search(r"ExitCode=\d+", line) + if match is not None: + split: list[str] = match.group().split("=") + return int(split[1]) + + return None + + class UEProjectGenerationWorker(QtCore.QObject): finished = QtCore.Signal(str) failed = QtCore.Signal(str) @@ -77,16 +86,19 @@ def run(self): if self.dev_mode: stage_count = 4 - self.stage_begin.emit(f'Generating a new UE project ... 1 out of ' - f'{stage_count}') + self.stage_begin.emit( + ("Generating a new UE project ... 1 out of " + f"{stage_count}")) - commandlet_cmd = [f'{ue_editor_exe.as_posix()}', - f'{cmdlet_project.as_posix()}', - f'-run=OPGenerateProject', - f'{project_file.resolve().as_posix()}'] + commandlet_cmd = [ + f"{ue_editor_exe.as_posix()}", + f"{cmdlet_project.as_posix()}", + "-run=OPGenerateProject", + f"{project_file.resolve().as_posix()}", + ] if self.dev_mode: - commandlet_cmd.append('-GenerateCode') + commandlet_cmd.append("-GenerateCode") gen_process = subprocess.Popen(commandlet_cmd, stdout=subprocess.PIPE, @@ -94,24 +106,27 @@ def run(self): for line in gen_process.stdout: decoded_line = line.decode(errors="replace") - print(decoded_line, end='') + print(decoded_line, end="") self.log.emit(decoded_line) gen_process.stdout.close() return_code = gen_process.wait() if return_code and return_code != 0: - msg = 'Failed to generate ' + self.project_name \ - + f' project! Exited with return code {return_code}' + msg = ( + f"Failed to generate {self.project_name} " + f"project! Exited with return code {return_code}" + ) self.failed.emit(msg, return_code) raise RuntimeError(msg) print("--- Project has been generated successfully.") - self.stage_begin.emit(f'Writing the Engine ID of the build UE ... 1' - f' out of {stage_count}') + self.stage_begin.emit( + (f"Writing the Engine ID of the build UE ... 1" + f" out of {stage_count}")) if not project_file.is_file(): - msg = "Failed to write the Engine ID into .uproject file! Can " \ - "not read!" + msg = ("Failed to write the Engine ID into .uproject file! Can " + "not read!") self.failed.emit(msg) raise RuntimeError(msg) @@ -125,13 +140,14 @@ def run(self): pf.seek(0) json.dump(pf_json, pf, indent=4) pf.truncate() - print(f'--- Engine ID has been written into the project file') + print("--- Engine ID has been written into the project file") self.progress.emit(90) if self.dev_mode: # 2nd stage - self.stage_begin.emit(f'Generating project files ... 2 out of ' - f'{stage_count}') + self.stage_begin.emit( + (f"Generating project files ... 2 out of " + f"{stage_count}")) self.progress.emit(0) ubt_path = ue_lib.get_path_to_ubt(self.engine_path, @@ -154,8 +170,8 @@ def run(self): stdout=subprocess.PIPE, stderr=subprocess.PIPE) for line in gen_proc.stdout: - decoded_line: str = line.decode(errors='replace') - print(decoded_line, end='') + decoded_line: str = line.decode(errors="replace") + print(decoded_line, end="") self.log.emit(decoded_line) parse_prj_progress(decoded_line, self.progress) @@ -163,13 +179,13 @@ def run(self): return_code = gen_proc.wait() if return_code and return_code != 0: - msg = 'Failed to generate project files! ' \ - f'Exited with return code {return_code}' + msg = ("Failed to generate project files! " + f"Exited with return code {return_code}") self.failed.emit(msg, return_code) raise RuntimeError(msg) - self.stage_begin.emit(f'Building the project ... 3 out of ' - f'{stage_count}') + self.stage_begin.emit( + f"Building the project ... 3 out of {stage_count}") self.progress.emit(0) # 3rd stage build_prj_cmd = [ubt_path.as_posix(), @@ -177,16 +193,16 @@ def run(self): arch, "Development", "-TargetType=Editor", - f'-Project={project_file}', - f'{project_file}', + f"-Project={project_file}", + f"{project_file}", "-IgnoreJunk"] build_prj_proc = subprocess.Popen(build_prj_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) for line in build_prj_proc.stdout: - decoded_line: str = line.decode(errors='replace') - print(decoded_line, end='') + decoded_line: str = line.decode(errors="replace") + print(decoded_line, end="") self.log.emit(decoded_line) parse_comp_progress(decoded_line, self.progress) @@ -194,16 +210,17 @@ def run(self): return_code = build_prj_proc.wait() if return_code and return_code != 0: - msg = 'Failed to build project! ' \ - f'Exited with return code {return_code}' + msg = ("Failed to build project! " + f"Exited with return code {return_code}") self.failed.emit(msg, return_code) raise RuntimeError(msg) # ensure we have PySide2 installed in engine self.progress.emit(0) - self.stage_begin.emit(f'Checking PySide2 installation... {stage_count}' - f' out of {stage_count}') + self.stage_begin.emit( + (f"Checking PySide2 installation... {stage_count} " + f" out of {stage_count}")) python_path = None if platform.system().lower() == "windows": python_path = self.engine_path / ("Engine/Binaries/ThirdParty/" @@ -225,9 +242,30 @@ def run(self): msg = f"Unreal Python not found at {python_path}" self.failed.emit(msg, 1) raise RuntimeError(msg) - subprocess.check_call( - [python_path.as_posix(), "-m", "pip", "install", "pyside2"] - ) + pyside_cmd = [python_path.as_posix(), + "-m", + "pip", + "install", + "pyside2"] + + pyside_install = subprocess.Popen(pyside_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + + for line in pyside_install.stdout: + decoded_line: str = line.decode(errors="replace") + print(decoded_line, end="") + self.log.emit(decoded_line) + + pyside_install.stdout.close() + return_code = pyside_install.wait() + + if return_code and return_code != 0: + msg = ("Failed to create the project! " + "The installation of PySide2 has failed!") + self.failed.emit(msg, return_code) + raise RuntimeError(msg) + self.progress.emit(100) self.finished.emit("Project successfully built!") @@ -266,26 +304,30 @@ def _build_and_move_plugin(self, plugin_build_path: Path): # in order to successfully build the plugin, # It must be built outside the Engine directory and then moved - build_plugin_cmd: List[str] = [f'{uat_path.as_posix()}', - 'BuildPlugin', - f'-Plugin={uplugin_path.as_posix()}', - f'-Package={temp_dir.as_posix()}'] + build_plugin_cmd: List[str] = [f"{uat_path.as_posix()}", + "BuildPlugin", + f"-Plugin={uplugin_path.as_posix()}", + f"-Package={temp_dir.as_posix()}"] build_proc = subprocess.Popen(build_plugin_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return_code: Union[None, int] = None for line in build_proc.stdout: - decoded_line: str = line.decode(errors='replace') - print(decoded_line, end='') + decoded_line: str = line.decode(errors="replace") + print(decoded_line, end="") self.log.emit(decoded_line) + if return_code is None: + return_code = retrieve_exit_code(decoded_line) parse_comp_progress(decoded_line, self.progress) build_proc.stdout.close() - return_code = build_proc.wait() + build_proc.wait() if return_code and return_code != 0: - msg = 'Failed to build plugin' \ - f' project! Exited with return code {return_code}' + msg = ("Failed to build plugin" + f" project! Exited with return code {return_code}") + dir_util.remove_tree(temp_dir.as_posix()) self.failed.emit(msg, return_code) raise RuntimeError(msg) diff --git a/openpype/lib/applications.py b/openpype/lib/applications.py index 7cc296f47bc..127d31d042d 100644 --- a/openpype/lib/applications.py +++ b/openpype/lib/applications.py @@ -889,7 +889,8 @@ def __init__(self, application, executable, env_group=None, **data): self.modules_manager = ModulesManager() # Logger - logger_name = "{}-{}".format(self.__class__.__name__, self.app_name) + logger_name = "{}-{}".format(self.__class__.__name__, + self.application.full_name) self.log = Logger.get_logger(logger_name) self.executable = executable @@ -1246,7 +1247,7 @@ def launch(self): args_len_str = " ({})".format(len(args)) self.log.info( "Launching \"{}\" with args{}: {}".format( - self.app_name, args_len_str, args + self.application.full_name, args_len_str, args ) ) self.launch_args = args @@ -1271,7 +1272,9 @@ def launch(self): exc_info=True ) - self.log.debug("Launch of {} finished.".format(self.app_name)) + self.log.debug("Launch of {} finished.".format( + self.application.full_name + )) return self.process @@ -1508,8 +1511,8 @@ def prepare_app_environments( if key in source_env: source_env[key] = value - # `added_env_keys` has debug purpose - added_env_keys = {app.group.name, app.name} + # `app_and_tool_labels` has debug purpose + app_and_tool_labels = [app.full_name] # Environments for application environments = [ app.group.environment, @@ -1532,15 +1535,14 @@ def prepare_app_environments( for group_name in sorted(groups_by_name.keys()): group = groups_by_name[group_name] environments.append(group.environment) - added_env_keys.add(group_name) for tool_name in sorted(tool_by_group_name[group_name].keys()): tool = tool_by_group_name[group_name][tool_name] environments.append(tool.environment) - added_env_keys.add(tool.name) + app_and_tool_labels.append(tool.full_name) log.debug( "Will add environments for apps and tools: {}".format( - ", ".join(added_env_keys) + ", ".join(app_and_tool_labels) ) ) diff --git a/openpype/lib/execute.py b/openpype/lib/execute.py index 759a4db0cb7..6f9a0952851 100644 --- a/openpype/lib/execute.py +++ b/openpype/lib/execute.py @@ -8,6 +8,8 @@ from .log import Logger from .vendor_bin_utils import find_executable +from .openpype_version import is_running_from_build + # MSDN process creation flag (Windows only) CREATE_NO_WINDOW = 0x08000000 @@ -102,6 +104,10 @@ def run_subprocess(*args, **kwargs): if ( platform.system().lower() == "windows" and "creationflags" not in kwargs + # shell=True already tries to hide the console window + # and passing these creationflags then shows the window again + # so we avoid it for shell=True cases + and kwargs.get("shell") is not True ): kwargs["creationflags"] = ( subprocess.CREATE_NEW_PROCESS_GROUP @@ -196,6 +202,11 @@ def run_openpype_process(*args, **kwargs): # Skip envs that can affect OpenPype process # - fill more if you find more env = clean_envs_for_openpype_process(os.environ) + + # Only keep OpenPype version if we are running from build. + if not is_running_from_build(): + env.pop("OPENPYPE_VERSION", None) + return run_subprocess(args, env=env, **kwargs) diff --git a/openpype/lib/file_transaction.py b/openpype/lib/file_transaction.py index fe70b37cb19..81332a88915 100644 --- a/openpype/lib/file_transaction.py +++ b/openpype/lib/file_transaction.py @@ -13,6 +13,16 @@ from shutil import copyfile +class DuplicateDestinationError(ValueError): + """Error raised when transfer destination already exists in queue. + + The error is only raised if `allow_queue_replacements` is False on the + FileTransaction instance and the added file to transfer is of a different + src file than the one already detected in the queue. + + """ + + class FileTransaction(object): """File transaction with rollback options. @@ -44,7 +54,7 @@ class FileTransaction(object): MODE_COPY = 0 MODE_HARDLINK = 1 - def __init__(self, log=None): + def __init__(self, log=None, allow_queue_replacements=False): if log is None: log = logging.getLogger("FileTransaction") @@ -60,6 +70,8 @@ def __init__(self, log=None): # Backup file location mapping to original locations self._backup_to_original = {} + self._allow_queue_replacements = allow_queue_replacements + def add(self, src, dst, mode=MODE_COPY): """Add a new file to transfer queue. @@ -82,6 +94,14 @@ def add(self, src, dst, mode=MODE_COPY): src, dst)) return else: + if not self._allow_queue_replacements: + raise DuplicateDestinationError( + "Transfer to destination is already in queue: " + "{} -> {}. It's not allowed to be replaced by " + "a new transfer from {}".format( + queued_src, dst, src + )) + self.log.warning("File transfer in queue replaced..") self.log.debug( "Removed from queue: {} -> {} replaced by {} -> {}".format( diff --git a/openpype/lib/vendor_bin_utils.py b/openpype/lib/vendor_bin_utils.py index b6797dbba0c..e5deb7a6b23 100644 --- a/openpype/lib/vendor_bin_utils.py +++ b/openpype/lib/vendor_bin_utils.py @@ -224,18 +224,26 @@ def find_tool_in_custom_paths(paths, tool, validation_func=None): def _check_args_returncode(args): try: - # Python 2 compatibility where DEVNULL is not available + kwargs = {} + if platform.system().lower() == "windows": + kwargs["creationflags"] = ( + subprocess.CREATE_NEW_PROCESS_GROUP + | getattr(subprocess, "DETACHED_PROCESS", 0) + | getattr(subprocess, "CREATE_NO_WINDOW", 0) + ) + if hasattr(subprocess, "DEVNULL"): proc = subprocess.Popen( args, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, + **kwargs ) proc.wait() else: with open(os.devnull, "w") as devnull: proc = subprocess.Popen( - args, stdout=devnull, stderr=devnull, + args, stdout=devnull, stderr=devnull, **kwargs ) proc.wait() @@ -375,7 +383,7 @@ def get_ffmpeg_tool_path(tool="ffmpeg"): # Look to PATH for the tool if not tool_executable_path: from_path = find_executable(tool) - if from_path and _oiio_executable_validation(from_path): + if from_path and _ffmpeg_executable_validation(from_path): tool_executable_path = from_path CachedToolPaths.cache_executable_path(tool, tool_executable_path) diff --git a/openpype/modules/clockify/clockify_api.py b/openpype/modules/clockify/clockify_api.py index 6af911fffcb..80979c83ab2 100644 --- a/openpype/modules/clockify/clockify_api.py +++ b/openpype/modules/clockify/clockify_api.py @@ -6,34 +6,22 @@ import requests from .constants import ( CLOCKIFY_ENDPOINT, - ADMIN_PERMISSION_NAMES + ADMIN_PERMISSION_NAMES, ) from openpype.lib.local_settings import OpenPypeSecureRegistry - - -def time_check(obj): - if obj.request_counter < 10: - obj.request_counter += 1 - return - - wait_time = 1 - (time.time() - obj.request_time) - if wait_time > 0: - time.sleep(wait_time) - - obj.request_time = time.time() - obj.request_counter = 0 +from openpype.lib import Logger class ClockifyAPI: + log = Logger.get_logger(__name__) + def __init__(self, api_key=None, master_parent=None): self.workspace_name = None - self.workspace_id = None self.master_parent = master_parent self.api_key = api_key - self.request_counter = 0 - self.request_time = time.time() - + self._workspace_id = None + self._user_id = None self._secure_registry = None @property @@ -44,11 +32,19 @@ def secure_registry(self): @property def headers(self): - return {"X-Api-Key": self.api_key} + return {"x-api-key": self.api_key} + + @property + def workspace_id(self): + return self._workspace_id + + @property + def user_id(self): + return self._user_id def verify_api(self): for key, value in self.headers.items(): - if value is None or value.strip() == '': + if value is None or value.strip() == "": return False return True @@ -59,65 +55,55 @@ def set_api(self, api_key=None): if api_key is not None and self.validate_api_key(api_key) is True: self.api_key = api_key self.set_workspace() + self.set_user_id() if self.master_parent: self.master_parent.signed_in() return True return False def validate_api_key(self, api_key): - test_headers = {'X-Api-Key': api_key} - action_url = 'workspaces/' - time_check(self) + test_headers = {"x-api-key": api_key} + action_url = "user" response = requests.get( - CLOCKIFY_ENDPOINT + action_url, - headers=test_headers + CLOCKIFY_ENDPOINT + action_url, headers=test_headers ) if response.status_code != 200: return False return True - def validate_workspace_perm(self, workspace_id=None): - user_id = self.get_user_id() + def validate_workspace_permissions(self, workspace_id=None, user_id=None): if user_id is None: + self.log.info("No user_id found during validation") return False if workspace_id is None: workspace_id = self.workspace_id - action_url = "/workspaces/{}/users/{}/permissions".format( - workspace_id, user_id - ) - time_check(self) + action_url = f"workspaces/{workspace_id}/users?includeRoles=1" response = requests.get( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers + CLOCKIFY_ENDPOINT + action_url, headers=self.headers ) - user_permissions = response.json() - for perm in user_permissions: - if perm['name'] in ADMIN_PERMISSION_NAMES: + data = response.json() + for user in data: + if user.get("id") == user_id: + roles_data = user.get("roles") + for entities in roles_data: + if entities.get("role") in ADMIN_PERMISSION_NAMES: return True return False def get_user_id(self): - action_url = 'v1/user/' - time_check(self) + action_url = "user" response = requests.get( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers + CLOCKIFY_ENDPOINT + action_url, headers=self.headers ) - # this regex is neccessary: UNICODE strings are crashing - # during json serialization - id_regex = '\"{1}id\"{1}\:{1}\"{1}\w+\"{1}' - result = re.findall(id_regex, str(response.content)) - if len(result) != 1: - # replace with log and better message? - print('User ID was not found (this is a BUG!!!)') - return None - return json.loads('{'+result[0]+'}')['id'] + result = response.json() + user_id = result.get("id", None) + + return user_id def set_workspace(self, name=None): if name is None: - name = os.environ.get('CLOCKIFY_WORKSPACE', None) + name = os.environ.get("CLOCKIFY_WORKSPACE", None) self.workspace_name = name - self.workspace_id = None if self.workspace_name is None: return try: @@ -125,7 +111,7 @@ def set_workspace(self, name=None): except Exception: result = False if result is not False: - self.workspace_id = result + self._workspace_id = result if self.master_parent is not None: self.master_parent.start_timer_check() return True @@ -139,6 +125,14 @@ def validate_workspace(self, name=None): return all_workspaces[name] return False + def set_user_id(self): + try: + user_id = self.get_user_id() + except Exception: + user_id = None + if user_id is not None: + self._user_id = user_id + def get_api_key(self): return self.secure_registry.get_item("api_key", None) @@ -146,11 +140,9 @@ def save_api_key(self, api_key): self.secure_registry.set_item("api_key", api_key) def get_workspaces(self): - action_url = 'workspaces/' - time_check(self) + action_url = "workspaces/" response = requests.get( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers + CLOCKIFY_ENDPOINT + action_url, headers=self.headers ) return { workspace["name"]: workspace["id"] for workspace in response.json() @@ -159,27 +151,22 @@ def get_workspaces(self): def get_projects(self, workspace_id=None): if workspace_id is None: workspace_id = self.workspace_id - action_url = 'workspaces/{}/projects/'.format(workspace_id) - time_check(self) + action_url = f"workspaces/{workspace_id}/projects" response = requests.get( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers + CLOCKIFY_ENDPOINT + action_url, headers=self.headers ) - - return { - project["name"]: project["id"] for project in response.json() - } + if response.status_code != 403: + result = response.json() + return {project["name"]: project["id"] for project in result} def get_project_by_id(self, project_id, workspace_id=None): if workspace_id is None: workspace_id = self.workspace_id - action_url = 'workspaces/{}/projects/{}/'.format( + action_url = "workspaces/{}/projects/{}".format( workspace_id, project_id ) - time_check(self) response = requests.get( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers + CLOCKIFY_ENDPOINT + action_url, headers=self.headers ) return response.json() @@ -187,32 +174,24 @@ def get_project_by_id(self, project_id, workspace_id=None): def get_tags(self, workspace_id=None): if workspace_id is None: workspace_id = self.workspace_id - action_url = 'workspaces/{}/tags/'.format(workspace_id) - time_check(self) + action_url = "workspaces/{}/tags".format(workspace_id) response = requests.get( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers + CLOCKIFY_ENDPOINT + action_url, headers=self.headers ) - return { - tag["name"]: tag["id"] for tag in response.json() - } + return {tag["name"]: tag["id"] for tag in response.json()} def get_tasks(self, project_id, workspace_id=None): if workspace_id is None: workspace_id = self.workspace_id - action_url = 'workspaces/{}/projects/{}/tasks/'.format( + action_url = "workspaces/{}/projects/{}/tasks".format( workspace_id, project_id ) - time_check(self) response = requests.get( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers + CLOCKIFY_ENDPOINT + action_url, headers=self.headers ) - return { - task["name"]: task["id"] for task in response.json() - } + return {task["name"]: task["id"] for task in response.json()} def get_workspace_id(self, workspace_name): all_workspaces = self.get_workspaces() @@ -236,48 +215,64 @@ def get_tag_id(self, tag_name, workspace_id=None): return None return all_tasks[tag_name] - def get_task_id( - self, task_name, project_id, workspace_id=None - ): + def get_task_id(self, task_name, project_id, workspace_id=None): if workspace_id is None: workspace_id = self.workspace_id - all_tasks = self.get_tasks( - project_id, workspace_id - ) + all_tasks = self.get_tasks(project_id, workspace_id) if task_name not in all_tasks: return None return all_tasks[task_name] def get_current_time(self): - return str(datetime.datetime.utcnow().isoformat())+'Z' + return str(datetime.datetime.utcnow().isoformat()) + "Z" def start_time_entry( - self, description, project_id, task_id=None, tag_ids=[], - workspace_id=None, billable=True + self, + description, + project_id, + task_id=None, + tag_ids=None, + workspace_id=None, + user_id=None, + billable=True, ): # Workspace if workspace_id is None: workspace_id = self.workspace_id + # User ID + if user_id is None: + user_id = self._user_id + + # get running timer to check if we need to start it + current_timer = self.get_in_progress() # Check if is currently run another times and has same values - current = self.get_in_progress(workspace_id) - if current is not None: + # DO not restart the timer, if it is already running for curent task + if current_timer: + current_timer_hierarchy = current_timer.get("description") + current_project_id = current_timer.get("projectId") + current_task_id = current_timer.get("taskId") if ( - current.get("description", None) == description and - current.get("projectId", None) == project_id and - current.get("taskId", None) == task_id + description == current_timer_hierarchy + and project_id == current_project_id + and task_id == current_task_id ): + self.log.info( + "Timer for the current project is already running" + ) self.bool_timer_run = True return self.bool_timer_run - self.finish_time_entry(workspace_id) + self.finish_time_entry() # Convert billable to strings if billable: - billable = 'true' + billable = "true" else: - billable = 'false' + billable = "false" # Rest API Action - action_url = 'workspaces/{}/timeEntries/'.format(workspace_id) + action_url = "workspaces/{}/user/{}/time-entries".format( + workspace_id, user_id + ) start = self.get_current_time() body = { "start": start, @@ -285,169 +280,135 @@ def start_time_entry( "description": description, "projectId": project_id, "taskId": task_id, - "tagIds": tag_ids + "tagIds": tag_ids, } - time_check(self) response = requests.post( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers, - json=body + CLOCKIFY_ENDPOINT + action_url, headers=self.headers, json=body ) - - success = False if response.status_code < 300: - success = True - return success + return True + return False - def get_in_progress(self, workspace_id=None): + def _get_current_timer_values(self, response): + if response is None: + return + try: + output = response.json() + except json.decoder.JSONDecodeError: + return None + if output and isinstance(output, list): + return output[0] + return None + + def get_in_progress(self, user_id=None, workspace_id=None): if workspace_id is None: workspace_id = self.workspace_id - action_url = 'workspaces/{}/timeEntries/inProgress'.format( - workspace_id + if user_id is None: + user_id = self.user_id + + action_url = ( + f"workspaces/{workspace_id}/user/" + f"{user_id}/time-entries?in-progress=1" ) - time_check(self) response = requests.get( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers + CLOCKIFY_ENDPOINT + action_url, headers=self.headers ) - try: - output = response.json() - except json.decoder.JSONDecodeError: - output = None - return output + return self._get_current_timer_values(response) - def finish_time_entry(self, workspace_id=None): + def finish_time_entry(self, workspace_id=None, user_id=None): if workspace_id is None: workspace_id = self.workspace_id - current = self.get_in_progress(workspace_id) - if current is None: + if user_id is None: + user_id = self.user_id + current_timer = self.get_in_progress() + if not current_timer: return - - current_id = current["id"] - action_url = 'workspaces/{}/timeEntries/{}'.format( - workspace_id, current_id + action_url = "workspaces/{}/user/{}/time-entries".format( + workspace_id, user_id ) - body = { - "start": current["timeInterval"]["start"], - "billable": current["billable"], - "description": current["description"], - "projectId": current["projectId"], - "taskId": current["taskId"], - "tagIds": current["tagIds"], - "end": self.get_current_time() - } - time_check(self) - response = requests.put( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers, - json=body + body = {"end": self.get_current_time()} + response = requests.patch( + CLOCKIFY_ENDPOINT + action_url, headers=self.headers, json=body ) return response.json() - def get_time_entries( - self, workspace_id=None, quantity=10 - ): + def get_time_entries(self, workspace_id=None, user_id=None, quantity=10): if workspace_id is None: workspace_id = self.workspace_id - action_url = 'workspaces/{}/timeEntries/'.format(workspace_id) - time_check(self) + if user_id is None: + user_id = self.user_id + action_url = "workspaces/{}/user/{}/time-entries".format( + workspace_id, user_id + ) response = requests.get( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers + CLOCKIFY_ENDPOINT + action_url, headers=self.headers ) return response.json()[:quantity] - def remove_time_entry(self, tid, workspace_id=None): + def remove_time_entry(self, tid, workspace_id=None, user_id=None): if workspace_id is None: workspace_id = self.workspace_id - action_url = 'workspaces/{}/timeEntries/{}'.format( - workspace_id, tid + action_url = "workspaces/{}/user/{}/time-entries/{}".format( + workspace_id, user_id, tid ) - time_check(self) response = requests.delete( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers + CLOCKIFY_ENDPOINT + action_url, headers=self.headers ) return response.json() def add_project(self, name, workspace_id=None): if workspace_id is None: workspace_id = self.workspace_id - action_url = 'workspaces/{}/projects/'.format(workspace_id) + action_url = "workspaces/{}/projects".format(workspace_id) body = { "name": name, "clientId": "", "isPublic": "false", - "estimate": { - "estimate": 0, - "type": "AUTO" - }, + "estimate": {"estimate": 0, "type": "AUTO"}, "color": "#f44336", - "billable": "true" + "billable": "true", } - time_check(self) response = requests.post( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers, - json=body + CLOCKIFY_ENDPOINT + action_url, headers=self.headers, json=body ) return response.json() def add_workspace(self, name): - action_url = 'workspaces/' + action_url = "workspaces/" body = {"name": name} - time_check(self) response = requests.post( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers, - json=body + CLOCKIFY_ENDPOINT + action_url, headers=self.headers, json=body ) return response.json() - def add_task( - self, name, project_id, workspace_id=None - ): + def add_task(self, name, project_id, workspace_id=None): if workspace_id is None: workspace_id = self.workspace_id - action_url = 'workspaces/{}/projects/{}/tasks/'.format( + action_url = "workspaces/{}/projects/{}/tasks".format( workspace_id, project_id ) - body = { - "name": name, - "projectId": project_id - } - time_check(self) + body = {"name": name, "projectId": project_id} response = requests.post( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers, - json=body + CLOCKIFY_ENDPOINT + action_url, headers=self.headers, json=body ) return response.json() def add_tag(self, name, workspace_id=None): if workspace_id is None: workspace_id = self.workspace_id - action_url = 'workspaces/{}/tags'.format(workspace_id) - body = { - "name": name - } - time_check(self) + action_url = "workspaces/{}/tags".format(workspace_id) + body = {"name": name} response = requests.post( - CLOCKIFY_ENDPOINT + action_url, - headers=self.headers, - json=body + CLOCKIFY_ENDPOINT + action_url, headers=self.headers, json=body ) return response.json() - def delete_project( - self, project_id, workspace_id=None - ): + def delete_project(self, project_id, workspace_id=None): if workspace_id is None: workspace_id = self.workspace_id - action_url = '/workspaces/{}/projects/{}'.format( + action_url = "/workspaces/{}/projects/{}".format( workspace_id, project_id ) - time_check(self) response = requests.delete( CLOCKIFY_ENDPOINT + action_url, headers=self.headers, @@ -455,12 +416,12 @@ def delete_project( return response.json() def convert_input( - self, entity_id, entity_name, mode='Workspace', project_id=None + self, entity_id, entity_name, mode="Workspace", project_id=None ): if entity_id is None: error = False error_msg = 'Missing information "{}"' - if mode.lower() == 'workspace': + if mode.lower() == "workspace": if entity_id is None and entity_name is None: if self.workspace_id is not None: entity_id = self.workspace_id @@ -471,14 +432,14 @@ def convert_input( else: if entity_id is None and entity_name is None: error = True - elif mode.lower() == 'project': + elif mode.lower() == "project": entity_id = self.get_project_id(entity_name) - elif mode.lower() == 'task': + elif mode.lower() == "task": entity_id = self.get_task_id( task_name=entity_name, project_id=project_id ) else: - raise TypeError('Unknown type') + raise TypeError("Unknown type") # Raise error if error: raise ValueError(error_msg.format(mode)) diff --git a/openpype/modules/clockify/clockify_module.py b/openpype/modules/clockify/clockify_module.py index 300d5576e2a..200a268ad7c 100644 --- a/openpype/modules/clockify/clockify_module.py +++ b/openpype/modules/clockify/clockify_module.py @@ -2,24 +2,13 @@ import threading import time -from openpype.modules import ( - OpenPypeModule, - ITrayModule, - IPluginPaths -) - -from .clockify_api import ClockifyAPI -from .constants import ( - CLOCKIFY_FTRACK_USER_PATH, - CLOCKIFY_FTRACK_SERVER_PATH -) - - -class ClockifyModule( - OpenPypeModule, - ITrayModule, - IPluginPaths -): +from openpype.modules import OpenPypeModule, ITrayModule, IPluginPaths +from openpype.client import get_asset_by_name + +from .constants import CLOCKIFY_FTRACK_USER_PATH, CLOCKIFY_FTRACK_SERVER_PATH + + +class ClockifyModule(OpenPypeModule, ITrayModule, IPluginPaths): name = "clockify" def initialize(self, modules_settings): @@ -33,18 +22,23 @@ def initialize(self, modules_settings): self.timer_manager = None self.MessageWidgetClass = None self.message_widget = None - - self.clockapi = ClockifyAPI(master_parent=self) + self._clockify_api = None # TimersManager attributes # - set `timers_manager_connector` only in `tray_init` self.timers_manager_connector = None self._timers_manager_module = None + @property + def clockify_api(self): + if self._clockify_api is None: + from .clockify_api import ClockifyAPI + + self._clockify_api = ClockifyAPI(master_parent=self) + return self._clockify_api + def get_global_environments(self): - return { - "CLOCKIFY_WORKSPACE": self.workspace_name - } + return {"CLOCKIFY_WORKSPACE": self.workspace_name} def tray_init(self): from .widgets import ClockifySettings, MessageWidget @@ -52,7 +46,7 @@ def tray_init(self): self.MessageWidgetClass = MessageWidget self.message_widget = None - self.widget_settings = ClockifySettings(self.clockapi) + self.widget_settings = ClockifySettings(self.clockify_api) self.widget_settings_required = None self.thread_timer_check = None @@ -61,7 +55,7 @@ def tray_init(self): self.bool_api_key_set = False self.bool_workspace_set = False self.bool_timer_run = False - self.bool_api_key_set = self.clockapi.set_api() + self.bool_api_key_set = self.clockify_api.set_api() # Define itself as TimersManager connector self.timers_manager_connector = self @@ -71,12 +65,11 @@ def tray_start(self): self.show_settings() return - self.bool_workspace_set = self.clockapi.workspace_id is not None + self.bool_workspace_set = self.clockify_api.workspace_id is not None if self.bool_workspace_set is False: return self.start_timer_check() - self.set_menu_visibility() def tray_exit(self, *_a, **_kw): @@ -85,23 +78,19 @@ def tray_exit(self, *_a, **_kw): def get_plugin_paths(self): """Implementaton of IPluginPaths to get plugin paths.""" actions_path = os.path.join( - os.path.dirname(os.path.abspath(__file__)), - "launcher_actions" + os.path.dirname(os.path.abspath(__file__)), "launcher_actions" ) - return { - "actions": [actions_path] - } + return {"actions": [actions_path]} def get_ftrack_event_handler_paths(self): """Function for Ftrack module to add ftrack event handler paths.""" return { "user": [CLOCKIFY_FTRACK_USER_PATH], - "server": [CLOCKIFY_FTRACK_SERVER_PATH] + "server": [CLOCKIFY_FTRACK_SERVER_PATH], } def clockify_timer_stopped(self): self.bool_timer_run = False - # Call `ITimersManager` method self.timer_stopped() def start_timer_check(self): @@ -122,45 +111,44 @@ def stop_timer_check(self): def check_running(self): while self.bool_thread_check_running is True: bool_timer_run = False - if self.clockapi.get_in_progress() is not None: + if self.clockify_api.get_in_progress() is not None: bool_timer_run = True if self.bool_timer_run != bool_timer_run: if self.bool_timer_run is True: self.clockify_timer_stopped() elif self.bool_timer_run is False: - actual_timer = self.clockapi.get_in_progress() - if not actual_timer: + current_timer = self.clockify_api.get_in_progress() + if current_timer is None: continue - - actual_proj_id = actual_timer["projectId"] - if not actual_proj_id: + current_proj_id = current_timer.get("projectId") + if not current_proj_id: continue - project = self.clockapi.get_project_by_id(actual_proj_id) + project = self.clockify_api.get_project_by_id( + current_proj_id + ) if project and project.get("code") == 501: continue - project_name = project["name"] + project_name = project.get("name") - actual_timer_hierarchy = actual_timer["description"] - hierarchy_items = actual_timer_hierarchy.split("/") + current_timer_hierarchy = current_timer.get("description") + if not current_timer_hierarchy: + continue + hierarchy_items = current_timer_hierarchy.split("/") # Each pype timer must have at least 2 items! if len(hierarchy_items) < 2: continue + task_name = hierarchy_items[-1] hierarchy = hierarchy_items[:-1] - task_type = None - if len(actual_timer.get("tags", [])) > 0: - task_type = actual_timer["tags"][0].get("name") data = { "task_name": task_name, "hierarchy": hierarchy, "project_name": project_name, - "task_type": task_type } - # Call `ITimersManager` method self.timer_started(data) self.bool_timer_run = bool_timer_run @@ -184,6 +172,7 @@ def on_message_widget_close(self): def tray_menu(self, parent_menu): # Menu for Tray App from qtpy import QtWidgets + menu = QtWidgets.QMenu("Clockify", parent_menu) menu.setProperty("submenu", "on") @@ -204,7 +193,9 @@ def tray_menu(self, parent_menu): parent_menu.addMenu(menu) def show_settings(self): - self.widget_settings.input_api_key.setText(self.clockapi.get_api_key()) + self.widget_settings.input_api_key.setText( + self.clockify_api.get_api_key() + ) self.widget_settings.show() def set_menu_visibility(self): @@ -218,72 +209,82 @@ def register_timers_manager(self, timer_manager_module): def timer_started(self, data): """Tell TimersManager that timer started.""" if self._timers_manager_module is not None: - self._timers_manager_module.timer_started(self._module.id, data) + self._timers_manager_module.timer_started(self.id, data) def timer_stopped(self): """Tell TimersManager that timer stopped.""" if self._timers_manager_module is not None: - self._timers_manager_module.timer_stopped(self._module.id) + self._timers_manager_module.timer_stopped(self.id) def stop_timer(self): """Called from TimersManager to stop timer.""" - self.clockapi.finish_time_entry() + self.clockify_api.finish_time_entry() - def start_timer(self, input_data): - """Called from TimersManager to start timer.""" - # If not api key is not entered then skip - if not self.clockapi.get_api_key(): - return - - actual_timer = self.clockapi.get_in_progress() - actual_timer_hierarchy = None - actual_project_id = None - if actual_timer is not None: - actual_timer_hierarchy = actual_timer.get("description") - actual_project_id = actual_timer.get("projectId") - - # Concatenate hierarchy and task to get description - desc_items = [val for val in input_data.get("hierarchy", [])] - desc_items.append(input_data["task_name"]) - description = "/".join(desc_items) - - # Check project existence - project_name = input_data["project_name"] - project_id = self.clockapi.get_project_id(project_name) + def _verify_project_exists(self, project_name): + project_id = self.clockify_api.get_project_id(project_name) if not project_id: - self.log.warning(( - "Project \"{}\" was not found in Clockify. Timer won't start." - ).format(project_name)) + self.log.warning( + 'Project "{}" was not found in Clockify. Timer won\'t start.' + ).format(project_name) if not self.MessageWidgetClass: return msg = ( - "Project \"{}\" is not" - " in Clockify Workspace \"{}\"." + 'Project "{}" is not' + ' in Clockify Workspace "{}".' "

    Please inform your Project Manager." - ).format(project_name, str(self.clockapi.workspace_name)) + ).format(project_name, str(self.clockify_api.workspace_name)) self.message_widget = self.MessageWidgetClass( msg, "Clockify - Info Message" ) self.message_widget.closed.connect(self.on_message_widget_close) self.message_widget.show() + return False + return project_id + def start_timer(self, input_data): + """Called from TimersManager to start timer.""" + # If not api key is not entered then skip + if not self.clockify_api.get_api_key(): return - if ( - actual_timer is not None and - description == actual_timer_hierarchy and - project_id == actual_project_id - ): + task_name = input_data.get("task_name") + + # Concatenate hierarchy and task to get description + description_items = list(input_data.get("hierarchy", [])) + description_items.append(task_name) + description = "/".join(description_items) + + # Check project existence + project_name = input_data.get("project_name") + project_id = self._verify_project_exists(project_name) + if not project_id: return + # Setup timer tags tag_ids = [] - task_tag_id = self.clockapi.get_tag_id(input_data["task_type"]) + tag_name = input_data.get("task_type") + if not tag_name: + # no task_type found in the input data + # if the timer is restarted by idle time (bug?) + asset_name = input_data["hierarchy"][-1] + asset_doc = get_asset_by_name(project_name, asset_name) + task_info = asset_doc["data"]["tasks"][task_name] + tag_name = task_info.get("type", "") + if not tag_name: + self.log.info("No tag information found for the timer") + + task_tag_id = self.clockify_api.get_tag_id(tag_name) if task_tag_id is not None: tag_ids.append(task_tag_id) - self.clockapi.start_time_entry( - description, project_id, tag_ids=tag_ids + # Start timer + self.clockify_api.start_time_entry( + description, + project_id, + tag_ids=tag_ids, + workspace_id=self.clockify_api.workspace_id, + user_id=self.clockify_api.user_id, ) diff --git a/openpype/modules/clockify/constants.py b/openpype/modules/clockify/constants.py index 66f6cb899a5..4574f91be1d 100644 --- a/openpype/modules/clockify/constants.py +++ b/openpype/modules/clockify/constants.py @@ -9,4 +9,4 @@ ) ADMIN_PERMISSION_NAMES = ["WORKSPACE_OWN", "WORKSPACE_ADMIN"] -CLOCKIFY_ENDPOINT = "https://api.clockify.me/api/" +CLOCKIFY_ENDPOINT = "https://api.clockify.me/api/v1/" diff --git a/openpype/modules/clockify/ftrack/server/action_clockify_sync_server.py b/openpype/modules/clockify/ftrack/server/action_clockify_sync_server.py index c6b55947da6..985cf49b972 100644 --- a/openpype/modules/clockify/ftrack/server/action_clockify_sync_server.py +++ b/openpype/modules/clockify/ftrack/server/action_clockify_sync_server.py @@ -4,7 +4,7 @@ from openpype_modules.clockify.clockify_api import ClockifyAPI -class SyncClocifyServer(ServerAction): +class SyncClockifyServer(ServerAction): '''Synchronise project names and task types.''' identifier = "clockify.sync.server" @@ -14,12 +14,12 @@ class SyncClocifyServer(ServerAction): role_list = ["Pypeclub", "Administrator", "project Manager"] def __init__(self, *args, **kwargs): - super(SyncClocifyServer, self).__init__(*args, **kwargs) + super(SyncClockifyServer, self).__init__(*args, **kwargs) workspace_name = os.environ.get("CLOCKIFY_WORKSPACE") api_key = os.environ.get("CLOCKIFY_API_KEY") - self.clockapi = ClockifyAPI(api_key) - self.clockapi.set_workspace(workspace_name) + self.clockify_api = ClockifyAPI(api_key) + self.clockify_api.set_workspace(workspace_name) if api_key is None: modified_key = "None" else: @@ -48,13 +48,16 @@ def discover(self, session, entities, event): return True def launch(self, session, entities, event): - if self.clockapi.workspace_id is None: + self.clockify_api.set_api() + if self.clockify_api.workspace_id is None: return { "success": False, "message": "Clockify Workspace or API key are not set!" } - if self.clockapi.validate_workspace_perm() is False: + if not self.clockify_api.validate_workspace_permissions( + self.clockify_api.workspace_id, self.clockify_api.user_id + ): return { "success": False, "message": "Missing permissions for this action!" @@ -88,9 +91,9 @@ def launch(self, session, entities, event): task_type["name"] for task_type in task_types ] try: - clockify_projects = self.clockapi.get_projects() + clockify_projects = self.clockify_api.get_projects() if project_name not in clockify_projects: - response = self.clockapi.add_project(project_name) + response = self.clockify_api.add_project(project_name) if "id" not in response: self.log.warning( "Project \"{}\" can't be created. Response: {}".format( @@ -105,7 +108,7 @@ def launch(self, session, entities, event): ).format(project_name) } - clockify_workspace_tags = self.clockapi.get_tags() + clockify_workspace_tags = self.clockify_api.get_tags() for task_type_name in task_type_names: if task_type_name in clockify_workspace_tags: self.log.debug( @@ -113,7 +116,7 @@ def launch(self, session, entities, event): ) continue - response = self.clockapi.add_tag(task_type_name) + response = self.clockify_api.add_tag(task_type_name) if "id" not in response: self.log.warning( "Task \"{}\" can't be created. Response: {}".format( @@ -138,4 +141,4 @@ def launch(self, session, entities, event): def register(session, **kw): - SyncClocifyServer(session).register() + SyncClockifyServer(session).register() diff --git a/openpype/modules/clockify/ftrack/user/action_clockify_sync_local.py b/openpype/modules/clockify/ftrack/user/action_clockify_sync_local.py index a430791906c..0e8cf6bd374 100644 --- a/openpype/modules/clockify/ftrack/user/action_clockify_sync_local.py +++ b/openpype/modules/clockify/ftrack/user/action_clockify_sync_local.py @@ -3,7 +3,7 @@ from openpype_modules.clockify.clockify_api import ClockifyAPI -class SyncClocifyLocal(BaseAction): +class SyncClockifyLocal(BaseAction): '''Synchronise project names and task types.''' #: Action identifier. @@ -18,9 +18,9 @@ class SyncClocifyLocal(BaseAction): icon = statics_icon("app_icons", "clockify-white.png") def __init__(self, *args, **kwargs): - super(SyncClocifyLocal, self).__init__(*args, **kwargs) + super(SyncClockifyLocal, self).__init__(*args, **kwargs) #: CLockifyApi - self.clockapi = ClockifyAPI() + self.clockify_api = ClockifyAPI() def discover(self, session, entities, event): if ( @@ -31,14 +31,18 @@ def discover(self, session, entities, event): return False def launch(self, session, entities, event): - self.clockapi.set_api() - if self.clockapi.workspace_id is None: + self.clockify_api.set_api() + if self.clockify_api.workspace_id is None: return { "success": False, "message": "Clockify Workspace or API key are not set!" } - if self.clockapi.validate_workspace_perm() is False: + if ( + self.clockify_api.validate_workspace_permissions( + self.clockify_api.workspace_id, self.clockify_api.user_id) + is False + ): return { "success": False, "message": "Missing permissions for this action!" @@ -74,9 +78,9 @@ def launch(self, session, entities, event): task_type["name"] for task_type in task_types ] try: - clockify_projects = self.clockapi.get_projects() + clockify_projects = self.clockify_api.get_projects() if project_name not in clockify_projects: - response = self.clockapi.add_project(project_name) + response = self.clockify_api.add_project(project_name) if "id" not in response: self.log.warning( "Project \"{}\" can't be created. Response: {}".format( @@ -91,7 +95,7 @@ def launch(self, session, entities, event): ).format(project_name) } - clockify_workspace_tags = self.clockapi.get_tags() + clockify_workspace_tags = self.clockify_api.get_tags() for task_type_name in task_type_names: if task_type_name in clockify_workspace_tags: self.log.debug( @@ -99,7 +103,7 @@ def launch(self, session, entities, event): ) continue - response = self.clockapi.add_tag(task_type_name) + response = self.clockify_api.add_tag(task_type_name) if "id" not in response: self.log.warning( "Task \"{}\" can't be created. Response: {}".format( @@ -121,4 +125,4 @@ def launch(self, session, entities, event): def register(session, **kw): - SyncClocifyLocal(session).register() + SyncClockifyLocal(session).register() diff --git a/openpype/modules/clockify/launcher_actions/ClockifyStart.py b/openpype/modules/clockify/launcher_actions/ClockifyStart.py index 7663aecc316..4a653c1b8db 100644 --- a/openpype/modules/clockify/launcher_actions/ClockifyStart.py +++ b/openpype/modules/clockify/launcher_actions/ClockifyStart.py @@ -6,9 +6,9 @@ class ClockifyStart(LauncherAction): name = "clockify_start_timer" label = "Clockify - Start Timer" - icon = "clockify_icon" + icon = "app_icons/clockify.png" order = 500 - clockapi = ClockifyAPI() + clockify_api = ClockifyAPI() def is_compatible(self, session): """Return whether the action is compatible with the session""" @@ -17,23 +17,39 @@ def is_compatible(self, session): return False def process(self, session, **kwargs): + self.clockify_api.set_api() + user_id = self.clockify_api.user_id + workspace_id = self.clockify_api.workspace_id project_name = session["AVALON_PROJECT"] asset_name = session["AVALON_ASSET"] task_name = session["AVALON_TASK"] - description = asset_name - asset_doc = get_asset_by_name( - project_name, asset_name, fields=["data.parents"] - ) - if asset_doc is not None: - desc_items = asset_doc.get("data", {}).get("parents", []) - desc_items.append(asset_name) - desc_items.append(task_name) - description = "/".join(desc_items) - project_id = self.clockapi.get_project_id(project_name) + # fetch asset docs + asset_doc = get_asset_by_name(project_name, asset_name) + + # get task type to fill the timer tag + task_info = asset_doc["data"]["tasks"][task_name] + task_type = task_info["type"] + + # check if the task has hierarchy and fill the + parents_data = asset_doc["data"] + if parents_data is not None: + description_items = parents_data.get("parents", []) + description_items.append(asset_name) + description_items.append(task_name) + description = "/".join(description_items) + + project_id = self.clockify_api.get_project_id( + project_name, workspace_id + ) tag_ids = [] - tag_ids.append(self.clockapi.get_tag_id(task_name)) - self.clockapi.start_time_entry( - description, project_id, tag_ids=tag_ids + tag_name = task_type + tag_ids.append(self.clockify_api.get_tag_id(tag_name, workspace_id)) + self.clockify_api.start_time_entry( + description, + project_id, + tag_ids=tag_ids, + workspace_id=workspace_id, + user_id=user_id, ) diff --git a/openpype/modules/clockify/launcher_actions/ClockifySync.py b/openpype/modules/clockify/launcher_actions/ClockifySync.py index c346a1b4f62..cbd2519a04e 100644 --- a/openpype/modules/clockify/launcher_actions/ClockifySync.py +++ b/openpype/modules/clockify/launcher_actions/ClockifySync.py @@ -3,20 +3,39 @@ from openpype.pipeline import LauncherAction -class ClockifySync(LauncherAction): +class ClockifyPermissionsCheckFailed(Exception): + """Timer start failed due to user permissions check. + Message should be self explanatory as traceback won't be shown. + """ + + pass + +class ClockifySync(LauncherAction): name = "sync_to_clockify" label = "Sync to Clockify" - icon = "clockify_white_icon" + icon = "app_icons/clockify-white.png" order = 500 - clockapi = ClockifyAPI() - have_permissions = clockapi.validate_workspace_perm() + clockify_api = ClockifyAPI() def is_compatible(self, session): - """Return whether the action is compatible with the session""" - return self.have_permissions + """Check if there's some projects to sync""" + try: + next(get_projects()) + return True + except StopIteration: + return False def process(self, session, **kwargs): + self.clockify_api.set_api() + workspace_id = self.clockify_api.workspace_id + user_id = self.clockify_api.user_id + if not self.clockify_api.validate_workspace_permissions( + workspace_id, user_id + ): + raise ClockifyPermissionsCheckFailed( + "Current CLockify user is missing permissions for this action!" + ) project_name = session.get("AVALON_PROJECT") or "" projects_to_sync = [] @@ -30,24 +49,28 @@ def process(self, session, **kwargs): task_types = project["config"]["tasks"].keys() projects_info[project["name"]] = task_types - clockify_projects = self.clockapi.get_projects() + clockify_projects = self.clockify_api.get_projects(workspace_id) for project_name, task_types in projects_info.items(): if project_name in clockify_projects: continue - response = self.clockapi.add_project(project_name) + response = self.clockify_api.add_project( + project_name, workspace_id + ) if "id" not in response: - self.log.error("Project {} can't be created".format( - project_name - )) + self.log.error( + "Project {} can't be created".format(project_name) + ) continue - clockify_workspace_tags = self.clockapi.get_tags() + clockify_workspace_tags = self.clockify_api.get_tags(workspace_id) for task_type in task_types: if task_type not in clockify_workspace_tags: - response = self.clockapi.add_tag(task_type) + response = self.clockify_api.add_tag( + task_type, workspace_id + ) if "id" not in response: - self.log.error('Task {} can\'t be created'.format( - task_type - )) + self.log.error( + "Task {} can't be created".format(task_type) + ) continue diff --git a/openpype/modules/clockify/widgets.py b/openpype/modules/clockify/widgets.py index 122b6212c0e..8c28f38b6ef 100644 --- a/openpype/modules/clockify/widgets.py +++ b/openpype/modules/clockify/widgets.py @@ -77,15 +77,15 @@ def close(self, *args, **kwargs): class ClockifySettings(QtWidgets.QWidget): - SIZE_W = 300 + SIZE_W = 500 SIZE_H = 130 loginSignal = QtCore.Signal(object, object, object) - def __init__(self, clockapi, optional=True): + def __init__(self, clockify_api, optional=True): super(ClockifySettings, self).__init__() - self.clockapi = clockapi + self.clockify_api = clockify_api self.optional = optional self.validated = False @@ -162,17 +162,17 @@ def invalid_input(self, entity): def click_ok(self): api_key = self.input_api_key.text().strip() if self.optional is True and api_key == '': - self.clockapi.save_api_key(None) - self.clockapi.set_api(api_key) + self.clockify_api.save_api_key(None) + self.clockify_api.set_api(api_key) self.validated = False self._close_widget() return - validation = self.clockapi.validate_api_key(api_key) + validation = self.clockify_api.validate_api_key(api_key) if validation: - self.clockapi.save_api_key(api_key) - self.clockapi.set_api(api_key) + self.clockify_api.save_api_key(api_key) + self.clockify_api.set_api(api_key) self.validated = True self._close_widget() else: diff --git a/openpype/modules/deadline/plugins/publish/collect_pools.py b/openpype/modules/deadline/plugins/publish/collect_pools.py index 48130848d51..e221eb00ea6 100644 --- a/openpype/modules/deadline/plugins/publish/collect_pools.py +++ b/openpype/modules/deadline/plugins/publish/collect_pools.py @@ -3,21 +3,60 @@ """ import pyblish.api +from openpype.lib import TextDef +from openpype.pipeline.publish import OpenPypePyblishPluginMixin -class CollectDeadlinePools(pyblish.api.InstancePlugin): +class CollectDeadlinePools(pyblish.api.InstancePlugin, + OpenPypePyblishPluginMixin): """Collect pools from instance if present, from Setting otherwise.""" order = pyblish.api.CollectorOrder + 0.420 label = "Collect Deadline Pools" - families = ["rendering", "render.farm", "renderFarm", "renderlayer"] + families = ["rendering", + "render.farm", + "renderFarm", + "renderlayer", + "maxrender"] primary_pool = None secondary_pool = None + @classmethod + def apply_settings(cls, project_settings, system_settings): + # deadline.publish.CollectDeadlinePools + settings = project_settings["deadline"]["publish"]["CollectDeadlinePools"] # noqa + cls.primary_pool = settings.get("primary_pool", None) + cls.secondary_pool = settings.get("secondary_pool", None) + def process(self, instance): + + attr_values = self.get_attr_values_from_data(instance.data) if not instance.data.get("primaryPool"): - instance.data["primaryPool"] = self.primary_pool or "none" + instance.data["primaryPool"] = ( + attr_values.get("primaryPool") or self.primary_pool or "none" + ) if not instance.data.get("secondaryPool"): - instance.data["secondaryPool"] = self.secondary_pool or "none" + instance.data["secondaryPool"] = ( + attr_values.get("secondaryPool") or self.secondary_pool or "none" # noqa + ) + + @classmethod + def get_attribute_defs(cls): + # TODO: Preferably this would be an enum for the user + # but the Deadline server URL can be dynamic and + # can be set per render instance. Since get_attribute_defs + # can't be dynamic unfortunately EnumDef isn't possible (yet?) + # pool_names = self.deadline_module.get_deadline_pools(deadline_url, + # self.log) + # secondary_pool_names = ["-"] + pool_names + + return [ + TextDef("primaryPool", + label="Primary Pool", + default=cls.primary_pool), + TextDef("secondaryPool", + label="Secondary Pool", + default=cls.secondary_pool) + ] diff --git a/openpype/modules/deadline/plugins/publish/submit_celaction_deadline.py b/openpype/modules/deadline/plugins/publish/submit_celaction_deadline.py index 038ee4fc034..bcf08507687 100644 --- a/openpype/modules/deadline/plugins/publish/submit_celaction_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_celaction_deadline.py @@ -106,7 +106,7 @@ def payload_submit(self, # define chunk and priority chunk_size = instance.context.data.get("chunk") - if chunk_size == 0: + if not chunk_size: chunk_size = self.deadline_chunk_size # search for %02d pattern in name, and padding number diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index 417a03de744..c728b6b9c72 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -3,7 +3,15 @@ import copy import attr -from openpype.pipeline import legacy_io +from openpype.lib import ( + TextDef, + BoolDef, + NumberDef, +) +from openpype.pipeline import ( + legacy_io, + OpenPypePyblishPluginMixin +) from openpype.settings import get_project_settings from openpype.hosts.max.api.lib import ( get_current_renderer, @@ -22,7 +30,8 @@ class MaxPluginInfo(object): IgnoreInputs = attr.ib(default=True) -class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline): +class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, + OpenPypePyblishPluginMixin): label = "Submit Render to Deadline" hosts = ["max"] @@ -31,14 +40,22 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline): use_published = True priority = 50 - tile_priority = 50 chunk_size = 1 jobInfo = {} pluginInfo = {} group = None - deadline_pool = None - deadline_pool_secondary = None - framePerTask = 1 + + @classmethod + def apply_settings(cls, project_settings, system_settings): + settings = project_settings["deadline"]["publish"]["MaxSubmitDeadline"] # noqa + + # Take some defaults from settings + cls.use_published = settings.get("use_published", + cls.use_published) + cls.priority = settings.get("priority", + cls.priority) + cls.chuck_size = settings.get("chunk_size", cls.chunk_size) + cls.group = settings.get("group", cls.group) def get_job_info(self): job_info = DeadlineJobInfo(Plugin="3dsmax") @@ -49,11 +66,11 @@ def get_job_info(self): instance = self._instance context = instance.context - # Always use the original work file name for the Job name even when # rendering is done from the published Work File. The original work # file name is clearer because it can also have subversion strings, # etc. which are stripped for the published file. + src_filepath = context.data["currentFile"] src_filename = os.path.basename(src_filepath) @@ -71,13 +88,13 @@ def get_job_info(self): job_info.Pool = instance.data.get("primaryPool") job_info.SecondaryPool = instance.data.get("secondaryPool") - job_info.ChunkSize = instance.data.get("chunkSize", 1) - job_info.Comment = context.data.get("comment") - job_info.Priority = instance.data.get("priority", self.priority) - job_info.FramesPerTask = instance.data.get("framesPerTask", 1) - if self.group: - job_info.Group = self.group + attr_values = self.get_attr_values_from_data(instance.data) + + job_info.ChunkSize = attr_values.get("chunkSize", 1) + job_info.Comment = context.data.get("comment") + job_info.Priority = attr_values.get("priority", self.priority) + job_info.Group = attr_values.get("group", self.group) # Add options from RenderGlobals render_globals = instance.data.get("renderGlobals", {}) @@ -216,3 +233,32 @@ def _clean_name(path): plugin_info.update(plugin_data) return job_info, plugin_info + + @classmethod + def get_attribute_defs(cls): + defs = super(MaxSubmitDeadline, cls).get_attribute_defs() + defs.extend([ + BoolDef("use_published", + default=cls.use_published, + label="Use Published Scene"), + + NumberDef("priority", + minimum=1, + maximum=250, + decimals=0, + default=cls.priority, + label="Priority"), + + NumberDef("chunkSize", + minimum=1, + maximum=50, + decimals=0, + default=cls.chunk_size, + label="Frame Per Task"), + + TextDef("group", + default=cls.group, + label="Group Name"), + ]) + + return defs diff --git a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py index 15025e47f20..062732c059e 100644 --- a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py @@ -422,6 +422,7 @@ def _tile_render(self, payload): assembly_job_info.Priority = instance.data.get( "tile_priority", self.tile_priority ) + assembly_job_info.TileJob = False pool = instance.context.data["project_settings"]["deadline"] pool = pool["publish"]["ProcessSubmittedJobOnFarm"]["deadline_pool"] @@ -450,15 +451,14 @@ def _tile_render(self, payload): frame_assembly_job_info.ExtraInfo[0] = file_hash frame_assembly_job_info.ExtraInfo[1] = file frame_assembly_job_info.JobDependencies = tile_job_id + frame_assembly_job_info.Frames = frame # write assembly job config files - now = datetime.now() - config_file = os.path.join( output_dir, "{}_config_{}.txt".format( os.path.splitext(file)[0], - now.strftime("%Y_%m_%d_%H_%M_%S") + datetime.now().strftime("%Y_%m_%d_%H_%M_%S") ) ) try: @@ -469,6 +469,8 @@ def _tile_render(self, payload): self.log.warning("Path is unreachable: " "`{}`".format(output_dir)) + assembly_plugin_info["ConfigFile"] = config_file + with open(config_file, "w") as cf: print("TileCount={}".format(tiles_count), file=cf) print("ImageFileName={}".format(file), file=cf) @@ -477,25 +479,30 @@ def _tile_render(self, payload): print("ImageHeight={}".format( instance.data.get("resolutionHeight")), file=cf) + with open(config_file, "a") as cf: + # Need to reverse the order of the y tiles, because image + # coordinates are calculated from bottom left corner. tiles = _format_tiles( file, 0, instance.data.get("tilesX"), instance.data.get("tilesY"), instance.data.get("resolutionWidth"), instance.data.get("resolutionHeight"), - payload_plugin_info["OutputFilePrefix"] + payload_plugin_info["OutputFilePrefix"], + reversed_y=True )[1] for k, v in sorted(tiles.items()): print("{}={}".format(k, v), file=cf) - payload = self.assemble_payload( - job_info=frame_assembly_job_info, - plugin_info=assembly_plugin_info.copy(), - # todo: aux file transfers don't work with deadline webservice - # add config file as job auxFile - # aux_files=[config_file] + assembly_payloads.append( + self.assemble_payload( + job_info=frame_assembly_job_info, + plugin_info=assembly_plugin_info.copy(), + # This would fail if the client machine and webserice are + # using different storage paths. + aux_files=[config_file] + ) ) - assembly_payloads.append(payload) # Submit assembly jobs assembly_job_ids = [] @@ -505,6 +512,7 @@ def _tile_render(self, payload): "submitting assembly job {} of {}".format(i + 1, num_assemblies) ) + self.log.info(payload) assembly_job_id = self.submit(payload) assembly_job_ids.append(assembly_job_id) @@ -764,8 +772,15 @@ def _iter_expected_files(exp): def _format_tiles( - filename, index, tiles_x, tiles_y, - width, height, prefix): + filename, + index, + tiles_x, + tiles_y, + width, + height, + prefix, + reversed_y=False +): """Generate tile entries for Deadline tile job. Returns two dictionaries - one that can be directly used in Deadline @@ -802,6 +817,7 @@ def _format_tiles( width (int): Width resolution of final image. height (int): Height resolution of final image. prefix (str): Image prefix. + reversed_y (bool): Reverses the order of the y tiles. Returns: (dict, dict): Tuple of two dictionaries - first can be used to @@ -824,12 +840,16 @@ def _format_tiles( cfg["TilesCropped"] = "False" tile = 0 + range_y = range(1, tiles_y + 1) + reversed_y_range = list(reversed(range_y)) for tile_x in range(1, tiles_x + 1): - for tile_y in reversed(range(1, tiles_y + 1)): + for i, tile_y in enumerate(range_y): + tile_y_index = tile_y + if reversed_y: + tile_y_index = reversed_y_range[i] + tile_prefix = "_tile_{}x{}_{}x{}_".format( - tile_x, tile_y, - tiles_x, - tiles_y + tile_x, tile_y_index, tiles_x, tiles_y ) new_filename = "{}/{}{}".format( @@ -844,11 +864,14 @@ def _format_tiles( right = (tile_x * w_space) - 1 # Job info - out["JobInfo"]["OutputFilename{}Tile{}".format(index, tile)] = new_filename # noqa: E501 + key = "OutputFilename{}".format(index) + out["JobInfo"][key] = new_filename # Plugin Info - out["PluginInfo"]["RegionPrefix{}".format(str(tile))] = \ - "/{}".format(tile_prefix).join(prefix.rsplit("/", 1)) + key = "RegionPrefix{}".format(str(tile)) + out["PluginInfo"][key] = "/{}".format( + tile_prefix + ).join(prefix.rsplit("/", 1)) out["PluginInfo"]["RegionTop{}".format(tile)] = top out["PluginInfo"]["RegionBottom{}".format(tile)] = bottom out["PluginInfo"]["RegionLeft{}".format(tile)] = left diff --git a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py index aff34c7e4a8..cc069cf51a8 100644 --- a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py @@ -32,7 +32,7 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin, label = "Submit Nuke to Deadline" order = pyblish.api.IntegratorOrder + 0.1 hosts = ["nuke"] - families = ["render", "prerender.farm"] + families = ["render", "prerender"] optional = True targets = ["local"] @@ -80,6 +80,10 @@ def get_attribute_defs(cls): ] def process(self, instance): + if not instance.data.get("farm"): + self.log.info("Skipping local instance.") + return + instance.data["attributeValues"] = self.get_attr_values_from_data( instance.data) @@ -168,10 +172,10 @@ def process(self, instance): resp.json()["_id"]) # redefinition of families - if "render.farm" in families: + if "render" in instance.data["family"]: instance.data['family'] = 'write' families.insert(0, "render2d") - elif "prerender.farm" in families: + elif "prerender" in instance.data["family"]: instance.data['family'] = 'write' families.insert(0, "prerender") instance.data["families"] = families diff --git a/openpype/modules/deadline/plugins/publish/submit_publish_job.py b/openpype/modules/deadline/plugins/publish/submit_publish_job.py index 53c09ad22f9..0d0698c21f9 100644 --- a/openpype/modules/deadline/plugins/publish/submit_publish_job.py +++ b/openpype/modules/deadline/plugins/publish/submit_publish_job.py @@ -756,6 +756,10 @@ def process(self, instance): instance (pyblish.api.Instance): Instance data. """ + if not instance.data.get("farm"): + self.log.info("Skipping local instance.") + return + data = instance.data.copy() context = instance.context self.context = context diff --git a/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py b/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py index 78eed17c986..7c8ab62d4d8 100644 --- a/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py +++ b/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py @@ -17,10 +17,18 @@ class ValidateDeadlinePools(OptionalPyblishPluginMixin, label = "Validate Deadline Pools" order = pyblish.api.ValidatorOrder - families = ["rendering", "render.farm", "renderFarm", "renderlayer"] + families = ["rendering", + "render.farm", + "renderFarm", + "renderlayer", + "maxrender"] optional = True def process(self, instance): + if not instance.data.get("farm"): + self.log.info("Skipping local instance.") + return + # get default deadline webservice url from deadline module deadline_url = instance.context.data["defaultDeadline"] self.log.info("deadline_url::{}".format(deadline_url)) diff --git a/openpype/modules/deadline/plugins/publish/validate_expected_and_rendered_files.py b/openpype/modules/deadline/plugins/publish/validate_expected_and_rendered_files.py index f34f71d2137..ff4be677e74 100644 --- a/openpype/modules/deadline/plugins/publish/validate_expected_and_rendered_files.py +++ b/openpype/modules/deadline/plugins/publish/validate_expected_and_rendered_files.py @@ -68,8 +68,15 @@ def process(self, instance): # files to be in the folder that we might not want to use. missing = expected_files - existing_files if missing: - raise RuntimeError("Missing expected files: {}".format( - sorted(missing))) + raise RuntimeError( + "Missing expected files: {}\n" + "Expected files: {}\n" + "Existing files: {}".format( + sorted(missing), + sorted(expected_files), + sorted(existing_files) + ) + ) def _get_frame_list(self, original_job_id): """Returns list of frame ranges from all render job. diff --git a/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py b/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py index 20a58c91310..15226bb7733 100644 --- a/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py +++ b/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py @@ -362,11 +362,11 @@ def inject_openpype_environment(deadlinePlugin): args_str = subprocess.list2cmdline(args) print(">>> Executing: {} {}".format(exe, args_str)) - process = ProcessUtils.SpawnProcess( - exe, args_str, os.path.dirname(exe) + process_exitcode = deadlinePlugin.RunProcess( + exe, args_str, os.path.dirname(exe), -1 ) - ProcessUtils.WaitForExit(process, -1) - if process.ExitCode != 0: + + if process_exitcode != 0: raise RuntimeError( "Failed to run OpenPype process to extract environments." ) diff --git a/openpype/modules/deadline/repository/custom/plugins/OpenPypeTileAssembler/OpenPypeTileAssembler.py b/openpype/modules/deadline/repository/custom/plugins/OpenPypeTileAssembler/OpenPypeTileAssembler.py index 861f16518cf..b51daffbc8f 100644 --- a/openpype/modules/deadline/repository/custom/plugins/OpenPypeTileAssembler/OpenPypeTileAssembler.py +++ b/openpype/modules/deadline/repository/custom/plugins/OpenPypeTileAssembler/OpenPypeTileAssembler.py @@ -16,6 +16,10 @@ FileUtils, RepositoryUtils, SystemUtils) +version_major = 1 +version_minor = 0 +version_patch = 0 +version_string = "{}.{}.{}".format(version_major, version_minor, version_patch) STRING_TAGS = { "format" } @@ -264,6 +268,7 @@ def cleanup(self): def initialize_process(self): """Initialization.""" + self.LogInfo("Plugin version: {}".format(version_string)) self.SingleFramesOnly = True self.StdoutHandling = True self.renderer = self.GetPluginInfoEntryWithDefault( @@ -320,12 +325,7 @@ def render_argument(self): output_file = data["ImageFileName"] output_file = RepositoryUtils.CheckPathMapping(output_file) output_file = self.process_path(output_file) - """ - _, ext = os.path.splitext(output_file) - if "exr" not in ext: - self.FailRender( - "[{}] Only EXR format is supported for now.".format(ext)) - """ + tile_info = [] for tile in range(int(data["TileCount"])): tile_info.append({ @@ -336,11 +336,6 @@ def render_argument(self): "width": int(data["Tile{}Width".format(tile)]) }) - # FFMpeg doesn't support tile coordinates at the moment. - # arguments = self.tile_completer_ffmpeg_args( - # int(data["ImageWidth"]), int(data["ImageHeight"]), - # tile_info, output_file) - arguments = self.tile_oiio_args( int(data["ImageWidth"]), int(data["ImageHeight"]), tile_info, output_file) @@ -362,20 +357,20 @@ def process_path(self, filepath): def pre_render_tasks(self): """Load config file and do remapping.""" self.LogInfo("OpenPype Tile Assembler starting...") - scene_filename = self.GetDataFilename() + config_file = self.GetPluginInfoEntry("ConfigFile") temp_scene_directory = self.CreateTempDirectory( "thread" + str(self.GetThreadNumber())) - temp_scene_filename = Path.GetFileName(scene_filename) + temp_scene_filename = Path.GetFileName(config_file) self.config_file = Path.Combine( temp_scene_directory, temp_scene_filename) if SystemUtils.IsRunningOnWindows(): RepositoryUtils.CheckPathMappingInFileAndReplaceSeparator( - scene_filename, self.config_file, "/", "\\") + config_file, self.config_file, "/", "\\") else: RepositoryUtils.CheckPathMappingInFileAndReplaceSeparator( - scene_filename, self.config_file, "\\", "/") + config_file, self.config_file, "\\", "/") os.chmod(self.config_file, os.stat(self.config_file).st_mode) def post_render_tasks(self): @@ -459,75 +454,3 @@ def tile_oiio_args( args.append(output_path) return args - - def tile_completer_ffmpeg_args( - self, output_width, output_height, tiles_info, output_path): - """Generate ffmpeg arguments for tile assembly. - - Expected inputs are tiled images. - - Args: - output_width (int): Width of output image. - output_height (int): Height of output image. - tiles_info (list): List of tile items, each item must be - dictionary with `filepath`, `pos_x` and `pos_y` keys - representing path to file and x, y coordinates on output - image where top-left point of tile item should start. - output_path (str): Path to file where should be output stored. - - Returns: - (list): ffmpeg arguments. - - """ - previous_name = "base" - ffmpeg_args = [] - filter_complex_strs = [] - - filter_complex_strs.append("nullsrc=size={}x{}[{}]".format( - output_width, output_height, previous_name - )) - - new_tiles_info = {} - for idx, tile_info in enumerate(tiles_info): - # Add input and store input index - filepath = tile_info["filepath"] - ffmpeg_args.append("-i \"{}\"".format(filepath.replace("\\", "/"))) - - # Prepare initial filter complex arguments - index_name = "input{}".format(idx) - filter_complex_strs.append( - "[{}]setpts=PTS-STARTPTS[{}]".format(idx, index_name) - ) - tile_info["index"] = idx - new_tiles_info[index_name] = tile_info - - # Set frames to 1 - ffmpeg_args.append("-frames 1") - - # Concatenation filter complex arguments - global_index = 1 - total_index = len(new_tiles_info) - for index_name, tile_info in new_tiles_info.items(): - item_str = ( - "[{previous_name}][{index_name}]overlay={pos_x}:{pos_y}" - ).format( - previous_name=previous_name, - index_name=index_name, - pos_x=tile_info["pos_x"], - pos_y=tile_info["pos_y"] - ) - new_previous = "tmp{}".format(global_index) - if global_index != total_index: - item_str += "[{}]".format(new_previous) - filter_complex_strs.append(item_str) - previous_name = new_previous - global_index += 1 - - joined_parts = ";".join(filter_complex_strs) - filter_complex_str = "-filter_complex \"{}\"".format(joined_parts) - - ffmpeg_args.append(filter_complex_str) - ffmpeg_args.append("-y") - ffmpeg_args.append("\"{}\"".format(output_path)) - - return ffmpeg_args diff --git a/openpype/modules/example_addons/example_addon/addon.py b/openpype/modules/example_addons/example_addon/addon.py index ead647b41d0..be1d3ff9205 100644 --- a/openpype/modules/example_addons/example_addon/addon.py +++ b/openpype/modules/example_addons/example_addon/addon.py @@ -44,7 +44,7 @@ def get_settings_root_path(self): class ExampleAddon(OpenPypeAddOn, IPluginPaths, ITrayAction): - """This Addon has defined it's settings and interface. + """This Addon has defined its settings and interface. This example has system settings with an enabled option. And use few other interfaces: diff --git a/openpype/modules/ftrack/event_handlers_server/action_push_frame_values_to_task.py b/openpype/modules/ftrack/event_handlers_server/action_push_frame_values_to_task.py index 1209375f821..a698195c59d 100644 --- a/openpype/modules/ftrack/event_handlers_server/action_push_frame_values_to_task.py +++ b/openpype/modules/ftrack/event_handlers_server/action_push_frame_values_to_task.py @@ -9,7 +9,7 @@ class PushHierValuesToNonHier(ServerAction): - """Action push hierarchical custom attribute values to non hierarchical. + """Action push hierarchical custom attribute values to non-hierarchical. Hierarchical value is also pushed to their task entities. @@ -119,17 +119,109 @@ def attrs_configurations(self, session, object_ids, interest_attributes): self.join_query_keys(object_ids) )).all() - output = {} + attrs_by_obj_id = collections.defaultdict(list) hiearchical = [] for attr in attrs: if attr["is_hierarchical"]: hiearchical.append(attr) continue obj_id = attr["object_type_id"] - if obj_id not in output: - output[obj_id] = [] - output[obj_id].append(attr) - return output, hiearchical + attrs_by_obj_id[obj_id].append(attr) + return attrs_by_obj_id, hiearchical + + def query_attr_value( + self, + session, + hier_attrs, + attrs_by_obj_id, + dst_object_type_ids, + task_entity_ids, + non_task_entity_ids, + parent_id_by_entity_id + ): + all_non_task_ids_with_parents = set() + for entity_id in non_task_entity_ids: + all_non_task_ids_with_parents.add(entity_id) + _entity_id = entity_id + while True: + parent_id = parent_id_by_entity_id.get(_entity_id) + if ( + parent_id is None + or parent_id in all_non_task_ids_with_parents + ): + break + all_non_task_ids_with_parents.add(parent_id) + _entity_id = parent_id + + all_entity_ids = ( + set(all_non_task_ids_with_parents) + | set(task_entity_ids) + ) + attr_ids = {attr["id"] for attr in hier_attrs} + for obj_id in dst_object_type_ids: + attrs = attrs_by_obj_id.get(obj_id) + if attrs is not None: + for attr in attrs: + attr_ids.add(attr["id"]) + + real_values_by_entity_id = { + entity_id: {} + for entity_id in all_entity_ids + } + + attr_values = query_custom_attributes( + session, attr_ids, all_entity_ids, True + ) + for item in attr_values: + entity_id = item["entity_id"] + attr_id = item["configuration_id"] + real_values_by_entity_id[entity_id][attr_id] = item["value"] + + # Fill hierarchical values + hier_attrs_key_by_id = { + hier_attr["id"]: hier_attr + for hier_attr in hier_attrs + } + hier_values_per_entity_id = {} + for entity_id in all_non_task_ids_with_parents: + real_values = real_values_by_entity_id[entity_id] + hier_values_per_entity_id[entity_id] = {} + for attr_id, attr in hier_attrs_key_by_id.items(): + key = attr["key"] + hier_values_per_entity_id[entity_id][key] = ( + real_values.get(attr_id) + ) + + output = {} + for entity_id in non_task_entity_ids: + output[entity_id] = {} + for attr in hier_attrs_key_by_id.values(): + key = attr["key"] + value = hier_values_per_entity_id[entity_id][key] + tried_ids = set() + if value is None: + tried_ids.add(entity_id) + _entity_id = entity_id + while value is None: + parent_id = parent_id_by_entity_id.get(_entity_id) + if not parent_id: + break + value = hier_values_per_entity_id[parent_id][key] + if value is not None: + break + _entity_id = parent_id + tried_ids.add(parent_id) + + if value is None: + value = attr["default"] + + if value is not None: + for ent_id in tried_ids: + hier_values_per_entity_id[ent_id][key] = value + + output[entity_id][key] = value + + return real_values_by_entity_id, output def propagate_values(self, session, event, selected_entities): ftrack_settings = self.get_ftrack_settings( @@ -156,29 +248,24 @@ def propagate_values(self, session, event, selected_entities): } task_object_type = object_types_by_low_name["task"] - destination_object_types = [task_object_type] + dst_object_type_ids = {task_object_type["id"]} for ent_type in interest_entity_types: obj_type = object_types_by_low_name.get(ent_type) - if obj_type and obj_type not in destination_object_types: - destination_object_types.append(obj_type) - - destination_object_type_ids = set( - obj_type["id"] - for obj_type in destination_object_types - ) + if obj_type: + dst_object_type_ids.add(obj_type["id"]) interest_attributes = action_settings["interest_attributes"] # Find custom attributes definitions attrs_by_obj_id, hier_attrs = self.attrs_configurations( - session, destination_object_type_ids, interest_attributes + session, dst_object_type_ids, interest_attributes ) # Filter destination object types if they have any object specific # custom attribute - for obj_id in tuple(destination_object_type_ids): + for obj_id in tuple(dst_object_type_ids): if obj_id not in attrs_by_obj_id: - destination_object_type_ids.remove(obj_id) + dst_object_type_ids.remove(obj_id) - if not destination_object_type_ids: + if not dst_object_type_ids: # TODO report that there are not matching custom attributes return { "success": True, @@ -192,14 +279,14 @@ def propagate_values(self, session, event, selected_entities): session, selected_ids, project_entity, - destination_object_type_ids + dst_object_type_ids ) self.log.debug("Preparing whole project hierarchy by ids.") entities_by_obj_id = { obj_id: [] - for obj_id in destination_object_type_ids + for obj_id in dst_object_type_ids } self.log.debug("Filtering Task entities.") @@ -223,10 +310,16 @@ def propagate_values(self, session, event, selected_entities): "message": "Nothing to do in your selection." } - self.log.debug("Getting Hierarchical custom attribute values parents.") - hier_values_by_entity_id = self.get_hier_values( + self.log.debug("Getting Custom attribute values.") + ( + real_values_by_entity_id, + hier_values_by_entity_id + ) = self.query_attr_value( session, hier_attrs, + attrs_by_obj_id, + dst_object_type_ids, + task_entity_ids, non_task_entity_ids, parent_id_by_entity_id ) @@ -237,7 +330,8 @@ def propagate_values(self, session, event, selected_entities): hier_attrs, task_entity_ids, hier_values_by_entity_id, - parent_id_by_entity_id + parent_id_by_entity_id, + real_values_by_entity_id ) self.log.debug("Setting values to entities themselves.") @@ -245,7 +339,8 @@ def propagate_values(self, session, event, selected_entities): session, entities_by_obj_id, attrs_by_obj_id, - hier_values_by_entity_id + hier_values_by_entity_id, + real_values_by_entity_id ) return True @@ -322,112 +417,64 @@ def all_hierarchy_entities( return parent_id_by_entity_id, filtered_entities - def get_hier_values( - self, - session, - hier_attrs, - focus_entity_ids, - parent_id_by_entity_id - ): - all_ids_with_parents = set() - for entity_id in focus_entity_ids: - all_ids_with_parents.add(entity_id) - _entity_id = entity_id - while True: - parent_id = parent_id_by_entity_id.get(_entity_id) - if ( - not parent_id - or parent_id in all_ids_with_parents - ): - break - all_ids_with_parents.add(parent_id) - _entity_id = parent_id - - hier_attr_ids = tuple(hier_attr["id"] for hier_attr in hier_attrs) - hier_attrs_key_by_id = { - hier_attr["id"]: hier_attr["key"] - for hier_attr in hier_attrs - } - - values_per_entity_id = {} - for entity_id in all_ids_with_parents: - values_per_entity_id[entity_id] = {} - for key in hier_attrs_key_by_id.values(): - values_per_entity_id[entity_id][key] = None - - values = query_custom_attributes( - session, hier_attr_ids, all_ids_with_parents, True - ) - for item in values: - entity_id = item["entity_id"] - key = hier_attrs_key_by_id[item["configuration_id"]] - - values_per_entity_id[entity_id][key] = item["value"] - - output = {} - for entity_id in focus_entity_ids: - output[entity_id] = {} - for key in hier_attrs_key_by_id.values(): - value = values_per_entity_id[entity_id][key] - tried_ids = set() - if value is None: - tried_ids.add(entity_id) - _entity_id = entity_id - while value is None: - parent_id = parent_id_by_entity_id.get(_entity_id) - if not parent_id: - break - value = values_per_entity_id[parent_id][key] - if value is not None: - break - _entity_id = parent_id - tried_ids.add(parent_id) - - if value is not None: - for ent_id in tried_ids: - values_per_entity_id[ent_id][key] = value - - output[entity_id][key] = value - return output - def set_task_attr_values( self, session, hier_attrs, task_entity_ids, hier_values_by_entity_id, - parent_id_by_entity_id + parent_id_by_entity_id, + real_values_by_entity_id ): hier_attr_id_by_key = { attr["key"]: attr["id"] for attr in hier_attrs } + filtered_task_ids = set() for task_id in task_entity_ids: - parent_id = parent_id_by_entity_id.get(task_id) or {} + parent_id = parent_id_by_entity_id.get(task_id) parent_values = hier_values_by_entity_id.get(parent_id) - if not parent_values: - continue + if parent_values: + filtered_task_ids.add(task_id) + + if not filtered_task_ids: + return + for task_id in filtered_task_ids: + parent_id = parent_id_by_entity_id[task_id] + parent_values = hier_values_by_entity_id[parent_id] hier_values_by_entity_id[task_id] = {} + real_task_attr_values = real_values_by_entity_id[task_id] for key, value in parent_values.items(): hier_values_by_entity_id[task_id][key] = value + if value is None: + continue + configuration_id = hier_attr_id_by_key[key] _entity_key = collections.OrderedDict([ ("configuration_id", configuration_id), ("entity_id", task_id) ]) - - session.recorded_operations.push( - ftrack_api.operation.UpdateEntityOperation( - "ContextCustomAttributeValue", + op = None + if configuration_id not in real_task_attr_values: + op = ftrack_api.operation.CreateEntityOperation( + "CustomAttributeValue", + _entity_key, + {"value": value} + ) + elif real_task_attr_values[configuration_id] != value: + op = ftrack_api.operation.UpdateEntityOperation( + "CustomAttributeValue", _entity_key, "value", - ftrack_api.symbol.NOT_SET, + real_task_attr_values[configuration_id], value ) - ) - if len(session.recorded_operations) > 100: - session.commit() + + if op is not None: + session.recorded_operations.push(op) + if len(session.recorded_operations) > 100: + session.commit() session.commit() @@ -436,39 +483,68 @@ def push_values_to_entities( session, entities_by_obj_id, attrs_by_obj_id, - hier_values_by_entity_id + hier_values_by_entity_id, + real_values_by_entity_id ): + """Push values from hierarchical custom attributes to non-hierarchical. + + Args: + session (ftrack_api.Sessison): Session which queried entities, + values and which is used for change propagation. + entities_by_obj_id (dict[str, list[str]]): TypedContext + ftrack entity ids where the attributes are propagated by their + object ids. + attrs_by_obj_id (dict[str, ftrack_api.Entity]): Objects of + 'CustomAttributeConfiguration' by their ids. + hier_values_by_entity_id (doc[str, dict[str, Any]]): Attribute + values by entity id and by their keys. + real_values_by_entity_id (doc[str, dict[str, Any]]): Real attribute + values of entities. + """ + for object_id, entity_ids in entities_by_obj_id.items(): attrs = attrs_by_obj_id.get(object_id) if not attrs or not entity_ids: continue - for attr in attrs: - for entity_id in entity_ids: - value = ( - hier_values_by_entity_id - .get(entity_id, {}) - .get(attr["key"]) - ) + for entity_id in entity_ids: + real_values = real_values_by_entity_id.get(entity_id) + hier_values = hier_values_by_entity_id.get(entity_id) + if hier_values is None: + continue + + for attr in attrs: + attr_id = attr["id"] + attr_key = attr["key"] + value = hier_values.get(attr_key) if value is None: continue _entity_key = collections.OrderedDict([ - ("configuration_id", attr["id"]), + ("configuration_id", attr_id), ("entity_id", entity_id) ]) - session.recorded_operations.push( - ftrack_api.operation.UpdateEntityOperation( - "ContextCustomAttributeValue", + op = None + if attr_id not in real_values: + op = ftrack_api.operation.CreateEntityOperation( + "CustomAttributeValue", + _entity_key, + {"value": value} + ) + elif real_values[attr_id] != value: + op = ftrack_api.operation.UpdateEntityOperation( + "CustomAttributeValue", _entity_key, "value", - ftrack_api.symbol.NOT_SET, + real_values[attr_id], value ) - ) - if len(session.recorded_operations) > 100: - session.commit() + + if op is not None: + session.recorded_operations.push(op) + if len(session.recorded_operations) > 100: + session.commit() session.commit() diff --git a/openpype/modules/ftrack/event_handlers_server/event_push_frame_values_to_task.py b/openpype/modules/ftrack/event_handlers_server/event_push_frame_values_to_task.py index dc76920a57c..0f10145c066 100644 --- a/openpype/modules/ftrack/event_handlers_server/event_push_frame_values_to_task.py +++ b/openpype/modules/ftrack/event_handlers_server/event_push_frame_values_to_task.py @@ -1,6 +1,6 @@ import collections -import datetime import copy +from typing import Any import ftrack_api from openpype_modules.ftrack.lib import ( @@ -9,13 +9,30 @@ ) -class PushFrameValuesToTaskEvent(BaseEvent): +class PushHierValuesToNonHierEvent(BaseEvent): + """Push value changes between hierarchical and non-hierarchical attributes. + + Changes of non-hierarchical attributes are pushed to hierarchical and back. + The attributes must have same definition of custom attribute. + + Handler does not handle changes of hierarchical parents. So if entity does + not have explicitly set value of hierarchical attribute and any parent + would change it the change would not be propagated. + + The handler also push the value to task entity on task creation + and movement. To push values between hierarchical & non-hierarchical + add 'Task' to entity types in settings. + + Todos: + Task attribute values push on create/move should be possible to + enabled by settings. + """ + # Ignore event handler by default cust_attrs_query = ( "select id, key, object_type_id, is_hierarchical, default" " from CustomAttributeConfiguration" - " where key in ({}) and" - " (object_type_id in ({}) or is_hierarchical is true)" + " where key in ({})" ) _cached_task_object_id = None @@ -26,35 +43,35 @@ class PushFrameValuesToTaskEvent(BaseEvent): settings_key = "sync_hier_entity_attributes" - def session_user_id(self, session): - if self._cached_user_id is None: - user = session.query( - "User where username is \"{}\"".format(session.api_user) - ).one() - self._cached_user_id = user["id"] - return self._cached_user_id + def filter_entities_info( + self, event: ftrack_api.event.base.Event + ) -> dict[str, list[dict[str, Any]]]: + """Basic entities filter info we care about. - def launch(self, session, event): - filtered_entities_info = self.filter_entities_info(event) - if not filtered_entities_info: - return + This filtering is first of many filters. This does not query anything + from ftrack nor use settings. - for project_id, entities_info in filtered_entities_info.items(): - self.process_by_project(session, event, project_id, entities_info) + Args: + event (ftrack_api.event.base.Event): Ftrack event with update + information. + + Returns: + dict[str, list[dict[str, Any]]]: Filtered entity changes by + project id. + """ - def filter_entities_info(self, event): # Filter if event contain relevant data entities_info = event["data"].get("entities") if not entities_info: return - entities_info_by_project_id = {} + entities_info_by_project_id = collections.defaultdict(list) for entity_info in entities_info: - # Care only about tasks - if entity_info.get("entityType") != "task": + # Ignore removed entities + if entity_info.get("action") == "remove": continue - # Care only about changes of status + # Care only about information with changes of entities changes = entity_info.get("changes") if not changes: continue @@ -69,367 +86,287 @@ def filter_entities_info(self, event): if project_id is None: continue - # Skip `Task` entity type if parent didn't change - if entity_info["entity_type"].lower() == "task": - if ( - "parent_id" not in changes - or changes["parent_id"]["new"] is None - ): - continue - - if project_id not in entities_info_by_project_id: - entities_info_by_project_id[project_id] = [] entities_info_by_project_id[project_id].append(entity_info) return entities_info_by_project_id - def process_by_project(self, session, event, project_id, entities_info): - project_name = self.get_project_name_from_event( + def _get_attrs_configurations(self, session, interest_attributes): + """Get custom attribute configurations by name. + + Args: + session (ftrack_api.Session): Ftrack sesson. + interest_attributes (list[str]): Names of custom attributes + that should be synchronized. + + Returns: + tuple[dict[str, list], list]: Attributes by object id and + hierarchical attributes. + """ + + attrs = session.query(self.cust_attrs_query.format( + self.join_query_keys(interest_attributes) + )).all() + + attrs_by_obj_id = collections.defaultdict(list) + hier_attrs = [] + for attr in attrs: + if attr["is_hierarchical"]: + hier_attrs.append(attr) + continue + obj_id = attr["object_type_id"] + attrs_by_obj_id[obj_id].append(attr) + return attrs_by_obj_id, hier_attrs + + def _get_handler_project_settings( + self, + session: ftrack_api.Session, + event: ftrack_api.event.base.Event, + project_id: str + ) -> tuple[set[str], set[str]]: + """Get handler settings based on the project. + + Args: + session (ftrack_api.Session): Ftrack session. + event (ftrack_api.event.base.Event): Ftrack event which triggered + the changes. + project_id (str): Project id where the current changes are handled. + + Returns: + tuple[set[str], set[str]]: Attribute names we care about and + entity types we care about. + """ + + project_name: str = self.get_project_name_from_event( session, event, project_id ) # Load settings - project_settings = self.get_project_settings_from_event( - event, project_name + project_settings: dict[str, Any] = ( + self.get_project_settings_from_event(event, project_name) ) # Load status mapping from presets - event_settings = ( + event_settings: dict[str, Any] = ( project_settings ["ftrack"] ["events"] - ["sync_hier_entity_attributes"] + [self.settings_key] ) # Skip if event is not enabled if not event_settings["enabled"]: self.log.debug("Project \"{}\" has disabled {}".format( project_name, self.__class__.__name__ )) - return + return set(), set() - interest_attributes = event_settings["interest_attributes"] + interest_attributes: list[str] = event_settings["interest_attributes"] if not interest_attributes: self.log.info(( "Project \"{}\" does not have filled 'interest_attributes'," " skipping." )) - return - interest_entity_types = event_settings["interest_entity_types"] + + interest_entity_types: list[str] = ( + event_settings["interest_entity_types"]) if not interest_entity_types: self.log.info(( "Project \"{}\" does not have filled 'interest_entity_types'," " skipping." )) - return - - interest_attributes = set(interest_attributes) - interest_entity_types = set(interest_entity_types) - # Separate value changes and task parent changes - _entities_info = [] - added_entities = [] - added_entity_ids = set() - task_parent_changes = [] - for entity_info in entities_info: - if entity_info["entity_type"].lower() == "task": - task_parent_changes.append(entity_info) - elif entity_info.get("action") == "add": - added_entities.append(entity_info) - added_entity_ids.add(entity_info["entityId"]) - else: - _entities_info.append(entity_info) - entities_info = _entities_info - - # Filter entities info with changes - interesting_data, changed_keys_by_object_id = self.filter_changes( - session, event, entities_info, interest_attributes - ) - self.interesting_data_for_added( - session, - added_entities, - interest_attributes, - interesting_data, - changed_keys_by_object_id - ) - if not interesting_data and not task_parent_changes: - return - - # Prepare object types - object_types = session.query("select id, name from ObjectType").all() - object_types_by_name = {} - for object_type in object_types: - name_low = object_type["name"].lower() - object_types_by_name[name_low] = object_type - - # NOTE it would be nice to check if `interesting_data` do not contain - # value changs of tasks that were created or moved - # - it is a complex way how to find out - if interesting_data: - self.process_attribute_changes( - session, - object_types_by_name, - interesting_data, - changed_keys_by_object_id, - interest_entity_types, - interest_attributes, - added_entity_ids - ) - - if task_parent_changes: - self.process_task_parent_change( - session, object_types_by_name, task_parent_changes, - interest_entity_types, interest_attributes - ) + # Unify possible issues from settings ('Asset Build' -> 'assetbuild') + interest_entity_types: set[str] = { + entity_type.replace(" ", "").lower() + for entity_type in interest_entity_types + } + return set(interest_attributes), interest_entity_types - def process_task_parent_change( + def _entities_filter_by_settings( self, - session, - object_types_by_name, - task_parent_changes, - interest_entity_types, - interest_attributes + entities_info: list[dict[str, Any]], + interest_attributes: set[str], + interest_entity_types: set[str] ): - """Push custom attribute values if task parent has changed. - - Parent is changed if task is created or if is moved under different - entity. We don't care about all task changes only about those that - have it's parent in interest types (from settings). + new_entities_info = [] + for entity_info in entities_info: + entity_type_low = entity_info["entity_type"].lower() - Tasks hierarchical value should be unset or set based on parents - real hierarchical value and non hierarchical custom attribute value - should be set to hierarchical value. - """ + changes = entity_info["changes"] + # SPECIAL CASE: Capture changes of task created/moved under + # interested entity type + if ( + entity_type_low == "task" + and "parent_id" in changes + ): + # Direct parent is always second item in 'parents' and 'Task' + # must have at least one parent + parent_info = entity_info["parents"][1] + parent_entity_type = ( + parent_info["entity_type"] + .replace(" ", "") + .lower() + ) + if parent_entity_type in interest_entity_types: + new_entities_info.append(entity_info) + continue - # Store task ids which were created or moved under parent with entity - # type defined in settings (interest_entity_types). - task_ids = set() - # Store parent ids of matching task ids - matching_parent_ids = set() - # Store all entity ids of all entities to be able query hierarchical - # values. - whole_hierarchy_ids = set() - # Store parent id of each entity id - parent_id_by_entity_id = {} - for entity_info in task_parent_changes: - # Ignore entities with less parents than 2 - # NOTE entity itself is also part of "parents" value - parents = entity_info.get("parents") or [] - if len(parents) < 2: + # Skip if entity type is not enabled for attr value sync + if entity_type_low not in interest_entity_types: continue - parent_info = parents[1] - # Check if parent has entity type we care about. - if parent_info["entity_type"] not in interest_entity_types: - continue + valid_attr_change = entity_info.get("action") == "add" + for attr_key in interest_attributes: + if valid_attr_change: + break - task_ids.add(entity_info["entityId"]) - matching_parent_ids.add(parent_info["entityId"]) + if attr_key not in changes: + continue - # Store whole hierarchi of task entity - prev_id = None - for item in parents: - item_id = item["entityId"] - whole_hierarchy_ids.add(item_id) + if changes[attr_key]["new"] is not None: + valid_attr_change = True - if prev_id is None: - prev_id = item_id - continue + if not valid_attr_change: + continue - parent_id_by_entity_id[prev_id] = item_id - if item["entityType"] == "show": - break - prev_id = item_id + new_entities_info.append(entity_info) - # Just skip if nothing is interesting for our settings - if not matching_parent_ids: - return + return new_entities_info - # Query object type ids of parent ids for custom attribute - # definitions query - entities = session.query( - "select object_type_id from TypedContext where id in ({})".format( - self.join_query_keys(matching_parent_ids) - ) - ) + def propagate_attribute_changes( + self, + session, + interest_attributes, + entities_info, + attrs_by_obj_id, + hier_attrs, + real_values_by_entity_id, + hier_values_by_entity_id, + ): + hier_attr_ids_by_key = { + attr["key"]: attr["id"] + for attr in hier_attrs + } + filtered_interest_attributes = { + attr_name + for attr_name in interest_attributes + if attr_name in hier_attr_ids_by_key + } + attrs_keys_by_obj_id = {} + for obj_id, attrs in attrs_by_obj_id.items(): + attrs_keys_by_obj_id[obj_id] = { + attr["key"]: attr["id"] + for attr in attrs + } - # Prepare task object id - task_object_id = object_types_by_name["task"]["id"] + op_changes = [] + for entity_info in entities_info: + entity_id = entity_info["entityId"] + obj_id = entity_info["objectTypeId"] + # Skip attributes sync if does not have object specific custom + # attribute + if obj_id not in attrs_keys_by_obj_id: + continue + attr_keys = attrs_keys_by_obj_id[obj_id] + real_values = real_values_by_entity_id[entity_id] + hier_values = hier_values_by_entity_id[entity_id] + + changes = copy.deepcopy(entity_info["changes"]) + obj_id_attr_keys = { + attr_key + for attr_key in filtered_interest_attributes + if attr_key in attr_keys + } + if not obj_id_attr_keys: + continue - # All object ids for which we're querying custom attribute definitions - object_type_ids = set() - object_type_ids.add(task_object_id) - for entity in entities: - object_type_ids.add(entity["object_type_id"]) + value_by_key = {} + is_new_entity = entity_info.get("action") == "add" + for attr_key in obj_id_attr_keys: + if ( + attr_key in changes + and changes[attr_key]["new"] is not None + ): + value_by_key[attr_key] = changes[attr_key]["new"] - attrs_by_obj_id, hier_attrs = self.attrs_configurations( - session, object_type_ids, interest_attributes - ) + if not is_new_entity: + continue - # Skip if all task attributes are not available - task_attrs = attrs_by_obj_id.get(task_object_id) - if not task_attrs: - return + hier_attr_id = hier_attr_ids_by_key[attr_key] + attr_id = attr_keys[attr_key] + if hier_attr_id in real_values or attr_id in real_values: + continue - # Skip attributes that is not in both hierarchical and nonhierarchical - # TODO be able to push values if hierarchical is available - for key in interest_attributes: - if key not in hier_attrs: - task_attrs.pop(key, None) + value_by_key[attr_key] = hier_values[hier_attr_id] - elif key not in task_attrs: - hier_attrs.pop(key) + for key, new_value in value_by_key.items(): + if new_value is None: + continue - # Skip if nothing remained - if not task_attrs: - return + hier_id = hier_attr_ids_by_key[key] + std_id = attr_keys[key] + real_hier_value = real_values.get(hier_id) + real_std_value = real_values.get(std_id) + hier_value = hier_values[hier_id] + # Get right type of value for conversion + # - values in event are strings + type_value = real_hier_value + if type_value is None: + type_value = real_std_value + if type_value is None: + type_value = hier_value + # Skip if current values are not set + if type_value is None: + continue - # Do some preparations for custom attribute values query - attr_key_by_id = {} - nonhier_id_by_key = {} - hier_attr_ids = [] - for key, attr_id in hier_attrs.items(): - attr_key_by_id[attr_id] = key - hier_attr_ids.append(attr_id) - - conf_ids = list(hier_attr_ids) - task_conf_ids = [] - for key, attr_id in task_attrs.items(): - attr_key_by_id[attr_id] = key - nonhier_id_by_key[key] = attr_id - conf_ids.append(attr_id) - task_conf_ids.append(attr_id) - - # Query custom attribute values - # - result does not contain values for all entities only result of - # query callback to ftrack server - result = query_custom_attributes( - session, list(hier_attr_ids), whole_hierarchy_ids, True - ) - result.extend( - query_custom_attributes( - session, task_conf_ids, whole_hierarchy_ids, False - ) - ) + try: + new_value = type(type_value)(new_value) + except Exception: + self.log.warning(( + "Couldn't convert from {} to {}." + " Skipping update values." + ).format(type(new_value), type(type_value))) + continue - # Prepare variables where result will be stored - # - hierachical values should not contain attribute with value by - # default - hier_values_by_entity_id = { - entity_id: {} - for entity_id in whole_hierarchy_ids - } - # - real values of custom attributes - values_by_entity_id = { - entity_id: { - attr_id: None - for attr_id in conf_ids - } - for entity_id in whole_hierarchy_ids - } - for item in result: - attr_id = item["configuration_id"] - entity_id = item["entity_id"] - value = item["value"] - - values_by_entity_id[entity_id][attr_id] = value - - if attr_id in hier_attr_ids and value is not None: - hier_values_by_entity_id[entity_id][attr_id] = value - - # Prepare values for all task entities - # - going through all parents and storing first value value - # - store None to those that are already known that do not have set - # value at all - for task_id in tuple(task_ids): - for attr_id in hier_attr_ids: - entity_ids = [] - value = None - entity_id = task_id - while value is None: - entity_value = hier_values_by_entity_id[entity_id] - if attr_id in entity_value: - value = entity_value[attr_id] - if value is None: - break - - if value is None: - entity_ids.append(entity_id) - - entity_id = parent_id_by_entity_id.get(entity_id) - if entity_id is None: - break - - for entity_id in entity_ids: - hier_values_by_entity_id[entity_id][attr_id] = value - - # Prepare changes to commit - changes = [] - for task_id in tuple(task_ids): - parent_id = parent_id_by_entity_id[task_id] - for attr_id in hier_attr_ids: - attr_key = attr_key_by_id[attr_id] - nonhier_id = nonhier_id_by_key[attr_key] - - # Real value of hierarchical attribute on parent - # - If is none then should be unset - real_parent_value = values_by_entity_id[parent_id][attr_id] - # Current hierarchical value of a task - # - Will be compared to real parent value - hier_value = hier_values_by_entity_id[task_id][attr_id] - - # Parent value that can be inherited from it's parent entity - parent_value = hier_values_by_entity_id[parent_id][attr_id] - # Task value of nonhierarchical custom attribute - nonhier_value = values_by_entity_id[task_id][nonhier_id] - - if real_parent_value != hier_value: - changes.append({ - "new_value": real_parent_value, - "attr_id": attr_id, - "entity_id": task_id, - "attr_key": attr_key - }) - - if parent_value != nonhier_value: - changes.append({ - "new_value": parent_value, - "attr_id": nonhier_id, - "entity_id": task_id, - "attr_key": attr_key - }) - - self._commit_changes(session, changes) - - def _commit_changes(self, session, changes): - uncommited_changes = False - for idx, item in enumerate(changes): - new_value = item["new_value"] - old_value = item["old_value"] - attr_id = item["attr_id"] - entity_id = item["entity_id"] - attr_key = item["attr_key"] + real_std_value_is_same = new_value == real_std_value + real_hier_value_is_same = new_value == real_hier_value + # New value does not match anything in current entity values + if ( + not is_new_entity + and not real_std_value_is_same + and not real_hier_value_is_same + ): + continue - entity_key = collections.OrderedDict(( + if not real_std_value_is_same: + op_changes.append(( + std_id, + entity_id, + new_value, + real_values.get(std_id), + std_id in real_values + )) + + if not real_hier_value_is_same: + op_changes.append(( + hier_id, + entity_id, + new_value, + real_values.get(hier_id), + hier_id in real_values + )) + + for change in op_changes: + ( + attr_id, + entity_id, + new_value, + old_value, + do_update + ) = change + + entity_key = collections.OrderedDict([ ("configuration_id", attr_id), ("entity_id", entity_id) - )) - self._cached_changes.append({ - "attr_key": attr_key, - "entity_id": entity_id, - "value": new_value, - "time": datetime.datetime.now() - }) - old_value_is_set = ( - old_value is not ftrack_api.symbol.NOT_SET - and old_value is not None - ) - if new_value is None: - if not old_value_is_set: - continue - op = ftrack_api.operation.DeleteEntityOperation( - "CustomAttributeValue", - entity_key - ) - - elif old_value_is_set: + ]) + if do_update: op = ftrack_api.operation.UpdateEntityOperation( "CustomAttributeValue", entity_key, @@ -446,449 +383,116 @@ def _commit_changes(self, session, changes): ) session.recorded_operations.push(op) - self.log.info(( - "Changing Custom Attribute \"{}\" to value" - " \"{}\" on entity: {}" - ).format(attr_key, new_value, entity_id)) - - if (idx + 1) % 20 == 0: - uncommited_changes = False - try: - session.commit() - except Exception: - session.rollback() - self.log.warning( - "Changing of values failed.", exc_info=True - ) - else: - uncommited_changes = True - if uncommited_changes: - try: + if len(session.recorded_operations) > 100: session.commit() - except Exception: - session.rollback() - self.log.warning("Changing of values failed.", exc_info=True) + session.commit() - def process_attribute_changes( + def process_by_project( self, - session, - object_types_by_name, - interesting_data, - changed_keys_by_object_id, - interest_entity_types, - interest_attributes, - added_entity_ids + session: ftrack_api.Session, + event: ftrack_api.event.base.Event, + project_id: str, + entities_info: list[dict[str, Any]] ): - # Prepare task object id - task_object_id = object_types_by_name["task"]["id"] - - # Collect object type ids based on settings - interest_object_ids = [] - for entity_type in interest_entity_types: - _entity_type = entity_type.lower() - object_type = object_types_by_name.get(_entity_type) - if not object_type: - self.log.warning("Couldn't find object type \"{}\"".format( - entity_type - )) - - interest_object_ids.append(object_type["id"]) - - # Query entities by filtered data and object ids - entities = self.get_entities( - session, interesting_data, interest_object_ids - ) - if not entities: - return - - # Pop not found entities from interesting data - entity_ids = set( - entity["id"] - for entity in entities - ) - for entity_id in tuple(interesting_data.keys()): - if entity_id not in entity_ids: - interesting_data.pop(entity_id) - - # Add task object type to list - attr_obj_ids = list(interest_object_ids) - attr_obj_ids.append(task_object_id) - - attrs_by_obj_id, hier_attrs = self.attrs_configurations( - session, attr_obj_ids, interest_attributes - ) - - task_attrs = attrs_by_obj_id.get(task_object_id) - - changed_keys = set() - # Skip keys that are not both in hierachical and type specific - for object_id, keys in changed_keys_by_object_id.items(): - changed_keys |= set(keys) - object_id_attrs = attrs_by_obj_id.get(object_id) - for key in keys: - if key not in hier_attrs: - attrs_by_obj_id[object_id].pop(key) - continue + """Proces changes in single project. + + Args: + session (ftrack_api.Session): Ftrack session. + event (ftrack_api.event.base.Event): Event which has all changes + information. + project_id (str): Project id related to changes. + entities_info (list[dict[str, Any]]): Changes of entities. + """ - if ( - (not object_id_attrs or key not in object_id_attrs) - and (not task_attrs or key not in task_attrs) - ): - hier_attrs.pop(key) - - # Clean up empty values - for key, value in tuple(attrs_by_obj_id.items()): - if not value: - attrs_by_obj_id.pop(key) - - if not attrs_by_obj_id: - self.log.warning(( - "There is not created Custom Attributes {} " - " for entity types: {}" - ).format( - self.join_query_keys(interest_attributes), - self.join_query_keys(interest_entity_types) - )) + ( + interest_attributes, + interest_entity_types + ) = self._get_handler_project_settings(session, event, project_id) + if not interest_attributes or not interest_entity_types: return - # Prepare task entities - task_entities = [] - # If task entity does not contain changed attribute then skip - if task_attrs: - task_entities = self.get_task_entities(session, interesting_data) - - task_entity_ids = set() - parent_id_by_task_id = {} - for task_entity in task_entities: - task_id = task_entity["id"] - task_entity_ids.add(task_id) - parent_id_by_task_id[task_id] = task_entity["parent_id"] - - self.finalize_attribute_changes( - session, - interesting_data, - changed_keys, - attrs_by_obj_id, - hier_attrs, - task_entity_ids, - parent_id_by_task_id, - added_entity_ids - ) - - def finalize_attribute_changes( - self, - session, - interesting_data, - changed_keys, - attrs_by_obj_id, - hier_attrs, - task_entity_ids, - parent_id_by_task_id, - added_entity_ids - ): - attr_id_to_key = {} - for attr_confs in attrs_by_obj_id.values(): - for key in changed_keys: - custom_attr_id = attr_confs.get(key) - if custom_attr_id: - attr_id_to_key[custom_attr_id] = key - - for key in changed_keys: - custom_attr_id = hier_attrs.get(key) - if custom_attr_id: - attr_id_to_key[custom_attr_id] = key - - entity_ids = ( - set(interesting_data.keys()) | task_entity_ids - ) - attr_ids = set(attr_id_to_key.keys()) - - current_values_by_id = self.get_current_values( - session, - attr_ids, - entity_ids, - task_entity_ids, - hier_attrs + entities_info: list[dict[str, Any]] = ( + self._entities_filter_by_settings( + entities_info, + interest_attributes, + interest_entity_types + ) ) - - changes = [] - for entity_id, current_values in current_values_by_id.items(): - parent_id = parent_id_by_task_id.get(entity_id) - if not parent_id: - parent_id = entity_id - values = interesting_data[parent_id] - - added_entity = entity_id in added_entity_ids - for attr_id, old_value in current_values.items(): - if added_entity and attr_id in hier_attrs: - continue - - attr_key = attr_id_to_key.get(attr_id) - if not attr_key: - continue - - # Convert new value from string - new_value = values.get(attr_key) - new_value_is_valid = ( - old_value is not ftrack_api.symbol.NOT_SET - and new_value is not None - ) - if added_entity and not new_value_is_valid: - continue - - if new_value is not None and new_value_is_valid: - try: - new_value = type(old_value)(new_value) - except Exception: - self.log.warning(( - "Couldn't convert from {} to {}." - " Skipping update values." - ).format(type(new_value), type(old_value))) - if new_value == old_value: - continue - - changes.append({ - "new_value": new_value, - "attr_id": attr_id, - "old_value": old_value, - "entity_id": entity_id, - "attr_key": attr_key - }) - self._commit_changes(session, changes) - - def filter_changes( - self, session, event, entities_info, interest_attributes - ): - session_user_id = self.session_user_id(session) - user_data = event["data"].get("user") - changed_by_session = False - if user_data and user_data.get("userid") == session_user_id: - changed_by_session = True - - current_time = datetime.datetime.now() - - interesting_data = {} - changed_keys_by_object_id = {} - - for entity_info in entities_info: - # Care only about changes if specific keys - entity_changes = {} - changes = entity_info["changes"] - for key in interest_attributes: - if key in changes: - entity_changes[key] = changes[key]["new"] - - entity_id = entity_info["entityId"] - if changed_by_session: - for key, new_value in tuple(entity_changes.items()): - for cached in tuple(self._cached_changes): - if ( - cached["entity_id"] != entity_id - or cached["attr_key"] != key - ): - continue - - cached_value = cached["value"] - try: - new_value = type(cached_value)(new_value) - except Exception: - pass - - if cached_value == new_value: - self._cached_changes.remove(cached) - entity_changes.pop(key) - break - - delta = (current_time - cached["time"]).seconds - if delta > self._max_delta: - self._cached_changes.remove(cached) - - if not entity_changes: - continue - - entity_id = entity_info["entityId"] - object_id = entity_info["objectTypeId"] - interesting_data[entity_id] = entity_changes - if object_id not in changed_keys_by_object_id: - changed_keys_by_object_id[object_id] = set() - changed_keys_by_object_id[object_id] |= set(entity_changes.keys()) - - return interesting_data, changed_keys_by_object_id - - def interesting_data_for_added( - self, - session, - added_entities, - interest_attributes, - interesting_data, - changed_keys_by_object_id - ): - if not added_entities or not interest_attributes: + if not entities_info: return - object_type_ids = set() - entity_ids = set() - all_entity_ids = set() - object_id_by_entity_id = {} - project_id = None - entity_ids_by_parent_id = collections.defaultdict(set) - for entity_info in added_entities: - object_id = entity_info["objectTypeId"] - entity_id = entity_info["entityId"] - object_type_ids.add(object_id) - entity_ids.add(entity_id) - object_id_by_entity_id[entity_id] = object_id - - for item in entity_info["parents"]: - entity_id = item["entityId"] - all_entity_ids.add(entity_id) - parent_id = item["parentId"] - if not parent_id: - project_id = entity_id - else: - entity_ids_by_parent_id[parent_id].add(entity_id) - - hier_attrs = self.get_hierarchical_configurations( + attrs_by_obj_id, hier_attrs = self._get_attrs_configurations( session, interest_attributes ) - if not hier_attrs: + # Skip if attributes are not available + # - there is nothing to sync + if not attrs_by_obj_id or not hier_attrs: return - hier_attrs_key_by_id = { - attr_conf["id"]: attr_conf["key"] - for attr_conf in hier_attrs - } - default_values_by_key = { - attr_conf["key"]: attr_conf["default"] - for attr_conf in hier_attrs - } - - values = query_custom_attributes( - session, list(hier_attrs_key_by_id.keys()), all_entity_ids, True + entity_ids_by_parent_id = collections.defaultdict(set) + all_entity_ids = set() + for entity_info in entities_info: + entity_id = None + for item in entity_info["parents"]: + item_id = item["entityId"] + all_entity_ids.add(item_id) + if entity_id is not None: + entity_ids_by_parent_id[item_id].add(entity_id) + entity_id = item_id + + attr_ids = {attr["id"] for attr in hier_attrs} + for attrs in attrs_by_obj_id.values(): + attr_ids |= {attr["id"] for attr in attrs} + + # Query real custom attribute values + # - we have to know what are the real values, if are set and to what + # value + value_items = query_custom_attributes( + session, attr_ids, all_entity_ids, True ) - values_per_entity_id = {} - for entity_id in all_entity_ids: - values_per_entity_id[entity_id] = {} - for attr_name in interest_attributes: - values_per_entity_id[entity_id][attr_name] = None - - for item in values: + real_values_by_entity_id = collections.defaultdict(dict) + for item in value_items: entity_id = item["entity_id"] - key = hier_attrs_key_by_id[item["configuration_id"]] - values_per_entity_id[entity_id][key] = item["value"] - - fill_queue = collections.deque() - fill_queue.append((project_id, default_values_by_key)) - while fill_queue: - item = fill_queue.popleft() - entity_id, values_by_key = item - entity_values = values_per_entity_id[entity_id] - new_values_by_key = copy.deepcopy(values_by_key) - for key, value in values_by_key.items(): - current_value = entity_values[key] - if current_value is None: - entity_values[key] = value - else: - new_values_by_key[key] = current_value - - for child_id in entity_ids_by_parent_id[entity_id]: - fill_queue.append((child_id, new_values_by_key)) - - for entity_id in entity_ids: - entity_changes = {} - for key, value in values_per_entity_id[entity_id].items(): - if value is not None: - entity_changes[key] = value - - if not entity_changes: - continue - - interesting_data[entity_id] = entity_changes - object_id = object_id_by_entity_id[entity_id] - if object_id not in changed_keys_by_object_id: - changed_keys_by_object_id[object_id] = set() - changed_keys_by_object_id[object_id] |= set(entity_changes.keys()) + attr_id = item["configuration_id"] + real_values_by_entity_id[entity_id][attr_id] = item["value"] - def get_current_values( - self, - session, - attr_ids, - entity_ids, - task_entity_ids, - hier_attrs - ): - current_values_by_id = {} - if not attr_ids or not entity_ids: - return current_values_by_id - - for entity_id in entity_ids: - current_values_by_id[entity_id] = {} - for attr_id in attr_ids: - current_values_by_id[entity_id][attr_id] = ( - ftrack_api.symbol.NOT_SET + hier_values_by_entity_id = {} + default_values = { + attr["id"]: attr["default"] + for attr in hier_attrs + } + hier_queue = collections.deque() + hier_queue.append((default_values, [project_id])) + while hier_queue: + parent_values, entity_ids = hier_queue.popleft() + for entity_id in entity_ids: + entity_values = copy.deepcopy(parent_values) + real_values = real_values_by_entity_id[entity_id] + for attr_id, value in real_values.items(): + entity_values[attr_id] = value + hier_values_by_entity_id[entity_id] = entity_values + hier_queue.append( + (entity_values, entity_ids_by_parent_id[entity_id]) ) - values = query_custom_attributes( - session, attr_ids, entity_ids, True + self.propagate_attribute_changes( + session, + interest_attributes, + entities_info, + attrs_by_obj_id, + hier_attrs, + real_values_by_entity_id, + hier_values_by_entity_id, ) - for item in values: - entity_id = item["entity_id"] - attr_id = item["configuration_id"] - if entity_id in task_entity_ids and attr_id in hier_attrs: - continue - - if entity_id not in current_values_by_id: - current_values_by_id[entity_id] = {} - current_values_by_id[entity_id][attr_id] = item["value"] - return current_values_by_id - - def get_entities(self, session, interesting_data, interest_object_ids): - return session.query(( - "select id from TypedContext" - " where id in ({}) and object_type_id in ({})" - ).format( - self.join_query_keys(interesting_data.keys()), - self.join_query_keys(interest_object_ids) - )).all() - - def get_task_entities(self, session, interesting_data): - return session.query( - "select id, parent_id from Task where parent_id in ({})".format( - self.join_query_keys(interesting_data.keys()) - ) - ).all() - - def attrs_configurations(self, session, object_ids, interest_attributes): - attrs = session.query(self.cust_attrs_query.format( - self.join_query_keys(interest_attributes), - self.join_query_keys(object_ids) - )).all() + def launch(self, session, event): + filtered_entities_info = self.filter_entities_info(event) + if not filtered_entities_info: + return - output = {} - hiearchical = {} - for attr in attrs: - if attr["is_hierarchical"]: - hiearchical[attr["key"]] = attr["id"] - continue - obj_id = attr["object_type_id"] - if obj_id not in output: - output[obj_id] = {} - output[obj_id][attr["key"]] = attr["id"] - return output, hiearchical - - def get_hierarchical_configurations(self, session, interest_attributes): - hier_attr_query = ( - "select id, key, object_type_id, is_hierarchical, default" - " from CustomAttributeConfiguration" - " where key in ({}) and is_hierarchical is true" - ) - if not interest_attributes: - return [] - return list(session.query(hier_attr_query.format( - self.join_query_keys(interest_attributes), - )).all()) + for project_id, entities_info in filtered_entities_info.items(): + self.process_by_project(session, event, project_id, entities_info) def register(session): - PushFrameValuesToTaskEvent(session).register() + PushHierValuesToNonHierEvent(session).register() diff --git a/openpype/modules/ftrack/event_handlers_user/action_applications.py b/openpype/modules/ftrack/event_handlers_user/action_applications.py index 102f04c9566..30399b463dd 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_applications.py +++ b/openpype/modules/ftrack/event_handlers_user/action_applications.py @@ -124,6 +124,11 @@ def discover(self, session, entities, event): if not avalon_project_apps: return False + settings = self.get_project_settings_from_event( + event, avalon_project_doc["name"]) + + only_available = settings["applications"]["only_available"] + items = [] for app_name in avalon_project_apps: app = self.application_manager.applications.get(app_name) @@ -133,6 +138,10 @@ def discover(self, session, entities, event): if app.group.name in CUSTOM_LAUNCH_APP_GROUPS: continue + # Skip applications without valid executables + if only_available and not app.find_executable(): + continue + app_icon = app.icon if app_icon and self.icon_url: try: diff --git a/openpype/modules/ftrack/plugins/publish/collect_ftrack_family.py b/openpype/modules/ftrack/plugins/publish/collect_ftrack_family.py index 576a7d36c4c..97815f490f4 100644 --- a/openpype/modules/ftrack/plugins/publish/collect_ftrack_family.py +++ b/openpype/modules/ftrack/plugins/publish/collect_ftrack_family.py @@ -7,23 +7,22 @@ """ import pyblish.api -from openpype.pipeline import legacy_io from openpype.lib import filter_profiles class CollectFtrackFamily(pyblish.api.InstancePlugin): - """ - Adds explicitly 'ftrack' to families to upload instance to FTrack. + """Adds explicitly 'ftrack' to families to upload instance to FTrack. - Uses selection by combination of hosts/families/tasks names via - profiles resolution. + Uses selection by combination of hosts/families/tasks names via + profiles resolution. - Triggered everywhere, checks instance against configured. + Triggered everywhere, checks instance against configured. - Checks advanced filtering which works on 'families' not on main - 'family', as some variants dynamically resolves addition of ftrack - based on 'families' (editorial drives it by presence of 'review') + Checks advanced filtering which works on 'families' not on main + 'family', as some variants dynamically resolves addition of ftrack + based on 'families' (editorial drives it by presence of 'review') """ + label = "Collect Ftrack Family" order = pyblish.api.CollectorOrder + 0.4990 @@ -34,68 +33,64 @@ def process(self, instance): self.log.warning("No profiles present for adding Ftrack family") return - add_ftrack_family = False - task_name = instance.data.get("task", - legacy_io.Session["AVALON_TASK"]) - host_name = legacy_io.Session["AVALON_APP"] + host_name = instance.context.data["hostName"] family = instance.data["family"] + task_name = instance.data.get("task") filtering_criteria = { "hosts": host_name, "families": family, "tasks": task_name } - profile = filter_profiles(self.profiles, filtering_criteria, - logger=self.log) + profile = filter_profiles( + self.profiles, + filtering_criteria, + logger=self.log + ) + + add_ftrack_family = False + families = instance.data.setdefault("families", []) if profile: - families = instance.data.get("families") add_ftrack_family = profile["add_ftrack_family"] - additional_filters = profile.get("advanced_filtering") if additional_filters: - self.log.info("'{}' families used for additional filtering". - format(families)) + families_set = set(families) | {family} + self.log.info( + "'{}' families used for additional filtering".format( + families_set)) add_ftrack_family = self._get_add_ftrack_f_from_addit_filters( additional_filters, - families, + families_set, add_ftrack_family ) - if add_ftrack_family: - self.log.debug("Adding ftrack family for '{}'". - format(instance.data.get("family"))) - - if families: - if "ftrack" not in families: - instance.data["families"].append("ftrack") - else: - instance.data["families"] = ["ftrack"] + result_str = "Not adding" + if add_ftrack_family: + result_str = "Adding" + if "ftrack" not in families: + families.append("ftrack") - result_str = "Adding" - if not add_ftrack_family: - result_str = "Not adding" self.log.info("{} 'ftrack' family for instance with '{}'".format( result_str, family )) - def _get_add_ftrack_f_from_addit_filters(self, - additional_filters, - families, - add_ftrack_family): - """ - Compares additional filters - working on instance's families. + def _get_add_ftrack_f_from_addit_filters( + self, additional_filters, families, add_ftrack_family + ): + """Compares additional filters - working on instance's families. - Triggered for more detailed filtering when main family matches, - but content of 'families' actually matter. - (For example 'review' in 'families' should result in adding to - Ftrack) + Triggered for more detailed filtering when main family matches, + but content of 'families' actually matter. + (For example 'review' in 'families' should result in adding to + Ftrack) - Args: - additional_filters (dict) - from Setting - families (list) - subfamilies - add_ftrack_family (bool) - add ftrack to families if True + Args: + additional_filters (dict) - from Setting + families (set[str]) - subfamilies + add_ftrack_family (bool) - add ftrack to families if True """ + override_filter = None override_filter_value = -1 for additional_filter in additional_filters: diff --git a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py index a0bd2b305b1..4ea8135620e 100644 --- a/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py +++ b/openpype/modules/kitsu/plugins/publish/collect_kitsu_entities.py @@ -29,7 +29,7 @@ def process(self, context): if not zou_asset_data: raise ValueError("Zou asset data not found in OpenPype!") - task_name = instance.data.get("task") + task_name = instance.data.get("task", context.data.get("task")) if not task_name: continue diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 6702cbe7aa3..f8e56377bb8 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import gazu import pyblish.api +import re class IntegrateKitsuNote(pyblish.api.ContextPlugin): @@ -9,27 +10,98 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): order = pyblish.api.IntegratorOrder label = "Kitsu Note and Status" families = ["render", "kitsu"] + + # status settings set_status_note = False note_status_shortname = "wfa" + status_change_conditions = { + "status_conditions": [], + "family_requirements": [], + } - def process(self, context): - # Get comment text body - publish_comment = context.data.get("comment") - if not publish_comment: - self.log.info("Comment is not set.") + # comment settings + custom_comment_template = { + "enabled": False, + "comment_template": "{comment}", + } + + def format_publish_comment(self, instance): + """Format the instance's publish comment - self.log.debug("Comment is `{}`".format(publish_comment)) + Formats `instance.data` against the custom template. + """ + + def replace_missing_key(match): + """If key is not found in kwargs, set None instead""" + key = match.group(1) + if key not in instance.data: + self.log.warning( + "Key '{}' was not found in instance.data " + "and will be rendered as an empty string " + "in the comment".format(key) + ) + return "" + else: + return str(instance.data[key]) + template = self.custom_comment_template["comment_template"] + pattern = r"\{([^}]*)\}" + return re.sub(pattern, replace_missing_key, template) + + def process(self, context): for instance in context: + # Check if instance is a review by checking its family + # Allow a match to primary family or any of families + families = set([instance.data["family"]] + + instance.data.get("families", [])) + if "review" not in families: + continue + kitsu_task = instance.data.get("kitsu_task") - if kitsu_task is None: + if not kitsu_task: continue # Get note status, by default uses the task status for the note # if it is not specified in the configuration - note_status = kitsu_task["task_status"]["id"] + shortname = kitsu_task["task_status"]["short_name"].upper() + note_status = kitsu_task["task_status_id"] - if self.set_status_note: + # Check if any status condition is not met + allow_status_change = True + for status_cond in self.status_change_conditions[ + "status_conditions" + ]: + condition = status_cond["condition"] == "equal" + match = status_cond["short_name"].upper() == shortname + if match and not condition or condition and not match: + allow_status_change = False + break + + if allow_status_change: + # Get families + families = { + instance.data.get("family") + for instance in context + if instance.data.get("publish") + } + + # Check if any family requirement is met + for family_requirement in self.status_change_conditions[ + "family_requirements" + ]: + condition = family_requirement["condition"] == "equal" + + for family in families: + match = family_requirement["family"].lower() == family + if match and not condition or condition and not match: + allow_status_change = False + break + + if allow_status_change: + break + + # Set note status + if self.set_status_note and allow_status_change: kitsu_status = gazu.task.get_task_status_by_short_name( self.note_status_shortname ) @@ -42,11 +114,22 @@ def process(self, context): "changed!".format(self.note_status_shortname) ) + # Get comment text body + publish_comment = instance.data.get("comment") + if self.custom_comment_template["enabled"]: + publish_comment = self.format_publish_comment(instance) + + if not publish_comment: + self.log.info("Comment is not set.") + else: + self.log.debug("Comment is `{}`".format(publish_comment)) + # Add comment to kitsu task - task_id = kitsu_task["id"] - self.log.debug("Add new note in taks id {}".format(task_id)) + self.log.debug( + "Add new note in tasks id {}".format(kitsu_task["id"]) + ) kitsu_comment = gazu.task.add_comment( - task_id, note_status, comment=publish_comment + kitsu_task, note_status, comment=publish_comment ) instance.data["kitsu_comment"] = kitsu_comment diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py index 12482b56573..e05ff05f50a 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_review.py @@ -12,17 +12,17 @@ class IntegrateKitsuReview(pyblish.api.InstancePlugin): optional = True def process(self, instance): - task = instance.data["kitsu_task"]["id"] - comment = instance.data["kitsu_comment"]["id"] # Check comment has been created - if not comment: + comment_id = instance.data.get("kitsu_comment", {}).get("id") + if not comment_id: self.log.debug( "Comment not created, review not pushed to preview." ) return # Add review representations as preview of comment + task_id = instance.data["kitsu_task"]["id"] for representation in instance.data.get("representations", []): # Skip if not tagged as review if "kitsureview" not in representation.get("tags", []): @@ -31,6 +31,6 @@ def process(self, instance): self.log.debug("Found review at: {}".format(review_path)) gazu.task.add_preview( - task, comment, review_path, normalize_movie=True + task_id, comment_id, review_path, normalize_movie=True ) self.log.info("Review upload on comment") diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index 4fa8cf9fdd1..1f38648dfa4 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -129,7 +129,7 @@ def update_op_assets( frame_out = frame_in + frames_duration - 1 else: frame_out = project_doc["data"].get("frameEnd", frame_in) - item_data["frameEnd"] = frame_out + item_data["frameEnd"] = int(frame_out) # Fps, fallback to project's value or default value (25.0) try: fps = float(item_data.get("fps")) @@ -147,33 +147,37 @@ def update_op_assets( item_data["resolutionWidth"] = int(match_res.group(1)) item_data["resolutionHeight"] = int(match_res.group(2)) else: - item_data["resolutionWidth"] = project_doc["data"].get( - "resolutionWidth" + item_data["resolutionWidth"] = int( + project_doc["data"].get("resolutionWidth") ) - item_data["resolutionHeight"] = project_doc["data"].get( - "resolutionHeight" + item_data["resolutionHeight"] = int( + project_doc["data"].get("resolutionHeight") ) # Properties that doesn't fully exist in Kitsu. # Guessing those property names below: # Pixel Aspect Ratio - item_data["pixelAspect"] = item_data.get( - "pixel_aspect", project_doc["data"].get("pixelAspect") + item_data["pixelAspect"] = float( + item_data.get( + "pixel_aspect", project_doc["data"].get("pixelAspect") + ) ) # Handle Start - item_data["handleStart"] = item_data.get( - "handle_start", project_doc["data"].get("handleStart") + item_data["handleStart"] = int( + item_data.get( + "handle_start", project_doc["data"].get("handleStart") + ) ) # Handle End - item_data["handleEnd"] = item_data.get( - "handle_end", project_doc["data"].get("handleEnd") + item_data["handleEnd"] = int( + item_data.get("handle_end", project_doc["data"].get("handleEnd")) ) # Clip In - item_data["clipIn"] = item_data.get( - "clip_in", project_doc["data"].get("clipIn") + item_data["clipIn"] = int( + item_data.get("clip_in", project_doc["data"].get("clipIn")) ) # Clip Out - item_data["clipOut"] = item_data.get( - "clip_out", project_doc["data"].get("clipOut") + item_data["clipOut"] = int( + item_data.get("clip_out", project_doc["data"].get("clipOut")) ) # Tasks diff --git a/openpype/modules/sync_server/sync_server_module.py b/openpype/modules/sync_server/sync_server_module.py index 28863c091a8..5a4fa07e982 100644 --- a/openpype/modules/sync_server/sync_server_module.py +++ b/openpype/modules/sync_server/sync_server_module.py @@ -1472,13 +1472,15 @@ def _parse_sync_settings_from_settings(self, settings): return sync_settings - def get_all_site_configs(self, project_name=None): + def get_all_site_configs(self, project_name=None, + local_editable_only=False): """ Returns (dict) with all sites configured system wide. Args: project_name (str)(optional): if present, check if not disabled - + local_editable_only (bool)(opt): if True return only Local + Setting configurable (for LS UI) Returns: (dict): {'studio': {'provider':'local_drive'...}, 'MY_LOCAL': {'provider':....}} @@ -1499,9 +1501,21 @@ def get_all_site_configs(self, project_name=None): if site_settings: detail.update(site_settings) system_sites[site] = detail - system_sites.update(self._get_default_site_configs(sync_enabled, project_name)) + if local_editable_only: + local_schema = SyncServerModule.get_local_settings_schema() + editable_keys = {} + for provider_code, editables in local_schema.items(): + editable_keys[provider_code] = ["enabled", "provider"] + for editable_item in editables: + editable_keys[provider_code].append(editable_item["key"]) + + for _, site in system_sites.items(): + provider = site["provider"] + for site_config_key in list(site.keys()): + if site_config_key not in editable_keys[provider]: + site.pop(site_config_key, None) return system_sites diff --git a/openpype/modules/timers_manager/timers_manager.py b/openpype/modules/timers_manager/timers_manager.py index 0ba68285a4c..43286f7da4a 100644 --- a/openpype/modules/timers_manager/timers_manager.py +++ b/openpype/modules/timers_manager/timers_manager.py @@ -141,7 +141,9 @@ def tray_init(self): signal_handler = SignalHandler(self) idle_manager = IdleManager() widget_user_idle = WidgetUserIdle(self) - widget_user_idle.set_countdown_start(self.time_show_message) + widget_user_idle.set_countdown_start( + self.time_stop_timer - self.time_show_message + ) idle_manager.signal_reset_timer.connect( widget_user_idle.reset_countdown diff --git a/openpype/pipeline/create/context.py b/openpype/pipeline/create/context.py index acc2bb054fe..22cab28e4b9 100644 --- a/openpype/pipeline/create/context.py +++ b/openpype/pipeline/create/context.py @@ -22,7 +22,7 @@ deserialize_attr_defs, get_default_values, ) -from openpype.host import IPublishHost +from openpype.host import IPublishHost, IWorkfileHost from openpype.pipeline import legacy_io from openpype.pipeline.plugin_discover import DiscoverResult @@ -1374,6 +1374,7 @@ def __init__( self._current_project_name = None self._current_asset_name = None self._current_task_name = None + self._current_workfile_path = None self._host_is_valid = host_is_valid # Currently unused variable @@ -1503,14 +1504,62 @@ def host_name(self): return os.environ["AVALON_APP"] def get_current_project_name(self): + """Project name which was used as current context on context reset. + + Returns: + Union[str, None]: Project name. + """ + return self._current_project_name def get_current_asset_name(self): + """Asset name which was used as current context on context reset. + + Returns: + Union[str, None]: Asset name. + """ + return self._current_asset_name def get_current_task_name(self): + """Task name which was used as current context on context reset. + + Returns: + Union[str, None]: Task name. + """ + return self._current_task_name + def get_current_workfile_path(self): + """Workfile path which was opened on context reset. + + Returns: + Union[str, None]: Workfile path. + """ + + return self._current_workfile_path + + @property + def context_has_changed(self): + """Host context has changed. + + As context is used project, asset, task name and workfile path if + host does support workfiles. + + Returns: + bool: Context changed. + """ + + project_name, asset_name, task_name, workfile_path = ( + self._get_current_host_context() + ) + return ( + self._current_project_name != project_name + or self._current_asset_name != asset_name + or self._current_task_name != task_name + or self._current_workfile_path != workfile_path + ) + project_name = property(get_current_project_name) @property @@ -1575,6 +1624,28 @@ def reset_finalization(self): self._collection_shared_data = None self.refresh_thumbnails() + def _get_current_host_context(self): + project_name = asset_name = task_name = workfile_path = None + if hasattr(self.host, "get_current_context"): + host_context = self.host.get_current_context() + if host_context: + project_name = host_context.get("project_name") + asset_name = host_context.get("asset_name") + task_name = host_context.get("task_name") + + if isinstance(self.host, IWorkfileHost): + workfile_path = self.host.get_current_workfile() + + # --- TODO remove these conditions --- + if not project_name: + project_name = legacy_io.Session.get("AVALON_PROJECT") + if not asset_name: + asset_name = legacy_io.Session.get("AVALON_ASSET") + if not task_name: + task_name = legacy_io.Session.get("AVALON_TASK") + # --- + return project_name, asset_name, task_name, workfile_path + def reset_current_context(self): """Refresh current context. @@ -1593,24 +1664,14 @@ def reset_current_context(self): are stored. We should store the workfile (if is available) too. """ - project_name = asset_name = task_name = None - if hasattr(self.host, "get_current_context"): - host_context = self.host.get_current_context() - if host_context: - project_name = host_context.get("project_name") - asset_name = host_context.get("asset_name") - task_name = host_context.get("task_name") - - if not project_name: - project_name = legacy_io.Session.get("AVALON_PROJECT") - if not asset_name: - asset_name = legacy_io.Session.get("AVALON_ASSET") - if not task_name: - task_name = legacy_io.Session.get("AVALON_TASK") + project_name, asset_name, task_name, workfile_path = ( + self._get_current_host_context() + ) self._current_project_name = project_name self._current_asset_name = asset_name self._current_task_name = task_name + self._current_workfile_path = workfile_path def reset_plugins(self, discover_publish_plugins=True): """Reload plugins. diff --git a/openpype/pipeline/publish/contants.py b/openpype/pipeline/publish/contants.py index 169eca2e5c3..c5296afe9ac 100644 --- a/openpype/pipeline/publish/contants.py +++ b/openpype/pipeline/publish/contants.py @@ -1,2 +1,3 @@ DEFAULT_PUBLISH_TEMPLATE = "publish" DEFAULT_HERO_PUBLISH_TEMPLATE = "hero" +TRANSIENT_DIR_TEMPLATE = "transient" diff --git a/openpype/pipeline/publish/lib.py b/openpype/pipeline/publish/lib.py index 1ec641bac45..81913bcdd56 100644 --- a/openpype/pipeline/publish/lib.py +++ b/openpype/pipeline/publish/lib.py @@ -20,13 +20,15 @@ get_system_settings, ) from openpype.pipeline import ( - tempdir + tempdir, + Anatomy ) from openpype.pipeline.plugin_discover import DiscoverResult from .contants import ( DEFAULT_PUBLISH_TEMPLATE, DEFAULT_HERO_PUBLISH_TEMPLATE, + TRANSIENT_DIR_TEMPLATE ) @@ -690,3 +692,79 @@ def get_publish_repre_path(instance, repre, only_published=False): if os.path.exists(src_path): return src_path return None + + +def get_custom_staging_dir_info(project_name, host_name, family, task_name, + task_type, subset_name, + project_settings=None, + anatomy=None, log=None): + """Checks profiles if context should use special custom dir as staging. + + Args: + project_name (str) + host_name (str) + family (str) + task_name (str) + task_type (str) + subset_name (str) + project_settings(Dict[str, Any]): Prepared project settings. + anatomy (Dict[str, Any]) + log (Logger) (optional) + + Returns: + (tuple) + Raises: + ValueError - if misconfigured template should be used + """ + settings = project_settings or get_project_settings(project_name) + custom_staging_dir_profiles = (settings["global"] + ["tools"] + ["publish"] + ["custom_staging_dir_profiles"]) + if not custom_staging_dir_profiles: + return None, None + + if not log: + log = Logger.get_logger("get_custom_staging_dir_info") + + filtering_criteria = { + "hosts": host_name, + "families": family, + "task_names": task_name, + "task_types": task_type, + "subsets": subset_name + } + profile = filter_profiles(custom_staging_dir_profiles, + filtering_criteria, + logger=log) + + if not profile or not profile["active"]: + return None, None + + if not anatomy: + anatomy = Anatomy(project_name) + + template_name = profile["template_name"] or TRANSIENT_DIR_TEMPLATE + _validate_transient_template(project_name, template_name, anatomy) + + custom_staging_dir = anatomy.templates[template_name]["folder"] + is_persistent = profile["custom_staging_dir_persistent"] + + return custom_staging_dir, is_persistent + + +def _validate_transient_template(project_name, template_name, anatomy): + """Check that transient template is correctly configured. + + Raises: + ValueError - if misconfigured template + """ + if template_name not in anatomy.templates: + raise ValueError(("Anatomy of project \"{}\" does not have set" + " \"{}\" template key!" + ).format(project_name, template_name)) + + if "folder" not in anatomy.templates[template_name]: + raise ValueError(("There is not set \"folder\" template in \"{}\" anatomy" # noqa + " for project \"{}\"." + ).format(template_name, project_name)) diff --git a/openpype/plugins/publish/cleanup.py b/openpype/plugins/publish/cleanup.py index ef312e391f8..b90c88890da 100644 --- a/openpype/plugins/publish/cleanup.py +++ b/openpype/plugins/publish/cleanup.py @@ -93,6 +93,10 @@ def process(self, instance): self.log.info("No staging directory found: %s" % staging_dir) return + if instance.data.get("stagingDir_persistent"): + self.log.info("Staging dir: %s should be persistent" % staging_dir) + return + self.log.info("Removing staging directory {}".format(staging_dir)) shutil.rmtree(staging_dir) diff --git a/openpype/plugins/publish/cleanup_farm.py b/openpype/plugins/publish/cleanup_farm.py index b87d4698a27..8052f137346 100644 --- a/openpype/plugins/publish/cleanup_farm.py +++ b/openpype/plugins/publish/cleanup_farm.py @@ -37,7 +37,7 @@ def process(self, context): dirpaths_to_remove = set() for instance in context: staging_dir = instance.data.get("stagingDir") - if staging_dir: + if staging_dir and not instance.data.get("stagingDir_persistent"): dirpaths_to_remove.add(os.path.normpath(staging_dir)) if "representations" in instance.data: diff --git a/openpype/plugins/publish/collect_comment.py b/openpype/plugins/publish/collect_comment.py index 5be04731ace..9f41e37f222 100644 --- a/openpype/plugins/publish/collect_comment.py +++ b/openpype/plugins/publish/collect_comment.py @@ -29,7 +29,7 @@ class CollectInstanceCommentDef( - pyblish.api.ContextPlugin, + pyblish.api.InstancePlugin, OpenPypePyblishPluginMixin ): label = "Comment per instance" diff --git a/openpype/plugins/publish/collect_custom_staging_dir.py b/openpype/plugins/publish/collect_custom_staging_dir.py new file mode 100644 index 00000000000..72ab0fe34d2 --- /dev/null +++ b/openpype/plugins/publish/collect_custom_staging_dir.py @@ -0,0 +1,67 @@ +""" +Requires: + anatomy + + +Provides: + instance.data -> stagingDir (folder path) + -> stagingDir_persistent (bool) +""" +import copy +import os.path + +import pyblish.api + +from openpype.pipeline.publish.lib import get_custom_staging_dir_info + + +class CollectCustomStagingDir(pyblish.api.InstancePlugin): + """Looks through profiles if stagingDir should be persistent and in special + location. + + Transient staging dir could be useful in specific use cases where is + desirable to have temporary renders in specific, persistent folders, could + be on disks optimized for speed for example. + + It is studio responsibility to clean up obsolete folders with data. + + Location of the folder is configured in `project_anatomy/templates/others`. + ('transient' key is expected, with 'folder' key) + + Which family/task type/subset is applicable is configured in: + `project_settings/global/tools/publish/custom_staging_dir_profiles` + + """ + label = "Collect Custom Staging Directory" + order = pyblish.api.CollectorOrder + 0.4990 + + template_key = "transient" + + def process(self, instance): + family = instance.data["family"] + subset_name = instance.data["subset"] + host_name = instance.context.data["hostName"] + project_name = instance.context.data["projectName"] + + anatomy = instance.context.data["anatomy"] + anatomy_data = copy.deepcopy(instance.data["anatomyData"]) + task = anatomy_data.get("task", {}) + + transient_tml, is_persistent = get_custom_staging_dir_info( + project_name, host_name, family, task.get("name"), + task.get("type"), subset_name, anatomy=anatomy, log=self.log) + result_str = "Not adding" + if transient_tml: + anatomy_data["root"] = anatomy.roots + scene_name = instance.context.data.get("currentFile") + if scene_name: + anatomy_data["scene_name"] = os.path.basename(scene_name) + transient_dir = transient_tml.format(**anatomy_data) + instance.data["stagingDir"] = transient_dir + + instance.data["stagingDir_persistent"] = is_persistent + result_str = "Adding '{}' as".format(transient_dir) + + self.log.info("{} custom staging dir for instance with '{}'".format( + result_str, family + )) diff --git a/openpype/plugins/publish/extract_burnin.py b/openpype/plugins/publish/extract_burnin.py index 621c63a87ea..816393f6f96 100644 --- a/openpype/plugins/publish/extract_burnin.py +++ b/openpype/plugins/publish/extract_burnin.py @@ -16,9 +16,7 @@ get_transcode_temp_directory, convert_input_paths_for_ffmpeg, - should_convert_for_ffmpeg, - - CREATE_NO_WINDOW + should_convert_for_ffmpeg ) from openpype.lib.profiles_filtering import filter_profiles @@ -255,6 +253,9 @@ def main_process(self, instance): # Add context data burnin_data. burnin_data["custom"] = custom_data + # Add data members. + burnin_data.update(instance.data.get("burninDataMembers", {})) + # Add source camera name to burnin data camera_name = repre.get("camera_name") if camera_name: @@ -339,8 +340,6 @@ def main_process(self, instance): "logger": self.log, "env": {} } - if platform.system().lower() == "windows": - process_kwargs["creationflags"] = CREATE_NO_WINDOW run_openpype_process(*args, **process_kwargs) # Remove the temporary json @@ -730,7 +729,6 @@ def filter_burnins_defs(self, profile, instance): return filtered_burnin_defs families = self.families_from_instance(instance) - low_families = [family.lower() for family in families] for filename_suffix, orig_burnin_def in burnin_defs.items(): burnin_def = copy.deepcopy(orig_burnin_def) @@ -741,7 +739,7 @@ def filter_burnins_defs(self, profile, instance): families_filters = def_filter["families"] if not self.families_filter_validation( - low_families, families_filters + families, families_filters ): self.log.debug(( "Skipped burnin definition \"{}\". Family" @@ -778,31 +776,19 @@ def filter_burnins_defs(self, profile, instance): return filtered_burnin_defs def families_filter_validation(self, families, output_families_filter): - """Determine if entered families intersect with families filters. + """Determines if entered families intersect with families filters. All family values are lowered to avoid unexpected results. """ - if not output_families_filter: - return True - - for family_filter in output_families_filter: - if not family_filter: - continue - if not isinstance(family_filter, (list, tuple)): - if family_filter.lower() not in families: - continue - return True - - valid = True - for family in family_filter: - if family.lower() not in families: - valid = False - break - - if valid: - return True - return False + families_filter_lower = set(family.lower() for family in + output_families_filter + # Exclude empty filter values + if family) + if not families_filter_lower: + return True + return any(family.lower() in families_filter_lower + for family in families) def families_from_instance(self, instance): """Return all families of entered instance.""" diff --git a/openpype/plugins/publish/integrate.py b/openpype/plugins/publish/integrate.py index b1170068716..760b1a6b370 100644 --- a/openpype/plugins/publish/integrate.py +++ b/openpype/plugins/publish/integrate.py @@ -24,7 +24,10 @@ get_version_by_name, ) from openpype.lib import source_hash -from openpype.lib.file_transaction import FileTransaction +from openpype.lib.file_transaction import ( + FileTransaction, + DuplicateDestinationError +) from openpype.pipeline.publish import ( KnownPublishError, get_publish_template_name, @@ -80,10 +83,12 @@ class IntegrateAsset(pyblish.api.InstancePlugin): order = pyblish.api.IntegratorOrder families = ["workfile", "pointcache", + "pointcloud", "proxyAbc", "camera", "animation", "model", + "maxScene", "mayaAscii", "mayaScene", "setdress", @@ -168,9 +173,18 @@ def process(self, instance): ).format(instance.data["family"])) return - file_transactions = FileTransaction(log=self.log) + file_transactions = FileTransaction(log=self.log, + # Enforce unique transfers + allow_queue_replacements=False) try: self.register(instance, file_transactions, filtered_repres) + except DuplicateDestinationError as exc: + # Raise DuplicateDestinationError as KnownPublishError + # and rollback the transactions + file_transactions.rollback() + six.reraise(KnownPublishError, + KnownPublishError(exc), + sys.exc_info()[2]) except Exception: # clean destination # todo: preferably we'd also rollback *any* changes to the database diff --git a/openpype/plugins/publish/integrate_legacy.py b/openpype/plugins/publish/integrate_legacy.py index b93abab1d88..1d0177f1515 100644 --- a/openpype/plugins/publish/integrate_legacy.py +++ b/openpype/plugins/publish/integrate_legacy.py @@ -76,10 +76,12 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): order = pyblish.api.IntegratorOrder + 0.00001 families = ["workfile", "pointcache", + "pointcloud", "proxyAbc", "camera", "animation", "model", + "maxScene", "mayaAscii", "mayaScene", "setdress", diff --git a/openpype/plugins/publish/preintegrate_thumbnail_representation.py b/openpype/plugins/publish/preintegrate_thumbnail_representation.py index b88ccee9dce..1c95b82c978 100644 --- a/openpype/plugins/publish/preintegrate_thumbnail_representation.py +++ b/openpype/plugins/publish/preintegrate_thumbnail_representation.py @@ -60,6 +60,8 @@ def process(self, instance): if not found_profile: return + thumbnail_repre.setdefault("tags", []) + if not found_profile["integrate_thumbnail"]: if "delete" not in thumbnail_repre["tags"]: thumbnail_repre["tags"].append("delete") diff --git a/openpype/pype_commands.py b/openpype/pype_commands.py index 932fdc9be41..dc5b3d63c32 100644 --- a/openpype/pype_commands.py +++ b/openpype/pype_commands.py @@ -270,7 +270,7 @@ def validate_jsons(self): pass def run_tests(self, folder, mark, pyargs, - test_data_folder, persist, app_variant, timeout): + test_data_folder, persist, app_variant, timeout, setup_only): """ Runs tests from 'folder' @@ -311,6 +311,9 @@ def run_tests(self, folder, mark, pyargs, if timeout: args.extend(["--timeout", timeout]) + if setup_only: + args.extend(["--setup_only", setup_only]) + print("run_tests args: {}".format(args)) import pytest pytest.main(args) diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index cb4646c099d..d0a42669412 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -4,8 +4,10 @@ import subprocess import platform import json -import opentimelineio_contrib.adapters.ffmpeg_burnins as ffmpeg_burnins +import tempfile +from string import Formatter +import opentimelineio_contrib.adapters.ffmpeg_burnins as ffmpeg_burnins from openpype.lib import ( get_ffmpeg_tool_path, get_ffmpeg_codec_args, @@ -23,7 +25,7 @@ ).format(ffmpeg_path) DRAWTEXT = ( - "drawtext=fontfile='%(font)s':text=\\'%(text)s\\':" + "drawtext@'%(label)s'=fontfile='%(font)s':text=\\'%(text)s\\':" "x=%(x)s:y=%(y)s:fontcolor=%(color)s@%(opacity).1f:fontsize=%(size)d" ) TIMECODE = ( @@ -39,6 +41,45 @@ SOURCE_TIMECODE_KEY = "{source_timecode}" +def convert_list_to_command(list_to_convert, fps, label=""): + """Convert a list of values to a drawtext command file for ffmpeg `sendcmd` + + The list of values is expected to have a value per frame. If the video + file ends up being longer than the amount of samples per frame than the + last value will be held. + + Args: + list_to_convert (list): List of values per frame. + fps (float or int): The expected frame per seconds of the output file. + label (str): Label for the drawtext, if specific drawtext filter is + required + + Returns: + str: Filepath to the temporary drawtext command file. + + """ + + with tempfile.NamedTemporaryFile(mode="w", delete=False) as f: + for i, value in enumerate(list_to_convert): + seconds = i / fps + + # Escape special character + value = str(value).replace(":", "\\:") + + filter = "drawtext" + if label: + filter += "@" + label + + line = ( + "{start} {filter} reinit text='{value}';" + "\n".format(start=seconds, filter=filter, value=value) + ) + + f.write(line) + f.flush() + return f.name + + def _get_ffprobe_data(source): """Reimplemented from otio burnins to be able use full path to ffprobe :param str source: source media file @@ -144,7 +185,13 @@ def __init__( self.options_init.update(options_init) def add_text( - self, text, align, frame_start=None, frame_end=None, options=None + self, + text, + align, + frame_start=None, + frame_end=None, + options=None, + cmd="" ): """ Adding static text to a filter. @@ -165,7 +212,13 @@ def add_text( if frame_end is not None: options["frame_end"] = frame_end - self._add_burnin(text, align, options, DRAWTEXT) + draw_text = DRAWTEXT + if cmd: + draw_text = "{}, {}".format(cmd, DRAWTEXT) + + options["label"] = align + + self._add_burnin(text, align, options, draw_text) def add_timecode( self, align, frame_start=None, frame_end=None, frame_start_tc=None, @@ -345,12 +398,6 @@ def render(self, output, args=None, overwrite=False, **kwargs): "stderr": subprocess.PIPE, "shell": True, } - if platform.system().lower() == "windows": - kwargs["creationflags"] = ( - subprocess.CREATE_NEW_PROCESS_GROUP - | getattr(subprocess, "DETACHED_PROCESS", 0) - | getattr(subprocess, "CREATE_NO_WINDOW", 0) - ) proc = subprocess.Popen(command, **kwargs) _stdout, _stderr = proc.communicate() @@ -414,11 +461,13 @@ def burnins_from_data( True by default. Presets must be set separately. Should be dict with 2 keys: - - "options" - sets look of burnins - colors, opacity,...(more info: ModifiedBurnins doc) + - "options" - sets look of burnins - colors, opacity,... + (more info: ModifiedBurnins doc) - *OPTIONAL* default values are used when not included - "burnins" - contains dictionary with burnins settings - *OPTIONAL* burnins won't be added (easier is not to use this) - - each key of "burnins" represents Alignment, there are 6 possibilities: + - each key of "burnins" represents Alignment, + there are 6 possibilities: TOP_LEFT TOP_CENTERED TOP_RIGHT BOTTOM_LEFT BOTTOM_CENTERED BOTTOM_RIGHT - value must be string with text you want to burn-in @@ -497,13 +546,14 @@ def burnins_from_data( if source_timecode is not None: data[SOURCE_TIMECODE_KEY[1:-1]] = SOURCE_TIMECODE_KEY + clean_up_paths = [] for align_text, value in burnin_values.items(): if not value: continue - if isinstance(value, (dict, list, tuple)): + if isinstance(value, dict): raise TypeError(( - "Expected string or number type." + "Expected string, number or list type." " Got: {} - \"{}\"" " (Make sure you have new burnin presets)." ).format(str(type(value)), str(value))) @@ -539,8 +589,48 @@ def burnins_from_data( print("Source does not have set timecode value.") value = value.replace(SOURCE_TIMECODE_KEY, MISSING_KEY_VALUE) - key_pattern = re.compile(r"(\{.*?[^{0]*\})") + # Convert lists. + cmd = "" + text = None + keys = [i[1] for i in Formatter().parse(value) if i[1] is not None] + list_to_convert = [] + # Warn about nested dictionary support for lists. Ei. we dont support + # it. + if "[" in "".join(keys): + print( + "We dont support converting nested dictionaries to lists," + " so skipping {}".format(value) + ) + else: + for key in keys: + data_value = data[key] + + # Multiple lists are not supported. + if isinstance(data_value, list) and list_to_convert: + raise ValueError( + "Found multiple lists to convert, which is not " + "supported: {}".format(value) + ) + + if isinstance(data_value, list): + print("Found list to convert: {}".format(data_value)) + for v in data_value: + data[key] = v + list_to_convert.append(value.format(**data)) + + if list_to_convert: + value = list_to_convert[0] + path = convert_list_to_command( + list_to_convert, data["fps"], label=align + ) + cmd = "sendcmd=f='{}'".format(path) + cmd = cmd.replace("\\", "/") + cmd = cmd.replace(":", "\\:") + clean_up_paths.append(path) + + # Failsafe for missing keys. + key_pattern = re.compile(r"(\{.*?[^{0]*\})") missing_keys = [] for group in key_pattern.findall(value): try: @@ -574,7 +664,8 @@ def burnins_from_data( continue text = value.format(**data) - burnin.add_text(text, align, frame_start, frame_end) + + burnin.add_text(text, align, frame_start, frame_end, cmd=cmd) ffmpeg_args = [] if codec_data: @@ -605,6 +696,8 @@ def burnins_from_data( burnin.render( output_path, args=ffmpeg_args_str, overwrite=overwrite, **data ) + for path in clean_up_paths: + os.remove(path) if __name__ == "__main__": diff --git a/openpype/settings/defaults/project_anatomy/templates.json b/openpype/settings/defaults/project_anatomy/templates.json index 02c0e353773..e5e535bf193 100644 --- a/openpype/settings/defaults/project_anatomy/templates.json +++ b/openpype/settings/defaults/project_anatomy/templates.json @@ -58,12 +58,16 @@ "file": "{originalBasename}.{ext}", "path": "{@folder}/{@file}" }, + "transient": { + "folder": "{root[work]}/{project[name]}/{hierarchy}/{asset}/work/{family}/{subset}" + }, "__dynamic_keys_labels__": { "maya2unreal": "Maya to Unreal", "simpleUnrealTextureHero": "Simple Unreal Texture - Hero", "simpleUnrealTexture": "Simple Unreal Texture", "online": "online", - "source": "source" + "source": "source", + "transient": "transient" } } } diff --git a/openpype/settings/defaults/project_settings/applications.json b/openpype/settings/defaults/project_settings/applications.json new file mode 100644 index 00000000000..62f3cdfe1be --- /dev/null +++ b/openpype/settings/defaults/project_settings/applications.json @@ -0,0 +1,3 @@ +{ + "only_available": false +} diff --git a/openpype/settings/defaults/project_settings/blender.json b/openpype/settings/defaults/project_settings/blender.json index fe05f945902..20eec0c09d2 100644 --- a/openpype/settings/defaults/project_settings/blender.json +++ b/openpype/settings/defaults/project_settings/blender.json @@ -80,6 +80,94 @@ "enabled": true, "optional": true, "active": false + }, + "ExtractThumbnail": { + "enabled": true, + "optional": true, + "active": true, + "presets": { + "model": { + "image_settings": { + "file_format": "JPEG", + "color_mode": "RGB", + "quality": 100 + }, + "display_options": { + "shading": { + "light": "STUDIO", + "studio_light": "Default", + "type": "SOLID", + "color_type": "OBJECT", + "show_xray": false, + "show_shadows": false, + "show_cavity": true + }, + "overlay": { + "show_overlays": false + } + } + }, + "rig": { + "image_settings": { + "file_format": "JPEG", + "color_mode": "RGB", + "quality": 100 + }, + "display_options": { + "shading": { + "light": "STUDIO", + "studio_light": "Default", + "type": "SOLID", + "color_type": "OBJECT", + "show_xray": true, + "show_shadows": false, + "show_cavity": false + }, + "overlay": { + "show_overlays": true, + "show_ortho_grid": false, + "show_floor": false, + "show_axis_x": false, + "show_axis_y": false, + "show_axis_z": false, + "show_text": false, + "show_stats": false, + "show_cursor": false, + "show_annotation": false, + "show_extras": false, + "show_relationship_lines": false, + "show_outline_selected": false, + "show_motion_paths": false, + "show_object_origins": false, + "show_bones": true + } + } + } + } + }, + "ExtractPlayblast": { + "enabled": true, + "optional": true, + "active": true, + "presets": { + "default": { + "image_settings": { + "file_format": "PNG", + "color_mode": "RGB", + "color_depth": "8", + "compression": 15 + }, + "display_options": { + "shading": { + "type": "MATERIAL", + "render_pass": "COMBINED" + }, + "overlay": { + "show_overlays": false + } + } + } + } } } } diff --git a/openpype/settings/defaults/project_settings/celaction.json b/openpype/settings/defaults/project_settings/celaction.json index bdba6d73227..822604fd2f2 100644 --- a/openpype/settings/defaults/project_settings/celaction.json +++ b/openpype/settings/defaults/project_settings/celaction.json @@ -9,6 +9,13 @@ "rules": {} } }, + "workfile": { + "submission_overrides": [ + "render_chunk", + "frame_range", + "resolution" + ] + }, "publish": { "CollectRenderPath": { "output_extension": "png", diff --git a/openpype/settings/defaults/project_settings/deadline.json b/openpype/settings/defaults/project_settings/deadline.json index 6b6f2d465b5..fdd70f1a44a 100644 --- a/openpype/settings/defaults/project_settings/deadline.json +++ b/openpype/settings/defaults/project_settings/deadline.json @@ -23,7 +23,7 @@ "enabled": true, "optional": false, "active": true, - "tile_assembler_plugin": "OpenPypeTileAssembler", + "tile_assembler_plugin": "DraftTileAssembler", "use_published": true, "import_reference": false, "asset_dependencies": true, @@ -43,10 +43,7 @@ "use_published": true, "priority": 50, "chunk_size": 10, - "group": "none", - "deadline_pool": "", - "deadline_pool_secondary": "", - "framePerTask": 1 + "group": "none" }, "NukeSubmitDeadline": { "enabled": true, diff --git a/openpype/settings/defaults/project_settings/fusion.json b/openpype/settings/defaults/project_settings/fusion.json index 954606820a3..f974eebacae 100644 --- a/openpype/settings/defaults/project_settings/fusion.json +++ b/openpype/settings/defaults/project_settings/fusion.json @@ -16,5 +16,10 @@ "linux": [] } } + }, + "copy_fusion_settings": { + "copy_path": "~/.openpype/hosts/fusion/profiles", + "copy_status": false, + "force_sync": false } } diff --git a/openpype/settings/defaults/project_settings/global.json b/openpype/settings/defaults/project_settings/global.json index aad17d54daa..30e56300d13 100644 --- a/openpype/settings/defaults/project_settings/global.json +++ b/openpype/settings/defaults/project_settings/global.json @@ -249,6 +249,29 @@ } } } + }, + { + "families": [], + "hosts": [ + "maya" + ], + "task_types": [], + "task_names": [], + "subsets": [], + "burnins": { + "maya_burnin": { + "TOP_LEFT": "{yy}-{mm}-{dd}", + "TOP_CENTERED": "{focalLength:.2f} mm", + "TOP_RIGHT": "{anatomy[version]}", + "BOTTOM_LEFT": "{username}", + "BOTTOM_CENTERED": "{asset}", + "BOTTOM_RIGHT": "{frame_start}-{current_frame}-{frame_end}", + "filter": { + "families": [], + "tags": [] + } + } + } } ] }, @@ -591,7 +614,8 @@ "task_names": [], "template_name": "simpleUnrealTextureHero" } - ] + ], + "custom_staging_dir_profiles": [] } }, "project_folder_structure": "{\"__project_root__\": {\"prod\": {}, \"resources\": {\"footage\": {\"plates\": {}, \"offline\": {}}, \"audio\": {}, \"art_dept\": {}}, \"editorial\": {}, \"assets\": {\"characters\": {}, \"locations\": {}}, \"shots\": {}}}", diff --git a/openpype/settings/defaults/project_settings/kitsu.json b/openpype/settings/defaults/project_settings/kitsu.json index 95b3da04ae0..59a36d8b97d 100644 --- a/openpype/settings/defaults/project_settings/kitsu.json +++ b/openpype/settings/defaults/project_settings/kitsu.json @@ -7,7 +7,15 @@ "publish": { "IntegrateKitsuNote": { "set_status_note": false, - "note_status_shortname": "wfa" + "note_status_shortname": "wfa", + "status_change_conditions": { + "status_conditions": [], + "family_requirements": [] + }, + "custom_comment_template": { + "enabled": false, + "comment_template": "{comment}\n\n| | |\n|--|--|\n| version| `{version}` |\n| family | `{family}` |\n| name | `{name}` |" + } } } } diff --git a/openpype/settings/defaults/project_settings/max.json b/openpype/settings/defaults/project_settings/max.json index 667b42411d6..d59cdf8c4a3 100644 --- a/openpype/settings/defaults/project_settings/max.json +++ b/openpype/settings/defaults/project_settings/max.json @@ -4,5 +4,20 @@ "aov_separator": "underscore", "image_format": "exr", "multipass": true + }, + "PointCloud":{ + "attribute":{ + "Age": "age", + "Radius": "radius", + "Position": "position", + "Rotation": "rotation", + "Scale": "scale", + "Velocity": "velocity", + "Color": "color", + "TextureCoordinate": "texcoord", + "MaterialID": "matid", + "custFloats": "custFloats", + "custVecs": "custVecs" + } } } diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index dca0b952935..e914eb29f98 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -147,6 +147,7 @@ "enabled": true, "write_color_sets": false, "write_face_sets": false, + "include_parent_hierarchy": false, "include_user_defined_attributes": false, "defaults": [ "Main" @@ -330,6 +331,11 @@ "optional": true, "active": true }, + "ValidateMayaColorSpace": { + "enabled": true, + "optional": true, + "active": true + }, "ValidateAttributes": { "enabled": false, "attributes": {} @@ -784,7 +790,7 @@ "ExtractPlayblast": { "capture_preset": { "Codec": { - "compression": "jpg", + "compression": "png", "format": "image", "quality": 95 }, @@ -811,7 +817,8 @@ }, "Generic": { "isolate_view": true, - "off_screen": true + "off_screen": true, + "pan_zoom": false }, "Renderer": { "rendererName": "vp2Renderer" diff --git a/openpype/settings/defaults/project_settings/tvpaint.json b/openpype/settings/defaults/project_settings/tvpaint.json index 9173a8c3d5a..1671748e977 100644 --- a/openpype/settings/defaults/project_settings/tvpaint.json +++ b/openpype/settings/defaults/project_settings/tvpaint.json @@ -42,6 +42,7 @@ "default_variants": [] }, "auto_detect_render": { + "enabled": false, "allow_group_rename": true, "group_name_template": "L{group_index}", "group_idx_offset": 10, diff --git a/openpype/settings/defaults/system_settings/applications.json b/openpype/settings/defaults/system_settings/applications.json index 5fd9b926fb1..eb3a88ce665 100644 --- a/openpype/settings/defaults/system_settings/applications.json +++ b/openpype/settings/defaults/system_settings/applications.json @@ -133,7 +133,7 @@ "linux": [] }, "arguments": { - "windows": [], + "windows": ["-U MAXScript {OPENPYPE_ROOT}\\openpype\\hosts\\max\\startup\\startup.ms"], "darwin": [], "linux": [] }, diff --git a/openpype/settings/entities/schemas/README.md b/openpype/settings/entities/schemas/README.md index b4c878fe0fa..cff614a4bb0 100644 --- a/openpype/settings/entities/schemas/README.md +++ b/openpype/settings/entities/schemas/README.md @@ -350,7 +350,7 @@ How output of the schema could look like on save: - number input, can be used for both integer and float - key `"decimal"` defines how many decimal places will be used, 0 is for integer input (Default: `0`) - key `"minimum"` as minimum allowed number to enter (Default: `-99999`) - - key `"maxium"` as maximum allowed number to enter (Default: `99999`) + - key `"maximum"` as maximum allowed number to enter (Default: `99999`) - key `"steps"` will change single step value of UI inputs (using arrows and wheel scroll) - for UI it is possible to show slider to enable this option set `show_slider` to `true` ``` diff --git a/openpype/settings/entities/schemas/projects_schema/schema_main.json b/openpype/settings/entities/schemas/projects_schema/schema_main.json index ebe59c7942b..8c1d8ccbdd1 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_main.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_main.json @@ -82,6 +82,10 @@ "type": "schema", "name": "schema_project_slack" }, + { + "type": "schema", + "name": "schema_project_applications" + }, { "type": "schema", "name": "schema_project_max" diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_applications.json b/openpype/settings/entities/schemas/projects_schema/schema_project_applications.json new file mode 100644 index 00000000000..030ed3ee8ad --- /dev/null +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_applications.json @@ -0,0 +1,14 @@ +{ + "type": "dict", + "key": "applications", + "label": "Applications", + "collapsible": true, + "is_file": true, + "children": [ + { + "type": "boolean", + "key": "only_available", + "label": "Show only available applications" + } + ] +} diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_celaction.json b/openpype/settings/entities/schemas/projects_schema/schema_project_celaction.json index 2320d9ae266..c5ca3eb9f56 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_celaction.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_celaction.json @@ -22,6 +22,31 @@ ] }, + { + "type": "dict", + "collapsible": true, + "key": "workfile", + "label": "Workfile", + "children": [ + { + "key": "submission_overrides", + "label": "Submission workfile overrides", + "type": "enum", + "multiselection": true, + "enum_items": [ + { + "render_chunk": "Pass chunk size" + }, + { + "frame_range": "Pass frame range" + }, + { + "resolution": "Pass resolution" + } + ] + } + ] + }, { "type": "dict", "collapsible": true, diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json b/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json index bb5a65e1b7e..d8b5e4dc1fa 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json @@ -121,7 +121,7 @@ "DraftTileAssembler": "Draft Tile Assembler" }, { - "OpenPypeTileAssembler": "Open Image IO" + "OpenPypeTileAssembler": "OpenPype Tile Assembler" } ] }, @@ -239,27 +239,12 @@ { "type": "number", "key": "chunk_size", - "label": "Chunk Size" + "label": "Frame per Task" }, { "type": "text", "key": "group", "label": "Group Name" - }, - { - "type": "text", - "key": "deadline_pool", - "label": "Deadline pool" - }, - { - "type": "text", - "key": "deadline_pool_secondary", - "label": "Deadline pool (secondary)" - }, - { - "type": "number", - "key": "framePerTask", - "label": "Frame Per Task" } ] }, diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_fusion.json b/openpype/settings/entities/schemas/projects_schema/schema_project_fusion.json index 8c62d758159..464cf2c06d4 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_fusion.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_fusion.json @@ -45,6 +45,29 @@ ] } ] + }, + { + "type": "dict", + "key": "copy_fusion_settings", + "collapsible": true, + "label": "Local Fusion profile settings", + "children": [ + { + "key": "copy_path", + "type": "path", + "label": "Local Fusion profile directory" + }, + { + "type": "boolean", + "key": "copy_status", + "label": "Copy profile on first launch" + }, + { + "key":"force_sync", + "type": "boolean", + "label": "Resync profile on each launch" + } + ] } ] } diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index fb47670e74a..8aeed00542e 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -46,12 +46,94 @@ { "type": "boolean", "key": "set_status_note", - "label": "Set status on note" + "label": "Set status with note" }, { "type": "text", "key": "note_status_shortname", "label": "Note shortname" + }, + { + "type": "dict", + "collapsible": true, + "key": "status_change_conditions", + "label": "Status change conditions", + "children": [ + { + "type": "list", + "key": "status_conditions", + "label": "Status conditions", + "object_type": { + "type": "dict", + "key": "condition_dict", + "children": [ + { + "type": "enum", + "key": "condition", + "label": "Condition", + "enum_items": [ + {"equal": "Equal"}, + {"not_equal": "Not equal"} + ] + }, + { + "type": "text", + "key": "short_name", + "label": "Short name" + } + ] + } + }, + { + "type": "list", + "key": "family_requirements", + "label": "Family requirements", + "object_type": { + "type": "dict", + "key": "requirement_dict", + "children": [ + { + "type": "enum", + "key": "condition", + "label": "Condition", + "enum_items": [ + {"equal": "Equal"}, + {"not_equal": "Not equal"} + ] + }, + { + "type": "text", + "key": "family", + "label": "Family" + } + ] + } + } + ] + }, + { + "type": "dict", + "collapsible": true, + "checkbox_key": "enabled", + "key": "custom_comment_template", + "label": "Custom Comment Template", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "label", + "label": "Kitsu supports markdown and here you can create a custom comment template.
    You can use data from your publishing instance's data." + }, + { + "key": "comment_template", + "type": "text", + "multiline": true, + "label": "Custom comment" + } + ] } ] } diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_max.json b/openpype/settings/entities/schemas/projects_schema/schema_project_max.json index 8a283c1acc3..4fba9aff0a0 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_max.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_max.json @@ -51,6 +51,28 @@ "label": "multipass" } ] + }, + { + "type": "dict", + "collapsible": true, + "key": "PointCloud", + "label": "Point Cloud", + "children": [ + { + "type": "label", + "label": "Define the channel attribute names before exporting as PRT" + }, + { + "type": "dict-modifiable", + "collapsible": true, + "key": "attribute", + "label": "Channel Attribute", + "use_label_wrap": true, + "object_type": { + "type": "text" + } + } + ] } ] -} \ No newline at end of file +} diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json b/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json index 708b688ba5f..10945958513 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json @@ -202,7 +202,13 @@ "key": "auto_detect_render", "label": "Auto-Detect Create Render", "is_group": true, + "checkbox_key": "enabled", "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, { "type": "label", "label": "The creator tries to auto-detect Render Layers and Render Passes in scene. For Render Layers is used group name as a variant and for Render Passes is used TVPaint layer name.

    Group names can be renamed by their used order in scene. The renaming template where can be used {group_index} formatting key which is filled by \"used position index of group\".
    - Template: L{group_index}
    - Group offset: 10
    - Group padding: 3
    Would create group names \"L010\", \"L020\", ..." diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_blender_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_blender_publish.json index 53949f65cbe..1037519f57d 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_blender_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_blender_publish.json @@ -112,6 +112,66 @@ "label": "Extract Layout as JSON" } ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ExtractThumbnail", + "label": "ExtractThumbnail", + "checkbox_key": "enabled", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + }, + { + "type": "raw-json", + "key": "presets", + "label": "Presets" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ExtractPlayblast", + "label": "ExtractPlayblast", + "checkbox_key": "enabled", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + }, + { + "type": "raw-json", + "key": "presets", + "label": "Presets" + } + ] } ] -} +} \ No newline at end of file diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json index 962008d4764..85ec482e735 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json @@ -408,6 +408,71 @@ } ] } + }, + { + "type": "list", + "key": "custom_staging_dir_profiles", + "label": "Custom Staging Dir Profiles", + "use_label_wrap": true, + "docstring": "Profiles to specify special location and persistence for staging dir. Could be used in Creators and Publish phase!", + "object_type": { + "type": "dict", + "children": [ + { + "type": "boolean", + "key": "active", + "label": "Is active", + "default": true + }, + { + "type": "separator" + }, + { + "key": "hosts", + "label": "Host names", + "type": "hosts-enum", + "multiselection": true + }, + { + "key": "task_types", + "label": "Task types", + "type": "task-types-enum" + }, + { + "key": "task_names", + "label": "Task names", + "type": "list", + "object_type": "text" + }, + { + "key": "families", + "label": "Families", + "type": "list", + "object_type": "text" + }, + { + "key": "subsets", + "label": "Subset names", + "type": "list", + "object_type": "text" + }, + { + "type": "separator" + }, + { + "key": "custom_staging_dir_persistent", + "label": "Custom Staging Folder Persistent", + "type": "boolean", + "default": false + }, + { + "key": "template_name", + "label": "Template Name", + "type": "text", + "placeholder": "transient" + } + ] + } } ] } diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json index 1f0e4eeffbd..416e530db2e 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json @@ -19,12 +19,12 @@ { "type": "text", "key": "compression", - "label": "Compression type" + "label": "Encoding" }, { "type": "text", "key": "format", - "label": "Data format" + "label": "Format" }, { "type": "number", @@ -91,6 +91,11 @@ "type": "boolean", "key": "off_screen", "label": " Off Screen" + }, + { + "type": "boolean", + "key": "pan_zoom", + "label": " 2D Pan/Zoom" } ] }, @@ -156,7 +161,7 @@ { "type": "boolean", "key": "override_viewport_options", - "label": "override_viewport_options" + "label": "Override Viewport Options" }, { "type": "enum", diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json index 1598f906439..d6e6c97b8cd 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json @@ -132,6 +132,11 @@ "key": "write_face_sets", "label": "Write Face Sets" }, + { + "type": "boolean", + "key": "include_parent_hierarchy", + "label": "Include Parent Hierarchy" + }, { "type": "boolean", "key": "include_user_defined_attributes", diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json index 994e2d00328..5a66f8a5130 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json @@ -144,6 +144,10 @@ { "key": "ValidateShadingEngine", "label": "Validate Look Shading Engine Naming" + }, + { + "key": "ValidateMayaColorSpace", + "label": "ValidateMayaColorSpace" } ] }, @@ -365,7 +369,8 @@ "label": "Arnold Render Attributes", "use_label_wrap": true, "object_type": { - "type": "text" + "type": "list", + "object_type": "text" } }, { @@ -375,7 +380,8 @@ "label": "Vray Render Attributes", "use_label_wrap": true, "object_type": { - "type": "text" + "type": "list", + "object_type": "text" } }, { @@ -385,7 +391,8 @@ "label": "Redshift Render Attributes", "use_label_wrap": true, "object_type": { - "type": "text" + "type": "list", + "object_type": "text" } }, { @@ -395,7 +402,8 @@ "label": "Renderman Render Attributes", "use_label_wrap": true, "object_type": { - "type": "text" + "type": "list", + "object_type": "text" } } ] diff --git a/openpype/tools/launcher/models.py b/openpype/tools/launcher/models.py index 6c763544a90..3aa6c5d8cb7 100644 --- a/openpype/tools/launcher/models.py +++ b/openpype/tools/launcher/models.py @@ -19,6 +19,7 @@ CUSTOM_LAUNCH_APP_GROUPS, ApplicationManager ) +from openpype.settings import get_project_settings from openpype.pipeline import discover_launcher_actions from openpype.tools.utils.lib import ( DynamicQThread, @@ -94,6 +95,8 @@ def get_application_actions(self): if not project_doc: return actions + project_settings = get_project_settings(project_name) + only_available = project_settings["applications"]["only_available"] self.application_manager.refresh() for app_def in project_doc["config"]["apps"]: app_name = app_def["name"] @@ -104,6 +107,9 @@ def get_application_actions(self): if app.group.name in CUSTOM_LAUNCH_APP_GROUPS: continue + if only_available and not app.find_executable(): + continue + # Get from app definition, if not there from app in project action = type( "app_{}".format(app_name), diff --git a/openpype/tools/loader/widgets.py b/openpype/tools/loader/widgets.py index 98ac9c871fe..b3aa381d145 100644 --- a/openpype/tools/loader/widgets.py +++ b/openpype/tools/loader/widgets.py @@ -295,10 +295,10 @@ def set_grouping(self, state): self.model.set_grouping(state) def _subset_changed(self, text): - if hasattr(self.proxy, "setFilterRegularExpression"): - self.proxy.setFilterRegularExpression(text) - else: + if hasattr(self.proxy, "setFilterRegExp"): self.proxy.setFilterRegExp(text) + else: + self.proxy.setFilterRegularExpression(text) self.view.expandAll() def set_loading_state(self, loading, empty): diff --git a/openpype/tools/project_manager/project_manager/view.py b/openpype/tools/project_manager/project_manager/view.py index b35491c5b21..2cf11b702d8 100644 --- a/openpype/tools/project_manager/project_manager/view.py +++ b/openpype/tools/project_manager/project_manager/view.py @@ -72,8 +72,8 @@ class HierarchyView(QtWidgets.QTreeView): column_delegate_defs = { "name": NameDef(), "type": TypeDef(), - "frameStart": NumberDef(1), - "frameEnd": NumberDef(1), + "frameStart": NumberDef(0), + "frameEnd": NumberDef(0), "fps": NumberDef(1, decimals=3, step=1), "resolutionWidth": NumberDef(0), "resolutionHeight": NumberDef(0), diff --git a/openpype/tools/publisher/constants.py b/openpype/tools/publisher/constants.py index b2bfd7dd5cd..5d23886aa81 100644 --- a/openpype/tools/publisher/constants.py +++ b/openpype/tools/publisher/constants.py @@ -1,4 +1,4 @@ -from qtpy import QtCore +from qtpy import QtCore, QtGui # ID of context item in instance view CONTEXT_ID = "context" @@ -26,6 +26,9 @@ CONVERTER_IDENTIFIER_ROLE = QtCore.Qt.UserRole + 8 CREATOR_SORT_ROLE = QtCore.Qt.UserRole + 9 +ResetKeySequence = QtGui.QKeySequence( + QtCore.Qt.ControlModifier | QtCore.Qt.Key_R +) __all__ = ( "CONTEXT_ID", diff --git a/openpype/tools/publisher/control.py b/openpype/tools/publisher/control.py index 49e7eeb4f7f..b62ae7ecc15 100644 --- a/openpype/tools/publisher/control.py +++ b/openpype/tools/publisher/control.py @@ -6,7 +6,7 @@ import uuid import tempfile import shutil -from abc import ABCMeta, abstractmethod, abstractproperty +from abc import ABCMeta, abstractmethod import six import pyblish.api @@ -964,7 +964,8 @@ class AbstractPublisherController(object): access objects directly but by using wrappers that can be serialized. """ - @abstractproperty + @property + @abstractmethod def log(self): """Controller's logger object. @@ -974,13 +975,15 @@ def log(self): pass - @abstractproperty + @property + @abstractmethod def event_system(self): """Inner event system for publisher controller.""" pass - @abstractproperty + @property + @abstractmethod def project_name(self): """Current context project name. @@ -990,7 +993,8 @@ def project_name(self): pass - @abstractproperty + @property + @abstractmethod def current_asset_name(self): """Current context asset name. @@ -1000,7 +1004,8 @@ def current_asset_name(self): pass - @abstractproperty + @property + @abstractmethod def current_task_name(self): """Current context task name. @@ -1010,7 +1015,21 @@ def current_task_name(self): pass - @abstractproperty + @property + @abstractmethod + def host_context_has_changed(self): + """Host context changed after last reset. + + 'CreateContext' has this option available using 'context_has_changed'. + + Returns: + bool: Context has changed. + """ + + pass + + @property + @abstractmethod def host_is_valid(self): """Host is valid for creation part. @@ -1023,7 +1042,8 @@ def host_is_valid(self): pass - @abstractproperty + @property + @abstractmethod def instances(self): """Collected/created instances. @@ -1134,7 +1154,13 @@ def create( @abstractmethod def save_changes(self): - """Save changes in create context.""" + """Save changes in create context. + + Save can crash because of unexpected errors. + + Returns: + bool: Save was successful. + """ pass @@ -1145,7 +1171,19 @@ def remove_instances(self, instance_ids): pass - @abstractproperty + @property + @abstractmethod + def publish_has_started(self): + """Has publishing finished. + + Returns: + bool: If publishing finished and all plugins were iterated. + """ + + pass + + @property + @abstractmethod def publish_has_finished(self): """Has publishing finished. @@ -1155,7 +1193,8 @@ def publish_has_finished(self): pass - @abstractproperty + @property + @abstractmethod def publish_is_running(self): """Publishing is running right now. @@ -1165,7 +1204,8 @@ def publish_is_running(self): pass - @abstractproperty + @property + @abstractmethod def publish_has_validated(self): """Publish validation passed. @@ -1175,7 +1215,8 @@ def publish_has_validated(self): pass - @abstractproperty + @property + @abstractmethod def publish_has_crashed(self): """Publishing crashed for any reason. @@ -1185,7 +1226,8 @@ def publish_has_crashed(self): pass - @abstractproperty + @property + @abstractmethod def publish_has_validation_errors(self): """During validation happened at least one validation error. @@ -1195,7 +1237,8 @@ def publish_has_validation_errors(self): pass - @abstractproperty + @property + @abstractmethod def publish_max_progress(self): """Get maximum possible progress number. @@ -1205,7 +1248,8 @@ def publish_max_progress(self): pass - @abstractproperty + @property + @abstractmethod def publish_progress(self): """Current progress number. @@ -1215,7 +1259,8 @@ def publish_progress(self): pass - @abstractproperty + @property + @abstractmethod def publish_error_msg(self): """Current error message which cause fail of publishing. @@ -1267,7 +1312,8 @@ def run_action(self, plugin_id, action_id): pass - @abstractproperty + @property + @abstractmethod def convertor_items(self): pass @@ -1356,6 +1402,7 @@ def __init__(self): self._publish_has_validation_errors = False self._publish_has_crashed = False # All publish plugins are processed + self._publish_has_started = False self._publish_has_finished = False self._publish_max_progress = 0 self._publish_progress = 0 @@ -1386,7 +1433,8 @@ def event_system(self): "show.card.message" - Show card message request (UI related). "instances.refresh.finished" - Instances are refreshed. "plugins.refresh.finished" - Plugins refreshed. - "publish.reset.finished" - Publish context reset finished. + "publish.reset.finished" - Reset finished. + "controller.reset.started" - Controller reset started. "controller.reset.finished" - Controller reset finished. "publish.process.started" - Publishing started. Can be started from paused state. @@ -1425,7 +1473,16 @@ def _get_host_is_valid(self): def _set_host_is_valid(self, value): if self._host_is_valid != value: self._host_is_valid = value - self._emit_event("publish.host_is_valid.changed", {"value": value}) + self._emit_event( + "publish.host_is_valid.changed", {"value": value} + ) + + def _get_publish_has_started(self): + return self._publish_has_started + + def _set_publish_has_started(self, value): + if value != self._publish_has_started: + self._publish_has_started = value def _get_publish_has_finished(self): return self._publish_has_finished @@ -1449,7 +1506,9 @@ def _get_publish_has_validated(self): def _set_publish_has_validated(self, value): if self._publish_has_validated != value: self._publish_has_validated = value - self._emit_event("publish.has_validated.changed", {"value": value}) + self._emit_event( + "publish.has_validated.changed", {"value": value} + ) def _get_publish_has_crashed(self): return self._publish_has_crashed @@ -1497,6 +1556,9 @@ def _set_publish_error_msg(self, value): host_is_valid = property( _get_host_is_valid, _set_host_is_valid ) + publish_has_started = property( + _get_publish_has_started, _set_publish_has_started + ) publish_has_finished = property( _get_publish_has_finished, _set_publish_has_finished ) @@ -1526,6 +1588,7 @@ def _reset_attributes(self): """Reset most of attributes that can be reset.""" self.publish_is_running = False + self.publish_has_started = False self.publish_has_validated = False self.publish_has_crashed = False self.publish_has_validation_errors = False @@ -1645,10 +1708,7 @@ def project_name(self): str: Project name. """ - if not hasattr(self._host, "get_current_context"): - return legacy_io.active_project() - - return self._host.get_current_context()["project_name"] + return self._create_context.get_current_project_name() @property def current_asset_name(self): @@ -1658,10 +1718,7 @@ def current_asset_name(self): Union[str, None]: Asset name or None if asset is not set. """ - if not hasattr(self._host, "get_current_context"): - return legacy_io.Session["AVALON_ASSET"] - - return self._host.get_current_context()["asset_name"] + return self._create_context.get_current_asset_name() @property def current_task_name(self): @@ -1671,10 +1728,11 @@ def current_task_name(self): Union[str, None]: Task name or None if task is not set. """ - if not hasattr(self._host, "get_current_context"): - return legacy_io.Session["AVALON_TASK"] + return self._create_context.get_current_task_name() - return self._host.get_current_context()["task_name"] + @property + def host_context_has_changed(self): + return self._create_context.context_has_changed @property def instances(self): @@ -1751,6 +1809,8 @@ def reset(self): """Reset everything related to creation and publishing.""" self.stop_publish() + self._emit_event("controller.reset.started") + self.host_is_valid = self._create_context.host_is_valid self._create_context.reset_preparation() @@ -1992,7 +2052,15 @@ def get_subset_name( ) def trigger_convertor_items(self, convertor_identifiers): - self.save_changes() + """Trigger legacy item convertors. + + This functionality requires to save and reset CreateContext. The reset + is needed so Creators can collect converted items. + + Args: + convertor_identifiers (list[str]): Identifiers of convertor + plugins. + """ success = True try: @@ -2039,13 +2107,33 @@ def create( self._on_create_instance_change() return success - def save_changes(self): - """Save changes happened during creation.""" + def save_changes(self, show_message=True): + """Save changes happened during creation. + + Trigger save of changes using host api. This functionality does not + validate anything. It is required to do checks before this method is + called to be able to give user actionable response e.g. check of + context using 'host_context_has_changed'. + + Args: + show_message (bool): Show message that changes were + saved successfully. + + Returns: + bool: Save of changes was successful. + """ + if not self._create_context.host_is_valid: - return + # TODO remove + # Fake success save when host is not valid for CreateContext + # this is for testing as experimental feature + return True try: self._create_context.save_changes() + if show_message: + self.emit_card_message("Saved changes..") + return True except CreatorsOperationFailed as exc: self._emit_event( @@ -2056,16 +2144,17 @@ def save_changes(self): } ) + return False + def remove_instances(self, instance_ids): """Remove instances based on instance ids. Args: instance_ids (List[str]): List of instance ids to remove. """ - # QUESTION Expect that instances are really removed? In that case save - # reset is not required and save changes too. - self.save_changes() + # QUESTION Expect that instances are really removed? In that case reset + # is not required. self._remove_instances_from_context(instance_ids) self._on_create_instance_change() @@ -2136,12 +2225,22 @@ def set_comment(self, comment): self._publish_comment_is_set = True def publish(self): - """Run publishing.""" + """Run publishing. + + Make sure all changes are saved before method is called (Call + 'save_changes' and check output). + """ + self._publish_up_validation = False self._start_publish() def validate(self): - """Run publishing and stop after Validation.""" + """Run publishing and stop after Validation. + + Make sure all changes are saved before method is called (Call + 'save_changes' and check output). + """ + if self.publish_has_validated: return self._publish_up_validation = True @@ -2152,10 +2251,8 @@ def _start_publish(self): if self.publish_is_running: return - # Make sure changes are saved - self.save_changes() - self.publish_is_running = True + self.publish_has_started = True self._emit_event("publish.process.started") diff --git a/openpype/tools/publisher/widgets/__init__.py b/openpype/tools/publisher/widgets/__init__.py index 042985b007e..f18e6cc61e0 100644 --- a/openpype/tools/publisher/widgets/__init__.py +++ b/openpype/tools/publisher/widgets/__init__.py @@ -4,8 +4,9 @@ get_icon ) from .widgets import ( - StopBtn, + SaveBtn, ResetBtn, + StopBtn, ValidateBtn, PublishBtn, CreateNextPageOverlay, @@ -25,8 +26,9 @@ "get_pixmap", "get_icon", - "StopBtn", + "SaveBtn", "ResetBtn", + "StopBtn", "ValidateBtn", "PublishBtn", "CreateNextPageOverlay", diff --git a/openpype/tools/publisher/widgets/card_view_widgets.py b/openpype/tools/publisher/widgets/card_view_widgets.py index 3fd5243ce94..0734e1bc274 100644 --- a/openpype/tools/publisher/widgets/card_view_widgets.py +++ b/openpype/tools/publisher/widgets/card_view_widgets.py @@ -164,6 +164,11 @@ def _update_ordered_item_ids(self): def _on_widget_selection(self, instance_id, group_id, selection_type): self.selected.emit(instance_id, group_id, selection_type) + def set_active_toggle_enabled(self, enabled): + for widget in self._widgets_by_id.values(): + if isinstance(widget, InstanceCardWidget): + widget.set_active_toggle_enabled(enabled) + class ConvertorItemsGroupWidget(BaseGroupWidget): def update_items(self, items_by_id): @@ -437,6 +442,9 @@ def __init__(self, instance, group_icon, parent): self.update_instance_values() + def set_active_toggle_enabled(self, enabled): + self._active_checkbox.setEnabled(enabled) + def set_active(self, new_value): """Set instance as active.""" checkbox_value = self._active_checkbox.isChecked() @@ -551,6 +559,7 @@ def __init__(self, controller, parent): self._context_widget = None self._convertor_items_group = None + self._active_toggle_enabled = True self._widgets_by_group = {} self._ordered_groups = [] @@ -667,6 +676,9 @@ def refresh(self): group_widget.update_instances( instances_by_group[group_name] ) + group_widget.set_active_toggle_enabled( + self._active_toggle_enabled + ) self._update_ordered_group_names() @@ -1091,3 +1103,10 @@ def set_selected_items( self._explicitly_selected_groups = selected_groups self._explicitly_selected_instance_ids = selected_instances + + def set_active_toggle_enabled(self, enabled): + if self._active_toggle_enabled is enabled: + return + self._active_toggle_enabled = enabled + for group_widget in self._widgets_by_group.values(): + group_widget.set_active_toggle_enabled(enabled) diff --git a/openpype/tools/publisher/widgets/images/save.png b/openpype/tools/publisher/widgets/images/save.png new file mode 100644 index 0000000000000000000000000000000000000000..0db48d74ae2660e8766fc2bcd30ed794fd067068 GIT binary patch literal 3961 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 0: dialog_x -= diff @@ -549,6 +635,14 @@ def _on_context_or_active_change(self): def _on_create_request(self): self._go_to_create_tab() + def _on_convert_requested(self): + if not self._save_changes(False): + return + convertor_identifiers = ( + self._overview_widget.get_selected_legacy_convertors() + ) + self._controller.trigger_convertor_items(convertor_identifiers) + def _set_current_tab(self, identifier): self._tabs_widget.set_current_tab(identifier) @@ -599,8 +693,10 @@ def _set_publish_visibility(self, visible): self._publish_frame.setVisible(visible) self._update_publish_frame_rect() + def _on_save_clicked(self): + self._save_changes(True) + def _on_reset_clicked(self): - self.save_changes() self.reset() def _on_stop_clicked(self): @@ -610,14 +706,17 @@ def _set_publish_comment(self): self._controller.set_comment(self._comment_input.text()) def _on_validate_clicked(self): - self._set_publish_comment() - self._controller.validate() + if self._save_changes(False): + self._set_publish_comment() + self._controller.validate() def _on_publish_clicked(self): - self._set_publish_comment() - self._controller.publish() + if self._save_changes(False): + self._set_publish_comment() + self._controller.publish() def _set_footer_enabled(self, enabled): + self._save_btn.setEnabled(True) self._reset_btn.setEnabled(True) if enabled: self._stop_btn.setEnabled(False) diff --git a/openpype/tools/sceneinventory/model.py b/openpype/tools/sceneinventory/model.py index 3398743aec5..63d29451457 100644 --- a/openpype/tools/sceneinventory/model.py +++ b/openpype/tools/sceneinventory/model.py @@ -327,7 +327,7 @@ def add_items(self, items, parent=None): project_name, repre_id ) if not representation: - not_found["representation"].append(group_items) + not_found["representation"].extend(group_items) not_found_ids.append(repre_id) continue @@ -335,7 +335,7 @@ def add_items(self, items, parent=None): project_name, representation["parent"] ) if not version: - not_found["version"].append(group_items) + not_found["version"].extend(group_items) not_found_ids.append(repre_id) continue @@ -348,13 +348,13 @@ def add_items(self, items, parent=None): subset = get_subset_by_id(project_name, version["parent"]) if not subset: - not_found["subset"].append(group_items) + not_found["subset"].extend(group_items) not_found_ids.append(repre_id) continue asset = get_asset_by_id(project_name, subset["parent"]) if not asset: - not_found["asset"].append(group_items) + not_found["asset"].extend(group_items) not_found_ids.append(repre_id) continue @@ -380,11 +380,11 @@ def add_items(self, items, parent=None): self.add_child(group_node, parent=parent) - for _group_items in group_items: + for item in group_items: item_node = Item() - item_node["Name"] = ", ".join( - [item["objectName"] for item in _group_items] - ) + item_node.update(item) + item_node["Name"] = item.get("objectName", "NO NAME") + item_node["isNotFound"] = True self.add_child(item_node, parent=group_node) for repre_id, group_dict in sorted(grouped.items()): @@ -482,10 +482,10 @@ def filterAcceptsRow(self, row, parent): return True # Filter by regex - if hasattr(self, "filterRegularExpression"): - regex = self.filterRegularExpression() - else: + if hasattr(self, "filterRegExp"): regex = self.filterRegExp() + else: + regex = self.filterRegularExpression() pattern = regex.pattern() if pattern: pattern = re.escape(pattern) diff --git a/openpype/tools/sceneinventory/view.py b/openpype/tools/sceneinventory/view.py index a04171e4292..3279be6094d 100644 --- a/openpype/tools/sceneinventory/view.py +++ b/openpype/tools/sceneinventory/view.py @@ -80,9 +80,16 @@ def _leave_hierarchy(self): self.setStyleSheet("QTreeView {}") def _build_item_menu_for_selection(self, items, menu): + + # Exclude items that are "NOT FOUND" since setting versions, updating + # and removal won't work for those items. + items = [item for item in items if not item.get("isNotFound")] + if not items: return + # An item might not have a representation, for example when an item + # is listed as "NOT FOUND" repre_ids = { item["representation"] for item in items diff --git a/openpype/tools/sceneinventory/window.py b/openpype/tools/sceneinventory/window.py index 8a6e43f796b..89424fd746d 100644 --- a/openpype/tools/sceneinventory/window.py +++ b/openpype/tools/sceneinventory/window.py @@ -160,10 +160,10 @@ def _on_hierarchy_view_change(self, enabled): self._model.set_hierarchy_view(enabled) def _on_text_filter_change(self, text_filter): - if hasattr(self._proxy, "setFilterRegularExpression"): - self._proxy.setFilterRegularExpression(text_filter) - else: + if hasattr(self._proxy, "setFilterRegExp"): self._proxy.setFilterRegExp(text_filter) + else: + self._proxy.setFilterRegularExpression(text_filter) def _on_outdated_state_change(self): self._proxy.set_filter_outdated( diff --git a/openpype/tools/settings/local_settings/projects_widget.py b/openpype/tools/settings/local_settings/projects_widget.py index bdf291524c0..4a4148d7cd7 100644 --- a/openpype/tools/settings/local_settings/projects_widget.py +++ b/openpype/tools/settings/local_settings/projects_widget.py @@ -272,7 +272,7 @@ def _get_sites_inputs(self): ) site_configs = sync_server_module.get_all_site_configs( - self._project_name) + self._project_name, local_editable_only=True) roots_entity = ( self.project_settings[PROJECT_ANATOMY_KEY][LOCAL_ROOTS_KEY] diff --git a/openpype/tools/settings/settings/search_dialog.py b/openpype/tools/settings/settings/search_dialog.py index 33a4d16e982..59750c02e19 100644 --- a/openpype/tools/settings/settings/search_dialog.py +++ b/openpype/tools/settings/settings/search_dialog.py @@ -27,10 +27,10 @@ def filterAcceptsRow(self, row, parent): if not parent.isValid(): return False - if hasattr(self, "filterRegularExpression"): - regex = self.filterRegularExpression() - else: + if hasattr(self, "filterRegExp"): regex = self.filterRegExp() + else: + regex = self.filterRegularExpression() pattern = regex.pattern() if pattern and regex.isValid(): @@ -111,10 +111,10 @@ def _on_filter_changed(self, txt): def _on_filter_timer(self): text = self._filter_edit.text() - if hasattr(self._proxy, "setFilterRegularExpression"): - self._proxy.setFilterRegularExpression(text) - else: + if hasattr(self._proxy, "setFilterRegExp"): self._proxy.setFilterRegExp(text) + else: + self._proxy.setFilterRegularExpression(text) # WARNING This expanding and resizing is relatively slow. self._view.expandAll() diff --git a/openpype/tools/standalonepublish/widgets/model_filter_proxy_recursive_sort.py b/openpype/tools/standalonepublish/widgets/model_filter_proxy_recursive_sort.py index 5c72e2049b9..602faaa489a 100644 --- a/openpype/tools/standalonepublish/widgets/model_filter_proxy_recursive_sort.py +++ b/openpype/tools/standalonepublish/widgets/model_filter_proxy_recursive_sort.py @@ -5,10 +5,10 @@ class RecursiveSortFilterProxyModel(QtCore.QSortFilterProxyModel): """Filters to the regex if any of the children matches allow parent""" def filterAcceptsRow(self, row, parent): - if hasattr(self, "filterRegularExpression"): - regex = self.filterRegularExpression() - else: + if hasattr(self, "filterRegExp"): regex = self.filterRegExp() + else: + regex = self.filterRegularExpression() pattern = regex.pattern() if pattern: model = self.sourceModel() diff --git a/openpype/tools/traypublisher/window.py b/openpype/tools/traypublisher/window.py index 3007fa66a51..3ac1b4c4adf 100644 --- a/openpype/tools/traypublisher/window.py +++ b/openpype/tools/traypublisher/window.py @@ -247,7 +247,7 @@ def resizeEvent(self, event): def _on_project_select(self, project_name): # TODO register project specific plugin paths - self._controller.save_changes() + self._controller.save_changes(False) self._controller.reset_project_data_cache() self.reset() diff --git a/openpype/tools/utils/delegates.py b/openpype/tools/utils/delegates.py index d76284afb1a..fa69113ef1d 100644 --- a/openpype/tools/utils/delegates.py +++ b/openpype/tools/utils/delegates.py @@ -30,9 +30,11 @@ def __init__(self, dbcon, *args, **kwargs): def displayText(self, value, locale): if isinstance(value, HeroVersionType): return lib.format_version(value, True) - assert isinstance(value, numbers.Integral), ( - "Version is not integer. \"{}\" {}".format(value, str(type(value))) - ) + if not isinstance(value, numbers.Integral): + # For cases where no version is resolved like NOT FOUND cases + # where a representation might not exist in current database + return + return lib.format_version(value) def paint(self, painter, option, index): diff --git a/openpype/tools/utils/host_tools.py b/openpype/tools/utils/host_tools.py index e8593a8ae2a..ac242d24d21 100644 --- a/openpype/tools/utils/host_tools.py +++ b/openpype/tools/utils/host_tools.py @@ -38,7 +38,6 @@ def __init__(self, parent=None): self._subset_manager_tool = None self._scene_inventory_tool = None self._library_loader_tool = None - self._look_assigner_tool = None self._experimental_tools_dialog = None @property @@ -219,27 +218,6 @@ def _discover_pyblish_gui(self): raise ImportError("No Pyblish GUI found") - def get_look_assigner_tool(self, parent): - """Create, cache and return look assigner tool window.""" - if self._look_assigner_tool is None: - from openpype.tools.mayalookassigner import MayaLookAssignerWindow - - mayalookassigner_window = MayaLookAssignerWindow(parent) - self._look_assigner_tool = mayalookassigner_window - return self._look_assigner_tool - - def show_look_assigner(self, parent=None): - """Look manager is Maya specific tool for look management.""" - - with qt_app_context(): - look_assigner_tool = self.get_look_assigner_tool(parent) - look_assigner_tool.show() - - # Pull window to the front. - look_assigner_tool.raise_() - look_assigner_tool.activateWindow() - look_assigner_tool.showNormal() - def get_experimental_tools_dialog(self, parent=None): """Dialog of experimental tools. @@ -315,9 +293,6 @@ def get_tool_by_name(self, tool_name, parent=None, *args, **kwargs): elif tool_name == "sceneinventory": return self.get_scene_inventory_tool(parent, *args, **kwargs) - elif tool_name == "lookassigner": - return self.get_look_assigner_tool(parent, *args, **kwargs) - elif tool_name == "publish": self.log.info("Can't return publish tool window.") @@ -356,9 +331,6 @@ def show_tool_by_name(self, tool_name, parent=None, *args, **kwargs): elif tool_name == "sceneinventory": self.show_scene_inventory(parent, *args, **kwargs) - elif tool_name == "lookassigner": - self.show_look_assigner(parent, *args, **kwargs) - elif tool_name == "publish": self.show_publish(parent, *args, **kwargs) @@ -436,10 +408,6 @@ def show_scene_inventory(parent=None): _SingletonPoint.show_tool_by_name("sceneinventory", parent) -def show_look_assigner(parent=None): - _SingletonPoint.show_tool_by_name("lookassigner", parent) - - def show_publish(parent=None): _SingletonPoint.show_tool_by_name("publish", parent) diff --git a/openpype/tools/utils/lib.py b/openpype/tools/utils/lib.py index 8d38f03b8d9..950c782727b 100644 --- a/openpype/tools/utils/lib.py +++ b/openpype/tools/utils/lib.py @@ -862,11 +862,11 @@ def result(self): return self._result def execute(self): - """Execute callback and store it's result. + """Execute callback and store its result. Method must be called from main thread. Item is marked as `done` when callback execution finished. Store output of callback of exception - information when callback raise one. + information when callback raises one. """ if self.done: self.log.warning("- item is already processed") diff --git a/openpype/tools/utils/models.py b/openpype/tools/utils/models.py index 270e00b2ef8..94645af110b 100644 --- a/openpype/tools/utils/models.py +++ b/openpype/tools/utils/models.py @@ -202,11 +202,20 @@ class RecursiveSortFilterProxyModel(QtCore.QSortFilterProxyModel): Use case: Filtering by string - parent won't be filtered if does not match the filter string but first checks if any children does. """ + + def __init__(self, *args, **kwargs): + super(RecursiveSortFilterProxyModel, self).__init__(*args, **kwargs) + recursive_enabled = False + if hasattr(self, "setRecursiveFilteringEnabled"): + self.setRecursiveFilteringEnabled(True) + recursive_enabled = True + self._recursive_enabled = recursive_enabled + def filterAcceptsRow(self, row, parent_index): - if hasattr(self, "filterRegularExpression"): - regex = self.filterRegularExpression() - else: + if hasattr(self, "filterRegExp"): regex = self.filterRegExp() + else: + regex = self.filterRegularExpression() pattern = regex.pattern() if pattern: @@ -219,8 +228,9 @@ def filterAcceptsRow(self, row, parent_index): # Check current index itself value = model.data(source_index, self.filterRole()) - if re.search(pattern, value, re.IGNORECASE): - return True + matched = bool(re.search(pattern, value, re.IGNORECASE)) + if matched or self._recursive_enabled: + return matched rows = model.rowCount(source_index) for idx in range(rows): diff --git a/openpype/version.py b/openpype/version.py index e8124f14663..4d6ee5590e3 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.15.2-nightly.6" +__version__ = "3.15.4-nightly.1" diff --git a/openpype/widgets/splash_screen.py b/openpype/widgets/splash_screen.py index fffe143ea5a..7c1ff72ecd3 100644 --- a/openpype/widgets/splash_screen.py +++ b/openpype/widgets/splash_screen.py @@ -49,9 +49,7 @@ def __init__(self, self.init_ui() def was_proc_successful(self) -> bool: - if self.thread_return_code == 0: - return True - return False + return self.thread_return_code == 0 def start_thread(self, q_thread: QtCore.QThread): """Saves the reference to this thread and starts it. @@ -80,8 +78,14 @@ def quit_and_close(self): """ self.thread_return_code = 0 self.q_thread.quit() + + if not self.q_thread.wait(5000): + raise RuntimeError("Failed to quit the QThread! " + "The deadline has been reached! The thread " + "has not finished it's execution!.") self.close() + @QtCore.Slot() def toggle_log(self): if self.is_log_visible: @@ -256,3 +260,4 @@ def fail(self, text: str, return_code: int = 1): self.close_btn.show() self.thread_return_code = return_code self.q_thread.exit(return_code) + self.q_thread.wait() diff --git a/pyproject.toml b/pyproject.toml index 2fc4f6fe390..42ce5aa32c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "OpenPype" -version = "3.15.1" # OpenPype +version = "3.15.3" # OpenPype description = "Open VFX and Animation pipeline with support." authors = ["OpenPype Team "] license = "MIT License" diff --git a/tests/conftest.py b/tests/conftest.py index 7b58b0314dd..4f7c17244b3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -24,6 +24,11 @@ def pytest_addoption(parser): help="Overwrite default timeout" ) + parser.addoption( + "--setup_only", action="store", default=None, + help="True - only setup test, do not run any tests" + ) + @pytest.fixture(scope="module") def test_data_folder(request): @@ -45,6 +50,11 @@ def timeout(request): return request.config.getoption("--timeout") +@pytest.fixture(scope="module") +def setup_only(request): + return request.config.getoption("--setup_only") + + @pytest.hookimpl(tryfirst=True, hookwrapper=True) def pytest_runtest_makereport(item, call): # execute all other hooks to obtain the report object diff --git a/tests/integration/hosts/nuke/test_deadline_publish_in_nuke.py b/tests/integration/hosts/nuke/test_deadline_publish_in_nuke.py index cd9cbb94f89..a4026f195b0 100644 --- a/tests/integration/hosts/nuke/test_deadline_publish_in_nuke.py +++ b/tests/integration/hosts/nuke/test_deadline_publish_in_nuke.py @@ -71,12 +71,30 @@ def test_db_asserts(self, dbcon, publish_finished): failures.append( DBAssert.count_of_types(dbcon, "representation", 4)) + additional_args = {"context.subset": "workfileTest_task", + "context.ext": "nk"} + failures.append( + DBAssert.count_of_types(dbcon, "representation", 1, + additional_args=additional_args)) + additional_args = {"context.subset": "renderTest_taskMain", "context.ext": "exr"} failures.append( DBAssert.count_of_types(dbcon, "representation", 1, additional_args=additional_args)) + additional_args = {"context.subset": "renderTest_taskMain", + "name": "thumbnail"} + failures.append( + DBAssert.count_of_types(dbcon, "representation", 1, + additional_args=additional_args)) + + additional_args = {"context.subset": "renderTest_taskMain", + "name": "h264_mov"} + failures.append( + DBAssert.count_of_types(dbcon, "representation", 1, + additional_args=additional_args)) + assert not any(failures) diff --git a/tests/integration/hosts/nuke/test_publish_in_nuke.py b/tests/integration/hosts/nuke/test_publish_in_nuke.py index f84f13fa20d..bfd84e4fd57 100644 --- a/tests/integration/hosts/nuke/test_publish_in_nuke.py +++ b/tests/integration/hosts/nuke/test_publish_in_nuke.py @@ -15,7 +15,7 @@ class TestPublishInNuke(NukeLocalPublishTestClass): !!! It expects modified path in WriteNode, use '[python {nuke.script_directory()}]' instead of regular root - dir (eg. instead of `c:/projects/test_project/test_asset/test_task`). + dir (eg. instead of `c:/projects`). Access file path by selecting WriteNode group, CTRL+Enter, update file input !!! @@ -70,12 +70,30 @@ def test_db_asserts(self, dbcon, publish_finished): failures.append( DBAssert.count_of_types(dbcon, "representation", 4)) + additional_args = {"context.subset": "workfileTest_task", + "context.ext": "nk"} + failures.append( + DBAssert.count_of_types(dbcon, "representation", 1, + additional_args=additional_args)) + additional_args = {"context.subset": "renderTest_taskMain", "context.ext": "exr"} failures.append( DBAssert.count_of_types(dbcon, "representation", 1, additional_args=additional_args)) + additional_args = {"context.subset": "renderTest_taskMain", + "name": "thumbnail"} + failures.append( + DBAssert.count_of_types(dbcon, "representation", 1, + additional_args=additional_args)) + + additional_args = {"context.subset": "renderTest_taskMain", + "name": "h264_mov"} + failures.append( + DBAssert.count_of_types(dbcon, "representation", 1, + additional_args=additional_args)) + assert not any(failures) diff --git a/tests/lib/testing_classes.py b/tests/lib/testing_classes.py index 2bafa169714..300024dc984 100644 --- a/tests/lib/testing_classes.py +++ b/tests/lib/testing_classes.py @@ -243,6 +243,8 @@ class PublishTest(ModuleUnitTest): PERSIST = True # True - keep test_db, test_openpype, outputted test files TEST_DATA_FOLDER = None # use specific folder of unzipped test file + SETUP_ONLY = False + @pytest.fixture(scope="module") def app_name(self, app_variant): """Returns calculated value for ApplicationManager. Eg.(nuke/12-2)""" @@ -286,8 +288,13 @@ def app_args(self, download_test_data): @pytest.fixture(scope="module") def launched_app(self, dbcon, download_test_data, last_workfile_path, - startup_scripts, app_args, app_name, output_folder_url): + startup_scripts, app_args, app_name, output_folder_url, + setup_only): """Launch host app""" + if setup_only or self.SETUP_ONLY: + print("Creating only setup for test, not launching app") + yield + return # set schema - for integrate_new from openpype import PACKAGE_DIR # Path to OpenPype's schema @@ -316,8 +323,12 @@ def launched_app(self, dbcon, download_test_data, last_workfile_path, @pytest.fixture(scope="module") def publish_finished(self, dbcon, launched_app, download_test_data, - timeout): + timeout, setup_only): """Dummy fixture waiting for publish to finish""" + if setup_only or self.SETUP_ONLY: + print("Creating only setup for test, not launching app") + yield False + return import time time_start = time.time() timeout = timeout or self.TIMEOUT @@ -334,11 +345,16 @@ def publish_finished(self, dbcon, launched_app, download_test_data, def test_folder_structure_same(self, dbcon, publish_finished, download_test_data, output_folder_url, - skip_compare_folders): + skip_compare_folders, + setup_only): """Check if expected and published subfolders contain same files. Compares only presence, not size nor content! """ + if setup_only or self.SETUP_ONLY: + print("Creating only setup for test, not launching app") + return + published_dir_base = output_folder_url expected_dir_base = os.path.join(download_test_data, "expected") diff --git a/tests/unit/openpype/pipeline/publish/test_publish_plugins.py b/tests/unit/openpype/pipeline/publish/test_publish_plugins.py index 5c2d7b367f6..88e0095e340 100644 --- a/tests/unit/openpype/pipeline/publish/test_publish_plugins.py +++ b/tests/unit/openpype/pipeline/publish/test_publish_plugins.py @@ -135,7 +135,7 @@ def test_get_colorspace_settings(self, context, config_path_asset): } # load plugin function for testing - plugin = publish_plugins.ExtractorColormanaged() + plugin = publish_plugins.ColormanagedPyblishPluginMixin() plugin.log = log config_data, file_rules = plugin.get_colorspace_settings(context) @@ -175,14 +175,14 @@ def test_set_representation_colorspace( } # load plugin function for testing - plugin = publish_plugins.ExtractorColormanaged() + plugin = publish_plugins.ColormanagedPyblishPluginMixin() plugin.log = log plugin.set_representation_colorspace( representation_nuke, context, colorspace_settings=(config_data_nuke, file_rules_nuke) ) # load plugin function for testing - plugin = publish_plugins.ExtractorColormanaged() + plugin = publish_plugins.ColormanagedPyblishPluginMixin() plugin.log = log plugin.set_representation_colorspace( representation_hiero, context, diff --git a/website/docs/admin_environment.md b/website/docs/admin_environment.md index 1eb755b90b7..29b70a6c47a 100644 --- a/website/docs/admin_environment.md +++ b/website/docs/admin_environment.md @@ -27,4 +27,4 @@ import TabItem from '@theme/TabItem'; - for more details on how to use it go [here](admin_use#check-for-mongodb-database-connection) ## OPENPYPE_USERNAME -- if set it overides system created username +- if set it overrides system created username diff --git a/website/docs/admin_hosts_maya.md b/website/docs/admin_hosts_maya.md index 0e77f29fc20..68b402c5e06 100644 --- a/website/docs/admin_hosts_maya.md +++ b/website/docs/admin_hosts_maya.md @@ -6,13 +6,13 @@ sidebar_label: Maya ## Publish Plugins -### Render Settings Validator +### Render Settings Validator `ValidateRenderSettings` Render Settings Validator is here to make sure artists will submit renders -we correct settings. Some of these settings are needed by OpenPype but some -can be defined by TD using [OpenPype Settings UI](admin_settings.md). +with the correct settings. Some of these settings are needed by OpenPype but some +can be defined by the admin using [OpenPype Settings UI](admin_settings.md). OpenPype enforced settings include: @@ -36,10 +36,9 @@ For **Renderman**: For **Arnold**: - there shouldn't be `` token when merge AOVs option is turned on - Additional check can be added via Settings - **Project Settings > Maya > Publish plugin > ValidateRenderSettings**. You can add as many options as you want for every supported renderer. In first field put node type and attribute -and in the second required value. +and in the second required value. You can create multiple values for an attribute, but when repairing it'll be the first value in the list that get selected. ![Settings example](assets/maya-admin_render_settings_validator.png) @@ -51,7 +50,11 @@ just one instance of this node type but if that is not so, validator will go thr instances and check the value there. Node type for **VRay** settings is `VRaySettingsNode`, for **Renderman** it is `rmanGlobals`, for **Redshift** it is `RedshiftOptions`. -### Model Name Validator +:::info getting attribute values +If you do not know what an attributes value is supposed to be, for example for dropdown menu (enum), try changing the attribute and look in the script editor where it should log what the attribute was set to. +::: + +### Model Name Validator `ValidateRenderSettings` @@ -95,7 +98,7 @@ You can set various aspects of scene submission to farm with per-project setting - **Optional** will mark sumission plugin optional - **Active** will enable/disable plugin - - **Tile Assembler Plugin** will set what should be used to assemble tiles on Deadline. Either **Open Image IO** will be used + - **Tile Assembler Plugin** will set what should be used to assemble tiles on Deadline. Either **Open Image IO** will be used or Deadlines **Draft Tile Assembler**. - **Use Published scene** enable to render from published scene instead of scene in work area. Rendering from published files is much safer. - **Use Asset dependencies** will mark job pending on farm until asset dependencies are fulfilled - for example Deadline will wait for scene file to be synced to cloud, etc. @@ -107,6 +110,41 @@ or Deadlines **Draft Tile Assembler**. This is useful to fix some specific renderer glitches and advanced hacking of Maya Scene files. `Patch name` is label for patch for easier orientation. `Patch regex` is regex used to find line in file, after `Patch line` string is inserted. Note that you need to add line ending. +### Extract Playblast Settings (review) +These settings provide granular control over how the playblasts or reviews are produced in Maya. + +Some of these settings are also available on the instance itself, in which case these settings will become the default value when creating the review instance. + +![Extract Playblast Settings](assets/maya-admin_extract_playblast_settings.png) + +- **Compression type** which file encoding to use. +- **Data format** what format is the file encoding. +- **Quality** lets you control the compression value for the output. Results can vary depending on the compression you selected. Quality values can range from 0 to 100, with a default value of 95. +- **Background Color** the viewports background color. +- **Background Bottom** the viewports background bottom color. +- **Background Top** the viewports background top color. +- **Override display options** override the viewports display options to use what is set in the settings. +- **Isolate view** isolates the view to what is in the review instance. If only a camera is present in the review instance, all nodes are displayed in view. +- **Off Screen** records the playblast hidden from the user. +- **2D Pan/Zoom** enables the 2D Pan/Zoom functionality of the camera. +- **Renderer name** which renderer to use for playblasting. +- **Width** width of the output resolution. If this value is `0`, the asset's width is used. +- **Height** height of the output resolution. If this value is `0`, the asset's height is used. + +#### Viewport Options + +Most settings to override in the viewport are self explanatory and can be found in Maya. + +![Extract Playblast Settings](assets/maya-admin_extract_playblast_settings_viewport_options.png) + +- **Override Viewport Options** enable to use the settings below for the viewport when publishing the review. + +#### Camera Options + +These options are set on the camera shape when publishing the review. They correspond to attributes on the Maya camera shape node. + +![Extract Playblast Settings](assets/maya-admin_extract_playblast_settings_camera_options.png) + ## Custom Menu You can add your custom tools menu into Maya by extending definitions in **Maya -> Scripts Menu Definition**. ![Custom menu definition](assets/maya-admin_scriptsmenu.png) @@ -142,7 +180,7 @@ Fill in the necessary fields (the optional fields are regex filters) ![new place holder](assets/maya-placeholder_new.png) - - Builder type: Wether the the placeholder should load current asset representations or linked assets representations + - Builder type: Whether the the placeholder should load current asset representations or linked assets representations - Representation: Representation that will be loaded (ex: ma, abc, png, etc...) @@ -169,5 +207,3 @@ Fill in the necessary fields (the optional fields are regex filters) - Build your workfile ![maya build template](assets/maya-build_workfile_from_template.png) - - diff --git a/website/docs/admin_settings.md b/website/docs/admin_settings.md index 8626ef16ba5..1128cc00c69 100644 --- a/website/docs/admin_settings.md +++ b/website/docs/admin_settings.md @@ -7,12 +7,15 @@ sidebar_label: Working with settings import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -OpenPype stores all of it's settings and configuration in the mongo database. To make the configuration as easy as possible we provide a robust GUI where you can access and change everything that is configurable +OpenPype stores all of its settings and configuration in the mongo database. To make the configuration as easy as possible we provide a robust GUI where you can access and change everything that is configurable **Settings** GUI can be started from the tray menu *Admin -> Studio Settings*. -Please keep in mind that these settings are set-up for the full studio and not per-individual. If you're looking for individual artist settings, you can head to -[Local Settings](admin_settings_local.md) section in the artist documentation. +:::important Studio Settings versus Local Settings +Please keep in mind that these settings are set up for the full studio and not per-individual. If you're looking for individual artist settings, you can head to +[Local Settings](admin_settings_local.md) section in the documentation. +::: + ## Categories @@ -76,7 +79,7 @@ You can also reset any settings to OpenPype default by doing `right click` and ` Many settings are useful to be adjusted on a per-project basis. To identify project overrides, they are marked with **orange edge** and **orange labels** in the settings GUI. -The process of settting project overrides is similar to setting the Studio defaults. The key difference is to select a particular project you want to be configure. Those projects can be found on the left hand side of the Project Settings tab. +The process of setting project overrides is similar to setting the Studio defaults. The key difference is to select a particular project you want to be configure. Those projects can be found on the left hand side of the Project Settings tab. In the image below you can see all three overrides at the same time. 1. Deadline has **no changes to the OpenPype defaults** at all — **grey** colour of left bar. diff --git a/website/docs/admin_use.md b/website/docs/admin_use.md index c92ac3a77a2..c1d1de0e8cd 100644 --- a/website/docs/admin_use.md +++ b/website/docs/admin_use.md @@ -68,7 +68,7 @@ Add `--headless` to run OpenPype without graphical UI (useful on server or on au `--verbose` `` - change log verbose level of OpenPype loggers. -Level value can be integer in range `0-50` or one of enum strings `"notset" (0)`, `"debug" (10)`, `"info" (20)`, `"warning" (30)`, `"error" (40)`, `"ciritcal" (50)`. Value is stored to `OPENPYPE_LOG_LEVEL` environment variable for next processes. +Level value can be integer in range `0-50` or one of enum strings `"notset" (0)`, `"debug" (10)`, `"info" (20)`, `"warning" (30)`, `"error" (40)`, `"critical" (50)`. Value is stored to `OPENPYPE_LOG_LEVEL` environment variable for next processes. ```shell openpype_console --verbose debug diff --git a/website/docs/artist_hosts_3dsmax.md b/website/docs/artist_hosts_3dsmax.md index 71ba8785dcf..12c1f401815 100644 --- a/website/docs/artist_hosts_3dsmax.md +++ b/website/docs/artist_hosts_3dsmax.md @@ -47,7 +47,7 @@ This is the core functional area for you as a user. Most of your actions will ta ![Menu OpenPype](assets/3dsmax_menu_first_OP.png) :::note OpenPype Menu -User should use this menu exclusively for **Opening/Saving** when dealing with work files not standard ```File Menu``` even though user still being able perform file operations via this menu but prefferably just performing quick saves during work session not saving actual workfile versions. +User should use this menu exclusively for **Opening/Saving** when dealing with work files not standard ```File Menu``` even though user still being able perform file operations via this menu but preferably just performing quick saves during work session not saving actual workfile versions. ::: ## Working With Scene Files @@ -73,7 +73,7 @@ OpenPype correctly names it and add version to the workfile. This basically happ etc. -Basically meaning user is free of guessing what is the correct naming and other neccessities to keep everthing in order and managed. +Basically meaning user is free of guessing what is the correct naming and other necessities to keep everything in order and managed. > Note: user still has also other options for naming like ```Subversion```, ```Artist's Note``` but we won't dive into those now. diff --git a/website/docs/artist_hosts_aftereffects.md b/website/docs/artist_hosts_aftereffects.md index a9c9ca49fa4..939ef4034ca 100644 --- a/website/docs/artist_hosts_aftereffects.md +++ b/website/docs/artist_hosts_aftereffects.md @@ -34,7 +34,7 @@ a correct name. You should use it instead of standard file saving dialog. In AfterEffects you'll find the tools in the `OpenPype` extension: -![Extension](assets/photoshop_extension.PNG) +![Extension](assets/photoshop_extension.png) You can show the extension panel by going to `Window` > `Extensions` > `OpenPype`. @@ -104,7 +104,7 @@ There are currently 2 options of `render` item: When you want to load existing published work, you can use the `Loader` tool. You can reach it in the extension's panel. -![Loader](assets/photoshop_loader.PNG) +![Loader](assets/photoshop_loader.png) The supported families for loading into AfterEffects are: @@ -128,7 +128,7 @@ Now that we have some content loaded, you can manage which version is loaded. Th Loaded images have to stay as smart layers in order to be updated. If you rasterize the layer, you can no longer update it to a different version using OpenPype tools. ::: -![Loader](assets/photoshop_manage.PNG) +![Loader](assets/photoshop_manage.png) You can switch to a previous version of the image or update to the latest. diff --git a/website/docs/artist_hosts_harmony.md b/website/docs/artist_hosts_harmony.md index aa9355e2214..eaa6edc42aa 100644 --- a/website/docs/artist_hosts_harmony.md +++ b/website/docs/artist_hosts_harmony.md @@ -44,7 +44,7 @@ Because the saving to the network location happens in the background, be careful `OpenPype > Create` -![Creator](assets/harmony_creator.PNG) +![Creator](assets/harmony_creator.png) These are the families supported in Harmony: diff --git a/website/docs/artist_hosts_hiero.md b/website/docs/artist_hosts_hiero.md index 136ed6ea9c5..977c7a7baf8 100644 --- a/website/docs/artist_hosts_hiero.md +++ b/website/docs/artist_hosts_hiero.md @@ -231,14 +231,14 @@ All published instances that will replace the place holder must contain unique i ![Create menu](assets/nuke_publishedinstance.png) -The informations about these objects are given by the user by filling the extra attributes of the Place Holder +The information about these objects are given by the user by filling the extra attributes of the Place Holder ![Create menu](assets/nuke_fillingExtraAttributes.png) ### Update Place Holder -This tool alows the user to change the information provided in the extra attributes of the selected Place Holder. +This tool allows the user to change the information provided in the extra attributes of the selected Place Holder. ![Create menu](assets/nuke_updatePlaceHolder.png) @@ -250,7 +250,7 @@ This tool imports the template used and replaces the existed PlaceHolders with t ![Create menu](assets/nuke_buildWorfileFromTemplate.png) #### Result -- Replace `PLACEHOLDER` node in the template with the published instance corresponding to the informations provided in extra attributes of the Place Holder +- Replace `PLACEHOLDER` node in the template with the published instance corresponding to the information provided in extra attributes of the Place Holder ![Create menu](assets/nuke_buildworkfile.png) diff --git a/website/docs/artist_hosts_maya.md b/website/docs/artist_hosts_maya.md index 07495fbc967..0a551f02131 100644 --- a/website/docs/artist_hosts_maya.md +++ b/website/docs/artist_hosts_maya.md @@ -230,8 +230,8 @@ Maya settings concerning framerate, resolution and frame range are handled by OpenPype. If set correctly in Ftrack, Maya will validate you have correct fps on scene save and publishing offering way to fix it for you. -For resolution and frame range, use **OpenPype → Reset Frame Range** and -**OpenPype → Reset Resolution** +For resolution and frame range, use **OpenPype → Set Frame Range** and +**OpenPype → Set Resolution** ## Creating rigs with OpenPype @@ -386,7 +386,7 @@ Lets start with empty scene. First I'll pull in my favorite Buddha model. there just click on **Reference (abc)**. Next, I want to be sure that I have same frame range as is set on shot I am working -on. To do this just **OpenPype → Reset Frame Range**. This should set Maya timeline to same +on. To do this just **OpenPype → Set Frame Range**. This should set Maya timeline to same values as they are set on shot in *Ftrack* for example. I have my time set, so lets create some animation. We'll turn Buddha model around for @@ -500,7 +500,7 @@ and for vray: maya// ``` -Doing **OpenPype → Reset Resolution** will set correct resolution on camera. +Doing **OpenPype → Set Resolution** will set correct resolution on camera. Scene is now ready for submission and should publish without errors. @@ -516,6 +516,22 @@ In the scene from where you want to publish your model create *Render subset*. P model subset (Maya set node) under corresponding `LAYER_` set under *Render instance*. During publish, it will submit this render to farm and after it is rendered, it will be attached to your model subset. +### Tile Rendering +:::note Deadline +This feature is only supported when using Deadline. See [here](module_deadline#openpypetileassembler-plugin) for setup. +::: +On the render instance objectset you'll find: + +* `Tile Rendering` - for enabling tile rendering. +* `Tile X` - number of tiles in the X axis. +* `Tile Y` - number of tiles in the Y axis. + +When submittig to Deadline, you'll get: + +- for each frame a tile rendering job, to render each from Maya. +- for each frame a tile assembly job, to assemble the rendered tiles. +- job to publish the assembled frames. + ## Render Setups ### Publishing Render Setups diff --git a/website/docs/artist_hosts_maya_arnold.md b/website/docs/artist_hosts_maya_arnold.md index b3c02a08944..da16ba66c02 100644 --- a/website/docs/artist_hosts_maya_arnold.md +++ b/website/docs/artist_hosts_maya_arnold.md @@ -6,7 +6,7 @@ sidebar_label: Arnold ## Arnold Scene Source (.ass) Arnold Scene Source can be published as a single file or a sequence of files, determined by the frame range. -When creating the instance, two objectsets are created; `content` and `proxy`. Meshes in the `proxy` objectset will be the viewport representation when loading as `standin`. Proxy representations are stored as `resources` of the subset. +When creating the instance, two objectsets are created; `content` and `proxy`. Meshes in the `proxy` objectset will be the viewport representation when loading as `standin`. ### Arnold Scene Source Proxy Workflow In order to utilize operators and proxies, the content and proxy nodes need to share the same names (including the shape names). This is done by parenting the content and proxy nodes into separate groups. For example: diff --git a/website/docs/artist_hosts_maya_yeti.md b/website/docs/artist_hosts_maya_yeti.md index f5a6a4d2c95..aa783cc8b61 100644 --- a/website/docs/artist_hosts_maya_yeti.md +++ b/website/docs/artist_hosts_maya_yeti.md @@ -9,7 +9,9 @@ sidebar_label: Yeti OpenPype can work with [Yeti](https://peregrinelabs.com/yeti/) in two data modes. It can handle Yeti caches and Yeti rigs. -### Creating and publishing Yeti caches +## Yeti Caches + +### Creating and publishing Let start by creating simple Yeti setup, just one object and Yeti node. Open new empty scene in Maya and create sphere. Then select sphere and go **Yeti → Create Yeti Node on Mesh** @@ -44,7 +46,15 @@ You can now publish Yeti cache as any other types. **OpenPype → Publish**. It create sequence of `.fur` files and `.fursettings` metadata file with Yeti node setting. -### Loading Yeti caches +:::note Collect Yeti Cache failure +If you encounter **Collect Yeti Cache** failure during collecting phase, and the error is like +```fix +No object matches name: pgYetiMaya1Shape.cbId +``` +then it is probably caused by scene not being saved before publishing. +::: + +### Loading You can load Yeti cache by **OpenPype → Load ...**. Select your cache, right+click on it and select **Load Yeti cache**. This will create Yeti node in scene and set its @@ -52,26 +62,39 @@ cache path to point to your published cache files. Note that this Yeti node will be named with same name as the one you've used to publish cache. Also notice that when you open graph on this Yeti node, all nodes are as they were in publishing node. -### Creating and publishing Yeti Rig +## Yeti Rigs + +### Creating and publishing + +Yeti Rigs are designed to connect to published models or animation rig. The workflow gives the Yeti Rig full control on that geometry to do additional things on top of whatever input comes in, e.g. deleting faces, pushing faces in/out, subdividing, etc. + +Let's start with a [model](artist_hosts_maya.md#loading-model) or [rig](artist_hosts_maya.md#loading-rigs) loaded into the scene. Here we are using a simple rig. -Yeti Rigs are working in similar way as caches, but are more complex and they deal with -other data used by Yeti, like geometry and textures. +![Maya - Yeti Simple Rig](assets/maya-yeti_simple_rig.png) -Let's start by [loading](artist_hosts_maya.md#loading-model) into new scene some model. -I've loaded my Buddha model. +We'll need to prepare the scene a bit. We want some Yeti hair on the ball geometry, so duplicating the geometry, adding the Yeti hair and grouping it together. + +![Maya - Yeti Hair Setup](assets/maya-yeti_hair_setup.png) + +:::note yeti nodes and types +You can use any number of Yeti nodes and types, but they have to have unique names. +::: -Create select model mesh, create Yeti node - **Yeti → Create Yeti Node on Mesh** and -setup similar Yeti graph as in cache example above. +Now we need to connect the Yeti Rig with the animation rig. Yeti Rigs work by publishing the attribute connections from its input nodes and reconnect them later in the pipeline. This means we can only use attribute connections to from outside of the Yeti Rig hierarchy. Internal to the Yeti Rig hierarchy, we can use any complexity of node connections. We'll connnect the Yeti Rig geometry to the animation rig, with the transform and mesh attributes. -Then select this Yeti node (mine is called with default name `pgYetiMaya1`) and -create *Yeti Rig instance* - **OpenPype → Create...** and select **Yeti Cache**. +![Maya - Yeti Rig Setup](assets/maya-yeti_rig_setup.png) + +Now we are ready for publishing. Select the Yeti Rig group (`rig_GRP`) and +create *Yeti Rig instance* - **OpenPype → Create...** and select **Yeti Rig**. Leave `Use selection` checked. -Last step is to add our model geometry to rig instance, so middle+drag its -geometry to `input_SET` under `yetiRigDefault` set representing rig instance. +Last step is to add our geometry to the rig instance, so middle+drag its +geometry to `input_SET` under the `yetiRigMain` set representing rig instance. Note that its name can differ and is based on your subset name. -![Maya - Yeti Rig Setup](assets/maya-yeti_rig.jpg) +![Maya - Yeti Publish Setup](assets/maya-yeti_publish_setup.png) + +You can have any number of nodes in the Yeti Rig, but only nodes with incoming attribute connections from outside of the Yeti Rig hierarchy is needed in the `input_SET`. Save your scene and ready for publishing our new simple Yeti Rig! @@ -81,28 +104,14 @@ the beginning of your timeline. It will also collect all textures used in Yeti node, copy them to publish folder `resource` directory and set *Image search path* of published node to this location. -:::note Collect Yeti Cache failure -If you encounter **Collect Yeti Cache** failure during collecting phase, and the error is like -```fix -No object matches name: pgYetiMaya1Shape.cbId -``` -then it is probably caused by scene not being saved before publishing. -::: - -### Loading Yeti Rig +### Loading -You can load published Yeti Rigs as any other thing in OpenPype - **OpenPype → Load ...**, +You can load published Yeti Rigs in OpenPype with **OpenPype → Load ...**, select you Yeti rig and right+click on it. In context menu you should see -**Load Yeti Cache** and **Load Yeti Rig** items (among others). First one will -load that one frame cache. The other one will load whole rig. - -Notice that although we put only geometry into `input_SET`, whole hierarchy was -pulled inside also. This allows you to store complex scene element along Yeti -node. - -:::tip auto-connecting rig mesh to existing one -If you select some objects before loading rig it will try to find shapes -under selected hierarchies and match them with shapes loaded with rig (published -under `input_SET`). This mechanism uses *cbId* attribute on those shapes. -If match is found shapes are connected using their `outMesh` and `outMesh`. Thus you can easily connect existing animation to loaded rig. -::: +**Load Yeti Rig** item (among others). + +To connect the Yeti Rig with published animation, we'll load in the animation and use the Inventory to establish the connections. + +![Maya - Yeti Publish Setup](assets/maya-yeti_load_connections.png) + +The Yeti Rig should now be following the animation. :tada: diff --git a/website/docs/artist_hosts_photoshop.md b/website/docs/artist_hosts_photoshop.md index 88bfb1484de..12203a5c6ed 100644 --- a/website/docs/artist_hosts_photoshop.md +++ b/website/docs/artist_hosts_photoshop.md @@ -75,7 +75,7 @@ enabled instances, you could see more information after clicking on `Details` ta ![Image instances creates](assets/photoshop_publish_validations.png) -In this dialog you could see publishable instances in left colummn, triggered plugins in the middle and logs in the right column. +In this dialog you could see publishable instances in left column, triggered plugins in the middle and logs in the right column. In left column you could see that `review` instance was created automatically. This instance flattens all publishable instances or all visible layers if no publishable instances were created into single image which could serve as a single reviewable element (for example in Ftrack). diff --git a/website/docs/artist_tools_sync_queu.md b/website/docs/artist_tools_sync_queu.md index 770c2f77ad1..7dac8638f94 100644 --- a/website/docs/artist_tools_sync_queu.md +++ b/website/docs/artist_tools_sync_queu.md @@ -2,7 +2,7 @@ id: artist_tools_sync_queue title: Sync Queue sidebar_label: Sync Queue -description: Track sites syncronization progress. +description: Track sites synchronization progress. --- # Sync Queue diff --git a/website/docs/assets/harmony_creator.PNG b/website/docs/assets/harmony_creator.png similarity index 100% rename from website/docs/assets/harmony_creator.PNG rename to website/docs/assets/harmony_creator.png diff --git a/website/docs/assets/integrate_kitsu_note_settings.png b/website/docs/assets/integrate_kitsu_note_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..9c59f0bf5cc9a748de1a8b66b248f539ee8014b5 GIT binary patch literal 48874 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

    KZ;uX*}2 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

    _?B@ssfQYlBAHF=3EyzE&_=Z2gg)O{M_nh8~ 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�lF z3v}%-a*KhmUwz_Wgu1>Q(BJ-w9?PAou;fxSU`r9$p#_)iA<@r11Tvsk)OhOOfdI0Z z#t8BoE41vKMk^dL(+B61@;Ps0K^LtwC%Qnxh*D{7FuMRXaWNnAMsmyxutmZlJ?DF{ zPu7pMq^VgMYZBGW(;p9{az9d}pm4*0Aq7Byh9l)m%gVkQ-987;Wdh;0fYE2WaMJp` z(f4nxvwf2s7oY~pTS?W!Z&BwY>uPF2QF{6~AN;tE*>QPVuub`$JlNd>^$z$@zm9KP zFRIywgDN(ypGGW{g-M3x=aFB_ORy&BY`V`RLJt<>OL+T*Y5r6cPv8^^ezTTIf^+=m zyQ>CkvfZu%Xr6(!?UgF(uW~_`dK%vLbl;I_2_Bfayd1Ms>kv>xDTz4xk7CF4R`k}vS<3$p9{;7_0sHH(bpB4e|G%Rc fw&7b=Cmv8OJ)uU~wvf`no{Qp&`t?g-pX>iGR($zU literal 0 HcmV?d00001 diff --git a/website/docs/assets/maya-admin_extract_playblast_settings_camera_options.png b/website/docs/assets/maya-admin_extract_playblast_settings_camera_options.png new file mode 100644 index 0000000000000000000000000000000000000000..1a5561328e056fe03278f78c56ea6b837a384e56 GIT binary patch literal 16732 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 literal 0 HcmV?d00001 diff --git a/website/docs/assets/maya-admin_extract_playblast_settings_viewport_options.png b/website/docs/assets/maya-admin_extract_playblast_settings_viewport_options.png new file mode 100644 index 0000000000000000000000000000000000000000..5b801775d32338ea9dcb051d2b01a008697c7bd8 GIT binary patch literal 1064191 zcmeFZby!qw-!8m{p=(eiBt-<2RvIa3qy*{i?rug(Y3c5gR=QIq1nKTB>8_bQ=zYIW zygQ!#{qy~^=QucyxmH|j)>^+j&+{VqjhqAyCJ810060>TqKW{31O)($UUV>GOTvWc z5&(dKH!@0MjL&)FQ_^LX^%+>zxcDVUCg=Ht<)~;F*m#5=kWex(FerMY#l`yyAr1?% ziBFCYF%R=Mf1@iVpps$hpd!em3{`y2%P3|M<)P=Cl4cZ?9F&&s9-P?O+h=a=K+EvF zu&knFV!p^(P=^SJ%RrppMW#pBV5GgG3+GO z9Rc9J)7>9v-h>iinw9lZqOX+PQhzm@dlq$f)OZu1KVNPNOU@c`-QRGB!yyeB&7Q93 zuT^AZ48GnA@DN-CLfG=j%8t2RSl(qn+WSEtv@8n!XuD!@q>ruzh7OMIVp9QN$=D9y zejY1S^cnUe1THW-33hnWOwy1{YM?_eS zdf5+95&OCjC-b2`d96<*^Lw%b;=eZj@(WfZ7RrvDivXSKKR@JGsC}6Iu|E>@Lu3R1 zyv?pqPQpYvb)UkCamz!JCIf8@Qm7<;tZUmrU>s0kiiY*z*v1{gIR|>d%T%A+Q|u~I z9nP|_F9Rms=AYex^1TKD08YblV0`8>Zy+WkNXWPv8l+HX*_c%K;@T=G6*aUAs?#Ri zlP`)X1Q`w#V8>}I#D1?jfu4_7yRz)LREZd8mf}#4nwC;`iymJh`!6ES*$SqgckO*C*FvV4!W?xUi zjd!E6C~5~3?pG5O(uOXyv-5Cwoa3W3Kgi7OAz=4bp4cTlpQ8a~H3-NYTY8u^CTzT3 zloVcIA{v z2A_Qw)WZsP@GJ_`Lk|!V%Y0j^Ggn=m-xjC&*=O7{2&)v*_TpgdJu5wuI7FAp=?Ktk zDiipWQbL$cRNC=kFn05y2Kjy=66NwsZ-a91_jQN{gxqu-4Bmtt4~#et@Lau0s|3PW09_b=Lxz}6E{}UnJ&~7lfuPytloX?nmNw$! zY=;>0?M$nBR;Xo+t%2;8zG<&}Cpz!;vDv=9;b@VOC%M>^f8Qh4|3C_nX;KzJh z?}lRSUO;z<&3bDfot#o+Q6e!iJVC*v63?C-gIZI1uShORj9$5&Ma zJH3Wea+r>Tk=0m`kq1r90EZ6K&PfgRViNPDX|R>JrIWLYc+{*KlwOh}gXE*tyx9 zI=e(T9Z?(=^T@7q@Sbc0_MLML1mNWbC?-s@QO(C4ha+|dX|w+EQ$wNb2Lg94$DH`v zKbM{(95@mbtT>5+|J$Lnz^w}~jVl2fVcY;U-GGm|i*7;=M*rsOe-9-dS&8?u1m+Ku z=xiS>T;TnfXN8hx5eVa(@1nF}y-5&M-W{B3dr6gYK+PA0b*Wh_e=OERA8{b}!N>I` zy0|+b7T0v|bScGk?bjOuA7P|C&+$R9iW}@u!;Xs|ahxo!3$|EIA zKzN6`iG4*E%-lrw=)F*mAiH?!uvKGBI5w6_4{`rKLB6G17E)H;nezl|h|a?XPWp#u zgAv!Hy5ll2yOI?sqmJYoKPs8bYeGHH+6I4h#ObD6N{vX(c)UG(4(l3STnijIFT<+v zS1-)WUvlz(>(8cbVIt1otVNQ4758qOt32FwpjyvkWH*9qx!|_Art-7uPp9x#Z`wxj zbX*f}51MwW7K*p`8tDp{%yLl}`>UbOHBe2vMZ!1RoPY?iPUG9abS|A!FB7xm{3TsO zgYz^gpFA6|EJlDdN+Xv#B|3}sYl!hRO-_3pGm>o!RoIkEXEn>7vRU|KUOZ~%mZ#b4 z+Mf(33!R{dEF56UFVaCCFsm!u@%a{498klrYfr^c|NkVg4AA z6Skgyczxd6CR4UG;~z0S0|yn|&+Plyry{_}gD8Wsa=jm!q1myDy+3yh>PV^Y1Fm)3-n`#N&~NbW#73$Y#>xr0ZSR9;kX3**BMf`bcxrJYR+JTkM(E%!~e+ zgh|Di(|g+Vu%Rn64Y-*%U|nF4@0;Y})(8@x;3%klDlA=K*@wwkf|Yru_FUGx;ns}n zWgSFTiHAgA{yvVLVJzHfMlcy@I*U0Z>5DFl{X#cmi!#?tVPqgJJ1${VIN@&-3CCJh zRJAFZ46}08a?D?ogDm}HRvr)6xf-6AR&J2mcP`EjXyrO9Y60FnOGB*j%!cKoH1*#f zM4-t8d>dlza;|sv(?ugKL`)+N(Dr1p%4726xjGMrhFE??PG)8tzx~<=q8Zn(WykK z+$_8--4|u`Z$2p+Ot%lE?ZX*ddiGnbAC-H}<_@YmI)FrB@2N1q4b-9W4F7HhnD&KTDB(@bRx3GTxVJSfjNxb}n;{*qsGHLp4)8V#pgbk&6+ zAE_TAFP@$Yf^G=C-EI+EM2oH}ZF0Z*f^IIauqMP7(V4sw^_gfpo!wfr)~Bj{uB#U+1#ww)V42d<2?0)`w4tV3TpgJU{E!#YM)a^@YXq zy+U_bd6_JI~PZsw0A7L5oX7>xotdKQY2bHg2HDVOlGc&xj!VoNK(P_Fc5MKqa#-NU=}z7jOsp=-S~vsY@d-QMf@hM8N2Biv z>LG&wxcuv9@Rw=lU6I>q<<^Y78jkA~Z+i@lwPA7`P!HbGPbl=QpRdawhvl=`tW;#D zaIO5L%lGI|6ZUCirB;Pw+~k`l=ijnL%u=?@yAR)lzwEt4WeJX^`+Vu~taOfyc$$G4O~u#c>@6iP-d@Vi`2u{c7h5JC4}pW(f~jYc zjWl_&?~;#7vl}PoX3TbNlj1dX4!}r2s>W{DfqW;b0KY=aUStnb9mFiY=_d>s+8RLP z+jo`L+P9UJ{kC|_f)KcQ27i%v&7Cp)W(q_4bvizsEBOHq(1MiVPSnN*UF^r0$8Vu^ zByFEvq!61AF2Qa>#+rw++>!`kkpuJPhtn)suT7gWBRzP}kuysPd|pkwU!f_K8yC+z z?LxnpIk8II75ol~y1DIwcecV_YLj265&27K)L>s-wCOhtEczTqa&V;` z(UXQMUbP)tX_{-^!soshDLOjyO{<5C{obZJ2Qhpd6V(*NjviWdLZxL%)7J81@&~?i zvXEU)7I(i?ci=Q629k0!U^iP(K%A$Nil2#J0u#m9S3zmF``MzSVUA_Xibm2fRfsA zc0DU1&i}MN=?|J?oxxY2VkB@xlwe=ZB6!vNLnvAQ?za9BEq^y(|2C{$=A>SG?`>y} z!{U5l`+T4=W>*j35@raX9iGO55@j+ET)J29zXL0BElIdNCK}dO&R7qPR!*IPDlrJ! z=JKLPu{z%n>*reC5d^{9rFc z*vTM$Lw)<5j_}ueF%it3^-~@Tl8Gw<7>DFHIK|55*^OFX$y#acQ22GA$~A17V+5C= zKDa^T6_FPbnJWPLRq9{%Q2z6s!oVWRw#POPETGyCDVxnT`)k=*<-RGDj+O1*9dER%0 z*9YAD`?C=NYz(|J!;gY zc$l1Telc-C5u>`f1Btz;L`zP+1pAI{BTOB+?HRJ2AbHh<3mwm} z^R*>=vQ8rBjU~{zQJ4LJJ6j@(mem7C!GW*C2k|t|hhL!?Ve$8mhR{5klbZqmAo0x9 zcS19+Obln>-Tx5bROx>(vs^?L{+UjKysg=3(2yjj$tiEtenh&pgOr2*9U6&k+-$+i z?YZv{wCzM&-_Hm&^42q{mD@9Rw4^SZC9c`#w%FsYrL4NOiK>y|II5_UIvKh>P1;4@ zcXV{SWw{s8fHfaMz-#7El`0RYZfEvS_-rcn+e+bv25X6>LHJ_A7CX+qIk-jO14x>FrGnMzP+6GaZV3* zW}v*$4wTVpzimdNlV@tS!T?L+2CKP-by4r&Y!=SH!xyyx9u=!d0Gn>@jvOP7I<_}j zyY`VEbOg>|iA7JOqg>_de08SKY3ESrme!=z&xIdsGf*yRFNz~750}Qc?^e$!pO7xk z@q^@D=ZjuQp|OHkbW7uh1D~GM&N{R_70ueTPH1CNerHI!M!9$4pOA9-%ss!U?Y0t6 zm~Ww+KE{ctsWm}tfeT=T zOG;P<#7o>UA|dlw`x)NL+2@PQIs!oVsp66Z1KpKiW@7wzd<*S4%vGp@>>@FhNJ_dp z?6GFzUb`u8mGsDCG2b`de#Soq7cVass&IiwU)Y(_iOkK?PNZOYb0*FSEaisF?H<{$ z7kzir4zfAABz%EEgbZ0(F~d8|%+yLT*E!ySUNmhLZj{H9#D(3sVX-w0G6#lCPH1@qJp+;OD6<+VzXkjZ1&GbK2Y8K`+i zWt|}W%E+S#0~y%dN{WIw~z3kp|5tjCWlSx+vjK!X9)GT}h;F$ZvBRg!$Pb&A)V#gE@i4A04zhE#?Y9HmP~RiI$4MHOsfeF(lc= zT-kooUBzBcjEN2Yh1{lJCwf2CY=3vy($S3?`!E)h_9 z*Ej{o?%@|q(No{!0K`j4R~=mD^PNh4n&R4QKQu^z+=z@g7t;^785_7%xWc#)xjC)f zul0c)lgbCwZs>t#zx^OOP^sp7)|x7SHwN#=A4ire+UBHxp5FTXDSWGjZawjC7WVnz zH&Fz+*t?*o5!2nK{czyoSWp;UpZ{h&v(&*;&Q0{BHk?6H)`uig5m8c3owTyi9Jl63 z%z>ctXuy$rJGdQBr)uKVFDI7m9P9(x)lqh_C67HM0v5SYZ6T9LWpvec=uEzbwvDLr zXxps-P|L!gAr$dp9;N-px??0QR&l=c7nK}0bnc7`he_7HZqa6Q;2hyXxQxDsqZqF3 z3*vv8i2JDl-6SMPZFV zsHNg+#3-z5`K|qp2^ZBG&U-5q*Bk*dPL)}P4XJLE+-F_WQ6I=d>8KhjdRfI)zO29h z@fVu%KMz&^9J$74u{c#(XpQ(8ykA-&V3+YK=uB@m`V?->zk;d%)*t;}4^vPF?;pmy zNv}G7!9t%3AOJC9QUyGXbpTF~Jg`Zm(yN*D8uQ{n1Neou9vqMApQ@m;!aG?pU9Af+ z*>58Er)eCdN^C&hUFJNS4J(Gt)BbpY9uMQ6&dr7jn=8uHQXuBaTnM%z7_@cQljJnI zmFkut*TE~$*v4?(6#%M|2h3_|F-jg}9GTU=P7f`E#Oh{Nw$hS*X;(iuvDSgH`S6*a zp#cw!ok?WaeT-X;P<8flaOvJtFs`tAO8<;Mqd56?tJ?uUmYy}s(Za; z*RS-%&H+QC(buB$H5X`=eTT;u`O<%5L6CpUs26pyUg&I1uTlDEc-nlT&8dTfI*aE> z-%gXc@G{R0>4+r>ViLk9q-`nd43j`KlcbkW(YKo@rpYbhk00mM_)u3rdi{aU|E+ra zkA~4cw5wWDmwAIq8lBSQFj5>m&rZN5Km}bkx0(oG5z>Y!Rg0K{->=$sL>`FlnV;2P zvFpZ`EGq`B5><}TNS~lly_Sv#K{*sGw_Vv7JXfV(zh^tY`aFXhjZr|@Mv5>lqaQEJ z$|f{uL}VE5XCpJ{z$qUSNLihb;;%<|3M0ueLA&9sqFER9B?Ke33Dw@9;R`#z4e{f4 zO@MPUmoi;aqM4e7i&RM{-qC}Os>Q!mznZ>(GSB#BrNvrEzPun7WgA+m@+M=khFO@?2j&)u3)d%7|i z0Jzp2)7!5oPPiWE1Q{v zZ1AkCHj%bH{GmOQA&h>{h*=3g^REA`b3G(Y7c^G)#1v6+C;}m8Zm@}ru;ai<4io|G z=NyI_B+&eQl(&ktIic@*q$Dj{@}&;*Z{h`)mwCp324K)md*T)eD2>ci)@r{oSh{Wz zw81sy0L5MIud?wi4KSr<(9YOrgGP_1R5PFE#a0|+UQ7U5wrkJE=&hGZXft^-3cFp| zKb+N{*7mz5f3-^njgIi6>CB|*9FIsq(}%9UAY}E!BLNkSlTe|r;IXlT%TyzyY3Y_~M>x%BapJ>}0t$(oF ziWJmF_2KM^;44RnPsYSx=^{1>k zl-(=EXw!VyHV&CGX8An6&*?Lu z_qTtUlRrsc!C4H)6Mj%(41BKfrpwc5BFcWFK`_W+8;=zg()8tuqeAAOzWtVa9(WAz z#0y+DHTUij8`e$78y_ojfD@1~pg})BsuX-o$ zYZj&vgKW|eq+f45P+blv1(<^mrhSZ?no@R1#D^FLLXfy*2R1cZfl`-7=K(2YnpEVa>SnGVQ{1erqBk%g+J=}_3DGK7fxhc z#epH);$=JBd*qorF6W)@Ke>5I7exl(wAitp1~sK(>+MBe?8a#N?Y^Pp0BlK2IpdC;At;f?DmWMcHPNp-D->+YQ zxdk*&)B9r+n81TqiQ1w=p^)VSL3KKqz)3P$lT;~g<`Ck91L+}B8?Mv{ z^`UhyGcDlZP=Dmdtxbmq(}d9aeKS1mYFN$2g6kHUCvbXFq9D@AbO9AWItd#`gNCps z|E!bx5n>~7rFi1SZJw3g@dNY`I&tOzXl*T1AM05To-~vO)}R2yV##frX#_oo=-2jr zpx9)UlJhVKAhi3%Ao(f*wJI$n2}U4Vx&`UYH{k;djWm$HN2|7y8VNC}vJCvoA(<(x_-^ga))Bfon$=Y0`UvI@Fw<|fG>@`>)6Lja5%_==l z+`arJ&o%M`fNluLdhD18Q0JXIw*7)j;LWhPclrpN`6npIw(Y#C?SiLSTlRU@;ZzmJ zur2%v2q)s5jJ_|g!gGAdEQ-k>iRhs@`ad@<{B5wgT3Z{LsGA1*FE{jN8lFbfVa?+r zuo_9ZU`LEh9s9R}$wlXWR{dM#;As5yCUMaiHt2s8EPk4CkH1=SYXi3fHpsWo_kKD0 zobP(s!~uVSA}Tn=x}&gf{3sRQVyLcmQNyWjp=hgSa>8DVm{%4<-(;?9^H}Z74=d8t zbxH4bU9_}*Dzv3Pz#xXCj70VznacgS)--bDD;#flid=_0x$PYiW$PoHED$|jmj{0f%d z*HJF~3lO>`9IxVL>#}c*2cx!vb~87XXH^81Q#>Cy!KrBOcnU@P4%~X4+C$AV~K;R935P zEQ}kIuxekb9~m#}leyAryF^o` zqx=^Q@^{|(kEV>3X3O2fBxpwS1I?nB;w4L3vH&{JhTJEMb1Wi}nrFa}j4CiUpI(<5pW`3@1!?g(TVaWyV^a;>FT8BL zla#CGr!wF-o_LR6?#RD9ntDOKv#nBjP5b)uQT;bXKyS@4YugfnfM$5qF16gQ?-EsS zvQN^J&LL#HzbI9q-(VoBUcvSEPaJZ3Ok)V2@QxPZFOT#{vvAY4Rr~z<`%^9JPon`+ zr+?_z^aa>&e_`?A+E_TLUP@{0z8{PB`Sw}BCouGIi`zy8+_WLzWp4BYs&(GEWzv+% zzcYD+_(Ch;w3gncOvNpfQt}c>Q7%^yl7N}0qI;Ll1ic|kxwv!P&g2Wtp$iL_E>XLy zK2ITfEl&gN0JXbfP%PfW3J78aga%B5^36$L9Dop4nc$!qPyL0nB?JPQvdA6flieCO z?fO{Bn`;B^mz`&nITLpWsJs>;TL`3C1ZG1Qwc|tpR$45QvYiIqmEaIFbSjSyA-?4N zxNG~o{4vh~linZ9O{LW@;Ax`ss{C-?({SCdas~>%giTPL9o%Wfa$MFHhdqxKtj%xo zz$QXyL{0@f+W9sHV*i}0RCmQS8m4l}(O}{T6PA1O(cfeBQ~CVlrtRY&Zx)c4-`o=) zc~~pbOa`d#fT0sEB1416LHpM&3)>|PAIRU*Yw-`-VPRP(A}Cf9?E^D0{HHt=`hufq zZ!D7Y10h4nuuLn9?`*)N%2btyhn+?g(+T@q2GotOYlk~Zl|#To?FsC;)DO=%id*hT z(pyUy!@=*Q^hShes$)@rU12S)j$eV|E&(Ogg#fom|%GH zLnwdQ-^GGyGvc^zeK(7M^ZGTo*Gfz3^WMfq>RgoxncbSMpGzaja1wcn(ldWx zD%TSA%~0rn)BS7Or$nKO??^|9DYogI8dSuyTeuA=?|+k8l5HuQ)|D)me1w2Gg-E=F zj5M1D_p4#CBoZH8g;ht-S<&6v@=2E4H4J@inu*Wu%mYES%P@6xs`P!;I0YwcwO!Tsg**(#d6rI~+R8WI zM;H4{-UnxpW+s#pJ=-Oq=}07r7g)|W2M#2%^0M*|U)A-0BpJLXj84T1tX>d*wu$u8 zZQPZK1SzKle29!52fblmD`l#fYDvFz@XTiaTqbK;7FO8)rA$_WMafE``xL6tLl_us zS7JGmG!EQpJyyR);sR#lc3!8BH9B9+;;a;ik|@)JO#n5)GU;}@xBmW!Gp4*g!Srq) zK`-C!!5Ez5Y<>5MoQt~67I<+NI|T)RR&O{5MrJaz8-Dddi-BPIuIlCk5wi@enf(JwSZZ|~~TH#pa*8$(wg4k6#i7xvuF7P)%$I7K5Xs#2o? zmlnTT{}PX`?*Y0+#Ii@|L(0~SL`=M@}8#!)!6JMSk_x>`{eJyzDsez%w;n!eAA z7xHK05*~D8?|;y2L)c94hg;y$zQjbzOdt9nn?0=k@(TWRv*Iw-#a-J|B%%)G&U9KQ z%j22MHHKnsCb_uffA^B>slKdbFxLqLvq=}Xuxm>z{pMa9&ZrN@huh@Ku-M@km%Brm zo!9b1`t=O9DZ`30@)JAle5kWGzWOjsS)mKRMmu=FuzxZO-#Nx9O<5B2)MlwWcwxPN z!$xtBoZy<~TgJ3=*TgO1aRQ?$L7RWbE$l`bKN5cM;)HNC4e~{r-72Oi%&$y2l0TQEn^U0 zAl2on(LLLptI19{OTLY$roQ)*P+r)@I8HyT#GoIN@VAibzw0mm4I?b6Cu(|~{;FHN z#L1%qQ6{L5ASp^p|9|giv&b#khL!t03wK)3FMD@<3uiJa5fyK^TkOi>m>4yC%Dvh9 z8b_`xRIv@ynr0yUI`WOI%`wV=r{9>r9Q8EIawtt0){R+?3gff1($zF$iRlBOQ}n=Q z?V&!B9d!U+;H7H9PPIzUWbRtay>`OP1!fGZ2bRI8yyV_s`_-|xUV;7TWUg3=aQzR$ zhmOqr2>2+zHA1>It=Xl4w8^UOrlP4ERVk;qRrIKv)=n_uCG>zCzMqk#Lc>>{UFu~n z?0zQjYDd6r%8o@Ve01i@};2c z*&;X6C(E2@eTem_;%+q6!Uoddo|38bFI`u`u=H@5306key$igFPCw-rv?gad;z-@j z{?y+ON#^S$%`_1jF=9a^^0&KQ)Lr5%uOe22oy16efQ-K)0MXWya0NFh96MnDp-@i4 z!BxP$j}Ej0BShCeKgZd;fh>;iV!|`qBpDYU2r(5hq_u82l3J4&)im1jopzo99s+Fa zvLgrO8`6xr710d(nZx1y#<&w^4~yxO1Xou*8}F}jBW?1hJY&&B{S7iDYyL8@5B{xu zXqf+Oo5 zto0oHR;S!hCo;a|US;W|g>FvFsic3eCe?KoD^yh-16WJQl(wuxS+HyjRoy&s8fd?X zMs%&X^d!(sO$vc7o3B5|tgU@;0JTrgYw!R)yxoq@m3x!GUT6ovsZrXHKgVGyJ4(Tj zU+8PzP3VzaNKl}fo|jLs!@mMPmj1hJ$a(oR<=ZbK0t7_GR+=>dqq}aX3$jecnn`AO zu)KdTSF0HzE_pvr+pab`y5f2T#Vlf8yVklT`+2XlYHyFe&mY7}&nI|;NN`Su1-w`q zeeERCJaZUbE5qPLKojFiIMH1-d*l^<9N2Nwlvd^Byw0MIs0`S+DOm4ulZ8HA;|ns3 zV)Ofty32otks`WYL{dhe@!^p{>h7I@X~Af@d#JZi40}wlV!{mk%&5dabY^vKxzl>d z{jQa<#mP>eX`xAIYy6uVJtLK{8)96jJyZ3Ph;=*0%G(Rdr? z5*00fA*dF`tpwbIk)t2SQ)37$=@G2(6eo-F0P1CkH5sc4P3M}{!SxVtK-A>H$+q(_ zu5|v&Q-YmpG^*|T<>sfcP@X8g4Tghi>=(3e`cfdmeP3HTrzm9B-!nqF&a*#CRDGY~ z0}wYBi@33g9VLaW;4oI8F!K7VP=Bo+oRsw1q^9M&p56nJz@fp<8U&(Zejcw#Nhhb9 z$@Fwx5nygySLKbAOk@4ljd}AQdLU5Fnbe*1M8cd}Xtb#(@oP)7Z zBn8Lc2O){XwT^I~<7T}j<*(?hykjyhKVOjSplH#6!b%=_#1u2Gv~X*j)LY;@o&X9? zgZR~ANEnV6Fm9p2hew*2Lff@d@Vo_t#&HAE%Dz~%*t;}a!OgPx8bi+wW#4l4{`RHJ zueJD~8Jq$W6D$JlD;$IdSwkO;wU zUI>_2to{F(J^wA44npc4l0n=aaZ}h)BOne`T**0{D-gaPSkcwbr>)aoAJlX&Zcq@x zsNm_xD3Bq{^&=M6qNd3kloO>=o}?HSOohb6u;n|q&{6}Qcbg0S#O2Rt_G&$4Ff3Dh zkFZ4t^921Sh05%LAV(7tbd1gVU-(DjZ_Ax?aW<>vJez)ckuQA7N$AL{hPwU0#xCa( zR7HAgp1Cot3eX!2)8D}*%*;^YRgL2_D*ib~;GaQJ%cHrzYu!zMsgKe-e(#R3h5-xI z!QQ599FXp&enHqo!Wx8Mu>MR&aFMFMj_{2<0h>QPAUo3Q{RrOqY2H{6FaDm6F-V%o{G|BNWn~?s?~gd%yf7ZWN$C)SvP;{YeR_b^mJm4K7S+a%3M@)u;|06s{Li;!1M;1~2a3zK6 zi8(i!CB6*X?GGbZ3mU2&sChZxhjF%q`u#g?)=Tk8lo)FN|0n`8?-$n1E#BdK?dYVh z1od9n32oaToDPo+rxO1z%;G~9aa&qbgpIPQVePN)z^Gs}JGzAh`jeUM4!-{y>jv1c zYp*4mzCu{>qXM6YCJYO@n^LvOhsX?b$Ou~MkMP20bBnei`$C;9{bTE1MCctVDA$ZK z+j~ybt81b3;%GmHTH?CFl31+#7tWnBd~5oX(PXET{oQ4H(Cp9_DE~&d>kqM4M(k%x zf)HiFuMo~FyPE+i^Si?eUE3QkV1VQ;K9s7`F1o2!Fvd+c%7a`|Qgm@Py+!V2AO*Ht|j2444^|$KN_n1o>xlKDr zEyRm?1*+XkB_gi2qZ%ce2r4KG<`J5XYjD#Yi`2Vz&#Ep^N?PJ>#zSCl{Tlp-Bnm|( zMkHjD-x%|++`v0eS_aJyoxlGrG%&1 z2HO>Oe#v)zr6^!yT?CJ{PwM<4+|n8y>ymu=@-cHJ%BW@Q5vsSZM0=h~`>JGJA9Etv z^M6{g^lwi7PeX^JfdDW3-yTn_|J&muf~M{~e%VXB^Fd`y*T*|Tv{Bh$%@L8;s@Lvf zlmuDZm+kV3hFBfTxG1MU*=!9 z4XJat#&{lY^5E^&``ewp_d}ILSifu3uG`vlb*d#|Hhbhd66W(r^Va=4qj+8mwMM_7 zJ_aA8gV>9}o8od;E9q5FPa$p`ZNUtKLu+VcKYFHsM{GN94eum50XC}*xU-GsBB~jh zwF3KwG>wjZOnR{Q`X8Ezcrc=_E(&#IUsLbR8fyKGW1Z$}Vv)UT;VR4Kd3o~tIXMDL zFC*Z5BuXMht?B)9>)mhVKLg;VYmgM?5Vh{LsFOpLL&++I;CadtFbiP;TsFN;vDQ2>jZ~p1O*N#P zHO7@Wg}BqLsH|Q(E#ERj)QJ$W5X7?$SmYPZorX;$Z4WqFXC-~Z1l+=BjrI*O|H$Q5 zQk?!vZS$wTJSz1lvrbyKerj?TA`Ef$uIHSM&%5Y^i&|?fbQ)f4K514kOf64D`ptaG z$q~;N#nY`NjC5(zoNq;V)c&ZwRvDVxv8e+Pk=8#)KR$Ef@do=Hp@E2R&pn(E>RTR6 zMI1kjaF(=i?jN=Bys`E{!`8!ow$(e%{8+bw<0dJ_Hb9$|=fyu&kpF8ycrB6g2Oljr z#et9=Ylk=@x?z)jY#>D>`LE^(a~EB59ZbG6YzCxHMEikHV_hy=t!kBRzmnk3@J8uE zFF(Iiu}iT)gyKgGNQtncfX`(v?(Mg7#oMT<+9|xZE>{oihOBRCMGw6tEG@9_a^jk4 zyNAFzQi+?7Cr@Lk#un_XdOg>xu)EyK^m~Ry;fXZbh56-Lc-QC%( zkoQeb@5VA`k!JtijM{^_OH2w93ZuSySrk%AO0@AkI>()Q<1slzRDm)=GAGWumJ)d{ zd26Yc0{T3u&=&g2h|~%GNCQ47+=yZOK+`8An&k+9e@1*Jw_tVmzuJtF5|%_iM*^BN zPrI%Mf5>tX)L{M`tXAmx{Qj(N8nF_H1;&K9PG-rQ@XNdj;qP{t8z@0X#gSE|T*j1k zYY7_~!%ij{!=1n0Z)g|X>KG{}PJD0N&|oG1tMtqt3)}`ldxdt0UgS{xOC1WZ?Rufa zC6X9$ZQrfm0Rzb#Q8h{3*xyr zWm36Xz^|m7?Lt{p1brxU>=VxOG9&wH6cbt@>$Lj|o}6!WHq}^~qFC=tgo7xX)W#LI z14%jWz-_ruzO@9(5;RN?L^c@Qm_9swJ4WF5+CU|x>pHpW(`DaPv5>7`u^8PARw#$m zU6>r7$LP6cqoag=cDMc6PE<>Oaxc@g3dZZ7kHXULSl%jLvc=@gV%q$Q`hpiq0pH-3m(c0)*F_Kl!tmC}-{}^_{Sc z=$IZbL@F~*1v)ANHOic&^B3IAE;)$hI{r14L)JzdvYwmflq0fYFux?q&%Xg_h6~I; zNzX*9Qc7@fNsXfIH_w?%Zhr)#I-XCxoBhuk9WB#?k#PHwk=W<1A{O)2DfB)+Z3Vs} z2&f3ix`w#I>nVEgAWi}pmWfZ>`sSST%=%95w0!MtPB1sZU5U{saPXT5*0B-Qi|EDK zlA0;LP&9f04_RpHUGD3Bmw}M%Mv0K)Hy|+)XWN!V19 z5ztSsclstBuN>YW?(*&7;;IPCG68lmXo4Hfl(#L3g;hq9TN1a&d=5jQb5#zVf(F4^ z^ya$?%N3(MG3~-gM=4&h9eZhKFzO2eY*d>yLYN-$5X-wNzILxY!o80mF&->@`%HRu z%x?!T0iWjaGsz2&$53dMvWR9Q(@|9f1p%yNf+Sv7i0)2`>Q3MJ%Wr~BkFtsFFSu2N zk*jV0$hCp##Yx;)2CcsULhotwuYjw(FekMv&v=CBFEzx1vN+|S=M^Cwf?6)^qW`?g z{qG`?1<_hET{a3!`ydTQw{ldi(xEe5&WK3+M6>#OzLJLdAhvQSYGMrR;bt=dAE zE>p4>>~j~gxCNzsKI{fuav}JQisv;rV1O~`07%WE5&Rn8apR@%L3l`0W|1?bCb(=9 zlH@sQIKdKlT)FywQZdnYWs`EKVkE=@Rz!FH#jFS33CF*f@WsEN{+Wnn*ZCFWc&*YH z2_b{w-Xu55j^F?Zu?V0md;;1Ksd5$6*1LhAL;;I)f;+KJmO#O%hZTzMGNq4Tu{m7! zqP$*7juSeAc?^C682wi1Eaq=L^xl~ep8L&wveG}x&^T)L$td_1Y+nJIRY`;Z9t|77 zU+cT>IE)C-+BeQ(q~6>hKHhgx(3PL4PS|*onr5@PA8d zW_K__kBnhgr-Hur(2mzlIGSxExQpLAZh&i-H)3MMvUFy*0STQ}pQM!%7VHd1*Fi9O zAvpC`>*_4G^q-e@C#N1fK{I~KmJS-IW*SModTH8lGi~^d{j@yh)anYE6>f>*k@gWtft_!{ulO+3 zd+J+QF3`=0&=k)#&#t14_^m(_F&f+fXFjIKwW#uuYDWWyI-iA|)@||4dgM__JX{0f zZ;Uc&e9_E$=p+E9ODQ2~*xoUBpl-v9%d-2|>hGQjMcv62z5}wt-sHx6-hwR20pI*Q3VYP;R>T_f#|sYtegE{o0PkqK_d_c~Q9vC)E|? zyb5JbNyxNTa}RLTVp^12_YAu|^Ddt9#?NcB&nN|+j-R64+tM=c5#)@Zhc+hd(`iBO zI_Io-iv;XT9nfGsdGP0~==htQl}`rg)-SwS>lM+ryP60YK|sn16pA zmSX{`^menqB(4bYZAkR~M!J9lV^zp?H+ zKYV~-pIp|l8>?1*849d=7J9u}5o~z^&HMNp+tmk%kdwIINvu7={)YgMCrlWL_Vpqg zOK6I@{9Pl&4-v2BF&NKAMj&p^pE`R&L>h)W812i7cxCr%pgUQ=4Mp$?A|@d-UG@lx z>_;GM1sh=;2-8_b&!iE=K)hsfjiVUoU$6ep5dYmD!?=eS5@;OtJn#JPAlku;J`+UT zV?abh#AKR?Xy}I+@*{>Ah}r;g2{filPZ4PW1@N7fk}sZVrPBDyyTt#BAxK4h!n_wk?>PJX#T;)7wwDZ15g+BY)ND;U*fHvAja@@>8D zCI=Y68@6=4yp;C$H_om<6=8_=FUavX6fjSy;QoD{yh^=iVr4{^z@~9)0VG6wQ&4LH zgU}-%|5Pc%VX|O1MLH_PGc5@0I97z7=bb(mxH?4$jP(KiW&x&447-kqO#=4x;_*!0 z>o@mss6^$7p@}UmCiFv;M8gOb<6~G{B7#iLcnq*>O*pp#`%^OR_AH#pP`LB^T9ZP= zf)Rh!?2K$`5B!>#O|IE8!I5Q_WnHjcv%MqN$j(S~D+|Jabvs?|-!@SWFS8*2$p=3^ zdy>N4wLKkzm=+N`%(IdReWPmLJ|AiQUOu0^eQMqV7m(YMo|nrOWFkkL^if*7zHs@% z*zxV%X$xJ?<}jqv`-2`K>T5#oc*Tt1;9F<9>qJ=Xw{&G>&Q!-t`3G8Fxcu1dACMe>H6>E2X*qv-Ztzb@}l;UQ`<0u^bkY4mmj5eyo9hH^gOV z`3vXY*g3zWiobl-znSId)T7>HnhhvvZ^%!+L#~yz&oyBuWJv^-aK@+zs4%9E9Lnq9k*D1rToj6px5ORNns`A&Um8F zF}&lV@o#?(^bvx#u0$I7))vP*bynZ+mpu11NBPnU=pL6_-6qawR*>Gjlz#e_f6^@1 zTZIcAJ0C{Rsc%97<4=Ms2o|&B(Yt}df(@VqdzS@CyE5)Y*)0f_Y_eTppHyFSxfQl|OEXO*OtKO@GWb*>|1ou?FG@bHfyx;3ca3w`#E!TchP#i^&%=hf*Gbin!_ey*S4HM~8q(S1m({Z*b31Wp z3h+&z+Nth43!#3lsxFllYw^$I-Elr;zz_Zv+vSTioLVjP?j6E|m@lj~*6bQtwdGOm z)96k8q8WdtnL}d6&wCKm@PJS72$o@*-RFA|QTWCe2dHRi3Vhv*YCqhV6(F7p(~BcX z$w1vTdj>7`%;(H>4Bf-=4nwjbTn$;w$s%3_oR&-wMwI(J#@MVXeCPNO_!TjaHItlnaG+t*F@)lZZ=8B_8ykB1{3aC2F41X^$ zgQOZiL1CsYh$cZmz4T=|r&OVa?#nBS9A5tTQ>!_+07}Gg-rdE9D@^(;XbAg7`U7wLwJkvAdETMfGm!KhAj^E+u$B3o7Wkhp|fW=mG$i59KF^fSIp(G zYK6Pq>p&1t_1)*&cZuu&c8%{WYUUnFR=zFyz<)wr!oO|wWNAafJ=8;{p>V}={pl_3 zQLlq)o=*qcP3-&MUyq%{3C|-IxNA{=m)sQVgQ-67?++VvcR`O>&I6oAC=xZC0se-^4yqj1P1NTHf)OdPx!M9{*W?%d1fIayUAp&7o=3VGu z3l-O_&h`3s@OvYAO!-+~K$w@vr`KpO975t4ANtD=?QT28CDdhZ&QQ!Dj))JEsIu?w zjQwBiqh-7#m(x}pixH9u#8%l_=<21)1)TEk`X3_uZ*Kn#ufnBIe{>KajuLvShNuo9 zv7#F{M;`>={&|42Iij%E*yT2VyJjng&z+kJ4ff#cwdbQK&6OxXVOVc!l5s6rN!X(3 z?Xqf#mV<)T5PYFgwTOcLf{+jXoE!6uQXb3G!-g?;2=!XeqN{A!#W6O~8X0Q2;}dSq z@u&J(4=Mz$}ij&H@;IdF?R?ZFb#_=wK-FZU-n&P%wjqr_IHm{ICi1zE^3 ziWFPj#ay^SfZMsRVSgf$GhURPtOyWXC|TZUxJUN+j-cBA&3OGJmCXln@`d5tWd+Hc z0aVQN39(E66o`JDOPVMiQ1`AdkhPH=?XRorpGHmwQ(!cfR0Fq$VgIrZmr*r3A^{xQr&ywqgluSv2C-d zl|od9Chq_}-MonoopAu`je|W^%tq?6-bI@C%GLE!5pF~jNlmWJpbz0@#LO*%wY!Bk z&RfE^m%s@cxT!bWR-8GKnjaIz;yngGvOrApKLug-HS zBC~$^S>Jqat^PbzhA*II;BI@)u2P(vRBvL|j?B?oc4sd}0Yd_T)j7AAM=|!CUG}aU z7ManAE72|0$s>gi$Y`Fd4sFIlD7eCRXnI-h-_4rAF-=@`n)2=@?dz!Ghbm-C(*gR?Y~I3sCeybShtlJZxy>YG?Ca=1eKo8etAKdD|W#F0fp zr5tZ%7Pd}}88uk>WZsqvaVfr9MzP|MZZy`&hN9AnV{qY;Z>pm^f$an4cs+1aNTcJX zOV{UBE!DwVdgbc$;!V2Y)o+;d>OiP2+}WcNgu{>{fbboE7P%;IBT0 zju;m=55kA8Df4u?R4Wtl4Hjsdg8Uw0ig#i#Pd-iOOcHI-H+#~_-nkWimWByh13nY;h?6xljT@{kp4C(hjrp4CGcoUOsHlR zrfzzWa1cfwiy(f+b}ME+A!K>}(Y**;b42hd?cNd7<=abk5H?%JNfGs|8QzQu(!NHK z*-6K7%QKkr!R5;keNq_SV&A-X&_}uAj2VNbWqN^!_-DvF2j5|of3A&L;0{<1LS=P> zQ~5ud@2j~p#uhB47M@Uas$|zJ?@yt4;ZGB$=tP~v@aSi@!%6*`VZ|SrH$%#J9=jDD zF&6*TGN9wrO?nvo;)3A!F^GjJk3!>z`|F;eyL;eOOAr#99VLk@KnZZ>D}T${q~TbK zwWY=XS`E_j;gX55pWj^#SGtfr8awygbjaX&(cPvA9h3=VBysFM zoALU>K_@}`kY%M(GnDT7X zZRzx8K`6SXOCE4LT>)vFtps(W;X3K`B1L6{j!(8UfgIs2hVhGyVJ4cbtIHKrbu*r% ztHszvi+S_W!KXRd9%R!DjRF$e@H5hlh{TVJSa~9w)OI}C!rSk{ljT;v%5>Wam!^AZ ziTCt7^Zb4hr&bQWt;-&*$?beU2t-!Z_EBd(p4h#xVbOU^L@rRHz)wHT*StzMexYyv zX%eq3PyOs|VB4vX$x>TdU&=yo>H-p6iL5rNe!i85@b%Oe6E*F$Y-vS&p-OvdZtZl%>j z&Ui z*!6X%LU)BqXy`5%kfEm*J|{g`NC&#=HL~Ve7p9FS#+wTSHGHoNhWTbs8ghf|9|5v| zDp@5rYLH7wfZQH&Bzzt{#W|EkIlxmO1Oyv^CH^<6>-PyaWE9?Tm|m$u;0*H#-NgmT zmkX>=j9c=9ub|La-tY-^jmQ6o4B@W2DnSnQMb&*7RaJjnN1-*|t$s_qJ6I_nJU6MM zAYQ%Ts$rYX6FI#+)u3A|uer>fo@j9pv0WGf98Sp_xsz4ZrNDLFJ_ zLVobKFa9F7s8+V$S{>&`C*oSY;+63}Og6}`uV(1l*1_lsk08F-f!&j08&JN?bISPm z-*&f*AcLZD7RIZBY#-#++(6)wkX4cv$2rWa z9pSth{L|P&3zin}^eC@BO0!*U>i;FSfS(qV<}w_rl|(?T>;(E0+o6Q6Sg|{Y$Gf!y zWT63|VYVNgg;G%(%lwm+-)7N)=H~j1HoIX~Z(B0VZJtuNLfm-QvuBdR|5h4q zTvU|$@*6l|z1rXoKICIdg3;h{E8@1gx5yprlsjc7q(d&GBz@=>iZ76v{4PT}L5sFm zbL}tOm;ERrMYeQ%M4w&B?VR1PWo@Fya+mrN4_wu8TXuZB7pG1y751)aUumiNn={x& z6yF~#NtAO%&W@5S30=TAKimmA^z1Av);}w>QrZ^;KM-33?Hm=p!isRdO48eNw!*Z! zSk>FS=DFr_nEFy(35L<$!G^Kb;jHm?7=xRp@gXfNKt~H=}Y#+g`cT^BG=Q736WVldYh}Q4oH=sd-7sEkr7P(*SH7;RGvMLtE%e z@4&wD-sA(x{TH{Fk5;292k_oW?8gQJfHF*HLt02T)iZ8+kHbLn#0Ny`TD72}II_KadRA6O#zZEjUZ*WX$-^s4LqUNki zYG(JcC1!#5)8p=r=a2cf()p4DlMePRpDljdW!RP-cOvTXCdnD)zcn)9e8wgFn&Bt) zF4ilf*@4gT*RpB8GKkub--#(>1&#$SGgm30&>VT+dS!bH1rGh`_m&V?sv7u=mEkX4 zs1?`x``h3wgfeCbo_`QaYkh-k!2B%GG#HpUHDWqn#H^2w2HgTWW!)1RR5r`!!~5Yu zge!)@{y4*vp3w)oKDCc^A&sDIZs>B7r)opE1br@t?VZlqIYrPWq<_iexCLuXM% zGQ!}p;_3rjtM`n$cD60}XFpZN29I)D<|&;Cl#4GZ)Kl8`WE|YNo=EF^?mZ4h!hiUF zqPR?yc{!KHa#-rpn}z@z5_#Grj$Z{{(-k*z@ZhU9zFMI&`-_6Ii)(tL@0I)NDL+?; z(@G;#g<_X?rGQtXI&BG2e2-W4CqF2DQfoiV&a^P7a>+<;bp5%qF&eFKh5ycorIJ~z zhvfCGW1A&|1t#!2BOka}6;qZBoN8Z0!~3l!;&-g~Dy7zh7eg;pXwK=*Gzi7Gu?b0@ zNIAfP`bxF*NW!BT-QO%3Rbs!M3tmNDXj-4Q>xH7pUg&02raQh(oqQX_7}vdVVLnzQ zZh%4qU8QMl(u2nhYB2vVmdL!(ERVOlmKecvTSQ9B9wBQ$k^5Frf9b;TZR{(SW~px| zhVEwk`u^4(zYAd*EkY4D(=o5__$`klGjXzI&S``ZI6p1Ip+-(6Kk8FO(GGxDME&%Zahc~)Wd3v`T;sA>qLe808zw<>|0k5UW`g=qOWjaUj>UG#hKbG?eHUgYh=p1~-!2?=!8cEy*l6t088ZMM&&s?tGDI-VCECVrSWr-456%5=Hr zoN!9sD63~Ku^va{?$X5~i}pSxC9uT5s1v9)TlShZG&@xXb_4-m?LWS7AWDV^L}@%1 z@E9xu4GcJ5 zijS6S3MIevza{};LP9Npa9jJlbM?$JZ_C@*<6uGa7T%h3?0VPF8q1S^Mak`U^vcW0 z1Y!8NfKrlJ_$hEOaK+nb1#T&WI)H@LQ0T6g+47^>!5|P3a;L#Z4b(qX$^Y{k#9@Fj z8vbAR$Nj+#2@%=woZ3I>GLo+GXO^?$08N5{alu zN!JsGj*ag=+Fzl2PAO;T_*7x5!H{=PErga%Gp)T*v|Nqn@r5^`Zxk6a1>Y2~>j)}P z%Z|R5dpV$zbzyoNLM?02uJ*23Hy#L(-g4CqMw{i0hh1ZFAJn6$wFwx9<^9<&RkYc@ zbJ1jRVYwU}6Ih3Kb(ToABTCo4D5t*SNb?U!#EZt-I1K9`ta&QVzI8$VVNZD{3&)DCVK-F8PLjiK0<2nM|O)+kinE^FQx1p9;yYmZBL=koax7Fud#isS z9_PRJ{(EBDogsA`!l50vJTAD_28bajc7ak0TnI)#Hm?;V8RUYf z)dKsZhBJa-LX4Vsi`~r@DDEG+y{nhe#I(cWi>FWc3DEC86jn977Ep9(PNRsO2&0JK z;5qbK)wSTlKI}0$q2Gq8BOi9>VHw)T!sY3ld(OzZK-4j#l}wW!fv=g58XGiag_P$q zO>lXb`Y&~#Gp1A8(g~J8c=i5%KSX6)%|Nj|=#B z>iI8MyLc%3R*edyx|C_qId(i!HU3kN6+imW1$-aGw_LXG*q3vb#}TK0h-_6~85MYd zCfU=OQBAeR1uuz$jtKP*Cjr!qVpnGvJ5Oq27%u=3u|JT&geY_}HQy;ga=&bcWYsbP zpynk{lLvHb<~2`g&8KYWlv+GKv47({N>Fa(kw_P&sqzny+&Vp`MynzJ^D6-S@MrNW zuGe6tO|_rV)YABppVJN<)^mNIJIu~#zpTJ#tSFRP*NP#ttojEx(wxp!?|y6yAW4%@ z1X%hVhMQ!*_%6)j6bGu>o!he=q7z(`uJ?PsQ(GV?=BA@eGmPia`X!(vNa{W_6E0}0 zy&a~P8J0sw>s=t+omk8AVrd(1?m&x3{L{_1|_;=3dz zlxyp~&iUOitina|k`~QkGV|^0G3SV4@mPO#h^FkFHRY5TCa<4Sep--G&%?M@yGk7v zSAWCV>xY|n_-w1`*BV=`DkAA0^CzFNZ-35|#v*u3sg7*T`@KpJpDPI%%T#Fk1|JL9 zTJ>Jr)IFG3E_?62#Bq){)D8k$^jPwK#wC$i@@Rz_g9xRYtK)o_@AEa(Jtvx2cGvT& z80q|3j2;ywAfKAvXKl9n=JxA^SfIN<`0WdiGs`uzSzjN|-G1^@+ey)*e)0Gh)C-3- zgzNytH{?VMAY;9jcieotL`Uk$X^*KM<-hS7eH6)Z8w zsJaN3DIi12tY^ePB*)TP4c*NW=;XK;i*~=g^`w+ECv;SylDWB~tKK9bBqpzN9_@5U z!%}f%pQUz9(})StRgo#S%*OuVD{%>KA}a^ZcnSer_C(}n<$|O0{J|QRs+VZR>-DcX zR;Eomog=&cmc9QD`r zOm*XZ?p4{1)L(__0eW_?ygj$HQNAc~8_iiClPS_E)5M;7MJcv7HI z&lVf65kasfDNR#=a0@GId-CQ(R{Fkhk!bejUFNcGkP%(NwIRUTnYLyl{WR~w!S7dUB{Pao`aFYa6+3;wjvtg39H5UML# zGv&jeA|t}>vzwaWW}XzgIc0KTFXCj`3Jvp5azW!OFUqQmWikxLI~8F1mJ!J_8J2@x zWggYyF!#P>RsfxUZmbX*ti06-cc$=(eYnxP^(Og%Uj11(BQsl?lXirvk<^nQ@SldG z78I6Nuc%v1lgMWG!pviLMW1G!MUF4za!KdYrIk28gDR=jj z{nMt{fVLmkfU{(Ce~@*=A92_KTXTh2Bge@BBoI#`fjj!4^2ymrrMuTidr)83J4MKGJ=iG0mSv}GA( zzty+>?c29X_UIQL@0L2D8`|)(5`8#R&uS;h+*bDYGMfkO+EE5(et}*l=Z!&-Js&(z$RW)4i zv&mskmf+ZiF79&SI?DYfv%(p%Lf}^<6x(RGzKTQytf~As)8=;KhlMjPhAU7Iv`x-* zW$B9McIS>6lE8RYk*)LC8i=@KhOwl?st3A_GjunRmksXLRhY8~1U+(<$51=5+YcPd z37UuaJ$wdEfNPiG|4KUbFZXfyDPXH6EeFpwTpuI{VR?uMFWZyX|8qpre-SWrpG1ZJ znCJ}SFeFfu3Vo0l^QPMXKSfsqf7XZBn6G1*w3 zqtKJDY_`_mzW_~wY9bB__*&w1SXk+&3*vA3xN&bXvga_>A%BG|DvbnF?0_*)YD9&K zQeX^}ks%vth;DP|O)6J^%I-H~h}FJt4oYdb$K)TBRMOaubf2xA*6#hTP{P|%X?gA8 zrumW?dAC1JtrJuK$2}bas804yd{`PGJ*#P6bE+KXI={NiOi46J#)0;ZQlsBJ<@+Nh zYb^f6PzJ>UPk1U)ATF?&<>GDANXmXmI~@?FWPe>SFLYdt&y|GuijQZ`uf8yOw%Xy= zyzDx03jR68wbGH}i{i`IXOg@%uVxT}UJdh|<~JS(=bTb~W`Fofu=n#VKJOC{u3MRp z`8G`Bw1?E8Pz}YOn07%BuY_q-|hF5|`u-2~Y}q>rvcr@abkB z{4vbb=7b3R4=IlSC*#xd`}V|{uY#jF!nd|KF+wa)M@9wKEE?BxNvs~AQ z{?b-epM8~gOaRsUM>aM^728xJSb#a-H!WiJ;Z@jRnTu|tzb%>GVf@B@>%PX-QE9alvo`!9TAi*&?Z7!$BQ&2 z#lQOD7Cjlj=p%j;PT{#j#`5-0?h4Khovd8(XJ#tFZRw&DmlCeq40rw8Cc{Gud{S`! zTGDKjubTZvf3TM#&BlAvwKa>UzOZp9Yg-Ww@y!bQh2a2C5QXeN*b)ey?TaaZHu1r0 zWQ%p`!M^D|>lnoGlBr&rwc*N=MFW=xnDo|V?yS)cTYns!iE3gs`2`#9ug=yyz;E86 z4nC!fO>XoJZex*e{%5w=b2aQfjo@Xqe3?1&mzprh0z$U+F?E2Iy2Lf!wAy1KBFL$c zH$;1ix1Y_qOi+@=gA7v|Z36v{zrGx@3u})5#8M)Zf~Ov|95!xGIj%Tv&iC>vaGtDn z!l$&nR~NioH|65C)Yh;nc-{z$yN`~!UGIBAVIi~kf^M?B`+$nZ*NcE11MI-S7>)%F z(#tOUTZz&Bhu*tCQj?GsVa}5jHAoi10D?ZkZA37bwBQIlq27fkM5>x}LDH4;n%Z~t zS%9~yrU+MH7@4Qf5_;nSsEp>kJ29OE3~bSgP}eqesNfZ5a_l)|JHb}U=$Z$M(G;J1 z-}B#8>R!e({nFWSH=iyRgMCkdgnk);Q*Ir1uPovzgdmj|!U4`YoVB{URP^+SJ6Mj| zD$^d=)B>F`iSjf*hZ8E<`S|QR_la^VF$mA=@Zjq zC%jC4?ccMC5mL#F_m^fqI0l-je+8$WUr82TEkF6g30Hue9}i8*zB1@f$q|c$nd}=- zYVV~FDO5pj=!FqU9PleuTDIvm#m<)wt(^J(q_3yC`0%}R@OzC|T;|!+&8aw?g9jR? z@zHqWekkz6nZOSZqOkITL722!jP)e`s(zQmjgh*_TQRM{=H4qCV#{8n9m4; z;(Iq}TB8Lg(U2#8!YN`H6k?6My$0OMGp{oMucy+Q53ma4URKOLT!u_^B_z|LjnW#ku>afzggGeC>ZB3@zA3=WOclu;$sI~v?{z;MQs-vg{M%Z? z93UTJV-1{6*?-f5|Ceg&Tg#Io8~n&?rSE!++{KHdU3t8AVki>kb&GS|HBX6O%{;~G z!|W#;;JI?1lbIHV%*=X<0-%MV`m84dS~-qYfc+_HA(nS=heGcciRqIazfm6^z-5qC z0c{w?s8@2ZQF<>I6G8X++ni>rs1`WIkT%;0T!?g<`m^05y0+G*av5ow0M30(w&AJg zI}4m6`mBiIXe0c17-Cy^oso9utjNn(iR+b!9yLE=HGAApu- zC2)RNv%th`Zih?h+Z5qb2cbWaQv|y#Dl#Y`em&-uX&F7013GRBu+Z*^Z9zW8DC_#P z1C;olZnPx4tO0BH1+NjrF%JMGxeeez|5elI-%MFOI=(-_mE~rIwQfsd{&2l7`Qb*Sp9JcuRb5F2@3@DQP+k%hsbf-Dvg+fcH+5WtR2DoF?!UiHhn9rS!OXxv4&#kw?q@@IC}L0;v=_dtZ0CbOx;26diQ&{#4irJ%$jyGP;2r z0duo1LP1?oix!#@_l2jC5XxdSL1xO%$e5Z?yCBiu1P~2!BhU6MA~(MSvMqVDi1ZRw zrt~j=>#4ZAPl_AEx3z|+l_akj5(Hob{kj&yYMj$jKk(;B>hB^2-fZ)J_L!jvrOF-d za{#A=^j(5xJQxMtG?lRmhd-iIvsd`(-eyq=7C=AX@$1OHjAge zknInym44TX$_F2M2!Dvq3@Nt0Z6q(sy7ch_7y{H@t6L1m1KQRPP zV0LY#FIl`Y^N?<}-g+Jd^9ovHZ>Ylpl>3*N1>Uwu9ft=xd$14-|51Q}aJ~OW{`1i+ zByjwraFJOl%ieI-p2o(QdCclu+l>Rkh%yrSXNU8z=3e63@G;BN-Qauvan`ez>;JTH z9U3G)0XzZCpLha=i)?F?AHb>vz*^ienqYz!eX_*s7T=7v;veY zg3(M(4$NXnVNm_S)DXGk z4U9m$3GKy*psQ$H@o#)$dNK=aV3mhU!#hp{@YXlx;o+_?k+)K8K8t<~Z7d%?dIW8( z!H={-)OlTqXX9U)t1^!lWWQ7VXc2fZ zT&z%ea^eI$C#mrBkoqb)3lp6P^Xq}~I~Z5wwFQi#RVQFOT;Tgeaw_@17{dIQ5&zpE8I2RG7xSa$xtcmHpeVXalK zDNQuIV@D9!J0=G7H^cW!fS7tk@j$aH$v``*akn^;N75(OYo_xu%g4sb`>igHoi_qE z0daxvA?TA~XH%0vRKj=DMrqVHLc|0NqtHS>uqvjcOnZ-dh&`7Faa2;J2;Y!B&IX4o zTr;KqU5XU&^s1h0g~PTwB0XM_vkY4s;^%uC9xJ`f_WpS2a0I9+Ch-HlLNWxVCfP!X zsVOu#_cDn+C-<}66E}`ZUJOq*5%s$$+gE92o+qoe3Q)(`kqmRkBk_8jnC4?6M6O&iKecnwt=^-gzJsr2@fEt zx&;E+(I0w;13&)@W#(@bp~i#kdP6M5X$kdLic`?n5dHkGcHJxRgV&TPn4$k>#JIpLlG>{jf6K#e_ z_Cy1Zln1487qF!dUmW)NR+wJv#{FLnDYHmQGs>(Q?TPXHDlC1S>6nO;M3#ua2> z497QqgImLNXUC-6FRE~Ieqa(G+HnW+39Q7L$sW2YZls@I*{6dqHc1>pHnF{i36z7< z&-K8jH6DnN2#c88kc&ZEQ^DcB6Yfn2olIE(1@S9(KdOE=t*oq$bs5!dx4z=G!gAcs z;Y>cW|AhXrF)_gSF)%(c$>A=R5UWWW6TwXh;(mg$b2u-}FV*ojmi)X9oi6j+sW*2J z=DP={>hhPbP>P+JCIT@E!I&h@ugME}Z<8LiY_N+Qu^dPC3x|I7d`yy(R*S+ipI4&U ztm@m3iCqFmK%j9%PFO=^ga}&wQKYbOimPSs{FCefv#;Ds_Wc{X!^hHLzjecBZcp@i ze~r=^xyI7SGBL(+y}z7GFAU!NhZwLw)Fkm>L@L1xkYVB0AT4keu5kYbF_t4zqYTE9 z1M6A;?Ub894r(nh)DKM z4ajISy(4uo<^Qpdl4YTfwA59tN8Nd#2jlO4)TUMo*M-~1KGL-ODUJEb-}EJ6>d5DI zv!mZpm7G!o9}4AWw(iXvxV+MK#Gi?Yp`-tqC4GY|Ahnz*-)8XDyqr|)rCg~#PoQ{- z&c9Fr+`{j8rVQx#W(wImU)S!|=e&{>kaRc0kFLex#O4P4C@MNkcxtod^xg_~GKPW9 zx@a&#qat)4tO*G5BB=T+#4T6$d1GPD^mLfJlcFp89f!!z*EwZd_Hy5AaS#|wu+7y|c$67tnOuqA zXT3kbS=IFuN2ai5=8|s~y{_+hqc|O4ZG6Je146|X1czoe?sAbFkpgjE7*Hkt&qSOy zA1hOsuqn%{RY5sasV7xJ?WTBFaUl(GaU;WuOp6TC7KJ~)Es1Cgc-;OkTxwQ z<>x<@r!WY>SW24~UOhjv=ARQN&};gm$rqegvV7tw>ra=CMu&@N!)aI1C|CsKF63Km zR2@JN+=^UN62%uG!~cQe)FnQE3md=d1yzTl$7k+i5w6lDx+HywQrR5OLur0o6(;Gl*SXg z!RGmn${{p=39X=y*F)tQ zh(0oOzSPAAl9|)}asquc8(w#6Ax87yXR%XBq(n+Uo&PI4Fzep#{`6esLD58IUga8u z6zi`O*ovo=dns2RA2HE{g^%K74f0=ZGSQ7{&1eb`|7}`D9;qgXD|K%!+r%Th7oQDo zkU_w;u~88?N6Z8x#;fkB#rN4_uuS0?UI#F^N<-^Orq&ha+}pI*^2hHY#V%vj-q5G5 zj22xAAHlTuR=h=6@J$NS!?v|#y-t(=DPQ`rJo?-snIS7kvVnKvy?n-0NHK+>yr?Dq z#Bnfj-69W+XdgDiq%&XTiIl~TvDrqLZ+qpWGQ95EIV#NKD9x&{+_B1zTaJ_ncN|6Z+H=gA=T12YgEC|b47#n_$dQ?R8*ZEX( zS1bF(wrg}~j^@|958d^CIZ{sg*zPvFHNd-?JV9u)T&vD*J^Kl5WU~AE8Ok%nn>>lhv^}D z*8|wDfr(;-`i?Fpnlgr89aeI*mF;ieIS|3RyPe(T8FO`K!t$ihYrv8?vUO`M5c z6wf=9Ql6FJ8Ns|S?~W+s|iz-HrRf!zAYZ5(<_s^dE3=t7c!ZJf() z=u4|^Mo%Sin9$FPLZE65T&b@78!HafDXIKc0~DM8s179J3Jh>;s)3xM+;F^|t`I}8 z>m+dxM-b~7j)IAl=ppqhXMjQ%K>DZe@~?j0Kcb31g4VHg*18*%e?xkPSGh}o7*_ZT zx;pAnWljUF_EKY!>D>lXAbbdUO@^^K6mLV5gy8jDl0@gbS6~Ij%jSJVFAH&>DVLdLYdlBkD^2yWZ@MSdN|Y=wL#K{5>yYV$Y5_l zVyK6!EfvwO4jkODAS8f-fUp7Gbc98H&I6DkcVk(63KV_^nn%D}38K)aMH$bOSw5a~+fzU5+D&vA2@Bj9 z-U2yh5Uelygc)tM9huSK88ql}7cdlU>rn)#<97ety!=60{4BPtq6j6Q`Vf^h{C1uH zupsyO(DVrpS=#Q*vVL`>XdVueVQESRdosHA`J^IA_+Ab1RA$eAa&aJBRX(LQab@lk zzdb(DfsrrK+RKs#8wSBC?YBaxm$9FAE1WskiL+PZ^w8ma zuqzX#GXz-jl(fXyQyX`8sU=+9+cGAHfy`~sPyy$Jc0y$e`0~qA7LTnCi80#5B7@8!PHBG zW0-Y7)VT5?@5wsEMkBo&wNvd~boseqbt)Kuh12H?XObCJ6JwpnoLr@(xJin;jdXv6 z+#$iRYz7=?O)fM$XPQF%(rF`-qFO|mSGcTPS~m%jk_tFxJ=N49cz#fwZ9)$7k04&Y14qje@*gzeG25 zi|?tM@R0LpEyzF<9kIusup2eKul9~2x1EB%whucL$kba({0nsT2I`L7dRc+*ypE$K zRqGxvwIzwxJb^1kfro?rS(0?@DDw$Z`jUJr&us4B6XsUUyqHgE4Po!;icd-Cex}-& zKThosx$|xAy-A&$Pqa4l=540=lmuBg`yhoTF{lq;5&jSB!(%sI7;upf(z&vU0Rl10 znAlVMa?zv(gsyrC6UB%2j*6!8^B%oG#gkZ~w^(ER()_({VX%aMqIwK(@znN>V37l0 z>VCu!5i%r_;?o^mM}je1?X7z8D$Vvf`Wg#7^r9*j&+*%vS};uRbk1!ecxDFQ7rf|C zFlS<%upP|0P!1X2MGf?QU1>9<;1foDX-_d6O`b=;;%vt9P9s;4w~0WmAcXpA;V2V5 z;V1NH)bBU5Fq@}mvT`Z;g7;Qi$XYV5p#k`qhdiYZeOf?L02(DOgDLJC8BK_(seg_y zz&0QP?xb3&xQ4cctaK;P>TR^}C;qr!3nC}Kz>}l+0`-1Sh`k)hA`Mi~Ll*Lffi3{s zc=Lg^dOWJq7JFseKX2C0@joBV4QzOh2ZN+_7LohK@6RG4$_$H&TLk2bUKhPQEW*U~ z_Xw_&36C;?9Ojxt!|n+xx-J~*cVN2O|Bqyb&hqN7!`nAm?w^Ai%7@gmkLSL=o(}U( z1L}w|?PP@>G>7VR4o)E`>z754NRh?NRENg8SY&*iBYm%M?PulB&a3 zFrJEe59M3f2f>3aH|I}4+lUV9A_OV3hcZz!MM_W|nV!*BtO{JKEJBz!PMigT&0y6S zJ|#T$Q7IHwq_s3aP4bZj10;zJapprp-O!ff6?|6;5YQC}V~rK$IwcQb#EOLEHN>~l9w#~Uep`)=)8`Yz4!Uz#T6;T+ zS%`H7qwxO8L;CN2`#VJ$eQ;+rp$=-bc<(9v^n6FCRI@;WX;~10rr10+cm9|BagV%@0o9 z<(OmA)(di4d-mu;vi%pLMWa z-a*MH$@)p|5f}XC&cNxkU;eh-uvap@1uyb>wgz#1&4{=NPss~n_u8qOdta50?Z?1dbwYUpgkhIS; z_7G&oHSJtLC8ohiib?^VpBN6ePuZ)brk@iPon;ZC0u{gT#g37x1RTIunTjZiN&)kI zQS|)&^NEM$Ok#;}#aLZ{UKU<7zk)s}921{1^d{Z=7fzO#5LjG$Nr;btYg?>oyGuBR@WD-;y_y-Uc_o+Tc3y(@-aqfD81S z*bwBy>|yOwraq&~yySTaEDbO2kYnnp=mmH2s>>#eJI)c~!^K4vfE`lM`>{wze-OW- zmV25WzP$f0sBAgL-j;BS5LUqct3nx0Ps9eMPwVi4(7(nAPr#_3s5n7$fZZ752C zI$^_!oV(jTV=~xcg3-5)p7sr)?nrn3bA-{JO7L8h=w~GKHpp@3)E}3pZB;JCiJt+H ze}VNnBDx5%cB8#D8*_Yi{1g}1KzOAS5{;|(WybHfe5q2EyWAHdIa($Ct z_=&YjIk+j71u7A<9m4gG^%1|aCB_HsIM4p~MS!A{LKV_hk{Aylc>05KAA=a1y(l=h z3CXW%UyT;90%fWfBYsG@kovrJS?>Xp^c`&eGlCt>tybszAm=Kf7y-NsqmhJzOR*$- z^sHvx_^5fG20HlFJ{2Qt|oC{3i1yG|M%0P=B z?~v0A!400LVU%(^EtS$kM8na0cs^^dyq9tIXGKd;ey|sLJk3nsVf9p z8z6X~!?8z}N7Dscd|1)-6k=h8+dS89M{ARSpOUY6JKx>)DqRy%4vr$*Kc|nv$E+Jq z;7aL9qhumL8SW!-f7a9ukEI9FfQ0x2q|%ISWmvm)=K7h$*7=apSWHgC*H0xE?&rg9g{JWv&rvatNgB@Khdn&X3&96|aN#y%S2j9lhK3u2n`#Y8 z_wk=-8-#>qhFk>i6aMej`xTdSD+2$;fqngt5_tt&BB%fMI^F?&FH;sylb_>J0;%+Q z&^Oa#u<$|$7s>NxKjD7uU!0x1dmR1<*t$bzc;FN>J3=Y!f(0m+w=|X1CkaDv%Ym+A z%>W1dL3z9Kl}6bc7hABfLLJjjmV0n>*$;VKO1P1!yLRwXvI|(`u~T9z&3{@ips;tO z2v)1i3vhjp1Bc!L-;H>PjwpWN6bbv43%xa?2Bid(&sk60`a$mzi%gv{Q#gLzxON&sx$)fK zzWwZC8(~g=v?9jc>3vR@-bZ1fMj{RrSO=aQD?AY5 ztX#pzcW~LOapc^uv-zL0vXzo9%A#RoERj^K3nHcl&knm*B1O^&pvrPrxcLuABD9Ml z1=AE%wyZBc7!~Q5^YXoNS$l@aFHwR@UwsR`SAN5Y&(`&gZSwLm0zOsK% zCen1WpV5Gt%0M<{!;AZ-fgcs|T90luGA{Vbx8t_oDy8*&qhF!crs6kp{Kp$} zt~C9U@!)p(u0A~>QQr5EXJ}IKV~C}@8ml@N!Y7~?{Bl?B*g`jECo~MQi&I;dPYlK- zpaMm`;Lp(^&UbHfFxMf}+?CFJdPqXZ+Pj{XU8L_*`B^{or_?$^Xw)2+bnsiozH=@A z8>FABjB~U~5A-$giA$-zueDK;z2cA1@EnS8E)!0+zNoFKG;#la#wG*~DtfS&te6n0 z5M>W@B)>jw(D_}TRe+~a0WFYDgTUN>fRJ5T7=CB-4v9<6C`nS1HFF#RDBw(BLyKcZ%nC~O-Qwnl0Ek?#{^)dGHFWkcYD2W~|7#j|o zYHD(;Y2+Wnss2SE&1~d^PH2D4VYC)TAyCZUF0uhK)ll@Xn zEI{4{AMd2b2h}h(4P-U1AzRXi53M92v`E;!Pm5+3|H9GhT<}(> z5hGrIPx(b~rA$&6XQdOC6tx7$G_z6VdF@z-UI^xc#ccW(@_3y{HR~8C-tg~*` zzJ5%FF5iuRa+c1DnDtrvYgJK-fb+Nc^e%FaU0g;uWK)POBRY62OI^VcbOM2Dbi zUP9H`Tqr9sv&!_JF%Nj3sfTiXQ-Imph7jc@=yNNv=M^kC%c z_D}w6G*AjpVhH0JcsbzMvBe20Sq5#y=2I;TKLN@&pS8Rz+1AN}pP|jg&LiAe5FrBz zk2>m>49Kq+SmL8>o|vm&Eh(4Q^NEf`{eSFz31C!3^7os`op371p&U`e`9KB`h+IL4 z#trKc#dsj1gvBT-9uXZm5|z;nC|-=m5M@z8MHECNq9Fmi5f!5n5eSIf_myj|?^o6R z-n=;zTy_8Jx9fJ8d9RPE?&_*vS6BB;x>HfcESmRh^@Gb>uOIWsqu&gh_fh3}d$KeC z_QvJwznS*(ru$z1-r;>>;nh1+o`2%bn;&iTXw!G&<_%o@W?I+N-Fxq8)@bn$3%7c= zs8_FS;vU#@uI;C$Uq`i%d174i#gopO`D>#{V;n*N7M}Rz-l9qEd!-C$THNYDRQtFl zueOhM=3o3!)EgfzUDUGThsO^$Th{dX_6xgjyUbd!arrJ+>krEl`c%Y?e5$p z?gU$fbB|nmq^Y%_5|gz>>P@EU-zJT0);+f8*bcq=Tw0q_vu(__>?KW~Z?{n0w!I{+ z(Txc3I8; zl)ZBk=H;cM%c34ENa#1SKyl_@d)F`K_7zDZmt5N@hYH?6@9x6815y8oTX<8|!^iV4 zF4%F+i0)^7c6RE+4VVIk?)kFobj#q(0ZpGjZEoD=q$<x@qJ46=TSs>tIFG7C zTEB3sQd!kKWyd(>t-Ac%KFu5Qz=gjmcds(He@PixrR=V_{=tb~-fJp*%RWS1_wMO>?|;3dO~Ukjz+4wW zH!nNKYxZ<8UGw;mFTDRs$*H_}ozihlqJkOo{uoT?#@5_I9nkwJU?)3L{ zPtHzjUA$(=z8=rsHg0Y2eT_-IM@J9pVk%zw?hD>1<&i7gDP11VR9@ONs^#nPTXILm z{Otu05dUwE`QNsd+FxiDV$ARA7xl({dDlZZ zzGOWM}*1yN;Kwo_nbB%-y%&cKpuSMWy+e8DBh=|Cnpf(yCSC z+uXKN+1Bp;O?_AN>sA`&%}z*?%)JLzRiE2-S@qPff9d&E z&*!dR+OEL*!^)ReJXrK#@~uT{rtGe;WINQ^?+^O!fN8h0=hnuUUuQpXdawATYvwrr zF|2g{#R&ao52 z-s}Bs?UjcYe>rvLybhNinW`*$wnMXZwJBr9jqecuWrthVpE~ce>)HROMo}x5 z#oY@fIP0v%`D?RZvz6X>+KR<-?p+)cJFkwfXGq-R2-uY0wiP z?C7AWJ^FkTTBF86S6W9upT8)6``4Sso<;_7P4wpG$#a)3?({j7!sr+C*Trw|ynOZT z=MSToXAiYKHDs(~M^(lL`Fm$QyZ`gJiceNudtmM9CtF=SWS({B`tcaQ^qzObMDJ>T z;pmtP&9@}1%S$Y`y)|UTnrr_~eP2AlH0P$xtG;NjH2T{a`5PQJz4&(jBONlQjZbVb zWyScBans)07xi|#hXy}?&fU4@PtSQ|`=sw}*Ul+*y`6=!z+sreXJ^bB4 zhiTsE=6~OR-^34=z1R`@`Hq{TN6#^pHpYCs+hU$} zZLACU?#f^9jvj57PluV!i(E6WEp0XbNAumHSSEM?uz(j*VQdiGcU@fVmsrX?-KRmN$0@ki%aeIY48NOpV<5Q z7ti$mapxO4I9b!Jl>zjL>ZOX{4*S-CC<8`n1FN5(N zy&(UltEMOXZAaFz9}m6vrunszCl-D)tk-+ibq{(zy!Neo+tp1TJ)rTj4s+uMCBlYY zw|&4FU$ki;oYdw>MciiKlb~*&`%T)u>T{+m`*v1sJoEMf%+vurOx2IMesbLSY~THp zA6;NFL7{b9n6mArr%HdhzRM%-b#CjrgQVmZ-gm}XwfDbO+CT2)JGMQrf5r1Ze2Ek7 zKY!|EAX1SSKelD9qonD*hptoJK0IRa_{sn1|EXiTa%Ab|<)y__TgJaPaO33pKPnY* z->>ePSUk(MxcJbc-}QK+Rd)9Jq007Nx30gly4$*+vkS@&IUk+7svq*Lc_X3qY}evm z<3Bn6%C`F+So>~moN~JJfx8ml{b=wR@o!x>wX*w+mQ|*_NjICPol$$`f}|7AO^92! ztAo;U%EX`Fx#+eXRlr2~EuNm5)^6_e`TzX9vhc@N-ZQs+_Ws~Yro^^Rif()O`OiwbN7+}>>m8Y`1dZP*Z|Dt|?U}f(?^i=yPu%#%ptpLi=r-{d2;Xt4^_@h#lpysQ0=n^P|{HQgUS?V?|#A ztK0JjqMmM%I>Get5@lhp+dtoTPm=Psxw=)peaYrgm-Tvo^}F4Qe~cShcFnfCQnO9F z+YKwfx1_*(&9UxEuRSf4SzBiz)6&)R+v}OGG(FdD*!Y#ot4}J;R+aX@>FRYQ*Kj?Q z<=n1!FEGEI7u{;q-W$iy*i}(^AmPi8moFbO_U5je+a#S^xoc$1=yAEwtGy^i*I@vTqHFQ-jg^FmVVCTkP($8PvX_oR1j{b1=!+v;L7Z=PDV_lcCt z?`pq&!rTw?yJU|jU)k>Z<9#-*n!3O3KVRCmDOOpsA#UV={vXV|A@`oP+aH}fVbae{ z9<(;ecrN6l;PK_FJ)zY62m|NetZpE?p{&msP#)VIvP}aV5X{Xo5wCH-<$@a(G zJ8sRJRC;xr^*!?@etq_o*{r!Mr(XTQ`%{anvSVI3d?Grv>HRJGExf7cf%4cZr+vKj zz#Fr_SuuKC;qK+vdnV7FaPQu^&Iik)e|#&ZaaHv3wJ8a=y#LUe!?kA)tct$Jyis{N z`ME*O|9*EuL+o*@eoy4}ay_`Z>*|{xDXF=5{U`h5J)fLFtk(1;7Ysf$?#I-lhgWYX zJG?sg`5xb|J9ysvHJw-O%PXpwQ|f(g&FL$<^h`@zHm!QuHDj+xdHc^uZnp&mVazbK5rqyvxQeyRJ5AkolICuRZ+4l0FHaryQ9u zx-9XrpC(t1{P6JLf5tMRJ8gTKa^K=MA9npIuF=LPR!l2$5#t-By>aWm z&T2dDuDb`fTQ_-Ov+HhpWn+!kARU3~wI1Apmq zbb~3+73+Xen{H};zIFN2Cz`i><;LM1(l;JhGM~^T5jTeVM&Rzk2hU+!Y1>rfi&R^0I68UU1@Y@uar@ z7&-s~2{*SHGsu$(%DrxrkofE$S z(EIg&k-?ONBFRu{*g+cv57@_u*b z%{+W}-6rL2=f9?`K)CkX=48`*kL;Yba>t&3bemHB&A~fU@4MpItM5JBY0{PlTh2dY zb=O8`W({63wr#oX-l1olSGj-YS*=RWdAhpgq+eWbv?*Uc`RIZNNVf5<~W z|MYaUfTv0dW;>%WzRpO2m9BH1mVsJs%?%mdumVJIzRL%Q0c5TxkYTNjw*%Q_m zU)uE7Ykr*)v-vTnN%`B%_g?OO!@QwGyT(8IO24n(JTP_D4z+Rd*J{hphs-6(*gIP)*~{Db_Z#WyZGcG}3#`YYQW$sYDEk9p7!Uv0bfUDxqG+mGBd zE%DeFPgvHx?m6w*Pg9i34!)Uq)yG5TH8H}g)Y*5bcVASWpDw_De&O8M`?xuT+wN;? z$GjeA-ai6M)~4&tTMOGf`r$o2J|1IQ-2u?A@Rl=2;l?Q64W;kwmjT|2d+Y91|i?-*jc_PyG< zYieR%?|%H1rk8zxW4~k5rf0V)ZTa2H?v0z9yBD>ZGbMk=3sr-97O(95;(Hy&ULUn= zz=M}#F@Mf^os-w~yK&>p7bi^|cjSs?XWso{#Vz;tY3aGOy!EgF-ses{aH8p+OFO;$ zl-O@7EZ+UW2_UrgA1$*=hzw4e6y&ZIlyGdd3K zu=cG@Q{q3oZ@}jE%ikS;_mxW7kx_4KKm6Ru+xyR-o^}oV$2;2PXKW?lzF|!Y`8+zC z-`+GOt)|Hb%Z9Do)Ixc)@oN{&?ElEX`O|M~*BK7BpPo9?lzsb<&sNR6@1^p$``s{M z@`*dWJ23Ctq&DyMTJ!=&9<=f4H8W($ekxHF*UPZogkgl#OyU{p6+% zMHT%zmXy8w{;%$<9d|70UbkXL^0*~;z^FBxA=tD^o;VE3d$EIznQG`KZfK~Ymz;xtA(N#sNbq4d!8rDY{OqQ zIm@1==H;ZN<=C^-EW14?Ez6##;uD_Qv(nP?>^8R=m1DDK)lxB6RwBPs?KZsg+P$hd z&7S2}O?fttnnVw^%IZ|5zl%tBC&!H|FCcb^72+0u+{xZzZ?c(bPa07k#4YnvP(H!~ zej>8VUBDSlMPd1M*-bVO8BJW}cRrd1uo z`pkd*lTB(=pAnZ|RdaRx4Kv^UY{O?u3kI$VVr;W&>XCl(YE!}Ib>-&I^Lms8<=BE8 znJ2GSo~bG~J<(%z!26GRrmR-Cs0yl43Qm+Od4YL$s#15Dvg`*r|2|d8skJL2TXQR@NyJ<7X_DwEa*}b@}Rgh?UrCmqt8O;#q!fEo5vmlWsez& zR`9ou>UUw5crZ&mD#%o$((E}|ZhN$i3cJ+=8}g^wVH@lona|DtnrtYoTm_0g14W;P zp{OggE>lFdC5!D0TO6CDGbfJ>QI4wG^I%hKd9XP)d}<5xBkU5WQB@mfhaM0#wG}kw z*|MP4^_-%GTJ^-$$_7xhAq+(cQ0z>REze1P47Ry*z-^rxlZTe_z$spk{j+hQ+jglOgQ7(>3V~Js=C6Q=h_VZw&m=q{c zH>pMBi^6~q4Z)NMhhT}B`-iO51Z2s>zm zC~2_-ukb{S@JT9weu$ueeiK+@LfmRo8|xr3UxX+Nkfvf-)3R(DF)l++2?inVy6${D zNO$Ubv4NPXiuii&XBZ_Z=UQ>1c75=B6{H#Xx z>}5HB5%9vi{^q`x^Q!&e!Dcnu(x*%3a~1(`yn&TMZE|#{Zff72wSKv_sNUWLNhn8E zvN@$+AAi`fRW`eoAAVSIi5p*hMc$S6e3J@`%oY)= z15~k5SpHvRO)y7U_Fn-5wd#QI2QG8}U|KfN6Ih?o!XH)-sYzIAWo6~qSd(w0WfZTz za&~atCtyEGZK83izb083QJ3sRGL0KSU)D+b(M)IOP^Ghfb8pkcVn}dUJxnSMW{Y}& zngMn&<=ORCpqvT$)+S@Af;A=M>oTu@&0m2B&{A4}XuL|71~!2+)i z3qS^}Rjsh5Fd48Iu%3<5>{wFLI?)G2=o2k2iQF8!fD=#@8m!Q8hR-m&r5d(-B`)!0 z0bEIA^il&(oypN7%9+=a_vw5?;F!}-OOOUo~j4p|?_W?Kn;2noq7XadkF zk2;+BE-o5Di)UV4vHQTxeub#wqT)zg!%Ttn2=GR-ZBwMW>V6g>GK?b-K zFlh9hO(tb^63ZS{x2SUY&EN}N=TQ@>>tqt+3}Z>tgHai0;ZJEgLKNc+=Lhl2j*sFZ zNHh5LBu8V}S`WjKL6qb-3;gOCL$ON+9#n(O9ARwn9pdj)os6Wptd78FS^_a7N^D2$ z`mxHGk#aElW2}GzG_shxf=}|GfLS;Yipt?5fpb9T^Qb|&@yw;!5e}Id_!F62QiMS) zkP9Qd7#`3-4nZ=85{QTphK;9fojpl|b_C0?0Fj6>41+EzEU-`*{#?Xw0T?8Im>9?x zgH;ocO-RINU=J+-@<9-5)n>#SmKh8lHF$<+0i&1YRAUMFLDaZ~lUNS`4F66;N4_!g z#1vrs;1Cn4D8$%-o%8#@^o%@RgELE^v<{_z_k_LRS#aF3S;U-wBUqgNq*lvMQEzh6Gey{F|!> z?IAZg>`Z+-X}DBJnV8ineRY_rWfY!2f}=hF+s%iCwQRk5X!S`ftoHJ+YKv+*zmo>Y zPZ9{$@i^D9MK$;Ach2jQQy}(p`}OqC0o>o`e6?$e0r#hL>)y|Y`?(%kJoM?KFCKdL z(iac>+HbA%7kRQneR*I3|M$|sDs2(eCG=CVwll2v{vv(w-^kY{QZu##Y7};{(mv*8 zxN%^1t4f;FZps60p{08o_5{Lbgo76g5N}q5+JN4KC4!~c9lkEIQdE^afpH-j5hzyL zfda8|5d^G7&uNVmOI{DuC_H*;KZRgJ)_5A0QDl|yhrB0fMa`-+v|@AF3AmAsMC*#J zB79YSsXs(j$PPjX50EAGHKD=+iX7UrtOyl0@l{BRJ#Yh$BEbym3{efZb=eaLLEs58 zZ46Id5?;&3sqfBZ3+P`PwUUQFAkqfHQD@ltu(&~+axee{csWWmG1Ak>6aByy(kpxj zRUwcO%K*%>=ri=9M?H&B2z4NBq55?!eT8LZ@9B>r7*^6Cc&GtRHI#GO&2TmXRMU{q z1L6|fu1ItR=DFg|RQ+8|tMa6|!1Vhfj+URf?$8r#f}Y+jbp-cybp7&DwZ zp6k)K)Zp#S!$c7k^5T($6HuL4<>}Rh-eBO$*!cpRA>3zrWxVTT&v6;K16`r_OtgyF zC*Z@?v^_*1923_~Y8ZSooJKF<-)K@bJd;t3S_**NNjfUe<1PuktLAIE6K&V<+C;`~ z@Op<;9C?bMq=av%4nCzM&0%E2GhPC^)V3G|)|_&ajla?I3koO92AZ#N=s;e8Ne>Ns zdZdR&43OB#6Rt6t39Hju8veXEZW-+v96#*iG1*8K>SH{H+NMn~G)P3CLCs|%hLaaA z;8J&{aLW)CcNTVHxN$0u;gX9;I9-Go);HWx(P+BP9?b=zZDBb;O<=Ra#UWe8NXLja zc@vDf*`_xbSx`}ucEZRDL=FMwGb>bs(rM&tQRA{!1iDa9G+?6f+|ayq*d;@wv@?pa z32GFtFnm1ZzE-t?MNxhu29>;ok<^6d8HdO;(--KlR~(cCuOYhx(91lmsF{4GShB-A zqfc60mf1@{h7*!4Wf@CoUAF~nX|X)>R=?PNN?@DI5ki>Nyeih(gqpSe3>=Adb(CkO7L%*nZk0ZHkc-f3 zw$M+5OaJeQVU)Oc{}hPvDbI&(5@{)=Vl-0d4)-u)l&-psq`fY&Bq6=bFauTUyIpc)1{(?J2B!)y zwS*sJKSX>FK1r2KtD&~qCKfCz^ff7L>={Lj-|>;v@c11kF$_}JL<>-Y-AUS=V&fEJ zLvQ5p>I#cha-f5ZJnY%3u{mxe?t^D*Xzjw^kMbpR+Ct6FehpA!+&DMXz=JX z_Qzn%cy0k1fxrmyJ={^J7Bh|7Xm=tOJ`XW+fZUkd07?{94YDK}(w0aZABN{xz)`*i z1p0ueZ`m|Jr`mJAX$W2t`9+{lK%|adn-=KvHKPY3CK9D(=WEez6N!UvcM8iE4cnfD1)^33CIxLpBSHth1SpPbl}sRo>qPJ-piUX6 zvy-9@q@mBk3M;5u@+qKNTD_BdPDJX2ReBuL_X}D6BmPw(1X$Dpw-+LD!r}m~fP*A7 zQw@s5Y*KQ-YaVt#{d@$zS*6)~*(1$aE6KUXGZQm1M)(8SB~96dNXk_ zPJYH(3q;`%S{Qvnoo?f`_!yshlJvD@`eZ($PeKL40nM~17yYTPczCabB(JHT`DSHJ z>r@{G@U2Qg94`}5J5eK6sy3iDmMPye&WGJpSOTit5S79YIq+92+<*>j;%C{(vOzcy zoRB1d0g+-fcWH3vir53lf~3tCC!(KFVI$>78Wzhsv_Mf%7Fq7xY|1nvPmqM2RMjdX zUWJo{K!L!Hb@r$%&4pp4iE{W(&4j0^0p1TDPsSdaofjyHI;%>J2T%y;DNJALw|~2r zB4`dtlQ*xCX6>Z_k%(34Q7DAmXqoh#Sb!=eCkO(H5A8L?3vX@2D zh~bmgUyCb5ql6%u5`tg?eTV^G6(9*6L)77XmZXjI=)x~(gR@3>pA4kQeD(Qao+hz5 zreXz|152VEK?xm53!asQAq1H_{G~XDN(9mGw9&QY}q$8Eb*iz!mcRDYc@3yBa>DO70q2CW^3{ zcKpisR*#b9paEzOTKn4RXb0;~UwhiRD?A|4sWduj+UwpN0>%a}kBm|l?g}Vak9xWe z&q!}e%vQsggWtF0UT1?OoIkMN$kt4_kO+PH+(XhPg+q5ls#6>}_VeFx2kKqI-^9?- zrVN(sn#V_;%>vQ%8Z>IJ8RX$nof;<=`6|SZAD#lVQ$}nB!8YI&AN;1VcF-c}aVVCodU7QJCY&i-NsIjwZaQkk~>$AZCW)O%y8y>8@aeQy=aNBr?Da zBzsfavg7^Z95?wyBuMe~qdtZ4{&WfSnK>=|*Qq8_P%rf?GZ=uC!=b=H3I$t`N;(oJ zX0$;dvvB;0a5PPN(M%wP{2HMdf)b)ec$z>SKKaON7#8%2VzgxI9HWBdsWZ(B=ph(?;oBIcH&XmQ@n(2)$r8h{CzRwwPF`r0JFQ4$BYq7`yr ziy2FfB7%YSbuPJ=Gaym(M2dD+NJ9nUCfW(Gli zfTm7=tt(3%(2x$mDpRUH4L@mk2C9l;A>=++@VPQl!BKviLjo|WR&0170y~Z)*bByBuf3Uwr7?gVaZVhH$fI`B^^FdoNJmD%I>KXCr=F=7 z03hOhHT>01i?uawv;`a#1F{1r;j20*zOWM3@E zo+VHcgLf5xADG48cuE*`st8HU9Bk3}*9OALF$YV`fucUd2AHOwpU26r;}<^IOjB&#lTFn;(k4BKyjEVbZZbg7uV(# zh3eeL1&-q2t5DrbVR*nam$1Bkr&t!q&B&85)I?T_y z2x7oKEOEb49IhUsE0_Z2U5(zojG3YcQE}%o*w7&rdsdz5Ibk7Hcti!MCx0Hoq>L~u zm~{J@96Uu5O+Xz=1&5~qhwv{d7fj&j4WB0T*Bu%UPsr0^h?-9`Frgn6!rBvWejD7P zxeIxQLKZ9Fpc74+sQBx0ztc=Y0g98KMa7|cC{W)aHB!N594mHGJq0+uG$Kg%Yg}`Q zJVectAW(_W2G5uMJ>ALYD-*%wN&zWQ-;<8Nje1KOvNrTXCaNrV9 zEpXx(emvV=0{Diw_&y)whN-n(K}R=vi;<)wpjtgT{x~(WS70_Z51}5Y8yJp`0iD1r zY-CdddZfHE2^SCA2>jSxKK<;Xgdv-W-6Esf>V(p;v3EkVp(PEd{kuah! z5I>D#?BT!D{GLp4BS|q@hx3FOOoU-uPdLWq zMG$z_kWOW{tMF$+a&`A8QRpAzUmt;py+W7aM42CfTqnd;`k07+Kl&ObqjBUT!uU$R zDEFV?7ytuE5jscsJah*F5TlP!2Zq|0mthc3pkcC6Oso_chhReJkE-p;P;!|R1rWD?LTHlM%JNO2m3~<+v1lzQmL03qCRz$Vp zdQ?qwi0p~)HRM3`1mkdyYIJRgfjezdMpx_V5r!O~QeSC-ORJ$-t?xy)}AwVtI zU1xi`HjF)mQSN=`YpcIq{o2H?VU6-%5#9ZEWb=pP7;J13j#&8qEt10Y4E6}-9R89+H zNFw6s@@!voD0xm6-KcrkKQ!OJ@^Em*&Ps?u3Y0H)P zBF3A1UX5%pbSh*+^KY`ih)1=Mc`}YB8D7ObC)>jKld7dCyMT^2dSXF1YM`(sgxT>h zaBpc2B6*wXd%@>W zU?Ko5JMuXA-$ygu97P+|8o@M|LbxfTnQFR;O54EW@j(ahHguR{2vK0wMq~$v9D?Qm zL=?FHFo$q8qXM|#7-svZhDwp3NFW*mG(s74J+i`GExMZbnCU_&JyZ|H4F?sPut@0G z%Gl4)b_ATDCqn8yxl{5ic3YrOaqmNp%?1JG007}`BW)nTk=(P_QH_C6%~M9sNoX?x ztF*o)O65&kemm8Qlw#rvtr&t7L+F2Bxn%oILIRj$~BOMK@ql& ztfAJ`pt_+aAp+tWu_h13Pm*ea5aIEYA(O;U|9irF?P5!0f(9jv0&Fpe3G3!c8IEMjdn&f|AuZe{cX0d`PqC#iwm=U zg`Y>n+kgyWJyOfF*@=azho~qsj166^ScBjlmPVWtKz)h_m;UgmK@sxSp3v%0 ztl}o=ApETl0>vFec}crK1A!Z6sRzVL6gANAbyS5_f#m3AD%Ait3v9bwAJVU2 zz>gPE8_}J!Img2;>2zWXR77V2I=mH6)8h zJ%t|{u;&0tWZ~ySB5ABOEJuMFi_bArX&X7BvyMbiV5>tYFj<^~ZBaI?GApZBnUUNP zTaa(44JZs5Z7CL2G8BaXCa+jSc`9{rEo*?{BM%Ci@Y-VKB`bWqNe^&khy|Aq&C@J8 z8|v@1)tf4)daSfwZ7Rb-2)bg?nWHrVsN-9W zV3zWMHCX-9(NhWr*+0YABp2}N1ixei%FYj+l-w-dFj4iWpwN#z-Qo7ifr{5 zL+dr!^0u&}6Mj;Suk8^`l2(I`t0`ESrb&`;R6!Bs(9K`^KBngL(>5oecQ6_Fk|)FN zrZ`Va1ZeI+&Bw=Qb;D|TCPyG`0+|A*!$2V@C@Y6Ingn+C->9SvjW~nm1{7YsAgXw; zLQoar3`aQgwu_)Uc8IkQEV0E0uF>=Q_9Gi^k|L(wc*DGJ&)0WXJbUW`58y`V6|qqc zEvcQc5_YPz3Zvvp)|` zh%}%SI&e#C0pB$od7#AqdUooX$aMJ5Skx!)_&pumGvf1Ip)srmaF|Hao-Ys( zET(#-Cp$y@yCd=(W{igUj^o7OoDWg32=M+i`)bJ-B>Kho7DPZ-h+EG|lfeA(GKOT* zpB7EnBvg&0nVJ(s$pW(Rt*B^5;NrY2If>~Pp_m-M&A&#R0aHfq83HxY623X^C)aNi zXCx3n8oCpcQ~JBZ`>hI8o;c_o(kHZwCq7|!fjN&Mf~oWTUlZmPTY@m!lMD+tOnmyPz<(_Mxri0>3LnwfB)S?Qj!73)1X?(J*77# zm(toklDtL)zf=fRL$^QEzvu-@(n`{zyRCK(L%XiTP-D2|_%3jAZ3Jd6zdN{&tT3IY+3c?EX_huBQh2a;EeiFmGWIpQH00eS#;uW&sIS{x9!;%E9Se{KmHFBs$92qYj$a|sP2+P!i+c2=~ z7upx4tz?Z?0$gx3i@i;aOSwtOjfs^#ZFK7JjYGI7jMH#vRtSK`A||ilkOp>5xn>`G zBxS%~)IYN0jQla`phL9@AeAMYjyvdkd+25`7zXccXLp&8KhDg5^syBinmmB~Ba1<} z&#m$zz;M{spF8Ly{X#yXMbvEIj`fxdNedc1aOb2SE!B>M1dUyIv$CB#K}-SeQ4%&R zro>-u^u#tOPf9vF8h|w^vj+^KPkcvpHU8xGDn!*VC#eO$@grZ3zWFMs;lENph=~Cv z^+UZZ{MuWV(C{0tut&5XieCyNKN>j^8TuLbU9k_q=#%FbSBFlfLM_F;FRYiz&yUht z&|0Dax58whfZ-6Z#(sO+1`krp0d2uj5sVda9wJZ&Sl-@2G$1J^$u{6&inVJ&6OW(k z&MR%i!sB7|hCDiA#KGD=E}mg`m3FnXn!p$3rz3@Ei|uS^tPIpc>p(dXF?^^&>jwD) zJ8a;!XMqjDZo>fvMMbax&J0?*3EwmQ+gzAvz8zS^-%(T@-6O=Jpk>vkWF!Fo3PYG* z;LHMU3=>)>5x6g_KU6){=fW#yxVVKqY5sNo*?Io|I*RQ3dGQE8YFVIuC*UVV-*LDZ zkUVej=yFNhJNCRC{Hsi1PaNs%w{o?qgzZ8N;8I*%TThtXWx(jw;?b`vqjzXB{x!?U zhmH%>a$(b9*ioJUJNZ8(O2;WpdcrmG1$^@7E9oR7@$dg@VxlhGjt3R)gW06l$<|?kGF&o!qujOZtP9#KPVZ#b+iTbPJa#fR;Us@#L|W!5i1lN zLJ%k!fB6n`uPsJ+?j;eYi(o4Wu32fN(H0d^!9VX9j*9OjWaW@46c+%2qq7)1QGY~2 zo=|y0w@E_eF=2pP?Z7aNEd979{peyiD!ye|fFfm&I~*p2``FUK`UuNRDmg3|BfA2+Q%G#C{vn(yCXml_7(j)o^sM=w~c@k)_y#?&7g+Vw#i63r+f zmT~MrLoSTAh^?S&Fa0_?ChTk`OZTF=XVm4?O6Iu)rf}ks*EjP~IP+8FCP!Ap#X=DH@TL7beP|N26o8a3qE zqK5sYI&KR4E8%~sj&npfHEL)l)TvR!>;FL%8vQ@#H@FMvBvOw37lTxWxh92vY?0k$ z5pYV42%S5EN;z^l%Z>=Q28jFT4T3DRZ4QlvJp|nDrnO+B7U;LPX$p@Uu~LGKkUtm+ z5oLEHfsPOWhIJmT#BimZ-YcjUKTGZ6pWxOi4@5FlX;>tq)oR#hBx`B2HzKD!uO(vUb0mz8SMZaxxO603)1Nd1 zwTRF|Zj?+U8ujaQK9edVW2C*pFBs#OsK*r*e84RGLlp#EM1(2w${pPy~005sipn=Y@V47p?=1xuM01J>^P4I6Wrv9)>cF_`ACjb~Hq> z{}0D#ze>xU_GcoS|G!)2avGHxC>&>?|^sc4heE_hQ&JwjtBaHo0prTz@AfvKh#EK_=5wI)Cf|*^$yUJ zv{kENls^a~ooEn7a;ohlks#D}pM%)Uq%BpA%0C849d8hla@re-D@KV_qk}+vr(<$* zAM` zAHrZgr^HF z13rv%&-c&9`xIcg~AlHdk9y||U|AP}I&|F+1 z_k)3y?;C{P{*4QGwLQEDJ~5E-UHv!>r#}eFg}4+<#El?;!tdt~IP|@tE;5jS-{Ok^ z$*TXYyK%)f4Sc&{9c3Wk8(KDnLtelAs#~q?@UAl1c35=voA0jGnvUo!L+d{@3_!6H z?svJ5_7n(f09b;~pj`Uhf2gP2j?BCB;2PUGQWt=f1L zNaoC3i&yR7t)#DBYQylxI*L0=^_F57DoYXVTFL`wo?O15Zg}GC1!Km{E}uPoc=>Gi z@Wc|ZQ&K*84Bk0?T$FmTQ;6{t9ga^JeQzaKhtPTYir(QY^g^^FI9LPWLf00ttcxs= zH6mX;r@24{VyTZ%QIxEylDW`cU{Da;PwfyTBw5@iMI_|Wv&+jDjHwwOv!DdsU+y7+ zoIHGT`54b|a5%=LbCF04sHK&Z+@qKs)Qjs0iqLNmG_D>@#iETrSD+L#;Rj(BS zAV&h;z9MfCZhW>vI6-!)r!v|qO2kt2sK`uhV45%&sEMC57odXr2=Z0x#ZY)lkEk`n zqlkyv;Z2AIqJB8@QsN#14kl|HxYc;-BraO#6)n1in39h{r@gd)(1bJuCs3 z@I`8or!<;K(a2-6DciRd3~CwQ6|WY$A1X36zXd;u#)KvO|Kjpbl55`lwET zY~cUY?dUnQSF0vK`X$97`@4k5G*FB<+R9Qa`~!%M*vC{q{$B%P52+`ICzdb3Je^Hb z6tpH_vWodya#9KieB|DuO45m}xTvifH327rcca=q@VAoXXJqSvp(T61q+{3*k?%`48vr87RAWyFH(OC**f=%;EZ_%hxP|#uw zTbJTnk?dDiH&Ubc#6z%Js3MSuC#af)yvS`;U^1ZG!O7&L5@^WsUYojd)*L zi96phm$nDJ^g@F|(WATfqcZef>9!Dglu|&0qJ5j4_=`+x786?^BS@LF$NfHj)L2XjG9ZkhUYOM_PweCeteX zOYh2&&O_4ZI}4xdYqK5lBqOyCk-Fg7rAQNz?m&72$%S+bX&2H?q%BC>koF^;M56xc zi$wi-2~uw)s=Ff+@zW5Rj5HhjgZgD4(lDe8ke)?)4(Tx@8`8t_-$(H8^GJ52UPxym zbwDCIjCF_lO!+z?QJ-{_iTblM5{<=WNVg;1j8uhGgG7DtGtvem8i&nD)kw#Y(vSut z(YW+L>WV~lQJo!;s86UpYBv-;k)EA_GL$0a`FGw?e-W)jAJKaS(#1%ZBT+wS|B{TP zBmE7D_@LBLrhlh>t*lW7NVcdQYLot*hLn%=Ad(en64E_LcOyN7G##lMQY%B!>OGZz zf3Lna@C7h-zcPENb`{9 zBmE1B=y(Q+Xqt_*0O=JZl4F{~q#H;s0_$(c_dlvHM}i)bNs>{b_jRO~Wpd!(myn3B zw~$^#(&U14U_5uR^*3>3XDhkd`5luBHB+i$wA>52+Z5-ck96$V9k2#`bCM zUx!5PXCtjZT8l(|{5BHxF^%i1NFO56``@#D>VrNq(b%OS4MU>wqt6!^(r|oEMzno<+(>Dv+rV|B~(^d3XVdWSVquL+4mvKN$HZokQ|RGC*{A6vY&afA=HpM*0qE zBhn9e-WbV@&szIL1Es+F1HVU_%13$#=|QAPNcSK;fb>r!vOVX> zM0$hh|E+U85?w0lCB2i2M15mLBHHdpnk*C1MD)x;nt?>Nhsu$B{!w(%93dHCBKNBT49BEGLd8iz#k^a#>pNcl)KmehY*f01sRjil-7p7>1V zf9p5~${T%eh&|Nuv_^hPP3lQ)4fSeejcxbC`zw*gAYF*`0n%qkYminUEkSw%iN<6r z(gvhdq%)DuMIw3D>ZO0Fy-+kY!t=nCSYQ$VJ!7d!@mO4Ku}b`pKB=~NvYtpS;QwAo zb?Q`wd9MENIgi?J>W80F%~KpxK1kik|IQ2SbFLHbW;tfLQe&q$W~JiOhpDE_DQ<^p zO6Gok6SmYuhr^ZXbwp20%^aQiS*mH4qbAin+Tn0Il+nlNt2@<P7h?ywA zc^rwEsbFaeUQVPcC%VBKa)38aYWx((=uEuKoaF|=uGFY0pvRq>0D8CrDgoY7>3#HQ zS-)Nyxkpc=D$%HXSQ?U2SE{SxP^uZ708|BRO*n_DRqu0 zWEx%Phyn4$mBTb~ic64);Yp=FkD7&7bq@2yRJ=h+?g12uq9Xh}6QhtBnj&Yar{ZAh zP;QM|7saWc1U1wF5F304)kFinBRARv#hLUGIj49Wu@gsUQkGg!WSRoPP9yq^`SH@7 z+L5U<7L^q;^P|z|s*pWbm#S3kPmLAhhr#7>COSM*ypGdH^T5t>WTHuK0AwN$TFgWq z3=76r5RXBn?$@b|)2Ni$i3PV_J4&JA*}$t_oSXC8xX?Fg;8+~ zJq8?grD&X6Db#69QiRCiD5VWrVOQH1<%NC1rH?k}{QK3BRpQF%%m<$W$+KEpKki3?y z7Sjl7^Of=w6{hmcHGWn47x>DeIJP6XWkF>Unkhb3p*Z|Y6>t;pSWMZDU+7OQ8c}8= z?-$7XiGSYrED7m_4o6|O#Zp-4vUm%U!m1vwW64k>(&Z+EU}_aE3{W`jqkD7N)1HiS}b@IlZ!en zmRO5MPh4&xe@ypSOzDNF(OQe%0AJpOqGmRpk29oF=8t0UWz?Ldih)A1?YQ79f+ zatjNs+3DIp)J`^KZ$$j+*=j9jE_)i4r9681YzO$WI>2SJ17xEA&=Sbj+mtn@=Q`5U zYb@=2&-J|g3XG!Kw!YW74o7Y}xJ&WJosq3>(Mi?y8DY-!d!4+0Y|wY$qL%Ie!U@CZ56u0*S5^0bK-kP+2g1Uh)8;M z*a@{6G0P6MZ+-7zmCIKc+808`9PoSZIO2Gdy+Z+%>CS9i=gy_SNdz2Lb!lkblqPhj!?#9II>YvB(TNMx?#S4(&bHUKTTNRSAx z9i&2g7*9CywboaBXG&B_Ma7H*DW>@)TT@IkDnxGta=XD2pY5PYUPziZT!pYpj>DkI zouW)|RhUXLj-{ANDm)on`^gmZgo+Gjig*4=YUda}Jk32H+!o;;C?KGxy*|Q^3ZgO3 zvt=Xk6DlTTOqfwpG2?iOsba=n;=z-mRMh&nREvkTi2 zvp%pV!Jr2DXaI>=7kYKRCnY`u5>hfDC1r-YA{qqGDDhM%6Fk)0ZoI6(8}KpTU7^fy z$(|PjF~L(2J7NBOl&BDOWFV)zqVWvMk7~GHbO|b}FeBqa=G&c8HwVxBCff$?ZVVEc zMX&*`V9R{a&stckp*9*XC|@x=567rg^msI%K)enm=3Mny?R1_p^n zW@gY=8fSjg93>ib$(-JfM4P&mgom( zH7PL_GsL4rjZx68O{f^khKS#k*bKoYi2**7Y+#CUEi)?gXOt6yF2~iG;+f+N!=+q5 zc%WqnAJQ00#3|>V+mQfP0f-3E8d=379Bt(f6Xi7DX` zb&0MaKDiraRLCck$5bMjtV>bmAcYj(7@=WYSPK=B7-J-x`bHPaK}NOF5N~TC*6GZs zM6|&yA_HSlpYTSJ@YYs%S+{_s86}vm^$cc40~q8yI)mYqbu6hI5bmUv9+s=LcH`x| zn5{h5Xw89_j%+{fXmQ6~V~|xWeUY)wFg0UH;3{T75;1h1l%x{OO?ps|ur`1{RALyw zVE$nEaxfe!1@KBw80quw1Bf8B6mP z?>*@;qB1~oDX27ySl3|E#qrEyelf|wDhXdACYYvA0_G(oQ%uXSvRZ<<4xKL4PB5#C z7_2b8B!m_iyjU?88QyvU6%nJ96lC4ihteDs{0I^3^Kq7)m zSnU}TCO{ct7@)zK zrlJ(G@k^SYN#c>n6`JV}$b|3Z*|y7KDzt9%!I$}D05j&ph>`JQ`r?Ginm+?D14b(j zCXDIxq+s?{%!d-6;H-$64+2Dn*a@2QFjb&TB4yI4<43~wY3d_zNF;UM!kx4VCfXK} zu5qVq@u{4UWe!-p>4cy5W8DrB%PurI(q(ZHcNDLf5urm4SfT)9viC_(SD}(#iME%f z#7&rw;euUrr|j^330+YE`TbDFlmWZ|Ea*ZJ?el_=2uGBN1h`H8&(rWaAm4fY0|B}D z{DGYo8UX#^zJWPRy;H?i7FuLX;?wv0qn_sS~_saFz#rrWcz06RQA1GfH}M@6C%LAj?AzUZ2y1{DN4Q zfHn!Ul=QYtm~ct^vTCb=&<tHz)wV3;s~TgcDwqhI5i}zkx~l+NVvn0QH!;T zj%e$Vdcym>l5G&qtYOK;5IC?A0&oV`zyEj`x*`|8Fvgq_{GVD!kaPYN0HIC>`SG;v z95Es^EK07A46EZL(;VK5Ni_T>&<2+qWDPh6{UCjw3TEiTPU;7}?hK6_&Wqxnr zw?Xbcex+fLu&)_gd=pgoKkX|FHn=}qqWYZQZ{Q;M59bXwU(o;jYCpuV*%Cbs{r!Q*R*R|61q5p-!-*8rz&=5s zrC$%j`yN5C$236I-ow8(5U{n!fS@`CcGmK^Qlc_H{4f(sfzAVs*#I)Fg-htqF~)9$ z#E2%WD@GRo_+#-%f49uL(w_fhIYdH-_%SQ3b~b8;AG^O)6Zs!CMREJ0C@oN3Dbe5<&J$W;!GFa*Yj$-;V+~#(-=H32 zK`aD=8_6}$7Y0b?gSw_YB7Cj2uvY*>kGHh*#$VZwg13TQ?0HJ7sv{%nG&gqAu`(A) zjxah-4gw_KWI(8I1p~q za3jY2(0ksT49yRm8*o6gTS8;##Sr?3dNU-lGxCHiz*LZ|T1!*v;zAHj&d4CX&^H)$ zrzMVv6Y_+zRnnpPdkhnAJdgvKlug8ef+su_RE&p|6KO1h5-ZZ?0Qh2T2lZ#^(c0Bs!vKz%&Y zhCO4|I!l{uVJ@XA&>WJ6QA`rt3SFwPOS+O(sDQk>d()>>NhT!nrG~Q|r(=tWh1ZuS zka?+CG#4gZR!T{2#rlY*G9tuHK=hRySx6yaTB@+r4W!U47g%^7 zy@YWV>neD5VP7&}VByv-aZOOj+o{h0Ww1ZG2rf^)M-TZPQ!?tXJ=fsEM}U=9M8Zm4 z{MynmVHgyL%;d#0UC>Pfn>u(ziLMvua8t`Tpr@A6hf2@u7nH4EZ!MbyxR!uCTP&u5 z-87Vq4d!ka=pdV$+G2rku=DGZQNZwSgM9u!&H*&ve_-#PMl|2`Jj(@rbu`bpXh|?2 zb&$3s=+{qQ67XxkHN;=!$qviQ7Z&h;FI`xrEp57lek#^*h8U2)NFV$+^0kR=G)jAXyNOO92diY$>sRVVfI)Se>OoMQU61qijBH3VM zB8`nrCR#RPp(hqLRG7>!ULXV)SOgXqM;8h!LU6zp((5>~d8jYl=`f?RI!C$9*U23?5yJQhG(!hVuX zw<8g?^CK+pB2?#fB#@cYdW}O=s5&5HQ5_(U!)rwhG3w)$GoFX7k5-i0Ft{!4uyYAc zK_25eS)b?zCKPVXLj3>75ZuaWsLKxvNDfe3O%yr2ez zLA)m#vIf_*o<(^NzfKSLdaoslnEF154pDkP7B*luJ^XuwJ_4(i2bKSC)H(lon(NyD zV}rCg;#mvM0zeTio)qujqJlhCoXDD$1R#D!}q*MZ13tTV7l zMH}c!E>195PwLeG*BWAs{f}jEO}-5>?5c@n87g!LcM#$Zl=Q#~!|axEZNA+y_K5K+ zZy$Te1Y~v@IK<*Q^zNBn6K|Us;I!Yd3WV`srH*c+aDaH>or3zq48cJTv1k^DIebW4 zL*sPv1FeTXa$#t_69vfmRwgv-)9HAG-18!}$7dXzmL@(o5iis=3fcxNZo~oz9wqDo zg*g#nXdkW!=o)Ah_PVeKN3IXqwSWZ$Ibnq3hO^)sLS0A!9xBR_)DO*`Gf!uFbj-mnhI+>dK@ngp>D{KBiLCUG~o5H@LmMB zO3#^HG1Sq_E*&@!3v}85>tdFEN}R6%BFp&ZNhQ;Ty)PoVo{<8?kKGs(54 zF~ls^m-Og(n0*;uA33%i&3{Ba`FXvYQNEmHcl1d1Q+_P0ma+Vw_T-NXJwY!7auIsX z7W!#$>Hj_Pm$3qt&q(Jwc?kY(tnn#LhDrfApsn2D!*0;t9t~vB))axxpIWBe)#k1ND^1K2!Y96$74oq>_95wL_PeX5Z-Y~t!@ zi6t-wSs+?0AUKEi%f#VPB|V-12(1Xnwj%BV;S~rW)`RuKLJWzh*#vaUmfKp_`n4~omuhI+}j?_r!)F#;Z8y2C$$ z5Fg}w9(Sszq55N7;!fWn{SOju1u89^w8h?9Z5 zR7EuKm`5B%i;x=4tXr`{(`pdAdRSbNH-YLBAu|| zI+EonchM*PQc_9{Zlr=mk&?rQdBCw8T!C6khI2?R8ts(mI;b8pZSh`k?qdM;AC zdbkNwu0N6GKv+Gp2g1;@X5|G51aE3M(3{LSMjJ##kyzF`qQtiVl6=rXCxE)kk0j26 zav&+J<3kLl03VvAmn5ODsx1iw75qC2ZVvYK1W@Gb%J39%9;V2sIf77xAj)Mh_B>x1 z0#p%6jFSxL0I-DOm7o;-hE0bL5h!Ya-$WzFc;kS6qk+rP)rS_SqqGUglTvy}v}a5m z++xiI1KMK}btzZbIFTr$Am|yJcr9CG--=EpFFeTPLmV`%hHVXj8;t%EbgB$^@PP*> zdkhUHuVUdI74%`ykq1YV74EDLQ>AD*J!b<)i1u%s% zqp})=3;KYS9?z^@h9dEu)PFdG0{F20G2^ExSyBC zi_9|#a?=J!=@vxJzn#n^tqjtP1ShnU3%;}uy}Z}0uTzf)CrdGFrWE!#50^hc_G@7-Is>eQ)I=ltr_ zsk)P0I;ll=oTHu+IL+;;f>3`qB6N9FpvpU4A<9lOhlkA?HG^}abH)y)sQ1{UR*Uq5 zZktl*sV%kGq%wunxP2^f+tWB{$4ePf^eb0ZkA;iR4dzOYjn`DKZnFr2q$}q-x-$yj z^-;mVciZ_TD`!*WcClCt)d^l#%<6KKAw{9>#HzzjF3k=0bZx;AXG(XPdo30u=jx8pf>w zys*G)fxW8B!#0QH!qU}C0ySb`RHOyQMn~2q9(L=(O)#I)IvoySJ5_|b>F0G)1L#W2DKeTXfUVcDJ7IB`{eSpeZGR_F$MEH%EQ85H&Br7jo8NJ-eI-@chjH z@lvqP?xjrsPr;R+v8`Vd(jXt~LM>mnlLaF?^{UC%ubqZbrn@+LkA>tEUU`U1-!tD7 zv4!_FmY5SbT%t%Y%5>LJk69=-iCI+a_q7CXD^Q7YwKHqemHV1SFqd|D$THLQq!7%H zlL+P?G#Nb{)5#GvI?CwEkEcS_7q9H>S$oymo^w{ZW9lgpVaE5mK=saI*PXvVe*OE&w6t+V_Qhl=1PniC@v;6+4(L2z}-4hth2*p7Z9JtBP+v zCu#wTNVcPJP3@*rTu4lakrD1|z%Xa0FiaB&!{nL8uBon{j~>X_#dW$rvs5}Zz$&yY z%2cP0Y9E%x(`*0LCsJKe=$X2z(Bm5M#|a!G3|x%PEu^J>* z4ek{ffl={}tY|-oET9U;V(1_#Pc+*+(yTA6h2}R0nqy?cJ4}KY6i2ZOLd3>Ns=uye|9)PU9m7E7$Gv16@pr4AnZ7}DUkIz?m}Drz&YWFw(=GY1we zg_>+sbhPUfdDH@ek{lS!s^hAASeu~2c}!yH?YDDCN+v@MA+;Go%AoYAK%}E~G^>HB zCYzgFgca^?w|ibkE6uE|X@?veR?-73^!}(6J3&)Av&jiS3M~aJ^@@D76u@2sSeog2 zVeE^G5LN?=cbbyGne3H>bJF=8N>UPR7h{Wz?KR44g9A%N*MJm|3K;9SffTauy>zTU zO7jcH)rp4-mGWBJymyH$`Ch--!BdCckxlt<7biXLyzUUXbf@hSLavahm7GA7)-9pC z>;VP1hX-WI?Bt!i{2cchTyybLlMJ)J&bFq0xD9uG(wQ54b>EC?%iS0hJvGfDjOZP`~7&b;Ro51z?( zeXDEnrN8r$FWvp6k8C^d$(1cY_}C>a~NKFCodDY^IS+c-=B`{Nl2F&$FTp{Rbq%%XXj}< z1|Cp-Tyuo^z>~@13%|p0^lww^n-wn81NM*~IC*aJ}vEN2z zD~FZiKQheUsvNvL#p=PfFnQP65Au2iZe$hTX>sc zVH)HUBX4Mt_cDU)Lbi4;ya;9q`U;$95R9u0P{xt=`ivsj?0zV1xmxMpaG*I#bRsP! zLGs;@e0MI%5jaN}3~vQ;31k=Vyl)atacy`|D_lp(kvJ&95~QO-030?#!9Hvk#&GvK1?+Zw$+_oAo_|;RFOQ79MXp4 zohS{r(_i4&Mx>95Lzq}TreY&AM%NtktYK<`L?spga#MJ7L|tBH9}$IqrWk_enyKFr zTnO@Ya9}>YlH8PUAeczf#IdA`{`U*mR{Kk1NS)ZXFM915D!vb>-Er z@xE2#Y+R<6V$90?exsFn2kI3}%-(z)3vLY;UFE%+TC--)>2*vh?2_#&Fp3uiAkD%x zi`0v7sThapAni2>6w^6~i^L$#&qhJVA_Y0~P$UW=i+YN~?3PjVw4vy6#jkbKiMvccM`WQY1*bBeS`tB=HM9&+#flp(Ut*26Nf%b0?_rEsrctUHZwdbYOnbwrU! zG5ObjIK1LvMhsi(J&oZ3ZMP$!%<1fC17KrN{*nj)U46Qclf~kNLgJXAdK{B<@X-X( zu4bUApwpWQ>~s=?nBG(LPlKP)V-m|Oe=vI{Fi6sD7)zPVD0Gj<{UztG?b?aX)e&Fj zU-sU@L?m8{x+ZXWEjXm@FxesnuRWvB(J3a&P?!O|9~Y zx>KCkx#r|SjZ`<#+s=L%q_SuA4hJK&A;=FAs6#)CSDw@J=BwTuEfTy(N5IO`%7bRO z*{X9)jnI!_7vj+a1gc}JTl0lf8*|nlI2)sl0Vk(1QG%yb;3Q6iEdvOxbUt2)L|g#T zG*HSdW+g*CAT(%XGG%OyQIH{Y>wE82L{mB7}uw?yy$@QH94oYPPHA29{JOti5RX|bE>>O%>(tb z)Z_!Q)tVNE2Q0EjP$Pb!4g{x+Q(WPnC?sg-bquknx`a=GqJvGW^DIOJ+<^9ARasAy zmC@)Y*Yekxj%!l098ruI0+I;)aU3Q3TPlqCtqfNN0E;Sya?lt0pXU`gMBI*@28g+l zSxUUoq|uhd?T6tq8``nW`2ecbjQ*lvF`UY_mnt^xX_nPMBK%QT8!tL!?o9ol+EFuR zrmlw3^)A7vMGEvqjXAElLeRmo;J`8gU>t_L{eq=XIU$qN!>EXNJCsh1z#8AB>=xt| zjeaS`1o%2mUTvJPMTHD^J!p{p$9dDXRLA$*Zn-!cdBX;-e&XOKlo-&K{R^W95VWlzEkJ*vs#W;6i`uRF?z z%fnp!gdxm*{Y7@^W{wb==rfy6>u}aSU*c|5GWCc+iBKE{QAn#2WI2J;#xEjam z5llp4(*|~>;$OQnZLT7YC~wSQ#^r&A8_Jk2>$!5}M4OlYqp8p_=Pmqur;(VM^1h;6 zfhNGwpxo80V`{<3T!jCkDcP)?(`5(Y+LAiHgTG2-^pm!!kdvOekZOQ5BOs~ zxQ61@G#HS7Nhw{V2F?m^AG~ySy6=v<|YUfC@x-#*DW>jt$~6l3Nd(C z%%rTKFUi6$nIdrXzdS0I<1xPTM}&zWu|PCZX{K?4CyBY4sX$i-YiN_qDohk8VA zFI7WFToH9dYF*GV17Db%ztu@+1069Vnh#!QU*xQ$&0$$Chy=tDjA;E@cbEB(MHOg; zQ9dSj=(uE|k&<{LLlb@UG8+L`+diW(mC{^|RlRF;00^XMmStqTq%lM6*?O@;CNzn+ zr}eHHiDd(2sokp0tZ^7FFekA@=TwRYFoa>)9bt(KOWb4*ic{xw>p%=G?r#8K2Wz6`m>JaH0+MgpA6k^yg7+jLaDhxRTIAxIOnJE%&9l<{4#`|QeSfrZ;LFiBD-}o|m8yd@k0sXfc&Uvjb!F#S?fa#o z@6?||>@9E`BQf6B?PT7nSR=VP-1;5od#JdHT-B_i@Y%n>+vD_$;-VEe#$hnQe&H>= z3C2{mJL+nA%BB~vC~`b&w?cYdPt&_pplSrC)7viw51ya%tH#9Fn%Et4O>B()7xeSLqEzAnXGjA4$v4pmZ#1Z^i-^- zKQ`G?cI$Gpke)_ayEKh7HM7IN$HQ(_&}_R~G73>p(So46%&-WV<*pW<)PfjZSceN7 zNJ?&9IzAGZlh|x7*sTE)rO=B5c^^0j}@(RmG^0 zTA);d!ql>(ao-#(N#LdEE0Eb0VMD6*D0SP$4v0wXmGDIxTht(lswY-JQt&DWsbq(- z4^qYwJ9uC%QuPtX^Hkn_Zt*c{kTu`^@z46@Np+RI;5rTR$ja+*q)(!atf^MHt_oBc z!b*0N)R5_y#%@xxQafE6yD1+ITC)J88adVutxQ6sCjhE>&y5&lL#?(`r@f>gBYCY| zi7l|HcBO_|C^qUXXDHnAX=<3+$}9fy#3osZiuI-EH##-Pm_E?;{CH6_hLhTUA&q(U zHCil;zWL&2x;o>Byk-Th<-yJx#z8omPLd{w)?8oeHXqd~R$r;A(z%A{QR2-^*F`I` zX9hyUr`NY0%~~wn^TXDX*gkmb^U*9=*0ya(ZP{7_w9?rgqM{b{Eeau{!{epZ*i1G7 zxnVzv_U!tecbl3Tclai2@gZ(#FTb`s({-w+&##G?DHSZ{b=<+ebNjz z|E27~zv5>C>Sc$!c^`0;F^w&c@3M1X{d76Ce#W--#&6VavYFRTrgxZ|>6!atLmGS$ zfVM;6-?5EIxjTKL1%!k6i^5T{{tE>Hw(S5^A1lXJK(2hJOSqds`wMz$WAkmi!(9i3 zKn;f4+iJ1E=C1G%8-RC(jw$(W7YCsztUtWBF%(<>4kZ;wI0%1Ygp3-u3MdS{(}fjV`wU?%^;00ytp2#MsU(q|9n?{8mI!g z*xu(}WSCd~KRT?*HVZ*cdsm%5FvRg#d@zG&cFy_mV&o{Gr;TQg2yeIDMj`Y?3!sW1I5zTvK~*bJ8Xn8$)3Jo53PCafMVJ#$U8Dlx58 zsoe$^nye7Gw$M{em8L<^{~fCQjF(W^dv|w}>*zGv<9br@#X^5Bqi+6lT$35 z?GfIwtm8fYHmBKN3dkfEpg0Obkc!))hi`6~tekTom{&yziKGKM;@2L3;Py}E)H^;8 zSOP`}(STO1rn0pzJD)f(+_^)2h>9~*3;^D){EiQJSxQ5aFE)iFb+IcQcCuJQozAfn zg{p*FI}Ux|&<8$n=ynNMJu-3eSGmX}5y^5=(vOo_H6Wjkmvoucn_XGc>uz}q>Sv7A z>GoR1&G3o90qaW!(Bx`?p>TO89So;K2MeMA0`;~7x;TOab|eIUZhwcXx)B`QHD8p% zintMSnh90X3v%5Rr^j+0!<5AN6rK&dW4kFWcg_h^T)fL{S1J_7R@QG?bdw!vEq8m` zN5Jt6iLP*`>2O*`9zzmXWL9UweBersn#fa0iOlZBv&Gx5Y@T<{_sn`UF&~|-+80nv z*Uae!W7@NcYktO1%%?ON|NGcr2OORYWr#SP!<8Z^Gp!B&dXdg`J2}VyDI%LA^Fuah zFOG&?gyY)kLrd@$pg36eF&dWuRP%;A1ZX#L#W>6Sq;peWO@-2-PYwO3qUPv_6K0*! zmG4Dwenl(e)F$ZGEuuRAG_{`)jC5pfj5OW#Qcs{QBPOP|_>Fe5uQ8(V1VO1E&jU(H zDwnw<=u(UFC}> zyS(eea^X9?^pd?k%h8oBufA;6R4N1Adto{FDUYlyUUne|SSDJ`{Y%bG+&_0!!~IK3 z;r{f>+GQN#dG4hRc`iFUH)3*K$qjJLb;5TXQ=o8Vj<&c? z(_Vc8swXyDnU8|fr~8Zg56%OTX{A*w zcRt)K#)>ZHqv?UO-Y1gh34?;KH$h&k8q@pqb%>Ixt9xhu0kXd0TxS?Hf2|q7dderl z&gBdX73X6pcanlF#Nx+ghEvySK`0&Z;!r{2jMw=%ps4hovi z{)|d_=iI-5koxz|mB;xUBSQbuHGI0OWmWf;_pE8TvKu&>Eb%jFhr8FX(v-UT*{;H> zgKG+_X6mnYbM*}kSFhyimGxJ@z9#2NB(0zA@_GD~JGxr>HuW*7?BmHkOeeo|RBLg^ zIJ?_-?_=i9l}Ex;7u?%b+x;PH?SZbs?%DCeK0PzOkIjCYX2uIUSYENKyo_OYAyLj_ z+*j^LyQbC@Zsg4A{Wnf{Vv|L7?B3MXMR6R#x?_AFr4~1h&-P7rh3gN;#S&yP&i&o{ z9_#AZx4Wxr)A;Vkx~A83+;Zra>#x7%mQcFun$MAOe5$K$)A*(xu2c?7+dclEqmXTL zRHL%k>Y)Os*Ax%k^3R^WT32l!ft&lVoqhYp$MLXJ7k1YkX4GYENI6)w}~1*o7z?Yc#v};bJXps*azsX*b2~7@z{hBrV_s^`U?XRtA-?;zKq5aoSMTEC(8tC*i-Zrpgwp^a;0+l4xa- zRE>*%cNs^>4pFv9ED|ePD9L_WJGj$fcXl8iR*xt_a0qs!X^$byt+yOHbmNn2+7I2h zX3e2ns%zSBIkaZYE&FHJ6mQv|Xu6weO%QJI0BtgI|52DQp7KHOrtZ#cQaz? zjz_yD*R;XsL)T9_>Tfv&^{yGS8;ds{im6{L9w17biZ*WbO?NG)tM|FC?XntmTQx?M zf6iFM(Au#NvaRPC(|vujyX#5rYeF*jR5K-P8sG6q*OO~nknyTSfA-KaST2Dwmu)`GAKD32M+IcP2K%)*U>f0 zu7|Y!hpvaVLpN3#pDm12C_i-L6JD?hYNTlrKP1WsJ=V2^-|9z_my3F)8aEtM`HCR& zw}DO#hjup>6GGtVqy`ND+PC{5=xm35aIp$!MQ0m7^{aTxp+F}~599lgp=IchP3R0H zO(ON;KGXf2o%Z{H^cNdpRK_I4-W3DusUYVx- zfLfrKO}=Gj1G&^DoocrwS`lA@w(r;!#wn7Ds@XkGE7dCaup8;Hr>DjXn;yp^6_EG> z3TBZh`Hi=zMYkNfab`_%<1MnMk-prIF~7t3en(fWk1&+JANxc476RZ@n zflUSo$_7jVSZ^?Z^@citl?GzR{p<8$`}cN%$K(Be!La{VC>9EZ)877n9yYdN=8hNdJ?hK6(df zn6#VpE|U21Qj%zRIVo9o)_3JOizJ?$;gkCNY*H6#E$P3Iev9-NNp1cv>0e2QNr(LB zB%hCxet{%@h>mkfuO_K1m3an9JW+k~p{<_Y7xA1@{q<++w|FKQ5UuKmUm>j_NhbP8 z;)T+iN$PLi3w%C<}4u5VYeewFpBq<>Gk zoK#7qKj*vX2{e6>?>Cb)2GqxrS;<9x`SbaGB6z8>C7J9ey@B+Xqz{qAv%UWJ2l!OG z{)+V1q)w9bxAf$E^pfPcnQjm-|07A`7%M^b(I{5a|VBaM@!+r`gINz!LO zjk+NzFBd@L)ui<#@%dvUwMRVOL;4HS|3eawKSk0#JwG3r$jg(ge-&l@7HNQ_`aeTD zK>AzK-;q8^x`m|vzJsLu&t(0Qd+|X1_8OAp?DZs#-PI(G<2RCYU7uHwqy z%4=ud^gKIZXn49 z50n0g^gl^EN$(_8NH>v=cZ}8ZA=&;{QJ&;a{g16F7D*j^e~9!5=|0l8N#El7^GPT3 z{djeMvoU@)<-M8oYb5EK9VE3|pRzN*L;79P{~$?!E4{*}v-lMKPj!qpqpL)@|ADm8 zfBqq#LnP7i-$}nmx{mbwq(3I9f6gVTZ^WMyMVEBje<7)U$>d*>ZYKSiPh)((*C*-6 z50jn^y2P(vC#@$*kL>d4?R+YUe}CXV-^ZuuR9ns`X*}uqr`nJ8@~z)5@+s?HxEAtA zmnccLnaJ2?qU1)XWi2gRXNv73)ijJo)RDa zxx3|t%7#yMf6qSuqMqkg=J&d5mBO_%{B67Ts!HYB&vX|z+)%9)Z@Bis?p9sMdyJxo zXS+K#R4P|>Z`kmq?v|@6!^gT?hAWksO5ujb?e}bVZNvL>s%^QpQkhl$8xC~yeR#6F zl`A(?uWF@;8-8rp{w(v^+3u-{M~%1*Rp@TNw!0fTtKEfbtCgR>;VS#p-3?(kba&H& z4cxs-WnMMw+E%z0x+?9;vEka8%5-Hu1MoxN5pG)7_>% zfVy_5rJ<9R;#J+#Mpr98{R5Mgma9Z=;f8E#XyU{}-HWUyYE}(Df34$n2T6Dt(KFKoG-6rmdE~AfoOZ^kNE&iTV|L{qWsAu2-{c=?{ zrBmI7i63<@^4&(KN-p(Wb@)X$@StuWXd58S_yKv@Cn+g>jP4n9RkF z%s6`>6X^+0p2U;ZT+6$G9vJ>?X6JsVyMw~TG^>yjCh3vqaqZd)gXjihr;4g7qmef2 zh}6Z1G^=K|d$BRvWw(|D(p8vQb5d!aEE5kdx|L*H< zg+>aNR`zqO)Bl_NQ@v>ikVr%g|cTY{U-2KkWzR-~4Fgf1(#MZ*iM<RD2cxO7t&T_FbFjZEz@9FCY%dM4xa(SX$=%Lo%x%92mM!e`d?Aqwe8fqqg@yK2iA7^rOR8(Y|tx{I#J;RkMkl z`^owFbk4si7Y3`9_MzT#Z)I?{yp+G?^1x`NGSpiwpE5cyP=QSUQ5me3TZbx@(UyVA zK(*ZNvQ4Tk9&Oj7%Cf{=FWZk(Mk~E#${r|J2J~p}tW{W4@f}v~HKVAo-ed9QB|c}l zmpkpf6jLr2%TQ?#wTuo9pbgt(BLGB=HpjXM5X6`87H; z!*Jk_XyF!(kx*F%t{*F(9G+1>+2zxCu9rfFh6ZTSC_Je^TWz#e&%27OMAww~n#)yF zb*?D`#YFzu@*+{zOE(?O9aW(*%f&&pT%Q9|mA3kp45}q<){-fN`k3R>&?o~<&6q-1 z)G-Vm{wtgHUOUAZz4{VZLwCg2jQ8$lvJE~zf3YJL zSKl4IkDDSear5^k%S(nv)dlK^D#{PGs!xqtm7UuQzUPxI@cCT}X4DSUTSAAfNe_}w zQXOK*AGLOL5J{x|`UbecfzU`q9t#;oKEENK(Lgs0j%v^sD|8OBr+blrJK;R)Ds#_8 zxq=iWZt9YHV7go!tib;qoAJqV&k_*su}s{y(Xy0Al?PE?Kx5%6q7H1_}!NEe?!gg+@`JQL}uX$=o3Lkfkie(cYu>i0{*Iv1+O={6zrk!mgs(Y-N5_{KY5R}T@sq#pjd{yb7nV2;Wi zV2;oK=`Yt~4pd?9^gy8(66%a5GANiyoo(eHH0Kj|wI z<>KqQKX~Qvm4AL^ZS_=e#~CE!R`)M{uyeTcBb|jSk94+Naz#(%uk#rSSKjRJKTe*X zhP(UJn|GHH&(R?|HJ84xmw_;dvouF#;2}NrfUw4teon^Ef4{S^r8-gA@}th;#IA|X z;(@)6ANB41dU^5CDC2IhBE=3YN);)TWF#>t2ZkPjuG!AQ-q{I?d%Ux4?Zn=-TOL#e zPjnXd9+=|W7QX2o-`-{XZ>$euHF}}ilm2L^qULK@y!XJ`wOe*gOsu8%woI)3L1+8K zuFlRadnbK02V6DBI*VKO&Qf9Xx=_PX&}bb-=u!b-4-|o-rqPC+3PCrcUik}a9Yaxc z=rh1)he{Y7;(1wO;ma0AcYu*Fh33z6)+Ua07I#fN;K<$U$fW}g>^;_5+xy4){FpAk z%7ZB^hOiqXM##`e1lxfeq^{|X!3qXI6fV&{Db>Nz(~ZIi13HZ8OT*9w5@F|-YUkoD z2PWvd&Q7|rbyw%wy;XX2ZB;!MJ6k7qtvxV1QCK?@dUjW}bLrlRi34jVwsdwL z*emI3+uPZxT#MIss(%jblEm$u>Fn_N_F9W)JEz8wn$##m+YOCQmlq46(T2f_#CO!g zzRKWKxx>__sqe~=Z>>7ZEN)@2-L=+uVLF;WgB7%$Yv*+5=@Zbli$<(HFaeRfCf3s0 zwFkDWT|03g+0I1}zV^W0wQHwcJ5NzV_D*bByX%0pbK-QK*)nlJ50k6YHFUyVtadI6 zSzS|SI%mdavYQI5x26jJY3O2;4U(v_%hcHNDBX*sCK}7-D*D|umIsU}h#`=~!^qIw z_5(Cmoo54O*Tk{T4#thUWc_K^4}<}vUu!4m(T-iNmA==JRA0n_iCNvG*~->JHrK-G z&g$57b_?5`2zzu$hiEu06_zv!W;#?^Y!e-jwbYgVs7npXX0&p~=8S@w$yOr2vumxn z^J*nrpp{-`X_9dzZY9mNOO~yLY_644orN({qsY#v4@{ZZH+3ofa!TB{y{H9)<}^%Q z8?`d8FPYjqC>k2sisWvYvaz*`PH0)Xml4+1ye|>&`Lxoq#jVU#&87jtp!D9fn^aWz zwZ!9AI*Sa}W37W=a{zJZMmI7C8ibWBgXD`e5d7ZK3BS?hQZ&mMkc=zqmq`0GN~?9y zara|p3#$Y2MKH2#&gw8H{pj>dCBex+fMJ~Ulv6{PjHFYZw{_iGp8b!A0Ev$~}fm5&TA+cmKleYqFH z)!NgxU}aFgQbl{EjLC)d2|CspmzgckbM`~Jbjw6&^r$*Xbwy!Ub)t3eTG3v>3bydo%mWq>6S)OtzIS?} zbql)Ho4=@21WdT5T+S#!pSxz}FSl2Wz8@OSfIztjMBpuwlr6KJ6ZYApWj`v{dW)l# zAC_x_d>O11M*qb<4mtKXpG_WrNKOL)%@5tQs4#?w@5+yN)^^p_qU6Ca--*6|FcYr~ zm)#S_Mwr6`{_D+6@;5`<#mg@VVExCP#Z{~8(Rj=1H=esUM)RxQ^o!{n_)dG=M4)*2 zFQ#V#KW&qir$$d=PI%({&|lQB`9c#%^l%w*t)F`QkRdi%DGdIrq$1ZLtw*zF89yjj z2Z}?LDwElVHNQBjQgVDsDnm**%pCYNs8Qe^%5hRh4;}Xu0LwjCnJF&~E@?A)wb7!W zf2+)Z+|dQRQYU#IcjWt?)4S}6I&REwh7=I!UCB6BaDgp{FyBO2z7l#L2pHz2ZEbfRD} zs}3TdjtcwjvULE}Ja%p_Gk~At!L!Vd2a$#Xo>wg~_;zQ};j(y?j0K%b-j54#dNO3G zkCj^oE2GS*^0Qwpq{<$_y8BJei(= zrvTYJ6)%t7m(I@*cz0e%7IAuehbj>qGfkDdFTbM?i_r_#ZS|}d;nEpI&Xiex#G%>gTl}~^3o1gxbv^(Y# zWts4QE@Ojxk<4~m@f!Rl0#0Ps(7(EJG@u89V^W0ylY9Pd_M64O>j63^X3C$aGwKhQ zAJOUqtFHsj7w}El@#+AxjZqe*D}zU5`lY6<_{TbnYqv~w*494RSy=n`o^WdDntoHE zD_s*VQwISaEyncS@CErtipF(@wFjA)+u>0b^+*t|3H0nV-}bXfV(F`JwHyh z#L91u0U!WPE(pNlGwvJ4@lfv+mYD@PO|E)1q(_-+wu}xi(drmr%!9r)2^+9)<{>cs zIuI?4%Z!+7kuN-CtJhYV3_Ru^dta##_#zmR$PyN~pQN$VHhsY#bjn`lUYfI*3j{aL zOlJ#ImL?6J3t{*sqdu1mux2AII*LEC1qg7A1z0uOIV-E><*Z5TuHXrga6mWW1^BJ? zE3J;d)O;!RAVo_~enlzOYQdaZuNHYVYYkZzQM|2tYce|1*@o-*fIL>T7YTJvY534e z-#2eHqBH9ps*PaAw;8BqjuDLoCe;!#3~uDE#Dhmi_f`NR&Qm9kCbzA%c8B{`jl)8Y zX}(f5N)%XCW-ZltNJ*@Pb5E_rm0(S@2`CN)`Q2$U?s$CWO?tLDR0{oCF4wGO2C1?d zsj(`-V=Ysllb2~qs~k>5vbx_p+X1nl*PlSjpi=VtQxUJifJT{ z&d|um5?aT`ss>Ir{z^8^<)LLJu@>{tE9Ybzt?_^@YMeSmj_MArkq`tCYN#@wVW``x zHXRt8oQ)l5txK(*XSc3~SGryPR@b=qH7X)wZ5FCawoU8) zhG1gM+0r`?TOdg^#x>lmv(@rwxY-D_HaC++v1_7&GdIq4R6eRJRm>@mxEJ5&g0^&zWX3La!Mpw*`lzZ#La8c#Dz5dh6R_ z2S1>QxNSKm8yoEw>8;VAY3so>RA!bT3#wQ#Q&k1buE_warC3`0o^o{Wo!NrZF;7YwAC}7zpCrpryQU`Q z`{bka$lo;sORq{*6aZlkh9k4we8rxwfHWiI$P-=hYI?|c`KpjHhNPEV9zoKOZS`d# zn@6|h*QfIwE*IZ;L4eq-Bwuhvgs`oQ!{wG=c++_w@(l%pUvTB?(m8B631bQhjt64sf5qPvV@L+CP)HGV{ z)#}*L_nT%So{UUrW~wwrz08z$MP@~_8=}LwuE}HvZVm|ZzPZ6e87)w)EEMCq;~D)K zoT;>omYI~Y-sWqdSX?IZn8P%WP}V#A?`ys$X^$V6Ol``(&w%XeKVi3 zxIB!CynFNo4O#}>p1xi>fx-w_9aV_~`Gqah?a(Tsl#NgdJ3T6l45LGXMizhJ=;%M? zlBVc0$0K=ujYHy8f;3~8WJm4AAy^sAD~*n)G)QrLp;#zk!c%#HqGeMY)lW@46@Q&o zTw&CqaOQi1HsNKz7~QF&TVOdi^?0wCd3Q$JOr%|iUn|+^`DKKeOA=^}6ECjY!X;r# zKy(SjKx0W?R!0#XB~QaQ8tQR(e_%f2!MxiKGOvNm(StdUKj>l<{;}cqzeQE^lc#yE zl`gYG_a?(B>vvpO4q!wSL0Y%tg8R1!@BhFMVqxHk^5cStZi7XxADXBB(ffO~kz#b{ zhgwD*>Lrp#%jJdM7DCE2@A3sP$IDv`v!dd~Fs;M7sTi)OYR_EwitDzB@yOW{g`)W>B1~1xojeBK9b+La>iTkr zRhyhxl8f0ibFq1}*~PPm%?i$$;&%{46ESnb1Sg5_SBZ$#3~Oh5m-qlA1c;hhiJP;h ziD}k6-|Z~0R)wJdhHA}w5s6cqn#*&G75n6aw|tFr38<}PL89EW$Y~U$-%z6k#zi&y zX7ZS3=E)|;V=NuLAG+22s-v0%DuPFb5ucUJv>PSP+k|&6)vG4SzEkCw-~rd6aJspI z;K^vA>eOf!j@>dju9g?Mg{Lsv#H-}x7z(4-p6;bMMC*%Q7jR_G#z?Q#MaEl`{fd-d zIa;cy_$Z*g1LMwyEL!f=Og#IIs&>QICgB!QZ%#fN{*?iiuJU8psr<9z;+=D@JHtEs^s&}+7(->Nm2hyU4aYrt;n9AWnXQ4df`f1#)gyfnHfrBUGQ`P#<<49 zzc`d3)i|3URYQFb1Ym&?jRX37ft~FNRTorog-kRB6%S-a*gSw4T|78IsAgSBxw_gm z6GTxq)Q#E$l%&YW1rh$?Ef_g)Mii1(b!n20RfrZU6|JKW@_dc zax)F$6ao^y!;fhO!&aHhIAKW!++xx5Fc_(gm`!4CVj_+s=BAZJPTADhlo%OimocxJ zEE-mM9`q#kP&N&^i3vHbpc}thVOGsHSF+yfa4N9SjJ>DkWWPWIb+#MQ`49wS=Nbow zS+Jt>3ioD_VF-tVIAcM5 z7J&z}}nVd@yrI<`{X$ADIJb@-yH_^O9{0i(;eUmd8P8A-A$XSD=Bo zVR}dp&#}=D%DyJUV4=xhNm`=Jjea4!i_rOsA%i5|v9f%G&X=?Ah6tU;+x0NxxdRlQ z6%WFGv&h7ppzgjaO?b4ag`c$e8iH~nqaIFla79>r01{{}1QmvQw^*Baev>}o0oj<0 zqinvHwDJDjhjhW_Nzh*RM4(Ns;v>v#uyUW-{l^mRG$Mbb#va4V02avw0ak#TfR$cq zqeE6fV~GVhQ+4ukM3W2DP~Jvlx}=F;pAe;BORdK(#T7h!h;c26NpF0S2$66fzajKz8OLB+*A;#Tw@i$EL4vPdPmlZ;p$vT`kG zI>-9BQY{!5#{uaAiJ5MiTIDpuZsrM(kQ`op>3eC_ z(*is*(57W3g)v9BUuaz@GM(ecP+4#9DRx4G==6|p9^g)N&Q#hACxS}kb$7;6W;bGo zx54a;mkqXkG-=oduc0s8bRx#8qo3ecku?XN<`3*jj)SuUApll}z@NZ?_zJ4jtWeC3 z1qEaKoJ~`=n;$5)`Z|4TusYfXa#&zPhiRGHykV*>hH`>;h>PyNB+vs*af#+mN-;8iSkt^FIM9e?ID6I@CpE=g z?jlzGvbllk82p+0PM$lMVVn_z&4r{X3pa$Yr_0NATg+3U%nmElxtP$ix~hiyhdpv^ z3J7h5YJN~KWQDR62(;@t(9hq?LVR{Bg$jNOuKbK`2b++U|6tjiE(8qP(NayegY6W0 znJNQ3Yy>2bjE;sHVB@v3*#q}A7MT-JT-xQZ%XAqrb@47ZLDF!B!bd4wp@UklN)*n{ zt+iX$?rRp_tO^8ZR6%X%#|d=vWsQ@8!!fCBs#~iqU~?3Ee>?KHvDl6WD29tOM0gq(DATA%4B8GH)){L1m~cw%vlz%i7f{W zrMG((aD%;=8FJ9rroTOg($biAY+0l|8@196DZFLst%bKl%?Nl$n}-cN!5finhA0;e zx$}hpX=dSsNB}I(Kjs$GIA2vZCb4nL;R?by75n5>u^;VAy! zNrVK=P?|EHDFkH-U6v|3A2dMx@R(T%VJ`1v3&_!P0PyKHgA74+3ao`~SR6PC-Rv*g z#c^0p?rrnbTLZZPEM?LfZZ-lX3l&b7Bx_`Zlb%$I1Oyv)S9y8|p*Mxv;&nN8Ft+W| zX=9?+?}mz~HQli#E`Ux$N}d zoUlgbj+&v?5j?^Q4dgm~@Dy;=QI4h?HOK{olnlG!5YakXW~-!-go6_7fU-GKjy1D}i>df$xdnPfxJUwh8h?Y{P6GF<*-@bUdq^jPl3qUfQyHWsBb=58!XXUpDL zl*n^9YhzLBe&)uaM2;pKixRoAHWnprdm#Lrx>D!T^li(&ns5j{r+Dy8w(DEv#jAh+ z<6pk#%OCr_i;i`+md@?E)Sm#HVA;Lpme>CFSEnY5U){_$xvtmxBZU(=koedB(b0** z+qr-KYwvKr>FEAfeE2&Hx|PAN5rf7DD(Sa*{{RIRy3+aI>A;qqe@@`MI|S-+9|HfN zo@Hv+M&fokgSgx@fh8_4QA0<@>x8UEBF zbx51Dc*KfTUfBxWU8HJMk~~w(b<~783k0iFxtk?G@0X$XAE39CN$(4cUY7e5lNLEb zy?5kvS!}<`O}W4c>Wo6&VtN;0ge(|;8csQb`tR`6iV@MY!3XQR(sY!~^W6Ik422}i zgyef5`JN-4nFKoqyMtlHFMo^z&J!2w9>w7Y3?FgTJ4n>GOYQW2z%euikEX{-Aaa2V zCMQ;SxGT@w9IRYytdtkiP(|>GIxiH&G2Qg<9#9yS!~NOB=~W4&6md*Y;sV?uNlXnw zDRauDjZwGANS}IFsF9Y4_cuRXgvzsMJ4N1G))=g*NdPZD{WND^3d?eWQ~LA-V_xoP ztRdh=o{y!Y*^FilOIl|&p)3ZG7(f~GNLO_haW%byL+=HUB?MPCDji=pV0Vn{S7=ZF~1k*2CbCT|fv$F;y2C0JRodDvpvUrqU z8RUHz&USvqOx@?}OrwIt7r*|xkNv|v|FG|OFU+;TGWo3bMi$jUfS=VX&kAUH)Pt74 z(&&DOQ6!g$i*(D!F7MT_HARgTL0%LAT*bNR_V0bwOXH9Zpp-%NG56`xn}Hb0Hx0oa zQ_8nFvz0GJ^c4;`XNa;%wbJ_tLpYAauP;9j!@SqlQxJUN6FGOxFFRQIin+0vh*m~n z0IkB3*YhObR=l_TLaBF#y7>npC&6fKpjKIC1E>;^3)`AK=7{h{+F>cK3Z7U{9}p0q zk2Hl`rUeBJQHj=%b#}hy;lb~T{`4ys8pc*Yd@0`skCk5_`;XO>OOUdidt>w!xD*DW z@$W8V;92p2_XdraYZ8$!Je((^SS@0aKN|w)5I8 zIm)uCB6{CBMH`u(bizV4+%~bHe`RV-u?F8t40)hHuXu8ZC2~p;PAAjiz*3rK@0^JO z2zlJbD`I0r57?Tl-&)}7ffR^_nnoc{yTHfH1tdGz#x7C~{g`YW1f>N$ahgh@D#An& z-KYuZ){3%j%S-F+yd%-tDaJ#xa~)d|1UqmtGbCn38bWd%Mq1q2^_Jgw>u*GB5APvV zpehdI;#5Opk~NwPB^kxI*HZ9@i|S0zYdZ*v0cq&UDAdzO<2?$e@H2s*Qhe5!wYnXX z6O*_AoBTS-d$iUvO0BHsND&5FrJJ{Ay7zP{C+(%T3 z-AS*eU91OJA#gD+$IUYonw^cQJn4c)`Ist^$z!U8E4D_SkEs$2x;KE?v?C~y<8YQE zD0RQV?GxR7H{hm%U<_4IT6P*J5pwYiD)@7v{O{7Bw@H{3GcFBx%;)zSG@gH_JMDZ| zq@NhP<^(|)SqE8kf|L!9Y5o%p7~*5Bg{o}SugFmjqr?as@8TY>Q~v5cgo9^?aCJC#&>h~Uy7@HbVW0x9>V1n*gDmnG;vL_tOPA9c(1M@0 znr+d(n2dR5q7n$)e8FRm=kl`}k%%Rc8b0>g_oIf%t`!hEU zOk5{MMvGUw8*V%zG=OKL@y>Hq@BI{Lumcj!lm@fc2;c_Ri$R*{vi(V2CU1kCSbV?a zgQrIa_+xKG%N=0*6PnG<5gBZ@75NB)MatHYxk&d$`b5xw#1>};!x3dnNM>83$ zl6*^9u15Mo(1uo8wlZ`sCgC@~FZ1-|Oi9X>AaqELH$<3(RhS~ItP_0^z9vVRbbj^4iV~$-*uHMPItum+PIgau9J0zSddiH4A={qH___Iex%i{vP`8; z8R|xxvL-qUJQ5{gP;mc>v%)H;ba61s!X41Ot-TPy$q{ILk6+ zD`A5_Zn*z`Z(ts1xTBKNWj$A}JS!&V|48wG$>hQs_rSf z=i{5&Fs*LHN5N%TTR(D@y^$kJBJWrniTF|$qj9^6Acv{z*ECNK8QeOh_y08zr3EBg zxFoVs$9+(Vx%k{B-n{97>wBG&W_l1~#+Zf@dl^f#CTN!(6M`47q5dcYQI0*dpIJtl zi;hGb=io|j%fM)CUs-Nx9UYXygXf+yqzJ?;1+3TSxUWrU2#TG@%y?%w-{R?o^^6t> z>4D%@<3SdEq&VexkUuE$xEU$wliBM8B<4k+!!6f2Ct!1lmuKmul&cFuYNMR7hs7}& zOgPd4SImFbD5#BeB>2(HsCtel4lr_snGk42+a`2IiSdQLwy7+zD?a#~K7v}!(rm;u z5<+Qo4E@>6es_mE1}CI}1a`ZhC6BB!tvX#C2kFK!~&v|CB6EofAoDpT$Pja=vv>e}0G z^h@2+UU-uYqtCAp#svks^QcRSF9%PgcS>Y!Q>~Uy4!A?*QUfL$9nb3_)Z$Qn_zYZF zESz97@skHp#qAjs>)*q9^ArmiEMRPETlBIYM8Oq=-+nZ zgOyV7hE+37du8^t#6u$hif)pq0wYUSUpg`+jH+JO!kf&b7CfzNn*!PcYOjn{w4RwJ zk*4N!`S;3;;R=MIs6{8A)JHWzoT00&_bj5~Z*cH;yMhHr5>Igd|6Ad&GR*SM4=wKlpa_qMEcu4!W74y&! zc@v!bY;lufrTvb4@$NotW4J;!6(gvnTzc zYfk&Xz|r>Itp3Xfk!s(l27$HDbfVSgX%OU4>yT(oRcxDS8fvOlY=u+C#Kzua<5I&> zZla`g27@9Q)+kJkMP&q?PQ{yla$nsk7{(>%(imDFf1{wp*U07F*m`c=iSw?p6dhM+|ZzT{uxwGbUuTg zP9W(dQq~kq;uLL3Hir0@3k@hjNA*a9S;48wn1{#{M(B~%sT2EEQ?SgU*KF{R+rmu8 zjB=M@ZROc+Mteg~=*_11`!Ds>zv9K3(~%bCOoP3s-^&j-OSLhdDCgmvCpHvCj zz@ntwwMM85fH5qZBB37Vf??QF>E7j-PeV8m*L`Bo9L9tW!;7#ZA9q42st;wIU^sZ2)OA*4^dB~Y;7F@$(J1tm%pku zG9QBV*cMJYX-C-x?$@1tV%pZAi`Cfzm*!Px`W=MB<*#T|iKE!H7#xLJ8FneYXiy-6 zy-%;HsurlN&ZQvlQM74oZPbl`d?e#K*aH)rOvFgLj=zN~8wZ(z3);)cCZG)aBJg0N zCI$gqXoM6e`DigO>x&K3xX^p+tTRFN@vKWU_=t-S30 zq=`I-v-Xpw?q}{NP2^~@pEQw6CO`W{b=IOZ!g;na%g-DhX=T`PFiC9eb3w_SbAl2~ zoJD>;QeLD|QK<@gOTdWiw`&iV@0=Gvv7LP`WaZINgN|1zT={5cb?v9JcXmgD=NyW8 zV8zO|`37guMLY@b*LJ6?Z25G0TYkFeeCT4z6eVpeiTsI*=vd~?$JG2PGMF}pa3`Wf zZ@g~R{`l}N%zB-E=N!PrSHBDko^a){^K_t>Yt~J^{-u$ZEgWRx;EG;)d*G8fjla`- z*NEUXFIyI7F%k?;uz0r^lP6tY=IurbjG*bR`L@%<0%4r(us4?GRXaW(sN%#C7qqHW zqDm*2zDkyxg)v4I6%*b;-N8Gj*Y4fr1uBhEzStb2gjXtS21?*Zr9-PajkTIT$j%wT zc@U~y#PJ6Q_8yqnB`K@NDTH`5$0-)HB5&x)Dc?^+gQ?nvfR_G4&79Ssm;UaZaPpmQ zv1-nPDsDhZum#uvngHRbYfaqLwH~UFS?2>LYvp~zEo&#%ekMnbz_5VU1PA7(MKgVyk%ccAc!ddCL;MYL&ro0FPW#Ss9z;UmU(w4k zAbFZ50YzpzJM=+{C*gATzB~3Y>W&`sk_Qnj`baH8TUeK4sKf!+{}-seQ^=hmdg8 zZ&R#;PhHA+$kp^zk&jh02lC+%FlXU)@`K{|@h#xi#+UEbW6gbi;@}Y{Z{X2^7dd_% z!zNQ@dp`nnrp|i6o)XBSU6`K869uA<%nL+GD3KD!O>bC*8(oaF?V^igke?Zt_4s^X zmTaEHHzv&atD?0)ES%pG@{A!d+ajFrEi%xOA}H*P)XP3j7*2a+Zk)ziQXQYP`_bNH za>78I$Z87WQbge}v~7+NO(zQAaS}!3go?goc%uy9`3M2=&dzv9EuFFEq(JKv3ITOY z&wL>uzCG8;7M>t0;vPl&d9Kz4X)l1pP8|f-{wtsU<~Kk6E6hf^dZtqV>N)P{x}d?) zb%L+tgG8$sSKjJ3Ty)`iAN6yy$HI4^ik4;RIAWMLE3 z=g?r{(BSzvw?e7;5YNJdSTGBLawxLVfx%=r+7Pt{ zJe17`BB3pmjSyiM&H7Xin>D)TaGJrdKe9z}g-ZAbnmW!JA86`4OJ$$aftJcWx51d7 z6OBSG;~WctAzQPBK+Dr)A<*A%vJhxF=3EH0T=@%uc008YIG-!?akR~+oD-O*?g&}8 zf^YYo0VtJZ>3lO=wpTzJ#n{e?G8r>=gs zT)6yTf8p|(`m1ZX+ShRPDz5%&{nfAc=Uj=T^|NK4$6vXlTf-<&%+__1^05P??cwiFA^-Ud3IZ2J;8?k+xm&DTtBm|!2HQyeyH5CtuIl~ zV`LzE|D)yU{^HhKs}se$MkYL&6uUVpc2Upfo^qKY0TP?HspR7N&9gl?^umpY%PpII z(M-Yn){|pf|Kr@JLLTgUj4EmqZF@%c#8o)C{v0{ivxjv3=AO+ITwDLBENA8-KxRrZO3~I*0^3wio#@L>o&D*Nwmuz0Y zt-r6QkAi#pjdpjFwy9y;HtXKz&l>Tcr+{q|3W#rmvc4YN+3U9*i}TT38gNE={kFcI z{>|!$P=Z>pzK1U5{`ze+zMqm>`dl})Ox(3~8k+AK*}8S&uKxa8@1g~JCi?sLOzhdZ z^{$Dy1$qL<=r%Z_e&|p)Y~BW&DG$d7KaD^7!gZ_0(Z0Xj3RBnPND=kzkOhkg6VyfZ zhs*2e7k3FgLx!S4s9-Z

    mA^a3JxJqb`bjrvYR~P)_x<9Pepb*8Sdz0|&rX?4ZeBm_7^of*V<5j>_tWHmjy4(P4AcH?oC>|U z$WU3|rY=em-JeJF5)sW^Do4+(-`4X;`N{r8BcgOGvNEv@vL!CJB0D2f6NLoL8mas@ z&g1LcyneF0w9ko;BRGTK4ATB>Ns9St&(4d(j7rY>p~`Lj$D|bd9xfm4fAOso49vT> zN0#MURgfFKF$H}^{nw?QL>9xE>qzeT%5-HCKcE}&BkK_=kr`pwApdgQ`{ zCzb>!%k;M6b}R`-Ct}sd02Y}KL1r5q+%qxT-?C?7Yqh`i*1PnhIB{!&NVEY&EbHI4 z9?h`cms;zu^_&veDy`jP`olZqCFG0j%*#dbtK3*8=J9SEV%S-mM&*7sX+TxSPz}1+0n?R*^{l?7Ft*6 z$NoV}ZClhf*+;uVu%O+gw^D-7i$$dHqdxMZ7Y)^CT@Nq%Pz>Aj{M0sU)W}_CI;;JK zJ=KZUTenVZoyFJ{w$fgA3w@e2{&$oMJr9yN>80oXGX5A;1M7V2H-Ecaj}o{EU)gYr z9ZZepqhnks0GyhfH)*$VM_5s3#jC2~qX^Dv0V= z`|1!?8hIV}ua^(ozqbo59`E-HhW)=nu}~;1T}TT&Sdf7Q8CZ~k1sPb7fdv^@kbwmm zSdf7Q8CZ~k1sSN9f#KT1zXc8~aA1K03mjPBzyb#rIIzHh1r985V1WY*99ZDM0tXg2 zu)u)@4lHnBfddO1Sm3|{2NpQ6z<~u0EO20f0}C8j;J^Y07C5lLfdvjMaNu}3U^_Kl zOf-(ti+nnb&ycdNg?q>Ixso!^Aia!qKIxZydIO&yC;biSX3}2LhZ3K<{@0{)NIysV zccjxvbJhJ)@~j}KzWVf9uB{>c3hB+Hn@InMbQ?+a>GPBR`=|N*4Czgz`f~L94APk- z(bbHmmvjFt(iw^LO1_`%Q<=}Tq+ceDkp7tTzx?+hKL3C;Oxi_yJLyW2c&N`+q*s$v zmdZSXB$`y8>U}zNsq7w-c($Ijk@TCSU-#+X^Qr6qnWTFqpDyC_0@8_~OLd4I^@-%? z8q#l*{tIan>8+#<{`Y_7b2I5OpDyL|MA3C2Wxt*ze*Gdzv~2O8|A|l0Bw9pMNL_qa zQhP2Yod|xNOSxB&{x6c`U9z-;bUo=>(l*j||9c0Ye@MFAr`Pd$qWC4cB)_8Tmr4JF zB-(z@r~mFhhxq)zNuu}JqN|=?8hfJacS-+^B-%ueu8Zzximt4&dLneN`g9%X*GbZY ze@XffsX}@`Njhb%Pc^WIfMS2@)fb=cWcS-+5`YP!z(%<{v z5AZoblHJhQ7wzYfPSjYDEJ~kjCjB!>b&IAuNe6tAy*NzzCaISsd!n)Obm+?B<1^Lw zS!L_mOGqn7>MPldUm(dANuFQtf2&>kE#0a6d1XD->!(v@C+U?W(eN_TIVAP3uKgxS zG9vpZ{q-M6zd^d1B)$3{NyjUj^|b2wGf1KC)qKB#B)hSJqDGidgl2niC7CmaS?3}L4&ghxB>d^flPohj)7Y}5U zG)C12|D7bgr?Gl1No^KQvTfIqWIN_tf2gniv%Y@GS`SH|pCEmbR3ZHZ=@!yQNgpJA ziu7@kGg<#DDNj0B^+*QR zlO*dJ_v!=v)>!=aB#jA;hiAHejeF_3i%Gvv8X{>NC`tZhAO0)p4@tV#to|2qUrF+* zbn+ZY<1#!GK9ha7iu?Vf|3nf7{vv7Ir~Q2XE$PFg50So0x|^iFd?`u16|JFMeX71J znwE3DJ}n(Cxqt5}b#$&gbH$k}J7-HXFW|HQfBoI1V&|DND~e}!R_m@8R!*%btZcY? zCRfj_zj|!N{I7hc^#03+?O)}xqowd<_SKlmkZgOBo-&-pDkD~_*zsKEIexdH}W2KgL zW2>j^?^jC2jbjH(hf9UuI&!dJh24?LenY9SdU~v|Zn~6w?6FdDY~wV4wm;wsD3r)F z^8Hfr!Y>{OE(FT|q6Y$F|R|qqycpwUoxT&#e1?sqnVP4;Fr#g3ih)Xyeg2 z3)%RurNYe=aWh4{B2`4`h7zR4fWwbZe0Y~9G%7~jOE zYKd!Pn2cInjkEsT>ao)Hv9VHVwI0|wR^kDEjEz)F?ffc*BHLZQP!_B&jZva2dA8JH zkFOi!%6Q;!}SS`J5PU)!e=B)>k& zODBx1TURQLjjW~^h#cd`x-mVsodO#2`NF1+=BZL`q-`CQich`-sQwyMf9=SMdYUCU zH8FX6sZ=W!N48IvI#h?Tb*V`8$+3F6bc_!0d0^sfsb!-&;FJ-l9HETu+ec{Z*v2VW zjLTw$si$U262i9aC3}coT1%fAyZ+yN-vPnjiHE@m%+WqqALfM!AekC!odc&{^BQY=kzCY}9zF z%Z1z=^>jL&l90~rW5@E8ucH%L=~%74lXSj94BgK7X6<>j(bE)vMQy_qZ;%?r(jr5qg7y!l3Vv5=agDC!KxyUFp`8eSu~T`;K*iVuZ)(y=5EM8O5gT z+=%DK##zREQd3DOF0!nSV6Pi_!1SvA&YI?oGEMtZ9JTdob>rAkZz~Tp+Da_caLG*A z6Q#wk*?RLGU%TVx-+pzL)eSkfkNkPktl8yXF&8;#>Grz&QHm-ZE!PtEHz6UrfVH(QPqgI^Dq!jGE~-5ywsU z7bOz!>^V4GUD0vd!3{kd4npq9!(1CaIJ|;3 z?YV8khCuhsikbJ&y41LptUWEPV_->;KO%mSBVNd-L&ztC_6|q;o>{2gvtk9msw-Of zJGG)?&ut?6wnLuR(<`d)na-fu%}g3V&2b}+l}E7;q{8$ zE2F0cj6Aq9wI%q4*6w&f0X1kp^XhXH&%Mxrui^#gPo=QePZk#5 zQ))f$g071{3NZYORV^2Fo&RKtxO+=&T^GLU>{oo0#(fx_Ho2nhtaC~ioi~}vb+}Y} zjhe3+8*PI>hPp_z53XpnL141oc z@`{jWW<~3jpZ@ffNb@T%t}n{rLQ#Sy|E0gX`|iK{rFx701w(}QmuAL_BkO)xdQw{J zhe)_YQx8^G6fe7V_U_`XmsRrAnj#XV?`Gf66LU-t-QOs=T)JVBZw zjYs7b&YpgK;q0u^Hr^*=g|h^g&yPxv^TUe4Fm7OIZJ6|*JZiu1^hN$SgRl&rl&Omu zXk+T`{8iObtK4SQvEs&((-|EjruNp&jtr70Cz zUM5e+iEj?&%W>?VCp4$!{ybU^RuGH>+X^v-?^9uT_ z$p3S1>ETjMZr<%jAxxT_IaLn?&P$vB6&hB)qI)QXp*yzy2@09pq!|9V=&WGcBBO;7 zT6s~@_9TFcj8tp`&uKKL7n~c)^X9a4LAt2JrQ*eB1)Kha>}cAgA1<|=cgZV0n;v$W zE})^0`vU3}tUZWnu(iH;Mb7LEIt^&!)>-@#p2?LdCvc@X57mO8aEk}4b%oG9F* z3RigAv>M}$&8a1(qf&tDtPCMrEp$aISlI>FC zJun~5@Lq3QADgE(S}>}q3H-BZW`EW^4z|XmX-Tk=5rV6CJAA+_>jOR{=MfFBzrL2f7 zLu-Xj2j7C+kj|;;nmE0p4adK#@eYK@lhCxHY?JG&S{!)~Qo$_DCzzA7;sZPDJOy9O zZB&lw1v*#^3^suIS%-pHY~9Aiq^KraTcReZ>x3&HzotAptg7rD5e#N=Y`I7aEnZ6K zC)cRDxxT9^ZI!K;8m+Rc11CVDhBzjK`A&Wf_2xOQA#I+ss(5;h$gtCOl~|OH>lf!5 zY1RXWOAA|6)o}AVl(H-1?x_@#!q6({3;=Y z6iUdsl5gGZfjQR`ELW5D1iRm4Jt5rBn=*&{&DIk_o;lVN$o5Xn@0fWxzvK_*H1a(1 z2{ZEFHH)45bdIUF$FTx4>%M0mB%HtX_0I{GeHk0SEtlnpTUbc7py^yXJl$yGCrkK< zaYdr<EFenmrCSfV*n*AbveMGB$_ zmL*wH-jq8quF<$NsT-LdTWo%8bx#4|QQJc4A)cZT+LEXuW!+O%)LVDNapUZ|B?{?v zedAl zE%wg-bz@6S+JXz*S`=ag<}U>qHlA=?$fqX$`VkZY)#EVamHbsl(sWYQB)%|{8n-`n&DW9q^L>HlZ%UBK+Bs&vu4 z>zNk`ASz;a3uy7G4Pl}3*nkE?NlvVar{m43)5kv5r#0Qx)yL#?pVMjjZlx=+4^a!h z!dA$aYnf_0Y9f-)h%KiTC?ZK)(0vuuT(uOa!Y3#Q1V~a<`*r_+%*UGRy(=VuO}=FA z+Iy|J<{a}i#y`gxbF5_U*VwilWHq7-H`&s3;gTms7q0K8=)xsOrY>A^B@1@B-H7-- zc6nY|g8d^RSgQfN8NYAG(2R*l{{<#8bZhV!fHOE2a1~}AaUh_$%bwa}Y7hU*LOYCo z)Q{r~j41{pUyOj{8kcZK-;e`=PzL7p(?ZjREz6#9O5=GLyA{H=8$||o_pz2RQygfB zsL`=uq^(Y_Q;_%vYaln3HXRa)ZVY<2YBv1Skqv)p-EnvT+f{JPX*lmDc z$T)t=kr-3IYPV4W%tVv`v1Um<$g!tSC~D#4ug(hCa|IyD;)Ko9Y`gS}jG)mApz_eR zFuC$%y@1pXX;>{RAX;GKA!U8+FwNPymXlCz*HCLnMG$cZFhd&-;QUwq2XUA}YD{in8z_O`7Xy4+rD1@fD~$mdFfc(8PajbZq#aiI zWgITdu)>tVg_&M)6mm%Aagbw{YBDbQS8dSVFgTo{?dzMj%(v4T#vZk%BK`9ZzE)_r^u+h!6)i7<&6}zy|0CuSqo))J3oZ_`} zz%5c#qqqg~lt+dwaKXL|a`jnMI(N__6{mxi#X-=rdLd8Zi7eQf*aVO$bNZcUrAs*y7ik0$UOr3v|ITM*nBk8%8d= z-c00T$CqPl#~0$8@J6W*v#X9`7pXoKyPOh-T~^OCvl|p>ki*SMfP@C&i;xgr)N6sn zli-V8*u*bz;Dbp)vn4a&jiZ+xoHI)JtB2=`UQob>&5;7;fL?C1=tY$>7xZ$QG(NZX zk${+Z8KD;e4UfDGT@a6>7oOj6&Syx6OcwG-$DVQ&)h@E*&4w=AgvCJ@YH!RLjyXdY z+1VXeyD$<71ae6AF-I6fH4I>Mt(gGEjw}F-)u>tZ zLj%o?cyyRvPK7VosuwfFVv8{dVlE237odCLiE&q>*En!Fu6E&pKR_Ml?1YtJa>z6B z?1ag7++K9-tV~%Y$HtvIC;sY7uX@UA%}Y;VRx~=9^A8mgqtVIz#AtN5`-tA%lFxso zp!DgFB}GI+e){fFXye$H?27q$00+t#q7FO7&2Vg8z2z4Lc&=mfrfe$9;9;8-mrhEg zlA2*EB4y%a21?$HzzQ4SYytD#FX-XFY(5X}Dup|oapPlQnS$5;GC*ka7VKuLg=U=k zV6j_PKPqPiAh>vd5p6+%@j<|Bfo0c8R(s5d;4|I;D8*>zXK*Hf9v6k?4QpuuqQ1VF zE*^5A#mQ(-^)l2QPcguzp`(P6D#Y!g^QyAcL6XPEsdGqloollL)qzMlMoK(B{HNb*Q^pl}p%j7g6_i0R&q^NV4 za-fTcn1wo2r00=zoS9MnwfL@+%_m_`H4*|i&Rb|zoT2rx$m z&YdQRG@%Ue7pIw;Nuptxn91lR-IKC-5pCrpWB^rgSKPdMt)dUSTLQ4g1eF7Y62&z& zo}6TQ`HTNXD12qv&tR~^Y#5Wzpm8_BiuTnoIC-itEq*^5oFIsjxCL!k_OKL60HfT5 z4mYHImGUD%g_SI#qlHB(zorb5gS8JyJR~N}U0&oYBtU1qdqgzIZ2MX;~2EoRN)k&@zcJ zQA-o9PeNC6zS)f-EY4q)?>zU84zEQ+59?Nm{NmIMHVQJ!L>pH6 z%vQwwLl_IS%v>GfR|`jg$J7dog=5bb+IdzRQHa5|^eOF7a{%6;4Wpc8j2MY546saF zE_}36bZS#(&uE6f&bBY(@Lfa~V^}zwbkLSqc7RqLAvS!yUOKVR5Z%pl@F(&dym71#4Atw@8WNTVw8mM7 zkWpNW*z{^LlxEbT*iGfxGC@@E+Dkh`(t04Ae~;g_i1HQCbCyOQUTm!Vx+2n(S3V|*ofS0EK< zp7YZ^`CAb;@ME%RoB_#`z!PR##_tCTH!C38ioiHvt}})Gg*?F|l$Afy-ga1@tGE2z zDJjA6qHqgAp+I`!e=`LHQ{5n&SBB9c2wcqwgFgm)5)(FF6-73+dNT{>YD3(n_u13` z52l{}zlD%qFfnLm&{o#71@+)8y8uvxt%5MZOE)0j)lnjKW?=S={54+#;KzCT;30zV z#-65UJ&H}MLxGCrL4nEhRdmRas5=IvyH0qJU=s69I6gTe-Uxw?rKcX4KKt0d#sjZ) zP%rLKTLP7_c`cL}bq4x@#PBPy&uUnu0vIBy?>6sP9EKCt65f8!8Uzv|}DUkna{x;Y{5vH0eEf~V}X zDvHW;01-7-Mh9scLo{x~E(Y6zrkb~V*c@mIXSW>IP-?crDz5hiylg=?Mh>k;)U~=T z8i$}Q+Ys+AWV}~xaj<^j<2>@H&sL_ig75oK`ZOs2WvZD`K;r@2?QKiH)?#wyo41fe zn-Em$23v6Wj5gUX$21{;^6^3m#+L@G%o+!E#u}f(2(&6f4FaQMs@vfPAZnry_oFSq z?Bzy5YRAZhn~-Nn^|0@0bQIVGU5FZlAgVTViG(W-3lvALYQjo#RVbVu3@|Bc9qWy( z*uHWE8H4LWxS5P+d^4sIF;NysAOvXqx&U`3_C_E|eU4VzGtcU7YlYW}(pQD2GN@am z)3hUzYHXUq=TK}!!d8mL!|3qa4aOHH28IVjyXBN*&2n(jL&|+k$6R&7t0Xp#u$$p* zo%uG;Dt;joR75O%;yduR4s?n5ze9^KPoXZ{9WFC11Nnq?tYd952MeWu2fRV@kkG z6j9zk4*`GGHG90Kk&*~T7%KBw9q=O^iv+1Kcq<7d9p47Ltll$oG&Uiz{v3t)tE}&6 z)Ooy|7yiDYNjg4kS@wmbkmyp%vEv?ic#y$U7VG&;KLk&-I0X%3_ z7Qtf}G`0jMtH8um5upHx7QnvyBji1%(Jc*z&|d<3Ggd}BB@v&2+7logrpxG)c#k34 zg?&ijji4Mb60$)m0XUbh*q@a@q%{bI-qI`l*>>ao}lqw<0fq+29eUWDWlv@mv=RC`O2QCQtwB6E? zWy{*=vyX8%SX)-#@}@xLpjWjV)ZlSKYV3mniTkWm7K({VlMTji9FE&a2`9EAlNu-MVarT6}N@4K0S&cnV? z38h*6K`T|@?&kY&p`F`wzVaZ(cgZP^8(bI%=a-%Q+6iobkL>P^hBK$ZP}PIVw>^zc}~&3(a@Bw zv!P5mR~vTuaf;RUkR`B(n2na~elTi6HZ2jH4KSay@db{uhdj~Gs^2dF_?BduL%Wkc7m< zQ3b#Ym}rlR3ek?De!L`c!|G>JR_|THl%anC3BQrmrZh(K=oUVj$gA%bUOiJ-tf*%T z#GypFkjOz+rOY;5TQTXT&C8(7ZYCd-a2jbG8&!a9%@mgSRVX#EapG_tZtI(&wKJM9KDA@fF!P$+Fcz!s(2l|BVA+IMp^blMzZ7#7kQd9-vgbEwy( zbe`!pj)$V(1v7`5h}t)@bj8^C?vf1tZaT_676kQ+)S^yt`$6DLJ=MYqgz+3Rz)In8 z+1wr#3AcADQteR(w(;rf+)PELy--eye8B|4w{*^rc`2OVsYi)a7zB7nR8CqOC-q>w z)TosUt(g934)oILV&E=g7C#wcAT-0EdDk)mRO@=63gvKbdA*rtkPhMlBFeu8L;_Yk zMZ!t4U6b{KYGqqShpQ@daBAI(;!Ld;LH)SOG_fWBd%1GVWyW^cTCh$2d4{-6Mkw#Cb^~Ai@+hZpX_w!Cr*_8yqjp zIR)p7c_Izt>zab^F_VfgUak#B2^xwdA5c5SwM^-tD{|geW@>S4Rc<9}M_{aDct?o{ ziL_mSX^VOx87(>Juk2=6>s6*ekP4i4j?JhlRHyhd$8Ck#Ao$iLZr>7j1*|~@6ckrU z%pfS%M83;Q#x&CxIqB9ymL9g|v^69QWIf|#m$)!VMFuH}#KdMPR1fzH*8HM24-!`~ z#wp)n!VSoP-yTjK)?p~A71n*It5Lm)x*n%|QFq*zzelem%K=A=6T5eC?#JvMoV$-i z=cm1UuZo)qwz7K5_oz}X#ESsu0TZf$(|Gk}J_OhuqoZ*iv2x(wm@zB@f*C7?Q?%9Be0MxxM+erG0p^C&hbCqfzGH8|l~UrkX!z~*v$GW$0;%-*`2D2C77 zz_P+=uD}T8i0lx;)xw9xRGZB9!8?dQ!C-M>kyQqShJQCkFr?I%tN;Q_GzuWN3b4Wu z*R{7}^h1#v{f@OY24#UjQ=S7;y9QmKBSuhriqLnc#j$l!^8h2Mb_?_|z?wk2m6VY7F$98oiDg*4puQySQlK&|N37D%))pr% zk_3#c zG))cVWQwxWSMrsYRFr%af}{!K{vAq^XOz+j!~8A&d^AoUtB3KU{+5D|Za&~^{(lOt zvs&UKa9uTt5bNIz`QC3Z-HV2p)V#{elE&le$kP7~tv}Fs?x*?}uu)$GO zeR-k+6fwtvg0zYvFw~>?iMN1LT1$s1Su)?)eBww=(FVGta*YEq0^{(N(y9*twMeRU z0#sF^Aw1!O8+u|wg)6$mSYfV}g{DC4Th-C@XrIcCGiC$nP^rZ}-bu-qO`9^MKe_Gz zkwKM1Mg%Y zK_JX)_q0Ef{G0K5sjzL@j{fbOCz#VvYsUH=1T%u?LY{yFC!z}|1!bFCUxxS5a>J=u z3ReP=0sdrcV1*#mL#Y~r36_L0!D*t%q=8u2vjPPfGMt?xQd}t((}Z{qI#RGHSBgWe z8*9)CchwTCWvu5E8Jt_4Cnt7f2H0DIAuCckJ1AR%Myr_36nwUO00_`@^s98Ou&g-A z7p(*G1Uxs^eidwo%)ACfmaZZwvoH+F!bUZsadD$-cuh#&7j%%@jjHuM@!2UgtFUiTW3WA)0xf3lQfO?G2kMoS2+mplb>M5R<;#0|d z{_i<~u*1Mgt`vkSfExe=2O=~kMocu106c(&(Z;gKCly=#JYgy<_PA*FaLPE7 z!R}L0;SfsoT^XSq6%w;;np<9XVx+ucBYA9eWF_)zXO|so688y}6f)&CKf!yXq!c(`@4LHA`-j0gf%fRXwpfA>O)}c_?BKFf2L`jJ$j<0v+Nzr!t zP*F#Neox$wNFQSJnn@jkl4L?mU6|T}r1#!x99>U`lX`T;Tfz;EsH9?j%j@I_BHN15 z70b9)Mx^mhDYmhh2+MXec>Hlbn#Ln9RH)TaLo|FPi;qe{Db{PbpNILP}H5&>Zx}q!T*9@KRgv=i<|L{6Nmg4 zQOB=Lly;Zs2tk7!#wX(tT@~mO{UqKKX=qBol_=wGZC^kc&`df-i0&J2Ua(dQWo*N_ zE>t2+T4}}PeT3m70k-c@JRl(y*_uRAvC<2RCQ#hLQDdtky9; z=Bhqi}4u(>fl&lCLTfCs!!lF=l?*s&9O4xl@Cv zC?z%*icg#y=y(vIMUg38{CC;&q6K#}+)nYLo!&tIyXYAQ+cRqBX`3xdpMi))r}G7Z zN^K3!t)r!yo;NlLP=&XCB`!AW-zqMwQZ!^9Bd2V^Moep(7X^+$EYON*PE4%@#jWb_7Sq?-4-gFJJ3y#-3wC|odIKW zTdyX?*YSFJBBu-%iK>N*+b}koU)KtYEnioF8fIC258X#;fbFsG8(Wu<69|E`fw$_6 z5G)~Z3;_wuA0~Z$+5ym+>|ANLXN`?bSe?FzpgdMaNKUABj7qDAc4@ z_Y?%!r(yVxb=F=j8{r{WSgnXbD=c7q^t(D<0|Xv`S{;EQjEKQtTG5GOROQLHc5QJL z@gN2#v;#lVDohk17+YV27{&*PVhp3$mSAYHYk~K*#6G1^H*wIl7;&4HCQ#J8*8)ZA zV%?%Ip&Y@0igOe91R^PgFjJQpkOQNawzMBKQp6mRs1(lhw+GhZX|0y}p3GX9>-A4l zH-=Q^tKDi~Boj9m7{zak)G>!9d`DU?L-!b+5in9M3KVJMRI1jrzeoYGej5c*?#$UU za%ai`UPsL3I&ifkd^O*BCgQ`K*%`e4i9%av$C+oG+0j`oR8Gm+Qa+sh3*oW&@55)z z@j38m{tMOsXn)ZaS3R`6>8dL(nhn%_7eaM?e>vVc8n}9QA$QUK<++P0;j35R>J^cz zSK%rktV`+Lh3_s;xS}Z}yw`d3m3s?KYf5XLFXYx#3gtC8TZ>=6D&Y0>YwD%v3QeW@ z8U(d2;lmXDFn-p*AW!crdk2REOH;adAhkUuJOEm8 za(Ua-n!=i?`hh}udE0gS$F95Xrm@LDuiV3&B@{iiXAP;&*GmX=jZ07Z<<)h0I7}#| zmY3&u?EjH228(VRA8f^Ep|Gb`&uyy}=B=q0_SEb0yA>qhF$huO4WM%6sr(ANDYR-5;``cy0>-5^5r+} z@2f6v#pm+nJ8JuLH_hrc0OF!Y3l~l8DHNvar8T8GzO1S5nJSgg4E)AV6o{KsCDbA} z>wDI$*;C&(CT-Y5s`sE;X+i6n`nFPO4HQ1OI8!)b4M>*EQcAt>hWZqL)>(&hr?f^o zs!-p9VVK$j?7T+?uIak{J7$+JxM@dU-%a~(TE2Y$P1WTK#?YLx{nz#3UfFNOo;q*@ z22XW3zG3w1Q&Jp64S%9{Bnxk-dQ=PcVsfEtx5->rSuoc~zPiq}zz5pcM<}RSmoz1< zFgGwLuy3#)Qo?B@eX@;{yyd3-`*-wBFK^v3hVI{AVxaHFMD}MLqllBE(}Mpg!qnupXHKSn%5l+iH7SNQxm($ev0g z8}pR)A1>6Vo-Q0(-hLBFy>1LlCO1}FK96&U6KTgR-b>+AJs)!e|Jm*6In*~(n2*`7 zDUR*$F_P&}4E!;*2bDu}>5L(|BCe+O7J<-`feu9$?Q``2Sx%sL3 zZ$N1a`fzMVb$NZPy1aS+O=CM`B42mNr*jXO30%~t>f6?=0fSa!cS)eb1Cn1Xx55aDSh0WnJsxttAc};aw z^EQx&D=3?aP6o&)3(`ylOo^wMI=yy*@D( zXq-p_yKun*P*({OfsF$wt_!CCO;hE1ZjZFNWY8pJ4jjeGT#|UtS_7{#kFpvHAwG98bx{# z=}x4t>hw?edk4}zNPCf1B8AK0@6(aaM9QM+4ajpA5@|YJC-%wNI$epsq@@SxMx;+7 zeGKU%NFPG_TmARr_&bC|db*Ix>0p*e&_Q5qs{~hTskk%uSzW3?WkH72mwaf9B z3XEUK_V^JA(5^RApIQ@ z>0O5OV$c=tuNzP==^$-?g+$s+f05>8NJoRNxV3t$c2##uLplSAbNEuEWjgUUdB9ajMWnYQC6#rg*H1&4=OJ-^ory$R_?zjCNdFayb7Un_ zHxlKfkw1To@Ba;Hu5&X?E1y3diFKcYvomqxGBm!hgf{v)`{q;@{hm{tuGjN89oJ^GKgV`U=vQ zkw_=o#x}hUDO`Tm?{NKG#}^>6T=qM01;?L>1fu^`S%u`NW--{EyrKV zC6mZ={sR*E59!ZpW7>VU{p7J+>r59R{a;A`38@E(Yj2fKT#Nr%r=wXv*F4K+J)8ra z@0{zTfxLiqnz0zbcaFi)uAe;bZAipqA4IwyiF5z2k+}Xj_gVMfBJqA&{hXIfr|PsA zf724@uzAM(b;s^v+~+v3PuM?SN4gJbFVa0oTo1P*eF13_>AOgmA-x`nbe@G|%H?0y z7e~(`To0!On>_XJ6JFcWbIX#C30ynncQll&XK`jBUyjKAtrY4RPvvdR0T?KSqskG*-9{?!-n`~H1j z{L2dtcQl=S-qL$;HJIliFaM|a&ram;fA7JL+SqzC?3Qw&*VG7Qc4!qSg4;iy}bw_d)jeqh#j>DkJUeh!JFO25G%BUaKOs z>dhy$Dq#RhLuK^CGzMYDYhxD97q1SoPDG7-)bmC#Zm6|u*2#ef?bGFv=3Z|Izgt=C z5C;R#ruOPUt+xeTIDk&5d-;(8LthE>u{IVoQmS_42S%hr2P(Z7VAG6&kqRHGdW$*S zLjxer1EB+0T+&Q+-+jE=+uVhAfJBzgFIa$}Fk`NwdQG5Azv@T}M;lMKqdSDi8AYF7 zm`<*Nkt(~v5QzqrFi|maOMy%k&y-MBO=?BS@|Yqpem&a7qzPOiQ)mS93vC01svFfX zj|?2tQ}RTx4s@5zX1nos*o~+cw^dI@GpRBRje$-~WItglIX0-H=Cz@LB+i|TBZkU0 zQt4zPm32eCh_Eh*_DKqQOSlTjX=PGYo*L@+QR? zU}-*)lnRsUDv{=r%S-cJrP@e-$TB8Hv!9zQ42)MeA&3<=sy-J6GX)EZ@X?{tp=8-u zpnMgvb599V?}9MN4|R=19%SWK zj7w23?UhL{f6*m7uH1Cxr>|_f_^lU}4GIy`aPzXa?&#Rm@x_kZmCtuHExr7*aE9EK zpV#-FMV^<#-Es2MZ*bvZQkI6E^X5Z32UDop`dZgCXgtBT7 zL31k00GmK*!u>}Eu)40Sb~N=*tSEQXw|_OELt_XeCJ|gFO$FN$X2s9B7b&tpL7*3i zYAiZ3{Z{kl$@&G$AE;to;3EeCX&Sw&fd<#Sql8~(y#*HFa9B^Je0LE|Zx;~;K79hq z9SgUQb#&Y?wqk5zVr)gVqgB52S3B}IjMXM`{k4wP8@6|hO>BQiH>KJ!drLL6Abx!m z&`l0Nl(GvFtL}@HHq{1#*U-?vM(CcHxM2k-UeVF90_3mQJ^_LkkKx*OUb|szY1dm{0c20y zFrj<9+)=xw97pp}z(TVG`xT1n=__UelK4HGl!*9{Xt)HGwq zeG5{6WttU!G|T_UmLQ+T;7oUf}s+&lhT_8km>17 z_>?@oEy=2@Z23kp@OJFi*Bm%yu+kn#*KwsLPKM zdMbMkxFYS~+IHKkI7*1G+)(XrUxC%gHCX9*9s3%5rGG{L4fsX|(?6Ep|C_u?Vg9-P z@x9%g@@W zc>$r-m2U~>$X|4s0%rM3-ZC4&WiKsce8_8l^II>z{5F8b&s^D5yyUHi1H?V-wOo4H z`GvD@L*s4*gPZASIqw3m_|};~u1BCMx|r=}mO~v)=U#qEu#M=!Hy7E1%Fo%`oUdN_Y+!Q2O|x*Yn@^Dm8*arxOMPo<;zop;^!PKcPZFArx^NRO02_IH2n z2S4~)cUZdL3+YZB*yH$HA@={Zci5|!AoK+x^I1&px8G6yLH>@n*YL}&<6dG<(R)4a z%_I2e9l)0F2`QoGYV2MVa00nBQQf=|WHSwn%NCNdPXQg2IrAJi>ELB(5uX=3WHcrBc=Lr~aob7mSl z*Y=0?KdN@l1mH*Lbo}be-hAK$-FnoHA0xeu)}FgEe$B>ebIN2g1HHXi8JLL+jsAzd zE*){Q*9GMURLH6?khcr!=K4@>gxks&GBcw*WT-@~FF0liU|sY&twY==DoW~J4(y{< z&5D|bNki2erZ_cHq-6UT*2oRqILp^odxcoc=0U+4UD+Uq3BOWl)*-eOVU}=DF&@Seyh#0Y(P| zM7xbK3$`huf{t^2+%nM zVbLOzT}gVQ&q*#gj3t5vJ6Ph7*GwA`%B^~i#wEGrTRRd+4&wwVxr-$$tY}PCX+=jt zfFb-OW5o4MIu*c;Aprq^TPKN(cZ^M}rbRAlU~GVA>Yyfwcj(V>V8uHLaEFFm2&N&i z4$j;Ma&UlQv}lEpNaS4LU^aYUzp z4Kuwee6JS(mgW^O@W{>`Mk-f>kX&1$bY^uJXX7waQPvzSW7#^OD;UJ08Uj^UQ1Yn( zixJkU7U~Wtga`qQ7|*IAEVhGHIAS|mh2w~GWUUCx@0cp+mjplNUgU0d0)-~rDkRZyzBB0X~5JD$60u`$?N>b3e^OVe({HD3I;LG}%=>(ImqB zkRkH%z&~k`{|icR>=@%8Pmuibyb=+)E|dVBZMcN&O|~fnPP))@f-{3N2HKFi)3#5? zi2E5)+YZ6)P&C=45?yQQ&D)MzWaojZ)c%{g)r=jtttnR8qb@L8?)_9%##R8ehj@pI zDVX~B5*tYgs#(9S$5D+(w&bRccsl^xK}P0jb-zeYw$4fx@w&)KQ$ke)qbf9G80L7co-hPwJto9ezHvy`M^Qj^)s>zYzG@Mzel zIIW;fD-BU{XYAos{*eKjKXn_A+@JAut#$+wZ;IoQ{x-Z7$n!O;9v}n;PxKX zLqei{ie}OP%*5^&X^-jX&r8|L%|z7)5eEaO+okBBg8@5T)ks9)*T`Q3Bh!RYux=|8 za$1#PpdpLGVj0q}RUepY(tBymlw&%mUM%`)wT6L*tu+cf;4!HV@i~Kw=Av`iXf{=i zExgvb?9*!vDIJ_Hj)5Vw-f6vxE1)9Zw!muftKJ3g1_3070#NGfJ?1>O;;;z-C^;PM z3fAu^w88;XRQ>ROLdVm{AYFj^BRYztx&3)EhACgsQ0+LSaSs9XA)X%@2t41gYXF|U z%||q<47lHlOF*VOfIMtq&167$9LF@`x9Io*ptICJdot%mzw!#hG#{ljE(fM%BBt3B zk7>&AacSy;Os6=fK+WM1h<%26I=uzSOmlM~!_fQy)5js*eQ3sBz8! zF$-BO6F>~SOSSR?C8ZX-XHejtK-T#&mZY zhFR!f7*=aQ48&3my0hNiq0DN-I3`$a5{^l1ZwXd=tX?j;BWi3aj(WTcuP_vIR5dfQG0es=*_s*bZQ)2SkZ5igM(s3@ zYi1lYqje*Yk>tBaf@+jTE(6shsb(DA$PoY=GgUHxO@dxV&LMU60^C`VbL>?!>~HAe z)Df68bP>ihR!c&aj9{}l=w?){R2Nzu!Cae~3To`|0@Q?*GYvI1&PHS!9E)ihRnFKk z4#0}JDgIuFaz@Q>UnMpdOmkc_gHwn=LCy&c(OSSQA>)LG$#&e@)Ci_IHhE%0TpDP8i#`MEc6B14uwpQCCAN^(ij7&+Uu5wQwMb1;h%x$akK?-(oibTB6Q6Y z^hYHLPS3>0>@tNS%AQXm9;TVGUcy%IAP>Ae%JRA>u#^J@ii?j?W{V5>*xD#CNdfh6 zyg;OVGopRLKgWiMfmXkH0OUK0ee1f5!zYTS`HT~$bU`qFh~KNS=RtzUMbL9-oaZ>_ zWQWiLl`!+vyz>W!Xt;uTLo2|#02j3PioFJ#i#}^yR)p4-)hkS?*!@6hT+lqBG~m|D zz!)Yf9qf3~sClFjE=}G%9F!uBHUOS=P2!cHqY&n(o`W#{DR&~|X;(cdA&Jtu(eVMs zbTP!mhRj2l3UnG{rO;kR>!0-`(tcCU6{vW4PD&>7A_1TNC@b$~>O!*Tp?IjEC>VUr zX`e`}JQ9W&cpm1BPZ(#H?KL4xUGWLyitwF%*sr?JKv%|c(=N?fA@YPUoEWECbq+ly zgi)JkmW5APVq83DSxA>DZ)+%%@hrxQsMeou2x}hw<2IgRqr{FiNw_!4^ z;6RKBj8HTKEtTk@qy2~uH>7>NgRDD(OjySvak`*lid^GYjDH}fbETSR94Dj0-mmmo zUE0n1SEL@+Jx3}G;+Drzo7&N9;PNXPhkn53JcDoe0Fv_0^HwKvD`L+OqUMDL9;IjHR0RDlK3&v{I2qm+>Tc;$Rke=2i1z&L^I^9Yf;CVt2Usk+%SEe59AGR^5`K(Fi>9%uo5Wf&(=s0K7j70jFT$M9 z>^JTdy+6hhWx&E;cvK$#+$kx+wW4qfT*ysG9hQa7I}T{)MsP%czA) zLdgmCs7i(sbvB65GRpfDe>H48F#2h4}$|%mZsypc{D5oEm_Q zk}sj47E;By2h1>;9Can7Bm%psr|2ce2-{Vo?8I)ro~-Po&o-E!jgffj7~+#jkg{;F z#P24wjVQcKoNl1AYTfB`#_}0n5hODFp4?j zOE8iEMY^~OV(0`y5{X#lXH-F29%;e5Jg5y7ZPyT?JPVXZqB>RG8WSoD<>!OSK~51wh@YG=w@pfc=5Q<(}W$JR`#5oQO~{ zq;s&CD@yuwM>|(|EbW2gA&PcYjG8f=okqE8XTJ(EiL(&GJKMoK9S|9ov#JXM-;;)jX7mKdrb)~;BX_9+^p`DQt!S(~{bggfSxesrK65t(Je%#ZK z!B=BGl+d&d$7XokYv!?NST`wj3~L6uZ!3v#h29>F9A6Pt`~C=Vk4bc1M2*OmW{Lm3 z-r13M1|x@LMq#ad>)1$d+;iAG$Xg1}gwSAMEN(!c`KNiEUwILGG};nIM(&H$%VXi7 zkpaW-JYu3CcnhC|xHt(Hgjy5_3CLDQpZ~eqxL|9)=#@%BqXw7=04%Ik3aXQB%$}7{KLI>Ax5=oi;CAX2j*L=;Oy%aQX^9 z`u#Jnqw|_o?_PDyd5(liauCa(_pZvj^Y1#(mt_ydSkiOX%)UE!jh`p#DwbP?9PjdT z#Jo`T-RABWtyT3=!ieZQQ*F-M9K$H{Mm$WMoG@+vh*`o;S~klrZ9z;hJW}gHBO)}n zVTA>>BIFx6p5YF<1v!P+hYmZhBn2)H82l8fJ`L+rhdsd3#d4Ot2+e)H+`k3=p`5a@ z&wbX!8pf7g3~tr|#T)`uyL4lUz!7vc-0D zYKxO_)$j;Wf%5eBl@X{~qt9|o^zpb)m&!=SsRb$Im zAJCpWOKd*)1=KS9pPw|X#@@TYo{EDFcBwjl0^iLcYb?-+xsDD@NIX|He4sckKHDn2?7kV`a4 zB}9_xqNvvUmYQ{Fx<6%Ob6PN3G&6K<|Z=p;W45 z-C0Z?b%4{lGfElSg^R;z608Ix0oKW(YQ-?18{svT!R+tyUgtCW(5!;Dk3Au+`Mit@ zD5`fY;ncG4lz|?v*43)sFq6jm_3}P}yA{HANwU|%8sl+jZPnt05HVmvJMo<{VEh8| zu@!1W4BX1Dc*p~1i}#YWJV$2?3xv5{R*)CbMr^VFUalN#(Xd_ZoPVAn7qtHtm@r?} z`|}JraHsRqHTcnv4E!V&YTv0H{IH?{HMwXce`8C_J#~kny+6ez9OtU3Aty9fM(Jzb*KcRr43(VOR>l>4C-Or$pZAI7W-;44y~!d8k%ek zg7dY}s@wp$H^qzbh&Cg)cxw!@#cRATrX}Xh;{K|5_Be$TPtfY}gT|U*`TG51Vj4=t z`LaaBM#C;yglVFUFw#YQg_xOGv}oB%miX|00Dzp=@q!mPT9x=dmqgHir*gowuLNtO zMFcfD>j8DR6~$}>v=n$H!T+!lLP@Ex@SiO-58aMy}MV<7^3BR>3c}^c%JV(AcvpjMVnw%_L&IKcb*_Hq%Cfw z_unWW!VEu@v*Mjdl`LUP5>vO1BH%J)?D{>KUYivQ;T$n4m`Jsk8t+(_yHoMvu2PHr zHQ*OIPjdu>zdJ|}0g-y)XQG=cy8t>xhjldI9pcY`wM^AHy2cR_&drDhCsG-_l1*g* z(!%4&YaBHWR3t`?0~Ian3d#z5H)eYftTqp~&d>#`ywRV5Uvi;*KmUT~HMDhs}vQuc6CS5Ta!=!l$}u+*&V(7O=b zu84rBcsw3w_X?~sBwgnF_hV#;Q>%c$z&lN)D`P|j!?<&s0EbmIsr&^fa>m?G(k9tT zQ?yA=o+$HtC0}_d1;>zxjV28HcOU}}D18#5CVvaR9*xte>QNkWb_{&-Sw~O*Qz(p{ z#I@(*6-TxNB~9Rdlk5EkSkutM)EGUPs5lBd2g@OyI@G(A=Ru<`+X$+Pk`5JN>SI5w zb{o(bgIPGCk;76(X_yw`-3F+GyvUTgnCsEhhNY6Gh6)p0Y8ioTPN7HY8?*$%IZbN_ z2n#IMrX2|xi+FqjW8b|6lGx+rLjAD|IqO3o5r+pGz!-L#x_*^(+#R|q^nN(<2w}*J zZLCkt8))5UX6xRWEF!2rPelDC+qqZYGl?y3^xYp#S7b3W@8Z?FU%V}$O-L=zbzGE)9* zrhwyAQv)D2vMdP~sey{X1Vv-038Dw-Ql~CNOG>U6Bc4K4X!#VUYji4TT)3#>UmcPz z$tp&t61_bX|LGKQplY!4KzmrH8I^1upOdlpNdp}GbC98rMwstT&B5dD2nU~vJaU|a z-#Fk1Hn)&_A+8t7W@!ep=9m7lEfSVbf*vO*|tu$uERfpLVt=i{Zw! z$d&^B3m7PY)Mb+qd7k0K!tgs4o6G-&Gb zW6lPmt(ZekZPp`OYPg+%{dohK5Ox<$fqT^C0S2#zynb4Jr@QD-0)OH6@cHJO1vD%*4s zEG>mR%&%-NX-i}0r1hN&9+C6(hFB16i@+c@jB2;FONN@L>-x(t!<9znxjSksq+! zh_bs5Zj6=~6Ev1BkfFTfCXr^@VG~+66LWFE@icUTk+MbiD#}9ckD*MccHtKYPU&w! zrSrA-DLMvH*p_UM9Z(7G7cT9XVYy*nWw$HnZ7LQADU^dJdUmv4`KS7tYrkYg_5fVt zlJ+=emch%^DO~V1h85ag&OoZZ*~3cZ%pUhUr8I&!Rwb^jyIkK=&XXA)K4bhqzE<#6 zzEi5NBc9K>Lbgu5gnC!8=Ix0_V>IGU`e9Vnu|ZS=6B#xJcn+o$uHQwng`!h7mBsVb zR9DCE(Oa6)V;;o%9NAIG1j-;J1Rr1VSB^b{2S+Y}NhVLi2Q-7n_&xxrEFAujM@ujK zoh8zD(&_+geb9Nk+yjh5r&#)7_xXf%i>JRM>*qerA{ECKdefK)9un4kf-&L>KZXyT z<<;VI3lx*SMpg->r^=4~skIJQ;rJ)ZK|@c}p1>Vp69-3MtWB{7c-6d9EiYH- z+2`M25vp!NSMxyKJJn(JhWjh@hRTD-#q9d}4*9wqKH&D=a&mGp@E>p;eW~oq1bwX@ zkOGW)p)q<|TdgE8=Miv0^LXoI1WNQpMwc|wLSNDj^P11PbtZ}kG%|cZfk0i1qdaT| zeGk}_=golMvu9`VExDRRiGgYY=M%u@znfn@HPZiFY4%B-tCi89>?8#Oi4 zB+LU!!iYXuBs%v7i^acH;F5oC%@-%CYT!KP1^dx8i^x$c((K)SI|Wbf?AeaoS#mno z5p=n8arNBr)%?=45PIdTrNQf;@Y!2tQ{_`Ed3xLPuz=b>D@cO5b0JFlB+OcYC=@_OHxcQVCzZ8dsM`uCBn<72&Jj zU72tNfZo1^(#hM+c=IB6I*xV7#*%WZJxUDVXwaR z3sTlTFSoTip4-i5#&=h}Tz_Rew-F&7^r3KjY1=%-vj@$nU**QWNVI z*|xRc^HAK3*Sv9jH%iU-k5_x(VWY1<1x9pHLLy3=yhfSx>40%PaE}yMCnUgYkSf92<5c zNNLaR@$udL&@FA;>g^ui>h^$ z1{a^LyTQG3{k8EW{aaDo#&J~u3a*Z~ZA9_jZXp5V!uFE9n`c($Z{Ay*Xt{pn%DsCl zE9-mfD_hs@otW5r{j4Rtseinu=DoRRyq}%g)3X&{K*sK^{XO3J)}EgJjijADjvwmg z`1r;i)ZQ~D#N%C+=rTZFO?#~$p>=U(#yer7$tgvg!T#^*XQzOCU53|#mh{MdJcD+E z5HvvzRMV~rP`Y66&1={0npnH?`iZr*l?&HST)%Sd#9m&yzO0)8<~P0-{kwIXCE?Tn zDc(4~QI!V?$={qS`i8DZHDIsTvT-+>&Kb=toK@qbUtPvNb|WckXBV+6noyGbly=}w zo7~xm=^^!y5=Xg#Tsw^^g5{2u8dEUk^ZLAH!M)^tx#b!(X9o)nUC zk2Rx&{_%}ZdxuvxVUE{0^{W#L(dC>lm^v$0&RBZk_P<*VBWQu7+&GSNkeJfaKZ@8$ zH-lJE7$BAxu+?s)bFnC~l|>J4RZZRcly_+5!s|iW-ihl$+r-T^tj{K_Q&2u}^Fcka z5oG~QrwTYm#O zThV>!#Tt5+bhh9pf8}>g7&>9g8sCjMv=BU`A3OsyjZ^B>9f3eeXyl1a) zk$(Yy-CFBu?;mHw#vy8CF)rrw=9xTtb6_y-!sOTPVvBZ7++10iU%QL) z)bdN5f9bhb`u$$7-h(Yh&vW`Oq*%}6wBqdEis-4BH)v=W@AIb$Si{GM((CxNGkHM!$EU%rlWrN4fxM1yUE%+mXJE zbUV^NBJI#=C;om0=?<&fh_LJyKS^%yS0P@5Q7du5}~58|ht0pGNwBk^UKp zb@8vM_fCAj2kD(iab=y3>ugsRO>aP+vye#B={mg$f6vzGZTS29NbHx7A>D*Dg!Eyg zzeC!H^dY2=BW*@niS!PnSmx1&h-n72TqKkcX4bmk@??dWG>O=Yi zr1v2Gq5eI9zr4?}Eg-!G$wN98be)fKuR!AbVf+6KX+6?^MJ@4{V5W!y&uWY%V(A%v47cT$D+SD9@iqRM&f+`TcjKG-@nG+ z>yY@jgv2@aL8PmYu0%SP{YAPsk4YE*l8%i?q~m%d(!pyVK>9oV`^BP*>oDA3q~rfa zB263gchbe{M~kkwwR$XgFxL><_n(k@kUopF18D?l6zNm?`&RtD73m8|9Y}HXC0$G7 zEu8m%jPyT|{wvZ$NIyr~kMtlC`SHIZJ%IFUq{omhK;oR?dLjMCYOSz8xJKWHM7kb9 zA}#kJ-K*0#@%N`lKSH8x=t8;#>4nf0*N;bQ?BmMjHOkb}k$xA6GK2h!?O3MMmH10u z#`#TIKsl9E){$O64P|yBQC?Ag{T|YJNE~1O?nC+`B=Rn%UZnTvzkh*GQs&iB7S z`X5M?AxwX)6Z?hrbFMbpelwpq?(BC%ms>yk|IJ90M`t5lrxWWT9fltM{s7Y7AT?UQ zsW1FDT>s@LvkQrId>QGhNS{Xf2PE>MFCuM6`Z^NtvH#ho*Xa~4KkIk6e)5{7NNoR~ zA(`=KpR@nhB5_XsITG)=^}GF=Rj;}4*3Wr=G16O+NXH7KcOYGZbgfRj#{OBU6Q4I_ z9m!v}e$F|rb@Bnu!!*JmP;znF6Qm-WTbvftg(n6&(U%0dux}LjmwljBOf*}=}dciA^0IUXtIFZm>*p~!;c4wP2Hn? z`-_hhbMJqCGKb=FUNHAf#oTaZG&eX~^q<1F!QnDKMjzMD=LXB8x$a*U^UEH5elq{S zn^DfCdjqxJRICqI`*Pjs<)GY3-!F=}4?H`WyN<*}3ptod2nu+#n7bX1@5bZj2Ockw zhS_4v@cO>d(fsIOwV3Z7tc~V}yKBX^(e;C)qx^;B^7`&>sdRLGvABLzez^quc~2T199`en4SM^!h4R5c7H|Td>jTxc z%oB7zx3Jk_8-Jn+wPHI9SU)TzKLnB=dcHGEFegh3x`x@CK-EmKja8tFs>S&vR3&u% z==yRoH#m(P?UDmc!6V)5%O&g4jq68A-TGm4GX~A(ktglr<_;9%|KWy7Ej9G)B0I5r4tkJf?!9I{W zyxtU~vp6MG`lKe7FJGjcq%w7$qW)TOo{SLY)Npl_WRGIvv=5?F(B8gTtV=~A*CIpVSHM#uG{9Pez5UUBpE&UmjO_!pG40WZ$crFRgNiKRJvrULwKZ>=7 z_K`SuQV#0!TS=v#Nr;rGbu!mFidc_!tsfrbr!8uDu!1SAia>3_DT(K%lNhXYqdz4( zgv37Zp6>OdLZe#PLMSQJrXWCVcuI6e}pP^jsfs!JNoLpjB%aBb` z83LkZp`!~pNmaiV!PpiJb_>ycE;G&d4GWibrz*K%yUNUEW_Tgyu;K&q8OjtW2lKMe zWu)li!$vGVAaZPvD}M?UuD=p#b+9<^?WHe&>!EM$zV6L&BGzQZTKIINh^LD6_4RHr zncg1vejmQI?pwER za&p~6x*65Z*)7%3GWhk;KsE+XaPDY$qi~Lho#2o!6rv~hty{Hja$l{p?Z(L)SFPGN ziEpcLZ56Mz?%O$e`G^4OC>_~QGz>R(gju!T*b`RRz*6N!i}IeKY1g*P2M=$ z*}iUa6$WB*)r9Woa%XKzIhNw1f_`Ql_++|V=q4PB>2gK)&T3~H30*h2uDU9}Z|AJ~ z*|~4$4>j4?VQ)bSut~kDj}9JM+8?yF9=u){6kVcxEZ ze!=hvFu=!6hG4;BoaGJl^s3p;MVQj7*z1i@e6&zfxwyzdQKWob;-4F3+8~zjhr2*F-jZ1_;I`HHt+)pZ-t z;b&GfU9)W2;Q;)5xY)96`CHz60mb;O;A=CTE#4)UbzM0V$n^+RL07T)%yOu+Y3a3B z1>1-Yyy6;mATvDQneVzH*gfpvw>bCTdUfRf)o(WU%boSBp!R%AG|xLOFnKDS&Hr(1 z>_0-fT=0%?Q3}$Ll4@t`@89{uAKv-L^^d`kK->e&G6u_iifd~`XK5B5AtD5 z?rZ+J`osJ`UsJ;`w~~8_GAn(L73U3N_uI#<-4l4eb(kB?A0oS zt9@1*#?9G!aE&Hx`|83!+DSh)s8CKcy@z{V>Tig)E1hjSv9KW(XFHeZZ=Id`%l&Dz zM7E;TH|d?@f>GIXi>3>zkzwk^pcX5h!c93g%t8#*S=c;7*Cnu6q0XjNlj|@zJNK14 z)z{XY`#R0FWO6v-arz}qPODOIXizqc3b8K~t=FsoHrX4i9)xN@Q=)j_jgz26zP8>t zNihcMZk$Y}L}pK%63HP2Lsjh-nv7nhh02z`iXlenw@8r2;*>&Dmq5a&;-;%1A)o>h z5-QZ?VbeF-4ehq+g-US&#I~rSFd~&=3xxLQ`o`+NwKJv*;`BRGz07~;W@WT({pI3( z>M{uxSbg()Xu0&}FQfJ3DX|MSvPh_}5fW;B>~HA(78(T)YgJ=$YH>YQiR}yOiLgV% z6d6?HX!(2ua})C^tc;;@mwXahUeSuQ4x=tZNmG$3p&X`#K#^uB+reg)UGv3#kUD@iNlR@whQTzrBYkz3(P=Ykt2*I_!Z>+Iz2XNmo#zoe9e>GN>$N#SKI z3M>^{zZ?m{B2nMX-z2vBC95WSs0fu2bjhO!QPfOlZq@Th{F}w$zohytH~8b?)5R7j z@rI#BZA8`xIJw3%a?eUMuoy3*%E@1KiOJ{-$cwLXWtWt<>~fP$%i7}GgLxqE-*KT4 z_>f~4b_M1ABgLjGuf5<4n)L$_T)5(jU=9F_tKMP^ll9>fadJ>7x8ld!L{dkzq%46VbVPGVfs2j?Df}Uomj|N4z4V9Hx`v!28 zMot$3-JVuOgq172(}d+-DdxHt37GLsbPJS;PB4x}6b8p6SCfomT3|sO?gLU99-J<^ zHnxaNNG?4Qo6HoOVK$^ZWa-MvCUz22xS$S7ov%m_1x2k4fD!cplhom2iwH3#VI6B0 zMkTiBFp3Bi9Y7I>iV&ZeWVC9ydX+hn9fuHDG!#ivw4(q?D>*9th4RRhq4Y=F*ALeE zT43od7Ecn{j!rUGB-Vmk5cr&$3iS!(OdZx3v5sn#H3#y#4OU*DEnl}lOOD8LHUG5~ zPpaaRBD0?rR)GD2mdh!*A(vHdBaxHV?p7;(4@l`0w^?jrs}Z-)G{~Edi`l@2|HTx% zuQ&~bGF+118<}ZQU06@?Su1Rn-_Fyr%G^h>?h~{WpEcq(H=Gk^9sl72Rx|O940$Vs z{1o=#-0-h$-LsudFiF7PAj$}%l-Qdf7^Mi19G1PO~Ea15XoWXrJ29mOGna ztAY6-qHx%kR!@YRDgmr&YBxFt?fgPc%f761w(Q)uY9IClQGG&kZOL-jcbgI41n$b9 zqSd}E*f!*)D$x_T3WMaT5{0trL*sCO+Q3!0VMcAr+r!irQ3?D@jF6U*iWSmktVBpl zCD`{jR!LY~2Pz4O>u4n}tR-=BJ6eYt8$Ijv*d+8;RDw%mB6Cjd-_^2H-bqy&8)!g< z&^EK~$mRj&Ys}`Hep&%Njj=0mdP_xOhvPQf?!J?z+l?}JX0@!vT*Vp;@3&K)MLV5m z!6an6ZMN7+Oyc8K$j?Z{&**)17JvG<5%kl?1wFh{UW)znIRpyshySnBvXXBpJs|Mc`{59$o65X!>UEmUBb?gA?)$MKWSnA3kdE}DB5D5 zPLTKVxQK~g6r1TI25296K6`g zCCPczW_$@m9X>kj*bcBKoDtnR8F1DP%`__BvlIdu-KUkSswVWAxC0msEIZ|<#IV0tRbb{y^H_yaCCJu17gtL_#D{AMiFkTy_bs4Hu;|d~w{5K)A|tK; zL!-@!6Z1x|GvAmBsJLi@s8?ERnI^RF1CzxyD59!2jfzY=y;-LNy|oLBLKbt{iK;|P ze!F|0%X~oIu&fuO1hnw;*%q1O>&i!+sKVwDv6Q+*LExbIY{V(CEq9`-FrDPV^*e)K0E46C6vfN}#Q*? ze_FK%e{kr4S7c+XHu{G{8~s=_nJEq|C%VzE52K0dvX*0zk9GPeK-{QvHGmsZv);Dq z?f-Oi`yXrSGqp$fGhqRQ0k|b}*7oQN&IgI-XtO#A0|CSnHHHM;c%v1ViO~uq6On`# zl=lTN0Z6GTS2GYnE)Ky&asX2R6)}*^A_FP=Hq;(b6eQP<=i@c~Dg;z(dRJ{D7`j#oGcZ6;c>m1=N-QK1hF@BkM0WfeV0JA+%K!Xkdc=$F8VJ3xwCmON(%X1pTJQ9!; z#{rD^B0AQ7^p*N&kJY^BS6*QN=A#t&<-oK|1TcHz0Zh60ltMJv$;(zF8^i1&53KZs zF-#dy2**(c)r^ukHjZJWL-Sw!{F$I9m{ zPxNGnbA+^2Te!le6Rx0YjaNj%LoWiyGkqW_4L*bgxm0f8L%<;+h*}mps0DRv*djO% zb+>fm@VFd?N~=2zT>^EdLzif?0V76vPB^>T*d}LU7c%?&S@fb{NTcXwm$9up91s&PBlIFiTvOC9`hJS~MRH`SUnEzu`bBOZ zJJm`fCBMSZ%TZLnKnX#_k&Rts0~WbFQtPG@t!$R`5YKUf%?ZGS)GwUe z2#;iyPmSZ3FEJk+XQPx%JUyWf;Zc2tYR&I&?ub()?Iba4lUb z{Caf54&c}dzT^1d=pf^1)d%5pLq!AhDu8~}v!Jl}cw)LR-)|Pg_{UZf0^ijJ;R1|< z7C5X3ofS=SjOU^cy-553W1TbJxH#^i2tv3VeLMNPS%2FOP*D90`d*RbY^{5G@WAC1D$d4?Sx9#Rabm= z)WH_o=%NAc>Vu0B8IJC}aN4vy-LK%F9;L}UWB!kQ! zGt+`s0+iVz?+6qWEu}8$1{$~Z&F=h4;#UkFc6v2gsiLMP*r_&F?fSeXjdj| zkvxeUSgkS~mdNhzlWC%qX3-@Y<-;XVlc^*_Oq4o*xoSse>*|ydrjCSib0sP?YoUa% zyqtFm22Wv^DLS>turWmWy9qv3Lgw>E#Kpv>1Dz81H8m=oWP16_`$i~yg=wB(@)})# zH$Q?l-2~&=9T7D06g+}uCr0ZLiusih-+d49ClHHv5<1k7)>SHqf)mzawNkpC`e=(B zyOnyL@!g0H6@hik8Qi8->sIYf^&7e)0$v`clQUfl40yp&AxNeluswidu#h~1D%43` zxFfFOv7vpj$NkQ^qj)4xMJi7QDr!vwOIn=NG~5Tk)7A&>BfiLOqk$NgHej%ET!J@c z5wSoluU9CEM=pq=%n@N8u4q~{xij9=lKn>B(jdYCdy;@CJR+soS2DtZ$qLOt;7uDK zZxNm*+a`1(Z$*G%;|gs!Gwwob1jsU7oM*9?)5gV`0Dua6Kv_GJBKAsh8|Q?P@b(@7 zNyPAR5DDJnYz4xXD)2+30-C|nH5kII3j;N4JQO(Ag!VeEfEFC{rq;Ck(tW0ME7w6NqKOw@t)g|Sh)8b&WAJXGp2eN;$;kX>81R552^?7q8x0=Co*)tXq5%gTYlLQCsR*QfUB zHmowZ7FmRD=6Wr-** z9`%!4kNlQI9sC$K*wb>R#J3~I?*|IEC=e>40{PH>y<`Wwe~fj?kc7V|a;5kEJliIX z!s?^*bR-=XMjsVOD10C^;V^>BOK3vCedTj!6qhVo2Pmu~`l<<1_&^%!FKiJ=4=AcC zs-vFzAcAabub^S6FL<<8e3N)IBQ@*^A$@w>52yF~+ZtF{!@UoF0tvE&3@>rc^eiU12Z_steh z5lOA28~T8NU9#B{WtT8pG;jT|JAwJohGQbI{Camd$gO>vMnMtmDzf6iPR6>GSVV4c z#iYjhfrl)(wp%4k7)(hmrh!M;4k&+=-ylOP0y^5GlYC0)xl}>apO#1K^!D2k`P6!whKM4`56-CE5KTk4 zEabHyeg>mal2uq|F^5%4P`=X={Nl5cK|Mm_xPw6sBYZh#T-Y}MJ(+M0#4r3ki`PoB z?=yM_TD<)b8D93(6c7YrSbvN1oOhygsgG)hnGHNNH6IAyECJ>GifmClr~HF6>}oT5S~6%Y9^oUEu;Al;(+wLa!ztwvRfX%u2ppH;7)06l5gB)D4TRv57 zcejg=ct{3$xwZl`1_$^P5#MlkL+KuL=kl`2;iM)4y*Qprd6>Wv|ByeTxz6sp8eSt& zgS+`{ ztMJ$C-Z9ls@duggEyFewiLx$}@aM@R_f@~f>av5IG~w=RnlX@bk4#C>+nxMshmhdk z>~L(@+H-ZYH~k_RhC9?-wYQcmkypc{M_vnM+3~jx1z#M{^BvGnw#AlSe$|`a_Kvr` zsd~A6i`GCSHNo~e=Up0_kq88<+1UiD znEi&`8y*jfPdn-s=a@Q&`ThxaHq$k``IuW#X=8Rc!WQ4QWif6fA4E9bYey0Z);QBW zw`oJ=lL@O$V~iz7u#+SO`nZX5nAED7mFCB!vf)FSNu}8rrDdOJBAN2_MP({a+2zSE zO{Sa3*kF^o^sBnz1E{IxZDz7_5+RHq88SY|3yMeIgY+_3^P_R& zDUzEK_2{4?{{?|#VW4O7Y7z-Wc{R~P-VI#5QjD`Fq6TV?u<;XLZ-TDreOt!)rZoO& zv#(Dll5TexdxmsG2731fpYPH`qJq@!Xbb4QqnFPKyVGwRhaDTpWO2%^kLFql9z)Hp z=Wv}|T;6NAO!Q^W7GhOb66}z0>4oHlg=;ECsvfoN)yq*#R%TW8ziZ*!$=~rSh&hvw4Ct8AbbO3 zA0KW<__&S9-~hv7U=Qt-&HT_tCYlK`OKn?rgBV+>HF!5gA^o}))GN`89#7>^Zi)!t zD#bhrwq>efpRK`r-oaPaTO&TOl2xmkIa?`_1MzTUQYAC#7;23TRL5qvQ|Bl}C z6YzI~PO9q^i_k9`HMfB*fw))b?x0)AM`kR_*Onn*kjoI9n+$Tva}zSgnRZe8<*!+_ zj~NBlUb+PUde0JpaQ`>BKU&y?&!{oJ){8fplW>_}kAJe>I?V5~^MpC2Bw_nZxsvOT z$5nkG80d^A9zRiRCpga>6fCj2$p`at-Id$H32n8%{xMC-`AqM>w6F@dM_*ziHy5S) zrhM*P{6|9t7B!qv2G2JN{d51U!>^@oRgozzp9?{)@pJ4DvorjvqNNpfyR^a*PGGVM z$+y**f!i01TX^gy?^N$fH;cAaK7bf6&pb4O;#x&G*L&&=-XzOU9=yh}TNfm+U1yrL zGzMOr)=U_re)UbuT{1YS`z{a<&V6Y^x7@|}c1ybuiNO$fN8ZHHS;@K=wo{hDJoM7l zl9E2G8!Zik7ZZKDES2Gxrm`|RB_k|^xh+10zP|~`e3&d1;Mb0_0$e5BN|h}Y3a|@i z044xn!~_cG9lTqU_`dO<7|FC!SS$iwi*12%Z}wF&Ki}}`MK5G)ake@TW;d?Cydg`0u9rpjBsEVSHic-*6gjqu)4a*r(t%( z-KORvD=wIiWa?lB)#L?B;pClCAk*n{)Nd3};_{+OSy_oO$qG9siYP?^C6-6WVo>0 zH>(fUnzi!5s{G{#3$3^mMevPE#^*F&+F-Lnnq+pRVvgyO3Z2+Mmr|KG`Kc@O4(f?r z*FGIIL?#U{I@z0(OnVHSWK^w?bR_E{Zj$66C^dJ}ZW=>qg``E7QdIgUeYU$%Co0Fqe2{Min$}b#%t=;=raa^LC2L#N;Cdfz9Me)0%5OVtEe9 z`N^#P)Ozhx)gNxS(QSzlS2x~}m-2My1{6<37pgq};XcUr-p_{#?N@qnZg+2B<98Yd zYM9G@K5{(1suyf1X)Gu!pnf4g zE9X>i7Y4P^8|cAgD_%+X(d|=ymIDjhvCzVNt3??iEQDCTcY*ybUyWzajz`00XTTX< zO&7B2YjBpF#zOmBvb?LDyd^QTunK!$e<|t%~ZxhCL>|Ub?b0S*I zHLdyEG+A{L%w`o@8{bB4+Z!j~ygGx^-fS|AOcF0zmfecdC~|ELc~5q;bhA8E-cN?x)=T zu~T+x8GCE>4pYqnkiXGTdjoEzq-ffZyp|93_7cyg1>^Mf`jmyJU})WRuN|l@Y(&vtmNX&!u9BDQO$T0?Q<*?|f8N33}>p(qL%CXH5K7BMj= zYY7bxyQVn=tr|v5KxA9%0yUCW4E%tRh{ zr#o0F+evMB%-efCCo}tC;%-*d?ChgNZPdhV!QNuXtT%Sb1+1-I?573XcDM<(@(m46 za?e?0F7Zjjx6;+eqC^#jhrL&Do}#@80L^STn!dOreK8;9J}GE?q^^Xyhav_!_@p7+ zmFDdDd0ZEst3eC_XSCT*<%<1SD@FWqjupbYK-aTKudTIq!LPh0>o57ME3Pg5A=T#u zX8tFxDyBg20avE#{89{uR>bI|Uz~^%u_W+8Am5=8%kHGvwFE|E7|xSEN5Po}ezqJk zZBBJdfXuMd5_w+n&@Di&h0p0b1Y9CPH7b|N7&jfsd@bBd&naCXi_6tZ*Sh_Ol94QY zw*{TXnBJF7m73)$q6HPYb}TMEv_Qlw9cD(T+4hxIIBJX@2x~ssq$cMn*b`rGmi!vs zCqT4=GZ%6evte<&TXE1d*K&t&^ehZ%o`I4>k`F@~s|WMFMws0ZC%p1~8Wz-cV2v&E zq$m^K-Zef)_Gt3?>H1u#r1X0&c1VCh2e>6EEaGDrz=3qWNI5}@(ugiY-E_i9@&NX|Oo^d<+$VI?5Vh(bhm z4@1%b2*9^G-b+gY=EUsNmNYqRZ?G`AmbUT0{Q7`}L{?iOcw=g=ClMGVAr6@) zz4$utfS2G84pZ3EBHY}u(_N9!+`kXagM^UsdOhK4lrh^vNeDfXV09w(sRZKYm|^SM zG}BeAeJZaOhZPu)g5D8pU-+vZkJUKrbx7KMuM{sNxQaJ_vK+v-&zU-5P4O*~V0CEw z&@wDzKUOf@?#QIIUQY(Ewgi$;sx_NuC)u!3Xql;y!+SOU3Y05F{eqQf8i{2H0BjF8n?F0&9EaH0z-{GS;tLLxrL3LxC9fEH~H*6kk-MG+R* z?gzP?W&$EZ;jh_b9nkiBCKCU>MQsz)5Vl092!{BWaLH8+!+^qFWqlpxVZ)Ry2it>^ z96*sbV#&EC!`eAA8DgN*V7h5UJK9CN;5hb!;JtEV32dpAIf}>rD3F-zV<_t)-Y+5O zo6c;F!(`Z@Ex7Fxr3X$~45WGGqM%xXT``>xcEyrQce4}2Y>6xkO=LMwnjx66RLSB> z;Zr2dSTw4?lrb_Aba66Kpf-LnG|6`g_pC8FoHzXKMW3twX0arlbqG_M?6*toC#aHG z9@~=Q42~=pnTgS^I@H!18IuiH|ECwN#&$U)={WsCHAkh&^yQ^1Y)fxs{z_MJ^~(CI z8QFLAmR|ei!P09_Wv=e+Exr2SVCmH}^;h4()&7R7Z|3S->aX5E zm~#bF;{My)>!0yg?(D6t`CjkLn&bR@PzTU$-uPH=dF$ZA{Qdp#?3E92ssGc);%_*T zar5lf(nd6FaO)t*vvFo?X$_j`F0&tRYk$Ou*!D&qAAF?u)L?nbZF7gq_lzC(#f0tV zgzb_wo7eRA!jdmnY~Cu)<&B$X*MOwq#`k+WHhb2Lf&Ps=v2~Dqt~Chc#r{VTQ9InV zYiw64!qxfnd@D$xxaraQv2t&c2lI@t%Hoe!MUwv-R#&r$o103JFLAVdJu0?a`{Js zsbP2q;{e}U@A8dXw{Et2Y~IMrT^oCQ)to(RU~Td{_?O;E%C}|OwPyD{TL!lr-ZeY8 zjDH6Q$L=|N_%`l2H2@!I!roxJbSd{YZl&^r zaO&uH-PCdTo-L;+^F3o*wj91^aPYQ!sKKtogM+&c@7l8Ep2KMk^aj4lR$4^;(4%hH zyp?8#AJ&~et$p+h*G-Ho`+?q08g(O9LZ$DfSTykocTxS}o^|C{>tZs|p@aznHlr5e zYb8Kmj`h|yOO3lI;5}m}27AU1Zy7{Y<_5bD-!?d?UML^lb;>tB>(wfB|JF5PFuSIE zGk=L?=Nj6WyjSDA25sC-Kj{WlU9->H{XlQ6zjJW&W`-rDM_qV@xm$m?uJsPiZI*)Q zl_g@Y7S_Aez^f4LWH@(}zn@nKe@R-&&rj^yZDsa{Hb7xB@q6 zZwBe$*0{v{Y45hx!i-9C(-66JkY#t2==;6L2G76kFaz_REz%GQ%jk3i^zfFWUO~`= zjhhFhhFd8k1!bSA+FNCpsymg==mq6egP;?%?8eRL_D1x=lqb~$r_1!VYwc7MtemJ- zKLc3B{2s;Zq6K#yo*nGib$H9%VCQZ3=#TQ@+oD2(1{7lX;MR>G!$!}wHdtG8c4$_i z_8P+vD~gl2b@QFxVAKZZ*7N{6RBJPKVl%B(UbAs-%`$(Dp5_U98BNdDWrg92L9J=d z3e##~jewEWJ;nuP>)C4Ry>SK;Ff&-*b=%z7iraug^kvJIU5Bk^V~6j#ZFX?UuEV#D zZ5g|5Ea>=5Zw>23Hc9_xVL5|I4DGKHT5e5N0+9{b>e|nbAzQ_bB8-`+j4lzEXJ<1 zh5EW%;Aw39@9ZtD`3}TN>>AEx5`^?KdEB`98@=^j0yk;bZ|jl4#=A@C9W2Gx&3pl3 z4X}Bn;r$Nmq72?cy96ysvYywx|9bv* z`|tho7U%o>mD~M)rE;lMTDC}wZLp{Vi#o8V1B*Jar~`{Su&4uzI=6!U5nda*B4U0>i-MSYoJ#{!_X#3ZJ@C*1WD(A4N{+o7D9gLe~rJm z{iWj{gnl2=7|_q(fusw%{(eaP|0B?kK`Wsr)BkFJwZY~7=WF>XS_AcYQv2xdUxZ!< z>DlK&(!u%4*7It=3n0mU0dys#G5C|vT1Ya2e8~>-U(fFls(m0Sl{4%8HPp97Domjr=FT9an|1>lPeGs}9`aNhHq&^oWhI?v% z)jLq&+wRYL`K#fjHrH5_zKue{9Fg!x*HoVO_}>?@{?cXX|0^KjzuH?Qd-O(Vz?1qz zV^V#wkn+|3S3#1ma%lYjCZxW8E3^TU9h6S|2K4LDLduu@QNK$Eu7Fg(b&%?<`l~JU z_nRTz`(-GM{~zUdjl*{PJv^uKUjRw>MFHnj$00~~r)zKbzlXoK@b_kDA?q*ss+ZbW zb-oUIA0%B9y%&-`UJLyJq=kD)f_(Fh1A-*`Yot;Q#CV@AH*^9`A|HhgL#*{{kq~zrybtd!jc$!u?-_ zBu_t8j@6Lv$uF9({4nmq&se_3^3OxBhF$?}gFXmp90+%%bH57-hd%^KFJ1!4_Fo7+ z9}0Zi{VDkuK^H*kf7M%UFTU@D-T}QG3b?1AqF;kHKzi=SA-$_Iv@16}7uR1ru7ra9 z7uE^$gm>zPtD&G1zs&E#3cVkAozBl#zA*odkmN}JKMZ{oQXibvgrq+~pTf_$3@_*Y zAoS~y^yY7%DNhIZ`Ts(nfj$lWEA(YZ{T|v=Wea@uQ}UXXV+GgiY1#J5_R7~P<+uOM z^uhAqY&d#h>5~0i`FQ2Tg>#je=de?qzaFTRe*f6P((iHi1%K6W_hhAG)x^MqmD1av zI9M_cch)`gmzDCs*xW>UYzUqcJtM0s72cSslt;!+gj)m0Dvr^&E9IB|%@YU9fBj;_ zU3Q?3)$Nszv5B#{f%4eMTxI#h(5iuIZkN_` zyF=VoQHBXh*0XA2C@I%;rDJ4b)gwunN;kvfW_Vm&&ttEuKXhC?W-Hwhi&J*PSFl8J zYZd;T=r$qzQW~1E3#FkGmC^y&-wFGRny??5SY_<3hyzIx;m@5Dm8C-?t5yvmxN=Tq zVq$1uNRLc#ZNzFdHZibjU}EHCrF0)M?t9|GMhWGSiDNXT+HGPiZOl`2(8Obv&JnIj z)Ql=LGF#~x8>v(VCRWW=I{0_Gu<&r0t;|kz(B-pE0i-O}^)Y)i!J2D;CX~35vDsBH zAAouDhDR;-R?0&#uMPB2wn}AUh(1esySC{V7(?+o;225hG6~ZYC9!X=8^&G*n5pzo z$Amjw<`@l344tf;L9265>>~EQ0*~kGG2ETz(UzY3$x3Yu-V-BK0+pPupy1SPtd_Ps zZPO!Bl@?O4N78)IjgFm zX=7Av)xg+sH}tQS=4XaJlKv9)Ri~obC_jq6incC|9HU?OrE5%0!_T1sL^$2=N=3|8 zN<*{mX~UksZp0o$Y_I%NW$9I0Zoc!rJ8yp1i%(qGdC|p}UiJkpCjey+>A}S-z_qmo zP4?1v-+bV{12_NHWw}jOfceHG7xV4zgEsWRl;)VvGhYnAKJ-N}zdQnjeOKCU$bow2 zVLY$in_~PID?J|L-Rq|Qf}Gr8`z0GccR5HGGM}ip!WKcveIBa2S4}W1CgwaYGZtjG z&~m#_9s}|O;U&hD!M)iHT`3Qt;f$?S5w0&C5=e>=-5lSkETRp?&jMN*q?L-t>$%EV z39f6T4lv3Xl!oOrpP+p?XqP-+t1OLBzc#Vl3_)6eX5eq)LFnVE{@ASbX#jOYv9S?Q z86NK9smMmy#qz*J*D8!nunA@(4AELv+S>(t9bf}<0^lzZ#$kt6MORM+<6+N9teL^Y zSe$Y=>ZIlxjQcVMgT_<0PET~xh-M~A;NFr|V_+e`CG&uVl2y?|MFMkmk-kk$h{>b; zz;Q4er!aO18yS1T3F7W4^hj2$Y1N7bjnjK?P>g}IpWcp4SGuvm$%kBVTp(WHp91^y0i3T1-q9q(+;{&@zR~%h8J!0m>wJ&(LmD_k z%qh-wcE;>OMTj$^GUXcyUX+h(FPfFmIH`b<_-}eK2i$pW1cPhyD&XCa89umcW39yL zy&9++0J>We0qHiXIApJSx7NVE~@w-udM+$X>SFxSg zapyBznU}{+T;v6#U=be8R@{r$sRK-_7D44X3k@orFJ1Gdx11PU`nHdL{;vD)`it#9 z(>Nh`pi;h~@91E8``yzAJMJF2qJHYKz4CRQc>U4A(#MY-Ebq7?6S2T8()|()O52HP zjMU%#d)ZJq2P0V1feB`M7Ty?H^{{3pkl5qBYm#YWg~rwfidt*#qnBrN({#6;o@43oEkt6GV%yzohx}N zJW&}zsq<&$*r^O-bE}q6C-Y&QYmMVMN=HeNVnx?v$WE5&<`Dil0do5e}!jD6w8G}qz|yg z>J!=+P&j4|`-@7>RnASES`7#3>5#gT7PoS^dM;B}`Uhc>z|4PbfSD8zod3$CE$vTv z9p<7-3jA2L{sqb$2CH3jKLzTM;w{>sG2gAF%?tk29)&C}rP5&)2Ig?fIg zz~Q|)F;3sAq;Fs@3OwGtck(^n+&6M(-{~8XHA+GzIF_r%Y7m*jMY}1j}3FU6=E!@HOcd!Z>~6NViV*{pkuDGY|OJWa5G2M%tdaf zN5u^0!ZT!+YQJG?0Bm1(i+&Tc9Wb+jJ!q>Nr*g-MRC+xR5DyTOlo?U|s&axXUdF zkpOd1h#}S|soxTV<%qXaRUgbmRf#Qh$~qeGF8cghI5ePND6oGTz!iT#SJyrwNS&!H zsc1x?2Ie?xDU&c0X0`xWbKYEn+dxEDo@qYB=DbT$EK)1SCKnj;-&NTQC;vsSV(sO; z<%AnPQkhOY65mGFa2n{mmJ5s$IWjW<WiBTbahpAi+flnb+)xq8(rIh zQV_p%i+A>}^^VqbTj`T~HCdd)1Zvq1f0HG&{P?FYv|cu&sr88&r;CJ<{{uppFLF*@ zS7SP>m%ffk zFOa915x}@3r^1grtHgqOp2&(vxn})dmJEYUgci&bMON$F3VSHy!~M`-Ny8=0qtDhr z4-`e8?TN2PVWGO{Gxu+>fZ4J97&On^Z}y;M*%g*i$HeJaQTUm6Yytf5qqMp3PV?Ab z`i2cI%a03hG!IdRH|8oU>SD%8B1Mk{kp~pdvRny+gju49E?a_?csVo#+_K3O*+@Y1 zxN|D~%xu(H7S`p+@ta>Yu2@Hm(PNCC8i|LBhH9QyUYO#^C6}Gmhb?YcKWpGgAa`!S_ ztP$KnY=lDCsFrK#@+`~<`b@t~?FXn%sa2&3J&U<( zdC`*e(MRE|=W?eXCOQ}&mfZvh&eU|`2eb6qsnJy&at`7&@9!CK>yoTiijmK|7QCZx z$!cZOkcqJ|*Vs^l+=o>zMe-z`y3j?|A0pf-k0K$|iG9|68F(C(q-I zx#yW}7sHvo@@V>WF{pU~mfPX-$-p%WRfA;n!nF)1bCqiowaR((1~$*f#*6cb7m56 z(yl0_CbWTVA17Y#`I!5bR?0B4eQ?_@_w0ez$i{OcV;^7u#xB)ZrORA1hE(G%=b62~ z?v-bX7uE>mt>Dc7>dC=dkze*H0o&J!A{5zYd+0FJ_tLLBAww6Ostff#uU~2 z2_TeqVQAVkpcS@eOI>t=u_l?xL7SWuemmx7+N-EB)1>s4?X76x#Ce7`H)0pc5YyA6 zF*~~vb|~WLwesguelry!;IIRrk{P)xB0Oi(9gD5qyObxP1Xo647wK#|;R-(LwmE7p z->aoQg?%Q$V6Xre=G0~1pym(;2MhyR>;bB<;AG8(dGG<%{VQyfL6{SxR1@d;G_Iuk z&C6tVOeDF;FZ>kP8I;m#t;}pPA9g8PL1!H}`~0nf^Z*;(ZFq>!T>NW9#CEPc<*140 zjrKjEfNb+cU3%_|=$Ez(q3~l5$v1q+zf_E-_8Mz>LOH$0Ka$0SuLZt-vC=ugY6Muo z!phkF;jI>MtGC#@%3C8t+IW-X1t;-V@^FM_kg|PUyl0kVCj(;(**$q=wo*uZm!{tQ zd_fX(&3KwB2B9j_e`N`%>$8($BrlvUgnto7X#nx0?Ti7BK0a$6YEoHRirAKK4p7ZY zC$OdH;b{TAiLHzQ7EmM>+(}ZFi5)1U283Frn~I&UL2z=3!eT#>tA15{Hpv%@gwxIn z2AJ&SNrOL0U7Mv3>c#Ul`!o~g1o0^khGN*!6@`x~<*HH^9iauC35!-0&q_;yV5OLxEgTpd7z*S6$=kSF46BZ`6AKBC z)?0!3UVr9V%%|M;ZLd6H{q<;p?Yk$keGkj_k;yW2a-sy1*d79Rjl zFS3ee!dp&c?x~y;TS39H7O*7G&@cGo$u%XN*|tbu>#@p-%9$x>_%+JhVD&u)!io74 z5T~;Rzseb3LYf^C!Iep`H4&Xmyu#B&I*aF8 z_e7@6jEXI-+nnpU7K~CAEa~22@n-Jox^=EXdVa8nzQ*muud}5&P+DmNOsFS?$ey8S#UaI%6`bMv@%xK90lPmyPum)$=#2dshY0Xi53G7 z<(Vv=B#vq^rZMv~!yDhpw^6)vQ)PKLT}qlY&5koOR8p+({A;Ci zG!+nwp3<<)4TV`bDI8WooAEF=CmhJsnUUy`g2l|hjp=~P$$(oL{r4dyYYd)9&I!p~ z){NMN+#8Z%RA0km5^0@{Q}-DTM!O+%bH+dElSX_72fdPVtScc9XW@XNc}Y}8Lr!=2 zQ$XGnr$eoIh*?en9M?0%F;P~z4t#PwO?M7iKH(CBW~;l+eOj#;WI3by+MU?VDNl)3 znid-F8duBaX^EwqFD)?hd)gW1c#SER7*G|%udxqcXb1Lz=ko4tKu5esN?=<+zD%NEu0hN2rj2CJ zG9jpX_O>yfoWZs>E!K0NuB=F1=%Uhxw7(*yZDgJ}$trYyt1AVt7_1vvuSgwXc+Zd; zt2GJ(@7l!kYz4z3c{YhJce%nwf-9%l7;AfZy-D1M6%1gz+X=}Ig2kU8pNh z1B^eS<#}@AnlD{Yw;SE|F=6q<47kb<@(_k5NTw@5@*9Cv9hpNiDe)bq)q0UQy1keW zb1`Fg1A=qLg^PwV4QD-f#BaiNvvPKiJO8)^Uhl5QYX#o}-@3ix z8hy5nxRoQkJBDVn0UQOSrqPU2j(f6U-2UoTLQF9l8^?ggr*QJUKL{XacZ=&tIr;Mi zu@JgB!;T2Q&T}CMq4L>A@nrwGKdPx6cR0h-av3pCxy7Wn+wq7qOkGRb$tGz_hR(8< zM3q|l#Puw-q7`>|v{O9o@D|I!^-XGeZOa9Q&(hClhw}`)eo9;0^N1OYLlZ|@jn6_SK)EFVwxhG zO*cDi`^RSudj*IJM{rK+3}f4V?_|+M!v!6Gyby?uJ@{M4-q4x(B&czY20Q!BZ4Ji` zoYFayi~x63wiT&1mK#<_Pxe|^9V}`P;;@`Dn}4l=sneu8`Ii7m&3U9lxlwn|nzH4v z7NR@Wg1C{fV?tT^j&A6;3HW8-9|e4yJWf7d0CqM#gBNmKl~o1PdZ)w$@J>6c*}mU4UG#OR9w=P=HS6Ui7n) zC~!zxIO}_PhYoZxmGoF`Uv5rSbZ63Qddr+CoE}967VRouiD)6afY{%LvbPa#F>%(; zn(?gyAGFoq`hmm=dWpWLn&FtJQ$h}ZWE4Gxzd}&3J!=C%7N(`sw9j1Y@B?X6zA_)1 zf>UnRWsI#chYM|qv7M(ai9Wg@_W7>=SLS6zY+}CZA#u!|ABf{=*be-&*~(G}(?DwH z1V~2AnSU`cZAa6;a(YI^#qksQGw01*G zUlID-#A{ymtC?(UAQ`68Hqv}stm|5XJG;}aS;IoxM+$f?B1ez4BrE?=4i)YJ`GbYOD(d5-o6dBJ?&O@&eAtKdZutx5f6)cv|cQ^YrbZa z(dj!ShxNlDd{0u`^u+$9r#8Wt}|)h3hk z;+$QLi8f|>CbxY9mjVb!5~mg}48p}ZU%JB(C0e+d>uDRcr59fMs@J~$wXeF=eO1qj z)R@OqzVvl7uP?vuQv32A&-|gj-!MVKM`LiY^s4FCmtGYf{MUKfI3H^Ko{#i_&ornj zLfghtpE)FiW{yTiMVx%nvzbZ(@2w`1_43;{pU1T)#OBC#@)Z;fM;)mQ`dm~|%0g6x zdD>Gpn9>BM5YZsfbdI9gnMP4N6wE8LC76eKRRMg`+!C{^m{`*R0*{ITm&Rg67|5Go zHpsW==se=72%8&t7E|21`K2$5zCxfyTkRXJO+439CJ3ywOqa-(t9^5f-ubYr4n9k^ z%Y?@905QaOh}^Flv~5g4lj0QR$3+kMY1!fxGq3r!I%=S=H9ILJy5DG{Pb7E$-mv-h zCdN5^=6IAJ$C465mz6MCk)eB=+T8d}Rz>RaA@+DhuuuWZU@<|;H_-;*-m&c7I@(vVEwDq}k#|Ll& zQZ_j|Dk@V>lAllQi*o!Zjy{O!i-Vt*Bw!xpih0`ADv%a&X%1bFsisgS{ z(^;lW@n>;XctcIwSOKFFQF`jlRsKbnP|wEXtNH?&)wQn#yXx|<#qurVD9QblABH)+g-;NY-h( zxEejW%-eL?!BZ7%ann=4q8AbqenL+-Jq0ZLG>L7PY)pqOFV)gT&329f%d+xc7?#bH z7f`F5FFTX$LUl&6mDRhE~ae6+mXPer8jU$kLn%)v&_?w1%0Kq##$No{P*pwVxQG0c>3^ zY89NRrt!)g9wTEGy-asswmJ$dhtB{rC(UF1N;pVYc*tSG<%bZyvO%&CY0O6F!qxil zUbx;YIG7J=Q3SE+>?OM2WcHHWjm{XahqmOIoj_ZBws;eVBzksvif#TV@_KhFdf0F+ z9C2djmeH3gq^C>7$DYH@Rwyxd98fXySdiM6b+By!72SAGq(p&A)Zo zi3>X~y7(ob@1!$7O9E>22&EEqPI=%#-UmhJ!f2(x4gV~QM zh{M<;7507Ds)x<-ic{haIyeeQcu2DcH|etXazWAFOFwvxemM*K~M zB_Uw56o*jOV}kj62ZKKv-tzGod4b6uC7U+V^2zE&xRA=l^Yv#bwwVEEEkB)X>kMI`W@3-IC5s?b zrbSVeva2x~Lo!&~*>BC|HmxovSF%oFVpqsVPppR;+Eth%HrvX4i>1Pl41HU7a2>3< zgi|uCB+V?jey(l?N=p*8u~O2%yrlxVN8-2-|Z`I+}8R9%XGUgwz-&=G$&XBFi4COxH&icLAiK~A<_{t}ePI{(X`KROq z%+0?jN6{ zpe&3%#QvSYzWFC*!sF<$-U(|0f@H=o!%L$$F>)>hr^N$o+o}fp)%-(2LBw3;*$kje zNP|!Zps_-Mj%2j2Ok*C2IV13(h$cq_H~kFIm1@rAiFGo#N)7}|@~!PMxlMSV_N$qa zIMko}@prTa@mQ#gX5~n5m1sMM8t6B3Fbpk{uzl`_=8d@_Ag|6;p5-}f zlc+^Yv^_L%j^ZXf9PJowt_vB~QK?mQ{?9Kp%<&*-^MY^3r_5bUC0J&3L*I)>|6GHs zb)qK%hTZ zHxbl!p&6Vefwwv{)%R#d=R(UYh2?+n9qu2~fI9AaE(M+DUw!BC8~y$+^0g}rm}q+` zH~-jw`W=7H!+Nu4P!fG&(gFKi1Cu%ghwU@vN~`FNRkdJ(WA}5TH+GjCP89c_^LCx` z%x=HwXJplPP#Zn{FU^*eoI&OJKa)>s^A^I9BLfd7FEuQSMXxYjL8m9;r<>1NOn{AI zwm?oS(ZN-~6lGVJ+vjXqv^s=cMg`Jck}k5to>wXFMH@w3;r!^1p@rC5q$Nnvcdmt0sEnv$`1x zP~Aq92Y!E=xb_h@W^jCutFj9CpuDZ}kdj{fli;pLtgK*5R4~4tO5@RU1qnqNR_1{R zR<40)v@@;Im@r=Iml*8n`X6J1^{{Dho+KZ+yEL~)I zs5JLC6WDZ~?Gx^^i32(frMX^5qxJTv)#7 z@{|{F`*2z((t2`}U~jDSTz<(#7hZJ9<(x3^oDvoLXANRvOZZtj{Q?gc$dq3(TRAK7 zFM^jXurq`TFFfgN*bgVgaDeT~;m;SxiEzQ6#EX(QXy?R?xozMJnF z>&&t2ms}dfoB3qf&bLmsgiwekyZyZ>4nA!PTX!_^dN;#|om=aU%+^Zl9<5BTE?>KE?qK&Uvwx+Aqm zE2mcXTzhcewb$OT?{KD7zMv;ZVSQx(I+eOy8-3I+eK+M-^ZdT&xt>~GzUAOoJsaG& zU3#&be=C*!bG6bgvgFp)D*J0S`@5SWP#A2MzuAc(`*p9io0Y&SSK$UF=U*!V*OEtF zg=&=*RHn9{w&dASm~`%{R7PiOOO8l{l|!YW3#|Go=)RM#dAn~}z50fO8)jE`^Y7}_ zx6BQPOR>}WgpFda83$&?dod}ZkSt54L8grwOFPKRQ4Yc&91ZR zz?XUbF4_%6Gxk)fhi0Z0+$rxr;%aecr8bHJ_?{q=y{oqCB-c<*ioJjCNY|))qetvv z)FBxR6RQQB?7G#0QmBp4ul+T;qPG8$%8AvTs>8|EXQ>J*{c5YrzS#}b;M!0FCfsTy zdv&_zB+fX^rCzS|#3mXF&p<$)H8jv;8o+?xRoOMSze`04#j|1`DJnL4D*4ANwIdH# zj;&sDgNl0XK0v0lZ*KKc>5dfXmg$3~sMKem8~m?kr{$2x3A|{(FLBfM-lt+lB_@1* zWItxPuCRq|EdKm|g2H~ka&+~wgSRkFZ_p5>tYFKE!|{f*inJRzQPWY>PGTRu|z9wqIf4fowLySlb- zc6H~$8}{8|ihS*{w4D0^6E^D{sqI>~4uE!jc>aF=+U48T;Kn0L+P}LFc#Bd#GCH@e z2h68pyGZ&scqxzWnp?NbUj&nQ#F>X|v)3xiBb;%K!5W3Gxn}CzMe(=-Ybp7z+0hav z1I(l**Dl`&O5Os%Y`Ep1>URrZGrPKHA3d|-+I<0XDAH){2vd|@v$bw?-ufK_Q0qD3 zR6RxgOyTy23YLz{@+>+B5_|-3Q*3K>v;#uBBd#TPjn!VfJ7t!O;Vl|2wS%fRlApj#eqz z&l&!HP-hA5sF4>W=N3}F>i=434YV3kyNlEgzXrV% zlFsX=`apg1WaY>GFFjCQrGKLLLmz^q`~L-!yzp~7zw6#*(2qbr4*eMPWcpw2FTEGf z7el`Qy$(`as7?Aj>2F>CMM%${52+0Em96L1eiuNJt@^(NszN^r1sRfCFaPyi6RFRh z3#slu3eC3+v3!-`QcvQmet#RZ77AlP`mb^Dc4z~n_vb4!em<73`fL122Q>aa2&s?N z=c4yQ?}Ie%bzP)>QricLdAIX>z5G|hOJhJ|>-Qnayatl)Ne_Pyx)yp5q6&N&dK0AfknZVk)m?26`v1rHeIfK;Hvc!Ew?c1+-T_I^RbTxceo7yH9a_lxYy7Eg zRfb=Jq+`-`>7n#qx~FUU`yRfB7Fj5B(hUY3No+a{enc?tlIv zKmQ#1@6bZZR~fE=g#WSwvM<8;V2AXx4_X5WqeSzSe;)6MWV7Tm>HQ0!P=Ad(l|dw| zkseCU>mbS3?vSG|OH z!arfZ+FJS`Tdcki77GLQe#~#azsK@l3a{W-{2af30Ftf?gU)I~(x0GD;b$!Wr@5~> zsLfsj{Uvl4bO8DS^gp1_KpJOryE2)lbQ5R*n^1ucu|(tJ|wztCoM` z?&(A2yWes2lG0`Sx$^PqiA(0HGb@=h^49~^()*4bD!rGxFZ!#7yChWbE;aN9Omu5QLc^l9jh9r2dm{*-2DWF zxdL%7IZ(&zj_P^qCnrbOuOBvMlk5A|k4}zOtDf6*b!p$^-KttW zx4o2Xa{NTKWBp{`T(z5*Qby&;@rOf+N}q+pXW;O{CLDMx;Q*h&;Z(K5?v#hAdTIS! z_3Ucj_~azT=CXe2o2_=cD<`U@yAW{K6PGlyuZwY*T!{?n(6NPlhx9f;r``j+{=@r$E(ZNtHnkqha>jfc&yr~OSN&U2^Hw+o1_Cr z$7ieM(Q&xumYJ95s#JNhbKG}0Z-)+7uLs`rKYtES&Q!Z4YI1b8kH28uyuB;it9z^E zahRXcw|@P&m{0aiN1W9twD;^}2i#KTR*#e7+guYI-%%8@XEZQX=gl}C9W?RD>KWrG z8)eLJcEuikJYQ#xH(EA26Ep9d9G+FTuBUD3r)m958+CErwRqYnqmz&2jV*ZJQSBU_ zWIU~}jn_<1PF9yNAk>|sC#%n9tY|P$DJjGHaj`!`y3#i+J)Eg7*A+^@I2s;4?#B6h z8pb(-ZfBg*us!2EPphA(cEgSLXmE|+6^ucr)uR&Oe>V~I1HIojI>*3Ye=Hwr5VF1c zPt~O_|1Y1p>&th2=G|8uzog@Zm%Zc*F#^~#dM*K|ANnh_*eibLv$WV}xBg^aixmL8 zwO=m4+g%WO6p+jTcpkae13dkEFXP@2{#f<9)!JyyK}9a2^YWLfOA|!Dx4MKeVUT`2 zem{TQ-e=?IE)S6oajm>XAi_%q&1VjeR>x&M91MeN0jtqX-(&m|ArGyO84MRsdF7F{@Xw(@sd>Oyq%w0&#C^_0EcGTrub-Th{Qgn@5xj5>Dm^sRoQ#3+M$FU!& zsL{z_F|ZqI6fvB)oURmEn0uXt>6V2tcTOhbEV+4ZjLEPtD$C=zYQda1(dI*%dGV6Xs)UVq^|2_1HeYaP{)8wsOS@u@Bif=WhN4o)BHIQYje z%fuoK+rC~czw84?KT*2l*rD>RFT1m0qVV-<>9@Ik8=;Du>hJzei|+I(6Xkf4KW#<}Ww@=Ux(+Xp;`xWr1Hk(t*_ zbaI@3?Qi$s$?6lID18O#Uul$HT7QCI%E{_7`4%R0a`=SM#jr$ihi;I@IkUr)K!nEa z691$ehjA`?fA?ssdJfO5m(R=GKb3Z@`fSST3a@Ygkm#LQ6GsX9dZ?1>X3}Tz3FWv@ zHSnhWE}flRn$+-#>T>!?4%e{e-gKOIVI^Z`a?ZK0UYteOy6gcuvZdZV2W?mJLTtme z>EntLSg?ntBP?R#T?Nq-v@59{;^=GcV|Jr4a&=?Z$=Aj$7GL^juDVRs@jYYmOgFea z?fh9M0?)lp96lfKQ@55Q+0`wLe7L&drT2|nh!7J}8!sV&F7-Ywp)hpR9N8WsB2hP< zK{xuxP86a{Km#XT18lrczN?dtJEM6B?mX==I?G?)r9A_!(o~cmJq(LTa+fKPJw`0> zWm{7Syr}^KCk@0NB979zW{Uyp|MmX?sQ>V{ldrD_)JZD;ZSx0XZ*X_D)~5m7>`o_j zS^r?eD+}jRic?&e|7gxny^9N8$*US2|M!CU$}N#)`c^f075tEg%stFSQArbHA?pH1piaL)gsWZcRj%2-C9)3Q z9<<-Cvy)vBTR|swEwEL5BZ2%}FFZ8pIdzbqSJvTU0oV)XQ-NuU>ja3RlBz*zfTTSY zq;T-ve7y*FDzJ3rOyN5zC%{?P?G}d!@Lc5AXL+aKEZ#0qJ#6Ya>ebZ(4YqLQaC*`8 zUwGI5sg7Uc^yli@A9!dr^<~tas&+|x*Uu=<#M(xI<~P2&!d_JXdzh6LEPd`!Y<$UA6uO3$uh!b6DJ1Y57UJZvyG7|q z7Qk#Rz3CcT=pen0*>MYOxQNom(Y`1CBbLryV`kV%jIAMK?~?Erjoi4GdYQSu~5Ea%9={R zn{XzrwSb;vD!}>!-VOcnWF5;?gwqqSDqt4-`hF?UAqN$BVdsgMySt ztGS_R9{C5e5T(8(y8kXb&Qf1`Qe zGQ3eAN@n!9ObR(KZp|c_`MYt;pE3}N&L&A0QP9ArU2xMSV&I!L4@svbI5Qheo~y1* zA_iJc!Let1}S_sT;2r@I9Jn7Qfv@XY_*k+U# zq^(P@IO!7YWU@ngMKSiLf3P{YtI)}-jmL9vUJClqHA0i4Fe5puF%5d?H=HcpQ@}93Mrg0CcFXq6h zZzkiyYMMT1VxO(ajs>t4ziu6|rT`9JI_0mKe$G~xs|3LWrK{K)k1mhT4WQ|&l^{Gw z&Se@$(SuRoq&RX-AwDPf^{Xud*Y3&5;jd=H&|LltW@?1-8R&h@ZW@v>sXx^4VqKIO zR?n0xPyGZZH?~46{*k#)T1x#!{+v7W980c~59ftVq9-5I8YvIvPC}gM#OBOZ&$87Q zpREVv&rWtSIEd+$@&YC%?kpK8MiT?j7ARM`MVydh%|f46Gz+86#>c#G1CCB{ur%Wc z?uUurDk_>2Vvbk{?kvs3(l#{O48ApRS)H*p#)3w1#V{VKSUr!KRzc);3W9wH4+^3z z5fhm?YmoYqFiR;45*v%qHzDSq@bKZD;kiE2eAIEd0b%3gogD))Fg{^p;oxptm1`OM zb&Sx4qpdQSdGcc#7voPf;Lyi3=Xku~@(&ysStf=`J^!V=7Jy}(pIk&nuIc2zL9>{NrK8m| zX$Q?ROcLiXDoJZJGZw?M>zBK9Rp;@Uk100u0<@c$a-Ev&B-=-wV;YlGYMzj`T`t)J z#XB+>F+4Uo{DFA9bMeDW@XQ-4Pxdw5bJM!~gNOfHr&U$w6C@ zFZO9ewXZ8;khi2o3EWcz2qvNCD=f)VM+99wmg{afW=iG}Qn8?MhWiE3!Jc-rID>7i zS(;O@y&-e9m1E{upQ`?N>Y0Tt5Y;g22hVDKH6@@0=glYBw(`~j^O|4!$89^BdRe;a z-8V9!ik-H=iQ&PF5y%E&B39{T4f2-mTb7&rx5;5`ej}a8r3PTFOptEbN@hp`YtfVJ z`-loia3Y;M+k`N=sl~q5&RtT@5X7JXiETy`=wzDdeJ!HiExbMB2|hkQ-7=GIEl4N8 z>nG3l>091km!uv)2QKmgKW(77R8wrPtY_ITh%+-gN?(^oQP$)M#XRUWpT1R)7GMLL z!C$nk&7NroM1FXld8*+OXL}T9y9hJc*2b#LbhSou>_hm254l&0A@tsACoi#rryuES zPqe^Pdu>$dx}yxn`(1dq1;F0RbZwHs&KznI4@erR2`zqD5=kXwrTOOQsQdsup)ncu z@%k5@6cSq*03sq^>@wBQivs{hz9qhh(B9H~2`ps`u`IlB+KBB6LFKDTl~ml-JSLl9 zF9%s9QSu4R8sfzAeYjLWF&}8Zx4L4z@{EN?0^)?tOqwh_3Qt4*9C<0~wuS#rWR>75 zIo{UP5%$MoWw&GlVzJiOr*A0k)edvb7OHAZMHpin5es*9c76Pur0wIUgPD>&Y|o;w zGi<#gB$K23t9VDomdvEd;MT?3P6Ia2YLeu-KJz%@)i7Z!d^zg2W8 z(r-lKi}dx80^}7heg3rVQz!)8>I)I2BTSS;V`18N%aF#*E#fmOI== zfWtpnZ>;8bS#L)nglCY6e5y^`_Ua?*sYeQe9Df&?wuiAf9N#fMJz2v3Ji%X#pV9G0 z3ug*{moam)Zr~?u=Cosi9akAf`BMpFlbF4uZc5>tL94@~1@nu)t2cj3P06M37TwkS zH(5taETZ!@6+~t4x0_*mqiLZL4dhm{4-;$ve1+M(C_sz}Q$X0br1K6O0WIKgh=i&p z+3b{AsTHhX`W%2DyVc~x$(E^O#nJ(B3T7VF6oN=2%&s+qV8H4`^~?maiV~X{aet>| zgviPX`n^pPz#4`|S1g4#tt1BHghNb&M{3t9LhayGiTLc(0?_O|i>6gTK}#^{V;z{P1Tet4mIF_tURs64Tg6IHWJE{?Sl zr_vjl=%GTZVJze15~Ud$%2=#gqgP-aJpriXtV9|w8<)21m~hGfrrl4D_aN+2(0VB^ zRWvmy0rKs>Aw>%uPfKQVKRdE1W#^FF`rp8;B|O)$10k8=IiT~%tTqd!YXQ0`Gpk8- zDpQKI%QahY@GHR8j?-3vnqf;}+z=5e2L0nK9uKVIX*(NQLM2>V<_g*~&kTrLs9HSL zP`SNIthacZ;HL;;+SyCr!WEx$&lm3z{8W10l6I=gg-_ngaoXwnPuW_6<(T(9ER;ME zWaW?a&u4Jb?7vG!2qCK;w{bmn-GeuubqQL5=jW^B0fzJpw^^D&8Ycs~Re;D*U%!&T zl+Mme2cyPfD@^^oN6ZzVrHx!WLN5tD;U^<_w%R4G<0bsE415$q?B^Y@xSdGqQ4TjT zyfs%W;mSPUbFI(b%LQD|*)J%{Sf$Gc0ArT5WoERuwXlxwbaoA)fwKqZcJ>$6adt=> zGV!wQ5w&s~yA10XQ{>d672jp4FKim36Z5==SPou0@Z2aP^<8a0RO0kHZI=$pL&&Di z75KG_U>(PZ+BQp1Jy;XH7$41zz);YS1J<_5a1PL&0YLrfMFn9OdyBBMo#;sLl(2s0 z#eBs6xFI%(B!|t4mK#_>$nJWq#^Z52jnPfFn>%ceRepin+uaJ7ch>_m@mb}KXh@On zu+k@J`#*iYYby-i?J?MG-8QST9M8{jt=q|+WMLOV@9r3Seg9Z21%E8w#|^yO?(4#c zhP9>nh<03w((v)(U2uj4n}{KQ(L36{)!NPVMYNMUV#m*Hu#8hEzj>w2ES zF3`{87)|4u-M_6V16tJD;cei^d@Swmc>8ve-rR=2TgMf}RE*z1GkeT{j_x4=1&QrB zysGi&k>XWax^p{yh7UhhhdMe`Y;=8>^7n<;I<fbR!ZKP)>%ly+uNJkVk7Uco|(ZvgNM1I&`VC9C`pFc8(K{n~S{Y zNT(X(x^+enLKY(|PkU~-wR%x7dV78{5bqwEpG^U7WKlS_;gO=8OJi)ALNU&_wkFfj zcMc>V-;5lR?ze45Sb?47P%s$g+Kxk~XFG^pDFf7iNT+UhF#2^kVJ%&wZ5bIqbb4kb z7Of)+JNpbdo~^>9OJA)ljuSp#i$j8cRB@SD;6mtyiPAI$h{18EB>4gNL#Jtsyy)OQ zFwc}NL9$BGcEl)1pO=|xBAV}V0G%?+?M0MK?&%mWTYyPN(;ObVj=9~Bw1D3d~BQKrLiV*%=jA)tpdFm#2PyK}J3Fq4uoA#xmxqIR|>=nn9B} ze=`_^37N?_6ZQ7DrZyLUO;{C z$BLUbxs2qyDC9gMoqXWLBA#yg8m5;P)k_Ls-}P%X$80D>+vfB*kvtuUuO`SAfOu)h zXiymn=bBmh^E0g$h}FtdeE|qE`dnab%5?2eH0x|A#5^pmiw0ZvUYK*vc$GjIG!`Ol z$WMvL7GeH|cZN;2KI&RG|8z=0llat%m9|QvZ$4P$rBxn9wqWxy%PuzScEKd`(WEqn z6?`~|{A0H#nW5Xx3^gfFLHIU$#+$#zD`sYMO?K2iP4~Y?_Zv<1iRA9z3-SK4iHS}h z0Upx?Ig*Y?S?JTzt2$V(ndOb&)S`xcm@p*D+547DK}PZ9zZRNQJJyrM3N5r)#vF58 zO{7_K{*I5)}oTlFWx-5Pr=xxaU9glhEd{0jE-fjd88(_#jgCM z2SPasg3VR0NVc{#Cfqg2x5Lt_q~}G+dv1#9vYpv)kn+P7v+XnnHtSa^buTrz#hd)2 zveKc1%m`04r0lshyf|Zz&hiDM2W=gRxf>9Rl^y1EAzPQV8y4jx)~Ih?@e;;CvjFXg zG7qU?78{kvsb)i_pB2Ww@h46)sfhH2;WzMJ;ap8vW%?+Lg?E!1y2%Z_N2-L10>0-= zZ==F!wyJ1ma<+g^;Y&*6a|7do;IC<6)O}o0ax$-5Fw~YF%O6{MA;@XfQoa6m1eO!x7HCxmS+3Uq84K^@ZE{tZxieGi5 zObq1Dukk7CIg!_h)w6DGa zAe%eYJ2#c^PfXoe`PZ=Z2YT1fHj<(y4?9egL)AD*@XG4v6S-%oGVx2;Ib^ea>l!V> zx5(K~$50NwMdbt2o#!rmYk7Ef&c|s&b1O`ea53L;e)$ouejZiK<1IMlx3HE~FRA|$5!8SJakB)Od%`l!-;{r)ql7Gwq zoDS6D1ZSn`>#T9Te7MQtNBny1%Z=;(N2<&GvPNK#zoP$-Sq%J&=ERIzCpSOaExg9( zP~8SWxeIOvr(BnFY>R;$q+x%yG(5F#q0DBjNZ70#{Oll}(izU-!p1ve-v)jr1@N9B zkT+ZXQF&50iQ%&bR)7!|VS;Mw6-yI%#fJ;gla+XK;TW#=G4~&pnw?^1=F;`0BWPuupZ%M(yfY|lua%z#flx@g=gxY>*=--YEE~3 zRgWnbe7!{=?89@3*+?oYXT6<-H>YEq)amqyuGLBmVJvE@*@L@m(`^$f-`^cPZbqh4 zM#lH69lq6$l?gI`Ld>JJ`eZjyES0?VbcI2(t-?vTB2j7z9YP%;wozo9LK$pEpyAx9 z)qA&)zs!HJ)Q5N!fpd!r>fBI*#Gq08aPZdr4BG!x(CSOl&+)If%mU!y$zk{K2kSNt z-I0F$AnyTN8D$p|#~LE7oY~c=OM=M31w}S%EXZc&^RrAuU_u zq07u$PjbJ0A;BE~=3l3YWIS7@D+yz0TwA)#nKELj4O^K$kr*xoyxoUoM#Pz(=2bBEJ}l3u7x16!W>5kJnoT@))joJ*_kCa_ zipqmO%{#%kI}77j2MIVf< zvcE}uT78Gzp0AA`bDu=YIPcv0WB)OBsuwIw5Qg{(HF#W z{bYjNe?d;{3#TtBU25s1G&a!5uqlrZo7eleKT2ejl{j~~IQR9%uzGP|_0I`*W_dl9 zT+dB!Ex+W_nM=x-z9eM@B9MyXYx8{pL|zu_jn$r)y!g^fE`9M!W~(zROVkO7Pm)tz z3T86>lM8W1m^(UO+VIFC#0!wh`r)JqQC8|t$dx9g(#S z-oG~IN&;qktNs~(<<4qH|E7MruL8?xoKvqw2d@$yZSwzD@A-5qMP*eBh~4(rJLpsl@Hu>*cUct z*|T#~wF)~{Vzy1~foplw)NDUlRsK3YPGE}>nd1J=J&#s<_Ux=yH%;w)w0df7&#i}U zz3#eOZw=gClYfB+r>3i2o2E8xb6iQ7+d1_eS3;b8#E2JTUJOsIEg!n|tG;|J!tY^s z@gAIs{ykGudp5D|v~6c~&(zLp|DL(2E@bcALqIXyT(WJC{o23R+DW2SpZ=;z-bNGH zh2${?)XqIPRHaRGQ)h453A=4mjsc8kr+T)*zPiVXK);0I-E?wo`KAMNhq|s?yY|3= znYFb8wYA+t2M!%NaNTrL@QzJW{d3iq_D^k6qxSdjeSBu{!QCdcC|Qv zxSLZ`+xn5-zt0N4zY2>@q$m2a&ux0buAHo%xh*_tEG|_0_is|8P<+p$+D}dT?LJ(n zCk3GjuA@3`Jw!>D9k^*|=+;9+Yp**rG`Dv7(4p(r4jnq6OV^$9)xaT{+DZHFoDwH6 zK_%WcwaxJ(8A^XkSNshx$W`D#wQJiRsxFPzBhsp=sZA&SWs;+|sbovkL~4o-IN6_8 z5AO8Xoo%Rx$x%sA96T+m_9)8SdF!D=HyvNwedwmOYY*Kzx3>G%Lu=RGdSG^K`PKtb z4R%gZgDIMOYUgZ!_cp4sZHnwU+N(cs-o`I5wHxKBZK3?#{hK!JoZ4o6Kym3BRs`I& zYX2-+$xtOfO}wrAQ{tlmq01&xgtxthDuxe zxWYCxGlivunZoJqUK|T5GsQ)G`K3Z{(mQ^{s_)~wCZ#@*siLIa7gAOeRLpFgKXqr^&{C;2r)Nt(@;Y*^9Q~d`F zMg9hS-8t94WYd%?HifCN!FZP557(-Cg1P{enKoZxz(V(Vjb1KAM;E{qHBoJktUwP; z(d<1ln@atURcF>dYv{mD*Ijqhp#!u%U~=7oLpRN??KpJc(CpeJz{_<**WGkeP;Y9- z@S;flJLjgl_Xr@VKnY~;b_yOrdsMQiO`&d>&Z!cx0Gmy|W@ZDq)Fn){+fuEhT>{$o zYzpHPO$BOpPEkwMigwtEcG%m~Q>9IhVUbE`d%Xp_^vbmWOVYJx%cP z0LJ`IYxg^=wSFe>{g3;fSh4;Gb-wDJo%pBd4fX8*R$|+oskFmkr?x#v(|)7j)>66& z6##_3125IM@tF=Yi{(B24+-C=;6|0|VCrP4*v1<=J%KlBD@HS{*<*PypT?|?Q!zv}5f^K%n)33Tq0 zAiW>U|5^SPT?M@dx(?b3jY7W-{T8$t+6KKBT1fdXfZxlYmqIUwUg7DL{QNmjD%;OM z`uQqoA?5!B{3J_!RsZ)vs^f1$TOif{-Ow;}J*2j|3_2fr9<&lVcb*it|BHB6^_Of> z=xgc3o1sBZ1N_|JX`$<{wpIPr4*EUxK`+0HbWim2knS&}eAT}XlJ1M7<7#`ggY^G5 zpkIgH38_ES7Yix>V)*?uB>hwSzaRPlbS?CI(C=yr4aD<>&}%)d=I0uy&y)UM3;iObaU%IY0?k*po{!~U%-=78RQC!b{;z{1`xiW^ zO!`|oc{L>cmu%HtV_?2zh~=yP`ukG<^R4_8y%Bm7^cHA6^h=O%QFy55=PNUQK9;Zg zzZ{azO9ws(eF##&UkhoxZ-d?geHa>pLjBbSqL_C(zt_uG->Tg;)}(WzkT6#|r*iy0 zBpp;)RE~wLzjROaRvTOeshx#8uZPs%p&w+Qeiiyp&_c>r`%Avs|4L{xGz>`xB=1-J z&-MJ=1Pwt8DgOoVlWbw1#=#)84jO>e7W!S+q=&x@sT^Va|0ut&gxcxz_?fu>rT_1Q zR5#UE^%Lglnn)NJaQ_;9SNkkv{Uu**tZ}7&myXHKz1Nd;QM&g#&_^KMTS)mYgkQjU zmEpHNy^EjHfB7L>JZT*0{zAyt7#8N}r`lWXuKxW)Xb1EGPqGKwp!Y#Lp+ABaLVm#i zi{bY(&}yg``ZV-8=wr~05q*^3b?+8vA?2(8e-gS1l3uTcghj7~UI(p#`k+@sx~|{n zEB`#+5uFcdyy*S7{*r$MB>N-05lMC^hsvV%3HRnJ|6JaUDVF~t?x}98AYtHkNPRE8 z*BJOc=vqkn|6%Au&`Y2ngD!xc55>IO`8}4e{#X4)s{cEocR(8R8V}*8u;JJIHQ}WC zP49}@kr_WzFJJYkLh6Hne`@PDK(YbS3H8CRKpG=@Kjt^z-(&ed1uw~xoK?^tc-qF# zvzn0fC+Ji78Ov823ZvDI>es!{0q73@^Z((e#@EfzH=u*iiy^h=MUXHd@YPSrYgUdG zT(75P+k3b7KG56o%6ENf`f&M6n~z>zuD%iOwVXWFC+u<*al%t zOi;;CKw@#o7Z34FoEv%wx9!{G+}Jf3Pn?;2b`RsYgVQ7~28kwa>~cV;FQlUat}hSU zBsS8Qo5X;zxK5B{BuoS!3X+-_g8^ZX5cBBi>8`rJ|Jr+>v+HrrsT%btAo`Q`boZ%! z)>`}ZUyr@^E}q?-tX>xn!)__;OPD#Z#*l zXjE#wRsJv;n{KvSJDQE@Bx!86#+voE-q}dT>#b>C*QaC6xzmY}`bsjk?~|ui$L@U* z#BTUl55Es3I~%R$T)p0CwUa%K=Ja&E*{UZ=Ah(|EoO7QyQ+k!xJ+@kTtwigk_TglF zt~Ixoj5V5@NvGM##5ynG<{k+mRXzxb--pEY{UkcgvyQ-yMl%!SJoF$u-B8=6X>c;9 zK2U{vyH%m}JCMB9m|jaN_dxs;5U=(U|41@E-I@#Jn~jV-oyR9@$<%bSK0V!Pwv#Iw ztwy~*N0kUuOq)9up|w2QPCe)?PSH2%@9emBxgygG9r(B{u+dbH76w<)=^gnBqsannunIKNOm^mLoh3clguf zGZR$JUhp7vuK~zM<24VPlga0jT|c()2cLN06Tko37p+}4QN6x)!yolkQpFUy?6vRa zCv@4q*M0Dw2k!ZUUwv_Impxd7{?>&B=x?8c)`FoN^rydl9e2>(Ee+2WL8T?-sG(yULkQQ*vO$z`V0wIs>>u4wz?i`R59-WUB zg|8;12~+_$NrFo9cv;%oR5eV}Hy#ok;-kXF7j&%~P`Ib(ZSqXXh6t*`)OD&Z&>n`S z#yMAISU*Q9L!2vUf*o|CDT)djYN~-^hL02kVBcu2Tb)XyfMdZl%(O^=zI9YqP#zo7 zcMTdfecG{-Rdk+_jCEn$xM;!j=@pyvL9a;9!kgifE|G?zi!@BFhOuJpNx#LM;sGpL z)t~HAGGg@XpfYGl&@6LIShbBg)nCXJevtt<$ps6}Qz9Ds^j=>Jy}nzA6~SYRT6}H)i^X z${`O`L*7F{e^`1j}VJ3vy!iO@3_TpI5z_v5ccJ`~S zAlHfcrn-p>+e;E}s|z#48&ra~4MAaV3Pv^^!iQHQ#zmNDLs9R2*|nJ#6-^cfKC-37 zcTe2Q#Tdm*i!e%19EO(GZexr^7?{ZJzpXIbKbK7G|LK47OKZn>{mMH(cHe{d{qb9- z`@Mt*ld+fn!_&vdZu!jm>iB2g^wO??hlzv9`_fmRK3;jxnbon@OYi6dz=x6w1S+=> z?|4)1r=O4tm!@f*61eb>vmNVyk*p?_{qX&j&k)=A^vio4!mbyayx3ul;gQ$B!7OU5 z>Fu9}={s@b-;)3CU&^tne>Lg2H~tB4e2h0fn*T;@-Cm-(?O@1xXwHSk4HeR0(oPUq zz~7sa4Myz3y!r8FT`IQ@^kC7TN}Y)ebo~Cq}BPOAOj9cSOGC}7-N%1Bu-MU%2G`0y{ z<3CNOfOaYKoib-+4xdRXLk+15dF-O6tbvVF62Q!`Y5erfWJ30>1!6Q_8!hHq%nvkX zAgvPMST^mxr$N7`)@)!&_(Ku8Nd%BjU?wgtvKB(zn(O;k>@2XNU`)0|{(k?^+1lD6 zelloxD>&j?D0Xz|1Pg}lHY3+{9~^smu{`G#5-VH8*09W&^_;L2<{Irf2EiQsXg3@> zbDilctcRt4;y^$i!t$hfSK>?$~+S=pdCvGTV?+jRsd}Ls< z+TSvCFJVc-Q7dzbRT1&tA>Mke!t9IS@6&JkTfOkNqK^D30hbg?TXz7ZAAQTqd!h8- znaBFoJ`1sxbhI|V()YnTg(C>o|H;;=08!csRkBrdo*=WgLmXIR-X|awB^mC&bzC*9<0eyk( zU}>k%NT~tsMJBqZnnF9lq*zv&A9R7A0raWj7lz@3H=S&BY_6M}5r(I7%2VndcNdX} zAi5y%9ZxGk^iBuSqE2I(nr_Pa&h;2Q2_^>+-i~*(y|~53{}U4L#`w>jbHASADu8{VTmGM2qa5)Lp$bMV?suxF`}ASpRN&GXHiBRY((fMATS+~EwV5pF3`ra#=tfv zTWN6iGGVrBlT2;dDhsrmg;|9}L9&)?u}KQM?v*dMhV`Eg&lVf0@GDQsuu5Hy^mqM} zD6BFtLTw%NU>u_9jZj;Sf(SLA{}v_~$#l74YO4HqQxlcuJ>D=7*z29uH~`ljqvkEQ zcm9bu?ase6I7S$~!c6oDcK(gQam@4$DUI&9a)5mH`z_Ke1=XE}afuX#qGSV8tEyM_2IZSPLoUD|{!=oAyfXiP{Q_Yv7h_Z0`nU4{{al%3*;a@Mb)O;?9R&B3uK2q9-A zvY|;EbETo6fO9%Sz`T%5pu}9!bkN2{O2`F^cWC3TJTh#AI?Q&~U12sf72jgHuc!LJ z=q*xo-|Bn(9fwGdBXnGbT1NWu$7?VtnvK863-d8VZxeK3H!9F-mA_bsV4-?5RL8+D z1~Pl&QAe9Y0EK84sLT48H2Zo=CWxI?841rkAxq|PR`OmWG%BEZI$9}a5>@6bVSFS+ zi)gT5*)N=SG$IgiTlj^T7Ev)fbO4nhKrNz@C(AIf7Ljq?QtxY0DXtlfjryKx^HiMq zmr@xO+TMl-dA>DKhnAl?nM9+a+Zz}mmcxVP@J3CY=D86diw&zcnS}OiKI);QsXR@J8+kt(7;&hOcSV2t6b_* zb4$%Pqs@^+v)?@CopDaIOPaC|oQWwUD>3B)IkUq$%?Uhqw&Bf9O>?l)^N!d@WoBI$ zJq5|3Cus@lv|Lhw3s8`sE2B@5fsj2`Jf0AVW!y+EjeKj_tl?wJ)+c4T)b8`6WOkqL zNaCQWdyQ=7>!+E-XwhOT&X;;0Ng(z(CKaQBK*8pIeuDA+dH2UtJ6FxLfm_kcB4XUcUPVG z4Y=ADdnHd({%EUiRwdA7$Ho+tG%si?kXd32DB2v|n{!eO3cs2dihHpgsVFT#ATh4c z^T!Y25@L6vBdIr$5rF0=&_X-f^81SQsj2r093+3Tri> zXQ$iKM)z{1>L?09Y_Fi9b<)M93^eYkF6iP+GfgL?oU^Fyg=!8l?<7ydH)$#1JC4{I zymz;oYX^D;`|+w6$A1sN4rTH0)-DlyqW1*MnG&XT6x|7-TucNyZDeI6*4h-kTDkxV zkp>bia*%Ci(_lBx+d4l>&M|AxP4wu6$Dy*E7?^h2f)PtJRg?l3i7{uZ9+lQ;x5m+B zt_QY8vyp_?np+(v8scmAn*O6b9?t0Q@bPCvH(zoWmS?Eg`iJpVie!bt;2xx?e%EO0mOW~CvnSA|Xs znx$y1;LThg4VLT7{$!X9yWUr9XHP?cdoRLY|nQGBp2Hzk^ zxql*wofdqS*Mi<)m3FgZGoqCmvFXO7S-|2AQe0A(oc=-)ZFM0oAOnKT5q8Q8K8y3^ zk?K>#CN;3#FVPdXCz)~uKGphZ2~g@CiEAgpeGEFTyG`Y->?CYvl0B->{iL_Kcxuvz+2I_!IHuUgQfsBwF869Jo29nX?gCZm%r)ny zpY1h~Zu2vDsNlR~ZputVS)IRh73-i@#3sVwRdOLcc!8C3cg@VE+6 zy>ChOu!THVue)>=3;x#?m1s5|&QnNmTGq7Fbt(D>z)Rm4tcZBy-Q>`?i%5iz0B%q{ zl?Hl9>Ie(m-$sRnR-$2ypi*MO#-y%&u`s_|n0qnCy`IS`6{`*-Ii`?4=CBM}k`{$* zk+QH>Qo&C273^PnQdAF_CyrD%Y})FzV=9HH-$M*>B4R1>r%+G^=RM?-7Gu#5;3>IM zl+Nf`Qv{YAd32B$L3K)yREh%l&8Ru_%WjAQ`GUPr!EncuP>4$aXf94UxOS6fhAUvT zLoRZ_RPN_Qc{`jHVe=-+!&(q74{KSaCkNzhRV$tl=scNdQ?u|O;`>6{A!iSj^kXj+ zpF@0KcKwr`h&Qu7eKTj~wnPjNd3k>%dl>$e-ivLucr&@3{}twDycK!BDo z;_H?_f5j5PDVCoBg#r`Pcv|TtO2eF5yv@DqVgL=h-Y-25$z2&K;d-m$FE9e*hdaIK zNxMA@WrD@K4Sl4Q^3s#`H+bX0cSz6^oRV1Y*>mWl?V&m(_eH9`@6=C^&`j$%G!#*e zd%FBAV;@o>UbF*ZWLybLb+%{So*5M3)W)91x^^@K}JLA(tC(P|cN>ShD)7-0W@jLG>Pc)0Ue~5xY!q|0l73 z$d8|)uMFoV*6JVg9(-RVG=n70J_ePq-|Zx z>SpYa1~C^;(p{e~i6|h!Nd`~G{$iX8!}FU+pQ%hwFwV_4_I)%?c4~*Ue^bvVA{S-U z82Km1lPAbp&fWi|D?g%$IB`3(-dK%H7PlH53JZm!)ooD3ht#(Z{G zmW*In+xZf+w%8aISy}Hzs4vo5(MaFd1SksX9ButZ_nm>B>`B8_`?OpK7!Qt0EO!a2=uiiXo#SJ-Hlbcm=qUk&2RR~g(%h% zo`nQXS#-@QiA&Z>vq`v|CC`~iZ+V6^pCS?okC*yjV)>S0Fp=n!}?r*d<{SB75%Xeo<$+U`ubZn*7DwMx427 z8b$-4%Y@lj_7_c^Pj)f)wA$w8u!iU!-YriqG5|4d(=EC+y$ryl*Z9ax*rA)Eq+#q@ zOW?!(Ek6sZCmJX#AKq%($)zXPiZhqwcqll(?UN0hBQx zQNc)sbqj#8P`5xyaqsYeNK zc{zqug><%8ge>1iNM5qmOK&TWWIOV;#aDRs>(wVnLn^rlxGu;}0;cX9QB~RrW^6-l z%1h}Nhso}|AeA|oPrl~7ll3@~=5!`*cQf*}sK}3|MN|41pVAoS#SNSIWCH`okyIz! z`ewG%rkLk&2~VEmXxb9h&rLs-E_R`b#SWYL6JEn>N9U8&@i4l$xh!nCa0U5JzHOsu z#Ay1(ed!m}5D`H&a1>{5(8zgi!-NXOZZs7b&y`dUdXBWd*xeJmQMF%JmqrP^VSWx3 zX7r4QRCmFVWktmLE==j{n)w$+Eo;Vt*05%;X{>(Jf zGR6L7mk6V1)3b_zd(RoJ=JHthpKx3_Vq+rcJFDRL zmVU8U8>2qoVkl>{SFRzoGc(>fqjiuWc1Hcw5L)PTjlR1qAjeSNX(~@qI$c!BduZEF zFqEy!a=v0Q>YxV)-~1ZY7^Jh;($D`?VDw)GsOqc=+YL&-(lHnIf^crM=jZ0ZJp=V` z{A&8GidkBnQE=H7Ut{JqzF4SQLFO#O4hL69bO@5wzlP;&Z}tXU)28`1N6)ZxIVWt+ zr1{OVX#BU+D7V?E(X0Xx!1g8kK#@i*J^9}&XLo|$v-=bD`t$RGpwH|}i4M8asfvx# z0WpUf_1$&Q$E(}6PJ-xbA@kBoB2f!+{N%Hk{`Ag^DOw^F43-oP@jTK@#1#9a$p)O; z2i9|oZd#zxD`#a^D0|RQc|dSC63FIegCjVe9OfO=U7|9Y#3dYBz?R3EG}K5lwe5{m z9zNN{i&8@g-ipkx&1pO4DYAK&8AK8>UkBzBs#{E=G@Y;%H)4Joemdml|=sQBawhv5*_(bU&Iort_5-nZc*r!$TTjSlJv8z z@^sjuNrVax^T!M1zhhGJbiMDzNoSEl)tY5g8n9p5D@t$5;}1kBk6r_7N(L?5HE_?M z=^-~q3Y#?cpuw$WUNTeVSJZ6_-3OL!Tnl$vyX71uXA(P~Jy|rjGAV6ANKEHxvpSls z7F+aP=W5*qOp(kqylvm=ZTm~#?=vX>GL>>$&+9gbs5^$SX!3pZh|uHJ^Ct^cyfQCM z#j~iCyS6%L?=_X?=J<-ZjuJUB|vVygW?HZMEpr};q-OP58&umu|9}ur62!$hsTu##%J_0pGy2^L5 zc5HX5J#xfMX|XWb^x^B;04y{>P6)NTU3|-}10-nJzMyD$*Cs#3Wgrb2F>MMrmZKn( zrI!dM8ETRpyNYeuWjz7{7lZH3vhAp41lV*af62`rgVLgC53EPLs}F}%z?D1#z5C4{XDyf zJU1Ka9Wk!i1>{j?R$orZJ7Qe(7m4?V{8H}k2!4reOW57!y`D&K-4SmP&pq7ZS&w=f z_`vh^c$(I1cW_7WmR+>19`f) zUR23p!`k+flHg3#L5~;V?$$!$yXc!-uG+tuk`2YDyI@XtcyZ3gzR|$0BGKyuExJ_H zPj@4q-Rboxc__Q)^c}(SABxlEKHUX|Wc^_xnU`;`<>I1$EyYD27$)~7oK29q#nm6$ zP;$w&Y;KIFhsv#q6Us2%8Eyc>2pS$vL(aaP7u9`R$F- z;qcnen)JqKy=9D{24hRcw(j?yxA?#rbeBUYZ*e{4%ma53WbwvD)M|sUG*V=ILDoTh z!={C}x+CefRWW8wMrPdvUb0+c3YILD73K#Dm- z1}48M4t*~4|FtO6C$&cA9x6Yv#8;4q5GV zhl2aOM4S49zthEP`#45ccks8)WOaGL?V8z1Dr`238C=G{iWRyOc*&UTIIGaT=fFxJ z<~R5Ybut#VbC9~tG7I&^_LoVAWNHkA^?vo0L7OR=8C=laTLZr-=mqM`J*jpw!R<;G zIIwnI7Pe_AjA9Oa(tTb5Ni+FiKM|3^@*8z|3{wPk1f(toa=9T;Q%~$TmE~^n8~1Ui zL6RtTpZlHlMxM^MKnAZ~*2IF0kcf3J z@h9t(Cj=o01GV%8+bBK0@lF8|u&O^ORH?3CSGnHuQW*sxa=Kv-l^MgQ{BiYGogF*> zK}jm@3n2G`j9f^H?IPENT=*bATXyV*>c(|r)f)n_zc854J-ohIkJy8ptk}0EQ#ZWe z`s=QL!3~=U7vRt~d%ru^HT4cJORWrVZ#%rx^544T*f)7WzTksG4kQ#X@3fwVT@BDW z13Y!Ng^k!|WDhuF!cavoJiffxOpp}mQ_3ck!YpPorqLuIM`jrbG5xQMoD}Q%Uw6{} zd((Ape6-q6CPB7Q|N6sZ{AI8B$p>b~fASSCTlXF9XnZKC{KRKwD?f3*>nYz){IdII zD=*vVefkQX9_)MilRW*Y-lw0M&3S^W<^KC{;_LV)cO;$tUr#pnpXKLQk~7KJ(Zj5) z6SI%-_cub_7vS`sIQV`e@h8dH{-c{GDu>C`o;@*3zUASK6P5j#?Cvqk=fuH?5EoM% zruyuo$@$r_GQj-C+ZvBO6<_jBMmeDIBA{HP~Q z#OB~(YMhvTjL%`niwD06i_Yrgt&6v2EL^Mqh?<9qJ03o||0skzhY2p9IQ%sy<{Ez+ zslO7vZzdbF_DXC#4H~2Z2QER zJ{&(f%k#?N4_SYS^(+a4;>$l`ObbIDEDh*(l0An{oH%OjIC_|uCl4oyx^rqjq>cYL z|1vtMe8<;aZ|=D3`0Vl3TQ_HS^Y85J;$5q&xAU2s23U-AVX}Mngmvux{YOuS5v>l70tb(ZwXN z>!HTO)phc#cL_`~hf*RiILfpTU6X+M!o4U*HH{|`@UF$R*{Q|VRq8%1)7259?i8;HMD%WFM%?ZtIz&lH?%d4xe}=IX64O zM7itS>=kOktc3SX**rdW*X>ygc4_7u*1PLACyyQ`TTdOR5mCn={tkWKE&d1!!nl869cNW)I zE0N4vsr+v}PxRsF;d9CEgKqjbfd}+Ai*)uxEHQuDyF>LbtCBbjEKkg?2^0^0BRMmB z&F!l!%)5?jh9E4f(=E`|w?wal3i2XP3f+Aft>0P<^(-^ z_$YJxF!RDDPc{?WTxPUgZ)Y>XbtH;~36Sv=`KgL#X zkAwsb5Ms~liNhenVNbO)+u46b=vJZje!~wF#c@1w^bW5uI#DVEarLg-H)nU=x_bNK@x|L0!yM-p9JCky(ZQp_au$;a+FuoBxpi3u zL^foPTX!O~t}=`MLzd2ov~ALl_5>HuK4rAJCO$VY2=LP}@~anwI%q>rUmOG&PU!vh z6V|B3yG(VqXDhe1S0`>izIuEUWmh>)d)-IiX{`M3AU5|k3en5`UrsRCfCenn!$<#T z(rYE~A^rMQRhjMobSI;OrZ{nwpv8V*^YeZ0kE0i*@E%Sk_e+g^KB)|}PAY>fnE_VM zU<*kW)xn>_qWYo4+Gzg0XP&hG-XN=d)Zbrl(*IW(t5hnxx65`PY|nx1Ij}tk zw&%e19N3-%+jF3Q4xH?4|F_)(+dZ(|1KT~Y-2>Y_u-yaOJ+R#a+dZ(|1KT~Y-2>Y_ zu-yaOJ+R#a+dZ(|1KT~Y-2>m5Jz&`Y`-%R)obta>o=bTu<@+etP_7!WJcs(%Ql8<9 z{{CTK{t-V_{&&hNDL+LyM46==ru;NT^+)9y*N^%C5VU@j@)FA5q%2ZyqP&*!tCZJM z-au(k!e`g% zps2r9UP1W>lo?+%9{(prW3iR|)&DP~h`;1GM){`{jrGq^>Xe_QXioeB0 zng?@~U#9#s|NK||-&@IFw8a1CD8iV3O=(hYq`cn$)cV)&Z>RhgWh?pr5cCqt-=X|% z%KIq4M|m6Nt(0ZTTPTw0J(S<3Y$g9^Ku>s9qx=X(82|Sv!lR#{9H9JN%6^KT>G!SV zul83dT6-$5pa}P+XT(oGCC86b^w~kmR`S_y`RlowGXgRoARC%n@*OjE*~_-TF@R%~Vei?`@&Ua9}zOwk(CIy^~f zP=3w-{J;2lGi59JtNm*GK8p13?@&HSc|Ya1DJvAMMe+U*l=o6{`Jb%bTpe3Ja=tn> zv%If*WO-k^IyJvst?pZ%+2prH`|VtHY;pcvweqS{_f_hrpH+Fz9aX)z_N;bw<9o>3 zG#c|8GrOxIQe9r$w{O0)+^LQmm9hE7c6E;)R_BlG+jnGnX02NJ7iaFPycSZ={^LGU z>&u?bzQyI``Kcp88lzL0X)ljekMPgp%$e%gtNvvDzOnz$Wcp|ip_A3IBg+p~cfIiV zd+zwNJKpn)e|_y)6F>OuzxKR8>aRDycw^7Q#p>kZ46UGR`ai17Z!TAkyrJinll|^iwrRNRmL=*Y}KNx?~KN$A;gKo@!l`;RJt}(Yy zAIh6teEL33(1)t4)v*`-$tgzruS4Q_ALD~`28K$jRX}g%^VQ009=osdi&Xn-dDWJ! z+Iy(>9!H8^VM;;iv4;%Q{CZKF)JtjXy5YUrk3^TGFi`8S$Lb(9s3Y% ze(`in&OVsZ2e!~BjVuTC1!NJMCERChR%)Di~F(B$F~ z?UwO;br1bW2WAcLlJs14oUU9ipHK89y$B-uzT8lUZ8CP9>exP}5FMI*P8X~d;-sIY z;AE#dwa8fd;lGqorE7VxZ+=;mYWYfGWz|aFk z_!!Y`%qpc&3f+@cAfOOOtFprs84_C)#mLK*n z6{D%WHh*3(+iU!znGRNz;OjlriRJm_eVf&Z88GWp;jI$5)mt;mM|f-gh>V3X0WH{C zo!Ga$&oH=M-K{l9kxk&%-DY+7qJc4MWh;=`q!9Z_apmU^rHH%_rdpi_&JqK7nOO$2 z5NNY{bt*>s!i7TkJs3(eutys#0$=BX2?pwhr^Bx=^)On~eHg?{{0VPnIVa zUH6@=K5FCj%>uvSu1NPiBHj1pYURke_IaqH6~4<{Hg;tPeYj&-M<61Qgn_f*`=_Z~Vhf+t$F^zOx+@h3g z*6u#GXoyVR`FXT4gezsENgGoY$Ghps$)@nMvS$NWr;b;sjmuXMlLA-oid35^mCWaQ zss*FOw#Uip8P<07nxNiniCa&X#juQZmp*fAwt{^t4{SnIvNfB=$m03r-nh&(pzodX zn3rjjZAUGHC9OM#QLqf|s4QZ!=E*FYof+QvTA_}5TXhe{*v!lk z@Qb;!UL{H)MWu=LwE~@ViyxytC>u}enfBiOja>s=_L(3zXZ zB@wZAS1*hFE1>>d)zp-Wf9-XKru0ozt4xEuTP;B=?2xB0zr2=)a59jw#)c}z`oXB- z4p<~j)cQ1n>$%P9PAQ!-_z&bPyl(By=v7_hE6_9GDi4BnQN&m{moFg{EgVo1{|XdM zfbm65k$}8CT}Z!BiD+6e9Cs1KHo%LYxpdy%LkYldaD7LyEIQ;_7YMmhd*Ycdnnw5&)mVMuRML_7x&)zO#IdZAQS$txCdp z0?=Z6{Wg!bKmZLeWwe~duCS%0R*0*K>XEVKeH#&$81xmxuaS2!)2?o^!EyvV*D|&R z9nqezfNcRw_wA%zrC8iWo6(Ry>k2{jlD9_8uP^VUBTH@WUh3=BOEVL?Ncz)5*wy{S zQzKbI=lA-|=`yhHCw*yV2t#|LdP!zNcb31`b};;$VVgpMn<0R^my6qQOXEK5U|=rq z(7f+m1V=WPCzzMpdly}Mpj#3>dakIH!MIg=Ab-c#KF{6pwND?__WYxHC{C5P3dI+J z4N!aoT;&IO2uGH`nUCc5mduD5d_BWd_aaziFXjNbe+?ualW}K~5m*{*1XH=yhv2)F zq+s)O-y-|D^FFxb5Mus_-*qdpgNE7CZNOGwEPiPcoH?ZQ=nW z8SpR~B++#Ceea+FFWCkjOqTX%^YdzEWIA235Hwp$p%l6&8DKi=^Cf%1q2@f}7lpTZ zd?R{irn3*flijVpkLH)+N8p#psUu)^aq#pEKJPB&lA zKzGxySAeK+1h({shF-r}RMf7rt6U{N0vhvkNNa@(2U^UG(d6a0%K+i@1@k=&@eCyi`5qyD`a=T#he?8&sTwkMkAaZ}K#U1Ku}AEA0!T0*P^j*^#Dz8rEOTqd z<*<+;464V&Y$OQXKnM({3ny`Y=II>Ro^_kP3_zJK_;6L^>D6BH(hDd68)4F1HnbJI z%tne)Hw#^TRJ=c&iZApgd>o7K6$Spj94OkM90%Z-cr-n9*0PJVGg_`IJ`4$r3>24b z0yB(?pRorS^oDoRG{E$Z+M;fQ#rz^Ygg1%`=7T)%(pmuvHbj`&XrT^^!a^Nx2;l4I zl3F1S2rxlhnsHVV1qMk`WF;bRF%?Y~t)*qAuJz5>A|1WQ4+M5OF4~OZIpkK+ud;n@j^oj8zae`4|>}jS2Vz7A5o6-=9EVA*Y&LSK$oVEcV z3zLoz=ELl$&;0oO!e;xsy>gvLot}bJd+elZbr2>Hpc0l!!Uz z`yLj>T>n56FFlglLdqMEBEM4F4};wT#C~_O*f06)1?Zw4&ZsgB5Yv_lFX6)s5kyK` zJ+hkW>2tV~Nv!Uc$1+ri$#`Fo{u;y^9Y{{9W*cd~6K$g?6>h8RJc4@n-*mI~7U-c?O~imSg>5GYuElf_r&Ru2s4)HS%PA>j_YgmRe-nPr12C49v$z zQIwd?I-!Hnm=Q0?TMFbyRG4OZ_HoJAn;#!hZw_ihz77@j;dLmW;d_WfN2W(F6OJn0 zqf(aaWIZ;b+T`$256h>-EDPguEZ&cswlYqC$`?#OI$!BKcYsnL#-BA{40fY&KA0X zUmQuDf&TO46SHuQYOX6Ns>7=>QKg%m2D3vBE*W6oB6cCF%*R>?uh_PW`&pi2Wur5q zdLz_`!-vVv^4+XH-RUUH7TC8)`ann`(C$xX`Fq>}#-Y8$FOIDITy)YDBjWgQuL5a{ z^Bg9g*MSi{7qAL(hw>Jk2t%vIwdyVfFwLY$`AcOx{yM&>yefuoNSD#`A6`+O)#(rO zhI{xc{27i=N`}g?p5qrs)tnq9r3-9AL;-ip`S4i{Q9lghL7D_31V$x*oi)Yp3+|(h z0pUhPdn=3aL@0M91OL$!tK&HH6r9-}Ptwc60eU;jsT0DT<)@-~@#jbJEKRQA6)*En zo+Sa+cJ z7CCZniM|DHq?Q4_EF;cQAphbB$4J>V_)?)lQh zDNy^(l&DmxkOdiC3W?=XFUlsMwP^+(u)9;%fdYrN6PKOsP{Kxmb80f>r1SYCz9^dy zaoFPv;t;D#Q?20|3lu(51Q!9Mku8o)9aK%B0~-cZ!O;OpfT>U+2T&)gBZ=UpxTdmG z%%cyQIX%v5B0IUHr6=v^Y3U^gL8`pu!Bi~&3&+d+pwVDt!VG3^D8ztz=t)0}B%&tm zrWXHFpXph!rD^k?D&h30-gD#N(`@3&Bt_gM5l5AoGA2+D1wW{MDj|d$T56FTI5^=q z>K-it-J#&)Dc_&vC|bbRQfO06?AM=@{23PScd0e*0vlUTDKYCvY4gg=mEG#x8a~Xv zsdd@F6vya9Pzq+K=L$|6E3uciw_Gn)%Fsnu z^d}2dywW6h%%d%4NXuC*T(obk?)EyJ+Q0(3c%Hr2{1ES3GZnt3+RLh)tFo;&DQuYN zs1E4^cGJ@BOMf_MLY|V@s=1fsu%JC-!emZoYD273y+(Q_J#XriWSQ1`D``f`C-Rpy zn8UYI3RVisV-;M?fyliI$0RaMWgAWkD$i7>@c88Q;f`VAI5aC&FV?Vi?OMqYn1_g( z79IZ_CS|3I2+go-0lFj^CM(5LaUL_K8W`*R>#SEWriy{Lo5uX2#VNCMmcw286~@~I zJ{XA^ZXJ;y>-W4tx*=}-g39)mSQcUQzD)#rIZw*q%U*jRKh@hl&rS8_)88_?|4crJ zQRnS|*pvgYeP@bL%<3weNuG&CV^lo{!K|`5A+|zUb5?mUfQ8DN9BuH1f{V9B&V;*D zX~^R@Z+GDNlz?HGIUlEaU!I!rg-GVx9U<8|L0Rwz^F?`ELPpwG9{Msu9?G=zGcwq3 z?tJ4=A*|3{0n5x@9(Mvk$!wLO0#O;E%LIy?hKa>#-!A6O@|G_K&%|xtWsA%uAfhk@j&Z!tayV1e6NSY`tDNPq{S7nn3)0+-Ko=6;FF(P# zSN2{mDBdR+%RrGeik~4<;YvBW=}DImPQk0v76##!a01*~ISxL_?6P-8f>Gmd7aloN zFcZLTaY#={q+t}>v%qzVQFdnt&Fn%3X%F4AH$3#-$NeA?^r{^mbIpiM4{aD0(>d!t zn>s{J%!(QZuI1?wXv%^t9;|XLPa8N7*WoR2T5vDRGd*`icbof{?o)&Za^@XhY+Qeb z<1kwkVa8;~zCBwV!|7vt#%)dnrm`ayKN)kJ=`0ewhRbNnS)(s0%PUbY&~2d7e4fPTf?}@#QTEP^xciaue5KLSXl}>He=16L)ONg+201aEK;iOO`g!USyEQ`%gIu|*e z&}}8=S_v0e<0B}y|EK`bC$0PTt(IhcGgefeU-Z?x&I|F`A7Tty6zE891$Te%y^dY) z`%<9gR`YjaozGP#UbO#}KeaZy>u2A5+s8lk@eiJSY1duI*6;_bW7i)zJv(;t&h`7o z@0`DW&{e%-*T4MqY~|)N_l-5LzoVzK-fjx<>r#b~shs4-==t6{zvp%(u<4lhUzh#< zA~^o+om}pF=SzDpwf((xBODz$s7; z(SJcQ>zC!FRh%k07i`luLArI|_7>c!&YyzC$6@i`2C`^ZuVw*t1uyn-@CP13@^rQD z&7vErIs@p5YU;MEQ?r#%!QoT=9QLHz$>1uzjF=_>urzE%2rn(|7V zaET<6QAdC_Fq#D38q93IJBKBTJ`>5lo?g$zh_{IPSvPVS=={u^Z~t$f`fne6eIMw& z)t}iif3_D`Z>e%#)G|?ad04OZ0rV|mwT#u}fW6&UK}4Udn10c(W+yKb?D|69_6r@` za-IywM8C$gQSHCTk3&=coic#UZz0$>Kl4cXQhprgomABE|K+%LuFs;{iXgJ*yHl4@ z0aNT^YPOFZff>0YV6j=^X^^obCT&u?dH6jTc6J$+?YaiU=1Ol-1r$edELyRnfXzwY z0eKERa1nQ!p=UH5j11u}{JW5;gg8dfIR*gFzU3*|tjZ(1>O=bknRHckdr`U0B;@q1FlW-)?*#!BpOk1ARLNx$iYS zZ#(awD$SNLvn#JhNTy&Otxb8#fg52Q4)@HgQ2iJ8(sjFu1&u}9O$kdx*kno znVh3!xZ0X9<@U6mT-9t{*cNRFHQ{6E9HjXt?TeP+>cmQQqs5WatK8*&fD5VHZC%64 zuq&J_q)7K|d6Fw4ZR^!wm?WJV<&=$(vkE!clKH` ztr)^ma($v*n4F^^S{bCZa#lyTXju@}d-y(PHGC3I5OlM;SB9`1{#P3E#JOxchJWqrkS2|rUHTh^z#PL62+RBaD;pKl zqhN%)LfBB>u`eju1o>hwuR{ zSEJ19AYM{@L%kPKo*lkR@JsDokxzRO@mw9GP&~{fHreJ+P?TAws}r2ior$(V*0sxk z%_J+$ehSl4fddY7b;vkkra4!tS1@Ymn--Aj3PjHKhUgXRGnefegbMwoBxc%~$yAz4 zmC2;RJg40;7h-hXW&ftfRiI8KHijgZcjw(ViplFYgVble2EnG(TQ*C2B`Z$P3Sz~# z8fcD~CwrA3BHMDZX<Q*FdXP}zB7?!%!G5( z%q;z3zxgpp>-LQ%6&1%0m}GaaYMHLxDjzo*mzkLr^`kN@^gU-TDsTDx)bRSEh$J(l{5G=_Dr0=R=Z{nLjif62R`RD(^lh)-M~S~hb(r7v?V{IG z^i8WOf6W)s{YMmitE;|kSKn-_Z(I%EzWOSDuT%8?Fnsdr#QdKPt-nF}QOb)cH&Nb5 z`Dec9o1XPetN)6k=PG}l^7N?W@yUDM%l~E2(zp5Qn^yJhy5c!Uc@0J1va4^~eJv$? z^Ym7>|GCh8A?0uSpXzUwX*ZBVkMRQGMhN5r!RbS|vfAzQ8u09Ckzg6>J-?aS;l%JuzilT2i);w2x z^?UfK`S6b^TiJfCKlQC-(6`xZj%luI9%|le?&+ES*0&Gqn}@fOzt+6ksP;<+wegoJ znghS$%Rl!&C5N7ECI9C@PkbeV##U`?QeIEdS`R;O@;`rrpTAA{e<)kYU*oTD+SWIn>l?K7&Enykr~e+m|6R%f%6^J4N@Xkg ztNmJcl0ijSqj@Mkfxmv23c49#8vD@y z8h^D*cqjZ5{;RJwAEb*l7Q*7K#(%XrjPDKn{w9j%{z;1Z`qwB8iZE%J@)pWgj=$Rf zHz{vK-;K0Jl*;?h-&fH&l9i*Q7$9<$Kht97|EI_DTs~l>t zR1WP}^74#912I>SZ>ha9wshc3ZR{8BT)%(pPLt}RJ)}<7#+DWytnK>IfA%{c|IEjK z=QY=#ea`p~KkxZ})L(7o*o{38-&EUi2w@K`jjbH$|7`34{ORWdZ|HgLB!72zP3e=W zs}a5RZTaMLwOu#-%J0&TzkA|G2K1xJ{6PM2*yj(rasQWn<8GfmlsCcn^!+wRAF8d^ z#%{Rt6a#)eG@k#lxUbV%tF_7skups9Xr4RJfzSoh}2|ds*Qt z;J{{WVuf|387ZxLs9oE6Y{|`AR-CYEVL^6)YG~E52nD{F2lm3_LSmBvsA$(Fk1g5H zX9oZVE>>8LO8|!%H47j#3zucuEyV8d!UZF?6N1LqCYO#O#JQSTOvhH}iaoxua9ued z<44^Qb;7v|gZ6uCmmXRHXaqI_;*`ur?Go2SG4!aP!*4|VcPwkza%f5G>InN|wt`)$ zhnTI6^@S^nduw}XE+bmg)KLRt9T78kZFYV9J!#*^wMW+|_i81eY*!ZeS2i_tGhMP# z+nx0|L)=;F2%9%+yO{tIq`Nxo)iE{^hEY9%`NGOVyLN>*W%@=Mpqeqa`R#0x0|$=L zX5${!KeTdz`Y8y(uzDeaUech%J+NdeebX%er+@-phEVs`CK{y(-8{LlE9Y0VZ8<>R&Mitk!CmrI2OVnD4;cUAwYN%L)3u zPD{B(Pd4O$WQ{~&tU1ICJzM7DIDVOm^ZcaDy7{>${rmuT`9tz49ZyVxQZLAJjg(u| zCf}#glYXv1a;D%MUpYKwj?&$|Y7LoF#pHj9p7itWc&}==c~y?_`BGmhur-DDY)ysO zrIP<7O4&2%m)>!0*PfnfLC3f@gqsyun;L^=xSodT9JypL(Ap(c#c3XmT#U>F?t)Xew8*~29hGWClFqznVkF*(rClZyb^ zw-j>apzDbl=3TAG05cQeGNj!jZ-E#;@T=~X6FCH+W@Hh@EfEn7^RI%=cfcx|lQtyV zP#N}Jw$!D#*id=0Myz*X=`RaV@_jgco9yZw`!c3@+tvSaAxgflwv!0bfkT)AU-u?_ z`d+@#{yy7Fz_J9?9uZ2e1z!2V>)X0;()9n7*0}8jC}cI|LjRfR9<2Fplb{SdZ>wDv z;i9uMjuAE3n_Aj#7a%g!5AF3^2iaoOS}eoV+dN`kYC#TG?jgD{3q4^cgI$}oNl{&@ zEcxxh03U@Adz*t;Tdy{vhk!;cUNgl~szmfW)s=)R@wFeR$e#h z35kA=&MP;ed+4rr?;-S2_P~5*2qU?NvP0T9_>&18_43N;QZu-RFd}Cbt@?Sl17r1p z%@FN0_!+{AIW`nL_w&eXSMAVbMz5RgGH+xdEVNf96}j2AYqvc9^ITcJC17oJ3ie{{ z^W42y`;_R#(n4+ohAKA$)*IS_Ct$g-0f2UhIPgwE*u~x=>}-8*OZ|E zBFSJg(Q*ST)Nb`+HNL1a2yAX1V#{{w(1QO{`2|yl^kE?|8_^zMCO)e)30q$)3wyPL zm;I@21O6(+U?b}6+MOPQ>C8Ra`!%XdOSMi7*Vt2CVr8-O!RB(Vb!!yO;&jmK$H!tR zz;C;DiR%VuRPNLtg%)l`&mz=PwFn@SOmUZ(Ab&ABOK9y9tj$R7kwS1P)J%JIWEV}d ze4$xt>t-~AUI2rZz4h(DH%Z|A@@{li^m@Agw=Vk*WTP0TP) z+3X_4K-07oLm_*TCel-%FW#jM6<3Ze#@;lKZ^9y4I5ep_d|<$5Oy-W3`Wt&*>v6)3 zzMiF^_Z|D>;sb2%#w~sJ5gDk&vfW0fr9#+Z@$1483;eb8 zSiaS4>k#G0vAkGB;G!+WtQBE- z@=R;VAbp2^TUo%AVxMWVNya_G|uiX-;Z_rfbGZ(zN0=q#O1tk~ep-Y7$U$AQirz(KpbqU-c4QEx(v z80ILyvu>+UmU5vM_=ty>duNG|)H8Rybaq&SPU>o0^vh zz(OB&s|l~O7nolPCTn8CfIdPd*cQjN0|(NsmfWr_eZ7H^+od%e3ym&3XcNV;0W+%?yRNez}w zD~MItXs9e;xH<5splCa+>+*~sn3QG&S)C_`F4(G8{IAt1_m8GifE$J5#ug4dT9k9i zFyHSog<_m9*Cy+=U8yn=gM8E9$PcYX*nwSH`l<-#>W=$Co(s?&#IBS9YDlLf&v8~i z3x-^cbdR<;GHzXUL24yttrXCS1BM(|OPFk%t4!nEZ#r#MjkBhpUD|MgFK{9BLPg0< zaoc=Ik`r*ZRy##8sxtDdgZY4;i7Y;W2HihQ#3wl@T;fUOw8$Oc_)ub@KL(BGx18G{`D~Hl@D8rfTC=uvTa|tQX2cQi1X4s&2jZ zw4mvv3CV_axkr)!TX1CwnXX`>4;QuyatyBm8Es)*g;}k5z)qKS&h4y}>AJg9we z&QXuX=>pUvtvj}%RJFkG%C6QGM)e||BPhkb{vc1sR(VlR4muZG-Tj8*H#%Nb6lVO=Xv%Iq#2f$0qU#6NOB};5 zU6`h0PtgL7a9KHaw$L{;4kKte9G9=y>NT>t9^#iq)ouuC$qk$Sw1!IsI7Y%3OURvR z*{od#R$;>`_^6+l)MZh~FO43BB>JUDo;2(=hR^=Ypv9M1&ZOrotn5{65fOCUaCraG zNi%}~xaIP%!?tt$sokgit{Xv9Pvx@l)D9>UqbGJWEjq?H2$M0Q46_hk16vhT@MgW z^jW_e2-gn^l^5&OFcKCM7&>O^;=cHlnRiKwoy}1G(OQUR!w{aP^~2~Yc7t%MkFWN4 znrWB#B#ONjX2#_tYho1F(*zqu0lO%yJMWTuo~bm36$ch{^v#_BS3d=~WI8qd0JHiPl}~Pl>blEo*|@;gv5Is#K1bVEjh8ad@+G znb}?bngH0|&efdZ?a@=?2t8@nDLVLR>T#TudVlIqE+R;g){q`qTG`#DQinQ!&+G|u z67Fi(t}jTf^IB4-aL|-!dP(}UC{52flP<5BlLZ+)OfY|dRQh&rx56FfIKRotepF6! zp4+WMh1xHIcm~T0=rT)8=K!%Nxno?rVLPxWFOJ_B_>vq!h>e%PWi?V~pG-gJ>)|jp z`*QkB2B{JE3n~?sUKoChQmUo;5GG9tv|MY&mia)cn4}1a0=^eIvgtr7ZkgU9;FI-I zX?zx7EQn<>@3Q?z$EWM{NSbpixbwFEUbbodTA0~(d>9oLJLF?6vN`N={Z zt_(>_XIF;g`4Y8#b8U}&G-a~mEKr>U$CXD4_C;@w6!lt-gr7sIo~xNdbrL`9e4MtE zI<|co^3?sQ(=w+t5ZWV*MrDXzZLeH6ioeXpC#M(2SV4xHYflN9%}BASSF25#hiSJ^ zIfYcFk3u)gHqaZ|mz+{2q2&*vO5EAYQdQy_w(f|iInIcQPV;aArBn?BDyUTL+f^vG zZ)cf)l4O{qlrAE&$Hv?i99r5iyYxmb>s-AEjG9%jvZT{vr21!f&kS)JS09-LQuaAI zWzeSV5(B#J7~x3UT?D1wf9YE}PfF0s-g@A1T)6dHnj5F{Aq)oZ$RNz>uIBGMTkROb zAf21nVU?YuVGC4pWG;GqVq+Tz^%s`7bmkaFQSKH9qwwi2fYT*e7*R^S=W+^^ z^&>@Ao4wwJczXZQ+HSvr5eVe$(%b7@82DLvzpPrvH^-KXUc1Dhp%BLf)!i1}mHu=K z{QWIj(9{lvvX!;>po28R&vE>ZiEy{pDERqlZ+nva>kKyu@O`qGFb5Z+lQ1cm;)>eN z#IE!S)>?>@?8RoYtB2e=_P67eVeY4uZk=JS>jf8LmvNgN*RXJhT-o)oA>l$JZX0(T z^q>>E?$#;=>M(5pYBR_zeq!yHxtN}^F_&AZ+hH3beITymaHZE}pbm}fuIIUv(kxv? zZNwEo?dKYH9z0L42*!*rFOpGwV3D2%?NY&Vsy5Qb`h0vQ zBJqQ~B(`3r*}j1sgY+yusV3pP4Cj3kw+1(Kd8*K8eYi|( zG==sb6`uN}=I7Ew#XI|q6O~tvxym=83S*=8LxiFU+u$=D$g5zc8Yhdmst|6y1ctMd zzY{g<=V}xCU-MflYwz0i+yD8l`#yW$fBkpUUAGd`u_tQ}*2Z7_%kMn%uCd$iTfcw& zzFS`0byc!ed8jt_;u}xDtMZ{U_m6$x#dq`!z}uw-|4It*m#K3*mp8wyx5@{C0wfBk zx~sLZ{bKps_i@SYeJ}65xb_3t?gFXS?gcK{eOKi_a~JJOe{HAVbUuTdntk=(qWWD_ z|F3z~Ik~J5ncpVY0rZe+t@O-EQ*Tr0=jnz3iy$@pSKx6UJpOwgkE^A+(trhXkM+(f zyG(GJ>9D<7jZ|>~VEzK$Q}3#L79OAN=YdraG?M|AmaIyeI4uo@9Zb9H#p17yVXhKx?um1@DH3*@_LYop*0~E4T;r7ygu` zDhV`LiyZQSAoS2N0X@(Z`H`GkBa>g=7GPjl%x_a5<`Rg+ip{@(`syho^=f^l^w4IJW-38QM1^j4sxeo4Cu!(UxhmdOL1ch#PfnbB@@&vaE7 zH=Dlg+SNktQS9h)lzdX+E%Ss&ZUMw)a*lnD4vwX_5 zPEpn?6AsvP$L7uA{g%HPgnLW;<6*K}A@hY4GrQ?LmOd{_U^OCO09R0X`M)7ZD9upy z?}e08mqnMldNLO-34Wrpn+&6 z<6+2Mq!d-;`STRP)l?S?3UF-)=(5{XWQl`MX-LRA=kevJBEbJlVLuXp3scP0m35oO zOLUMCq|HJ@*$aZdI7QZFW)791iU_M-Rb=!QT8l~WkE(@+x*X@iCb)~rQZefZGGi5>`Wm%^W`3(odQL!z~cM0!uaLZeK3S1Br z#=yl3vAfj?ZbYgOJhX6=yWxYVz5*K-lgK^3L9VIZ!LoD)xVtfzMaF3{R+;u$Kw9IL zhNW`c8EYtaJO-QBxh{&i$RrmTV9bvDXP%CWLlC+!)k?>xR=f6su&IK|?LFbats>;v ztt{DIiwjGmtM{5gkY=iSj%Ci07unP%|9D83QZ2?@jI+V~zwi zEJO1w>@E=4l;(jU>bIBjuZ;1c4K)dwmu?O}fJ<^SW*(3i35%YyZ#%nOuXqP&J8Il`CK zN*2knmF?G;C18T^AP2qP>xWxlK&4uPrP43(HGY0OK`)NgsU&~yPjzt{xn5$Tt~Tv@_m%Olwrm^ zt`m>H=Ks%A)HbzK?b8=#>zRtayt?ko96!}RTiJf`S08I#Y1}o(^rgK2(ihFed5XRy z`Cn7?*;exZVd%wQ68_8lt@4W$&HodW9b%6`fL%F8HvuHUzkzuGVU*Hfw#;f;!T2RS5*`X_w0mHeLzUA1i=MHqOJawA3a zUTff2DX*ny{=bRxM#}Rk-%q)g@=VHABNoa3gOqD2q5bLuwg2ZSnvYuZT9e_Yu;J(Y zGvTDhP4B8aUjAxNjiNCK_@};p1w}eQb3$VvoX{HC%KjJMms3Pv^Zz$}xrv`D8V{A% zQQkp$8)Yl`tN&h1c^Tyf%D<=l0p(qkcT>bq>rit22g>hKa`~T3-j<9tn(N7q)?6~( znrkPO`i@pTNt%t#WUAhp)^F#MvANb-Qu)PGtCgdtudCGVNKPg zjaI9fNi+_vcCw?{YSrt_cB|4jlZ?OQ7eBeaI(DxK_R$`}-jGzL$6ECVlU+Zy@CToG z;1j?9+83=|H&MO5cEca_*Q}4Vrf=+d{HCNc*O{jImF64zJ{of}ob35Pe|Ps!>65Cf z5xw@Jr)ui&e$5tz^)vV2_)lsDnQt9`pbp60e z=aR}?yEWFB-n3sPn@KX=Xt$=C)5$b*vD2Dhowyq9WM{KpXMQGi-e}f&^&V({0@~Gq zwAYiVxz^ltz1eCfS2tRXdYvUS-DI`2#HQKkOn0Ixmo^)%Ijt|2(wwM20QCn>T{n>S z`DC0my%`qwnRG?B{RdN8uT8BfrueBcQ6b0r+e|vmiG*Le$oUUC$(WF10^#dt%DOes z+tFx>o}_IwH(QeiI*4dA^&uE^KA8XtfR2*!3^cur8_A`JGCeK&A`_@~nkMNvF%iCH zlj%nX_T+jp7Iox?x(j@qb3`|@4`Bhi6`*C9!W;En(@8w=Oo0YcHW=2H$TnKLnFCoB z>sNu1BrZTuW8e|g=3tn$6Z9i@vbzPwcxyFX+z_$Ve^1i1gf?`!GS_NwMtze z_+9_x34zYHXd-?qc_>d+GYa=61pLTK?Otl<6A`9MuHt@IEPOdO9v}A!$1PWr<^T!Y25@L7KRFhgT zoJLcaC{3UzYi^6KvUaEJ>5sIk0MAsw&`9sN&Iv3Gl`~TGyYaVHGYW>Gxm>C0s|=+O z#P$jrT2Gp&PV4bZ7j$u^mrW<6oULh(OLK^MCwW@4QE!2WFz?bCUEFE+j%K50u)C^X zfQoVa_WazhYNs@nYiT6LoUM8cu|~T!P7T)sTcg?D zD=b+}hEQ+5X0MJL?QxG=@FdcaPl&cVnLMiTdbB{>-5qPYN2p!@3LfFPRt1f83fN@Q zx8}YXn}2=2gpmlE&-9%ZUj55SyFS)vwd<8>BL!+1seJSFZdMxNdR6GOpjnF6if7nI~#sR($<8JVP=sTSR3ix~td_fI6T(}K_P zTF@J;=9gfc!WuOZyq8onnguN0AjKth$!XpU%GC2N^WsSgb6lIc zpY-yRPM31TgRl|M1Ss{6#I=*)J_a4v-KO$Zc9JV2J?BPpV+jArGtQJ7GKZ1#W7++r zx4C#~QgFM?+j4x*>rrk*3Lq6zskO_!TFYkXl@^KWp1J1y^s~Jt(rtd`mPfEs=BCU< zlm+X&EIdX-VGpmcS>H)+*)#pX1h}Mrnxvnfonus(>z-$4pZ6gMR_}%HB&)jvkjdWYiHpJfzFeOg0va^pU35O}SZMB%&PmbOSfF*gWnddue3qHX9qs?#xPNme}3|6H?&aAo$s+ zCqrR%4;#0QmWFlC$L6qHT0iLx)F;_n+lK9n0Nc-%O+AMbK~%=xlY3QXFN267uy3z6(^qrQJG^LS5vHM&FE{i; z^;R!<6Me;{6gCt6*~R`t`12CQC9x7q11m-~jg^QF+GLNtsTIb;+dB=S8kdkv!C%F& zY(&lQHCR^Xs2BNH(Q!qLJ93~MQT{}==&u6%*Hg^E*bS4&$)tjuZ@T_O5$LZ%2+j!7 zSl~;_7a2e^NXoa5Nb;x2k3KFAY-B_Ou4_67B6H-_gep5H|JOl5k4ac;h`@1t>yn+|LLrk+oFoOUCxXKBXKckGiV2zGP#f9bf7C?ZY} z+QEcWy|=a8@)jDqd;n*lGN}o_DIhV~oO4Tu`TkhGVQnn5W@QG-Ld0a-@D^N#*v|4M z(Lph~$vG@Y80`TCd=x|Pi~|CX<%KVdjpFIxQ$HJ)zs-3etNq4bW^J)CDzdWPi%|a~ zSoT`cNZ;24C~5@(U;a0y{Tb-Vo-|ywPfLR9Ui@*^eGU&VzfiC#EJxE2?S`f zXkKQkdoCU9WE_FMmIMtEH1H(mzf@?2L^zbA+jW!+QLH7@S+J16DT}T-C2`4GX*LO$ zv*erS9fz~Y9x&Q^t4wc*1^axUT0P9D9vuP?=Cl$UWK(aro;pkVU=yL>%Y?*N%Qp)= z2QXe7IuPs8C&r*dq9ke`pl>xH&d4_#%qTb(Sn+-oNQ%OEhPa!6+BbmN$0NyVp_^o+>Z@+{auk$oT32!xsz^Oi5=F{*kD`)#S!1@K2go#oDL5|?h6pox-lOTN-cI+d zcd5U%qcc<(D&stY4vYIbG?*FSW}3{Ja@D3OKDugS(JPW?2~5UVeqK|dEmmN0^vXAM zRE4*mJSFHmdR4O+oreb2FvFaDKIFM#gz#1-$B?R!&i0Csa4w3|B`=u((%Z@-86olo zdkf=iYe+kUV%;%}&U}J2q>_t(>w@egB))S*Rf*kcwqc`X$xBARI81iu1*y!zeDXEt zoug{bLCwh5q9Q+<7ES46d`e@O7dLF;lMM_UM^c?^>xZF;+W z*L_VaaM;KZ@w|rDj?O2k<6(4hb6MDO;fnK}#BUUh7)`&paehISMFf2VVK}rR95iyC zTWP4!vl~qX#&adrgPtR;FLw9Toug{Mt}cxdc*Fc0D$M8^52@~gBMVr?`Yx=(Z6EMr z1vH-!4fmVGaLDq(zb^_lera?C=fjR)x8*xc@T1r#{L%#~xDa*xx=h^ZvxSb~msoHk zIEH6Ml00LU@tH#JP;^JpYetxj_6+Y`?f|J?tqEWlo6>?YN)N6OGaNd30F7s|jHvMx zlLS~&?Q^wHFd)E+*OulTJUtw09Nu@7G^1)m7rm4N5fnc9$^{E#c`GvwzsAd3?m~JI zhF6knF1U$HkqUrqZ-Mr}pP6R*WJpg^B8;Lp&njl=ePpwE0)GN;A=SY|VA&3l*x+Zy z(2Dd7$8zvk`&w^%gY5O;LNf-T4~B9s)dQnwR*8VaoT}8&0St=ymUGc8D0ef(eN;uO z@g~H2DIR8zn`twFzF>&#i058yf%?pf(cDfi*N}Rc8SmWAdVFRk^bF5H3%Q~dWf^(o z*!Dx8Sz-FS|1Qq9;}fE#|5RY~UkX(;8w*k59Bzzu_uM?Vr$qOz4N9Oh3NEkWYs|dH z7YkJ@$f#WkmrI8$tHU^i!|GpS>DimPp;iCp=(%(*yM%2RHb1gFWzNa?(==X)ooj6KFY5QFi{J#`Q)9L{`78&DO#P_x2+~+T#!&Arr0MscIdXx^xWc@7E<)e zSveHtmkyXfHa7>P07?inNt6Ky(@YwaMw*ii?nd(P$u3^h%L#so%&*O9JJ2bmQG9Jd z7|ns1gQ-Mm;$W9JvNFBrYC*?HC7Zg6g_3%nM30wWdJrVa$v8}9^1qx;hl{pKBHQIO zPRtVAcvI4JjQS#$NOdh_TY6tYCXs2}DQrQJvq5l~hxux;(Bqo zJyipVQL-bk^VxkxTPtT$qh%ZJ&Zp*&W~;?!eAfwDHvv;5GYxMWwPq}Bd*k2H-uTHv z6|Wpi%Z-TRO!FFvyy~OTo7FPu?rW3G!O-qX6Oit>(hyQ z1iKMY2@LoQZa@pZs3^D$PenW60wTDtt^P+v7$VmPr|%C+{65moC~2wI_DL7J zjYBI=}87&h>--_qKHc-B<5{OlZtcF4)?#b=#t`mkLXdm4Xsm`>O_)HZDL{VWXm z7qd{)Rhamyk0xTK1CbvxaPVYGs0qHX6P%hRkH{ zWW$X$ExUIl4$c3BV3!nx2+OAvCsb%AHuRHC%0#t%f`DxssE}mi>JJHKnI^d)uv^C+ zBw2`(lnrQkJXAGGY`^w$Ey+$4N&PKwyS*(tXRXb`4MTSA!vQQ&C*%GfC(ZpL;r>$+ z?nh$%+gggbpJ&9J&gEk7Ot+-W0v#`+*IP@zpQmlN^=s^$uG@(%S!@y3A%}8d`16b~ zB$AJ@Zu5DIoGX=!{e94=;ju#C|YZxpvG&QsLrqHwC0W;D!V zI^6mg2ndoi_CY^PRz|X!CU{aP+}18qf_AZYrW}SDsdACIHlRC|zCWk3X*1IN;Fvpz zK3P!l-WwbrCXSJ-7H-WS{>~;vAwA=;9(Hqkv$HdK?YTxxrFni*Fu75%1z7981h1RO zTNE~vfpBL$E}10m;KWXrC=e&s@TslhR$(M-QMqAxLZ!OBqNWtOt;%R70>C;8bt@~k zq`rP#LdDvlFo_bOsktfd53hEjL(GWWwFsM>uc6G(1gD{oE)fAW?XJJ~N3deSdHEVSi^xWL$Yn%AH>wHgDjCC!W0Vl*O;R_`74*jeY06 z&&ZsWY*oGPu7hXGleb2S)4lg|8_wZNTb4u5x_g>$<{_v}EjrBok#J@-x zl1tZxoGZO9pXAd)8Q$&EV#E(n;_I&E)Zd>Un?I!W)5%%{W}NaS{R_$aVvfgsZ*ywD z?2x2Ak+k0>?YB$P@`76*v)xhHY~~%5Ec)G+6tuRC_0qb(!zi!-)kcSy=h&so8( zd%#%@Q-?hyOui&a_1m-!v0fqXcm>$m&|&9KYhDPs`y(ycDGB+if$5Y~?(yL&%H0<8 zaYd&X^Xbhk59i=3iQ81xz&!T55qzw`Z`#G=XObYuau#mQ!O~)cSk?(gkcaayp_Z={e?tq0&Lw`eRmdF+8>>G zc}C)JC5_s6D&S=Eyz|#+SsoeJ;XL5OKJ+M;7vp<|lg3$Qht|%bj_C4>Tp&>{FG=2+ z^Lwn>Bz!xu*Oe10!skRcOMqExsRwLBf7|^g5OfKWI2F|6&a9f$zB0GeFmu?>>QIy8 zv$Lwn*;~psnLvqY(N`>%Vn3{TY1Y{o$`AU2a?-C^9yZ^(UnC@Mp!I9+wt39YtfO1T z(87F(M|psdmu3jx?YEz=U(LFlf6!5|tYsC#UNc#pPgdbU+jv;A`Mn7Sou=z6a+}>~ z7x5b2%to-rGr?_Ri^AL1vW}d`0vD7GTsg7lDCE^zBOkyzv;N`c?qReg))Q8sWFfW~ zaRJVFh>4k_h*u*fb_d0|TczdFF*7mtAR%U$R%@$!^DEK{Mk|J$gVz8aBAPxdDW8Vr|M%om`{Fk@=G7Ar>ns>P%LS}>;0ZQ6U;8E5 zW|k;8C63F7UyTuxu;=#c8^6!$ImQBG67y&MPDR6lsm5w{O)@ys$}zl@P_m^Fue1q- z#cDD*pAZG>SKG{+DUDrS%fPRg8&Fm7Mj&d7qh6uuK^6P=s$##UG4sO~D=p{1A`_fU z_=DhLvQhR!girZ-k-W3I2Y%Cm?{-||hU{9)58K4az%f0{0GRWfwIQ?0q8D2P&G`2? zkq{km^5POQ0;IR%MHy!+pdCVxcf7#TbN*`PI}2AkKbBT! zwelj9-Nnc%7E$w~_Hj9$SRd!X`iACC96FBd4l%2-VBIz~D<{ZbID4^MnzZtm4~)m)uI1Bxv3iJ4qqZIaaAMv|%}OtBjEQmKhM z4Pop*k&@_ITZge@du)zj%haZ$+yf_>tqlHYy;)QAQM}E>5ML&A?a(8e)WogHqcC6N zCsPPTe0iUZCoedx(gCm3+m<5ys=k|-l9Qv@ietH?zA4LTfb6Ok&N&ro{y$X&Q+KSOn>lJ;}mQ zXet-<>Ivf5Cp8lzh#P5w%z4=A1fY0WV70MW2A`M)w@my$^fA9QLzS8qMIlfD?_Ioe z$%Vb9>9G~896hZgvtnX;Ufil0Pp0~fCg!>B&`;la73g2BWu!IhH8E}4 z#Ny`L;w%;)N#I^zz@ee`WLDpU^wiQYVg4(hxE-Ff(4t%qV{R0mqyT|V>uX0_|` zKJ?(HKJ)a~=r{jc*3~sL<9>E6*R#Qs*62gd{IC07{@Fo4^jBBcn%Zk$%VmjvuR87Y zHP3#IHcyeXbm)ZB2Twcc)Yp;g^H;v``P_1pEsqW zefhfzPV=~ut48B(;AZeAa3lB)xEN5a{UTx9X!$KewYP{XE?sp}&qI z4}Eg}eID=RdLGdAZQvZBetZ`QpL_1*_hUgi@1oyIqyFtpLFMiZ)ECbIr+^`#c2IlV z0n`q^1L}vHfbRbV90}AGqC;)*IH0_gXD?8jsJu>S%hM|XB;@bU)!(8?^r{a;a~0@w z)6WIZ0%{BW)>VC?&yMSzUVq)3Iu+5L=7B@WTje|xJPqj6)^7p&+_--K3pgFT9-IaA z`SJZgdYl%O(eB<{wRO5KkB6?6K=nBSG=TV4y!;OEUhp3O_j;}u0`ZZ?XfN2D_Dz>B zew0Rf5fGn_fQ!M$fMngjdT3040_eGD))*Ggig(+!Tha5a(UxkLX9Lwm?Rgov5~x1< zeJN1A)Q+D9dM5ey2%!4x0*Yu&-&1?5-n}Vk90%F(&-^|PRKYdi2jFYq^Wd}KbN;uU z3Cn@n^9kT!@b@Si#4o)-Ja-Uy0eCrhDNudB3_c1j0ha@{vD#eqRvYX6bQ{k0ce?yT z$ZIut2@v0o0=47Uf#~=uxWePx{_nXgUu~fNQoo7cG-jRxp5(9MyOp3H{1eb~@t98ZZP-1g8SsdlfhZ=$Yv31r@NR<%>s;^-%pT0Fp_=9&hI= zxpf}+FnAxB?HJ3qPrCn=*Neb$Ky*xEB5uQV0^ACI2R48kxxXEl$M5}s+CLzlfBx@Q zV_f6>*+9Ji3~(l>dz{7f_23Oa_tg&Tz#blw8~cFG9pkO&ipclH;MG7f=*>X%NFTn= zU*E`8_umObn`FPnI0mQn8F-P0cvbhsuX?6&D;x~OlUsu>(-)6bFd?T+UqGmv`FXadIAtlqD3?X$Zio-AK4IFqrD_kRszXi@w<5G zZ15Iv8u%Ab^M9YsRkGzsk0){6TJ0se#J{5JSnviQ+RpHh&eHF*z&Swl-d}X(+e>3l zw5$bT4kvnaUv$qEU140NuUkU~t52)oML=@!C_xrJ= z-wX7num`{Q1{y2Jfm6Y1@GEd5_#g0N@E_p6{NI1%dOeWd(AXF4(sf&FtcVvSPhJK7 z7pQE}^aF6UhxEk;@C)z^Abp~-vL$pCwdY**eNo=J_ef9y>MQB7Cj;ps@$(V>Z`DhG zOLppcSzeoae;4xH4~REJ!(+g{K>e$GF9YHc=|{=0mw=ao7XZoCcXD4167Y0f=8hoy61m{M-GVFJE#-ZLj*Puhs8?57qC2`XKbj zT$ZmgWj_g`;TW(I{1bR;3cB|+@N^*h+tsnv^K|`H<`aS1UOXWE{Cw~nPzBEd&-Bn3 zTm|N`{5{A|GFat^2VM@u>l*j!1O2VB_+p?jq46-+Zsq$|}ID}eeV&?VZ!Z(Zl2e97Kkpz*IVCHF;x>aTIGI;-v)?~(Mk4xRDVJ3tG`2==w7=0 zb$>3)SN%24HQtW|k};C;Y6J1UWKYlm>Jwou$`Ado@t1CY@%Xvm4M4oE>+67cLHFMZ z)c=nFj{>`Zhs+Y9zZZn|R~zgHbUoT*fa^*RwU7Rm{5u9H?IVG7z--G_`gHkw@V9JC zjX}vm$yb#T$`3MFe;*4(gXnx1*cEIJ4e9dL2KrlLUl9Kb;&;hl@qUoI;)fRkrQe)- zhj-HDtNxNV;_E{}9h?i+f-}I`Kz%Nm7@n#9Rque1Z>QIM`A3nL+FWBz{Psp5nIlO4 z=$`0#lm9)J^%pOT|DOOP|JB}t^pWh(s)zbRV^V!Fm*uPdmjjhAIyC-Y4b;~!1*?Jd zpm^ey-~=$2UoUHPqX*lE9qbfUi(gz+Eb zoa#6PB=21Q&q0EMNS882Bgf6!1xK zCHPnHKF|Q~1)}Lv@NqDgK_4(J>gkE za$kBz<>@LqjskinyJ#-U*H}IR$o7y7Ivbn|G!7(p#dEI*lEZHU;)}-v>HZ3MEC}Pe z)2ry;4fF!lU-eeoE8juz3UC|GJn z;0xe#@Nw{Aps}d3KMO7cTT=ecyuY~+tmK+g{8q>c7zXLx6{{_C|@hz@;HU`AYfj*6?R%Pj#_`U+fyLs%x zJ;?~o5!L|ps6L(0l%_e|9%`4v!I3~R zKJbxvyAICr*K@gk5J=W*JnRZ2S42lT@1oyIw-->G^m?d0_Xg^VXM>Z$E5N;ABT!rX z8vGQfAFc!UfxAFIcrsAGNG?4NC@=!o>s+;Ux-Q}ewcAs{Q^1AbLqPm2ycfI&yc>)F$)5wkZ1_1}$9(zEBR}b=Bf%x$ zW8kAebi5ykrVGGjK=NCBtT8OvAil`w-^t%wt1YEl#gpPu(R(?#*yF=o*8|n-)8JAN z_(C$U6S*Y5R-G%L*CQ<()Rr#=Rq$Q#@8HYeO7KZ=1^5iO27CiZo~S>c2o42*kFr7a z>jjbp>ig$|mw}gn&w(!i$y&AVM}YX}5-ub15FCPzH<$p_82Yr1Czr|mAuL8ET{N?0vEYLVpz25`=6`T!*J>JPxvP=B%At0WX z?Co@n<=Y`$f5{y2pLjrYOcM*Ykn1hrX7Drc3vey>w*@`?4&{pmA)kN#?^a`cZ{C-D zc@cOvcndfiycN6&oC;0{ZvgKA(mlI-NN$M!%^l;d=!(c!a_1zVws|8EZD)YB9->L~ zybHVyNcZSH@#of}OJhVldL|HUmw-=zi#*=XwE-kIBug#__Xl07_Y1)w5I>y@-VV+N z>Pxj>XfMgO3qX+72k=|(&$b_T<{hC(_Z8jC^JOQ0??L{(K;vEQcrcux^jFC>$uZF*8Ll>bBA9KT2U^?F zrM#s(bbSSQ70`Hok;jXe=wwiaDM@2X#(0@Nm_0MVzm5lycIuLZiV=LZ6fThXRA+gj~)40*oUg`s)P7)Yqgj9QGF=7bbT{;3pfLa7U>7kCH-{{5WW52{-7)0 zUeZgVL$tjPh_=vPqPZW;1zllWrmtH|20sg${~3rUJ^`)(BOV{*`eE=P@JVnf*aM{L zYWKU9Y|&U*4gLj4o?H)Z1V01+39bg;2mcLj2EPH4E#jHS``=q@tQ<@Jk{gmA*MZ-H zAAzgDDENQi-+^fQ6;OJ~$isnX++4bf+Hs?I7`@>x2h)AB=k`D?y>wfjE- zUB3Xn3W7ZP7{4zCp8#J3p9i8-byJ-l3G(^3`#WF0#_<6_`KsMzL#Y1+^}F~%S3Mg7 zb6LLl?_dwnaJ0u!T&0%+By*kyB!5JIyE?Xdp02-Stj4;q96TSa0?z~*d(ZOFSbU+! zT$Zmfue?=`ctHFvUKb6L1u8T2#Yy~DAIx?6l6g-7vdP{I-U7t?uLm0c;(e8UCeZV_ zF29dF)%N0r72r^hCvgo>|LC{$&X$(HCwZvddx6G($Xk5)CZKw%&XPmY*}6&w=)T%! zKk#s{3)s@}w>NpH-PH!dOTbHk_(A+9ew5v!-@3mVY-#=VelJkn1+{5t=O^-8P(SFt z@DvZ}L#3O`@>PG0`2nCYuXY#I4w5;8Ks>Lj`apfLrRAslUwojtivNVSg0}(j{^>yF zh3hcC^=x182=Hj|DDaS3BH#Yvd*vy;Dmf>ar?ya=tn|>|x-S{1v^xXQFx#?~K3%@* zFWoC0DES-8P`UZ?C3^++*~5V9zAKn54e9d5e|vc-U-kRTz|%n(1LA*;gX6$zp!a86 zW;%VkeAQp$PduRUe=blTtIvfugEN7~z3vO@C$)V*I`2+?=gU8myfg+hw%!0#<{BX0 z6Ca)d)`B+yJ)6t=i}#iT$y{BZ=OLXG^wP8WEq(X`unNp&`D*`AzS{p);MG8U@M0kS zr|XNrkjGq?uez@Q;(zg)PzBEcY7g98@L4B(_o)69j8tdVD4!=JH-UH^ceDS~Rk0ZcSz~$i6K;^s}ywhLb z#r5Oh6JRdOSO3fYm;9F=kbaSj4|+(~m0$o!MhSCSzUr@WCmICF8u6jZIR>bF{T2<+ z1bRM~S@C?$Lwt8G5Fdz6jr$7d1rM1e#B-{5ufM9@)dso_d59-h z1L;CtB?FHG$Abfb$`AR>wtTf;FHqly_E-O_UXpi`f0F%bYw?40vHC)?c&_EY>Kyv_ z3H)9M#QVcQZG9#<3rHq4zylec49?1la%PYZ_l)p3Y zZ!T1>c(fmg)=vP@bp^N-eAr_>SGD6sK<}h6o3cCMEAilNpx0mfxE>Dn1=oS=!H>ZY z!S}$`;NQTnz!*^fM;?#j+OEtn?jA$hJT#V{15O361!|vr!7bnh@CSd@?^}VMT>^sq zm8>}sDBoV7da1m2G^L-X+e5siwip27u?xZb!MWh=Kz;N!AYT6n5(ZgC_&Ehv<+zkgcP~RLyH-gi^>Ha#*^({bS=MgCsmC^3rT(xz&E(bu<(LlODeDVR%0B-~D z0PpcQkL$(YA~0Ki&etnlzVebS{$g+>Sf9d2_$_(@O_%ZeQlK%QJ{Hf4FY@_!^7qzg zON}k@X?fC>CdG_}x8`Au8AT+)Jyd0>VKMzzNwebkJ1bh^zjlT}`Oz(HX z6J=@A<*y*G*qI(VS*2cmt697IycL+z|bnJH}hl6_M{t zz>vS5$@MHCT3!#%0B;0u0`CIqpZ$UQM(wk;=#p%EHBkBD$&Z6e!G}B=TtDC;`S>Yt zf6%4&dJ%XzkQ_PBl;wcnfl^&+mKQ+0Vf(0J1Ov+YO80O8>tX+AHymww*q@AOy^ zoyUNc;0O?8^+)-Ana3x&UIHXHzX)bKR(Iu{3V2Kb4&&Z4!1I8{jC8_(fv*9TrE4hn z8~pwjI2IJ;)yw_efXZvt7OlpJ#_m(VbAj4L#5Z8ZQ^fI)B~SPjIZ8rLuNe`^fsdEmi=`7OTO8gywKO2>$QRR33jHQ+Ts zbe!O!`zHg@tn_N9CxER*m+}=qizbyPT11!17hVZ;@3kP%t9LYZ)xK)8t$y>zjM6-{4bDhSP52uEupKZJ?EHS{tXdpc%`K5aFdpwz|WSRI|xRfm^vLJm?(cm0k~NP9s{gA%=zq1j+J6X$CtnTpEM0!OUE7r# zo~O$f-yaGN0ixp=@Ki7Wj`q+!wa?Q%^nS=|bFS&~#d8|#k^|zyfA)A5*XII_LH$Bg)wh;PSJn=jrn?#w#|{nZZo9r{4yLeMke2%zV4S-$GO z5{UN&@wnPv?I8Y_yg303f*_CQvi#l2SMo>vr}lp`BWdDi>bpLHY`g>>a zD6lJd$SfiHcLTjZ{HHcho|3;o<{iav$-tE!`dc#SX+YydT5Fa+kZ{5{A|WlQ#H9IOJe0jfZ4q2IbEK71h%9bx?M%I{r3Cw-ny zlkR`<{~%D^RA1Hal|c6d$w0|`VGU6G%w_#mzS>yhO8qV#lb(CChj>xE_d4))pl5Sg z{@&yllWMo(;|f9|Z3Kb6NiG z9x9>4YMGBB6rtN#xG%Ypbh=$NDVeGC`?E5VUKGD^SavV7HF zj#p7!{8hszSkHy1FQw&|8?MP;PK#5pcgzA zJY<#-{kwr)5bCcsQ2hsi_)+6s;~`un8;QRMfchZFKehF81u9SD zP;`A3TmeeUACBCA?~gWCrlZM+b{+V)y>nkQ{jBr*hV8!(^-aW7mE4aWyl=g>S?%z@ zeLbrh>%QK1lU*;#x4GqcQ{TK38;zAyeT!Cc(a&%8q50QMH@erYy2U;GXxW=98;w;{ zeGAt%*7fzRTJ`A!N zIoUTkc5B}bYAKOpIg7IChT3?B(t4n9y0HkFX^p;B<9g87wQi!Zga?oW)$3MGItr=D z%E`V35KVo@8$Ij#c(T|L$NLkFd3tBOu?^+uJ*rAv1jK>V_0Y5CCX zWcIDX_8af(8oQ-$M>4e@uohWK@$077_KJEvfa}&aR$2l4Lje?dqNPzEbAx~2vw5PV zna+^j(P_iLz5CGcE-9>1RB+v@e=8*O_k9cXJ{>&Ww}AH`alG-EwbnH2G_FnzeIJU0 zcv#RVRXGWHDvD-weJtu-b+Y8~?vCMIxXDWFGu~WT+~GI$Em+q$k^fJ-kxmuYZtB~W z8}uwa%@50le=T3NaMF4y@+is%$&U0dzeD;gdAz%wYUK$NdDDIKSE>Qa$m?3gC?u77 z%yHRt-+rs88w47cuG4*GxNfCJZHg0(-8_jWCNkuqyx}Sp-cZe^`*w{>Fg^~F!|uYV zJ@iyDk-xK1i@>v_Hr$|S<#b~qokU^Ox=Z7i&e8Z?=n7vo*+nPa?F84vjTcSnraZ39u=sTgc1s50w-juYx8Cyc505QgW#2V%&Do`LURH z!rxLO&3KxKyYT8#N2UF%(oQTMt>1Jc{j%>q_v3=X!E*nnDzG>2X}rI&FdR@&hs~}TKux}zWDv0e*X)@hkpyQvLs#?b??9Oo>kq$KNuhD`9W>} z?=+>@K#F7US=IIad&j!Z-~X!I^PXs^ac;CB>LQb_;k(DWYS|R;jJm6h@kq&T($CAH zdDTV~T_1JzQR>TnaQ9gE4-WrsCR4pqPhP42chp_0-k^V`dAV*c4^Y~9caC+PoqcuK z3i@o+-Ovk->bMGe4r#wg+An0&ektmzF+PVPNb8@97VvKrai?o&I(m42BdRqTk-t>+ zsK4H5^wfqLQ}$lh(8j1Ievt&zc6$lgxzvsNbhOP-Lx1sNZPLFr9W8X3RvG&B`{KLX z_;kFEja0WxX5y#w`WyX5nk&4!-aj67J)e4gpL%^STdyxiGxf#Q{-H)KiW);x(e8DA z)Em|Qs_yhRYV~S0T#VF4y}!SQ+CrL7wvo2u%{_V3Qp9gJs;Ztflt^q0kty|@sXxRQ z=(DdnPy@8a)=w0fOKmhCQ4y&k{TsP*^P8nj+bl-4#ycdzRDDV6(awsK#wMxTxr zh_0GQCO_q7zxt_HeJbj)e-|r>b?PFjZ{0E-^>A|&ti+p3{G0CWos?QFRjbvZ0!pe4 z7=i39lU(-I`#c@?JW1K#FdpR{@kabo4fe8LsNGZAZC`;ZXy2~iil&`wa5{JTt%hW5 z_2OSwby|HPwR1_RRdrLeohoFniD zo0cv-*0AGUqc7Z>iWZ5$A(#gyE*WB0r^#p;rC8hQS{rZ77yo7JQ>Q))Tz$~`)s4|I zwU^RcUB(+bS}!9y_`j;n?Wt%!32ODpXaUzaN2`XrXNmm7q!Ow0RB1YzuK`N?b(IK} zbk9&WBTIs!zDazRt%Y(6y>dsiZAfcXsBet6YYfp1t~27EsCL*B)@Dg1(w#>wCL%^K z;;vk(GIF59jR3M~4ApD)2QQ`TksdWQYv<}6A+=|Anrf!DtPZc$hnzsrKvAn$0hTIm z83syn*9{b<ao2vd4ROI!kyRzi zNHya8ET4n;* zM6eOG#0E3v&|rw4Sf9Q-r%#Kd9KPSN(_>hp7*8i{q%cZIJ?Opxhv}GpQv{AZ?IQx^nW=fx*aPaYrc?rXrh)%ZGV-e z&JvT)OMho`|6AX=KI%ST`DH7HSA1ke&p`+7A3OMrP#*R@{<6w&<%&wzin}X4`yP^b z0DXe46_@(wcakRm`rqQ|=d4%%CvvLnrl_2TpG1@5uPK>~f3>&%D4S$Le{V{?e^X`N z$k^EEUn)I=V*|gbbPtSm4ZhXdBwy#BM2l>o*EA$BFmt&g&K*_QKDFxYkTzMF9P1t( zyt6WYcx-rJ&=qk{rF(36qS8G$#xE6imwvymq(rl#7?QO=B~`d1DW~DfSw#K=gCk?3 zWHvJTr^-U=QmKp#ZVH8s`ocEyd~li)M_ZIQ8ExYPw=-wAshddB(D(L8RIOw8B2^H? z)R})LUE9hAb#`uTk&JZY14idODdDNcJeeaJ^fEnZ9NJ+@tv+&hrF(QF5IyFI{;O*o z=p7q;cX{JXMvs$)qGFxdC%x{BN~idvA7fJ5!ZKqa&3HEk8Il)-_5OtDm>G zo){P%8yguMl%nZDrh1yvMXJmOjdda#|A5v(Xqh+ zI!ARK8GxIH`4>L68ctP~`MOep!GVEHWyeMb1{hMR?5<<<4sk?zzwEpsOtjNb!2pEfI6s` z+f{XeT7>kK1;ehUgVa=QlddWE7U-VRbr1WBj#s)a1V!w-(94%eI>i{7?%Y1<;~_JT z-5kw0x?PuIfjZ+g)N;NmH!?mp->N7vGs;k1(4tGNo}(SsQ|aP*HtPwghOlsfLo8E#_L|WH&xXJli(c*BcV^ zRjZ-t#u80j7^zMnnxK(h>lvytk(_C4jK&+jmgcufMy1tKR&lqo!8l=tVhlSnJ=inq z#DyvHQLE&1WzmR)D{6hZGBdUV;+RCPsuf92N!^jj!5vJj+8r-;Rom_n-dd_;Uh0N> zS)rS+?bprD_>(yD4^j6}BJ4^H!l}xJ^0DZu^VevmUq;lQqxtxY`fF6q zzpfF%>m#GBO8qMwjCt@UoN3IIhJHiIpGVqT*Pyg-h<_JnGAtJ&Z=fSk@{^=@zb-2@ zYh3D9c6aykeS_JKxwr2@dAq#lz(aQXq_^8;*RMDrpQ3yJJ~u1qKJfA5Vb$Mk{=c^w z%;wRPOcS@F-})LGDOa`dTn|S#HBCbP%!G4OqpSahmJV#aSv1+;?f&WNOntigS4}eR zQzj)oCuL!JNR01h4~&~SV*szVy;$OM^Dl13B*45biJKZSBiznInEvz49X%Co<19|h zG^|rO&+#+ZwWU8grf9adzG=;=Xcu`}yzd&7T*nMVd^<;ro|+YGPVL0Y9nAk?Cvr?t z=XSW!VkS8@xSM@o3=GLiH=C4h!q)R9IZ9K1doQ&a=Ow=Sn37qT$V^b>xuo$7~EioMFMIx+z)$d&uH&Qx?}XUHuE)5)5sj zp1Vgcl>0dy37cW886i{A_OVk`z0at{muW^?1iRoY4a7{QQhNIhb}#i&imch$RQIZ$ zNESSm^BJw0yv|ocU`x%g7=a~LuPz+2am<8Q$>#BgGqT!w7=M&lJU{Kk!RXREOXR1f zG}G&$?rAVMep33}EQ%jDJ^ovJ44d`sucLVf9C*+nSK>vyWJS-x2R;72jKOeSH28x%tX83~r zdzaa5vcyCcGu)?r?b>U<_Oz@==8ImR|0+Twn_G<80mJqej>B*8Ihh+0XS6v~l^quT z;a{4%w);zmPxDto0{Nvi{B6;#T0W>%t3xa*TE0x9Z1y$ud&~Q7grdYIg)9G!m9ByD z$_(fp9MB*C<>{xGy(f<7+B;hu3*Fu%xGlO(A`NefG|w-b?Z7f;TnfTjmhYwtQ4kEkMLwc!_Q`wI7)RgrS8@CcpiyurS{=7Xia=D!*pft$@6h~FLuS&MFNXGHn>R;h1nZ535l zW)EahU9Gj7NruA5Cq&#CO_8<0oJAHb@$OGag-lfw*QZjL8;J~5Q^v0AS9wsVEDnT` zF?^VE35I&!krGBWay2^2EVESoTq2eojfF86VPSJv5{lwYm~;&xnIVg7OiLNpb+@AxdKV0IP0sD6{G@35S-j9*v5i<(7~wQr%tm#Q8uh{*>dZi;qL-B?mE zCuLFHoDqv5vQQpCSj|ef2fsX4l%gi)pzE}JB2UaP{f9%$@n}KcK{9TpB3p7XgcB&K#kfIe6C2$0R*saEjY6LKU#)mk zECdHZH1Z14If&aj z;&$)YF!tuIf&fzD*4xMG`L4!8!#o9mC1n~6wVI|>pC2{MfY!+G3ErAd4C5MYUPEsrKv%g zAEhi(oWWvqSq@PC1Rl+fU%ws8YShzNXi)8wEiM?3jL{-%kJNJabsxM}uuEerlQ;G} zI5rDILg)FD{g@cA`zE$mM+auJ+7NXgvR5$3SsLEskk}r#JT^o<2OPTl z<-Vp^?0Xz~KsE(-f8Qa|%Paf=XX14JFx%2zz z;=_mSzx9XT8zw>f6yJ5Ty;RJ|1EdZ9FV^c<((d)YC{VG{e~nGd(;aiO0*M;kHS88m z-TPS+C{Kukm)XcnwMA~208SI(Nx8W^FKH=d)!4@DLWx@ht5%>O)=z@4wRB&T&xP`O zm@7{nz5f3#sD{t+A$m?G{3GuPr9@S>D#fMLCly1C9z(3NC#?R<@~jTFcsI+6;^oFazLpuTsG8pvayZqc``kpl~ryf;Ctx%zaexpgI`P0N_KkP9|unLFO{iI>z^-_~9bm!VCLEjWSf z+$=B7u6TjLGK&}2Y(*{3O#XNtO{QxHUB!!SAtUn%BzCoyhh&5^aBV9G^)_>wR^mEe zqQ*utuc@S*$?bxYEdy(k;+3PM=)KIjA3Km3;O1_U)R3nLA?0>fjN?;U8UmT?+%s>? zWV8zjO>+80Hv3D{F9c4>E{vpbWS~vJ;<+KyOPeKf-`dpqX@Y;p9x*%Jr0%aRvXX7S z5zjesKQP^{ix=8eoLvkyA9ouh%Jy zJ2q_B-H2$4wv7yskF-T|6cp=R9KKX~dVwp`7Qxiaiu!T|wq{h`R7jC+ISBRi+X3PU zT0uQ2G1PKX5>eN|K(nzC0-&@%z&v;s;h(Q1kLa+ZUyY+f$MUK@ah)nJVJk5aJmato z!Sy!JH`Qm;cf5w?5}gp;`)|`#m$AWI)BpcAa+X1sm9<>aw-+oH@j6VB%%-4k(r{c zubJ0NRg1m88DTqK95OLpiryD3P7QE@b!Pp<4YB^Tk^?TZZo>gv>I0 z=U&B~`~8^cRocgvedbfL%o9(~WVEeKj`5_^NwiekU6Tnxvx^pIA%dncb-TUmp0HAr zX&&1q%l^=?pAribo@ufFG0-!cfS$X9VMjZNmUvmk@r;Xt*NmKp5d28A^((X1sfAC`^$oK1{4;+Y{x^Xt$LRqJCnk0h!tu`f(@rl1uLb zeR7dHac&{d=SOBeq-`SiwhtZtVbkNhvGKq$7w#7|f0gv|ZTja%Q;+wx)bb1@3%b?$ z5wO|(nmnK4IhTd4>@oc@Ujl;TJ~r6#2jMg=yb0v#19fiFf~QyXRo2;?vXxJPY&CnA zd(K7blv)86)2G8K8nD1eZn~ENqQPv?41sQB%Fpj!d$J<1W z2Z`SI^zCBw`E;T$wTEwq5aklzO@TQMk zD2_Se4UQ?!ig$|@HdSJyT9{S2N#W_Dqon8cFAVC#8jy}eCRYgvc99*yCt@kgSCWh_ zbtOB!cC@Aq2{U?~1uP$eW(;P^K3E>Dy)2$ar}y=5h%2N}SrFUHf>4(R{|T}UuL`m+ zwjsvZpXF)uvzrWUIBT5uDMgx3*UlI7KC#W65&O)C@JffHlZsC&z=9xot!~L{^^ag6 zq^*Y!(DG)J4c$p#Y53io%I!$HgEa2fhjaNnaLo+WENQV~uT1gX2ac(gZG*Y2*ZpF| zVY)F?%{$zGmHoc8g&Fr&TY>MY-jaIjR*9NhoaH8=qVjvwJotyt-GuhYh7Z&xs2I8nN*HU>%?!9X+vk>=r<~e{BD(JsYIdr zd?pmB)*oEP&M|{9L!HYtl?k7*<#S#k|kfVpWZ$n!< zOm-&awYTVED$|ad$HcMAGK{eXnEI;qEC3Ee&bccPupF5an`cVmZMKazTejy9(|h)A zoTpqnJ5;@&JbpdVKV{aPNS$E62x@~GoA=#E7o+InCZR0Xs6;~Iv0%z>(@Z(ToZSY| z>N;o)k4+VGYuue^rDUWQ(X%k^BG-~Iq>H+QLM_*rO4lhpc&gkn0GKDXYYUYuv))D8 znzFLmSgYAq<=S+ebF$3U;tXn0l#uC;Qt)K5Ceo3a=cy!cmsWHODQXTKOdyAkc0jYp zY8_@l!z_o?Cv3`4MB&hMZJxMdqOqM#Dtu2{b~@*v2gSR@%@n-5!ia2V_vMMqxq*CZ zh9x@});lGih&Ke1c8rJc&{TCNZ|Ga)Liq0lXHR&$)+(55#4;-|Pob+8Jf@Q!RA`1F zt89Og9j!s{+#`7k?J=Plu1@M_=V^jGei_9{`v*g^bTKVq#reM3cTanXG*EM++AKgA z(jvMkFyRfi=w@7JPj~j@h(--$7jrA85;4k-{N&{hY(k@TB0dm~hH%1gsRg%EN=8bW zDd=L<2|cGFlCsw$w4L)qN^ERM<>t?l82*CK(S`LduI%-sqmMoMNqf1kBSh!L_DolQj~PK3 zgJwK_9Bc2`ppmzWS*90#!F~$%45CWP)vt3k?<wf+%XIb6G7Y)!hJG=6N?lj3>=d&e2hIeRE&E}2b1 zRb0(bK>lo-W^0HZl)nmN%4@WOeP40kl4HEz%bixm$uI+U5K)foqapifNA|m%m1M?y zgu#!^l2xAGjGC>5S1z#04 zufp)KvkDBUaXY#~!_zDV>-1np-D9W7#!GuPlAR6bc>$)@1}u|Buz~ro-1$a}IC@A7 zoEvu=q*t)vpMxy9U*C!1$(Y3xc5))5Sn%uPF*!eGqG z^2}}~Cji~f&ymsMIt)jjlNkA>sc~lPNKATexWajOIoTg-ZEw_wninJJjbeqDB-fF& z&f%B5(?aEX1{sdN>>Yo{n3T2-RT42T^{#ns|7ob@#EG1Bm+Mc z7vFacpGdg+anP}^KMLQ|k;^uYj=xLA{K)oysZu zuO<7vT4s+bGpA>bJn96vnUzRz(k2eX=G+N61qZ4coJbxtt5h3d_83+WB5Q`e8Il{pW(PV)#-6%Dv>Sih z^fw*S`9bb?A@?fC-K~t=ZGtC-SUW_%Y;eD|crxmhjTn5Sm^_NH$A8Da*g;0;lsnZP zie+Ld0w0n^>wNiaxjrxeN26C$y@6#@vSSHiIr&xwz3J%WA4>tH;XV9^qgbd9|Xa@P8v1-kbpT&WA~^i z%*Ob)BaqlDnoOSrNE66t$b3Y>s51H;eVy^>BDtdIU+)*S_DgL8fHYM-*yrTTIRW_w z#2}`P$b+s<(wf=URh!g-Cf-5lyu#_+XvbFL6uvg;f?Et5k^(dk)qZZ@fIk`wpI8W{ zD(VtvRd_J$I5?DKSmkO#neo>=OL&Y64AS+s9HQr>vn3t=b zf4mpf3MHu0jc~_<+gk^yf<|FBEh2$g8=b(Lez_-30D6z_d7*tN@&kQEknJiWGXt|KHgYg4|tNWCQrd(rr&jD_)c3#?s3 zo+dKz@=6V@l?=_Qp|`P01WRfW%ytCYY3XjYeB9|6x0wM6>Y7!e)Wzd%uNSrF--_U$ z>4qeNoJu-1jjnd$(xsNI&)>LC!+~MGdF57hHaqQ$@6`0^)g}5ArM&!}l8Ho+{(qVnLn5?kg2vUM0=I%|qRAjC@*=D6Kk zGaPT;4^wp4hs+hJQ|4{Toz9z)UMeXXPAX{MDVZZa(a&TKL;lD@$%m>{ETr4Aq50X& z%fw{Egpe62TA9*P2N~CEKjNQ;^K+;mAFrRwvqVKeuGa8appra9AbN-8eEWEm8$-c( zndx8bJ}DL3Fw3O$X?}MaRuT!L2A+^;kKx&Y&ZMssP z!3(3Eu&PuIksrh^E(&jgkc)MSUjXJyTi#?rz#-|8b-@I1jw!P@ZNHkdATkx+2>wlD z7~amC_QXOsIVfh2Fgxo8Ypvj0@umv)gq2D(Yu?ma zAQxp=M$VG$mUK5pP5TRs=vo(T6E+xRLJFZc$KqKp_=O5g#Go}to(2CWH0$IjEmQ}B zHI{-IMD<+jV&WRrI*BSQ;938W!mPfMZ3z14L|tSzha5t4&LYaMKU^rg+N=UxaAsyF zR5PBuQRM7}WjS+46AawduBmN}SqDPJp?bWY+NiLdu|#ZJrP~>4C&LLjQ7HHPO3A;n z+JZpkB-f#O9R{@k0OxL#H1NieU$c*`npEosPnn#PNHb?vg|-!?{v@%?N_Cg#V%3UL zQbCFZ@;|0jb5x5^5xp^?OeV6Xk#E+-m`PD9w_luoJSEv3%Ns*rkib!$Y;{Nq4swG- zZu3S{LOydu293@vi;2$|N{$96j+;D^P#!`O=@h5yqzyw;Lv^P+A#!nz%*mVWCr`CZ zh;sWWmB`yq58kmg@^bqr)j+>4@&l!w7x;lvPd79hO7T+yM78qEKbxFA&i;jF%O{mw zLtWN4`=oivof7(oCMoB?Jx>ka8w(`8fad2_(&r?3lKwq*>TbP;scxwy$jwUv*2v&Vk1Ob+}zvE6&+%dw->jiZLC(L3H$f4v! zv%c4HZ>b2Bqf;-N5QJ3afSU!~?&pX43I^_jmeNRvW(?g`I;D$=9gc|3#B{jGIYd+U zZ}lH__)x(UJ6-vMO%EQZ((P|7r@kv*Ov@=gG|(8rlBn|ekX91wyT(U(iDmnk^>$s3 zXno-8b(&=3lp9Tiz`dX5VQm%*1!97W^&OhkU>0S96o9qOY3etoDS^?{pye zu@S~pW*Ucv#akFYkks0yy+{MbKB9}T>A<}Gun#qu z(Z{R$??FAJwvh09z1Julbfo>ncNZiu#q!6d2g)g%*8}CwR#z?mX>%VI0p-d1FNsM$ zea%07psAFl|6u0u5KEs-o6N^Tl*;wa6s6SG~t+u>^f8(vZWp}logv< zs8oVwmLRwRoma1kDqE{?R3%4zlsN7Z_4Wsu?yL}-8ZiZ}B|hk&<>Tc?yRSwt>eDC8 zr&=WrEKGEtDaAquT$%v4P)>AZn18TztOZyzf<%Lxm2g+C8{4db84=F7FQx#A?%$#w zw$HXyD|#-$6w%U9*m|Kac(Ws&b!^$?_!^U48TQDQ9i8W_sV7n`5$H(vShVAJzT3z- zBZ=<{I_Qz1&?Bgh>_hW>(KpR(T0lkzuCL+9HwfdM?ZnjFHc=Q0*!r~jYUK-Z?UFo& z2xNsj^<0t!^+z9?x=r>2nPVm}n>STkNv0iTqExYLk{Ojo1PA9;{UFx&8jPIG;@>h$ z;MVg}=acWq`Q-6w;zgvHc5d&tQY-1mJZH*kUC#Ytb-`-BKm@Dtq?MD$vU%N-AWB<~ zsU7Wzj?C&`w%Z&%GPO82sI~qc4qIi*7WQJJ!csnPcSFpT@vzmE_4TG%zG45~p}m?V zDw+|gz!)|t5c%(aT_0)5zUJbU(6ZGA8rwNQS?rUrj(2UAE9{$Pm)hQhAI85n5RN3f zj5C>)i?SwqiJ9Z3lwB-6Itg*_e*_zEXOFmzEqtn zE0zc}o)&44F>zzyJEJ$z+wta3vpd{zhZ;L*0T)`7Bz3PQyEvCgo5#z4wuDr$C)B>d zr)Ku^Rp|!_J}D<39%X}^6pLNBI`uMLitZ$Pi552japlMP$$wU6JKU@ySpAx5?Bq=a zi#-Yk!F05vk9?8~%q#z}%79bKBDpt&;0;QA&cd z%W1=j$R8uZmkP0Jbo#Tdw1VKZwI~;$j1Py(nKgbM>etPbG`B1nOJ*wK%S&t>#J+eAe=WspZ-Q?R+h>@r zyH@Qm7}X#oO6LQ$<@V!^a%`&EWq!o#8&mPJp*wZe)T<2?zvKulR0QjR+G$lxZ}U73 z>XL12UKqMlDXnU@%+|C^*6L*i1fPSiuvrQ|W4|{g>1wwx)+P_KKEjEx^o^pz%KS+; zXkAoG$)T=V)x^>4);2>e{UW6m=4SR8^UXrI6vmm_G@Gp=gEzHFgH_X9^~7b^U+SxZ z`kB?CO|{#Y>1c@v@xp!!1X95gd+&GVE=%fXtzrMfed`u9tpn|2-c5GjRAi<;;W;^{`K;~4Gbz7Z|XJX4^NFl z%NJhJM_Lc%OJVY($%$y)o?drl9l#>itZOVg#-3h!m^=5y{e73 zFQhgBhw4AZZHmf?k9A`i?dVqupCkk)xfj+vGXeQSou0G zt>L$hr0w9aj>|n(SGB4Ya-v>JuPud?WqP*QR>tblJkSqBx{n+}Gx!hem~kBLwH%Iq=FCq;-&wdBmb@+S#C)mcoks2V_Eo0R9Y^u} zZ7kZ}o9)gz<4|0Vt(VO{nX=LEbGL4c%z8(X+1D&vZ#o{1#+(s@CByqN*yaE5Ryw;h zb;okF1Ni*sE47nR_0N7y%;iOx93nh1vnAJMg5WAsyoXL#S(dT9orT_mBh1e6_7rSag`jUsS@l4a-aFS+xZl9|y{) z_=)iXg48_jI80>snWjVgIL$1PTxtwT{UZg3vP7iTO+`=xMMYAWq2zou%8tjZl;tZ)K2 z?)g}PvGu}a&1QQ~4jVB9?g`cE$kX zvcR;ET9&uoG5?IWNGy!r$bfclScv)4JzhwNl>7oI`S8O!-M(B9d5sMB*-hDiseXWv zU=c*@rC25{?^JX`hg0qC$Z#^cHL0DaNu+bp2Y{uK@nOUVQZ(%vjb*sfwf|C`ErgM< zbk}G$zv5k^sWcm+(l6CnQLL|&f2qz=wAeM8DyL}IXzFp+?76?qn13`Ag`G%4jT=&2 zS#nH@KDKCXvKDsAMi)AFJ42EID?LbrTLTdEt5wxMZh-F z0Ge*PlS;y;srh>G*zi|NivNBG28>Z)W(vzte*0iQExaUk$QLVeD%~PsVta*8(sJlX zS<(OAiPhpl53Nu+xF|H!=C&u*N5;foY+k^Zs0T-eziw5|nkocbv@}(6k%|ko&QnmV zb#)vf6BpbyGCewPWNd8Un-rb5S1j;LwqTLHf?v@VhZW?qZQ2#oTxH6JTj=IQMbpll z;(<0A8&S!hs$?szl1mL1V{dVm*=`t~TJpn=v<`N$>b9wf{>NM)wVbX&DO03&)1T&?Dz2d`dG9j9(dcE;5VjTQv z%X$>>JKzb7nZO?pH0ryexk=L2i2FJ(@?o&70n@3GVx!YzUBhK^%%!~zVcPP$yWZ^R zM6f?-$AquaTBF^cmd!tw9rJbbul;wTw}T~KYRwSusztw+*33j>u}*U}9eLws+BSE0 zZre;&m*N0&8kw^o{x}Er4x!<8ig~HMLvXw-5YC2BaSH62wfUnmTAM#?ko0Cw?sx~} zq?T%fjk1+&q`Nz^ktU)?dm`!b$KBjUc}R zlHYc!aC&3OT$*ckT6Vd)RzMgn9vQQd0P=`0La+IuhJ!mhkn8=t&5Bj~F zC+xr`zt>j2Q*JL>!Fcu#>f2}U-LLeHfK8S8d+i$?e88sAdzNZLG_(AZKE=J2o;?rk z8_ztacMmxDGN0h?O7|fL#Jz9t^ZcNFQqLc^yy^M!y~Fc~%FGicE8Y9_HKjRp_mF0? zGVhpgeB&5=7<(L&O=jyF{q4^OhOVD?U@Dq1IlDuG$@$ujj6;hWvOv7_A;BFwy{wdS zBM_q|ds=W?hnLT=)Z$Z)XfkUM+*!E=Jj5`M|43jT&I zIUv{Z=wb^IahN4?K%P9TY z&I~AX!p+Hfw6h?r17iu9p;YnNf=%Z+1P;wgkERo5168d(X|&h5CX2Kp=U!>!O)Ge# zrAIB3zO7d+lR9`WN>&I-+nHxABy6)n7?QPGA+$6tRtWv`7Au67qU{Qyr7B+`w8t4g zS|@ip@xI0Ryf0d~-=4cwcH48msc7<{UGe?*N8S7FhQYDhes+9#>VDUr;~Y!cbayxI z?v}snH#eo;F29pIRn}XE#dq&-dvVr%&{2)IZY|pF*)S4+U4F)hJ-@E`tl8LPzr!So zGc7r*Y^X6-zH#Hg3)n-Z{dM~GgjBG5O?&AT2GXeEkW&U-a+PGZ&QYkP;jSYgMEr%0TtskxyN_zw zs+TAEi1<(yIsq%)IV5apRcm7LSJKlbvSoH?up9@?Y~bJ%QZBwMY%zoC!krF|b7s`Y zESj=bt-S#j17wz5?C`R`#9B;!Xsy`hQ@j>SbR34KC0JYbt?4vYQQ&)uExNiOil@WuPqJVYHvyf-`wlz zbo`p)PVE9N+cg)sbD_D>#ho2}cgqiaYu6B&Z-MKC_A8*CVNbg%*j6p7fAgulpE3-3 zJ4exiO2hl*arAE3FLb-X-FR|xuf+$r(vnI-F*d3p*ka>#A}B46T-CpB79J-GG5U_$ zyjXp3&#AX7<8Pyu*qL&BEx&BV@QRPD=sD=X{bNUzCFfz^wk-<-;-_f9n^J$&(<-j@787@w-394XQ-Sc!p+m>&CkrZVdq51=pIGr zuqDx?mIY{NE>u+Yrkqe5llpvLl9lNW{$WV*84<#mCMw;7V_)t(Lw!axm7OFMx;B&D zX#4E8+^jJZiJ|PasVYC;?r!{tV{5yg!+{lDI>y~q_tR}_Ivs7X`C<}gJax8QwXus^ z1WfJSv{NhW>I>R`^Xejk5nrB z<=lzmm4zdtB75|gzO5%J(--m?ohF)PvM9(bb876YEFWcnnVGV%8ZqVZ_J{m1^Mnr) z%^^Yw8XLg7GZ@o780cokeIY2Kdy8x#Z%?I;*Qh3Bw{39fo^N!Ik1ZIa-A7^Y1=ip( z;d#OCrP~%6M&7uBf1P24)bJc`c32sQH#PRA$}-q`KOS!C@p@#5sg`kTZRIrO zORiRM+a*^^wV`~;)t+NsmMyu4=VeQ-;d!ei*N~>olB-Xa#Eh24<$cF2!kb;R-Jc_l zzpXa@>%@LA^f2Uu45$x~JPj_q{o^wA*xh?4H1$jOX_ z?m!U2=Ga_mXNB0Izl6vy7(;`PjBN@(Fqhn&mQ)mZnLHg2XDY2Q8sh&o8;=k0nBfR~ z+Z5me6G_Fvn09E23+2YJ9v-tz0$A7jH6Ihm-}#Ty7AbKjd0KMcI+Ax&^4>gM{ulzB z1nO7KULnbwycSJ9Iszg3H6J6#-zg^qo+7|8GIn3w$?LIvaf1ohi2?J8ch4cRJ>JJIiI#J%bLI4a+5H-h<^PivTocJL>3T02-28k-+=oUJ7|a#TTM8-F4JjWo@E=^1u5sU^bqdYSX?AOi#CKWvtUev}P| z%QdaPF0uool?@>_qca0caWq+AvZKGcN5|qHWwM5RYW3^Y?I{7sRkghBWeB_Rs@(D5B-{4EdD_sHEy%Y8dTfC zdxdDCSZSez_B=Rmh&;FtvuX9tnsD<>st1juYrpoiyu0HHZycE;sD}e1uJ4GAuaGF4 zB*K4jd@@828w~y;yU1-BZ}+|V;YfK5{azZ^*4Xs2lXSrv%6?uxIm6RlY_@((-Qi!x zw3#pGi(k(}jcP}L?Gunvj}4uc*%z5L_^d5DY*%NoG%df`ZErVtb0zmh;&@N8n!RxK zEA!1EnliO`hGNX>f%44DOb`Op6{;1P;)^ra+DMYQSM)CPtW{wR-)vRb0e)4lOmlvm z;*9h5LXvUTUSPopYLy33f4Nns;+*qa4Smi9)`0RJ@_EM&4P{#18qHhhEc+r|Pb(?n zoWP>~=pinkJn=nH2sVbSf~=Lz} zf^g!O6`?IxgK(9f36~vAplndD%4F!z8r&+KutW|YfK+oY1UJLgC6j8)qDawNrW5)$ zM1LkM#ubvBGvFNvu_vKrLB%T97sc7m{xGCuKBWqUSZbOx=P9_Rv{EIi7t?{RnvqIi zerCrVS#*kvNl{65<`E_3Tmj`JmFZy>WzVcMG*0gHa34NOQMtLkD=Mp%t(Tg$vMYn- z6{pi&*aS;C2`8{nR$M|}Jtrk()pJo1S}p3Jh`gTmMHJ}iTp?xlMcPN+$I-bo)Dh5T2BaR+N>v# zY@OzJgd@65vwv!<6f19z(x%MybgsD_A71q;-^Y$ zI_1SyT{7A|Q$$|7!;TzTxJ`1ZlCOn7xZ1vHA7IZJ@YW2(uttRWdaB-~C zQ*U)5gf8|v{g#BfFhMGpew|I*Ayt)}gkrp2_~KX0+)$WpZ3ab&5=6}vso zsObCs&Oer7f4eExsf@i@Ja4BX{>@Z6AM2F^nWMA_24?_IvCLzOW>Rr! zg)fmM*`PJtnS&bkn$dR@Kwy+1yl${hlHDE?#VsaW@l=S}Jy~XE_k}BAAv;XzgVs2#T!?ylAnv$Nxee#7R zg4$&jWKYiV<=dgio0^;eh0Bt@lMDUtQndv6yUi@|z5<(XdOIO|B95y(E1(<~nfD8n z7hYyK_|lQuQ_&Jx3#vSkq>1ei4!jA|HA>C72%5qHLRU9i5w5Y#5<&YW#l^Nne4ve1 zT;2SzxWK$kA^ulnrz(=(HA9Km6jow+4Z~qIZXt;%JGE`+wJb0&SYW~tuNYC;_i?w{ zUm@Tk9CXB9bMaKG+BU8FhbAsEImYEC(~#du9|H?V9b3=x*ETU*v$*5Nay@wJX3bOu zb_khfwm{3Ua;*?XwA@3!XnDT0A`$A|?13m_=}Tpr{3hi_urT0G*Y{~YGN{#?GO&e95);^u_D>{%Kt>fH7Q%Tn13 zf~L+h!Ly;Wb94sd=GZF6429v0Xoyh(bN65% zVIg_<2W9FbAABX6Hb^V8qEho_OHyhJv!%4M=vCJBrCr;Vn|F=)a-Cu}gTyROdM#_Y z#Qm#2j{6t&E%U}X|JoPb>@Kn5TiPxUEwWvzivxE;Kfp4v(BxT%fvHI`MZ~AYrT*`t=^QuEUcF+W9!A`G8^mVN~?U= z(1whf_&c&*%xGxgcJa?!xLqtoTepj)DtEis;|JX?a7pQrcxKM=d~ViL=Fsh;ua$OS zy0mh;xbJ?~bQZ+yOc$HWKInFd-7YqPG+QzRUobt-1z(hjc{$hGn=$bOJ?D4P**0#u z$%SH2Zini{7^AHjQ|59>eKJ0o92eOWdA)9|)5eM^_PdxXKn6uSeV#XAk|JA}Fl7~W zrDDCcE48GeZ4H>XXE9*nmABaa&_Q*#mg^;Sv8}}f3t~3hwFSNx?HEt{x;i&p9(220 zOH4baPHOK&ti$#Vn=FzeTlY;)e+|hVTrc|DnM8%>&h1lt_iyid`rEZrr*&_48lCa{ zucPkct{ETezGn4395MK9tm3RUuk_gMGUkAuE_zni0v_Y|JVF%?aDa&9j<*Ev|B zrj4A{`b~=P@85>6Pif%@k_pBw{yw&mD#y?tGK9`+Fq@r<=CSKT**2=bwLJqUF8>`O zGAup>EY5Hu9VF``W=!#gXaG}$&X>hOx(!8KMDuDxS~$^N{|Qnyw4@SR7*4`s?y=KL8+oBq>vi$Eh7a3? zSs-*K!i5n>tsEv%Lo6?@fYyi7ZBLks4#xwcPF)>5W^GSM*OHl_i!9AY3_#5*vaq*pmHnCt5zLT_^ zNNY3ZY)C^|yYuHn7c{s`k#Ked9B!@S?jGwhL48$;APm9E9UeBfPy}*fGugL!lW>HXsr}$3vTsM4nbu2xzZKbSD(~tNmDlbI>WCosUshA< z-v6~b|5)p1ELgz}|7QPY7k5im(Y~BFPHv6dCrG_&W|R z`8OFVDr6a^N@A(}SxU-2(C}+3=k_F!=)U9w>+K`+zKltcvtc;kOk)e36VR4Wgxk zZ@F`rfetU=P?5pnU`wl6*2<~0w{obN&Uk=V%B>t*AR@}*fYc$sF5;Pgy>@qhyV%}v zehOL=lSP419eyc((!O=d+<0ubtd5&$Cdr~tR9a#rZSwrd5m&mA{rq~^iiKvBk0d#UqO|8W%e+$5d6{)(`ws1( z(_doEY^6}Eeq*=yXD;B(KaR0*!z{JEYo9OwfA-!z$giuq^Zm72YRQsp`2hq>2;-2p z!L%_y9=6-Y6;;Yz=_;j?DP=1CkLUg|R~1!PaceSjM^(4_x^9hWG7GcvEM|*d4d}|!WuwIF{K;SU#hH6YHjLlAE4A?L zafU_-r1v52wZ05HIa4T2jK`E8ILv`>mZ0?mSLqOQLbkL&shN|Bzdc>BSDu$L*5kH5 z6r-3}Pq?PC%Cvcy2ZLx#ExpM?+I-)XYb>uZHqOD2w566E(5utLhR+XMrxqGA+&Tw; zq0Yg_!1~fuJr5mCfRqfaLcQ#N1<7eMqVxo(@{Zj5ypD+8PD-f=K7&q^AEz&!r>MBQ z=_j&n*-r&S9ZuX^RAUSe(n_iPu3~^TgCecP115Je9HCuz{Hy!-|J3a`{>?@k=;N{jFn#s(RS?5 zy+^*8)zlDpF>#wfp+S1%e~S|&Q$1k%wbJMiBD`-ehRVZVhCOj4kSjF~2xXyOsB-PL zC&^=+PXB)Ek(=HR z;OAg?`4GW9wWsOTj*k-*)=A^!kbeGif-jKpB+U_$z(sbfe~^fU}d z!G1~399mkPc%d%0K>nJsL_Z@y*R0BnN#_vL%bINoYZGjkNiUM6#Y9}H(sYI8i3|KY z%#;UqqX8i2*Ol#cpK!~iEf!V9F%*X(Ph7S|N!coX_|Mf&+nWPWXS!rex9JMqv$O{e zKK!Q*uUSkng9<#cuJ}{LL8-mSi$qhZx%tg-8V~G)9d{Rs149(PHVQ)MR+Mh<|C7+2 zihIAlJ8zuelwB~H$#@Q+@VTmXMreGu5pSD0?+aTko>NFAO!R7!Fz&jU?PN^UfKT5$ zV~1Az%(Y=^0uG@se?q>y$_WPVONR9){y;|_!`aG~UKIBYWBj+J7H5IZgCV&NB+D%j z7MXaSwq3l12VB;n{L-{FXde8GH9uKO9YHK0N|CPV6B@GAwT(g5=EGRylT`&|178rp%R}2>dS1hwr6-C!kxo{ z;>1;BT1o8+$LZw+lg7(54fHC(daSVHt zh%%g`wf<~Nw%fIdpE9Fw?S03EM56N%pJUj_Z$<8(pREz&8xw=!foP9BtJ$&~mRUGs zihlBa8en*(=?^`aEj7a$~L@A8o? zI-ODX{kJD}l8{ptp5_X4&}i8NPh`+&2N!!{Vws4j0MP>MyQ`19Z>O7+JA1hq4eYI4 z8CxZZ^v&9lEg*QTNBv)-bkQ%_d0qtNz({0+HDU)h+HF2>$;BTIx<)H{1+1>y70}~fhw^CE6i}n*b(H*26T9b%!Gz7@Fv#;CV zkcuJlvTvn#@W9BI?-tsT-~HcyTiW2-?)4)-S85!3z2{KF=YrV$JhHp4f~6xD_-qEk zCm3^`yXx#_rFboeKhZ}t4NI##UsAlFT=Lq^-mfrQW7hbQef=Mw+phU`eJVy{+hv!( z<`?(;;%hEXsX7l%GzOiGTt20VU2 z*(zO;708t4sNRa>Te>Qp|PN~G0*`($h{ z&6u`%VNo>PFMx5Z8n2TYVFyXC+ANNY$nEoH@Rn5zdmi)UhE+j^yDfG-k#lWs%LrCl( zs~fW;*LEho>F{oh*`wlPf+jlT+Q5;BM-P;Ka7#r0zaHp8*{*} z?0+>g?hnfrdn!+6BIZqt7?cihWrv$~i!`=osXUBLTT_f<;qZYrM&4h$m^tP(t6gWh zW8k6LcVVAqBim;z-I*qq{6YLZ4pbIOiHRL7N-KVfyGQ~T+gY7BUoc*ChMY4FH<;Vg zka7F0A@7eFMP(W_8>-b78;bqKIBD{Q1;TIboS$`RoIh*FMJf&fy)lzhu*O+C%$Ls^ zR~F-0fB^HDGwqFH;6qUiT#Oi~tS|zLg3lbPLpzv4HQh&^AD0=@L3ZYlmEQkq6AA2i ziG+(xU9Bj}tIFU>+0P$iy(R;a#?X?-QmRBq3tas+`#9 zbBE2(L`iejWyVo_EvU)g93U<%ZQ5f}%8Bv#<^Wj!f#R;U$Khj#zutCU46jSU$0#7=wom!tCZ3(S3$4T;aS)or17b`eIM*!Ksf1B-wy{CQ#$h^n zWM1k00MQUy!d;f#V`dH6_Ah)eE@&i@YBT^GM1!P5Xehg_EVh#Qs`5r$BZ%&=l_9i% z*cbVq4k)vma>EYpM)F<_6bRNpcIVilH{pX)$eg?vQ9&rYOH$t&#erJzgn||-$qK@- zX7b%G8OuZY^H#*ttKOWkA@qX}wx&#WY&NSQW~q2ZWw9kCbXF%~0ZZIlV}?qNwwa-_LjCOYC;7?KDoS35Albyc ze^!#@5jQ$9&Hti5zgB0D4b%9#LZ#5BhaW90|KEV??6v%eQa0)=PN@zPFtpS;@KLip z-3RRAQ!G`r=BE5R!K2Oc{7L=iXK`y%gTElIf0s5Z2H5>*nbeL^X?C;*c^A!Pa2Grv z7C;r)Ds@N0hk@W`$@n^HsVsus7Z_3Sa)}RPS1{&8U1GN9xracRp9xlyk*^{?l59*+ zo65@6DYz;5G@3N6%INJCeIN}iLvG3qQnS|kQX*1=hi0Qo98&Ncf9YIQGSjiBp^}wh zF^HRJrI1gNRQR`j0H&!rZYs1M=!6S4G>bl#7n*E9|B)(Z&*DBR(`tsm%82r(MIoA@ z&nYE0LG=05k=kMn%t>Vkb(;kkM^{S6nzIWnJZnItG@KQ&g^3B*Y>8D}5n7j`u`pK1 zD)*!5{bOnxXN>}xQ5nQOcT(!I=~$05I00|psXLh55jU4*X(m!1-OJI!kH?gBAX__JwA!u&JYBz zFkOyndAW+a*}Pm8dIy>}!$>O~3XI@&E!NFc(i!OM`m{L?Kka5c9QfUuH|+8w2Y#pT zMV(6c%)l^DD;m+sDTA#GI#0d#2uG&-J;G@|-&eYrK^!0}A)-J?5*hpbhxfI8&TkFuOR=!J>D@wdk26y(3$Y7bt4A@(Psj{zj4bWf- z+TR4%J`WIlVO5y<+K*AUOTPX#kS7B*&SK>aA+kafWtnAotIt|l8mQsLO=#gc6?qfo zNsZGgYshvd>AG8`LujEa9yo{D;;l+eyj|P$>%*|~|7Cdi>wUcW&jUOETFo0{=U?r6 zagLogWiPX#YO_IuJy-dvs@9J43bs<94~|P*#U58<^^oADNJ=#t5;r2m3pd>Nrdt zOu#T^y_Q-;3AGGkuFGqYm?7C2DyYwpjS9NlKr>ukiQx6~!%26W=3;spz4o;uqiBg| zbNF;$X}!o4KMbEcXDTbwJQbiE@L5a3 zMf=eBTK*+^J=!l7HRe+c-|c&}kH*G~iSZLORaltpTssR=QRznnQ}NjIFlub>oEgCF z-Xqnj&PTJB$^1=)Psv69g#rnd$KK%|hg`1m>Xtaj7t7h|%CWkRj z*{LrSJk4u8!1)Eguv8(m@P8%fJG{HiF=D+&-IPUUS6y{D)#0*BN4A1j2O`g+w$+JN z>PSj55MqYPTm@+#y}cY=uMLS!OwKA>@@R>WJSi@3CUpJC^Xv$s`pWE@XFM4r+Q6e# zJKRddvpot|J;z7ec;w3+wPv2_p`Q%mqgGLi_uAe!qC$J?E;~3=HO9i18D%~ozkz@i zY-z;~KDkYZ{S|`#&EMn|wO9hE>VvZC`5j8cU$7=gs_52Wsdiw-?8eAgUju@qwhx(& z5E|?-z8Htus;J29le-@&F0-!3mDKU!;9sB)oWNNXX8Y#mh2*7hXB+3bXvCPbTg5uM zouL{Go5qgn0Y4bB1Bqs0wZ2k6Z%%P~KOR=NF!&E>AUPa3zRV`JYa7Z(7_t@sRwo!t zMHL5AWoUpGkA;i?G=){od;(^-H|8uZR1?Wtu3FKqo8TZyXdw@J9Afd;SUn?d!-d`5 zjJx90R8F{PGob&lfTgY~vLIKC?#x+Hw~tL>Ezepo6D7=>^KC8K1p^NOK@`Q>Eq+&| zniV{=aA(zr4&V}Nv1olLk7uR!MMNxvt_uX+Y@JNf>WGbe^hrP!w|>=cHef)CZ?zCs zs~VZ7%qd4u#Db-HXXyyU_F#zC!VFemmW}ayq-6E1gU>E4eE_Us*9PIhIiiKGV~w2y zL?-1&Al&HdYaaj-oA9V6E8TzEAvJLhJGaRN=Ah1=F^K2eM=d56HxFGR$2h_M_!#jpg(g5{1_>180>y`uwNpL`~)|DaHQs6`a>X^SZ4->Z24vK7r zR<~~BA(P|D&O4-sB;`pm!X9GUv11I;mus9VLia|w5L?YpLBKvE!_U04>FIJ59`;1d znix#N0_P(Hg`uvO)ZS_)FpLo?8O#<2(VVI}`L@;2JSbP<0SRSyx$s9@gNmfALZiCmlR^5h9Rfk{du zEVgA1zp9+<8s3oXoe~Cln5d~AhX*Dhkg?$ zw9*oQJq5+x77hDu!DhdO+N{I}x~SFQyIG>y5se%Dw@v6^3EHR2ryCj2A#I#}=oIms zg!Zc04=_ISVZ9On=i)?GDS06S)n?Ex~QW2)(c+4)zvItlVzftoa<|-)8+)6j1XT;Zrmwn8@D9 z(JX3|xd}tuhJsmOr9)hnxXveaFKX2}rt+*a%~VETdDFlD52t=@+kgDM_uYBVo$oz( zLpc7N0OY}m`zA)NntJlrMh@P!bnm9S4qWw7Hc^p*MZD`cCH6e|Yn?ZpxOe3DuliWc z`wkU!4swCSf$G~&Nrnm>a0V2Xf~IHYjRU)NJgf6c+Wn7raRtv^H1Ozd93SAn zC+Qlp*R2Rdj)}owmGF2-K_P6BN9boY8$-gv0KES|(|6MJC)%36IN?}tS_}+@7R+ix zxQhAlKnQLSx=%?ViDbkwSPhem#^on|t#c18-_zgnDf+osL^lw57&EIg42o`qr*MNz zI?8Ld+=;CQ)?v?d+>Uky0F2?ewU-B$33w>C#|iL@6-*@JL!^WZ&N13hfM@qsY%(!g zj$r|K%1IyW(nHOtn>NmKjYx>^2_?8r@e`HcLGdUY0Hr1^Dm?{G3|e^4QimdPH8o6) zK0a}tp3?>XpT__itaH1Cs}v0WKCL#ha1XIblnIepD#zuq)igsE4ahA)EF5USMXAA@ z=xfc;F9K)KMz*eLVR@*YFH=8BytY^77@fsN_u_zK0=1G1ZWU)LnFOQ56)2172nB%- ziOu|vJ~mVE1IMrFS{GF()ZsC9D;9+j4t`P6a`LfC$=#u3Oj*-*Y{QM|;MuE~(?%Bf zM;glS5PlKa>CM0QH=nrY6Yu@+eeASnD(ZLOUu7ox))0R2P|X_)zj(0kg{ml5@=SU1 z6kuHp0K!%*&&EsR7+fy348rN#gapJd+P#!b-!voM#xEMdZ}CMYjgrX(TgvXk>qoW% zgsq3Z9~Aj(=9Sun5lP&(zW5SfBB zR2~1BP}w~oWJ6>|aZ!Y9+iw_K6f+kp9NJHrcf1s44h%N?jjAQPuhWScV<>-RsP)1! z!-va+TC2nkiTStXh64 z96A`s!%_{#OqS|7FQ&8cv&Gt<0_J+WML+yqu~bqN6TEBE)_}8InYb+xvn{5ChA-0z zU9{3hqe8>CkYbivooa7nw$0y)_EzP;?Nc`?HkliKcVekPBw>tf;Iz@(%)x4s;6L0{ zrSZ+bJ*}Pwa)%vZckUsbLYkg-D^VDyO)LuRm+ri?Z*6wu(`~d#l|D_*Ik^);Y%ez# zHhSH%k4nQgjORlP% zE4Ke}#G7}*ROlgr9<_W>CQ2*;drYp+a?6J`9O-)5WwDaPbrKd=`eB+aU$ z3k4<6&Vvh4H{GxpqAW#B43f(&0reKyqV@C3R%1!ncsbBmaOv=@98E!%a8EW;B>&Cx zOpMrSwavY9@n#!h+25IvgGgc&nkm(Tve(n=Z|5YSR+e zL_4)&d01KUp1Ki3u@>(B43=zf(yTL?nWJ%=+mFZz2t$zUn*OfdHmPxBs1@G@my7W{k1u8JNp*;-l$||(x9Ga z%9E!+tvTML05goQ7t=T2>DQXgCwaNU?FnXzqK{H@UH)RX6~}TeOLR)c*w99^yu@mx z_m72hF{hDt#i}uAY+S?Ac!kJ^$oh?y6Nb`w{Ke`p2rp)5;Uz`zL^LwXeFc|jJn@oO zf)fo<++WAQ+#-1;jg(key&!s%&8!#`xEFMbhxHQ!ziK(yVs#i~*(RZF2V06di~|mr zBqLT-ESE|(L*}lao<9)tW687e8dCG775WBxjnDDPKIZcVrsgni-XD9W6xe9ST8Dlz zh;dm(UkP@wfBfH`ysR_+5uT;k52ixVA!c6tzj*s|rN|I_>wbE!4XwA|QRYozU#Mn^ zCiBwYYF*K(JSfo1qiwh3%Zg1rT9j^QYM}v(?eNee_?nrj!PvuRuZrz*X{h#{M?bA| zA|IdeqL@IBujmu$6CjZOO2oW+*``or+RuLO^zyq3bQlR@KsxP>;d4qEp5r zhh%P4bWrf@z5$%g%N;oUTlse6;bCsv5Hw>;^}kZsN@w41Rz9hqFsr%56#Ji0L*=U< z$tOQ7d$Ue8vNwC%h|75U=VENfu_83e=UC`|K(pO_+~{1fx+vyXB-fjRV{N#y%oyOh zzKq;511PqITdmgp5;7}*H#_F(_!w**k=lNmV(uJpp z1FPCY=TLscEMamdTyyrDZG$GLSD2qMxwnA0I1GpsQ&|-@cHr=nd3E-p$PM0(=SuaF z$J?rdK_!jcNuY=j=8fwthif>e*4ieriUFzVFd zs^IKB6(c}f5MZbkKDq8@9x$M$f2SQXh&nL}?2!vY7*~Laffu`0+{inv`lXOAq@&z~ zLCo@x>%$(R<%`<2cQE9+L(T;bV+hY2KR)YR6XeZCexmNChO|5GW_{_%5DWhBcZ3bU z6FzF^ruG@WJaIXF#t*fH!Z(1w-py^*cq1(R^MS+n#IFXhTYbgZRlYi~PX}*;T{g3~ zdUh%g z{BD5KUYaMU^)TEv0(-aCqct|1jyo+zZ_Q5VvM2t_n#KB=60%_!lt~R1 z+T83$1%kJW6&CqPyRzfSKD&jHHKvy}&N$1WU~MaXt$yQ2H0LHZzaimq_r#?h@O*#@ zW#G=`MqTI47@y5}ULN-9qH-g0=5A7X5G8y7_U{x#0pr*?8vso@@>~PMZa``AA&BKq zPax?iD-E-t*CzUNgRV|kK5&h6Sn?*Y$hv|pAhdrb$2}4snsNr$gNgy z5Meq#naRE%NcIuQvTyN72To#VTx>}_)~Z!l6+sT-tT~`Xy7w^k>|Wcu&RM(_tH~GV zV=Ym0pDc+*xqbHD?^w~h!MBaNh`ud^qg(xg^<=ZxW+y5Gk?%ZQklRjGi2>2MFms38w1wd1%pcKO zxLC-#xtG>5Mk%$c#jb5DQ%paJJ++s_R%$Li>1z#Zoyolm6IVnMiXo!eG{i`yMj5{- z>+&9@R*Qc3HH(BO#9f$54D$n3DVxn)#PMyKId+uIX6ac?(@F7)rBO@Ub*)ckqRoVg zxzp?aw8|sogi=QSCo*6>S&?=-nAMhIP^hi2 z{s)s%G^eCIA&qWL*h8$&90rIsf?>45jUN+8>oU&qzcH?K8nV%>S*p>pKovDsD5S=C z-f^VK-91bFhN$a!<#ov6f`*3OP2iB=)NL{a5R_@tiu^#T@8xYby*F=NwxhTyhY z&8%XbPTbN`ER(}TkNMOxFg)&5Sf zf@gHHGw+7-i!Ylo)jM5hWf$z@#%$p)=cjEMQQudvP;ic{UKS}4Lkuw<5FbU{*^x0r z_otsF^?jw}OQu}EkSzd#&4<@N=Pi+t69vr;${(R5xQJc~&w(Rjc1nlGSSMOA|W_2;D|~4Et+a zwEdMQkSwB`M}6H3dFry!pMBBgSC-P5SfL*-prt)wKMlOmkB^BL zlN1DeF*s$veI*#NSNXiK@1R!eL+t3p0$?ku2T8!YRpB*D^1;SP-yui&PjHEmV#m$puRY?cN z?XN*O{$q`i8!uZ{Z$pMKi=q;7R$&O1lZb7 zCQD-=BCb~IBWamUM5&LY2Uv%{SW4}fxTZ=udE&~^gl8wkiwPg#2ClD`{yQJl`n)9O zGjOYst=56o1?oM>bTC+79S~C!OCDhUG6uzCfyhY>Ww?2Pr`^U)Mnp%z#U1Ja7uY5*#U0MFp|~}H=5P04SAd4MSYDp zFE@^-qa*Sz9yu{F%1>+^>yAkGHCo+6)zH>ZwK%#l=x})Dgb=Qop(1!V zL&#YeY%s7aWnMMan+ecYZBgD{J)>H!UUGrkUTlUjx#|`|s#hoxwVQ21W7HlnWFutP zSBiVdYF(_-ASh(Dq8<977zfxf_Gm`vq(v9W12VvLVojLgi!>)@7-t$~Kf?zZDt(kRnc?OD=9rX6Dpczk0Q2;@f23VT1Y-C4(zko2bo)9b2iR` z6}#aHI_ht25jeptG563B(?l(s&=41~WMj5n2L~O|&bgDIry=8>W|{KEjmQ*0xk;D9 z9F4iZRhC$_8locYt5ldc85RhJ^OJj}e;?Y_h^I2C@r<0GS~P*lwH3nl<4y zw75&x8DFgHjIpnV5T-}~$t++2eP>V`qirK0!wW)Sn|u=&@_@gNvEwsoy_KmSg%-)?F5tP8@kdCIPyd`caR=+`kY0y(m9mrd0mYa8OP;S=s zp;?Bi_TgnHOe2gChmK5+o-aNs(~SO;_#B{%-HFPuAzcjTVWr87@+MmqGdAy?8&u2| zEr(BS?^;x})X>mk(NrAE9vs_B7m{iu2Sqk{w@@sGRoIHP9os7n)YQ)qr3N5~IYjOknT&YD9e#IT43@WeN6};HqMkQWcpgLsooG9?(o)|*Yvv!9U za0LS)C2=`E*OrdkL|);4-zLH z46yq!7g8e1f~_Tn4*I`?W31R%-`uEp!_TV`yA{@P&i<#`IkpTBJvI62@1&-yb9H zJ5F9I6H%&W^5SeFoRK*{%W?1ew%bKaA>bwfWrjEhY)#5=DOR zqfK!$=vVJp-)wT(eS0q~i*tK9jNde@EHRl%h~sF%z!EdFiy;AXFl*0oh%Z|-dYlft ziqJ^EzBpCpi#=m!)DdptfeQ{7;Dgi}lnG42@0k#ObEbN6)&;$;g==2>3X|O8sdkqK z$n-Z(Y!5PBa&UP9S=^rQ>y3p7Kc&*``M#_)A#6x8M29(&)(iLLh7x{-hV3q4>N1De z`owc3XVQ67csfGTMJCMQv)sG(*(WY5-Mj{Ccq3s(@d|m>q)-*zs;1+Yg``5_43JcB zjF8$(UA8__h??bkfDMRd*C3D;EX_eB%jl>*Xepn_XtBZ#*^Kkf+0~eM@-cXN3y_ zEQ^C3g5eos7;Gfwv%qtaAEwzFO*7koej3LkXzKl!Cp59%d&v)ygGi&nc&>rSbZ7%h zj1A6Gh^CH~6QGrp>chnKTEw+!$W$^EyS_If&-fL5T0mIHGo3qPxJ~^_ev0^@XjfJh z0oCDL6mi8YrSu%3SslaaYxaaYCt{-#EwZ1Cc#l~z1b7V>(bm{*ZFk8=iATbk-D%n} zbE}cDf%XpX<h)SzeNFcR&7<_`IHTWX)VOF~a`Gd@Kannij%U9Ad2Fe>-+}L$g zcM3{dW3|QOU3sHezZAR;yf%)pI$>Q-HjlKlf$_t~u@yacBBJ|%I&6Q(gKcqYWrAa7 z$1I91EIPNGjw)M;sa9c+Z{U#T9WoGo#)fbA{R2!8P)zXyhePqwc_H3?5HMukmwk-| zJb&+}y}9c55{{X9!~S|^Jo$3ERJs0^AnWRVZMOtjiR0O|9F<#wc>fj?h!0B?)?Xh& zncLkf!LDR^KP)Fg%kA{HCr3n9zW(|ZtJlta$@!M*Tlr)FitrtqV->Jjs45^ z(k@Oy&W&wy6QnF#?pyG{vikdPViRiu zjUkzVo?IyHGhm=$W#XbxvkrcmT|}}b)|^>LXh%spWoO6m)4mq0>WpfUF6xmAMcp~o zR1ShL19YpQs2K*F)(VS?32A7ufUlMfLgkCf>yz@WQHS03 zPLzCFE<4Q!6q2tYnDT@vm~NUb&xwmtffF*ZxFV<{Kr4VIF>g&~vEE$~%dF2>vRf~4 ze}gvENuRlb=``Nt{>E@-%WjyevfA6ib?)G~z}6?Azs#U-Q&YM&(i!_&Ujcnk{^XhR zP#)DUb;6MsrU?zORz|OQ7Qha}bMU%G zj!jB$)e3Xmh+^^9Tu}gXGSaXm=N_ntTMg)0oz6yrZKKhp%1Hfjj8uXgtI!cEjA!?e zF=19$Qeb~WoNb}LKT6O(s|^i~oZ=I^VIR;tT*MJ|{b7XbSye{ZRuRUHs0rKM zL}V;geIs$xCjt?6D19#{=OddP6#iM`Ai zxC?Z{AI@x~D|C>qBMV(MyswK+qb+FSf~extykK!MAr({`Lu9;!7_$)1AtlK1EOOPG z$KAOZ?k#wqT9-GJc?p)J{BQ?p>v-J9jh?!yzD}G^UMeTcY{)Y>!%mu%IK^0 zAgA1*MBPChuoVz)U$fNS|);tdLV^ z-;pIU+1!;mSX!f7m4;~dUNV!Dz}(KMZGeltrs>v{(zfQE`S3 z!ij{gPF$Lfb*PVKn{f@uxTK{ANV*V^8664!p)uJ7?=nkK3}jXG>Q7gWieTq5cMLx* zHTPy~&656RCNOWXHP$B*Y;qJH;gsgVx5a(K$(0GW`!@UXVM2U%P z(@#8MOYkU1R&F{~JQHE8x=ls1)nl5@>TU^rv0ZFgwPXhE&B|3S#}2M>Eb>z3pwMDm zWB=_2===peSEo$tXb*!ehEhTn-6iU!_N~LK*jd;9ED%=qFpG{NxC~C63u=#ajihbf zr@*NdqOSdULD|6Qr-C#(eUi;%E6r7@Dq)n+O$$)9i#bIhj2CQ&lR6&l8i|VI6>hgI zXc`zxRnVl#T$FdrO^iNV_A?z<5sWd%kmxFhD)5;B(h&6;2^-UB*(%{%Dk~^!56_BZ zomVNj!1Fe2c$YoEPGPXxycboDvZVFEVn&{GXChVlScgqJRzh(cvtvcpbC+}|U-MTV4c1!QpNq+m#aE=g!HITYIM_H{IOpE%!P%Kc+udCpYn?>HE<=z241h zlcRjG=N~EA>n%=p_N?_rZ{D-#=CxjD&lC3W4{M2Dom^V@fyldMZE~v!pXA5diy=ML;dM%O5gliRY{}a;YVsIU71{2`2OT325XJM+UB%PPEz^yTYHeE?(46u zH&1FnCU05ljZ*05rQQ~ZSFd^_uf1i(No0B^HRhwY@@lEK>9v!*;Y%9~_IwYs zu&17)<;k^$hbMpDTC>*ubB&WzqXA&q@HbS82L7frZ9?%L{YuGO)_P;Fy?Kv{EJD%9 zEf99G=*!FVa&_|G8Fl%mp+f8Y%{2P=wIjDQ*;)ARSPh#Qa^yu zrsg5V`UGt(u%*eLwuhQxy|Ve@r+(Lqtow;L2xSm2xjFVF6mJ|jsDtm^x;nY}=3Duu zei?pavcnqcP>PwdwRJ0WcIYG<<5qUU&HSXM=hAw0{rMoVXGJyZq+lBtd57W$dcQV# zacIC7uYF9#Tl91fuh-eejWn_~#W$?*w{?#mxX~I&ZEg=IfJdS}%MWdCsl0F8;{_7La-hTe?*gGhJ}; z!0Gs;x9p?M^hfT#nitko6ihDrkg9#0#D{Ke*r^{fs=hdR(*AYfo{4r7Gf!oi8hCM9 z;`7J3o<5K_@uT?U%iYnNe&hAMQ*Yb$_V<7C-Y?$!Pk;PNe-Bzs$kd3wue<40|MgE# zylv!f?p<2gbnk7i`ewM_M!pM7G^|8wPP2Ksq-|imocK$0x{^p5= z&YR06=DX{2OI?-v7Qeld|JJ+rcSmkgn{U7OiG`7S_k6rmW%+}D>2`Ww=fBnPVdpn! z=KYT?bb95l4q6j`)g77XeM3JMX{7Ud%6^iv|5Psfx83um=6k*QnQnJ}ex%TZ^Sm@rgd$)Ya=$m;Tr^+nc4_{9Jc#j?X%? ztMQ|??wHp(2ltviRXkpwQv;*3-7aso%u;8!JJyZ#Y@MCAU#Hf(BUAI#IJd}X(64*x z*XPRpx}&>esy8<^HP@Tz&h+@==cf2=syFYCy0i21b2C%%AGI^1;ycyfRBW-k$-cc< z->OXdex^tN=6dwQwgy#q(6wUeQsiy|j2e+w09v(aWiB zSMtOi^j4yw>rfW^=73@lPjUOEUGcKkQd-NebG1P=^G!8)v1g1-TW-Q=+dKE zNScE-t3Ndqsy)F_6m5q>sVBud72m2hSRzv=8#mM)UfoWOpGH&vb{Bi=-hTG? z@PBq&k7a12C;A~IO~dS?#sE~(*CVAbpi%3+#y<|emR1^Io70-X*L;U%R33c(TIp_L zZ$L}NGJmPMFIe8IED5ODY(zl+oW2Po7M7813D%g1do-0a`sbLCZEON<=ULzA>;thz ztJ=yG!=E;t?E@=Sbik%WQ)=aVv&(d#H^b;RNQgVSTO*HQ1NY_`3HTV?WoDL@mwK>G zRhAi+6*&>V(fjxvoQf%rKc5{K5VI0n@`@QOIM1SZRb-MyQF~{*OXNfz%8t;kn}UPtM zV3_S?cu}u6mx-66+%~+3NTDyIkYb{p9}c z$SbaW=Zyz%{No!pUGwT!Bs-iTE?!Q)`kmtk$KO5Px$%kdO;_Jg80tcS&W-N~?;oQ~ z_4B9WEx>AS{_|Z{P8XrBjuyE*m<0D6p z-9J8ZXu(IL+S_}&+h%&&W zdU<^P=#y&aF@AZYjeLJw!aXn`(9=T&;g34e?DLt>$hQ3p`=|FGI<|1=@$r#`Ll3DB zYvY}T#d1q0d9*s9HL()IC-5b(-4^}suu=S5LTHx9n_(D^Q(+{~xa{wQ8ap$B)7z0- z!m|i3AS6gK0Y%0{-RI}gh5Zc0^uqp!#jO{;qlrI*%j%iA+E}VZz z<*CN%Wk{%OVG{-a-1@ybzH}SUN}KH-8*U~^Vv%mpD`Z&#{pRKuBWlxp!F+vs0(wMq zm>TmgM?gsLeRP0@sk<*cx-dRIy>M)Lnn}{k?4O3@V~6y&Xs5qBV}GX)EljhTeNFH3 zi99;J|JZ`{cYJ}5j`5KdvjJih;zMfoqTb_`@s-hgAp3xi6% zxl)%6=m?}rycwJ|P!OhG3A^jEza6aDn;)cBT#L;h%c>?m}{4YftZjxE+AQGa@yUHU< zR=T(+}DMptJ7oZ^pJgBIJ7#x<(SRriVuzYX~S@6Av{r;kz=8gOXHo}_^)>H zZgCE?f-W?#Wz0R=PI9uv!f@MURwsH@W5Or7`LYI{vO2QPawrQS)ov!Th>DylC9m$I$7 zMGJ1>5G#?XTN~eTjJ>G`0~YHL{iBj>0{i=i;G3P9fmy;jE>mwDZ)yUK?@GY{?+TZ) z=va;G^Bn*`^EbOXvqO4O0L$~Kmt)$uykDEz;*|l(!$Q?AGG4=`+iE+@`pYJxt6F^9 z*Iho?K+>F=r`hB-v97GW2GH|BfM;O$y>hn~88o1>rfP$rO> z<=&{ktea;#GifuTF_~q6WlvQg5$`2Z`_TUVFhiyhZhA~2oW5B%Um)HK59ROu`W4w8 zI?G4X2qf6;q1F8tO~bWRLTmtAz%hVYbzqm=vy0S_bnWSiSJ)t7(EIBUSMp0WF8|6e6wAJ z5_R^-WnW|;)hP+ot{CL4~YQOnjcYR9u>AUFdEU}sSk=|7JT+5x$ z7Y?-y$oIOVz?hlu1WVU^XX>l8{oe7d`;RhR$hFn+2Z}%HD>^8E zlT~@3DY>9&!@%FkT9bjdFq+6Nh+YD10cLfkE;Yj3BwZAZ+CaSlxFBm-Oztw>)Tv-j zk=2rH!M+Bm{;qF5NwWNCW+4t@%O8fgZuf;AJ9gbHppm)dZK z#7`Fx=$>ILiJ|=Z{Ac^jefBD1kH*)AEk4ut@zZT9>=(FS>5jhg)z{o`JNCo3-MH!c zYhQh`gc$DYZoY2vs);LZ2XVX$rEhV3^OY~_UjORFQmNzJk?XDzC{d9UKG-vI-9&tkeeDKd>s8nF)p5fWvCPW&=$;RK zXb-Bu6*uI?0GV_1f2|*n8FmvA6HVw9zx4hueBu4SR5r`JFUa#Rb-%AgNBr2Fw4EHOc-M4V9`5!_m**vHFFPJANLFoGHrhD+&1TcYmOL=&F}j8}>9T>H*dKI4~gA zeQLZjy@csZ2AS#o)B5vMfp{8u>GCghURrMKuWYLuAW%yqJ*+9z`NaSn;QQ9b6G9Av zu}jiBkAd$|2Ra7sF?Su~DGJKJgq9vJb;nz1#{}D8Hx3ER`snBZsf}R;Jov<%< zx6RJ!HSTcvvSorbtK+Pz(y)ijE6!(bcSQa2I)iIW5;dsjJ;Lkc;m(RA2lpvDygWX7 zXhG`YF05cEKPXvJWl*_TJyPD9r4$S&^_MZi?7ti|pw4e>lg%NW_$ zFUE#hU+!)dalW4T_Czpfo{4EP$Ab*WVm7T4g(bWWDsE$yi!@t;0V~QmK)(#z!T$1o zjrkfhV`bc9>^_D~-)<3q)=o|POA|d7nh5(#@6AlxGF!$+*k^cnd`-6RuL=NtZXWpJrm8g&kgpn^>0N@0$rf)> zrrP#WQJ&sQ=;hr1%<43?sf7gbUUR-J` zV!{R#M`2m&ueqbKld? z`F}8NJD-~#>3o2F)_noGe`1$EF)u(dWch(T27mf%FmUh)I1JnEZT?roy7rQWvGz;bVgoW?G= zdb2InypUn=YC>`S0i|f6{@jE@cc&2^p7p-iOxAg+zOET!7((h>>jG_s{X#cad)ukq z9--c~RJYzcPhu{PnuVySI*_qf2juCk&k;jReWp3{ysiBPo=<`XlX09<=yhFfo!KS13K=C;1qG~w zO@Oea-d3c)p3%#Wlwx3){{4InNxrfPd~tdxwN==GuPsuCC1@3yLJfo=-jjyr`fIw| zmhyx4daCL5L)}qz>Ri_M85Q>297NnfXR2CZgSX6TE4*c95i>3CJ7yts$h?yE5aqhw zdzNZ4w@C)4OUEh*<3Uqr*c1-1&8<_gKXwQQIb3P>!yE&qQT2AgL*WIH(D)p8V9MQ#_wVc**{2b|Nar>;}mUwyV zbMRELW~3;Onf#1#?u-P(9~xgOjLcfskz@ESPAWYEkJu04_3g3kH2-0Z`o# z5yubTTgp0ee+!oIuQwWrV6qa4-GW4<5eO7XEMV>6!vMo5SiZh-Z1`B?zX6z9Oi=rDwjD5Gj z9@PN(B|Dvj_@nm$kc0?&JDFxCVF{{>-EJ;Xi||8wQ*mQ3jx9eI>>CKi*#q!iB(=_CMU#SwUxe@rbK^m7mx$acl6Yw> zh%MG2R!qe(l?AONR4(s=5$)(Y&E2Ec+69sg#6f3O6yz z)06NWgbi4G5Jt;U$~y^yH>WJnTVkBqhKNxu%f;TP|5YKWfDVZO4OfXIE5mn?)M)td z$#n1$C4C@?u{zm3Pf(#eP?$N))>EOV7|Ldftc+2VbB;a~;Y6)u!ru0)L4Xq?$#7DJ z4uB&rY*sT7K(i?!QU5|yTSNaV8|B3Hw$;kY5UmoTUy;GqBy%VsgmPF{^+9(DSd zbjlI5uvI||`Lmz`4Ya?!Q5)+qlu7=1azJhYfC$BVvsSz}`^Oba%v*>SvJ*(XsmBNu zO@H*4v!F$A&!ZMk>KLe3sqL8yHPo{Lk=5H|>YqMy;8uAI&Sbxy8XyOJlcLR!kLt(6 zEkN!!fp5z_4%meczAxtoCzRI7yP@CYyJYLm%_;4H0;qF7TyY4gE-`wY*DI<+!+9j& zG^*sUzABr9jn_BDdB{-P4|FsHDTAMDM(Jwo4`cEVD}bp%jD~6m7c78Pif4|=Py)US z{Essz^jbEq?eQDNz%nV!&7Vv!eP~eQQgx%^pSxTEh2d=g$R#SxA0A9IKa)%|n7ouu z0sT$W5v}ZtU1e&K94FONhSU5^6@-SjiO`*?Le+PvLX@2|$B#`KwZS>jxnhYasur7) zw@805ZA%J0HCKx%l_jLc>r>h5K;xpNmolUnJXh9^g^Ldca}z#{vuiV(ErK97<;*di zDSS6X1q0vhwJxlgueh&7i1Z983^ zWwwY`&4}WAJ5x)&*o_KZv{_N@WD z=-{=$UbPiqnwScE6_fS>Tx^jGe^`=fG?J;U_E=>1n|Pk2=Pj= z&fb+o|Bt|vpRl7}_ltwPvkP0Eo5x{fS+81-e$5+3S?-d04@YtduRP47Z<%e1*uro0 z*Vqs^JVBLUl;!S;fLW+E$1JM$-{gWf4^&pKPG;?&{;ReK=84}6kY%NNQV8bp9KrmH zl+oh_ousHyDx>N5mO|CHjlcA!U;fo!zUj(wPg75gFb4sZ&MZ4lMqG)6fK-47;cWr{ z38~l?xWMczbwI@e7l4q1&V3;tC42&I;;-bq;slcgp^qP1DEDFH%3oRe)sbJhGW7sP zB-zoKUGMGkkeC=FBiz@AVXi1)m=*|w@{F@2+chXBSjO-MiB*Gp1x6UC z;zU+D4is!&6QJfNgHsYSmW+@B4 zvrrWT`*{yeW0mk%I$MPuSF1%CuQ=J}BtNP{QNQY>{tp8?qe665Ivpj|;-H=2pe7iE z3}Uk|o_!~$!a)sa&9GSJS>wc7XIhEJ{+iVgjyfeW4Ha!Rt7Jc+_ObyMZHJnARCJ=d zOBS_=ptKGQW>rSjKh`0rn2$*Vdh8fUQfdd(5YlEtNHvt64n#U(saXw7wH$8p2rJCp zetKT1l~%^rbwZ8~CA1W=)Qg(YQUrT_U}>fM?7|k85LVw1 z&l{7#m>igd8|lIcB{2z(i*ZE8&KfoK!NJmqcc28MBF5Sr%JT3~ zslcVpdY2u^5B$v%Pc0m(r~F`-Opo((3-Ho;J0--rVoi;cfvC(|;&j;u3UH4fNRnCR zou=}ndyS^K;;Tir*&xA3*ZsG5-}(7F z-~C@+c5-~v6<1yzlK5sL_Lc6)uiv$_Fml&_dUCvT;LPscH^fa;&wC(s8@=GAxp z8|mnOL%naST%yZE&s^X=BWyrD(b%LLhlY%MRm z2*w3Hh4Bo6F|`58NNKNsQv{p6kG1VoFT)K7(os@IT55vi&qMO(8%a*!oW)>xE0Rkf zyT&fqCK*XGYpZ*Dv^@?iQW(VrDj9b|`iPrTsJEl|h~9)HJk^rO33Ut{$_#=t(W}ZE zRiaGKh^f~YG*iaOH{Q!Et5o_qW%}HDD5yl&bHWBKN(VIobjyC}uq{R8D-MIsN5tJf zU?NL-{#j-=t*NLO0CuZrxw8G4UfN_f?nOE9IR@qyL63E_ECYrp&3>r?5NQ^S6%!8h z6L+bIV_>zYG?5iRE*qvg$FNm$7l^)*7FHz7BT3pYyc4D2C;bJEZAXTvI2IG`V;VLx z3v^AIXKhnkNHk&rAia2VM5Qd+N1`xjiZN)ejr|_Rgdkf73GXa+Sq|E=_FJ%tFUctni z&Bw6dK3sTJuxiR@&6(3VlnQ%frwWYXtr1A$xW-An6_bjMFcYM+29aVWhvlMWP?YDO zpbwFPocSm%g;+#0MKb$Vv5Dxt_WyhrqW4|DaaEJ(eI`P<(}yo-8?5}m!OH)uz5Q^P z1rS2yni0$YgmH>{%F`)ZfUa>+=ox^8@J89kSd}D?jA3)-dfS-A|1`G1S_F`=0G(NQ z?Y-GgE2vvxs3iaWK^8w(t-cAjP`PuWIVv!39g_A@V~wBDPZqxdx#>v=p3g_48M7SG zh(U61Rx(&;l`N_6>@LR=A&idgvfA4*pVCrByi!g#mBptp#Dv{y!$l`+h{S6Txes>A z7+Gijuv+YLM8V!-xKr$P=lI5F*XLhD6p0v9xc~sLI zKPdma1b}8P6>_pzyjV#QGgQSfxq*)^h<0@YP6eGoR3N8w3}Spw(La55#(+tzuOd3qe5fg3%rdrrW>P^dN&`bi$iDiSZ-u5V*9 z&1I-T)+#Tk)mcIfkr66)Z#6^HsBEI1#fg(^z8=&`O#`#-^1~pNeXBbhjL^OyKbAlR z{cIb*@}^(;)n7?Yg4>h=R+3g0G{eo-oDXV3KZae1M~@JwGOX_Ng;d*fHXj%p)4_lX z%9tn{QyTCUr_ELagvQ;*3y~}rKr|f`b1R0DtsW5?G@?w|uofuD5W3BMuqwi-95{t} zcFQDlp7>ff1r?{`8l>&YA&-W zP<51v70W^*;Pr41yvq8TqU^??T+3c#Jg%i>8KT%R1SApo<0DG+w^$hZtpryM080%+ zIp_=i&-V%(B5udB0U~ZBma-d7`ejMce+FD)LnpS$51>{}=x>b@!&$ans@OWyxYa-+ z{Loa}Sd2;B8T)~?!)8oO%`nhalVIwR0)1g)K5AYGJXjJOSSA3B!I0Z8aD~bUnX8AX ziZ?k*r$t~*m{Lv)az$fsrPuvI*!`|S^2eLhwo=LU`9I8qYeOuGUyxAu z#*R6?rSFqxDzAHbxz<0_ajkFL>^_N&_G_*D>*E>!3I-9_m!ECa*UAyhg=CG)>|+Hp zbHfkIJAQ4!u6*3c*!Vayw(xNcUvn>MG8V7dk&>i40k_N7gf;NMk47GtsH|gwU=~xF z*jhnJvNJ_}5vnQ3qHKyyd*&m?Fx6BYza(zLT2X|aUAI~dqsVU7YVOWJ#u}RuPti>Z z1y)bW2m93SLT#KOhAn5nF&k??|1CA9-X+B#G$v!cq8i#5HR~ZV>MTKOAD<2}Dd>g` z9n*PPJHOk)&OfdwiO9}EuPrKK!<4$`JO!wCJ_vzz63GZHo4*>f8MewYoe zul?<6+uKJ)z%0TTHksNAG@lj>5t304ApjnaDuZBVf=Gel;>CE~)yQvs6r?D`Xkjs# zg4vhu4_+ivOp~B>2LoG}>u;6S*+)k)5bc}S<%^7!^f|ia;*x+kf)QA2QHKPAOMh8BMGGqwX}?3__lrKGFj)tglU5J;1jWn?_Bzd&Kxdagnyq{Q3Tx~oRZ zvX8RTY1KAq9JdRDley@erDy{~7=qmi%L<(5${ZAz@^mX9hTMCKn64wsWVZ?^Pfxqt zR;D8s+LJ>lfE0X2A5}P0z~O8Q>iZ>BKA<0u=wM{ScEFSbAHwYUFY%Y-ME|f+C9UPt zU!S9*K^A?@EEH2~L-fUn*D$o~H)c!I8q~LKJtAdf{k6O>YsiDjiQqL}SFN zMGHs;OOW-_DEotFFG7G^u}BInp)U53as}IQg0=2*`cQ_~z}bM}NW(Q%FCjq|HK#mf zX^ZDGC71Ba%8B?qbvTk4|1A%Ks!NAF3w1nI*Mv|0O$g1cX!I>cDFr{C#<OUwfxgBlv&9IUK zFGXL0%%=h;l}}Zq$`DpQO=3gFU;3v>-71}Q z?VqM*IB4AhkZR{xKjfK&$Up#8bI*+i$hO-0yt2KNAR}e1U)d4ZQol-DEmoUm%LRqI zPfOd(Jg?ZtvqQ34DmIs4yy2-0!t}xJC52P7fRj3YA&xmSD`#Q)EmXJCeQEJg;H;pv zCfK=-a1f4WlEev;&-Dd<_^85IL!)X+c@5#C#G4tfOCH&ujfBR31HTPu)?(on(27ZaK_rndu#Kqn`OMwxz)r5okLCf4~kRHJ%tX^ z&5b*F)z1Q&N@}x7iwDoGV$}pEz4=SL`7%%ibaA}TFEVUu|8tHtIc6cqX?N9ygdsl0 z8V3`2Cgwz#4;QaE}*7)f9cXx^D`D}_TBDR^$(ZMKrM7#332 zhNc_~UT*N^Y!)GLKaP)=#aq{EFK3Iz>d#;%X>bs0PvhlmR>$$S%h{|%%Nfk9ow_ra z+3PZxd8*;bPaO0>A)TN5Mz$=|Re;6w=^<-t+XH1?i~GKDbGdW zGg8e>FeTMn^7+A6dpmlT5HjlgE+57BI`R)ibizH6oGOnOKvn_LUBSRsi&0Y3G71(6 z&g6sBxp*@HN=b?5^JEl@xjo_?%S!L@|21^`&WKDJ0g6))gH-&89=5q1l5%c9Fsq6X z68|YdM{(`((PMWswEKx6UmY+BdxSK;mh>8m;HUPIPA37S=QW=u` zV=E-7#IB54X0g6D-LR8FRbs1S3r81@9$h%51y)5S9)Hz{OtMIp^K&~+ZPS2!CSI${ zq~7ZIx~{wB7Ss>fP?!5_4Y%PFfdl+Y2GC?`VL%z>c_x^VjuR}10tnP?2TXB-1eOwl zAIA=P)BWJ!lf$AEJmN;k#kQz&E6Ci`rNufgU`m#sA`Am}Y`4;K*Fd1+@h+>~QYegh z)_YrfmeN}0_OgwD^bFZlcs3ofWi$;)hDBDD6XxhNsV16OQdZb6o*g+h-ClO!J+lE# z48zma`Z*NSUAeSlgZ5P7nx8Nf^8qR2pDF})#NmxlhKSPvrW8S$WgYO>MLKiyKPgo4?R8fqlVhi z4;f}%=*sq@n_uC|7_|wybtkIZr)mAHV5BDoW2EKo3j%@WM$FV(>_+pPYfKcLB`Edy z5Kv01a)+mo7qQ6@5!`wB;9L%Z1(7Rf3T!<#6xi}Lyu*{RC+adUq0UCwd6!d8*%`oN zkF?@3jRh{5Fs(LP!K-Jvb@Ou`XAZ0VKvSS>1@%^>8k*QT=D=cDAXu}?wm8E;&Zrs$ zO3A`m3mjk%~`(hU|X--RpzUwMRs zU_phkXTB?^^Bh);@aP;?bQ{IX`z&5(`AIWYw1%U0ugncs#4?2~^okqG#msesn>iU`>tQ1O`qzOl5sBtNGRt)v(Px8w zmwG=x93~{rpqfW_IN)bZv;#lhX6bZ?uyBPsn=xJxVlrLH3@|$ajhg2RQy>u{Ot_l|gvl zaAg$UPmYgVd3{-Sw>ti;hJlVhE7k1yv)3g9*)UIrF{`C|-q;MxT9A31eM6*g!n1;jE+!x= zA}(`O=e`*4vtfV)2^F1<(oSTgyq*Gr>L_qf`K4l|=a&yvcx{9eyS;Gmk;Z~zg`=c~x7@ub#ewl< z`>98*ofTaMDDzL3l$QXBfZXICO-3yJ!D!33c?zh#81FwI&PqWu7s>&~r;56VFy@v3 zF$W`*;KTIwa*s5&iV!nAGU!mGugQ3G6hKA>-$-9IaGx+&8-dxC8M*xu0JT_p-6Tpc z0ih%fh0xh}9>ODc;#o>x-CS#+h%O7`*DvfKO!E!rCgaT0d>}A`pnVre6&o`vCCG-4 zl9r4}>^Jdd(NdumJ8Y>MEJ6zc`PDvi0vpa%RtOw)jg(V(q3np+8O#viwA%e?4I}OH z+DEd#kf%zGG-^SlL2P6{6BR1AuzE63TV9MI8LI^*n*SavVZgqMv}VF&EI*&MD0{m9 zL_I9ZU}H=~s_L*9?Zf7fd0&m;S}D!-P!~(ZP3|LFIEgi)SYC;IfIqRniFl1acT`Hn zIQ(pb$4m;b0z&T^^6I#Fup=O%d8j+4$}}4f3^y6T0Z^_t;a84q)R}1sVl(w2blxlK z+X+S#8F+lmOB$6d@uBE8x+;9iBijQ^RFOo}CPb5h)&J<5iwHRFj}o>}feW zJ#nrCsv{s{r{6O~hu6Ai2)`_qvcj)-pDTApj%bt+0_ikmAuL?;VzaX2=&|wfL&u0q z;l?6ttM-eoe>rqaHv_GWZ#i_7Yp;%eC3IzVeCf7otl@Xg0J`abpC!A%nZf3g&OMqq zt4{rMjP8YnLkg*x9v|0*OVdXeAozk~JUgmqhmIXPx_>%SzB0aY8`gr-R<^D2!{Z(f z6IO`V`X|ggME_TbA9La%7Hh};@$sX_81SRV7RSdH4ng+9p@lHo%j0Xe5z5$4b5K%B zFlU2U2+Mjj_@yy7ve|kLA*y6=ak5v&w}{MzqpQ>0%C+c!9a{Kepc#$(HvX%n`Andr zEU#;s?#AIxbdQSeMFQwp-Kz_mZLA~NRW2X7rlJIML?!sKA*h6!QUYYrqzHVnIDp#a zok;efKD0Q#gP2m*v@eiBM4v&-lwm3j_l3??B8(b>_@fKvu<*q`)Q~&%KQww;R{GhP z{Z+KXwKHdi&q`^HA6nhNb(-C%J-9OdJdHJcW&ia4L;NNN!xdz$J@6Pl_~ZWNg{?caIGkQH}7T`v1%gjP4c zstTS)UNPywY~1xv0sRMx1hZY>SCPWKmJz{}@WW%nqx)O&FE@xUyXUNrX1M2OmWPa?Z#f<~R z?bj`!zw!9&lZ_--8Mw2*%+*F zos(kzCA&qGj^Wx(IX_JQtM(snT`K|n$brlv%R`oD!CD72SnBGbTJJw*5c_{ou@j;- zr+kOcj%fe!USk5ixVZL5V_^Yl7297p zMFFQE^PB@Zk0Z+v9SM|}>9$I^Z3s;T7m0H%m& z!yIfErzrMe@Jha2yuloZ0I8G-Vx-&qZpiguC@Q7}Xu?ib%hUt1^P~RH^vKlaNgX0? z(oN9XQdOMfANKJ$;UpLZj1B~}SwS=*qHN6Ff+=wWH|+-aQ@J@eEqZUE3I2fcl!i!I ztMLzBQt|j1;*l`Ta8Bh4;H;e{Op{W7A-K~8Lh@qi&ysX#uDcPV;Q6!guC7;SrY^$= zUU}cG%Vp3J2ZymPd#{urPms@d^r$-mSv8chq*mP@onL=dpjC0Axhme9S(gU-v2A+EE;6&!$Z6#1=_+92LT zWcfwF9XWE7wLua;`NlBDgU=TaaLymd~@>TGCJK)68--al0~3yaGUua7dbJ|G;j-d-3ki1Q)$ zs6`{B@0yJkZ_i|HXI4CSCVj1#ZZlKZkB=n;T5qecnvl1uWr_?+PJst-VTA*m-d0`m*cUST4mlQCB%(zmz&&!`I57?HoO8FL^&)XH`&B!jnpUe&{g#Crj<6Y zWwT_$Gtjszso~+5rY*>)^5&<2Xpe6$bnPZC@dt&Z_pcT0ENTDI0W9hdlC)nuC+(jm zY5(HBNZp1f%}TX>FwjF`rH;3FD6Bw>w2$wbq0ZF_6sC8m%jpCQ4GiuZfbB$Ct7)lQQ-wO|p4n)CUujQDfJDRaz+t z`n;8XK@Yts)ADD?T0Ym)tmsTs0vFN!U)P&HGg8)8jkLFDZo*pZ5@K)eJX>@CztpX$ z#&2XD)XDppS9r`jHlL0=rk0{EA6jZv;OW>OX<6C52a?;)FZJEZ%gb%XN}5O-TU|nkD?-C*7WFqtcCH zsjec4k2b!P{UHMrj6}f0)HeX|^L8_dXw#FV8@b+pvZD9bde2gIH9!DIE3$w~wcOu` zL{VH5JAIuyUU2&Nr|3~%f;He&zcrxN2bc(`#RqZl)|aLY-}`R)I%qwI6t3* zCqrz1xL5(k;2lCNUo8v`tK-iaK0?61@6DFJA38LEuWv69jn_f=?Qr1$_Hl$Y_m_l6 zGuJJeSf4G z)hvTTKs8EE!-bd|M>SS;hH93(%Hr0We+7@y|>AZCX|jQ;a%yhVyYaE2NVd1f{uV&bZ(F@xmr zg#@?>Oc2+a@CyyEu|hcyZbzCnBHH6{8*a!?+lFgrg<*DN7)H%T5M%Zk-3C2Bu-Ph( zDL31MV;cKAhu5Cnt37gBoo&T2X?``w;S7k0aTcDL83#Ap4`gD8Yk|!3TY${e*08t< zZ6T;;9@p1;(eVv0vJK&wVq=42(7dLwhjDZ+^`F*GeIt+#xY?xw}!7c+D)=C20C6ROXO*6p|sACcB=%R{geC-Oaftd`O=@+CPWR;|w$o?rfcpD0a9O(+q2zNpoC+6&o}BZ3xs9=2tV$`1&@^ zcg`}SvwXEDG|U)5w88aP#ze45SLTbCT%Qh(#)9X(O;54)X5*-z_W=wy2Hw z=IN(!K*BuR8DD8mm}l=B6Xx+2crTTgAMfoF95FY~9bolWA5&Pdf6F}rS;HrmFpm^^ z>jX6XfJ4E2i@hNDp(yn2=Dc}Un{ptn&gAuR>Og@z`e&BZ?F2TcR-Hwd+GglaMiNfX z)aUGqm6BzzAd!#dW?Y{`Qa-5zFJDuAQxaG@C~4Kz=O|0nm11mD7MP}ldK@pH{?+a% z*}e$)@T-x*URd=#QiKgq3iDTGK-ZULZHgdm!CmK0Y)ZIq@InkIB;OSV3`GQiG7>g5Dg|rdYAkIGz@uBW` zPo`25wGCqy1I%)X#MP$EBTWT^rd%mX)F$s=0BDK0?1`PjwXvI-+G*g^t$pgZM>oqB z(vT}Jn_~;TfwB-sq%&82x$;C9*X(v#Hw9sCUJIjUg!z+#FztvU*r!a_fb9l6RpiW| z6nRD%C&uMM+rWq!VbMrg9Re?x(ckv{Wcl z+^WW=hQ-#Wzq9cZvkycLnf}g+WM#2FwMf&MX#A!y+Y;}KOS#yv*!p4HZgk%27qidy z$nEg!cP%Z9-1VQH9PeEDkqSo{c=0+N@&Dy~=*RPkEM%{~=7!rzYWKDqH(h`2t524E zc+a%xU(Vdj&3{-w$_CP;Ba{x;zW5ILz%nfI{VuAug$DVuB7oR$e*i7bDMBa25uF^$ z`g(`NULP`18#~>cfMH7e>mlVou!|t9nMbl9qm$`gcKOW)#SvSBW!&;0t+_@YfXhQ{ zvbis)JCE=iKR{B&dEV89&UEb=LWXJs5M?Z!E>e;+Z@m$s7|T)Khj0pbxO*l3fA-!r z$g-=t^Sqf^?~+uKcoeIuI5ZK}6VrV^SRd$$aHZXv zj_8T%4;j_An|77w$~y$j6X(n8N-gpT-(UnSuKvuez z-XUMMW~O%nZ8)LjDJ-^Hpbb%~*p1d^URaz!#zhHYIvrzGPwMZ)Y$HQ zT5hGc2;bXp`jvZLf=@31~3<;1RnVgkLNOOEYtx zUZgNF)!EVs!j5kuf5&Tddbn(M3|-hER0~~*qnabN@5~%xrb;P~OI`5U@Hv#0mYFuk zn2FnOCo$XbOkDS#3xai(naEMycS7oDB#Pt6G!q<#fO>6`>ZKvBT*n=f*A@=w#q|3M`|D7Lk`N$7?w-R%6jHxtU98$YhO1i>IGT?b-8DDP9>=W)x z=k15iB2;|Zshc~8km75#02238IH#ZG1FTFOUl#Wr#U#vGBwmtDff*SOxeRzz0Nr(Onjvi6K)VMQ zqr9U&ca}IJpx78fk(Q2sK84s}NYn&_8f zlI3=tFW}JNCCRcRf^b(KThchh6NBvP*MR9c^IlFI@TuC<^=bwloel>AA0&`Dl*om& z1l%0wNA1PFxb1Wag)E~djVl5(;z@(dTqzPs>=v*8aLB(Ijh$%w+s(#K1q8tSQjWyu z+)jQnOHx)%miXz0z6ph|3#SLGBpGnjyB}8X+w~ubmJX1tqpQ-KN z8y$%o3Pq&ZoOuT$wq?x}5=w49mXofK67lFInbB9ju@$yS*!rB}|#U54J7V zpr6i=?bJFVi&xQ+s{K{n$PftKATeGw>7#cd1N7Iu4zQ;rOR}jolAo?B*7`~#Z$|w* z8Dv~n5GhIlCNkmHkj?h82HC|GvLAQ-w~p=-iofpH{Z`{vvaNcEVZ^oX-LRmA0QQG0 zDf7{i=sVv2&N4#PkgmxJUsXsy_q@H@;bV-s(eBmwkmtZTt^Rc5vGGps?X}F40fbxp zK@ItAtIQHyUizj~`F;wdsSSW?O|D zUrYpXnM(AhX{He|4L0S#u;Q`ZbsfF>-MUno^*uW^bBB1;2LenlvUk`KnR{;Ec+E98 zv53pLH0xzmsj7I;ck6k($fNnZo7V1`VmFkMY1T{gQZ0h_(%ltps^9Ny#T%thFGKyQ z7rpG|uZSk}m%JpI&@VBJe==2ua$B{b7uVH4b-&1yr`(h&z1(^}@~bj}onEebudYM= zz>g8^O*QWcjyMUtgXPzK{S{(0_G5&WZ@9L=S7)YlEE>n5gpRBtNLx>JZo(D!95({; zD_OPg7$WW~mYtWZ5uKB3!v8bJ)|U3_+8HD>mF?D58cWCOzUv(0%p*eMM-Uov)k*<5 zt%uGj3wbtTKw|^;T zx_n+dR>tL{!=GQ?ulas`GDc(H^QMo?-#mZh`OmXEZB1r11&B>N|7SLCp7@#P7bQPm z<4NxvS-ZJ&q$o2SD%P2&#LpBZ?i-G5xH-Q4!{k-{0??@@I3tyON9Gt+*`a{0tR$|@ zzfqBDkX9=4&fr08a6HQD!3tKEm#V=6tBCl9-DzJA3(6|rKK*!hB`LVPttR_4Sq98FmZ{B; z&FqB{iE|$%460=~)#Id`rs^zRH4z~m6B5){I1Juo7?W-@sD=q;9fiSAB2yewwN52s z#?(5XeoS73HH>*f1s%S7H?Nopz=fQtbmf}m=?e;@7vd-4O}|5NHAp8_{EnGt74D5f ztx9$8muG~gQQ5YShaj0lsoYWW-edG&l&j%2se!Opu0mu*-A0-pq)G|pK%Ca*No3mT zU^&qp4m5C5Gicfqdem@aOsc;nGA1h%5ZL7>t-SPHHa>M+G=D$LL5sKM&-tQs^+)S2 zrcSNA&-v)Sldia*JV_>*qY~9&F+4hgyS{&h=n3=90bb13dGa9zs)SSET4#^WaH@ET z>^Y5l_Wc;)+44eXx+W5b|Kw8H9-kmDaaa!=G%1--gSRjhjylcx>VU%sN;(QaHEr%AaHW&+l!soKpnFpNY^jbQfg zpZURp*;iH-(LU*fbl~$gD^Rq3^pKWTVD{$b-a5K_H0uxB`$}mmagVsJ#U9gf=-}1T zf-o@WGadH}Go4R&jUo`Fz|#r-SB(%ZrK-jYe>!aV@aOxU_xvM2bMw!Xj3@r)TxL!g ze$vSKv#)A7fA+qH^Ji~sOe*Q^M|{Pc1~P4*{0#qX*Yo`BgM#P7s?s+@KtKCJz)-%p zrDGqHfT%M3O396xtKruMU7DDB3KW6Mh_Q!zGH3QAu~02hV}coK_GK|THs|ib_W3SN z*gpV%qw{bkAPViEK?Dr7OPopQu4w@Zimuvd;2jpvz+RT=9Ql_CiR|T&1!t%+qLO1{ z!4@#g@sk+`JwR=hWkq^hW8@ibt{BtMT+aRj0zD8^f}*V?H3U!_wS?i;(!!CJU<_Q0 zG!HZ&WE58DLs0G)f3=u|Ds6Ej(d7lhQ!5&*YaHxk#%zf=HR_=;;1(NE))HGS$&R3f zgnkVP2tOW|bOkk3kuLjD^qOTz)@qO;tU@O@G+84mcA34;0#%lfWGx=dUl+SyaO;p3XD|efdacr@tSA z(KmVaoqEGjs==iR;WwRQAA&WVzE>8bZ#Ei^O5bfzH$feKm-0SNxEL%#I5pVzkuTYy zLf8X%GfRzJl`?K&I(S@XW2JQH2#vWNud|N=6M!QPj#z+a9X4Raze!sKmLY1f-%C0BTZFuDYG;tfvbVee# zGeqCaFp+D`s$6LpsmX7WP*|&}p`ub#!QVsYYSJug^`Xnf(==&_pfVZyj7V^-Rix`z zhN*0{1tuB`k*=MoQ14{y=R78{3kh(JnXAYv-$1}Tl`HZ->j9sJ2OW9ZL3!5CADH(fdh9E zYwez#a1&%e4$*AcV1CSqckc<7_j+Lu;FqPyXu=S29g-d=BO4{*hFXvzu))w+86LBP9Q9KdZQ`lYM37H)w#KZ1@r8?5|ExF%0*gqOG1SAb zB~SWk_7-vAEhKpmBCOk-N~t6N*%s*+$Kc@q85#P8A?CXrIC$L~v z0vFosi@z$MqO|Qeejgf+cuAA`dU*M|AKF?c71%cSdGZCSV+%`vy%vI>!BHF8SIvyw zzR`(=L=}+;jV8xfdaszM{@Zp#8^3QsFs8+0q&jNy9%Y>qTgBW{RP!8oW#r9xk4znG z*PTwy_!#YXi;+{~nXmM_?x#f?!j;v=gyWFy50M$xrJ@pfefFwH4Njf59;I5~zraBG z`A3`PY6dvfgKlN@jAM2y)gu98DZ;`ChZ|xW!>;OkrGqkukK(+n&eIrdFp^{D0p@;b zAC<}5V(SJcW0WQV2%}nlhOhP_fp_17AMn>mfr0X$C*;eAAC-I%AxuGkY zYo*O`;&raiJiD+iMgFIMj~xb8aF*5hYN4x+VuC)NA@lRqd4WcxgGO2^$yo-RpI9O*trtLdxF zc#*o^KlAJ?3e{qhbfyPo6g;SW1^Jzfp}qztOKl&}7QuKfXa`%=-b@wYcX*I|Y1r;K zA5+hCy#~HYHHcS)8h|SHCixu>1=qC{=McUcVm3%;P>#w^L#G%_%$AY7)K3poC97$$ z7?9T78F6wR*p9Wxlc5;Ztafza$90hoK1fSBmT2e2BW~>8h8xq9=z?b3n&FaK8)-HT zThMw+GC~tBSyNND*dKD()}U&lz~ACr<&8T0~x`K%FSqh zp17ZemEiR%+SEJ_R;ea0cz8p6YGJu9YId>}8rP!Z*eWB+G^^b3HPecBk0X1{WFL2NoT!6YbwCOofWa3-o0$6KUcSQX2+*^EJ2F=I#Np^y1y?LP&v^9K%ySYicl2EFZ&-x4E$A9Q*q(V# z#_A*Ycl1W%<>O*$6Mss6PCI-cwLEchaWVK0TqitQ&t*b*wq23}%6btndRt$UB#7q` zco2Ae?p_TKl~^W9i|{A}%m+T3x7jEn=w$VPf`Ga?M|Ic?dk>@TnGQ9wYvep^Zl-#= zB_GSu`2>Ulyf+F7xIGI(zGYyzHDW@ev7I*gVQV};rGWo4N(|&ibYGqn;`gRRSl(1N zTW$OJlesW43G|~;G|&@PDkGP9AmckBmx^<1L2rQFc+-X ztD!~Q{Id24=ltz9)9jmO5%VibXmEN4sd5@f)eKE3hg3mjhzAnPPzVa1#K7FlB!2~g zu+3N329cnRf*0QG$<3Uc#-#QTjX=0eh~ty_7=F;&mVGs$R0@$J8y62|+7aE8RT*ek z9Q@L^24#I{8hItu%Bz>+4a146)N0#=+3=qn`ZgGZ+g1ltP1qDHpQ|YYW3Wp!tiF?2eJ}Hpi_c4@j{M?nOXuFU@Av-OU*2{1U4QZ0bK!VdlDDU3?wy%@ z@vU!t>}?Z&de_=LlXt!8#UC1i$M?-ly!e+MeOu@KkKHrz&KG~U=6&Z@UjOOYdpd8d zzWumKPdpVs&_`h=L@6@g7%RS{fcYb8`1kHQd(XsOKV7<&1WZ@`@~lGQEFI*xh(o7?#2FZt##+P*Ph;~|J(==!WP!(((#aY97L;d2gO%7m<=II9DNNX0q`k5 z0!5Uiv$dbcH;%zUXf1_ECX;Dxf|hjX_Y zK#+T-IWw6kOk(6t_P!#Qj_Pb070nWg zamcoX%S3MAt!uM+&IO-K1Qv3oqfD(9YnM*sa&wL(x)#?Sn$KF^WedpsjOcDJ{?`Qy zeB%%cTrwv1bpk7lkrj1sEVAOOL!Vqc zTgEu{jwiFsrMIoXuY{`F{f}?YB-2-P?U;Yk?s{zes2S-tf6}OI=bvPvC^L*8&9*~~ zg)mewc~f>&z+AcNXD3lpvU?~yg9Tn_cbQ}{!4d^YlOg2oSQ=cAgkW{}QA)-@+<}5H zj9rMMI?5f+os*!6QJRE>*(zjPwW{H9cw&9RBre8uL6$pjwhQHXjn#^ELUF8iJV#`# zQ+HnEEI(E%{-4u2mOnC9TJUuuSTafpYEh+WJjZZL#wwl8f_*1CVVsp|AKNuquDf8) zs@tpvNH#53g?4DUUUpDkTx<0(_rCNzw(WH6uLjm?%a`rNadoX;yY`73S8a;v@TXVU zr!ijwlD<(P9{x52?1xjdZHjpFw_3t2+JEbZcGq%)+4xuCmTPPaQhwVIMOqD*L28{N z5VgqKgDsMhpy9(tu`-&}kwYs_g2)x-^m#FV9^*64r25xzGP@dwiU6-3*xP1th-6EJ zggr+`oB(?~=E)t6)r?+Aj^v*scHF_X$>7_G|Fd<;LDILED8}q5bo*V2^;o|~upTSZ z;ySbUjjl6$o3I*5SL@>=DE0yJYm&xYSx&Xa*e#|Uuw1o{#shp*gNIgr52;!Fq!u@h z*VNL$mx?;b-j zd1J*rLD@Q2h!ToWv_W_7ZsY)-bndiWrlg=)A@;vC~a10 z8?t*_txbQ{2;WB;!z^Np136T^6FYYr*n!oQ`{*-_)6)PU0&x{5&R)Ts{ zZ9xH98|~CwxJYwr=5P`La`*tIWL=Xs35W8X4H2@`iij+fF0(Jh;!@l_5pS(!x*!6v zi|{ogv&94K7V=ETI%vsk!jF#8tg+!3o_PgjAE=3~P)Lqn zwjs7}G*%50qvpHRq{(%YBL3^3-Gq$Qx;=E(W$}&+?)a_UfXa zDbnIf*@B7^d>T7hSTq_<)pboOB*9G9ZrYIRakm*XQp80t5yc3;qDc$N;M+!XbzOTu zB!h2Z_t5f19Qg7zOGg}9>uFKYn$;n3H(<+tJ=$Uo0nT2ggx73+ZjxqMl?2nZACr<7 zn|V}FMhd)GBh|d@Zpp@N6u2Fw64~8uxrT^$2)_Q!NW-<4TsrIq=S zm>2>$kz#CY_ozI%`I2Ke9vyY0nI>PSeR2Bi5Z8H~bdK)~J^sF9MwtF8G>`pc1jDj= zo|r`j0e5`qOD)!zHyYO>eiBQe75;Lw!H~%uDvo)eE-QLkC;q|1UN@fP+FackcW>-8uU2E1y*uht;lUdDWFNV>6dhJx}^qPmr}4y^Y3Zd)tV`c>71>#D9$*7BBU8VqFxgHw339(DX3tM%Gvp z+m5OPmUJAz^lj6$(qnD%cKDXY6H#EF3BT#QV-^~Kv`VkclW9?6Xr3cxGFIsXVw@;+ z=PH@vWUb&Xr!yKcz`fWuGX>geO>cE~tlmOsy^AE)34i<{i_HpPJRU756yRe^heG&P zD592H(rP;kv--s}_esT;F3VA%tAc#>e{^kVhwDO%5;AEpYi+5tQ|%*duTb#)$pOZ&(4nEsrK1Ph3lSV z6Mx#xyCWFvorHN3FNx1^ihBiFp~2{i=Q*BBQ{p`gG~ogrN@&+v!p*|;`h+;K(EuaD z@^$>Q{hQ}3jfq8ROxzy(terA06LBEgX)l;#I}u2g8HGy9$7P7gASo%5&7P|Ej|S~7 zZ$HagwiDKVr*1<6cZwg05vOXDjuG3LcQ|nUhV}}vFc$y!CT9Ss#CY3KXS_deR&q+^UO5%PfVh4GVB;px|3Yr$qdqZ zNtSFB!QeK<;jjn!yIBA>6Q$yGUbF=@f3)a{jT6klT_oyyA#c?6>x${N^-YrqCN4;& z&%O?d@)s}zswsS|B<3XDbiD+z zDmpR2iK|jY%>dM@Nn-C&S1B9}S|8dHyM3%G{$eK1U=k@s8z+hA8(v0Ka(%jnjW)t= zDe^Oo(mt$VW56#knU@)egAqmCKhry6LT|SNsBP}~JggHJQS`aI;Hy!}iMK6LhsV+x zaly<2SCa{%urT{*>ZclpS)H4?GO;YXbFNu|`Iv$cGASq4A7q-4weisGiG|P>okU=q zbB<}!kluw;FpVmsw^xX`(4K@@xjla}+@1_}9Iud0>1}2%#zrkDw3-RGtWV?g5|&&D zIB!=9&nQLdV^y(cLNf@a&~7HGhI`AAd=qWONg5s2@dT5(AcPUn zmv6MIOUMCLO7prk^8n-+>H^~Eo>q}$mV$c{jYI|-xxTo)1S_2BSP;^lW{ zt|+YX*iO#5WO8|O7*H96Ojc-=)F2^SW}jD>VK8h3E+giem4K-<%Y@(2ki>wBSW}5% z+WVB=1AfpldPQC8XdzG{%eVK&DbkU~Mm`=WGu;nO0F_MqVVE?k8;3pT)xjY{bs0mp z#bLa0G}8^0Sx>U8Oa-SsC~d*nZ&awpV5mj45aU}!k}s}5(y0W-syefT{FhI#U;Gp7 z`(E~M{*e1o|L|YGuyj9aW(92VTpHVMH}6{{Rbw1E6)Y2MXStWY0u&!BJ?V0hZ%HTB z1>w_o&7ghRdfi1oHDFb49Nwe)i@t0uTD+ z%Cs;e5;fI?c@(IY7SToE$oqShr=O2TimjU zcWuSBR;i;_Ke}z){-E8UVodk6GROm)-4>9du$$4X)o6$_I|LeBD6rqs+30bS>=*T! zeO6)kkmJS~95z{n{Kf2yk#E1K@}L9)U6xc(+_<`2s?(4!b&kZkMV(PDFwfi$?sb;W zZ_BpCDjETJ>uN+F3p2s|=Et|wbdSQj!?m(7W#i8lW?ZLA-7{u_eyTmiR4`J1*BLf?d9EpNudZSihbagKc!& zQuplwsMxaI(OEgvjR(X|ccU7G{7#lDQOeU4_dBt)w@*LPY+JDE&9}=wHt47Nf7mx; z;>@FXDwkws0Wt!!Avha}U^v<#7VIx#dMEownK6qa%Xo z)X0b+EA!Nl1sAIq-(8t<&(35D>_!rW3zHvei@9W)@9{{XoX?MzCTrO}2Wp^Mj9B$! zixE7qOC$xO!baI~kKC?1mmS#D6#;6TPL`fYcE6GnZjYN0%7*HK#7f>YEa%wNQR5uX z5HW@8Ym~&f=Yk{-0sdLXC1PP0F-;-B)eZ1a(qM46Ub~>!sW1vnNBDrA2`wRjhWQ&O z5mnauj>J?=)7;Ae>y%g?BUx2!_dsQoU*2OEYoC86JXO= zfvMCqdxehEbaoK5KFT#VymL{vW_O|(_7rYQu}7i+EV!ggxDT<=$4inG=@?%GGTY*H z9Z-+#0ed~_D6~$%ALhUDEm|~xSvc-o0lf6W@vLLpmbfCO?v9;FNduiBy-cdVCGf~v zxFF?A_zmC*#Le1imYR1+D32{QVJfxNH_FgEb}U0v{T7?0@O1GQ*?jchD1Gb>lU+N~ z$BG_>7OyR}*eWgYMR|)m($74rPF??Kxj{TyOBWy>>0QXO6WY7F)Von}N_PbPa0fzh zXgsk@rWqV3O3B*Xu|TY@o4i#iVy*gJ99;u$JJIj*RwWTrBrdC!Jx|XY4|~`aXGV7} z26JY@^(dJj4BKQ3<M-D}l0O1B4g zD%~K|f*Z&?VocFP0ge;!#TN1afz6pK&2IaNWbQEdr-?@#*;bqf@g3iCCny7dh_YB7PS{&mfV7a!Cn+b+eC=E5jqt8{{Nx z=7F8tG`Y&eY?}fZg+^ueyF`GlA7WjMsZB;A#ul89W3yB0`(Xm`L&ewy(J-D?Y3=V! zh?>b&KBnpjU``BCznTaihq3g_NW>2GOSk)?Qx@9gMpzO|y7of08b$>_#Ko|45xc>C z4#B=!(KLNgFeD*};;=aIri5lY-ToFX1v7bI>>t5DH z4Rl;Av+Qs^ms&Xgl{ns?wTfogV-X5Rc=1VGdP=gY6ngDa_uOzuoPBRm6GQ?peYsVn za=Zlao5jYV%}Qm)yZj9?VEejJa>lQB9vX+~Nznu8m`f0ke(8&4jt{3?QVGeC(@O`C zV}(c^>-;^dC(?9vc9@ostf}%bkm@=OQ zd3(4laD!-W)kKX}{84_t?ND%@d+QLP_KR3NlNAW`$P%-j!eS9}$I1L^PE3Rs$8UHj z@vB>{_z1qNPU`HF$>(M{9G4~%bhqrmDW=b8u-p7plSC>_24eUPey`$EO(psuCVg%% z^pY3)j-Uvyccc^2CsKAxoLTXL0V;R1vkXNpJ~ud*+1@a7O_XeI239E0 z9@8)_3zZ9`QSvAbGn{I#zEDWb9yq^L8jG*%#-BYF9MCdSXbH*1KM>$O}97Vn@YeH<>z6lXJV_ zVwblB-f1|~&gvw{emH~m#cpZkWJVu3${nMNlZ{M>-AI>93>idHEr6_aT5%jJRT?fJ zlm!+G+qPt`9x+29MRIXIJfml{wJ0M-oXha!E1v9S9h>t|lwu)#36t z+Q*rv+dHXK9tuS(+uzc^k=m0O0H$JYEu^`N^qtu~*PqWV(mJY?gY6F(04jepcbu13BatzkcC0TaH)LQf07ffR#u8Dr?0HR=FeCM6RxTzQ}7)e>rrBV}Tn|4^fw`QOtC zA1OT6IrbB==!GvKbvPL&(xPTlu&Bp#AY_AWvRm7EN*;N4&L7|k1K)6==j$PeTaz1y z+_(5i>wQe7wKIYC9+{^;sr7mKzV;JE&`aT^<6iieb48w4?=LPiXetmdH6T?XtyL=+ z4<~;=O4d;~^DufB;lB9alob4?1YrHmJhbx8C;+hns_bgZjXYLdha+@wZx5~!`2KEM(n}Ow@?o_9x(}q7^pfT3~^KaZjvUeTF(M6$|OnS zrS0!D;1DVgnxD_GX(|nL8?y~Y@5Xy?(%e#el;MoI4YN(H26{@PQ@l=GROo<+u9jV* zg^UfmfG280m#-s^3h|J=SKa$1joijUjB(4A>pm`IXo-v7XrxWfq%2KJWbfY8mUO0!<+n#hv7Fy(>cqy(vx22LxKbmxCVJ96h^jN0 zJR{p~%9}oj>H*_rIs&{?OoP41As;G)zanEIb7@r&{!@xPQeC!PjTiIV9ysP{IFhWg zV}%{j-=)k$m{oRcX_Csw{s^VxLHXZ`_`E{YUa@fvCLJ8(kO?GNP5LUw2>L{er{tFquS@GBSid9Mi^M+pWVJ=H_@$ZcV^hZzQg}?+ z8Sg8*hd(jX8sfrAnF8<~v#8Vi3Wu#c9-kNy?-IY|;8s9+WudzB--wOb zaeq_?5&#s(Ht?%JDfGH0W^3m9=v0BZS5J79FPM(1(P4@0!nze&9HlJT+}Ij0)E`*7 zgsN!-A~=(#CSCb4baC`p)t6??`X-N*7Mie?SB~sSO&SejSLtVmSv{xq$(eZOKMG~c)PhLR`DCN;$wmYPG zNG=^jx{l6xRBE8dhlXxh#}YjwgPw|!0hFCX?Up+r(xZVbB(!Ulta|qi!6IUas;?uD zOU>z#o2^XGh^##YH8SYA>jq>?(6x0Rcn~8yebCFq$Y$%t>s99)!5oG2_4>^?OYCcTd^>-q1Zaz17|Lq0aUG_o?o8=gH&Ut^d70 zd&>Uzmf7`0Rm1b^E;v}i+p1%3bv`h=J?PxJ!OvZ{-aHuG z`u^F8TW;GLOx$+sH)f~wpy@NJKD9Z!=a#|X=Gj|r`RMHA&4W|tW+zV#1{;IUZI9UB zo3q=uytSd($y*15O_jfGWtQJhou8fJ$!%LVPf^8f-?3+Jsr`0yc5U?`Bkq@0L{&310x8vKLXZnnQ>XCdsi*;#sU3vX{$oi}fK-#WKK*I>6w+;Z#2V10IL(3#zw zy_z!iu@|15<=wW8&Q|F=f9=gNOn+WWbGZ~!5A4OktmU|HQ0O0EZv@+J+(yx zyXf`o?D@eIWlpU#bm|j72c4VO2OG1yGzU<(8*1t3`N71^v+G9J6n};f&JQMU7P+0< z>ZzfNtKXX4Yc0{TTKEUI`q&sHHi?75DaOhu-WpuXq^dz$rw4p^%PhmR_qJR3mm+Jk zyEJ;D%jo0Xf$)W1YkaS)etab)>Kn#@dAYfs(zV&n>NjWihG}C`wJ!DD)~RRT#)o>r zLc0ahY&;-uYj*E#j3#AnR`E&b-D2RhJ_|DUIhjTANG7W%et9KdT6eANEzH2F57bWX zmuB}+xdzP|q=xg%$Td8>b-*UN&4yD|ZKH1MS7FCy_Moc=4r; zhGzZNO}1?P_y%UkiSo{wiz*>d@ZulpzZdqJ89<`KW&J8%#)F!aqeC~doEV1NSP`sCZQ`xLvu>#@J=@`NnV|E;sP&=<{26LpgM&t_cpx@Pxsn*Gg+y)5yIFptZeW4`MZC13L2?cTsiQaiQ8y;KVQ)u4VDj~ zYAJKH&Z+g;UC?{m&1;E?tD@bvhO+zYrIta7qp2b5v@!lu4LkGwM$+B0kK4a4!ZQJG z!sN*;Qv)I{NJxG^*E0m=uKQkm^0(coBmew0C(ixCzJK%9kKA?dT_1Yg+@FI<6aF-! z@9j?f#Q*W=FHF4Yb8D-UpL^|3d}ye|eU$jQM}ML7`;Vx_6?;IxzP&p&=ykiR-OdqO{WqUGyE^gNpZ-XxQaA`1hAVp=hYUU?$)O& zvfrO~?TRfkTK}+FC%om+c`ns?xJsZmHYOd?tz8D!W`suyNi7~x4%=%o&AN*z4Y$ha_|1XIPTEp^D$UdZJXUa zq7-U2yOZ{FH-9rZ4EO@`U_~Yd3(T8+w%bd^ytqpcnd$ORO?6RJ$v8d1aI4$Wp6f5{HKAD4yBa`^&r!p*#zNqQ04Fv(vyuVlQk;SU}p~YWKX)gbiMGI_4fRMqtY= zygT3Bzu4ClXd<>?ehjPT)TmY6jk6GDKJP&&?>*R1KVWYe5B=ZDo8&z-$1>!HdfQ)M zCDMMi1HL&}G+H7L$ATiCzagL9z%(rMwdp4YOb%;L@6rPI#rc>w=HI1KaTR4R^++?Y z-kn$&F#ZiP<2~KT7Z?Fp0$&|m7%ajb7NIolh<&0Zu&x8Vh(#WcAN_y|#HV7$`ddH6 z!gd)qGTvaUk{+t&U8<0ojuhlY_uD%y%j~u7mIHLEy8zo_T40??UjCh;SXCv4*~V*n$6F3 zS)TnxCbf~iPj`VZEN5|!LGN4o>Z`&UYx?ti@%`UVcTQ}rc20bAdSdm=>h#3QvX4i# zzn|{zTkNy%76xMMz@k!>LPY3^36U*mA zGb`TAx#@`$%bPUV-WF_F3>vP(4m}_M9DpKF)HvFrvk-VQ?3JGktq&-S4t@ss+@l)$ zi+nFhEPOf1?v5~$L81E_)7z_Orzg&=e$~lcc5<13mF08O+snV!JRa-a9}8d#i6QI; zi3u4RiC{aBgV;6Gu`oaYh{FAPC#Jg4KWr2x4Coj!)P|soBr=>Qwx;);SXpK6rl*<8 zsWa2_%UjIo{FY{tuAEujnx0xcGrzLA+L_;oGka!h`oQw)>dO4;iRtN;Wv#AV%hS^; zwQqh}^RseBD{gsXdQT{~Y(3tbUVAgErnJl8c8mS>?mi(j`miw2^6dxMH&|Hf?lJah z?0c{ndaKDYiQ8G&?Y*_JFdog1g#p~o`?)@Scoo{t(24n#Rfs&ZI!|xsS5C~&udd|% z+za9JE6elq>)y{p>d5lyiTN`t*3Z?$d~;%TMITdY+B>@H54WcG#-iTUjp>ayZ`5}c zSZ`ew{?pb)CL1JCXAi2g-9FRHO3gaU<1P5Rca{%qP*{dQk^m!PcXzMQT}_^ClryX6 zruVRK{E^M4Jzt3%NPo?*GNXIWcrU}Ovrbrvt*0wt`WI2K!9W0a=S(>4&D&plnSqH%w;~%*=bq`rVwj?vB+*`6>~cWTQF!&$27I6mrZktYVS}q zc5;f9dt%M@))^*Ya(EIH(ux(mtYyu{0l}cm-nuIl1OD0{a4VBV0h_U@ z1+Y1QI8LMQ%-+yqrN{#15(i?uPfRo3@NzMlE7*|iE1Q?ZeTG-7P0)_#v9^a>J=r4I zS*Ei(=42k7-)?meGIPubT-XX}rwR8Xw0Z~KreKhHkUDxbQ|nxKE+E*{TTP$y8|^%G zmmjvVm`|<3i4~p=_ty8O2Fgk`tyMtNMBqZObOBk*;mY{>wde1c)hN)HMdSo!SY#y2hXf7!!MU1T)n;a1X2d(D^|2D zW=tuhPvo&KTsBTz*U$C|3 zsO1c7{=~}G>h2XN(o}TLY^_c$&x`gBQgD)AO*|k05s@cg=F97=Qzzi9LHwmj5isGI zO1V&gK7VH7uW?q4zONh3fIyiDMBqEMQci46uiC#YJ^N;Ndv2mX_jwB!cztOi#S@hAJALyy2BEST4}~OJDVqh#f$RRARS!eFC&Aey92Z-NvM7);3+Rxp8G0b%GPh%3RYNK`aYC#!Q(1nNz~iKHrO2U`sh?mqk%z; za;;X-Fef|1gpX?|vUrL2uz!SBJ{vm&e7H= zGvb{I_z=&~P~(&JZzGZze*N7x4Gv4$&v&O@@l!V*eFx^kx7{>( zs(%S0emxy2#);R_1Q= zcrDz`0w*$S@rz!MHgqo z!#-Y|TSGGAkdtyXr!Cz_*PQJ4P_*{+*z=%oDPcYP%`61QUwg?hE-_-JMSkHU^IltR z67YzBP)CI$n{*ivF@f-6+jCOfmQEy=Libx|E&^48DOBiyF~xb9`e^17Y1J%SRxzE#&>1`VaK?3PuWIAe%Ks z`SS?TPXzH?D>f5)twFhy7#u^lnSQ}rge1~izwLAQ0Y$`Z%P=|IX?N0Fr$N&;gJr0U zmLUnMSTSQ&9mKHOl=gw(bn9kOWN5Nkx#FnXE8FJ!z^x5R% ztK+`z#C>Z?un_f{a0hGV-l`ntEkG~_75tM()PaJ(kg7Q|6^nuwUuZsG> zjX#z20ef9iAf6&mzSMo|{3-k2VE(bF*Zf%hQ&-@!c#o&Z7<@nW>u+UC>Y<9GqOF)F zp3loyU}zgK&mMtZ3e0LN2QmVWZuh>?SQjnzx8~#>Tm1XhLd26%2+mBC#;6Y((;i5y zNV_3AjOS7&_h9CLuwa{8xTmHEY86K@raQjTkA;oFWWS42ioY$iK(&}mWHFK4P}|Kl zU8{lc4=D&4)I!{ca8P(I6el7N$kXS~7VmDRtf&v6BI_P=L5B`Pcc5>MNuV+UR{N^4 z*Id~_y^g&iO4$gdvcst|3iKBjj4XaKqW!;aBu&w0K1Qhn1b z=I3hqW=q;b{H7?*%pWAoTq}Xz`10bpIW7rX0-|d{^oDEtgeHpUC|MdlJJgQ9{hHZ~ z7n)vw1HA?^`*$^b{tb^&_{`Aj??+bi-KTk!r_1Efy?Hog^~8mh07j$;(#nYo-oI0L z|7(U2JH1D{j|d|A0gFaEG+%ut*n4%5qQCfcxltGAh~$yGyfZgRNSXAmP!T#_lQYb! zDx6{R!@4SlDYiGjb|fcPuhX66@I<-BdPjlPr*By7a)*JZMIK5acv`A!)<4LqcX||+ zKm)8XoX{ZdW6-lb2QN1T*+SqHZf@L0yAqFJ2V00W#VD|`)5mTl(DzhI+x3p0*!H?d z@5``*iAcQSS#B(n-A6ne4rzv-weFR{`U7vr{pHrA_3pu>$JqBl*U=|xz1Hznv~3aN z$=H%Y(SnM|pep807K31pv5*!`eRq#Fn=6)-LYqbx8>7!2&mIpexG^Q1AV`Xs8DXN4 zB+RRph_%enZqDrw0Z1$$TE-JMa;AxCmY(k?3#?Z$=zpkLvtFd-v`gLPyM2m%3c*{U z#Ze2?JXw$^GcD^h1?dm9Xn}F5#n4SYlV+ZGvDjnf=>0gYW>@V?2UG-)1S2*piD};@ zZf(LkSDIB@$zf7um*4}RP)53)LGWdAR9&64aO9S)bZUjft;SBIB*g!6OwsM+X!Yp90$VAlx~SMbDkh6xwfU+PAMM;TBPEMn2pA zgC4G{<`{Mw|A0pEj*)(+qNIdPI!U+V$1bY!@1L|M=Bg=Cf3co03e{fJ>u2>(hrho3 zq`byXX5`MMuB67nCOmcsBG@r9AK<9Hk7J=(^4H+h&OKB8+2{nwF&ET{Y8Sy9uT zu7G1BrFsG~ji)ee;!V_y8FI4@;uHcBzQc}b0>ivaCY+EYJ$DvegTN>q#B7PVDTvrX z%*_-|PRZ0llo%N%ml3a077eRh13lRp%GRKpf{+~r-2`uiNi{oMiNDoxDzMOmeW2#5 z;GlszI}PbJ1i{!*`@k>@Qgp0vZ=4K^7#uV*78FdMgZpJ@bhh)ejjXg@YamV>p90X} z;BbcqQ_&QheHL>1PL7>MQ&bKM#ZGK9I&5s=gU#-h!Wb-95S@-HvfEoiav~`S>5Lym zt%?`7dTeOg(;yvYSZEk{gkeIuM7F1P1s8Cz=C}=JbYzZ^xAVvxNRyobLt0qbHee|> zn$Ze42rlHF1*QTH#0%p?`gp`aKPdZ@1cQYp-40xr`5aAIcS*B|&H1vp}0h#z&ah!r*?B`wwURG$OyL&Yr`{ z02XNk0ak&!fRsL9yF*ezdkKe}u{v2fl5znXN;ZQ++NUw064{#jR)@iZJ@6?+;Q(ag zuFH_v0Tvw!w&~r0x@{BHSGuT<(Ii-bOyWN?SGpwNgGs^^IGGayb%$fQ1x)m?v|ykR zc^0W+CW!bn=zl8OY>f!i5sPRX8SV`SN5b2177!pQr6%`{iKj<0JOujEGcOi!L*#JA zg-o!N4u{AD4F_vsYld0~na?199jUlZ-5TW>BV}p@yvVDP*jc|MaN?zsh59G5htT06V~3h$8-we*0Dn zto!%odGE;85XX|@N~8g?^FctUbm z^~LYSRj-Zk%s`vmObTO8ub*X8C^FsfW2kIy?vQ0@5S; zC3e$r1R2c9c*$TpM^lDvj5YMdm%haCItB%Qi?!z9X?$RJosZyVF9yI$5QGd2EMGyD zZL1WqV?n{lK9^~lcC!N&QeWAp7Pk7kh0#s!+0yV)TN~djXoqaj-?n9J`OK_e|OK1jQVV1#=Q!=idGRXbXs%4`CDZD^nO2 zO|S~lM7|KwL$wgZZkSAsc`?fn=rDDodqt!}6VIXpBcSB%mjWZQ(|4l*;Ltk!$676! zc?jlbrw6>|=wO3~$<1xnFtt`dIl()Yi{AcVqz9Uc8qJ(k8pz^fsd+6p(1>L_hoP~N zl!|+WN2~_7xq<2e{F(VqmOBQ+Mn(f{CM2mWyb!`(?_QzT8a(|+oqMcKH!;Cy^;8`V z9|z>v3JA?ZH69dHUt!3cgC^HdY5JD@h%ua%5a9t`&6#bLHVn) z$~n0;e`5ZR+rpdGfB=me*k1fjhHgHgebT$HAeBRP^Ev{y@+YA}k6zz5{lC8YU;f;` zeD%z<=dC}Jph~AdF$84n6oR3gB)P`~G9JvqT%_{VqhXUUk8SzB0{2MqG-i3Wyrmp; zve%j z?aG!r7sj{mkZG47lhIp%A|a}Pw|=x4QAI>3ii&RqsQ6Y!ysKrzD`40V=>yotgkk`n zA@U>8i|3idHaMVT$+0*Y`0f$|%sL?`g{2pyr9m%4t%$@f2x`%bWad*$LiLnVT-_xu zZlCDTzvDQ}pqdCf!l|G2y*SnV6XPWJz-t$zrt{5SCCt*fqB6sb9k)+d(ZwfG;4PO0 zUh%c*~;nbuuM*M-xFJAoVuLBT%Nl+%zpiCci#>F?p>ew z{3rh8|98a~pF!QpI0XQ47d%Ke_|M^d@txkOMUvW%s=H(%!a8`m9|MFjcY_;?6 zdH>@t|FGMp)B8I^_&W~W!NRAALE|4-($91M02Ov-%H?0{V9WBK6FBclpdJY!@ZZq4 zoXuTSo=zp;nfqE7189hc$BuEsC%L2G&KFVb%R-LrKt{RRA}0Q?M91Z`uZNR5gveuVN_d|J1BAs`rnq|LvEEwL z;VeF}YE@RULT~q~8Pz1q)D=oKVa5W%DmCs}0`z_YdOr@m*VWSdOrsZfpJLLIAv9P= z4ohMOFE{l9CulQ;x)t>9MF?3i{yHP&0`-5wQmcVTYC{Ot_u7=o<{H1xz)(nDCnSF! zl0ScTx|U!cU{4II@d{}aFrIj9MyaI|bw&jE_}-ETjHb|M5Tmw=Zgxz!Ld*dy_^6#V(Rb z#3S9BvCD60+Zv-rim+Z30lbBA)6egHGOWf$C7_f*4KerS+S@=3^&5xaj4Ab-&TRFI z5#33GbG9glR0nepvW1IC{A&G880I(3pTfcyK9O<9?6M1kJI#!RB0A_Z0Q3q;ULBKW zS@9d)XNkSD)y+PTj0FAd-uB?2ZJUX?s_2;yJLcQ(6HqIKxgq#7Of0hl?+G$f^?t+ZgS(`o4Z$tc0&p}(H`pg>nVIbumhDZ=R_S{y8uX%5Dj6hO%5wqIE`Ms&}7 zvf*e!Xa`at8fu0YdD#U1W-|dv4({R!$`DlHGJ{RS@hzW@bpNi!_Af3P##DJ@e{+@pJzo`5xXxsKAy+7!#*DT9B;W zWGKlf#=KU7KRncAhOxFpP;5v;S4N?}eylj7aEL!M{8Soe?OAKv2RT#XB5VqNk~hiM z(x+9tIbwv7R`DjCx(tI0Y5J{Vsx(T;i)5*tB-s1Gt{*A2ePVpuffNi@B!dt_w+5xS z#2PVBkSW!aS?g=z7gUzeQXJI`-=vkmPz!4W$VDteV(l5t!N3V?19a$98{@3H#lsob zsD>@pBB{`UH!_|;WqB_O@~ge z8hM@W!Rq`?%SZUO{g_3qfx+*`jkXHF{=N3*S3`Tr*1W zxb+97`DNEzAZTiIzf{SoF4oM&{v(YFU{>;*w#we(YGC%97#TUQesk!>gF*vXHiq9k zRr%ic00&#q(kyW>yG8&rur3B^<7FSod6}#Yma+INS|5Df@A1QKL~Gn&AIUhI>xgVN zJBoakq%3yVS>q=EaN=?HWdn;-zkpm4_?GL?Et+|-N`6aOBS-pB!^G2DA;k1U`yI!S?u#i@sWV zGn&7KX5gbmbgRL&sI@rD(M7FoQe6#16Az?6*N%Rjw*9ZPFoPd&ON>jmzo7 z1;4h@Yhc%TTQL@-)HMV4Lgp=8owc91x;0kI)Tu+$Xew(qS>VaoEyMo^hDP4MqV*7Y zKeeIJ)Up21QnC8d01jWi)CQtYb>Rnvn4rO0DPhf}Q$5MF>o}P|Wn~nA)`{O%d9tJt z;=CjrV+;WN+a^&Iw4k(RXAvOTffAt7z$MF?dBPUHGxYwgLBM=<=#6SB*Y#9+@}!8E zkBRYs$z;On{gpE&Ry`LlH7;!8ECF_KWjit}gA8bR>RaUWG9*9#RC z0?Bf8NCNGGuZcZ#Nsf|&6&_C)PzuFQhC=1XH@0D1-H1=YWpzhC8kxP3BS|9bSP_Z% zT%6IET}6;%>Z(uks#w7Nl)?TtM3fvz=C~xXQRzNt#7umCh_^{S@VQr(G~pB#Hg99x5#AuW!I+0TX->M$MIc(e)CFd~WrOr|hf1oCK` zLT8lNxG>kI$^yHJ#OKTr)JjXU9WzV_wJ|ZwXPe0NEi?Bc*xUu!O1{CKwhRAJg-l(f zC9Nq?n82*&l#;tJ=}&=gDy%_FCAtAK{z8fsw*^+-i@{V4 zT(V0RF2rHV#7Bb>i!P5eV#N~_`x@MXsTZeo?v}crvL`4m7Myre#5YoRu<&R4@sJL5 zHpp!Dg?qSqpGd#mr$D2{frU5$3I`J4!E%cDRDEp7cJcic{C<9-K?!I5xBEDy5YjbM z2^IHyocrt{FbbnG{>V_j9r0}7ZzQ*6;r^xlyhpX_5QGJFeE|)V$SEWR9DmRc)vY#) zcB={Bf_Bx_66GFfma+~FBR8byvc^$7d(W8z~2=Dm-0iQJsQaG!HG$I>25*@ zv6XmuR1s1zLcDbJ);WW=yJ+19tuCblCl^XHFRtoS2~&+D)tLMm#O7BBVpUMWvm!JI zzQceJU=!)Lbkr1G%D&kiTm>H$LycBME(VPC_-7qVsAf?Y6TbpHQ9dbAcT9DwdsW08 zs+SfJ(eQY#hft4W{qf&83j2f;OcTFq0XDA3B7vy@y~GNU5T7qaUj^Rv6_BdRn1Bbj z;4YD@j?O}AbFX2It1;Ym6M~gW@CL7$)Lw}_xp?RVK+%;%RhT4MwRYB&Fsf!a0yJHrjZCmNH&tq+VON0lj}o zt=Q!*p|iqUlPL>q>}K?7YHZDJk-;~eJY65yR*a`YhWZFW*`bbjLNe>1En)Sju7eH> zv5+ITgT+JK$35n89-0)K`^~vYwZ&`(N2Zu;n8x4%)g0>L?qu*T$k`;l5`D}M=Nfk^ zCNVn%5^9e9voC|wwV{7t;Bq; zZwSV810pKCExg5uB%61>Kbm>jf;`a%3-Ob5`NZDj3ZcG&1>0L5(4 zndkBaTc^5K8JtLbyuj88As45UtD$;<6Lg7k7IQX(Lpe`N2Z5RHk8EoHu7G=megS4; zjxzm;mB0-wO3I%NLtOxjVbKx^Rh$ck;Yg+5<=9L^Oo;3MBF`LSLWki+hNBsGLMf~d zW}OWL!Yd33{8^J=mw7d{|LLwJyu))N3~8MQHJb}AHs6K?86N>RUG$JwE`SPtqi$T zJTxefVDA&_s+t9AYjUY5SQJgI-R}DiXht$V!2y_H(d8KT9)THj}w#zXIImNP)1{nonDJ{x6k&qb(Moe6F2w;-53wWd8S zi*m}ymWEOc0_b+PGkaJMWp&f{o`%6Q8#F z>d%vAW$vpxPg;6kd!95a(Q=+ND%s0`)e1{h&|3y0>TlOR)xBdZfMO^6JY?me*n-llbZ&ZRdTajA>Q8p3h35vv zCa_|4o4!E~x-=&7er?aLa^ijEWBKK(o1u#_Q<$_3NwOy@qT`_F$CQ4R1g7Z_o)IP8 zcs-@_@$oLqDo?*-1aJw>A4Gy@raVrb_U3qI(-hi2kgRMmk%_|N9!CiNdp z`oauN;%*kk=qoBF-a);GJE!ND&x8e4#wh>29izl6m8F3a_%YZcug-9*W)HGFBNz{2 zvwKN@u(G_edPb|Pic<*jXvZlQv?6QhRVCZcP={&Swt!s!v1M{K=+fWiRbSub9;@Xh zsNx$^3tNBW*moXzVU|2wFHUgt*k*04NS^T92ub`j}#ow^*+3I^e+jpJuAT5G$MK5VUnmA1c zMK-7R=t5rRZj8cy0dHqHGRZ0r@p?zzxEmnHI4u1#hKU!_KIy3DX@+6`OxigSOycZg z0U4rPC52n8D*`g>%2MFsiRhyX!!>8e$2A*0u21O)Y1mt|nA!`*I)sG7ep|5)Hgz%Q zMQ`ask&iVr0{M^x%q6@sKPZkL+X7~7Z29hwHS_hQgGXfEz@o!gG}v_vo2+&1egx<& z<$6G#63C)cn1RSk1)|Q51){VlStUN2L9hxpdW^K4qAOyMFAmIlWE_|!nWyDj5a#x( zNli>|FE{7tIO;7&#t8QE?6=2q0apdixz}e}E zqpwJ_Y87Z!U!1-FC$mHEXI~WGuTO8^NaDX250`o63uBp$>8V%We*3G@q+a;Sa#b*q z!NTZN!I1U2G4NrGtIJaQ7S`WdGnZ97jvsCf&^VMYc%+4k>PcDHg8Cc{W=Vs`F>b|L zn<1Ws3E?n{fpRdies3WUhZ`sN?--UY8^2Ld&fgb7^H<=;DhH*FlfHM9)yqg3?Wv1* zTMcKs@U#kT8F|ei(QE*Ng1bf|vnP^T*9h2}ZZw8L!Kd4dVNWPgZfLyOBu4987T97E zyYRHPq3vd)SZKQmPd$2}Ic$rD+iX#^{?}u|CNvwNswbYAb|;jL1CihsDn^K~N3&jN zvRR{Rgwc%g`ek#9D^wzU&}ujv{-D)(Rw_QyfL1C!T40Q4M59tGIKmMai?uldtxSs} zFuZSZ1X_uajzBBb>mPsTB{rFzKG@UrW#o4)S)mu+@8eyEe4lOEz_*MTyw zdzs}C&z^U#Uz_e+KlJoEp1z>^G@KdAzHWX}Nh|AKrR(dTKG`U7$8#`Nk1uU6MxDPf z67P+NTsF*}J>@@Oj|RM31{QZ#V#lk*Y-g-l~A2oB9W zHj_?bICC?f>F%m3qB7IR@teWb)GM39K!#E4RBsc`amj!dS9UP4G z(h6q>2gEcL;IRH8t(@SZY|QwY?p<6YHcV(9&0an)s>kuh35oIv3#*Kn`r@#HDrh@u z>5Ij$)B;Om<%l;U$kLZgN9Hb8{2oU#DdB*UKwmzw0GdN`h6Q(SABzc-mdY?`+2`EX zC~s^!Xh02o%OE!#Fz{9A_i7Pjqwa@81H(rFFl(84b-hO%TI@#*jos=Vk}p<4MT?gD zw7(E53Pt=3r`530vz8QI7Sh3L*Fa^%xd5Mc+9&;s%}_e9S$D5i+>07L`EAp!VfZt* zy3Z7u@=|M^_Uw;RDL>-r9Tg-FvHkXKpt9kpQ%2=AzK*1>IK4Vok%i=2*4FhdV9p%Y zu~adb&o#pGJ6Q`)u=!v`S*XQ{tPEwwcq%DzGBRTdWA>hWy%x4mEK1KUO9-E+Oi}vY zx-Cl*x5^flZfGr+!pN?Zq09#Rro1Hit~t=YydT^H~7RWX5W6(shfWLrtKS&)hoW5 z{YhD*{t%<)+3Crb933)dx(i+JAK|}bsS2NeH{O2KaERRzx~<(uJ{nfXBq0?XaNs~h zGfl*c*J2rB)CUVz*Q2_%gU)Xkc~;@WgJqV!SJ)+DDHkr9Q|p5Gbo` z`{?C3=Luq$gl&wr9}quG@$R03!hR}>C5+yl)icx6D`!q{BiXWU5n5SYUB;#{F~7XE zI9sdkk3f9=Vj!D{C$x6tkV!blgj0FS4;s;{D+;Mu!SJPv zrMOv2CNQ26fG4t-SI?Z7k7RF5Z@d}XKxy~-V!H@%r%JlP3Y}4_S*^RBbVmOS^m6$a zzpb8Go5p@N&qS=w-xCIUeR}K7>$Ma+K!1YhheLP?7{wtsy2B|3fM;o!Io-=dGKtU= zt0y++Csvl%{Lkr?<+}sfXxMM&znX!*NO&mAlmViNH^bUthL!<`@Lfju+UoA*>FN39 zmCe;%8t_DT11oyM@Cfl;psPr*VKH+%>RtOt&#z5ip_o#Q`ZyF{ER@7Wpc#r1<(4BS zsYi{AJ1&yxRn~{ylf?!dhw_U9l@Nag+7j9DLO+3EC-H~K-Z-&$e%f{=gdessKEqvV z^Cy;1=$fnf`7^8S)O$c4OmTUAb?=E(m0zwkae~VpcX4CZ^qH;Iy~~79wkr~1U7NwPnIEA$#6A} zVeq1sX?Ct!Gb5d=R_eYM=c*NGajwSqP0rQ$zRkHB%ZzZYhGGusTCQL{)%`FcT{f<- z@~zL9cTc?c2!{?!4FAJInH#;Ybc;)szQOk%k-PY9>VPrK zpWwod`4jfrU$AmSPt)l|tMGoS6-&-Hy5HfLqN+ha>MqsgbKze$q5b{QP+v86*6IP8 zRgF@nV|f;ZWDS#Ard*a}DA2Jbe%tFYe~OKp{6D4h%6=oXy)nIKnT?H9T$?@=ew&^S zzueJA%aAH6dsEOH4|u4yDa4pYaF1FJu&(Y>;^6`+uW*uOzASPE1MDV=if3|`SJuO? zyO&p{O#tNr7LPYJ;xW*#!UOTqU)mg% zqv>s}m?yq!BnnhyHyRbD9Xl$(8WQx@Qw~aCGb4?cA@0~-0|~!Xw~rzTB@>X5P`bG& zlCaS|fY`RB0Revvqei4-k3h10|xvzJuU6$ zQ2HzU(oz$s|K6@=lU7x*R8+r?2w{`>@A2Ozw)#iu2G7rTL;mSUsY;i4p5;INJBq{q zk&jzv@o&2^QMIZV;dhO4@5oFHDta2nrP*LSnPBQNbW#8$o1+AN-jSe_nTn&{MAfYtFOlfwk3@v-M~h(M`w2XFba8errh zV;K7ddbn058Nc?Jx9>PlJ!3-wfhzX`mzx-3<&Jk03r6;qxho9J6fU|0?xHh{<5E0f zo91SkaZHQ@vk>mw$2KGrnrm;wCPjKK3tNY+3IQ;5vGOE+{j%k0Raa3&sp=Ancuc9Bt>*HrhdU&@4k4)OeyBP#fV9;-Ed7o0p(P{f zPu~}am*OT4L_2vvap`8p3d242Q0P1p^{vxdBi3mqML+E!=NxXP!nPoXX~;m7N%5v8 zxMl*6&m+bP*epRVx0Gf9dFd#ToA&N+Ch7aI)!uSnNVF-*#2G;ww?Y4$-N%5U6y~^Y^5M0ms=@1eJ(%lb+{u@ zTT~xEoGcR`8ey5RN;t|$6<<%E$8c>oMnJO}B|g$%2(T(>b=WAOS~1j{8G=(;?l%q! zZ3@F4GB~WXwKK#`T>yJaDLrTTD#4Ts$Dw*eGH2PhAz+z0T-9!362G2= z{CR6w;mZ>AqxjRWM?rt?vY;m>ra6xJ(rM2>Ca_Qf3=L13^=bQHq$|QowYeg!K#MCP zzHf3x#P@B2K9(8bilEqQ<(acww|!2wj}rEL@TWo8KY-vKU}&rTxM#;&=+a_Ykw+-nv7sTJD>;v$ z9`56IX(>*F!J(KpJbD+3U=%l5x9i*1T9cgjquWQ}vOh z2xN<;V>*K2UBS*4e-UlLfT+||vl<4+I99vSAmCHYf-2}woDY7 z04A&J(2%Gv+N#7)2W4GBXZsc7?8}Z|DH2fOI#6TQtE9c}WIa%}D(ht;QLOcTetKgI zaX(pO)-x&bmXKJDCHs4=E>6dmY<=0S2D0OgP~QCmR$Ka@Rez`W+mdMihIo?N7^%YB zXJ(t|EE31$Uqx-HnFWrg#Z$Qz9C1h~7Hd1CWMvRZue?4UJ;v#K{m~Qv5Z<>OQnC^w z4=GuxX5ntH#}UDouFTU+xc^5j%8e4{tXJZhnm-S6odY%DdNPY4-M|y%xkzOF9=*8# z-1Ygt@1~2%QZ)#EPtYTw_RXZ+|3#Z}Z-nvT{gNFEq~%b5EIWtk5N0QEMgQ?}q7Pzq zu$*B~j1HLY>bLC8!~vP127dDUPNI_+Kr_H_U(ahLbvE|1O2sWZ^- zvOzx=BLUh&0_gqQ4W#^?FbLtOqdbU9LS7qCt~4 zEowA|`CvVUSqFG<^QU;2-E_YL3}ZEB7-qdoIyRW#Bk-7=!56D(O!z_zgUNE{!0rCS zG`Vx!V$BZmb(u4Uaf@Xy6o=>TQPj(TTU;kp>+w>Doj?|!+|iKbAhJyIOpv9!oiK}; z9!ON31lss;B`k)zK*(XZqOJ?B&~(5nCgF+3)D4t=AZaIp+!~MYp%jo%MlA<3)I!?< zwiu41ZSIl=JSTYu0SW@FhF(^oOR4R4=rY`Gq_{4HVE2w{wrVX2D~&JRP{m9FM?kwJ z>=NhMtP6hr1e?h@Z7PK&jMMBecnM7x2;A=ZZ3Zuug${b)IH>Lc>1l6g9pB+<1&LNDgjXfeNp_buiZD>2giVx^kRFZTMKG7s#uo%l4OW8LA@G>Tyhq{Y46L-_8?U2$*qG+h{OjNBshr$?Y#g7Lf7fOIRM` zp_v-vi!2g$r~GK+Ko(kw;$#hvfn*x&FSIMMUfjYkCWt9D+YVytd#hXHlPqm$v#NL$8j`zHkipP(4 zahEdxaIMzQpIzXCIZes)th_J@D^!1Yiz^jxA_Qbdu4zKDkz?mAIbJv4=Uf z!tWd(94xBJ?L~raWN5&yf<7)g3zgO96AP6UakCIp99v135>q_}qL{00YmpFO4q9+n zk;ogl;*`%N9C}g7hT0ZNNfVZ0UyS5`uh9-pS9Mz-u<5T9*+kzj9@;0-`;CI>shDg{5*?tIXPAXy8(VX z*`2U@$nP*vn602#1>83E>xOFG9W15eUYxxFGoTDT$&*3!Y-G*I?vy@rDf>tlJ{x!< z@~u|M)gt>w!qX3Cfal}iJ-zq%Gk1Kl_w?jYUHat0a01cP5)(WbOAnSOXDhIvPMk2b zC(qF`jwuOoGE6IY^Na&S`{M<<(!=t{lT0*Q=GmM(B0vymF6l5x6Zl zLHtuI{#7wTLbCmd0O~~R03)ts3jdJ`+5R$_|^ zYUPuH+6>=W6Tp)sS~1h_X+_hT`>SU-^s);J~9Rle&A{(mQmhk*WZVi z`++78`TWE`|Lob*haNRk`q&0pnSMo`$;AI^UiO3e$q$+3376M;@sNJBeYykAv)}7T zBY!zV>6Ip?cc%dJRA%4v$Mq)?O9~QtZY!&+2j~hX8l_mJ(m44o2am(ErHgR5t)6S1 zS;u4c=C{2$zscQOuHr9Ju7iovUZP`yO>aPmO~E z#R@&pA8Dy|3lg-IgmXNFEGtDS$k(uhgUbr!DZE(<L?U_|JXe%24dF+U3OK7wsoBn& zQ@1Io73ZM^w5eC<^OQa{vTY|NR&6UAe6sk5k%_S$6u&fRhJy{D-Ur>V3ZshY}80$e?nyucQu zERi$v_hvVfFkXp_Jv-AbguKRtsY|`po=|R$f{vX%xid{Y=$>SA(vhn;Mu4k`3|CCGoOq5uN)8! zVKGXHN4%6SQ^eD)T|BV#vGbnVYAsYEu_Ui+8-WNisO9iUaW9iB+ z_x~UFR3!<&G1E<-^U!aBH4t$Du!Hr9R7pp`6r&=Yf4-zN;fj**GEMFy?yC*}*$2sR zDbT4v;Q`fGbCJSF$Fc?Pe7{9{TUIpCfn*fY8go?8%AktuMDE*wXapq zSlBm{l~aBD!#YV4tD!~wx<{HwF2WcS>10s!PvqX2#qxwRWraScF)f)&U~e z0BSWjflcZ5{ULBuNdjz|sSvrD4YschQ*ZptvbNejU$Gyl0y!V{hPqLAYhGQ+^%`Z) zAzq?K44RYUfQ9_ZwlG0xa?ZA{ORMzXcV<{*Z7+2?ZL=gWUx1n-B{L)cRNG@KXhMnx z%{4NU&rOWCX|Xvw%D*AaJ1ZCAoL`k{y|;qr#EVl+;*6F$?_M%asCcHPcCM2z(?7Ah zXAg^TJ!FaGd{w^V^r!BSPlTHUf>H6#qldVczvyzl4#x&f&_ke~DhYTViXX~&`R13BZXV-}|&`Fo28HeFnI zMj!^IHQ{dSp6~yBb`AnN@a2;#q+r%F)cr{cm#oDr57x)RK9Wc>i={m{v^uY_3&maQQk5Q{v(pe z)6^H9%Ze{q!u6sLfHYpl)ClT*gkN2R1o>taVBnMceLa(tY_4uGZ~gR2?%|q3>5(Km-P194^-QId3b?+@_ z@7jAy)9Q(ysItAEq0L+CHk~ktyYjdHwRm2YC0qq^{CEl*DlLDf@tr!McrzHKH2k0h zxy4ri*9oPm+8hw>KIEEo&=yx=4|1?!x6U6oLr3^DiWz{Sz)yrV~~(~B9Wjzp(tmiR?F-s4lpB(>?&&73$-HIz_ov6 zE>#}fCCQ&C>Lz2%t<*KI>gLBS3&tE6wgWx8=y)5Tt>7lmZbW-&hl@2BZ$?QLu)i~V zP4Rz#Lk{f;EtCbu7i61~9+5n@gcIo-!l!b}1;>EDIHr!c|#jRDOP>GHcRKr%#bB`puzPOq)!dP5Q)ku`FMl2}h59=p`bhg>K zyJ!6rwr73+o688v;4AvHUO@H~3&B-fVT6QG z+^#sfLZ*`;d6H-|3dHnG6*qzTm8CF&;>`}+zIg0ynFbG%ocXyRN`och0x#BM6ub)? zN^-CY&~Pk7<)hj)K6O<&NF^g2tn%YF9^;7Q)iJ`J*Qp)(p+qK@37PPO)3Q6m*i&or z&O8)TF-htb=*5mV3PK~>(dnfA#dah)ezcSTlUytl#%uz zI`bee8#s(xgK&z+iT_7tuPekqE}f2U94t(~oT!U)%!&1`u-*A=CDJb;9-&|>M!+Q( zIlr}Ba*Y=X8TU+C)XDvILF;3tz=b&`0uXFKCfxOU9)C>mg#V(&czgzx`$zxkcR%y^ zXa4)Y`1@z>ICAITe&dh-{stRJEjPKtZXaL0yyS}T3F?`PNaEe(!Ms6n<-^bkrP?pQ zE0vsQdcQuw6+T?O#71l`hw5vRxd$aUPN;~*0i=w}^VL!LJhc_cgs?zwL5SPHb0HjS zn{!##t38Ck;)UdGH8gO)U_2qQd%SbA+e3?%XwEf{$8B{jBe(X} zB&lWc9s$p2jB*=Rh3(Lvv0`Dv`>E6CZX&UQ`Nydw=YzbPJ*T}%PmK5@_QI=_okft>ab95P zeXoioeIp$&Gsk)>Zq|mkoi_)I1Hv1pl!APf<+Bw%xBq0ZM)a37$WDpO4NlVN61bvu={wU$|? z2K+>iNv8dMhY1w;pUg~v3%j0wVRi)S38Aj;PPWTbU780uIYKM-TDe!}LRWnfEBL>C zTwt@=4bUS|J_IjO`r|?AYeJvHO$aREgr_GpXR||vRkR!QGlTZ9=Vq@KGw`Sty>F5G z+h77#3>s~~9n275S{G-xbXs)GI-A4hP}f-}>N+zDX$qD@r5_vt!+oT&OsJagdNhXN zu_R*mT78nrAmu>G2ZVt_DyoCl8oSMeqaBIKexQfRPZ}m|J`+dfUrB+QVh`QB;R!Ju|0>@y>;sr;}CfTS8{Y zs?;8V^(rRBJStJO#UjYP&{Y)hx+rY zBTVHzm1aTT6)&8XyeS@R_Vb0SIch|&!6_Yy_hfbB~NQfA6_ zRpU$6BoQtsKNn_1`T(RDtA^bVHmyX6qOCWW>l>=@H#3BWtEDi>wx{AE>XMKyJTO`f zDL)%Hub3x%U3of8SS$@Gy5!~*wa3&+OqHF$r$CPgoa?f?vx%ZRXfa}nf;t9hi6(=V zv`yS@5=tx0KT%O}f}9F&*;u?X4EW&2mjyR|@8gbH0aBP&jU2}+=iNXi$N8vFw6^;M z=qVJ9WT%+4nQ%`o&<2LAp|v52PB~OgGfNyb0b`wXC=_mp{j@QKWju#1c=a+e;W;*k zFl1`A%xpHZ!+Y0KkHS|OK2>mLW98$xs4o*l7uN>#AUa|RtT7G7jh?Glr4!tZRPipF zEG5=w6n`XxM)(3Ft!FV4CTN^&M^yJAN&jB$vBog5`%uM2h=h-q649jNS2}4aKvy%u z`T8qW8wRm|h4&|8qlE@;U4dIf3=as*35#SwT*AT;nIkz(^r~03&sAl~jGK;nZ9>Yz zNIHOD$oSFdtu4tRVipMU;K-^Q_RQ8%h|@i3*i1Oz4XP+6zcgalEG>O%7Qf^;hmucD z_|w7cfYibDyE|VTb6~`N_X|lWRehDKD1_?!E`!`XdoU}se>6k5UC&AUZtOrEUG~9B z@c4>4tmrVT#y*%ujNV{_a#T_?Xv#KH1%^IbG9^*x+i*m@NOwU|0h^Be_BiKeM`5U= z(!g<8w(OOdAF*JfrM@zVg)=FZ)mVxQdsRP$yn%iH96faq+)_qsz^h?vkdz5H9Utc?-Ovqrg1 zTBEJ`O$>0`2E*A-o6I+pz>5j?5TmsD12Pm! zemg=JdEVe^rQh9oT@i}@%OZT|W)!i&ul#h^WmU+<`ylS;B7f|htCo>lt3IfjBSijv zrrJsh(kN0JO1I&w?M}395Tp9~X2?Q?7^m*+%muYYTNz6(5z});Ng`;XSWHv&H0mat zR|UP6=@B@S6g!sbpo5MiJ7@wbm|lh(r_5#1HgORUs}QeX;Q`khLol^40s=+0uM5&S zNoWVwrQo7NfYgZ;J8rnE;fUu*)nK2>!ibVjTI6aVlDLmVVWsvajrs65SI5T$nz+WJ z=GsTvBOe#DY5178~?LSuqs&GBrZ={~0 zdqRND&!25Nu9}X+RPF;JjZbf2I9L=hkAqB_&0S5*PSWF!BDtExgbzQda^rHWv8W&C zxKZ>j|6AguS8A<4NS^m%sT%gK#9F2z)wg6|>A#4oumW9sprWet%Q!hSiq)fER79yj zV)&2^fKQ+w7xoFWn-|sq> zS_f2b3WA(H0Zl{{L$q@k$^tL|wDI{FD+w{jX5Xx&*OT-Ho5|(cMgmLz0gKQW5@mKB zMIP9&nkBivP!jBrP0)*$s5L?=943>hE!-yAY#$@^uRUzf%fkpc zLa#>foCtl|6Zrnq0r-cQVUBba=oHGUlmi*YE2DP>Iw8ORz4{pET!$iJKBR+}16&20 zKXC`}_BpB(+!WcO7_0Nz=as>Y{oSGK2G$>Gg|#k;;8jW>0j2WUysAXQR;FcS+MxGZ z{2SSrhU$-dqPf{6qIJnFNXdYlS5ftx43Uh%z5tR#G>W#LQ>12O4`RX}EGf#2u1V1^ zS1J1L8Pr;2Xn^{&d5;Et*E4yKazGT?N_hLX5X+$2_S=lu2tM0T`$tqqFR1b^?d zhp+GFe3Skl6Zhu>*D-qXIXjJSN={)!6AXSk~8VCZy?dE@U@`Mu=_QAhwVNaI6ar`M)W1gfe^| z7l^^l1&D_i5t4k#4~n9Q7C8GMeMF_9hEb%?tgJ({Q_e(@-zR2USVK;U5F>KAM_9PV zl?}s$B0g1B;tOjMrtA)OLyeq?B0cJn2U&*KxndatplUG3SVa3;l?6xH4~+MUja3P6 zR+(CH{$pgsK`x@Gi_Aqb={ws>je}*lXbWPyh7xT&XB$ZWUO zh{Lc%+NQNM1T#xvR!<6!S(b6^R)4m|WHiu^6-9yBBxh)ecgo*+F)7ZQ|4u{Ss{KxG z(tKIQIS*8&a2}_m1j7;MA~Lbcs^cUlCgZVzn*K~f2P2Z=+}zV^>?o%Nhw@STRWJ3E zDP_cL{#2F&E;*?7DUngqyN3DEI~sn(VNe-J^+0YMVMFhfYh-m4A!^B^*~L&jCOf`M z^%xejz-Nr-yvusW3njr>RvOVC*`~)x=r79cfmHp%EayY$FNFoj8cojuT2DV9t6xz2 z#>k35Ix(O-9#TPwAleat$mI=-@z^wtF2i0oE9q&`8>&=#57JOpQv^9j8$oWus#CgF zyVs$K-irBVXBN-73!{gHjfb5!DPrfNv}#`EaT>)*t7w!+ao$=E+%+2WQqY(qKl#%? z`?fQ0Kk@VTfAXH*=@EaOhsL&W)O>kt4?!+y| zB{YH?qxgy2kXVv$EhYJev}+g9Yq*{z2@J`mIN_do``#(WKGhw2Z+T|@!t4f%93q*> zyt&YN5Cp}_Eko>;ycXBiB7BnykR)Sb`zK~O2Te=`&1mHLr$UReHzDbUw~omwE>c49 z#eEh9YF7rwrB~`bY_+9f@=&=@PjLB+5C9^ymS9EV*CgMv^BQq)etxYYb=7zrX&RKX%VgZIaUeWR3Ny zPSnLZ0yUoOd~tsY)aZV5sY0dtwQ2Xu?UO4c_VRR^e9|1zF+b*SX>ZM({tTrr_ZatJ z4)qx}yA1Xi)XAG3H8*OkC{U6UDON+5uH+RbYs{F?T7zy_O=Tm|9ioziZ;ozQHl#G1 zWJr+yEesOkBsTaua=w&}pwckHbk=0IabyOb!7LI$ZnW(nVjTcX`wL!Mx-#pjw~GK7 ztcd4<%n*U6%^MBTAC$xsR9+%z5q%Ncer&h$Y$m9Mv|~(4^vggcey{{gJ+0}qhqK1B zqTvNkX-e&VSN$I-c0;1O<$j77S+A`~boEd{7!=~jro~M(`kJ@%rKIy$h|>0yZYZaM zfVo6pEnA_aTI{pUTa0(a!qDk@Q*@QZd$Cqt%P_(1^bGPtAkx( zFP7s5tPj5o(L9U1nHDHxN-ul*`W>ODM=_r0<3P{dCz&xFBz5&1<@(FWT2^Iss{QQP z9O}NswFl~wzL9t3E8DC9(sPXPNoUuc`=)?kOi&}VsTmso!_tlmOx!+%i?O%+Y=Pqz z4V028=v~4kzKUM_YYCX1*A(G#qf=v+O}D`6F!C<25?ZprHYnl&=OJqh^0Mmsb6q6v z?IiO71P?NtE1%Yt+y?zX253?n1S%gO?5q-;bzAlvpiUKt<4%!txsist7LVMEmlCU? z6u?2zSIl~4q{}HZRwEr<;^)(gQkO}DtUx0~t&l!r5|>Y+tVZyTuuhP`vQC#t!mLIC zwhG*)K`y7jxj6`@T~0F1<#I`&?ICPU!wTXdJd?{Tk}_QT=1Z;N{+I2!%t9*TO$TMT zQI}r+Fn>~+ReCMdUb0iQiDuJ6?G_^zYQFz>h+qqsqU^VD(c}we6ML&il3*ZWuRd6r z8v|V1Moq8qoqt9#06FX~b?UbfR$VxWDZnoE=(l5*9%348yK)Y~AkskIF*B%k6vlNq zT(^fg^w5dtio1H2G0riC?r|~hP4TT zHW88$F?|XbiG+H0wyeBqs+ipKW?Y-ROC~+m08Ggqx`bq4c=1AWu$&+7zD-BvzU z5eLr(szEhm#Bq$+vU|t-Q5%CxjD`#$$^Mn2GR&x6m}#mNpEAbIR1f=h+gLJW&jy7c zHaYUo$I5e7s787dCOf>@jIeHp$cbM@drZ3=L#VAv78W(EO)4XHZIGb2H0S3llZNeR z%FchKZNKL8582L-Hn;k6&v!vGc|y&mQSvb<}+w=VJUw_GLBuXBZX|L zc2nhQnx>;AYH~9aYYwL=;H6ZK$zZtg;thCiE~%J{!B{AVHQ?RTopBOPL;vNaf)fnZ zB5Oc!^n+6e1nyhdJp^GqwR;1G9#TtaR6wSxmTUl#kFW%kH`1NN58(;IvN}X=r$lV_%=?ke+)a z=Y6m9@edqDvazZ~SGWFTifS3qi?`Pxd99XTA2Rc?MgLx;3$;^*RyY3B`arj9VpPqQ zv*+e0_#<_N9U&Q;mI5>^Aq!5kqa-)=zo?~pQ}2-{Sr zYT)RmSl-=RIADAyik4PbFf7WcUaTjz6HTk2SPt!hvISAApbX)%4Oy$e#IjJ1cw`LGQihh`|D7C(>qM&i#*f{Csj6jCP`K!1@I$`f?pkP1vBLrBZI*Q43al z{BBEVkoCRQFLb_20$Ph`&}W16ZS%?2q^33274P-p37t`XV%RX9z8`jF{I+P^soCja z$_5BGqRD)T`C-r-lUg09(V(-(jqqEAP!`ge6c1ShjuR4t_KovN51eJOZL&6b@p~9{ zoeoVdRV3V%3=L?To*8Z=h8xEVk+)%!a%lN2(Y)s>!7IMV&j*i-a(P9a!Dv}dPx7Li zHgcRUW-`Y}p&A$KHsQ%gPJdx5-TSB=^P*Y~6i{_2V zeHm3VvIrJtMX`ex^*RUDl}KW^=!g`U0iK@|Ojks7Hs1Mim2$jXUr#-@riqp1(JJB9 zLL>^R2uoCnIJGJ@#Tm_Srp8;TsRjFQlf|^i2>#P{S~vRslB$>6=vRbvCRzN6AsLZ< zc~mie*x8N{ptS!@$%^`c06$Jq-3`~DLO9iJ72Pmljnmji2^;TN&gV7MvwSp0 zaUY#sT<&4pJuxTp5>g;a>r}bym?KV8V#a!Isgk4Xv@sbatp!~U$}F@)*0_n%t;Par z6D!@tS#5qb8nSz>)TE%{_l90P2^SLAQ#zI?%sxqWj`G8$o#M#py|F2xK(1+~hL5eXQP< z9rr5YnpcF|-939+`!!Za?$b55<88e4{7E#z7bpsJe)bGxlS98=j2D$Nh|KxS?_?{P z|M~3VT=@v|Ju(dd1=TXBVRhrv+%(WltT4EsB}LC-tmxdQ6GuF1j(E|^$WhXkRZJYs zLl%}|G|o(th%UVgLw?PCeUy0?E_%Y`8ww)XaJ*cTFb*#GhQtMvz?y9?3=NyecILtv zEdgt6D8+Si;hA`+{6Feba%zSmp*8Z!iuK82Qv~ezrTQd%l4VpV7Otj-a7~qbioqI= z2YNN@O2(dwnQ2XI6Y(6C_*l~?af80+_KJ8O<5jHAd9YIxkPvpksL%*0KvkZHCSHW+0H>mmuEqD&kFDo_j^O)qBOOUYIG_dr9f(!B|~vsj6Oe zES`Hz9niQ&LcQf~M~AwmVy9IxE1|Ca#grmrBjJBBb-~>4K^c4;5%`d+m50;sZ_jCuhW4 ztS>!><@g8Wfsi!#mypaed8A9|MR|D`L|c1;37&SmEk!EZ>ewMB^F$LFeoe}Kvx*_Rpl?0SW@o08BYWU)-^;C`odN*7%~FM z73_R#Q+dCV52@Ni`chCXp%7~V9X<;e$g8{!9nibfWZi&#cEjh;ft^V8HU(NcpjmY@ zH$-q3W6BFsuk>^-V+ZVwm8dJY*9U19y?zn3TQ`OYH(D|4ki*}I!`OTBp*K;l114DwvyH)wjH`FfLh=aeZ%bq=}Ic$4a_ ztN$Bnv6To8+~kIc&((EP7I8#^`}XBn+Ht|xKrPprENgMJ_WYD}To&UhgPcEMEeiJ@ zk$)4!h8V{-2^rKr7QD6TxEfRO(k|nH^ z0Bv%d(S+$vPYnQ88G>4_Kc28CT`Neda}3{TqK-+QKm^u#(=#sQyQh>~*8Tz7MuYovR+D+!Z2W4peYC=&HY+FnuKS z4@2z-#z^>!3c5xVmRAz*Rk#^Dx2QYjP#HLI#Vv^6>@}pPQ55g&QcatikvK%=z(;Xo zi-qnH2nTZvuVa*g9TeG{A%t*Qtk#(ly1Z?_T465d%99i65hxK3jrM9y@eS<N%$X$3a0ZyX-46c2J@5wjZvry;u9_+fHF5H4WOB)~TKi3d1PbnOyn5Y@Wl zwa*o4o*EG=T4SJV=kBK^A}ES%7=XtClb9)3x6cotG5}Ju=B_^y$Y3hu<3rpG@8nFdFK%`lU$N|hcAg`_K!2n zIUnXe?!-Am#BEPwn2QShZd|m$NBAtvblbouZww>u#5!^7TWn`e^_W`+JZX-*aZ7YQ zD*f!WhRahNG3#MQPGfD)9YZIXqhYj0izsYIzmCQ`X}n!HVs-rLwM-Xk$|9I1xQjB^ zw{vMU$on`8OvCNQ0_(F<_+T25*^hHSE$6P>ueGFA0B=5@TbUWtz+1ArtjKaBYJQiG z=rtYir803|5f1lnvEiV^qu-Ai8^5tTgG*+|Z>u=Vav$TzxK8+uOJs1_>iBKlZ(a*S ziyJgFeuE3Q1AF5g21x6Zy2j6qYKMZm3tux}mAxx0En)`<^;#c+3?oyLCqvxTf}O!a zxOMOV9M8Dy$njKBAHq_wc~uH9z`%;uR^kp`o0A&1*Byn;uG}!Jmr@{55pA}GUnv$r z)btQR(8}si#Wa0CtwJUgwr7%O!nlb_Q4m13x1l|c&q*^s*;11f3cK*l=Vh}*UG0pI z;Vp+c7=?IwYKoDjQ?WH8eJ)Dfbw;;u5MLi!JbRGWU@PTPE3gY^6$&WKg{9^VU{kDH zE~-;75hRgjzbm8Feq&<25e;)g&GboNE!ZNzWp%q;py;7JGCm{wIv_s#E05B zhceV^rx6Njp*$MBQkE&lH9hq8dmMoHUwIDTvVL+!xbz>282ztN7L8*8_JJwUfpe%a z^6tescw~b2p6LsqGlYn%_zOrk=aU(nWL$ zZkQ6uEJ-H4L!&6>V53a~t{RR?JU$gi-7?3Y6O-_4hvNNMHxw@={)=oRKA91Hy}WW! z=_I-P;H}V*ip5sZB)DFe^Xumgn2XB!z=#Wk316Z2b10fm+KKsRQd7)mm9cN@wjwSF zC=u?+Co5b?;Xc#nwqx3)n3%I-C=@4XsyyadOlNaRvP}Xfek$rNB;X|Ru%Jz|eB59| zixQLV9t9u1IYCEto}rgW{JOC3gie7SFI$jzQ=VQA$PSa3?eJX^L)k8Sa*y!aSSBSrsh~RDCM?1} z@tgv2T-=YFi&PyVSa3c+38D0wr0{9=Pw13WBouVYEZhxyMiVNV!Hs{d3T{jsSVuA& ze_I>(*L6~odMt)bz{`oto-H{FSi)7oln(x?h+k|oR9YvIbSi8z7Rq)bZTw~ zP9mJ~tqj^YfQ6Eo!`o4--u~;FNA^q={J4!Rd7Cy@gwNkS%HkDcX%^3=Qk2^1Q7`Mg zbur!*%?b7yuL^c=X5!D&cDyK9YI-6PmAKAC)QPQd`8dldrS&i;c|122x|bm-K85~@ zh`F5`tXu4|hdFgKvO6|_vY)KvQ<~CUGbQe5O58e>e2RD((5W29 zbBRyvHpRvJBb*rIS8EF9qT*GwRXa|^t-IyK`;B{UoHP)-8eFfuU*~Ar?pPIkFk$Cc zgKq9x;k!4~FHbwfcM-Ctc(yLCBlC27CoErvV|L+Z>T58%zLqk!iiF6^wRKVL@g0iV z(Upj589Ec#$v}k$o0vcAV9B(BQdPblIfk5-9jjOmMbfn~68qbtAoXy-9N?zI0oXf&!~JVwNF*P^ko9>-&JEJVF9snibTOHLiKjtQ(Yp#3tSILpmr(@F;>I{! z62(2mBZ?Y*MXu_Fn6YiBTZ8v?Nf>M_;IEOC(InGkOA3SAcTw3*PLz6Gx93tv;IpO6 z!YJI_5+jWR;tq1CB&g=~Mwvt)$B<`-Tk}Wyn;~d*wv0@ZgO%g$wg`613ty#*d%{rGzHzgALZe2SxveONJY_hO zs(Wu0>NYg)z$>bQ7(;8V&lE%+0D`?4dX6 zKPaP4(hZEb%d9X0cQ+!d&7}~EN#bPrvX;;I$*hm(W06T?SUj__Wc(~-=&7V7nUbKd z8JMTUJ3(#C1s%^2q!qhub1>Vl^W?q7R#Mhf(tsb8$E*^IZu;3Y$g~{Ctqm+AH^k~l zb0UBd7A9B|>ByNuR1F0CdN9uxZ4A#t&+KH}al*(Nm()T01^_-kJ5dP#Asg%bwV<2S zXN%0p13G|zpTtJes4SsWWM}Ak_MdtD}q)6 z!wa1zR|^&2oceUiKO1uQ?8Vx0lroH1`L&^JH3qpqG#W_aH>2^N44b3fyis4~OG>T? z{+|p*Yti91lGbuiH6GMl+?abz3etu3^^_u_TB6hy$T%?(F__W;E7z}Y!+71q`>kG_ zpS>peX~X|oEYn0bNl{T+XU_v}L*||PD}{l3rr@TaAP75HAd$dSutb^w*M}NRZfOYo=N)?SK>dC-Y5wq*_5eQM2m&>=lVub4*^R4K*FlPQ;4Bj+lUc zqe#kDCOCS20}p~*9Y3Uban@Y~WYW5nB*uptT;&hUxK&oeUylF|^i?e2Y z_JsdGyV*Jof2lFA34y}1IAiTo0GmZTv7E1bNz%+32B*ele9o&6Z4>r95%9{;Uk~fi zX7DP-;rp%ys>YnGNk#g+q!F)ynAjgQu#REnJ+Wj(qFPzfz_oA6r39;<9(j3Qbkr+2 zU1PB?R~Gv}b!Q$K@wB{yBXW)!@DFDblW*B*xa*ztnIGo7so=ZIMLto-$!NUsI2lgN zVKe}Ap5+taE=jfqbsPzrN&TqE7ygiB@HkjmWpVX)-}8&Jo3io}4Y>j0Tg538vH}*A z9OPXbEbVu(Q63CH@!(;_+Wxh^glvlQz`r5giK64O)s(uE1zks_W*19Bx9beY#2jy8 zC0~r1r27WbeeH4+Q35Nf~TVv#}LI?Oa7M6o9= z6E`SLFe7B+;aE^?bO~X{ch;!YBtSV7)7uOA+>3<6{rj20r7F zSp}INEvhO&lJ+XG7qhDF6D&31gq|DeDQWZG0RCwE&SJ5syphBb`nG0>^N|M8{n!%0 zMU&m>J;;PD3zPL<*~DEu>A0g@XUnRR0tg1zS6*6PL>Y7P(=hz1%s97dqF;q7+6Dx# W{e?~d0zd_^MQP${Ly!BU>eDFqRnmjKq+&B1>hN$d(W$L$+cV+aQwc z8p~iTNtQ9jzOT>CcX{65@&1nIeUIb!{K3rJGxvF&*L9xP`8hwI>wa;|P>18_>7yVJ zh(i~8{SF9phy=W!IKmA4Ul)F$47@OS+|juPDrgs^0v`@LKnx%t(C28jZ5t-wGwVYr z%mV~E?z#WRFl;aK7zC2~t$Q7E_pv2?Xee5+CuMJ8N9|gK0bg_@bM!)l!!|Uija`_j z|GjeG!1GAiVp*G0JiRsWW9E-z7^)zBX1w|Mmk(6jBQUp%9?0CgRxNk?7iAE3-r_Lc zRN~m#y{oA9!fF#Z9A_9n>&}^;eH-}Ls>;q={hcxTW5uQd&d6l1t=^A|AMg#-Biy%p z>lEZP@b<`c%>I;4gQ1MT3kNrr0R(!=d}M#JR~faAVfW_tb_~edUu=O3wVj=dxqtpp z*evkmVW<6TS}lb^U=HBjW5*4XgWEw|QZ+||E&-Q*rjMIK4(wmSZ(lqx`ZO%wis@kF z`Tx)uFDFhHmdjvn%QlhUbMX!y77Y8VLEcT zkXU6#>r*nF6a*Fq`C~CRaUGn(^o_%#Lbk@|p)uonZ0^Kz@#|*rfQz+0V^XP+%`!N} zmz;;ZnJDavnH4S$I=4krV@~z?GI<09a(oqU)$o;tx*^`-?FY8<>rGml(H;Z$;KkK` z*jmrb8fyl5-u)JfYkl+^FI1p}nEC<^_Pn?Hq*_?0cvi#hYrUkih}MYQRQ&?r4IS`? zZxb9aS1fb0yhYJAAZ7NsmO8u6==6$rn-K~9U~%P%MxPTcK7_XYFep3E!L*X{hAV;r zts_b=8Qgxpqf@t7JS*QoC;Lsegb6=?lQg^M(xENdGvwd^J2othrbSz7@-t0(`l!tI zirh63B^F7K$Ym>QR4--uR5tmMdfk@72UEd#K8tX}sr1j-wXUNU z$FCG|$5^$W3ZHS>6+N*+o9!K)Vy2>GDj!}eUkSU8z?AMy9g!?{rQBJq?sZP6Sh0$X zr%I>ABk1OLwW(!OPb>Tz-%qdGQL^7DojqM*K5OwZ%X_Z|R__G@@mT^HD0U3n@cx=- z>(P@9wJ>(xmW~Onc%|*fI9NUFnNMERuZ0`z-tzDvEUymv9^o~CC{s-HBM=hT?I|ZM zvxJWHTqVP63@b0?T4m|oZ;#Z8>it}gsA?_t+FI)kyfAWQ&WDF;UI}X~@@v=G@>V6( z0BHo|c!WNNmyz|y=Lc6whYTuQ-5=j@hq-}o;$SxC*+O-NsH3$^Ln~` zJ`R;+mYm&1!|TOv#(~VOqtgvr9J>P>Do(Rd153>ve7vhlBVL!%fPHzG>O91~SOD|u z->ezZ!vzWn3kUjt5f|x;`)Qmxivg!_ncWDHzd2oKoK>1Xy{t+nVRtcLsX_YGhn+){ zPRL6bui`Q#Bj*+nNVe%eO)aaG78Gvy-o?|RwNh{Q6sqmKSXZ-SWM9w>9>6qtLR1w zoRypJU{iBz&YJ9CajU#B8Fi&sR;tA^0jM`uQ}^r0fISnZ`mH_&nYV5$zZx#qMJr0N znN+w6)X}`wv^-m0One~5GfjK-rz?n@p>JMmX6Jg29yoi4uv-MC7bH7>Dm3$1l{=q& z%6IsU0T)WiPvD*0s0on{0_mULuVJ21T|6J9mat2g%Odyt(L_8uzcy$^JsBr* zh$@-P7V!+tR(?SaZs@DwVU*U1%6|3asG7Mp7pVxP=nr1|{qm_i?eMi@gVGs>JJX-z zibl}8S6_dgg2{N8UWM0rvo}vTA%FN)A|}y9fzc{R+#ie^6i} zUazZ+%_h3K@Uhe@f%5=1)M5Fep$1|Crw}qOoyT_AG_n`;6 zdX2Uycg(HS<4;m9TpK9A-)_&vdI(f&)bjp89snBt;ZfHiXE_cpm~IYPR{DSEhB>~d z({kW{&0I6PeZ2f>A{(?|d;XA=B*NxC*%(t=??4E+jvw&~FN)7Co+~LOqIS+UYM*>O z)3Rz1ztGl_Z;ozvgj75y8VzikVG0J?-+Pq~=-BOzL`IxD=0b(k{5@NWr!lh0q14D~)LE(eNWX~Ef|;Aqv!q-MTIgYyiT-Mglzvs6BF#%t z*SCxV3m8D3`tj@+&;0>?1qqodaxX_btLIeqibl9s6H|{n=RI{Io8QwGm5eJ$>lu%C zX<0S0VUe#C=GXGqh+8S(^|ch3t1O~NPLrbzZWC?i*jlQ6OeiMGrK@-n^49LtPtnP} zv*jx(bas@(R`h#2*oeqQ5Qv>oD){9KRuZG_%BQ%`^+vGT3#}a?rx6t=Ee0Q+JQ07B zJSPWDv-*xCz>SjdyTfZkBG{G_(=sZGOqZjHGLl;pCdhiNlgcg z>_Ak@c4KVEn&a0#MeR%+rb^1bQVjAmQNs-i@B~Z>fI!K*2WieGapkM}=ak0U4|v(G zGbgBB`R~OLA8eY2&q>`!GxPhY$g%Ib3P%)i zSfgj@W2v4C!BxoVRl9~ZWe}-^hWVN24|}=vFVfjvCr|QIkZGoy^L!vs=!dPjDz5@x9+MAae6RqywA*cbF0ZhVZ7?^daGr6ogXrEDOcUHbfM6CMYyraf_{Ex zDL@!Llo*vpNfX*`4ymjzWcP(NdzF&Cg(-Xku>fFEfT$lKsefNNBC+J5j!OamICEkn zOOIK>td&)9fB4NpSq?F*qK>F8^Q`efAq-e!7Cx*!V*3c7fkKv}iQ4_kFvo;fd7qNqOM+Vl-z&yc5l%4#gOB>1n$7Ddi1S z)JXbSbagcFU8v<57C1R=c>SUh?;$=mmJFBvgddj;DtlR3>*QU>l1DaEPbUW03Bi;u z=@T~on&>S(nW%v()oao*$nLYzuZv{rK(fuh-)6ySB<}o>->TQ@Jd@LS>V}`}4|vY1 z{4&+%p)UWOctx2WZ8$KgF{~uCr8DB3`VZ*~TFs66f=veM24_d8iz+nuWDp7fp@7-m_+ zL9kRuQ2em16#Lq>X3sQ*p@|ZT{hTHc*IO|x6Je|JWLDChiA~DfcveqNE@!?pFgf>M z%uX9NC(BiCvDHiS?+L0#nKk=wX$Gd|=1vdntbE{^_8d*d!7GugyF6G1_79!blGBHs zMy1UihAIY&h!EfLcjbYT1?6k~r(UQLTE7kGy6m3xP_V7*uNd&O`P1t~_*bkr zWCEwLJ2YpzddbQyxOI(KT8?&_?lw7%RTJG9PLZ%jk7Hpk^M>`Wt*n%|swiD@8CA7B zcXaf4hTBL)v$@)-grs(sr-4q#v0dC!MDib(^vN8g#S@(TbFN`d8#Vg5zRh8Uu75@& zX6_HgD2VTh{qc;1i@3B)0;Co}Bii-|6=_)K^?C9%Xfq#$Db?~+l{&Ce$Jv!GYPQ~7 zx|Rln?0kp?*tp1bXgr{Bt4Ye7i!|AaX05&rj!$)@I19dXOEN)h*c}O1li?sWP(ht; z=wN&+LCf=IR!E);`J^x1u-?-#oVU7&evm~sNgmw3jPEVxugPQ&7@R>*f7HrtIfae2 z&bz?Y;#;TyIepa}i1)KT@8VHH^-_i^e0}0_d4K0Q2GvW~U4Xqu+yl~7E2rHy5{MW5 zvo=!WS`$S~NcDu6&?%vjM90X4S)hS+d?kSO*%s0sp4mRO^u120b+{qZessR5e{bq& zr|F{U&hSojk~&*-&ZKqCck;sl&xB>+=c_m0#POS%3YjJOVrC;kIFHt>@;L>#UjEA` zyQ*T|P(M*b#Y%W-!I0wq(%Rb3J!@>;{?gdiIvZf$Sidy!MX0!(k#o6zxqxU-p4pvx zr^XjDjZmnZcO12tVWFOMq~WY6A9E$44n}m0&M^Ah&6X}j=@EH?jDr#nFQd1^{cv=> z=>CX!uoSUzY?o)Wi>ob3OwWi1+t_4rB4d&_n%D4=HKufK(3Y1=L}_U&`r{;`aJX_6 zGGC@BvcGF5J`7~%UV^@g^RUlc`d(R}=H0fk3?sP^emSj<&Eu)S0wR9|;n%5KB21bh z13Jx^BE0GyWT4>@s=k@ewBJONaR(0;E`Ls&xe#Y7Z7koWWSR9Mu=i}e%J0LShL7HJ z$VWiiwdmV3A?*E_wGhQZ&I_5&>pB8xpWsWNh{PhWloHE5^$@Y=Z$uGJXzalDJ8lw> zl;~S9@-@nzpGR!ZIr4nh3}SEt&7L96&m~o_f{zt+tZyG;vq$a8t!&T4Rf+#TM8-Bk zdRd9eFCpZEGSD1^ht_+>raHmI&s@h1?7Ul73-Y{q+Mr^A7E$;bfk^3OHsUBMC}(W^ zCHG@MmlF@!#Uw``_!;KzQyA#$o(rIoHc|`3cUGK>F1r?3W$@}z4RDXj1+#{u*3)b{5e%| zIz}hPNnEA#oC;UTk_Y#1jYB@x)m1XC@<{GAh2`9WNC&TE35U{LItwWC_jD3V+h)$t zbV)(P6*jZL`!_<7eRglR-c4C@OnU@@goz5URCFJfctL;mz-)S!VsCLXn|I_B^Z3PV_N;7v|Je7Bu6tK?jdkZe-TlN6r# zxUkiK21T4<{qZDVQe&xgZ0Ya&!q=tu@ggZr}Pv-8cDAtt>`>4WYl> zqhRcAw5-s$nnNztmHh!R`}XxYr=(FM$#KczPL|qmmLVMNh(76y9RmlDUGq}#fui)6 z<GD`?OTQ?X(4M-lg;k=wC#3p7Vd99cCbjj1fw zUTY%9#xRNS2Lh()?LT>MPzzN!nQQ7z%CoFSpl~hUX6-f82aoZpW)=;m*+yZBE4xTG zN>mwpe^i-N9^!-4pzWA6Pno5w~t{iEcaVm-^Ex>G4lNAZl1}PQOOjNw7D(!>*p^<#$^F!4>4SCJCFmY#YjUTdr zmEQ(e3NhuOWV|O!^2Eo#&&OQq?pGhJ_C+7>%l!0MV~bF;U;WniQet zp3QpX1vm3PudfKG8nl)!oy>g4uiw#3@K*k+*{f?PyrEe_D34GJ!pp<;?_dlMrSf3U-o0RpTVjyr@ZS*DRZ2`?f_YaI4nJ&C>_@!m zDRig&p-F5nJxLIg%9M@B`pp$x_bC2Tz(oqP_uiT3YkU8_0A%d5d&xNWg#2O@9M!+W zN@|e3Flc?Urd^5_N@#cCkH@SAd3pNjsL?j3Ih4MG;SQ8*T6v|e;(gkUl1@tA8-Xm; zUypL^Hf9EMx;TL%SzDGo1#W8#WmRI|s=FgvTTaA^qL z2g!zV+cH$xE+M0ICd#LpC*MJ+=9k7w5yv=WKs^;5bqwg0WoOT+LX8H;=DNW{tQEcU z>{jA!a| z2>)=piEb=Xnw}RqNZog)BGtHYHA%pMkZfexZ(r>{rm@nW50YiqAeQxPJ0mMM76{(C zE5*Mz|FcC;WAaoe3YhZ^ZfJ3?AgZ= zo)sLuvF9(++L(5+?RMX_NNkm7j7r1(?2}oj*nGPkSABwh;n6Rml-nlS-u>Ccf{`i` z9d4NVUUVEmn^?QxFVMUyqo&PZL_e>hEgj@pW>qjN`=snsLsi)oWa<=I@cN$KU3S zt4^~}FHNbYx7jllOZ!+PpZt{@jPIgdd{)fE8@u@1r&U+RZwxHdr0!O(@Vh|(%t#PZ zhUyfK-}V|>w6he9DMlaNI#I^a1QY_j=J3*bsmyO8Fu>Wwzc`Jvz@get=4Od<+BZUFhsBLniioC&u6YV(|>WyU} z=(>FdNW;C5sqXi*(`4|F8vmj-hg;K&i5%Md9K|3!J2GbL@NX-+y6Ar+FG&SXn|I3m`$u~LtI+Lc{T zac|vcJSj&sg7ft1R)KbB`h`Zn;oHb$LMz&2y_4%MrP{+SQ}cvYWQ*U5QlSQS^o!mB zZjg2pTT9nOtcd?U^bS;c>0R9g+K{9t73+l|^A_6iacDbuzCH)U?8k)F&ERa8+1lI1 zE?zah8H~uj5{DnHQo<%39hOag4=k$HH@gI^#=l(y*^XZIl-iQ7$Z{g9{+K8+5BkJT zS)U+O{={VQ5sqTeKL#r39C-$p*-&gKlCZ{KfYn6Wlc_x!l<*-lfiBlKv-0R^8 z2aG7z>^Tl9?92~Biaor3xQ=|*QD1mw3Ba2Cxy^K9Slh4k@n_E+Mb}szyWoo@Rz0Rq za{iTyRpirhFyd~G&&p2S$+~Cy60AO9KN+34!MNYko-Ka(`|&nZ{(ai-T*dOw54mkK zj31?4g>gOC`_>r})etK`Fln>P?*fl(IA3_o8OrA4)9FHuwE$YBC?YLflf{Y^*-nzG9jX z32>095N6xk;!rm4epOoUcs!gJJC^pe#;08}e@LFtmFBuPQ&2v;J?OU`OJ6iz80e^U z(cGJhC&X_@_|M{gF}xR5f`(ZdoxR%fkmK0ttf8XZ)NauOTGnNy=82=&Rm1-rW<&bh z|A3-Z5LJ$^i@C`X#~){Q3K~=*L#WD7T>AQ>6IGexMYjT!M6xoug$iXD;PK{_$ECAK!r36MFceiNJfsdb`bDRfz>y#yx{qYZ$o@Hth#T3Bax5(ibE(6!?Q`Dpq$Ae?Nb|HIQN5vEK|Heu9GZYkgkZL^++zH=?T z@Zq(Jw85es$YwkYohAN7g{`lN_UjRstENMN-kb+vZ6F|J`mifNkTtReu!w4*3}bmI zJNOnFis5xiqY%|!8YT6CcESLG5&@L! zHW$LO@Dk4`=+-Zyi^yS3+wKFheGi`PL?t#?`_Qb9WQa#w|piU(-U@*(d zC!4!EU&hh`uq?Em628anZ*=YU8e z7q8s*QLgb{afo%AE!Oty>8Mal?MD{8>n{jA&ro~5+;;*}9Oz8&&6nr`igGHG6tKnX z624`+KZl?K+)Uj z&hu4IJ_BSsaK84hhj0I_nF8Pa`v*V%!`qe9 zu-JRg*1n_8c3LG|78gZVP-;ghrBxNR`EPs+_-3(l6!iW^n&qH#U`grF_By4qhlURY ztAAS+e%#tB;y>6rGwk4X<%*l|pj@)r&#RjHa|143ZL`ts<-xbJEftH|qIuhItnWNR zhi%k{NKG`1J1uRGb=mKw!kx_-LClk1zwiU;^Tua#`OU^J(#`}Bo0Yf7VzM|i`gQsF z>m5?UZ9>-8o&O?HoPCKZFiftTB;?RpL4AUHYzh+{Zb&(D`|RDqp$mROLHIGZj@@9N zEuzbWgUGgblzyzwfU3btu{3|Xs1_B5T`XqlmYODu&E1h)`FCT*uhw#rM?ii4 z|MWeCS zdVgr#-xqoZpV=-XI&S?ugpASrJ(0QZ+Ln#QaBhvy%CpD%_});^)3&v`Mf}EZ7Axbz z(K<`7j9|R~&n9xQ{F!UXb7Hjb73m_K!38c0^E`w1!woKjd&WjHvO0M zTg$D+4bQBJDCikD@W&Nns42NGBKTh=+)lU>)2i{Q)*iDzxSt$q&ctUhrq>JfbX1h= zOg}9>Gk#7H+G6_2!1tZSozOQQ+Vo0p18`k$%?<1&xA!#yjYWT? zHWCnBLp!G1WLk+pfsBzaOxqN~HZBlP^J0zOeu#^;M@wy*rf`Ay&IIAZ25k!WW!_>F zD<)iXGkZRuzUnJMW%A!Ckmm+3uW7tGbhnWX=%?DtUtDF#T<*|HAHx)-OTDND$8wD8sJ?HaEvTv;=&$FGHip{CY&NnI1Iz-2k=aIVljI)?w=L#a42W z@P&j34|XA$3y6x2*nDF^t%G}EEGq^#!0|r?Ln?bNyPrMU+r+X&Z!xI%JkhRMiMW?S zUHtOIFI#iQ=xtG-B-5Mf&5Vn*^j%XcdRH95kBdS8@f4n;af`w*7?-bVLUu zEvosRd%(kFvL4oK@nnlQh(8dd5iHa)9R5uASy9=|_m&shb5E>w^9C<>nwK9h(ZzQp zsO@d85+A`fY%{6?!g|g#Q{4j!-#5YW&+;>mFaP_lsl*+F9P(B_cXSf6+Dc< z8sv|CO_&d`4h*1PzoNOaFc&CNjBAn~ zsJJ$aaL&Ifrg}ReB@z<8>Mq5!b>pf^7#*b?f2{ z26FjcE}aRdY@H;|<~i)W?nDMV_M<4?Swry{7ok|Y9e)94p-NAcalR%zDw#Lx_KugE z1T=cl&xDKAD}o}m{}8!F&h(PmwqXQ00tb-Kx6jB-(Tmp3ZunY;I+TsCszX@>)#!Zvls5?@sjBqh4zM~*Ng$r+_OekBB>NcH zg=3r0d<)FIdZ&*(8F{H>WxETsGSNaZI3;i73e+3jczbJAfl?T`ehgh|=y-1cYzH$D zwCGB$&l6V?BD|9{9W1Oq?1Ts)40hW7KH0gSiesCWXQ7O>^I}lHh_UD^eUO1u+c5&o zi|Tp0d>(#qHJi?(9_i^uT+bS)k-_+E!5W&3SpOt`R<$Mmli$;p(tL%X0-PqKVzaM& zoQWQrl`*u%k8Mz{HeCV3AGJz!cz|lb+*oyNg5zMIS05)yS2>moQ5jaU%>s+L6(>Ey zFJb;TNDJFV^QHJ6zu_IA2J+O{MwqP_s~rL!B(&T-9E`QRU{tDNuGG&WaZ6Q8;ONZL zI}WgoC*6jRf^7(7)qv}80!IwpC=}vZT8`b>;=#rO58V}P^PQc97Dc86=%zIv>zpkB z1SWU?!gwa?a-y9rxkOY8^i+`>EAej>ixy7OA3hNl$FuJo2c7NfZ+UUaE?@hZJg2Fg z&*_lTJQI5y*_n`mMuAsl0Z)lZeTdih&*0A>6-HS zH6SGLY<_un+77NC1 zc#QuvN;5J@;T%s`OXeTPg~&UV^JHy@zR*m=h0rk!3!Z^7iwj;T7mCh!L6ivb{1yt7Y2f zMTSf-;q7=sinBQ|osNYag^B2d(vRfXH^eIt--uS}E6)38J6yAgZ9;a|m^0U9gkf^U zTT$7QXJ7s;&(E2F`2IMavA5YCFp<6l`8h>=@tR)HLDon(h;(%ucP%lIXhe3|fS5mZ4 sk`|hmb1iX~|G#@-JIJQ!(jLPpwv6a-s^wvzxd!RpFuY!H%{u760Ft(?nE(I) literal 11220 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 MZWh2!_Zu@zC-RKjZe8Y@R=?oKtf2P(R@GSfdH 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

    6UB=BTN2JGQDhT}p%k(-!~F@xZG> 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≦Kv8 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 literal 0 HcmV?d00001 diff --git a/website/docs/assets/maya-yeti_rig.jpg b/website/docs/assets/maya-yeti_rig.jpg deleted file mode 100644 index 07b13db409d0ad6bf1f887896e6f3d0fd5e7e10b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59405 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%0D1;wn^$71V{3R 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 EFKbZ!`Tzg` diff --git a/website/docs/assets/maya-yeti_rig_setup.png b/website/docs/assets/maya-yeti_rig_setup.png new file mode 100644 index 0000000000000000000000000000000000000000..876ecba0a2b0e4496f590a650de56532c3b104f0 GIT binary patch literal 111360 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
    ^s@U(eB2|H$bp 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 literal 0 HcmV?d00001 diff --git a/website/docs/assets/maya-yeti_simple_rig.png b/website/docs/assets/maya-yeti_simple_rig.png new file mode 100644 index 0000000000000000000000000000000000000000..31a60ac40b3f712e7ecd1bcdac4fc80017977594 GIT binary patch literal 96188 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

    `}O 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 literal 0 HcmV?d00001 diff --git a/website/docs/dev_colorspace.md b/website/docs/dev_colorspace.md index fe9a0ec1e38..c4b8e74d73a 100644 --- a/website/docs/dev_colorspace.md +++ b/website/docs/dev_colorspace.md @@ -24,8 +24,8 @@ It's up to the Loaders to read these values and apply the correct expected color ### Keys - **colorspace** - string value used in other publish plugins and loaders - **config** - storing two versions of path. - - **path** - is formated and with baked platform root. It is used for posible need to find out where we were sourcing color config during publishing. - - **template** - unformated tempate resolved from settings. It is used for other plugins targeted to remote publish which could be processed at different platform. + - **path** - is formatted and with baked platform root. It is used for possible need to find out where we were sourcing color config during publishing. + - **template** - unformatted template resolved from settings. It is used for other plugins targeted to remote publish which could be processed at different platform. ### Example { @@ -63,7 +63,7 @@ It's up to the Loaders to read these values and apply the correct expected color - set the `OCIO` environment variable before launching the host via a prelaunch hook - or (if the host allows) to set the workfile OCIO config path using the host's API -3. Each Extractor exporting pixel data (e.g. image or video) has to use parent class `openpype.pipeline.publish.publish_plugins.ExtractorColormanaged` and use `self.set_representation_colorspace` on the representations to be integrated. +3. Each Extractor exporting pixel data (e.g. image or video) has to inherit from the mixin class `openpype.pipeline.publish.publish_plugins.ColormanagedPyblishPluginMixin` and use `self.set_representation_colorspace` on the representations to be integrated. The **set_representation_colorspace** method adds `colorspaceData` to the representation. If the `colorspace` passed is not `None` then it is added directly to the representation with resolved config path otherwise a color space is assumed using the configured file rules. If no file rule matches the `colorspaceData` is **not** added to the representation. diff --git a/website/docs/dev_host_implementation.md b/website/docs/dev_host_implementation.md index 3702483ad10..e62043723fc 100644 --- a/website/docs/dev_host_implementation.md +++ b/website/docs/dev_host_implementation.md @@ -45,10 +45,10 @@ openpype/hosts/{host name} ``` ### Launch Hooks -Launch hooks are not directly connected to host implementation, but they can be used to modify launch of process which may be crutial for the implementation. Launch hook are plugins called when DCC is launched. They are processed in sequence before and after launch. Pre launch hooks can change how process of DCC is launched, e.g. change subprocess flags, modify environments or modify launch arguments. If prelaunch hook crashes the application is not launched at all. Postlaunch hooks are triggered after launch of subprocess. They can be used to change statuses in your project tracker, start timer, etc. Crashed postlaunch hooks have no effect on rest of postlaunch hooks or launched process. They can be filtered by platform, host and application and order is defined by integer value. Hooks inside host are automatically loaded (one reason why folder name should match host name) or can be defined from modules. Hooks execution share same launch context where can be stored data used across multiple hooks (please be very specific in stored keys e.g. 'project' vs. 'project_name'). For more detailed information look into `openpype/lib/applications.py`. +Launch hooks are not directly connected to host implementation, but they can be used to modify launch of process which may be crucial for the implementation. Launch hook are plugins called when DCC is launched. They are processed in sequence before and after launch. Pre launch hooks can change how process of DCC is launched, e.g. change subprocess flags, modify environments or modify launch arguments. If prelaunch hook crashes the application is not launched at all. Postlaunch hooks are triggered after launch of subprocess. They can be used to change statuses in your project tracker, start timer, etc. Crashed postlaunch hooks have no effect on rest of postlaunch hooks or launched process. They can be filtered by platform, host and application and order is defined by integer value. Hooks inside host are automatically loaded (one reason why folder name should match host name) or can be defined from modules. Hooks execution share same launch context where can be stored data used across multiple hooks (please be very specific in stored keys e.g. 'project' vs. 'project_name'). For more detailed information look into `openpype/lib/applications.py`. ### Public interface -Public face is at this moment related to launching of the DCC. At this moment there there is only option to modify environment variables before launch by implementing function `add_implementation_envs` (must be available in `openpype/hosts/{host name}/__init__.py`). The function is called after pre launch hooks, as last step before subprocess launch, to be able set environment variables crutial for proper integration. It is also good place for functions that are used in prelaunch hooks and in-DCC integration. Future plans are to be able get workfiles extensions from here. Right now workfiles extensions are hardcoded in `openpype/pipeline/constants.py` under `HOST_WORKFILE_EXTENSIONS`, we would like to handle hosts as addons similar to OpenPype modules, and more improvements which are now hardcoded. +Public face is at this moment related to launching of the DCC. At this moment there there is only option to modify environment variables before launch by implementing function `add_implementation_envs` (must be available in `openpype/hosts/{host name}/__init__.py`). The function is called after pre launch hooks, as last step before subprocess launch, to be able set environment variables crucial for proper integration. It is also good place for functions that are used in prelaunch hooks and in-DCC integration. Future plans are to be able get workfiles extensions from here. Right now workfiles extensions are hardcoded in `openpype/pipeline/constants.py` under `HOST_WORKFILE_EXTENSIONS`, we would like to handle hosts as addons similar to OpenPype modules, and more improvements which are now hardcoded. ### Integration We've prepared base class `HostBase` in `openpype/host/host.py` to define minimum requirements and provide some default method implementations. The minimum requirement for a host is `name` attribute, this host would not be able to do much but is valid. To extend functionality we've prepared interfaces that helps to identify what is host capable of and if is possible to use certain tools with it. For those cases we defined interfaces for each workflow. `IWorkfileHost` interface add requirement to implement workfiles related methods which makes host usable in combination with Workfiles tool. `ILoadHost` interface add requirements to be able load, update, switch or remove referenced representations which should add support to use Loader and Scene Inventory tools. `INewPublisher` interface is required to be able use host with new OpenPype publish workflow. This is what must or can be implemented to allow certain functionality. `HostBase` will have more responsibility which will be taken from global variables in future. This process won't happen at once, but will be slow to keep backwards compatibility for some time. diff --git a/website/docs/dev_publishing.md b/website/docs/dev_publishing.md index 135f6cd9856..2c575372238 100644 --- a/website/docs/dev_publishing.md +++ b/website/docs/dev_publishing.md @@ -415,7 +415,7 @@ class CreateRender(Creator): # - 'asset' - asset name # - 'task' - task name # - 'variant' - variant - # - 'family' - instnace family + # - 'family' - instance family # Check if should use selection or not if pre_create_data.get("use_selection"): diff --git a/website/docs/dev_settings.md b/website/docs/dev_settings.md index 94590345e86..1010169a5f1 100644 --- a/website/docs/dev_settings.md +++ b/website/docs/dev_settings.md @@ -355,7 +355,7 @@ These inputs wraps another inputs into {key: value} relation { "type": "text", "key": "command", - "label": "Comand" + "label": "Command" } ] }, @@ -420,7 +420,7 @@ How output of the schema could look like on save: - number input, can be used for both integer and float - key `"decimal"` defines how many decimal places will be used, 0 is for integer input (Default: `0`) - key `"minimum"` as minimum allowed number to enter (Default: `-99999`) - - key `"maxium"` as maximum allowed number to enter (Default: `99999`) + - key `"maximum"` as maximum allowed number to enter (Default: `99999`) - key `"steps"` will change single step value of UI inputs (using arrows and wheel scroll) - for UI it is possible to show slider to enable this option set `show_slider` to `true` ```javascript @@ -602,7 +602,7 @@ How output of the schema could look like on save: - there are 2 possible ways how to set the type: 1.) dictionary with item modifiers (`number` input has `minimum`, `maximum` and `decimals`) in that case item type must be set as value of `"type"` (example below) 2.) item type name as string without modifiers (e.g. [text](#text)) - 3.) enhancement of 1.) there is also support of `template` type but be carefull about endless loop of templates + 3.) enhancement of 1.) there is also support of `template` type but be careful about endless loop of templates - goal of using `template` is to easily change same item definitions in multiple lists 1.) with item modifiers diff --git a/website/docs/dev_testing.md b/website/docs/dev_testing.md index 7136ceb4792..434c1ca9ffd 100644 --- a/website/docs/dev_testing.md +++ b/website/docs/dev_testing.md @@ -57,7 +57,7 @@ Content: Contains end to end testing in a DCC. Currently it is setup to start DCC application with prepared worfkile, run publish process and compare results in DB and file system automatically. This approach is implemented as it should work in any DCC application and should cover most common use cases. Not all hosts allow "real headless" publishing, but all hosts should allow to trigger -publish process programatically when UI of host is actually running. +publish process programmatically when UI of host is actually running. There will be eventually also possibility to build workfile and publish it programmatically, this would work only in DCCs that support it (Maya, Nuke). diff --git a/website/docs/manager_ftrack.md b/website/docs/manager_ftrack.md index b5ca1678387..836d84405e7 100644 --- a/website/docs/manager_ftrack.md +++ b/website/docs/manager_ftrack.md @@ -4,7 +4,7 @@ title: Ftrack sidebar_label: Project Manager --- -Ftrack is currently the main project management option for OpenPype. This documentation assumes that you are familiar with Ftrack and it's basic principles. If you're new to Ftrack, we recommend having a thorough look at [Ftrack Official Documentation](https://help.ftrack.com/en/). +Ftrack is currently the main project management option for OpenPype. This documentation assumes that you are familiar with Ftrack and its basic principles. If you're new to Ftrack, we recommend having a thorough look at [Ftrack Official Documentation](https://help.ftrack.com/en/). ## Project management Setting project attributes is the key to properly working pipeline. diff --git a/website/docs/module_deadline.md b/website/docs/module_deadline.md index ab1016788d2..94b6a381c2b 100644 --- a/website/docs/module_deadline.md +++ b/website/docs/module_deadline.md @@ -45,6 +45,10 @@ executable. It is recommended to use the `openpype_console` executable as it pro ![Configure plugin](assets/deadline_configure_plugin.png) +### OpenPypeTileAssembler Plugin +To setup tile rendering copy the `OpenPypeTileAssembler` plugin to the repository; +`[OpenPype]\openpype\modules\deadline\repository\custom\plugins\OpenPypeTileAssembler` > `[DeadlineRepository]\custom\plugins\OpenPypeTileAssembler` + ### Pools The main pools can be configured at `project_settings/deadline/publish/CollectDeadlinePools/primary_pool`, which is applied to the rendering jobs. diff --git a/website/docs/module_ftrack.md b/website/docs/module_ftrack.md index 6d5529b512e..9111e4658c5 100644 --- a/website/docs/module_ftrack.md +++ b/website/docs/module_ftrack.md @@ -8,7 +8,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -Ftrack is currently the main project management option for OpenPype. This documentation assumes that you are familiar with Ftrack and it's basic principles. If you're new to Ftrack, we recommend having a thorough look at [Ftrack Official Documentation](http://ftrack.rtd.ftrack.com/en/stable/). +Ftrack is currently the main project management option for OpenPype. This documentation assumes that you are familiar with Ftrack and its basic principles. If you're new to Ftrack, we recommend having a thorough look at [Ftrack Official Documentation](http://ftrack.rtd.ftrack.com/en/stable/). ## Prepare Ftrack for OpenPype diff --git a/website/docs/module_kitsu.md b/website/docs/module_kitsu.md index 7738ee1ce2f..05cff87fccc 100644 --- a/website/docs/module_kitsu.md +++ b/website/docs/module_kitsu.md @@ -7,7 +7,7 @@ sidebar_label: Kitsu import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -Kitsu is a great open source production tracker and can be used for project management instead of Ftrack. This documentation assumes that you are familiar with Kitsu and it's basic principles. If you're new to Kitsu, we recommend having a thorough look at [Kitsu Official Documentation](https://kitsu.cg-wire.com/). +Kitsu is a great open source production tracker and can be used for project management instead of Ftrack. This documentation assumes that you are familiar with Kitsu and its basic principles. If you're new to Kitsu, we recommend having a thorough look at [Kitsu Official Documentation](https://kitsu.cg-wire.com/). ## Prepare Kitsu for OpenPype @@ -38,7 +38,20 @@ This functionality cannot deal with all cases and is not error proof, some inter openpype_console module kitsu push-to-zou -l me@domain.ext -p my_password ``` +## Integrate Kitsu Note +Task status can be automatically set during publish thanks to `Integrate Kitsu Note`. This feature can be configured in: + +`Admin -> Studio Settings -> Project Settings -> Kitsu -> Integrate Kitsu Note`. + +There are four settings available: +- `Set status on note` -> Turns on and off this integrator. +- `Note shortname` -> Which status shortname should be set automatically (Case sensitive). +- `Status change conditions - Status conditions` -> Conditions that need to be met for kitsu status to be changed. You can add as many conditions as you like. There are two fields to each conditions: `Condition` (Whether current status should be equal or not equal to the condition status) and `Short name` (Kitsu Shortname of the condition status). +- `Status change conditions - Family requirements` -> With this option you can add requirements to which families must be pushed or not in order to have the task status set by this integrator. There are two fields for each requirements: `Condition` (Same as the above) and `Family` (name of the family concerned by this requirement). For instance, adding one item set to `Not equal` and `workfile`, would mean the task status would change if a subset from another family than workfile is published (workfile can still be included), but not if you publish the workfile subset only. + +![Integrate Kitsu Note project settings](assets/integrate_kitsu_note_settings.png) + ## Q&A ### Is it safe to rename an entity from Kitsu? Absolutely! Entities are linked by their unique IDs between the two databases. -But renaming from the OP's Project Manager won't apply the change to Kitsu, it'll be overriden during the next synchronization. +But renaming from the OP's Project Manager won't apply the change to Kitsu, it'll be overridden during the next synchronization. diff --git a/website/docs/module_site_sync.md b/website/docs/module_site_sync.md index 2e9cf011021..3e5794579c9 100644 --- a/website/docs/module_site_sync.md +++ b/website/docs/module_site_sync.md @@ -89,7 +89,7 @@ all share the same provider). Handles files stored on disk storage. -Local drive provider is the most basic one that is used for accessing all standard hard disk storage scenarios. It will work with any storage that can be mounted on your system in a standard way. This could correspond to a physical external hard drive, network mounted storage, internal drive or even VPN connected network drive. It doesn't care about how te drive is mounted, but you must be able to point to it with a simple directory path. +Local drive provider is the most basic one that is used for accessing all standard hard disk storage scenarios. It will work with any storage that can be mounted on your system in a standard way. This could correspond to a physical external hard drive, network mounted storage, internal drive or even VPN connected network drive. It doesn't care about how the drive is mounted, but you must be able to point to it with a simple directory path. Default sites `local` and `studio` both use local drive provider. diff --git a/website/docs/project_settings/assets/global_tools_custom_staging_dir.png b/website/docs/project_settings/assets/global_tools_custom_staging_dir.png new file mode 100644 index 0000000000000000000000000000000000000000..f7e8660a8863239310a1934a49c2811b4e0c031b GIT binary patch literal 9940 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 VmwKMN3A}U$l9y4I&XY9q`!5KAZJhuB literal 0 HcmV?d00001 diff --git a/website/docs/project_settings/settings_project_global.md b/website/docs/project_settings/settings_project_global.md index b320b5502f9..821585ae21d 100644 --- a/website/docs/project_settings/settings_project_global.md +++ b/website/docs/project_settings/settings_project_global.md @@ -10,7 +10,7 @@ import TabItem from '@theme/TabItem'; Project settings can have project specific values. Each new project is using studio values defined in **default** project but these values can be modified or overridden per project. :::warning Default studio values -Projects always use default project values unless they have [project override](../admin_settings#project-overrides) (orage colour). Any changes in default project may affect all existing projects. +Projects always use default project values unless they have [project override](../admin_settings#project-overrides) (orange colour). Any changes in default project may affect all existing projects. ::: ## Color Management (ImageIO) @@ -39,14 +39,14 @@ Procedure of resolving path (from above example) will look first into path 1st a ### Using File rules File rules are inspired by [OCIO v2 configuration]((https://opencolorio.readthedocs.io/en/latest/guides/authoring/rules.html)). Each rule has a unique name which can be overridden by host-specific _File rules_ (example: `project_settings/nuke/imageio/file_rules/rules`). -The _input pattern_ matching uses REGEX expression syntax (try [regexr.com](https://regexr.com/)). Matching rules procedure's intention is to be used during publishing or loading of representation. Since the publishing procedure is run before integrator formate publish template path, make sure the pattern is working or any work render path. +The _input pattern_ matching uses REGEX expression syntax (try [regexr.com](https://regexr.com/)). Matching rules procedure's intention is to be used during publishing or loading of representation. Since the publishing procedure is run before integrator format publish template path, make sure the pattern is working or any work render path. :::warning Colorspace name input The **colorspace name** value is a raw string input and no validation is run after saving project settings. We recommend to open the specified `config.ocio` file and copy pasting the exact colorspace names. ::: ### Extract OIIO Transcode -OIIOTools transcoder plugin with configurable output presets. Any incoming representation with `colorspaceData` is convertable to single or multiple representations with different target colorspaces or display and viewer names found in linked **config.ocio** file. +OIIOTools transcoder plugin with configurable output presets. Any incoming representation with `colorspaceData` is convertible to single or multiple representations with different target colorspaces or display and viewer names found in linked **config.ocio** file. `oiiotool` is used for transcoding, eg. `oiiotool` must be present in `vendor/bin/oiio` or environment variable `OPENPYPE_OIIO_PATHS` must be provided for custom oiio installation. @@ -82,8 +82,8 @@ All context filters are lists which may contain strings or Regular expressions ( - **`tasks`** - Currently processed task. `["modeling", "animation"]` :::important Filtering -Filters are optional. In case when multiple profiles match current context, profile with higher number of matched filters has higher priority that profile without filters. -(Eg. order of when filter is added doesn't matter, only the precision of matching does.) +Filters are optional. In case when multiple profiles match current context, profile with higher number of matched filters has higher priority than profile without filters. +(The order the profiles in settings doesn't matter, only the precision of matching does.) ::: ## Publish plugins @@ -94,7 +94,7 @@ Publish plugins used across all integrations. ### Extract Review Plugin responsible for automatic FFmpeg conversion to variety of formats. -Extract review is using [profile filtering](#profile-filters) to be able render different outputs for different situations. +Extract review uses [profile filtering](#profile-filters) to render different outputs for different situations. Applicable context filters: **`hosts`** - Host from which publishing was triggered. `["maya", "nuke"]` @@ -104,7 +104,7 @@ Applicable context filters: **Output Definitions** -Profile may generate multiple outputs from a single input. Each output must define unique name and output extension (use the extension without a dot e.g. **mp4**). All other settings of output definition are optional. +A profile may generate multiple outputs from a single input. Each output must define unique name and output extension (use the extension without a dot e.g. **mp4**). All other settings of output definition are optional. ![global_extract_review_output_defs](assets/global_extract_review_output_defs.png) - **`Tags`** @@ -118,7 +118,7 @@ Profile may generate multiple outputs from a single input. Each output must defi - **Output arguments** other FFmpeg output arguments like codec definition. - **`Output width`** and **`Output height`** - - it is possible to rescale output to specified resolution and keep aspect ratio. + - It is possible to rescale output to specified resolution and keep aspect ratio. - If value is set to 0, source resolution will be used. - **`Overscan crop`** @@ -230,10 +230,10 @@ Applicable context filters: ## Tools Settings for OpenPype tools. -## Creator +### Creator Settings related to [Creator tool](artist_tools_creator). -### Subset name profiles +#### Subset name profiles ![global_tools_creator_subset_template](assets/global_tools_creator_subset_template.png) Subset name helps to identify published content. More specific name helps with organization and avoid mixing of published content. Subset name is defined using one of templates defined in **Subset name profiles settings**. The template is filled with context information at the time of creation. @@ -263,10 +263,31 @@ Template may look like `"{family}{Task}{Variant}"`. Some creators may have other keys as their context may require more information or more specific values. Make sure you've read documentation of host you're using. -## Workfiles +### Publish + +#### Custom Staging Directory Profiles +With this feature, users can specify a custom data folder path based on presets, which can be used during the creation and publishing stages. + +![global_tools_custom_staging_dir](assets/global_tools_custom_staging_dir.png) + +Staging directories are used as a destination for intermediate files (as renders) before they are renamed and copied to proper location during the integration phase. They could be created completely dynamically in the temp folder or for some DCCs in the `work` area. +Example could be Nuke where artist might want to temporarily render pictures into `work` area to check them before they get published with the choice of "Use existing frames" on the write node. + +One of the key advantages of this feature is that it allows users to choose the folder for writing such intermediate files to take advantage of faster storage for rendering, which can help improve workflow efficiency. Additionally, this feature allows users to keep their intermediate extracted data persistent, and use their own infrastructure for regular cleaning. + +In some cases, these DCCs (Nuke, Houdini, Maya) automatically add a rendering path during the creation stage, which is then used in publishing. Creators and extractors of such DCCs need to use these profiles to fill paths in DCC's nodes to use this functionality. + +The custom staging folder uses a path template configured in `project_anatomy/templates/others` with `transient` being a default example path that could be used. The template requires a 'folder' key for it to be usable as custom staging folder. + +##### Known issues +- Any DCC that uses prefilled paths and store them inside of workfile nodes needs to implement resolving these paths with a configured profiles. +- If studio uses Site Sync remote artists need to have access to configured custom staging folder! +- Each node on the rendering farm must have access to configured custom staging folder! + +### Workfiles All settings related to Workfile tool. -### Open last workfile at launch +#### Open last workfile at launch This feature allows you to define a rule for each task/host or toggle the feature globally to all tasks as they are visible in the picture. ![global_tools_workfile_open_last_version](assets/global_tools_workfile_open_last_version.png) diff --git a/website/docs/project_settings/settings_project_nuke.md b/website/docs/project_settings/settings_project_nuke.md index b3ee5f77a63..c9c3d12df91 100644 --- a/website/docs/project_settings/settings_project_nuke.md +++ b/website/docs/project_settings/settings_project_nuke.md @@ -10,7 +10,7 @@ import TabItem from '@theme/TabItem'; Project settings can have project specific values. Each new project is using studio values defined in **default** project but these values can be modified or overridden per project. :::warning Default studio values -Projects always use default project values unless they have [project override](../admin_settings#project-overrides) (orage colour). Any changes in default project may affect all existing projects. +Projects always use default project values unless they have [project override](../admin_settings#project-overrides) (orange colour). Any changes in default project may affect all existing projects. ::: ## Workfile Builder diff --git a/website/docs/project_settings/settings_project_standalone.md b/website/docs/project_settings/settings_project_standalone.md index 778aba29426..1383bd488e2 100644 --- a/website/docs/project_settings/settings_project_standalone.md +++ b/website/docs/project_settings/settings_project_standalone.md @@ -10,7 +10,7 @@ import TabItem from '@theme/TabItem'; Project settings can have project specific values. Each new project is using studio values defined in **default** project but these values can be modified or overridden per project. :::warning Default studio values -Projects always use default project values unless they have [project override](../admin_settings#project-overrides) (orage colour). Any changes in default project may affect all existing projects. +Projects always use default project values unless they have [project override](../admin_settings#project-overrides) (orange colour). Any changes in default project may affect all existing projects. ::: ## Creator Plugins diff --git a/website/docs/pype2/admin_ftrack.md b/website/docs/pype2/admin_ftrack.md index a81147bece1..4ebe1a7adda 100644 --- a/website/docs/pype2/admin_ftrack.md +++ b/website/docs/pype2/admin_ftrack.md @@ -8,7 +8,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -Ftrack is currently the main project management option for Pype. This documentation assumes that you are familiar with Ftrack and it's basic principles. If you're new to Ftrack, we recommend having a thorough look at [Ftrack Official Documentation](http://ftrack.rtd.ftrack.com/en/stable/). +Ftrack is currently the main project management option for Pype. This documentation assumes that you are familiar with Ftrack and its basic principles. If you're new to Ftrack, we recommend having a thorough look at [Ftrack Official Documentation](http://ftrack.rtd.ftrack.com/en/stable/). ## Prepare Ftrack for Pype diff --git a/website/docs/pype2/admin_presets_plugins.md b/website/docs/pype2/admin_presets_plugins.md index fcdc09439b9..44c2a28dec7 100644 --- a/website/docs/pype2/admin_presets_plugins.md +++ b/website/docs/pype2/admin_presets_plugins.md @@ -36,7 +36,7 @@ All context filters are lists which may contain strings or Regular expressions ( - **families** - Main family of processed instance. `["plate", "model"]` :::important Filtering -Filters are optional and may not be set. In case when multiple profiles match current context, profile with filters has higher priority that profile without filters. +Filters are optional and may not be set. In case when multiple profiles match current context, profile with filters has higher priority than profile without filters. ::: #### Profile outputs @@ -293,6 +293,7 @@ If source representation has suffix **"h264"** and burnin suffix is **"client"** - It is allowed to use [Anatomy templates](admin_config#anatomy) themselves in burnins if they can be filled with available data. - Additional keys in burnins: + | Burnin key | Description | | --- | --- | | frame_start | First frame number. | @@ -303,6 +304,7 @@ If source representation has suffix **"h264"** and burnin suffix is **"client"** | resolution_height | Resolution height. | | fps | Fps of an output. | | timecode | Timecode by frame start and fps. | + | focalLength | **Only available in Maya**

    Camera focal length per frame. Use syntax `{focalLength:.2f}` for decimal truncating. Eg. `35.234985` with `{focalLength:.2f}` would produce `35.23`, whereas `{focalLength:.0f}` would produce `35`. | :::warning `timecode` is specific key that can be **only at the end of content**. (`"BOTTOM_RIGHT": "TC: {timecode}"`) diff --git a/website/docs/system_introduction.md b/website/docs/system_introduction.md index 05627b53594..d64b0237044 100644 --- a/website/docs/system_introduction.md +++ b/website/docs/system_introduction.md @@ -15,9 +15,9 @@ various usage scenarios. ## Studio Preparation -You can find detailed breakdown of technical requirements [here](dev_requirements), but in general OpenPype should be able +You can find a detailed breakdown of technical requirements [here](dev_requirements), but in general OpenPype should be able to operate in most studios fairly quickly. The main obstacles are usually related to workflows and habits, that -might not be fully compatible with what OpenPype is expecting or enforcing. It is recommended to go through artists [key concepts](artist_concepts) to get idea about basics. +might not be fully compatible with what OpenPype is expecting or enforcing. It is recommended to go through artists [key concepts](artist_concepts) to get comfortable with the basics. Keep in mind that if you run into any workflows that are not supported, it's usually just because we haven't hit that particular case and it can most likely be added upon request. diff --git a/website/yarn.lock b/website/yarn.lock index 559c58f9314..2edf57abf4e 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -3,56 +3,56 @@ "@algolia/autocomplete-core@1.5.2": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.5.2.tgz#ec0178e07b44fd74a057728ac157291b26cecf37" - integrity sha512-DY0bhyczFSS1b/CqJlTE/nQRtnTAHl6IemIkBy0nEWnhDzRDdtdx4p5Uuk3vwAFxwEEgi1WqKwgSSMx6DpNL4A== + "integrity" "sha512-DY0bhyczFSS1b/CqJlTE/nQRtnTAHl6IemIkBy0nEWnhDzRDdtdx4p5Uuk3vwAFxwEEgi1WqKwgSSMx6DpNL4A==" + "resolved" "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.5.2.tgz" + "version" "1.5.2" dependencies: "@algolia/autocomplete-shared" "1.5.2" "@algolia/autocomplete-preset-algolia@1.5.2": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.5.2.tgz#36c5638cc6dba6ea46a86e5a0314637ca40a77ca" - integrity sha512-3MRYnYQFJyovANzSX2CToS6/5cfVjbLLqFsZTKcvF3abhQzxbqwwaMBlJtt620uBUOeMzhdfasKhCc40+RHiZw== + "integrity" "sha512-3MRYnYQFJyovANzSX2CToS6/5cfVjbLLqFsZTKcvF3abhQzxbqwwaMBlJtt620uBUOeMzhdfasKhCc40+RHiZw==" + "resolved" "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.5.2.tgz" + "version" "1.5.2" dependencies: "@algolia/autocomplete-shared" "1.5.2" "@algolia/autocomplete-shared@1.5.2": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.5.2.tgz#e157f9ad624ab8fd940ff28bd2094cdf199cdd79" - integrity sha512-ylQAYv5H0YKMfHgVWX0j0NmL8XBcAeeeVQUmppnnMtzDbDnca6CzhKj3Q8eF9cHCgcdTDdb5K+3aKyGWA0obug== + "integrity" "sha512-ylQAYv5H0YKMfHgVWX0j0NmL8XBcAeeeVQUmppnnMtzDbDnca6CzhKj3Q8eF9cHCgcdTDdb5K+3aKyGWA0obug==" + "resolved" "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.5.2.tgz" + "version" "1.5.2" "@algolia/cache-browser-local-storage@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.12.1.tgz#23f4f219963b96918d0524acd09d4d646541d888" - integrity sha512-ERFFOnC9740xAkuO0iZTQqm2AzU7Dpz/s+g7o48GlZgx5p9GgNcsuK5eS0GoW/tAK+fnKlizCtlFHNuIWuvfsg== + "integrity" "sha512-ERFFOnC9740xAkuO0iZTQqm2AzU7Dpz/s+g7o48GlZgx5p9GgNcsuK5eS0GoW/tAK+fnKlizCtlFHNuIWuvfsg==" + "resolved" "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/cache-common" "4.12.1" "@algolia/cache-common@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.12.1.tgz#d3f1676ca9c404adce0f78d68f6381bedb44cd9c" - integrity sha512-UugTER3V40jT+e19Dmph5PKMeliYKxycNPwrPNADin0RcWNfT2QksK9Ff2N2W7UKraqMOzoeDb4LAJtxcK1a8Q== + "integrity" "sha512-UugTER3V40jT+e19Dmph5PKMeliYKxycNPwrPNADin0RcWNfT2QksK9Ff2N2W7UKraqMOzoeDb4LAJtxcK1a8Q==" + "resolved" "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.12.1.tgz" + "version" "4.12.1" "@algolia/cache-in-memory@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.12.1.tgz#0ef6aac2f8feab5b46fc130beb682bbd21b55244" - integrity sha512-U6iaunaxK1lHsAf02UWF58foKFEcrVLsHwN56UkCtwn32nlP9rz52WOcHsgk6TJrL8NDcO5swMjtOQ5XHESFLw== + "integrity" "sha512-U6iaunaxK1lHsAf02UWF58foKFEcrVLsHwN56UkCtwn32nlP9rz52WOcHsgk6TJrL8NDcO5swMjtOQ5XHESFLw==" + "resolved" "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/cache-common" "4.12.1" "@algolia/client-account@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.12.1.tgz#e838c9283db2fab32a425dd13c77da321d48fd8b" - integrity sha512-jGo4ConJNoMdTCR2zouO0jO/JcJmzOK6crFxMMLvdnB1JhmMbuIKluOTJVlBWeivnmcsqb7r0v7qTCPW5PAyxQ== + "integrity" "sha512-jGo4ConJNoMdTCR2zouO0jO/JcJmzOK6crFxMMLvdnB1JhmMbuIKluOTJVlBWeivnmcsqb7r0v7qTCPW5PAyxQ==" + "resolved" "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/client-common" "4.12.1" "@algolia/client-search" "4.12.1" "@algolia/transporter" "4.12.1" "@algolia/client-analytics@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.12.1.tgz#2976d658655a1590cf84cfb596aa75a204f6dec4" - integrity sha512-h1It7KXzIthlhuhfBk7LteYq72tym9maQDUsyRW0Gft8b6ZQahnRak9gcCvKwhcJ1vJoP7T7JrNYGiYSicTD9g== + "integrity" "sha512-h1It7KXzIthlhuhfBk7LteYq72tym9maQDUsyRW0Gft8b6ZQahnRak9gcCvKwhcJ1vJoP7T7JrNYGiYSicTD9g==" + "resolved" "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/client-common" "4.12.1" "@algolia/client-search" "4.12.1" @@ -60,99 +60,121 @@ "@algolia/transporter" "4.12.1" "@algolia/client-common@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.12.1.tgz#104ccefe96bda3ff926bc70c31ff6d17c41b6107" - integrity sha512-obnJ8eSbv+h94Grk83DTGQ3bqhViSWureV6oK1s21/KMGWbb3DkduHm+lcwFrMFkjSUSzosLBHV9EQUIBvueTw== + "integrity" "sha512-obnJ8eSbv+h94Grk83DTGQ3bqhViSWureV6oK1s21/KMGWbb3DkduHm+lcwFrMFkjSUSzosLBHV9EQUIBvueTw==" + "resolved" "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/requester-common" "4.12.1" "@algolia/transporter" "4.12.1" "@algolia/client-personalization@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.12.1.tgz#f63d1890f95de850e1c8e41c1d57adda521d9e7f" - integrity sha512-sMSnjjPjRgByGHYygV+5L/E8a6RgU7l2GbpJukSzJ9GRY37tHmBHuvahv8JjdCGJ2p7QDYLnQy5bN5Z02qjc7Q== + "integrity" "sha512-sMSnjjPjRgByGHYygV+5L/E8a6RgU7l2GbpJukSzJ9GRY37tHmBHuvahv8JjdCGJ2p7QDYLnQy5bN5Z02qjc7Q==" + "resolved" "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/client-common" "4.12.1" "@algolia/requester-common" "4.12.1" "@algolia/transporter" "4.12.1" -"@algolia/client-search@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.12.1.tgz#fcd7a974be5d39d5c336d7f2e89577ffa66aefdd" - integrity sha512-MwwKKprfY6X2nJ5Ki/ccXM2GDEePvVjZnnoOB2io3dLKW4fTqeSRlC5DRXeFD7UM0vOPPHr4ItV2aj19APKNVQ== +"@algolia/client-search@^4.9.1", "@algolia/client-search@4.12.1": + "integrity" "sha512-MwwKKprfY6X2nJ5Ki/ccXM2GDEePvVjZnnoOB2io3dLKW4fTqeSRlC5DRXeFD7UM0vOPPHr4ItV2aj19APKNVQ==" + "resolved" "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/client-common" "4.12.1" "@algolia/requester-common" "4.12.1" "@algolia/transporter" "4.12.1" "@algolia/events@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950" - integrity sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ== + "integrity" "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==" + "resolved" "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz" + "version" "4.0.1" "@algolia/logger-common@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.12.1.tgz#d6501b4d9d242956257ba8e10f6b4bbf6863baa4" - integrity sha512-fCgrzlXGATNqdFTxwx0GsyPXK+Uqrx1SZ3iuY2VGPPqdt1a20clAG2n2OcLHJpvaa6vMFPlJyWvbqAgzxdxBlQ== + "integrity" "sha512-fCgrzlXGATNqdFTxwx0GsyPXK+Uqrx1SZ3iuY2VGPPqdt1a20clAG2n2OcLHJpvaa6vMFPlJyWvbqAgzxdxBlQ==" + "resolved" "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.12.1.tgz" + "version" "4.12.1" "@algolia/logger-console@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.12.1.tgz#841edd39dd5c5530a69fc66084bfee3254dd0807" - integrity sha512-0owaEnq/davngQMYqxLA4KrhWHiXujQ1CU3FFnyUcMyBR7rGHI48zSOUpqnsAXrMBdSH6rH5BDkSUUFwsh8RkQ== + "integrity" "sha512-0owaEnq/davngQMYqxLA4KrhWHiXujQ1CU3FFnyUcMyBR7rGHI48zSOUpqnsAXrMBdSH6rH5BDkSUUFwsh8RkQ==" + "resolved" "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/logger-common" "4.12.1" "@algolia/requester-browser-xhr@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.12.1.tgz#2d0c18ee188d7cae0e4a930e5e89989e3c4a816b" - integrity sha512-OaMxDyG0TZG0oqz1lQh9e3woantAG1bLnuwq3fmypsrQxra4IQZiyn1x+kEb69D2TcXApI5gOgrD4oWhtEVMtw== + "integrity" "sha512-OaMxDyG0TZG0oqz1lQh9e3woantAG1bLnuwq3fmypsrQxra4IQZiyn1x+kEb69D2TcXApI5gOgrD4oWhtEVMtw==" + "resolved" "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/requester-common" "4.12.1" "@algolia/requester-common@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.12.1.tgz#95bb6539da7199da3e205341cea8f27267f7af29" - integrity sha512-XWIrWQNJ1vIrSuL/bUk3ZwNMNxl+aWz6dNboRW6+lGTcMIwc3NBFE90ogbZKhNrFRff8zI4qCF15tjW+Fyhpow== + "integrity" "sha512-XWIrWQNJ1vIrSuL/bUk3ZwNMNxl+aWz6dNboRW6+lGTcMIwc3NBFE90ogbZKhNrFRff8zI4qCF15tjW+Fyhpow==" + "resolved" "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.12.1.tgz" + "version" "4.12.1" "@algolia/requester-node-http@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.12.1.tgz#c9df97ff1daa7e58c5c2b1f28cf7163005edccb0" - integrity sha512-awBtwaD+s0hxkA1aehYn8F0t9wqGoBVWgY4JPHBmp1ChO3pK7RKnnvnv7QQa9vTlllX29oPt/BBVgMo1Z3n1Qg== + "integrity" "sha512-awBtwaD+s0hxkA1aehYn8F0t9wqGoBVWgY4JPHBmp1ChO3pK7RKnnvnv7QQa9vTlllX29oPt/BBVgMo1Z3n1Qg==" + "resolved" "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/requester-common" "4.12.1" "@algolia/transporter@4.12.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.12.1.tgz#61b9829916c474f42e2d4a6eada0d6c138379945" - integrity sha512-BGeNgdEHc6dXIk2g8kdlOoQ6fQ6OIaKQcplEj7HPoi+XZUeAvRi3Pff3QWd7YmybWkjzd9AnTzieTASDWhL+sQ== + "integrity" "sha512-BGeNgdEHc6dXIk2g8kdlOoQ6fQ6OIaKQcplEj7HPoi+XZUeAvRi3Pff3QWd7YmybWkjzd9AnTzieTASDWhL+sQ==" + "resolved" "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/cache-common" "4.12.1" "@algolia/logger-common" "4.12.1" "@algolia/requester-common" "4.12.1" -"@ampproject/remapping@^2.1.0": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" - integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== +"@ampproject/remapping@^2.2.0": + "integrity" "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==" + "resolved" "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz" + "version" "2.2.0" dependencies: - "@jridgewell/trace-mapping" "^0.3.0" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.8.3": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== - dependencies: - "@babel/highlight" "^7.16.7" - -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4", "@babel/compat-data@^7.16.8", "@babel/compat-data@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.0.tgz#86850b8597ea6962089770952075dcaabb8dba34" - integrity sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng== + "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/trace-mapping" "^0.3.9" -"@babel/core@7.12.9": - version "7.12.9" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.9.tgz#fd450c4ec10cdbb980e2928b7aa7a28484593fc8" - integrity sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.8.3": + "integrity" "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==" + "resolved" "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/highlight" "^7.18.6" + +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.8", "@babel/compat-data@^7.17.0", "@babel/compat-data@^7.20.5": + "integrity" "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==" + "resolved" "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz" + "version" "7.21.0" + +"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.12.0", "@babel/core@^7.13.0", "@babel/core@^7.15.5", "@babel/core@^7.16.0", "@babel/core@^7.4.0-0": + "integrity" "sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==" + "resolved" "https://registry.npmjs.org/@babel/core/-/core-7.21.3.tgz" + "version" "7.21.3" + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.21.3" + "@babel/helper-compilation-targets" "^7.20.7" + "@babel/helper-module-transforms" "^7.21.2" + "@babel/helpers" "^7.21.0" + "@babel/parser" "^7.21.3" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.21.3" + "@babel/types" "^7.21.3" + "convert-source-map" "^1.7.0" + "debug" "^4.1.0" + "gensync" "^1.0.0-beta.2" + "json5" "^2.2.2" + "semver" "^6.3.0" + +"@babel/core@^7.11.6", "@babel/core@7.12.9": + "integrity" "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==" + "resolved" "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz" + "version" "7.12.9" dependencies: "@babel/code-frame" "^7.10.4" "@babel/generator" "^7.12.5" @@ -162,74 +184,55 @@ "@babel/template" "^7.12.7" "@babel/traverse" "^7.12.9" "@babel/types" "^7.12.7" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.1" - json5 "^2.1.2" - lodash "^4.17.19" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - -"@babel/core@^7.15.5", "@babel/core@^7.16.0": - version "7.17.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.5.tgz#6cd2e836058c28f06a4ca8ee7ed955bbf37c8225" - integrity sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA== - dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.3" - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helpers" "^7.17.2" - "@babel/parser" "^7.17.3" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.3" - "@babel/types" "^7.17.0" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.1.2" - semver "^6.3.0" - -"@babel/generator@^7.12.5", "@babel/generator@^7.16.0", "@babel/generator@^7.17.3": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.3.tgz#a2c30b0c4f89858cb87050c3ffdfd36bdf443200" - integrity sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg== - dependencies: - "@babel/types" "^7.17.0" - jsesc "^2.5.1" - source-map "^0.5.0" + "convert-source-map" "^1.7.0" + "debug" "^4.1.0" + "gensync" "^1.0.0-beta.1" + "json5" "^2.1.2" + "lodash" "^4.17.19" + "resolve" "^1.3.2" + "semver" "^5.4.1" + "source-map" "^0.5.0" + +"@babel/generator@^7.12.5", "@babel/generator@^7.16.0", "@babel/generator@^7.21.3": + "integrity" "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==" + "resolved" "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz" + "version" "7.21.3" + dependencies: + "@babel/types" "^7.21.3" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + "jsesc" "^2.5.1" "@babel/helper-annotate-as-pure@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862" - integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw== + "integrity" "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==" + "resolved" "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/types" "^7.16.7" "@babel/helper-builder-binary-assignment-operator-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz#38d138561ea207f0f69eb1626a418e4f7e6a580b" - integrity sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA== + "integrity" "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==" + "resolved" "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-explode-assignable-expression" "^7.16.7" "@babel/types" "^7.16.7" -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b" - integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA== +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7", "@babel/helper-compilation-targets@^7.20.7": + "integrity" "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz" + "version" "7.20.7" dependencies: - "@babel/compat-data" "^7.16.4" - "@babel/helper-validator-option" "^7.16.7" - browserslist "^4.17.5" - semver "^6.3.0" + "@babel/compat-data" "^7.20.5" + "@babel/helper-validator-option" "^7.18.6" + "browserslist" "^4.21.3" + "lru-cache" "^5.1.1" + "semver" "^6.3.0" "@babel/helper-create-class-features-plugin@^7.16.10", "@babel/helper-create-class-features-plugin@^7.16.7": - version "7.17.1" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.1.tgz#9699f14a88833a7e055ce57dcd3ffdcd25186b21" - integrity sha512-JBdSr/LtyYIno/pNnJ75lBcqc3Z1XXujzPanHqjvvrhOA+DTceTFuJi8XjmWTZh4r3fsdfqaCMN0iZemdkxZHQ== + "integrity" "sha512-JBdSr/LtyYIno/pNnJ75lBcqc3Z1XXujzPanHqjvvrhOA+DTceTFuJi8XjmWTZh4r3fsdfqaCMN0iZemdkxZHQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.1.tgz" + "version" "7.17.1" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-environment-visitor" "^7.16.7" @@ -240,122 +243,112 @@ "@babel/helper-split-export-declaration" "^7.16.7" "@babel/helper-create-regexp-features-plugin@^7.16.7": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz#1dcc7d40ba0c6b6b25618997c5dbfd310f186fe1" - integrity sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA== + "integrity" "sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==" + "resolved" "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz" + "version" "7.17.0" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" - regexpu-core "^5.0.1" + "regexpu-core" "^5.0.1" "@babel/helper-define-polyfill-provider@^0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz#52411b445bdb2e676869e5a74960d2d3826d2665" - integrity sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA== + "integrity" "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==" + "resolved" "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz" + "version" "0.3.1" dependencies: "@babel/helper-compilation-targets" "^7.13.0" "@babel/helper-module-imports" "^7.12.13" "@babel/helper-plugin-utils" "^7.13.0" "@babel/traverse" "^7.13.0" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" - semver "^6.1.2" + "debug" "^4.1.1" + "lodash.debounce" "^4.0.8" + "resolve" "^1.14.2" + "semver" "^6.1.2" -"@babel/helper-environment-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" - integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== - dependencies: - "@babel/types" "^7.16.7" +"@babel/helper-environment-visitor@^7.16.7", "@babel/helper-environment-visitor@^7.18.9": + "integrity" "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==" + "resolved" "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz" + "version" "7.18.9" "@babel/helper-explode-assignable-expression@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz#12a6d8522fdd834f194e868af6354e8650242b7a" - integrity sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ== + "integrity" "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/types" "^7.16.7" -"@babel/helper-function-name@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" - integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== +"@babel/helper-function-name@^7.16.7", "@babel/helper-function-name@^7.21.0": + "integrity" "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==" + "resolved" "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz" + "version" "7.21.0" dependencies: - "@babel/helper-get-function-arity" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/types" "^7.16.7" + "@babel/template" "^7.20.7" + "@babel/types" "^7.21.0" -"@babel/helper-get-function-arity@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419" - integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== +"@babel/helper-hoist-variables@^7.16.7", "@babel/helper-hoist-variables@^7.18.6": + "integrity" "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==" + "resolved" "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz" + "version" "7.18.6" dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-hoist-variables@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" - integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== - dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.18.6" "@babel/helper-member-expression-to-functions@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz#42b9ca4b2b200123c3b7e726b0ae5153924905b0" - integrity sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q== + "integrity" "sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==" + "resolved" "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/types" "^7.16.7" -"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" - integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== +"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.18.6": + "integrity" "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==" + "resolved" "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz" + "version" "7.18.6" dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.18.6" -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz#7665faeb721a01ca5327ddc6bba15a5cb34b6a41" - integrity sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng== +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.16.7", "@babel/helper-module-transforms@^7.21.2": + "integrity" "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz" + "version" "7.21.2" dependencies: - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-simple-access" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/helper-validator-identifier" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.16.7" - "@babel/types" "^7.16.7" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.20.2" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.19.1" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.21.2" + "@babel/types" "^7.21.2" "@babel/helper-optimise-call-expression@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz#a34e3560605abbd31a18546bd2aad3e6d9a174f2" - integrity sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w== + "integrity" "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==" + "resolved" "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/types" "^7.16.7" -"@babel/helper-plugin-utils@7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" - integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== - "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" - integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== + "integrity" "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==" + "resolved" "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz" + "version" "7.16.7" + +"@babel/helper-plugin-utils@7.10.4": + "integrity" "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" + "resolved" "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz" + "version" "7.10.4" "@babel/helper-remap-async-to-generator@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz#29ffaade68a367e2ed09c90901986918d25e57e3" - integrity sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw== + "integrity" "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==" + "resolved" "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-wrap-function" "^7.16.8" "@babel/types" "^7.16.8" "@babel/helper-replace-supers@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz#e9f5f5f32ac90429c1a4bdec0f231ef0c2838ab1" - integrity sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw== + "integrity" "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==" + "resolved" "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-environment-visitor" "^7.16.7" "@babel/helper-member-expression-to-functions" "^7.16.7" @@ -363,173 +356,169 @@ "@babel/traverse" "^7.16.7" "@babel/types" "^7.16.7" -"@babel/helper-simple-access@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7" - integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g== +"@babel/helper-simple-access@^7.16.7", "@babel/helper-simple-access@^7.20.2": + "integrity" "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==" + "resolved" "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz" + "version" "7.20.2" dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.20.2" "@babel/helper-skip-transparent-expression-wrappers@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz#0ee3388070147c3ae051e487eca3ebb0e2e8bb09" - integrity sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw== + "integrity" "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==" + "resolved" "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz" + "version" "7.16.0" dependencies: "@babel/types" "^7.16.0" -"@babel/helper-split-export-declaration@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" - integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== +"@babel/helper-split-export-declaration@^7.16.7", "@babel/helper-split-export-declaration@^7.18.6": + "integrity" "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==" + "resolved" "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz" + "version" "7.18.6" dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.18.6" -"@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== +"@babel/helper-string-parser@^7.19.4": + "integrity" "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==" + "resolved" "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz" + "version" "7.19.4" -"@babel/helper-validator-option@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" - integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== +"@babel/helper-validator-identifier@^7.16.7", "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": + "integrity" "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==" + "resolved" "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz" + "version" "7.19.1" + +"@babel/helper-validator-option@^7.16.7", "@babel/helper-validator-option@^7.18.6": + "integrity" "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz" + "version" "7.21.0" "@babel/helper-wrap-function@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz#58afda087c4cd235de92f7ceedebca2c41274200" - integrity sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw== + "integrity" "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==" + "resolved" "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-function-name" "^7.16.7" "@babel/template" "^7.16.7" "@babel/traverse" "^7.16.8" "@babel/types" "^7.16.8" -"@babel/helpers@^7.12.5", "@babel/helpers@^7.17.2": - version "7.17.2" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.2.tgz#23f0a0746c8e287773ccd27c14be428891f63417" - integrity sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ== +"@babel/helpers@^7.12.5", "@babel/helpers@^7.21.0": + "integrity" "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==" + "resolved" "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz" + "version" "7.21.0" dependencies: - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.0" - "@babel/types" "^7.17.0" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.21.0" + "@babel/types" "^7.21.0" -"@babel/highlight@^7.16.7": - version "7.16.10" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" - integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== +"@babel/highlight@^7.18.6": + "integrity" "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==" + "resolved" "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz" + "version" "7.18.6" dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - chalk "^2.0.0" - js-tokens "^4.0.0" + "@babel/helper-validator-identifier" "^7.18.6" + "chalk" "^2.0.0" + "js-tokens" "^4.0.0" -"@babel/parser@^7.12.7", "@babel/parser@^7.16.4", "@babel/parser@^7.16.7", "@babel/parser@^7.17.3": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.3.tgz#b07702b982990bf6fdc1da5049a23fece4c5c3d0" - integrity sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA== +"@babel/parser@^7.12.7", "@babel/parser@^7.16.4", "@babel/parser@^7.20.7", "@babel/parser@^7.21.3": + "integrity" "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==" + "resolved" "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz" + "version" "7.21.3" "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz#4eda6d6c2a0aa79c70fa7b6da67763dfe2141050" - integrity sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg== + "integrity" "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz#cc001234dfc139ac45f6bcf801866198c8c72ff9" - integrity sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw== + "integrity" "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-proposal-optional-chaining" "^7.16.7" "@babel/plugin-proposal-async-generator-functions@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz#3bdd1ebbe620804ea9416706cd67d60787504bc8" - integrity sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ== + "integrity" "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-remap-async-to-generator" "^7.16.8" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-proposal-class-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz#925cad7b3b1a2fcea7e59ecc8eb5954f961f91b0" - integrity sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww== + "integrity" "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-create-class-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-proposal-class-static-block@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz#712357570b612106ef5426d13dc433ce0f200c2a" - integrity sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw== + "integrity" "sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-create-class-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-proposal-dynamic-import@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz#c19c897eaa46b27634a00fee9fb7d829158704b2" - integrity sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg== + "integrity" "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-proposal-export-namespace-from@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz#09de09df18445a5786a305681423ae63507a6163" - integrity sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA== + "integrity" "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" "@babel/plugin-proposal-json-strings@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz#9732cb1d17d9a2626a08c5be25186c195b6fa6e8" - integrity sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ== + "integrity" "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-proposal-logical-assignment-operators@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz#be23c0ba74deec1922e639832904be0bea73cdea" - integrity sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg== + "integrity" "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-proposal-nullish-coalescing-operator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz#141fc20b6857e59459d430c850a0011e36561d99" - integrity sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ== + "integrity" "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" "@babel/plugin-proposal-numeric-separator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz#d6b69f4af63fb38b6ca2558442a7fb191236eba9" - integrity sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw== + "integrity" "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz#def9bd03cea0f9b72283dac0ec22d289c7691069" - integrity sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.12.1" - "@babel/plugin-proposal-object-rest-spread@^7.16.7": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz#d9eb649a54628a51701aef7e0ea3d17e2b9dd390" - integrity sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw== + "integrity" "sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz" + "version" "7.17.3" dependencies: "@babel/compat-data" "^7.17.0" "@babel/helper-compilation-targets" "^7.16.7" @@ -537,35 +526,44 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-transform-parameters" "^7.16.7" +"@babel/plugin-proposal-object-rest-spread@7.12.1": + "integrity" "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz" + "version" "7.12.1" + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-transform-parameters" "^7.12.1" + "@babel/plugin-proposal-optional-catch-binding@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz#c623a430674ffc4ab732fd0a0ae7722b67cb74cf" - integrity sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA== + "integrity" "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-proposal-optional-chaining@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz#7cd629564724816c0e8a969535551f943c64c39a" - integrity sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA== + "integrity" "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-proposal-private-methods@^7.16.11": - version "7.16.11" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz#e8df108288555ff259f4527dbe84813aac3a1c50" - integrity sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw== + "integrity" "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz" + "version" "7.16.11" dependencies: "@babel/helper-create-class-features-plugin" "^7.16.10" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-proposal-private-property-in-object@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz#b0b8cef543c2c3d57e59e2c611994861d46a3fce" - integrity sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ== + "integrity" "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-create-class-features-plugin" "^7.16.7" @@ -573,166 +571,166 @@ "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-proposal-unicode-property-regex@^7.16.7", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz#635d18eb10c6214210ffc5ff4932552de08188a2" - integrity sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg== + "integrity" "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + "integrity" "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" + "version" "7.8.4" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-class-properties@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + "integrity" "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" + "version" "7.12.13" dependencies: "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-class-static-block@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" - integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + "integrity" "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz" + "version" "7.14.5" dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-dynamic-import@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" - integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + "integrity" "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-export-namespace-from@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" - integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + "integrity" "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + "integrity" "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz#9d9d357cc818aa7ae7935917c1257f67677a0926" - integrity sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-jsx@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz#50b6571d13f764266a113d77c82b4a6508bbe665" - integrity sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q== + "integrity" "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" +"@babel/plugin-syntax-jsx@7.12.1": + "integrity" "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz" + "version" "7.12.1" + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + "integrity" "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" + "version" "7.10.4" dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + "integrity" "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-numeric-separator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + "integrity" "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" + "version" "7.10.4" dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-object-rest-spread@7.8.3", "@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== +"@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3", "@babel/plugin-syntax-object-rest-spread@7.8.3": + "integrity" "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + "integrity" "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + "integrity" "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-private-property-in-object@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" - integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + "integrity" "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz" + "version" "7.14.5" dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-top-level-await@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + "integrity" "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz" + "version" "7.14.5" dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz#39c9b55ee153151990fb038651d58d3fd03f98f8" - integrity sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A== + "integrity" "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-arrow-functions@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz#44125e653d94b98db76369de9c396dc14bef4154" - integrity sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ== + "integrity" "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-async-to-generator@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz#b83dff4b970cf41f1b819f8b49cc0cfbaa53a808" - integrity sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg== + "integrity" "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-module-imports" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-remap-async-to-generator" "^7.16.8" "@babel/plugin-transform-block-scoped-functions@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz#4d0d57d9632ef6062cdf354bb717102ee042a620" - integrity sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg== + "integrity" "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-block-scoping@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz#f50664ab99ddeaee5bc681b8f3a6ea9d72ab4f87" - integrity sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ== + "integrity" "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-classes@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz#8f4b9562850cd973de3b498f1218796eb181ce00" - integrity sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ== + "integrity" "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-environment-visitor" "^7.16.7" @@ -741,174 +739,174 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-replace-supers" "^7.16.7" "@babel/helper-split-export-declaration" "^7.16.7" - globals "^11.1.0" + "globals" "^11.1.0" "@babel/plugin-transform-computed-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz#66dee12e46f61d2aae7a73710f591eb3df616470" - integrity sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw== + "integrity" "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-destructuring@^7.16.7": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz#c445f75819641788a27a0a3a759d9df911df6abc" - integrity sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg== + "integrity" "sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz" + "version" "7.17.3" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-dotall-regex@^7.16.7", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz#6b2d67686fab15fb6a7fd4bd895d5982cfc81241" - integrity sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ== + "integrity" "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-duplicate-keys@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz#2207e9ca8f82a0d36a5a67b6536e7ef8b08823c9" - integrity sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw== + "integrity" "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-exponentiation-operator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz#efa9862ef97e9e9e5f653f6ddc7b665e8536fe9b" - integrity sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA== + "integrity" "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-for-of@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz#649d639d4617dff502a9a158c479b3b556728d8c" - integrity sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg== + "integrity" "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-function-name@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz#5ab34375c64d61d083d7d2f05c38d90b97ec65cf" - integrity sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA== + "integrity" "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-compilation-targets" "^7.16.7" "@babel/helper-function-name" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz#254c9618c5ff749e87cb0c0cef1a0a050c0bdab1" - integrity sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ== + "integrity" "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-member-expression-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz#6e5dcf906ef8a098e630149d14c867dd28f92384" - integrity sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw== + "integrity" "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-modules-amd@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz#b28d323016a7daaae8609781d1f8c9da42b13186" - integrity sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g== + "integrity" "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-module-transforms" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" - babel-plugin-dynamic-import-node "^2.3.3" + "babel-plugin-dynamic-import-node" "^2.3.3" "@babel/plugin-transform-modules-commonjs@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz#cdee19aae887b16b9d331009aa9a219af7c86afe" - integrity sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA== + "integrity" "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-module-transforms" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-simple-access" "^7.16.7" - babel-plugin-dynamic-import-node "^2.3.3" + "babel-plugin-dynamic-import-node" "^2.3.3" "@babel/plugin-transform-modules-systemjs@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz#887cefaef88e684d29558c2b13ee0563e287c2d7" - integrity sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw== + "integrity" "sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-hoist-variables" "^7.16.7" "@babel/helper-module-transforms" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-validator-identifier" "^7.16.7" - babel-plugin-dynamic-import-node "^2.3.3" + "babel-plugin-dynamic-import-node" "^2.3.3" "@babel/plugin-transform-modules-umd@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz#23dad479fa585283dbd22215bff12719171e7618" - integrity sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ== + "integrity" "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-module-transforms" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-named-capturing-groups-regex@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz#7f860e0e40d844a02c9dcf9d84965e7dfd666252" - integrity sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw== + "integrity" "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/plugin-transform-new-target@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz#9967d89a5c243818e0800fdad89db22c5f514244" - integrity sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg== + "integrity" "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-object-super@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz#ac359cf8d32cf4354d27a46867999490b6c32a94" - integrity sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw== + "integrity" "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-replace-supers" "^7.16.7" "@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz#a1721f55b99b736511cb7e0152f61f17688f331f" - integrity sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw== + "integrity" "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-property-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz#2dadac85155436f22c696c4827730e0fe1057a55" - integrity sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw== + "integrity" "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-react-constant-elements@^7.14.5": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.16.7.tgz#19e9e4c2df2f6c3e6b3aea11778297d81db8df62" - integrity sha512-lF+cfsyTgwWkcw715J88JhMYJ5GpysYNLhLP1PkvkhTRN7B3e74R/1KsDxFxhRpSn0UUD3IWM4GvdBR2PEbbQQ== + "integrity" "sha512-lF+cfsyTgwWkcw715J88JhMYJ5GpysYNLhLP1PkvkhTRN7B3e74R/1KsDxFxhRpSn0UUD3IWM4GvdBR2PEbbQQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-react-display-name@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz#7b6d40d232f4c0f550ea348593db3b21e2404340" - integrity sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg== + "integrity" "sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-react-jsx-development@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz#43a00724a3ed2557ed3f276a01a929e6686ac7b8" - integrity sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A== + "integrity" "sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/plugin-transform-react-jsx" "^7.16.7" "@babel/plugin-transform-react-jsx@^7.16.7": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz#eac1565da176ccb1a715dae0b4609858808008c1" - integrity sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ== + "integrity" "sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz" + "version" "7.17.3" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-module-imports" "^7.16.7" @@ -917,103 +915,103 @@ "@babel/types" "^7.17.0" "@babel/plugin-transform-react-pure-annotations@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz#232bfd2f12eb551d6d7d01d13fe3f86b45eb9c67" - integrity sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA== + "integrity" "sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-regenerator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz#9e7576dc476cb89ccc5096fff7af659243b4adeb" - integrity sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q== + "integrity" "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz" + "version" "7.16.7" dependencies: - regenerator-transform "^0.14.2" + "regenerator-transform" "^0.14.2" "@babel/plugin-transform-reserved-words@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz#1d798e078f7c5958eec952059c460b220a63f586" - integrity sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg== + "integrity" "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-runtime@^7.16.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz#0a2e08b5e2b2d95c4b1d3b3371a2180617455b70" - integrity sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A== + "integrity" "sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz" + "version" "7.17.0" dependencies: "@babel/helper-module-imports" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" - babel-plugin-polyfill-corejs2 "^0.3.0" - babel-plugin-polyfill-corejs3 "^0.5.0" - babel-plugin-polyfill-regenerator "^0.3.0" - semver "^6.3.0" + "babel-plugin-polyfill-corejs2" "^0.3.0" + "babel-plugin-polyfill-corejs3" "^0.5.0" + "babel-plugin-polyfill-regenerator" "^0.3.0" + "semver" "^6.3.0" "@babel/plugin-transform-shorthand-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz#e8549ae4afcf8382f711794c0c7b6b934c5fbd2a" - integrity sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg== + "integrity" "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-spread@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz#a303e2122f9f12e0105daeedd0f30fb197d8ff44" - integrity sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg== + "integrity" "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-transform-sticky-regex@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz#c84741d4f4a38072b9a1e2e3fd56d359552e8660" - integrity sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw== + "integrity" "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-template-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz#f3d1c45d28967c8e80f53666fc9c3e50618217ab" - integrity sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA== + "integrity" "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-typeof-symbol@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz#9cdbe622582c21368bd482b660ba87d5545d4f7e" - integrity sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ== + "integrity" "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-typescript@^7.16.7": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz#591ce9b6b83504903fa9dd3652c357c2ba7a1ee0" - integrity sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ== + "integrity" "sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz" + "version" "7.16.8" dependencies: "@babel/helper-create-class-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-typescript" "^7.16.7" "@babel/plugin-transform-unicode-escapes@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz#da8717de7b3287a2c6d659750c964f302b31ece3" - integrity sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q== + "integrity" "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-unicode-regex@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz#0f7aa4a501198976e25e82702574c34cfebe9ef2" - integrity sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q== + "integrity" "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/preset-env@^7.15.6", "@babel/preset-env@^7.16.4": - version "7.16.11" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.11.tgz#5dd88fd885fae36f88fd7c8342475c9f0abe2982" - integrity sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g== + "integrity" "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==" + "resolved" "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz" + "version" "7.16.11" dependencies: "@babel/compat-data" "^7.16.8" "@babel/helper-compilation-targets" "^7.16.7" @@ -1084,27 +1082,27 @@ "@babel/plugin-transform-unicode-regex" "^7.16.7" "@babel/preset-modules" "^0.1.5" "@babel/types" "^7.16.8" - babel-plugin-polyfill-corejs2 "^0.3.0" - babel-plugin-polyfill-corejs3 "^0.5.0" - babel-plugin-polyfill-regenerator "^0.3.0" - core-js-compat "^3.20.2" - semver "^6.3.0" + "babel-plugin-polyfill-corejs2" "^0.3.0" + "babel-plugin-polyfill-corejs3" "^0.5.0" + "babel-plugin-polyfill-regenerator" "^0.3.0" + "core-js-compat" "^3.20.2" + "semver" "^6.3.0" "@babel/preset-modules@^0.1.5": - version "0.1.5" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" - integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== + "integrity" "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==" + "resolved" "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz" + "version" "0.1.5" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" "@babel/plugin-transform-dotall-regex" "^7.4.4" "@babel/types" "^7.4.4" - esutils "^2.0.2" + "esutils" "^2.0.2" "@babel/preset-react@^7.14.5", "@babel/preset-react@^7.16.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.16.7.tgz#4c18150491edc69c183ff818f9f2aecbe5d93852" - integrity sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA== + "integrity" "sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA==" + "resolved" "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-validator-option" "^7.16.7" @@ -1114,81 +1112,82 @@ "@babel/plugin-transform-react-pure-annotations" "^7.16.7" "@babel/preset-typescript@^7.15.0", "@babel/preset-typescript@^7.16.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz#ab114d68bb2020afc069cd51b37ff98a046a70b9" - integrity sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ== + "integrity" "sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==" + "resolved" "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-validator-option" "^7.16.7" "@babel/plugin-transform-typescript" "^7.16.7" "@babel/runtime-corejs3@^7.16.3": - version "7.17.2" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.17.2.tgz#fdca2cd05fba63388babe85d349b6801b008fd13" - integrity sha512-NcKtr2epxfIrNM4VOmPKO46TvDMCBhgi2CrSHaEarrz+Plk2K5r9QemmOFTGpZaoKnWoGH5MO+CzeRsih/Fcgg== + "integrity" "sha512-NcKtr2epxfIrNM4VOmPKO46TvDMCBhgi2CrSHaEarrz+Plk2K5r9QemmOFTGpZaoKnWoGH5MO+CzeRsih/Fcgg==" + "resolved" "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.17.2.tgz" + "version" "7.17.2" dependencies: - core-js-pure "^3.20.2" - regenerator-runtime "^0.13.4" + "core-js-pure" "^3.20.2" + "regenerator-runtime" "^0.13.4" "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.16.3", "@babel/runtime@^7.8.4": - version "7.17.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941" - integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/template@^7.12.7", "@babel/template@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" - integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.16.3", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.17.0", "@babel/traverse@^7.17.3": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57" - integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.3" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.17.3" - "@babel/types" "^7.17.0" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/types@^7.12.7", "@babel/types@^7.15.6", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.4.4": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" - integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - to-fast-properties "^2.0.0" + "integrity" "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==" + "resolved" "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz" + "version" "7.17.2" + dependencies: + "regenerator-runtime" "^0.13.4" + +"@babel/template@^7.12.7", "@babel/template@^7.16.7", "@babel/template@^7.20.7": + "integrity" "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==" + "resolved" "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz" + "version" "7.20.7" + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + +"@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.16.3", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2", "@babel/traverse@^7.21.3": + "integrity" "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==" + "resolved" "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz" + "version" "7.21.3" + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.21.3" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.21.0" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.21.3" + "@babel/types" "^7.21.3" + "debug" "^4.1.0" + "globals" "^11.1.0" + +"@babel/types@^7.12.7", "@babel/types@^7.15.6", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.18.6", "@babel/types@^7.20.2", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.2", "@babel/types@^7.21.3", "@babel/types@^7.4.4": + "integrity" "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==" + "resolved" "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz" + "version" "7.21.3" + dependencies: + "@babel/helper-string-parser" "^7.19.4" + "@babel/helper-validator-identifier" "^7.19.1" + "to-fast-properties" "^2.0.0" "@docsearch/css@3.0.0-alpha.50": - version "3.0.0-alpha.50" - resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.0.0-alpha.50.tgz#794c6a8d301840a49b55f5b331c7be84b9723643" - integrity sha512-QeWFCQOtS9D+Fi20liKsPXF2j/xWKh52e+P2Z1UATIdPMqmH6zoB2lcUz+cgv6PPVgWUtECeR6VSSUm71LT94w== + "integrity" "sha512-QeWFCQOtS9D+Fi20liKsPXF2j/xWKh52e+P2Z1UATIdPMqmH6zoB2lcUz+cgv6PPVgWUtECeR6VSSUm71LT94w==" + "resolved" "https://registry.npmjs.org/@docsearch/css/-/css-3.0.0-alpha.50.tgz" + "version" "3.0.0-alpha.50" "@docsearch/react@^3.0.0-alpha.39": - version "3.0.0-alpha.50" - resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.0.0-alpha.50.tgz#a7dc547836c2b221fd3aa8eb87bfb47a579ef141" - integrity sha512-oDGV1zZCRYv7MWsh6CyQVthYTRc3b4q+6kKwNYb1/g/Wf/4nJHutpxolFLHdEUDhrJ4Xi8wxwQG+lEwAVBTHPg== + "integrity" "sha512-oDGV1zZCRYv7MWsh6CyQVthYTRc3b4q+6kKwNYb1/g/Wf/4nJHutpxolFLHdEUDhrJ4Xi8wxwQG+lEwAVBTHPg==" + "resolved" "https://registry.npmjs.org/@docsearch/react/-/react-3.0.0-alpha.50.tgz" + "version" "3.0.0-alpha.50" dependencies: "@algolia/autocomplete-core" "1.5.2" "@algolia/autocomplete-preset-algolia" "1.5.2" "@docsearch/css" "3.0.0-alpha.50" - algoliasearch "^4.0.0" + "algoliasearch" "^4.0.0" "@docusaurus/core@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.0.0-beta.15.tgz#1a3f8361803767072e56c77d60332c87e59f1ad0" - integrity sha512-zXhhD0fApMSvq/9Pkm9DQxa//hGOXVCq9yMHiXOkI5D1tLec7PxtnaC5cLfGHljkN9cKIfRDYUVcG1gHymVfpA== + "integrity" "sha512-zXhhD0fApMSvq/9Pkm9DQxa//hGOXVCq9yMHiXOkI5D1tLec7PxtnaC5cLfGHljkN9cKIfRDYUVcG1gHymVfpA==" + "resolved" "https://registry.npmjs.org/@docusaurus/core/-/core-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@babel/core" "^7.16.0" "@babel/generator" "^7.16.0" @@ -1209,103 +1208,103 @@ "@docusaurus/utils-validation" "2.0.0-beta.15" "@slorber/static-site-generator-webpack-plugin" "^4.0.0" "@svgr/webpack" "^6.0.0" - autoprefixer "^10.3.5" - babel-loader "^8.2.2" - babel-plugin-dynamic-import-node "2.3.0" - boxen "^5.0.1" - chokidar "^3.5.2" - clean-css "^5.1.5" - commander "^5.1.0" - copy-webpack-plugin "^10.2.0" - core-js "^3.18.0" - css-loader "^6.5.1" - css-minimizer-webpack-plugin "^3.3.1" - cssnano "^5.0.8" - del "^6.0.0" - detect-port "^1.3.0" - escape-html "^1.0.3" - eta "^1.12.3" - file-loader "^6.2.0" - fs-extra "^10.0.0" - html-minifier-terser "^6.0.2" - html-tags "^3.1.0" - html-webpack-plugin "^5.4.0" - import-fresh "^3.3.0" - is-root "^2.1.0" - leven "^3.1.0" - lodash "^4.17.20" - mini-css-extract-plugin "^1.6.0" - nprogress "^0.2.0" - postcss "^8.3.7" - postcss-loader "^6.1.1" - prompts "^2.4.1" - react-dev-utils "^12.0.0" - react-helmet "^6.1.0" - react-loadable "npm:@docusaurus/react-loadable@5.5.2" - react-loadable-ssr-addon-v5-slorber "^1.0.1" - react-router "^5.2.0" - react-router-config "^5.1.1" - react-router-dom "^5.2.0" - remark-admonitions "^1.2.1" - rtl-detect "^1.0.4" - semver "^7.3.4" - serve-handler "^6.1.3" - shelljs "^0.8.4" - strip-ansi "^6.0.0" - terser-webpack-plugin "^5.2.4" - tslib "^2.3.1" - update-notifier "^5.1.0" - url-loader "^4.1.1" - wait-on "^6.0.0" - webpack "^5.61.0" - webpack-bundle-analyzer "^4.4.2" - webpack-dev-server "^4.7.1" - webpack-merge "^5.8.0" - webpackbar "^5.0.2" + "autoprefixer" "^10.3.5" + "babel-loader" "^8.2.2" + "babel-plugin-dynamic-import-node" "2.3.0" + "boxen" "^5.0.1" + "chokidar" "^3.5.2" + "clean-css" "^5.1.5" + "commander" "^5.1.0" + "copy-webpack-plugin" "^10.2.0" + "core-js" "^3.18.0" + "css-loader" "^6.5.1" + "css-minimizer-webpack-plugin" "^3.3.1" + "cssnano" "^5.0.8" + "del" "^6.0.0" + "detect-port" "^1.3.0" + "escape-html" "^1.0.3" + "eta" "^1.12.3" + "file-loader" "^6.2.0" + "fs-extra" "^10.0.0" + "html-minifier-terser" "^6.0.2" + "html-tags" "^3.1.0" + "html-webpack-plugin" "^5.4.0" + "import-fresh" "^3.3.0" + "is-root" "^2.1.0" + "leven" "^3.1.0" + "lodash" "^4.17.20" + "mini-css-extract-plugin" "^1.6.0" + "nprogress" "^0.2.0" + "postcss" "^8.3.7" + "postcss-loader" "^6.1.1" + "prompts" "^2.4.1" + "react-dev-utils" "^12.0.0" + "react-helmet" "^6.1.0" + "react-loadable" "npm:@docusaurus/react-loadable@5.5.2" + "react-loadable-ssr-addon-v5-slorber" "^1.0.1" + "react-router" "^5.2.0" + "react-router-config" "^5.1.1" + "react-router-dom" "^5.2.0" + "remark-admonitions" "^1.2.1" + "rtl-detect" "^1.0.4" + "semver" "^7.3.4" + "serve-handler" "^6.1.3" + "shelljs" "^0.8.4" + "strip-ansi" "^6.0.0" + "terser-webpack-plugin" "^5.2.4" + "tslib" "^2.3.1" + "update-notifier" "^5.1.0" + "url-loader" "^4.1.1" + "wait-on" "^6.0.0" + "webpack" "^5.61.0" + "webpack-bundle-analyzer" "^4.4.2" + "webpack-dev-server" "^4.7.1" + "webpack-merge" "^5.8.0" + "webpackbar" "^5.0.2" "@docusaurus/cssnano-preset@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-beta.15.tgz#033c52815c428f0f66c87eaff93ea12554ea89df" - integrity sha512-55aYURbB5dqrx64lStNcZxDx5R6bKkAawlCB7mDKx3r+Qnp3ofGW7UExLQSCbTu3axT1vJCF5D7H6ljTRYJLtA== + "integrity" "sha512-55aYURbB5dqrx64lStNcZxDx5R6bKkAawlCB7mDKx3r+Qnp3ofGW7UExLQSCbTu3axT1vJCF5D7H6ljTRYJLtA==" + "resolved" "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: - cssnano-preset-advanced "^5.1.4" - postcss "^8.3.7" - postcss-sort-media-queries "^4.1.0" + "cssnano-preset-advanced" "^5.1.4" + "postcss" "^8.3.7" + "postcss-sort-media-queries" "^4.1.0" "@docusaurus/logger@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-2.0.0-beta.15.tgz#6d17a05fb292d15fdc43b5fa90fd2a49ad5d40ce" - integrity sha512-5bDSHCyLfMtz6QnFfICdL5mgxbGfC7DW1V+/Q17nRdpZSPZgsNKK/Esp0zdDi1oxAyEpXMXx64nLaHL7joJxIg== + "integrity" "sha512-5bDSHCyLfMtz6QnFfICdL5mgxbGfC7DW1V+/Q17nRdpZSPZgsNKK/Esp0zdDi1oxAyEpXMXx64nLaHL7joJxIg==" + "resolved" "https://registry.npmjs.org/@docusaurus/logger/-/logger-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: - chalk "^4.1.2" - tslib "^2.3.1" + "chalk" "^4.1.2" + "tslib" "^2.3.1" "@docusaurus/mdx-loader@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-beta.15.tgz#da23745bc73c93338dd330dad6bbc9d9fe325553" - integrity sha512-MVpytjDDao7hmPF1QSs9B5zoTgevZjiqjnX3FM1yjqdCv+chyUo0gnmYHjeG/4Gqu7jucp+dDdp6yQpzs4g09A== + "integrity" "sha512-MVpytjDDao7hmPF1QSs9B5zoTgevZjiqjnX3FM1yjqdCv+chyUo0gnmYHjeG/4Gqu7jucp+dDdp6yQpzs4g09A==" + "resolved" "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@babel/parser" "^7.16.4" "@babel/traverse" "^7.16.3" "@docusaurus/logger" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" "@mdx-js/mdx" "^1.6.21" - escape-html "^1.0.3" - file-loader "^6.2.0" - fs-extra "^10.0.0" - image-size "^1.0.1" - mdast-util-to-string "^2.0.0" - remark-emoji "^2.1.0" - stringify-object "^3.3.0" - tslib "^2.3.1" - unist-util-visit "^2.0.2" - url-loader "^4.1.1" - webpack "^5.61.0" + "escape-html" "^1.0.3" + "file-loader" "^6.2.0" + "fs-extra" "^10.0.0" + "image-size" "^1.0.1" + "mdast-util-to-string" "^2.0.0" + "remark-emoji" "^2.1.0" + "stringify-object" "^3.3.0" + "tslib" "^2.3.1" + "unist-util-visit" "^2.0.2" + "url-loader" "^4.1.1" + "webpack" "^5.61.0" "@docusaurus/plugin-content-blog@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.15.tgz#6d4bf532ad3dedb4f9fd6398b0fbe481af5b77a9" - integrity sha512-VtEwkgkoNIS8JFPe+huBeBuJ8HG8Lq1JNYM/ItwQg/cwGAgP8EgwbEuKDn428oZKEI2PpgAuf5Gv4AzJWIes9A== + "integrity" "sha512-VtEwkgkoNIS8JFPe+huBeBuJ8HG8Lq1JNYM/ItwQg/cwGAgP8EgwbEuKDn428oZKEI2PpgAuf5Gv4AzJWIes9A==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/logger" "2.0.0-beta.15" @@ -1313,98 +1312,98 @@ "@docusaurus/utils" "2.0.0-beta.15" "@docusaurus/utils-common" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - cheerio "^1.0.0-rc.10" - feed "^4.2.2" - fs-extra "^10.0.0" - lodash "^4.17.20" - reading-time "^1.5.0" - remark-admonitions "^1.2.1" - tslib "^2.3.1" - utility-types "^3.10.0" - webpack "^5.61.0" + "cheerio" "^1.0.0-rc.10" + "feed" "^4.2.2" + "fs-extra" "^10.0.0" + "lodash" "^4.17.20" + "reading-time" "^1.5.0" + "remark-admonitions" "^1.2.1" + "tslib" "^2.3.1" + "utility-types" "^3.10.0" + "webpack" "^5.61.0" "@docusaurus/plugin-content-docs@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-beta.15.tgz#9486bba8abd2a6284e749718bf56743d8e4446f1" - integrity sha512-HSwNZdUKz4rpJiGbFjl/OFhSleeZUSZ6E6lk98i4iL1A5u6fIm4CHsT53yp4UUOse+lFrePTFZsyqwMA4nZZYA== + "integrity" "sha512-HSwNZdUKz4rpJiGbFjl/OFhSleeZUSZ6E6lk98i4iL1A5u6fIm4CHsT53yp4UUOse+lFrePTFZsyqwMA4nZZYA==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/logger" "2.0.0-beta.15" "@docusaurus/mdx-loader" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - combine-promises "^1.1.0" - fs-extra "^10.0.0" - import-fresh "^3.2.2" - js-yaml "^4.0.0" - lodash "^4.17.20" - remark-admonitions "^1.2.1" - shelljs "^0.8.4" - tslib "^2.3.1" - utility-types "^3.10.0" - webpack "^5.61.0" + "combine-promises" "^1.1.0" + "fs-extra" "^10.0.0" + "import-fresh" "^3.2.2" + "js-yaml" "^4.0.0" + "lodash" "^4.17.20" + "remark-admonitions" "^1.2.1" + "shelljs" "^0.8.4" + "tslib" "^2.3.1" + "utility-types" "^3.10.0" + "webpack" "^5.61.0" "@docusaurus/plugin-content-pages@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-beta.15.tgz#e488f7dcdd45cd1d46e8c2c5ff5275327a6a3c65" - integrity sha512-N7YhW5RiOY6J228z4lOoP//qX0Q48cRtxDONZ/Ohd9C5OI2vS6TD8iQuDqOIYHxH+BshjNSsKvbJ+SMIQDwysg== + "integrity" "sha512-N7YhW5RiOY6J228z4lOoP//qX0Q48cRtxDONZ/Ohd9C5OI2vS6TD8iQuDqOIYHxH+BshjNSsKvbJ+SMIQDwysg==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/mdx-loader" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - fs-extra "^10.0.0" - globby "^11.0.2" - remark-admonitions "^1.2.1" - tslib "^2.3.1" - webpack "^5.61.0" + "fs-extra" "^10.0.0" + "globby" "^11.0.2" + "remark-admonitions" "^1.2.1" + "tslib" "^2.3.1" + "webpack" "^5.61.0" "@docusaurus/plugin-debug@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-beta.15.tgz#b75d706d4f9fc4146f84015097bd837d1afb7c6b" - integrity sha512-Jth11jB/rVqPwCGdkVKSUWeXZPAr/NyPn+yeknTBk2LgQKBJ3YU5dNG0uyt0Ay+UYT01TkousPJkXhLuy4Qrsw== + "integrity" "sha512-Jth11jB/rVqPwCGdkVKSUWeXZPAr/NyPn+yeknTBk2LgQKBJ3YU5dNG0uyt0Ay+UYT01TkousPJkXhLuy4Qrsw==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" - fs-extra "^10.0.0" - react-json-view "^1.21.3" - tslib "^2.3.1" + "fs-extra" "^10.0.0" + "react-json-view" "^1.21.3" + "tslib" "^2.3.1" "@docusaurus/plugin-google-analytics@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-beta.15.tgz#6ffebe76d9caac5383cfb78d2baa5883c9c2df6c" - integrity sha512-ELAnxNYiC2i7gfu/ViurNIdm1/DdnbEfVDmpffS9niQhOREM1U3jpxkz/ff1GIC6heOLyHTtini/CZBDoroVGw== + "integrity" "sha512-ELAnxNYiC2i7gfu/ViurNIdm1/DdnbEfVDmpffS9niQhOREM1U3jpxkz/ff1GIC6heOLyHTtini/CZBDoroVGw==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - tslib "^2.3.1" + "tslib" "^2.3.1" "@docusaurus/plugin-google-gtag@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-beta.15.tgz#4db3330d302653e8541dc3cb86a4dbfef0cc96f8" - integrity sha512-E5Rm3+dN7i3A9V5uq5sl9xTNA3aXsLwTZEA2SpOkY571dCpd+sfVvz1lR+KRY9Fy6ZHk8PqrNImgCWfIerRuZQ== + "integrity" "sha512-E5Rm3+dN7i3A9V5uq5sl9xTNA3aXsLwTZEA2SpOkY571dCpd+sfVvz1lR+KRY9Fy6ZHk8PqrNImgCWfIerRuZQ==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - tslib "^2.3.1" + "tslib" "^2.3.1" "@docusaurus/plugin-sitemap@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-beta.15.tgz#0cc083d9e76041897e81b4b82bcd0ccbfa65d6e5" - integrity sha512-PBjeQb2Qpe4uPdRefWL/eXCeYjrgNB/UArExYeUuP4wiY1dpw2unGNCvFUxv4hzJGmARoTLsnRkeYkUim809LQ== + "integrity" "sha512-PBjeQb2Qpe4uPdRefWL/eXCeYjrgNB/UArExYeUuP4wiY1dpw2unGNCvFUxv4hzJGmARoTLsnRkeYkUim809LQ==" + "resolved" "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" "@docusaurus/utils-common" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - fs-extra "^10.0.0" - sitemap "^7.0.0" - tslib "^2.3.1" + "fs-extra" "^10.0.0" + "sitemap" "^7.0.0" + "tslib" "^2.3.1" "@docusaurus/preset-classic@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-2.0.0-beta.15.tgz#13d2f3c4fa7c055af35541ae5e93453450efb208" - integrity sha512-3NZIXWTAzk+kOgiB8uAbD+FZv3VFR1qkU6+TW24DRenjRnXof3CkRuldhI1QI0hILm1fuJ319QRkakV8FFtXyA== + "integrity" "sha512-3NZIXWTAzk+kOgiB8uAbD+FZv3VFR1qkU6+TW24DRenjRnXof3CkRuldhI1QI0hILm1fuJ319QRkakV8FFtXyA==" + "resolved" "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/plugin-content-blog" "2.0.0-beta.15" @@ -1418,18 +1417,18 @@ "@docusaurus/theme-common" "2.0.0-beta.15" "@docusaurus/theme-search-algolia" "2.0.0-beta.15" -"@docusaurus/react-loadable@5.5.2", "react-loadable@npm:@docusaurus/react-loadable@5.5.2": - version "5.5.2" - resolved "https://registry.yarnpkg.com/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz#81aae0db81ecafbdaee3651f12804580868fa6ce" - integrity sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ== +"@docusaurus/react-loadable@5.5.2": + "integrity" "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==" + "resolved" "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz" + "version" "5.5.2" dependencies: "@types/react" "*" - prop-types "^15.6.2" + "prop-types" "^15.6.2" "@docusaurus/theme-classic@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-2.0.0-beta.15.tgz#35d04232f2d5fcb2007675339b0e6d0e8681be95" - integrity sha512-WwNRcQvMtQ7KDhOEHFKFHxXCdoZwLg66hT3vhqNIFMfGQuPzOP91MX5LUSo1QWHhlrD3H3Og+r7Ik/fy2bf5lQ== + "integrity" "sha512-WwNRcQvMtQ7KDhOEHFKFHxXCdoZwLg66hT3vhqNIFMfGQuPzOP91MX5LUSo1QWHhlrD3H3Og+r7Ik/fy2bf5lQ==" + "resolved" "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/core" "2.0.0-beta.15" "@docusaurus/plugin-content-blog" "2.0.0-beta.15" @@ -1441,33 +1440,33 @@ "@docusaurus/utils-common" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" "@mdx-js/react" "^1.6.21" - clsx "^1.1.1" - copy-text-to-clipboard "^3.0.1" - infima "0.2.0-alpha.37" - lodash "^4.17.20" - postcss "^8.3.7" - prism-react-renderer "^1.2.1" - prismjs "^1.23.0" - react-router-dom "^5.2.0" - rtlcss "^3.3.0" + "clsx" "^1.1.1" + "copy-text-to-clipboard" "^3.0.1" + "infima" "0.2.0-alpha.37" + "lodash" "^4.17.20" + "postcss" "^8.3.7" + "prism-react-renderer" "^1.2.1" + "prismjs" "^1.23.0" + "react-router-dom" "^5.2.0" + "rtlcss" "^3.3.0" "@docusaurus/theme-common@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-2.0.0-beta.15.tgz#5bd338d483e2c19d6d74d133572988241518398a" - integrity sha512-+pvarmzcyECE4nWxw+dCMKRIoes0NegrRuM9+nRsUrS/E5ywsF539kpupKIEqaMjq6AuM0CJtDoHxHHPNe0KaQ== + "integrity" "sha512-+pvarmzcyECE4nWxw+dCMKRIoes0NegrRuM9+nRsUrS/E5ywsF539kpupKIEqaMjq6AuM0CJtDoHxHHPNe0KaQ==" + "resolved" "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/plugin-content-blog" "2.0.0-beta.15" "@docusaurus/plugin-content-docs" "2.0.0-beta.15" "@docusaurus/plugin-content-pages" "2.0.0-beta.15" - clsx "^1.1.1" - parse-numeric-range "^1.3.0" - tslib "^2.3.1" - utility-types "^3.10.0" + "clsx" "^1.1.1" + "parse-numeric-range" "^1.3.0" + "tslib" "^2.3.1" + "utility-types" "^3.10.0" "@docusaurus/theme-search-algolia@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-beta.15.tgz#c3ad7fd8e27fcb3e072990031c08768c602cb9a4" - integrity sha512-XrrQKyjOPzmEuOcdsaAn1tzNJkNMA3PC86PwPZUaah0cYPpBGptcJYDlIW4VHIrCBfkQvhvmg/B3qKF6bMMi8g== + "integrity" "sha512-XrrQKyjOPzmEuOcdsaAn1tzNJkNMA3PC86PwPZUaah0cYPpBGptcJYDlIW4VHIrCBfkQvhvmg/B3qKF6bMMi8g==" + "resolved" "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docsearch/react" "^3.0.0-alpha.39" "@docusaurus/core" "2.0.0-beta.15" @@ -1476,268 +1475,268 @@ "@docusaurus/theme-translations" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" "@docusaurus/utils-validation" "2.0.0-beta.15" - algoliasearch "^4.10.5" - algoliasearch-helper "^3.5.5" - clsx "^1.1.1" - eta "^1.12.3" - lodash "^4.17.20" - tslib "^2.3.1" - utility-types "^3.10.0" + "algoliasearch" "^4.10.5" + "algoliasearch-helper" "^3.5.5" + "clsx" "^1.1.1" + "eta" "^1.12.3" + "lodash" "^4.17.20" + "tslib" "^2.3.1" + "utility-types" "^3.10.0" "@docusaurus/theme-translations@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-2.0.0-beta.15.tgz#658397ab4c0d7784043e3cec52cef7ae09d2fb59" - integrity sha512-Lu2JDsnZaB2BcJe8Hpq5nrbS7+7bd09jT08b9vztQyvzR8PgzsthnzlLN4ilOeamRIuYJKo1pUGm0EsQBOP6Nw== + "integrity" "sha512-Lu2JDsnZaB2BcJe8Hpq5nrbS7+7bd09jT08b9vztQyvzR8PgzsthnzlLN4ilOeamRIuYJKo1pUGm0EsQBOP6Nw==" + "resolved" "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: - fs-extra "^10.0.0" - tslib "^2.3.1" + "fs-extra" "^10.0.0" + "tslib" "^2.3.1" "@docusaurus/utils-common@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-2.0.0-beta.15.tgz#5549b329fc750bd5e9f24952c9e3ff7cf1f63e08" - integrity sha512-kIGlSIvbE/oniUpUjI8GOkSpH8o4NXbYqAh9dqPn+TJ0KbEFY3fc80gzZQU+9SunCwJMJbIxIGevX9Ry+nackw== + "integrity" "sha512-kIGlSIvbE/oniUpUjI8GOkSpH8o4NXbYqAh9dqPn+TJ0KbEFY3fc80gzZQU+9SunCwJMJbIxIGevX9Ry+nackw==" + "resolved" "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: - tslib "^2.3.1" + "tslib" "^2.3.1" "@docusaurus/utils-validation@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.0.0-beta.15.tgz#c664bc021194db9254eb45e6b48cb7c2af269041" - integrity sha512-1oOVBCkRrsTXSYrBTsMdnj3a/R56zrx11rjF4xo0+dmm8C01Xw4msFtc3uA7VLX0HQvgHsk8xPzU5GERNdsNpg== + "integrity" "sha512-1oOVBCkRrsTXSYrBTsMdnj3a/R56zrx11rjF4xo0+dmm8C01Xw4msFtc3uA7VLX0HQvgHsk8xPzU5GERNdsNpg==" + "resolved" "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/logger" "2.0.0-beta.15" "@docusaurus/utils" "2.0.0-beta.15" - joi "^17.4.2" - tslib "^2.3.1" + "joi" "^17.4.2" + "tslib" "^2.3.1" "@docusaurus/utils@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.0.0-beta.15.tgz#60868046700d5585cfa6ffc57c5f3fbed00b61fc" - integrity sha512-xkoPmFxCBkDqbZR4U3SE752OcXtWTGgZnc/pZWxItzb1IYRGNZHrzdIr7CnI7rppriuZzsyivDGiC4Ud9MWhkA== + "integrity" "sha512-xkoPmFxCBkDqbZR4U3SE752OcXtWTGgZnc/pZWxItzb1IYRGNZHrzdIr7CnI7rppriuZzsyivDGiC4Ud9MWhkA==" + "resolved" "https://registry.npmjs.org/@docusaurus/utils/-/utils-2.0.0-beta.15.tgz" + "version" "2.0.0-beta.15" dependencies: "@docusaurus/logger" "2.0.0-beta.15" "@mdx-js/runtime" "^1.6.22" "@svgr/webpack" "^6.0.0" - file-loader "^6.2.0" - fs-extra "^10.0.0" - github-slugger "^1.4.0" - globby "^11.0.4" - gray-matter "^4.0.3" - js-yaml "^4.0.0" - lodash "^4.17.20" - micromatch "^4.0.4" - remark-mdx-remove-exports "^1.6.22" - remark-mdx-remove-imports "^1.6.22" - resolve-pathname "^3.0.0" - tslib "^2.3.1" - url-loader "^4.1.1" + "file-loader" "^6.2.0" + "fs-extra" "^10.0.0" + "github-slugger" "^1.4.0" + "globby" "^11.0.4" + "gray-matter" "^4.0.3" + "js-yaml" "^4.0.0" + "lodash" "^4.17.20" + "micromatch" "^4.0.4" + "remark-mdx-remove-exports" "^1.6.22" + "remark-mdx-remove-imports" "^1.6.22" + "resolve-pathname" "^3.0.0" + "tslib" "^2.3.1" + "url-loader" "^4.1.1" "@hapi/hoek@^9.0.0": - version "9.2.1" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.2.1.tgz#9551142a1980503752536b5050fd99f4a7f13b17" - integrity sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw== + "integrity" "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==" + "resolved" "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz" + "version" "9.2.1" "@hapi/topo@^5.0.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" - integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== + "integrity" "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==" + "resolved" "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz" + "version" "5.1.0" dependencies: "@hapi/hoek" "^9.0.0" -"@jridgewell/gen-mapping@^0.3.0": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" - integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== +"@jridgewell/gen-mapping@^0.1.0": + "integrity" "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==" + "resolved" "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz" + "version" "0.1.1" + dependencies: + "@jridgewell/set-array" "^1.0.0" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + "integrity" "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==" + "resolved" "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz" + "version" "0.3.2" dependencies: "@jridgewell/set-array" "^1.0.1" "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/resolve-uri@^3.0.3": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== +"@jridgewell/resolve-uri@3.1.0": + "integrity" "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" + "resolved" "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz" + "version" "3.1.0" -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": + "integrity" "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + "resolved" "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz" + "version" "1.1.2" "@jridgewell/source-map@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" - integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + "integrity" "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==" + "resolved" "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz" + "version" "0.3.2" dependencies: "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== - -"@jridgewell/trace-mapping@^0.3.0": - version "0.3.4" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz#f6a0832dffd5b8a6aaa633b7d9f8e8e94c83a0c3" - integrity sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@1.4.14": + "integrity" "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + "resolved" "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" + "version" "1.4.14" -"@jridgewell/trace-mapping@^0.3.9": - version "0.3.14" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed" - integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ== +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": + "integrity" "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==" + "resolved" "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz" + "version" "0.3.17" dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" -"@mdx-js/mdx@1.6.22", "@mdx-js/mdx@^1.6.21": - version "1.6.22" - resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-1.6.22.tgz#8a723157bf90e78f17dc0f27995398e6c731f1ba" - integrity sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA== +"@mdx-js/mdx@^1.6.21", "@mdx-js/mdx@1.6.22": + "integrity" "sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==" + "resolved" "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz" + "version" "1.6.22" dependencies: "@babel/core" "7.12.9" "@babel/plugin-syntax-jsx" "7.12.1" "@babel/plugin-syntax-object-rest-spread" "7.8.3" "@mdx-js/util" "1.6.22" - babel-plugin-apply-mdx-type-prop "1.6.22" - babel-plugin-extract-import-names "1.6.22" - camelcase-css "2.0.1" - detab "2.0.4" - hast-util-raw "6.0.1" - lodash.uniq "4.5.0" - mdast-util-to-hast "10.0.1" - remark-footnotes "2.0.0" - remark-mdx "1.6.22" - remark-parse "8.0.3" - remark-squeeze-paragraphs "4.0.0" - style-to-object "0.3.0" - unified "9.2.0" - unist-builder "2.0.3" - unist-util-visit "2.0.3" - -"@mdx-js/react@1.6.22", "@mdx-js/react@^1.6.21": - version "1.6.22" - resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.6.22.tgz#ae09b4744fddc74714ee9f9d6f17a66e77c43573" - integrity sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg== + "babel-plugin-apply-mdx-type-prop" "1.6.22" + "babel-plugin-extract-import-names" "1.6.22" + "camelcase-css" "2.0.1" + "detab" "2.0.4" + "hast-util-raw" "6.0.1" + "lodash.uniq" "4.5.0" + "mdast-util-to-hast" "10.0.1" + "remark-footnotes" "2.0.0" + "remark-mdx" "1.6.22" + "remark-parse" "8.0.3" + "remark-squeeze-paragraphs" "4.0.0" + "style-to-object" "0.3.0" + "unified" "9.2.0" + "unist-builder" "2.0.3" + "unist-util-visit" "2.0.3" + +"@mdx-js/react@^1.6.21", "@mdx-js/react@1.6.22": + "integrity" "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==" + "resolved" "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz" + "version" "1.6.22" "@mdx-js/runtime@^1.6.22": - version "1.6.22" - resolved "https://registry.yarnpkg.com/@mdx-js/runtime/-/runtime-1.6.22.tgz#3edd388bf68a519ffa1aaf9c446b548165102345" - integrity sha512-p17spaO2+55VLCuxXA3LVHC4phRx60NR2XMdZ+qgVU1lKvEX4y88dmFNOzGDCPLJ03IZyKrJ/rPWWRiBrd9JrQ== + "integrity" "sha512-p17spaO2+55VLCuxXA3LVHC4phRx60NR2XMdZ+qgVU1lKvEX4y88dmFNOzGDCPLJ03IZyKrJ/rPWWRiBrd9JrQ==" + "resolved" "https://registry.npmjs.org/@mdx-js/runtime/-/runtime-1.6.22.tgz" + "version" "1.6.22" dependencies: "@mdx-js/mdx" "1.6.22" "@mdx-js/react" "1.6.22" - buble-jsx-only "^0.19.8" + "buble-jsx-only" "^0.19.8" "@mdx-js/util@1.6.22": - version "1.6.22" - resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b" - integrity sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA== + "integrity" "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==" + "resolved" "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz" + "version" "1.6.22" "@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + "integrity" "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==" + "resolved" "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" + "version" "2.1.5" dependencies: "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" + "run-parallel" "^1.1.9" -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== +"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": + "integrity" "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + "resolved" "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" + "version" "2.0.5" "@nodelib/fs.walk@^1.2.3": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + "integrity" "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==" + "resolved" "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" + "version" "1.2.8" dependencies: "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" + "fastq" "^1.6.0" "@polka/url@^1.0.0-next.20": - version "1.0.0-next.21" - resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" - integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== + "integrity" "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==" + "resolved" "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz" + "version" "1.0.0-next.21" "@sideway/address@^4.1.3": - version "4.1.3" - resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.3.tgz#d93cce5d45c5daec92ad76db492cc2ee3c64ab27" - integrity sha512-8ncEUtmnTsMmL7z1YPB47kPUq7LpKWJNFPsRzHiIajGC5uXlWGn+AmkYPcHNl8S4tcEGx+cnORnNYaw2wvL+LQ== + "integrity" "sha512-8ncEUtmnTsMmL7z1YPB47kPUq7LpKWJNFPsRzHiIajGC5uXlWGn+AmkYPcHNl8S4tcEGx+cnORnNYaw2wvL+LQ==" + "resolved" "https://registry.npmjs.org/@sideway/address/-/address-4.1.3.tgz" + "version" "4.1.3" dependencies: "@hapi/hoek" "^9.0.0" "@sideway/formula@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c" - integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg== + "integrity" "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + "resolved" "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz" + "version" "3.0.1" "@sideway/pinpoint@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" - integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + "integrity" "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + "resolved" "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz" + "version" "2.0.0" "@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + "integrity" "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" + "resolved" "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz" + "version" "0.14.0" "@slorber/static-site-generator-webpack-plugin@^4.0.0": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.1.tgz#0c8852146441aaa683693deaa5aee2f991d94841" - integrity sha512-PSv4RIVO1Y3kvHxjvqeVisk3E9XFoO04uwYBDWe217MFqKspplYswTuKLiJu0aLORQWzuQjfVsSlLPojwfYsLw== + "integrity" "sha512-PSv4RIVO1Y3kvHxjvqeVisk3E9XFoO04uwYBDWe217MFqKspplYswTuKLiJu0aLORQWzuQjfVsSlLPojwfYsLw==" + "resolved" "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.1.tgz" + "version" "4.0.1" dependencies: - bluebird "^3.7.1" - cheerio "^0.22.0" - eval "^0.1.4" - url "^0.11.0" - webpack-sources "^1.4.3" + "bluebird" "^3.7.1" + "cheerio" "^0.22.0" + "eval" "^0.1.4" + "url" "^0.11.0" + "webpack-sources" "^1.4.3" "@svgr/babel-plugin-add-jsx-attribute@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.0.0.tgz#bd6d1ff32a31b82b601e73672a789cc41e84fe18" - integrity sha512-MdPdhdWLtQsjd29Wa4pABdhWbaRMACdM1h31BY+c6FghTZqNGT7pEYdBoaGeKtdTOBC/XNFQaKVj+r/Ei2ryWA== + "integrity" "sha512-MdPdhdWLtQsjd29Wa4pABdhWbaRMACdM1h31BY+c6FghTZqNGT7pEYdBoaGeKtdTOBC/XNFQaKVj+r/Ei2ryWA==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-remove-jsx-attribute@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.0.0.tgz#58654908beebfa069681a83332544b17e5237e89" - integrity sha512-aVdtfx9jlaaxc3unA6l+M9YRnKIZjOhQPthLKqmTXC8UVkBLDRGwPKo+r8n3VZN8B34+yVajzPTZ+ptTSuZZCw== + "integrity" "sha512-aVdtfx9jlaaxc3unA6l+M9YRnKIZjOhQPthLKqmTXC8UVkBLDRGwPKo+r8n3VZN8B34+yVajzPTZ+ptTSuZZCw==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-remove-jsx-empty-expression@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.0.0.tgz#d06dd6e8a8f603f92f9979bb9990a1f85a4f57ba" - integrity sha512-Ccj42ApsePD451AZJJf1QzTD1B/BOU392URJTeXFxSK709i0KUsGtbwyiqsKu7vsYxpTM0IA5clAKDyf9RCZyA== + "integrity" "sha512-Ccj42ApsePD451AZJJf1QzTD1B/BOU392URJTeXFxSK709i0KUsGtbwyiqsKu7vsYxpTM0IA5clAKDyf9RCZyA==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-replace-jsx-attribute-value@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.0.0.tgz#0b85837577b02c31c09c758a12932820f5245cee" - integrity sha512-88V26WGyt1Sfd1emBYmBJRWMmgarrExpKNVmI9vVozha4kqs6FzQJ/Kp5+EYli1apgX44518/0+t9+NU36lThQ== + "integrity" "sha512-88V26WGyt1Sfd1emBYmBJRWMmgarrExpKNVmI9vVozha4kqs6FzQJ/Kp5+EYli1apgX44518/0+t9+NU36lThQ==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-svg-dynamic-title@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.0.0.tgz#28236ec26f7ab9d486a487d36ae52d58ba15676f" - integrity sha512-F7YXNLfGze+xv0KMQxrl2vkNbI9kzT9oDK55/kUuymh1ACyXkMV+VZWX1zEhSTfEKh7VkHVZGmVtHg8eTZ6PRg== + "integrity" "sha512-F7YXNLfGze+xv0KMQxrl2vkNbI9kzT9oDK55/kUuymh1ACyXkMV+VZWX1zEhSTfEKh7VkHVZGmVtHg8eTZ6PRg==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-svg-em-dimensions@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.0.0.tgz#40267c5dea1b43c4f83a0eb6169e08b43d8bafce" - integrity sha512-+rghFXxdIqJNLQK08kwPBD3Z22/0b2tEZ9lKiL/yTfuyj1wW8HUXu4bo/XkogATIYuXSghVQOOCwURXzHGKyZA== + "integrity" "sha512-+rghFXxdIqJNLQK08kwPBD3Z22/0b2tEZ9lKiL/yTfuyj1wW8HUXu4bo/XkogATIYuXSghVQOOCwURXzHGKyZA==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-transform-react-native-svg@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.0.0.tgz#eb688d0a5f539e34d268d8a516e81f5d7fede7c9" - integrity sha512-VaphyHZ+xIKv5v0K0HCzyfAaLhPGJXSk2HkpYfXIOKb7DjLBv0soHDxNv6X0vr2titsxE7klb++u7iOf7TSrFQ== + "integrity" "sha512-VaphyHZ+xIKv5v0K0HCzyfAaLhPGJXSk2HkpYfXIOKb7DjLBv0soHDxNv6X0vr2titsxE7klb++u7iOf7TSrFQ==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.0.0.tgz" + "version" "6.0.0" "@svgr/babel-plugin-transform-svg-component@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.2.0.tgz#7ba61d9fc1fb42b0ba1a04e4630019fa7e993c4f" - integrity sha512-bhYIpsORb++wpsp91fymbFkf09Z/YEKR0DnFjxvN+8JHeCUD2unnh18jIMKnDJTWtvpTaGYPXELVe4OOzFI0xg== + "integrity" "sha512-bhYIpsORb++wpsp91fymbFkf09Z/YEKR0DnFjxvN+8JHeCUD2unnh18jIMKnDJTWtvpTaGYPXELVe4OOzFI0xg==" + "resolved" "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.2.0.tgz" + "version" "6.2.0" "@svgr/babel-preset@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-6.2.0.tgz#1d3ad8c7664253a4be8e4a0f0e6872f30d8af627" - integrity sha512-4WQNY0J71JIaL03DRn0vLiz87JXx0b9dYm2aA8XHlQJQoixMl4r/soYHm8dsaJZ3jWtkCiOYy48dp9izvXhDkQ== + "integrity" "sha512-4WQNY0J71JIaL03DRn0vLiz87JXx0b9dYm2aA8XHlQJQoixMl4r/soYHm8dsaJZ3jWtkCiOYy48dp9izvXhDkQ==" + "resolved" "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.2.0.tgz" + "version" "6.2.0" dependencies: "@svgr/babel-plugin-add-jsx-attribute" "^6.0.0" "@svgr/babel-plugin-remove-jsx-attribute" "^6.0.0" @@ -1748,46 +1747,46 @@ "@svgr/babel-plugin-transform-react-native-svg" "^6.0.0" "@svgr/babel-plugin-transform-svg-component" "^6.2.0" -"@svgr/core@^6.2.1": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@svgr/core/-/core-6.2.1.tgz#195de807a9f27f9e0e0d678e01084b05c54fdf61" - integrity sha512-NWufjGI2WUyrg46mKuySfviEJ6IxHUOm/8a3Ph38VCWSp+83HBraCQrpEM3F3dB6LBs5x8OElS8h3C0oOJaJAA== +"@svgr/core@^6.0.0", "@svgr/core@^6.2.1": + "integrity" "sha512-NWufjGI2WUyrg46mKuySfviEJ6IxHUOm/8a3Ph38VCWSp+83HBraCQrpEM3F3dB6LBs5x8OElS8h3C0oOJaJAA==" + "resolved" "https://registry.npmjs.org/@svgr/core/-/core-6.2.1.tgz" + "version" "6.2.1" dependencies: "@svgr/plugin-jsx" "^6.2.1" - camelcase "^6.2.0" - cosmiconfig "^7.0.1" + "camelcase" "^6.2.0" + "cosmiconfig" "^7.0.1" "@svgr/hast-util-to-babel-ast@^6.2.1": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.2.1.tgz#ae065567b74cbe745afae617053adf9a764bea25" - integrity sha512-pt7MMkQFDlWJVy9ULJ1h+hZBDGFfSCwlBNW1HkLnVi7jUhyEXUaGYWi1x6bM2IXuAR9l265khBT4Av4lPmaNLQ== + "integrity" "sha512-pt7MMkQFDlWJVy9ULJ1h+hZBDGFfSCwlBNW1HkLnVi7jUhyEXUaGYWi1x6bM2IXuAR9l265khBT4Av4lPmaNLQ==" + "resolved" "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.2.1.tgz" + "version" "6.2.1" dependencies: "@babel/types" "^7.15.6" - entities "^3.0.1" + "entities" "^3.0.1" "@svgr/plugin-jsx@^6.2.1": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-6.2.1.tgz#5668f1d2aa18c2f1bb7a1fc9f682d3f9aed263bd" - integrity sha512-u+MpjTsLaKo6r3pHeeSVsh9hmGRag2L7VzApWIaS8imNguqoUwDq/u6U/NDmYs/KAsrmtBjOEaAAPbwNGXXp1g== + "integrity" "sha512-u+MpjTsLaKo6r3pHeeSVsh9hmGRag2L7VzApWIaS8imNguqoUwDq/u6U/NDmYs/KAsrmtBjOEaAAPbwNGXXp1g==" + "resolved" "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.2.1.tgz" + "version" "6.2.1" dependencies: "@babel/core" "^7.15.5" "@svgr/babel-preset" "^6.2.0" "@svgr/hast-util-to-babel-ast" "^6.2.1" - svg-parser "^2.0.2" + "svg-parser" "^2.0.2" "@svgr/plugin-svgo@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-6.2.0.tgz#4cbe6a33ccccdcae4e3b63ded64cc1cbe1faf48c" - integrity sha512-oDdMQONKOJEbuKwuy4Np6VdV6qoaLLvoY86hjvQEgU82Vx1MSWRyYms6Sl0f+NtqxLI/rDVufATbP/ev996k3Q== + "integrity" "sha512-oDdMQONKOJEbuKwuy4Np6VdV6qoaLLvoY86hjvQEgU82Vx1MSWRyYms6Sl0f+NtqxLI/rDVufATbP/ev996k3Q==" + "resolved" "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-6.2.0.tgz" + "version" "6.2.0" dependencies: - cosmiconfig "^7.0.1" - deepmerge "^4.2.2" - svgo "^2.5.0" + "cosmiconfig" "^7.0.1" + "deepmerge" "^4.2.2" + "svgo" "^2.5.0" "@svgr/webpack@^6.0.0": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-6.2.1.tgz#ef5d51c1b6be4e7537fb9f76b3f2b2e22b63c58d" - integrity sha512-h09ngMNd13hnePwgXa+Y5CgOjzlCvfWLHg+MBnydEedAnuLRzUHUJmGS3o2OsrhxTOOqEsPOFt5v/f6C5Qulcw== + "integrity" "sha512-h09ngMNd13hnePwgXa+Y5CgOjzlCvfWLHg+MBnydEedAnuLRzUHUJmGS3o2OsrhxTOOqEsPOFt5v/f6C5Qulcw==" + "resolved" "https://registry.npmjs.org/@svgr/webpack/-/webpack-6.2.1.tgz" + "version" "6.2.1" dependencies: "@babel/core" "^7.15.5" "@babel/plugin-transform-react-constant-elements" "^7.14.5" @@ -1799,81 +1798,81 @@ "@svgr/plugin-svgo" "^6.2.0" "@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + "integrity" "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==" + "resolved" "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz" + "version" "1.1.2" dependencies: - defer-to-connect "^1.0.1" + "defer-to-connect" "^1.0.1" "@trysound/sax@0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" - integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== + "integrity" "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==" + "resolved" "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz" + "version" "0.2.0" "@types/body-parser@*": - version "1.19.2" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" - integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + "integrity" "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==" + "resolved" "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz" + "version" "1.19.2" dependencies: "@types/connect" "*" "@types/node" "*" "@types/bonjour@^3.5.9": - version "3.5.10" - resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" - integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== + "integrity" "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==" + "resolved" "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz" + "version" "3.5.10" dependencies: "@types/node" "*" "@types/connect-history-api-fallback@^1.3.5": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" - integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== + "integrity" "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==" + "resolved" "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz" + "version" "1.3.5" dependencies: "@types/express-serve-static-core" "*" "@types/node" "*" "@types/connect@*": - version "3.4.35" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" - integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + "integrity" "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==" + "resolved" "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz" + "version" "3.4.35" dependencies: "@types/node" "*" "@types/eslint-scope@^3.7.3": - version "3.7.3" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224" - integrity sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g== + "integrity" "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==" + "resolved" "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz" + "version" "3.7.3" dependencies: "@types/eslint" "*" "@types/estree" "*" "@types/eslint@*": - version "8.4.1" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.1.tgz#c48251553e8759db9e656de3efc846954ac32304" - integrity sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA== + "integrity" "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==" + "resolved" "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz" + "version" "8.4.1" dependencies: "@types/estree" "*" "@types/json-schema" "*" "@types/estree@*", "@types/estree@^0.0.51": - version "0.0.51" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" - integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== + "integrity" "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==" + "resolved" "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz" + "version" "0.0.51" "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18": - version "4.17.28" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz#c47def9f34ec81dc6328d0b1b5303d1ec98d86b8" - integrity sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig== + "integrity" "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==" + "resolved" "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz" + "version" "4.17.28" dependencies: "@types/node" "*" "@types/qs" "*" "@types/range-parser" "*" "@types/express@*", "@types/express@^4.17.13": - version "4.17.13" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" - integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== + "integrity" "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==" + "resolved" "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz" + "version" "4.17.13" dependencies: "@types/body-parser" "*" "@types/express-serve-static-core" "^4.17.18" @@ -1881,172 +1880,172 @@ "@types/serve-static" "*" "@types/hast@^2.0.0": - version "2.3.4" - resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" - integrity sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g== + "integrity" "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==" + "resolved" "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz" + "version" "2.3.4" dependencies: "@types/unist" "*" "@types/html-minifier-terser@^6.0.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" - integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== + "integrity" "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + "resolved" "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz" + "version" "6.1.0" "@types/http-proxy@^1.17.8": - version "1.17.8" - resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.8.tgz#968c66903e7e42b483608030ee85800f22d03f55" - integrity sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA== + "integrity" "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==" + "resolved" "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz" + "version" "1.17.8" dependencies: "@types/node" "*" "@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": - version "7.0.9" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" - integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== + "integrity" "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" + "resolved" "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz" + "version" "7.0.9" "@types/mdast@^3.0.0": - version "3.0.10" - resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af" - integrity sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA== + "integrity" "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==" + "resolved" "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz" + "version" "3.0.10" dependencies: "@types/unist" "*" "@types/mime@^1": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" - integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== + "integrity" "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + "resolved" "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz" + "version" "1.3.2" "@types/node@*", "@types/node@^17.0.5": - version "17.0.18" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.18.tgz#3b4fed5cfb58010e3a2be4b6e74615e4847f1074" - integrity sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA== + "integrity" "sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==" + "resolved" "https://registry.npmjs.org/@types/node/-/node-17.0.18.tgz" + "version" "17.0.18" "@types/parse-json@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" - integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + "integrity" "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" + "resolved" "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz" + "version" "4.0.0" "@types/parse5@^5.0.0": - version "5.0.3" - resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109" - integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== + "integrity" "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==" + "resolved" "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz" + "version" "5.0.3" "@types/prop-types@*": - version "15.7.4" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" - integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ== + "integrity" "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==" + "resolved" "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz" + "version" "15.7.4" "@types/qs@*": - version "6.9.7" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" - integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + "integrity" "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + "resolved" "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz" + "version" "6.9.7" "@types/range-parser@*": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" - integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + "integrity" "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + "resolved" "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz" + "version" "1.2.4" -"@types/react@*": - version "17.0.39" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.39.tgz#d0f4cde092502a6db00a1cded6e6bf2abb7633ce" - integrity sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug== +"@types/react@*", "@types/react@>= 16.8.0 < 18.0.0": + "integrity" "sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==" + "resolved" "https://registry.npmjs.org/@types/react/-/react-17.0.39.tgz" + "version" "17.0.39" dependencies: "@types/prop-types" "*" "@types/scheduler" "*" - csstype "^3.0.2" + "csstype" "^3.0.2" "@types/retry@^0.12.0": - version "0.12.1" - resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065" - integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g== + "integrity" "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==" + "resolved" "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz" + "version" "0.12.1" "@types/sax@^1.2.1": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@types/sax/-/sax-1.2.4.tgz#8221affa7f4f3cb21abd22f244cfabfa63e6a69e" - integrity sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw== + "integrity" "sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw==" + "resolved" "https://registry.npmjs.org/@types/sax/-/sax-1.2.4.tgz" + "version" "1.2.4" dependencies: "@types/node" "*" "@types/scheduler@*": - version "0.16.2" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" - integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== + "integrity" "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" + "resolved" "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz" + "version" "0.16.2" "@types/serve-index@^1.9.1": - version "1.9.1" - resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" - integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== + "integrity" "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==" + "resolved" "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz" + "version" "1.9.1" dependencies: "@types/express" "*" "@types/serve-static@*": - version "1.13.10" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" - integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ== + "integrity" "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==" + "resolved" "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz" + "version" "1.13.10" dependencies: "@types/mime" "^1" "@types/node" "*" "@types/sockjs@^0.3.33": - version "0.3.33" - resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" - integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== + "integrity" "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==" + "resolved" "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz" + "version" "0.3.33" dependencies: "@types/node" "*" "@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" - integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== + "integrity" "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" + "resolved" "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz" + "version" "2.0.6" "@types/ws@^8.2.2": - version "8.2.2" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.2.2.tgz#7c5be4decb19500ae6b3d563043cd407bf366c21" - integrity sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg== + "integrity" "sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg==" + "resolved" "https://registry.npmjs.org/@types/ws/-/ws-8.2.2.tgz" + "version" "8.2.2" dependencies: "@types/node" "*" "@webassemblyjs/ast@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" - integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== + "integrity" "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/helper-numbers" "1.11.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.1" "@webassemblyjs/floating-point-hex-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" - integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== + "integrity" "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz" + "version" "1.11.1" "@webassemblyjs/helper-api-error@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" - integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== + "integrity" "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz" + "version" "1.11.1" "@webassemblyjs/helper-buffer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" - integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== + "integrity" "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz" + "version" "1.11.1" "@webassemblyjs/helper-numbers@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" - integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== + "integrity" "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/floating-point-hex-parser" "1.11.1" "@webassemblyjs/helper-api-error" "1.11.1" "@xtuc/long" "4.2.2" "@webassemblyjs/helper-wasm-bytecode@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" - integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== + "integrity" "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz" + "version" "1.11.1" "@webassemblyjs/helper-wasm-section@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" - integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== + "integrity" "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/helper-buffer" "1.11.1" @@ -2054,28 +2053,28 @@ "@webassemblyjs/wasm-gen" "1.11.1" "@webassemblyjs/ieee754@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" - integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== + "integrity" "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz" + "version" "1.11.1" dependencies: "@xtuc/ieee754" "^1.2.0" "@webassemblyjs/leb128@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" - integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== + "integrity" "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz" + "version" "1.11.1" dependencies: "@xtuc/long" "4.2.2" "@webassemblyjs/utf8@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" - integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== + "integrity" "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz" + "version" "1.11.1" "@webassemblyjs/wasm-edit@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" - integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== + "integrity" "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/helper-buffer" "1.11.1" @@ -2087,9 +2086,9 @@ "@webassemblyjs/wast-printer" "1.11.1" "@webassemblyjs/wasm-gen@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" - integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== + "integrity" "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.1" @@ -2098,9 +2097,9 @@ "@webassemblyjs/utf8" "1.11.1" "@webassemblyjs/wasm-opt@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" - integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== + "integrity" "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/helper-buffer" "1.11.1" @@ -2108,9 +2107,9 @@ "@webassemblyjs/wasm-parser" "1.11.1" "@webassemblyjs/wasm-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" - integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== + "integrity" "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/helper-api-error" "1.11.1" @@ -2120,124 +2119,124 @@ "@webassemblyjs/utf8" "1.11.1" "@webassemblyjs/wast-printer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" - integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== + "integrity" "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz" + "version" "1.11.1" dependencies: "@webassemblyjs/ast" "1.11.1" "@xtuc/long" "4.2.2" "@xtuc/ieee754@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + "integrity" "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + "resolved" "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz" + "version" "1.2.0" "@xtuc/long@4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== - -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== - dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" - -acorn-dynamic-import@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948" - integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw== - -acorn-import-assertions@^1.7.6: - version "1.8.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" - integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== - -acorn-jsx@^5.0.1: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn-walk@^8.0.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== - -acorn@^6.1.1: - version "6.4.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" - integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== - -acorn@^8.0.4, acorn@^8.4.1, acorn@^8.5.0: - version "8.7.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" - integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== - -address@^1.0.1, address@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" - integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA== - -aggregate-error@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" - integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - -ajv-formats@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" - integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== - dependencies: - ajv "^8.0.0" - -ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" - integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== - -ajv-keywords@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" - integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== - dependencies: - fast-deep-equal "^3.1.3" - -ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ajv@^8.0.0, ajv@^8.8.0: - version "8.10.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.10.0.tgz#e573f719bd3af069017e3b66538ab968d040e54d" - integrity sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - -algoliasearch-helper@^3.5.5: - version "3.7.0" - resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.7.0.tgz#c0a0493df84d850360f664ad7a9d4fc78a94fd78" - integrity sha512-XJ3QfERBLfeVCyTVx80gon7r3/rgm/CE8Ha1H7cbablRe/X7SfYQ14g/eO+MhjVKIQp+gy9oC6G5ilmLwS1k6w== + "integrity" "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + "resolved" "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz" + "version" "4.2.2" + +"accepts@~1.3.4", "accepts@~1.3.5", "accepts@~1.3.8": + "integrity" "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==" + "resolved" "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz" + "version" "1.3.8" + dependencies: + "mime-types" "~2.1.34" + "negotiator" "0.6.3" + +"acorn-dynamic-import@^4.0.0": + "integrity" "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==" + "resolved" "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz" + "version" "4.0.0" + +"acorn-import-assertions@^1.7.6": + "integrity" "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==" + "resolved" "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz" + "version" "1.8.0" + +"acorn-jsx@^5.0.1": + "integrity" "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==" + "resolved" "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" + "version" "5.3.2" + +"acorn-walk@^8.0.0": + "integrity" "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" + "resolved" "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" + "version" "8.2.0" + +"acorn@^6.0.0", "acorn@^6.0.0 || ^7.0.0 || ^8.0.0", "acorn@^6.1.1": + "integrity" "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==" + "resolved" "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz" + "version" "6.4.2" + +"acorn@^8", "acorn@^8.0.4", "acorn@^8.4.1", "acorn@^8.5.0": + "integrity" "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==" + "resolved" "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz" + "version" "8.7.1" + +"address@^1.0.1", "address@^1.1.2": + "integrity" "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==" + "resolved" "https://registry.npmjs.org/address/-/address-1.1.2.tgz" + "version" "1.1.2" + +"aggregate-error@^3.0.0": + "integrity" "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==" + "resolved" "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "clean-stack" "^2.0.0" + "indent-string" "^4.0.0" + +"ajv-formats@^2.1.1": + "integrity" "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==" + "resolved" "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz" + "version" "2.1.1" + dependencies: + "ajv" "^8.0.0" + +"ajv-keywords@^3.4.1", "ajv-keywords@^3.5.2": + "integrity" "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" + "resolved" "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" + "version" "3.5.2" + +"ajv-keywords@^5.0.0": + "integrity" "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==" + "resolved" "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "fast-deep-equal" "^3.1.3" + +"ajv@^6.12.2", "ajv@^6.12.4", "ajv@^6.12.5", "ajv@^6.9.1": + "integrity" "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==" + "resolved" "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" + "version" "6.12.6" + dependencies: + "fast-deep-equal" "^3.1.1" + "fast-json-stable-stringify" "^2.0.0" + "json-schema-traverse" "^0.4.1" + "uri-js" "^4.2.2" + +"ajv@^8.0.0", "ajv@^8.8.0", "ajv@^8.8.2": + "integrity" "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==" + "resolved" "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz" + "version" "8.10.0" + dependencies: + "fast-deep-equal" "^3.1.1" + "json-schema-traverse" "^1.0.0" + "require-from-string" "^2.0.2" + "uri-js" "^4.2.2" + +"algoliasearch-helper@^3.5.5": + "integrity" "sha512-XJ3QfERBLfeVCyTVx80gon7r3/rgm/CE8Ha1H7cbablRe/X7SfYQ14g/eO+MhjVKIQp+gy9oC6G5ilmLwS1k6w==" + "resolved" "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.7.0.tgz" + "version" "3.7.0" dependencies: "@algolia/events" "^4.0.1" -algoliasearch@^4.0.0, algoliasearch@^4.10.5: - version "4.12.1" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.12.1.tgz#574a2c5424c4b6681c026928fb810be2d2ec3924" - integrity sha512-c0dM1g3zZBJrkzE5GA/Nu1y3fFxx3LCzxKzcmp2dgGS8P4CjszB/l3lsSh2MSrrK1Hn/KV4BlbBMXtYgG1Bfrw== +"algoliasearch@^4.0.0", "algoliasearch@^4.10.5", "algoliasearch@^4.9.1", "algoliasearch@>= 3.1 < 5": + "integrity" "sha512-c0dM1g3zZBJrkzE5GA/Nu1y3fFxx3LCzxKzcmp2dgGS8P4CjszB/l3lsSh2MSrrK1Hn/KV4BlbBMXtYgG1Bfrw==" + "resolved" "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.12.1.tgz" + "version" "4.12.1" dependencies: "@algolia/cache-browser-local-storage" "4.12.1" "@algolia/cache-common" "4.12.1" @@ -2254,2429 +2253,2448 @@ algoliasearch@^4.0.0, algoliasearch@^4.10.5: "@algolia/requester-node-http" "4.12.1" "@algolia/transporter" "4.12.1" -ansi-align@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" - integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== - dependencies: - string-width "^4.1.0" - -ansi-html-community@^0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" - integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -arg@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.1.tgz#eb0c9a8f77786cad2af8ff2b862899842d7b6adb" - integrity sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA== - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - -array-flatten@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" - integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -array-union@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-3.0.1.tgz#da52630d327f8b88cfbfb57728e2af5cd9b6b975" - integrity sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw== - -asap@~2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= - -async@^2.6.2: - version "2.6.4" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" - integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== - dependencies: - lodash "^4.17.14" - -at-least-node@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" - integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== - -autoprefixer@^10.3.5, autoprefixer@^10.3.7: - version "10.4.2" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.2.tgz#25e1df09a31a9fba5c40b578936b90d35c9d4d3b" - integrity sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ== - dependencies: - browserslist "^4.19.1" - caniuse-lite "^1.0.30001297" - fraction.js "^4.1.2" - normalize-range "^0.1.2" - picocolors "^1.0.0" - postcss-value-parser "^4.2.0" - -axios@^0.25.0: - version "0.25.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.25.0.tgz#349cfbb31331a9b4453190791760a8d35b093e0a" - integrity sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g== - dependencies: - follow-redirects "^1.14.7" - -babel-loader@^8.2.2: - version "8.2.3" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.3.tgz#8986b40f1a64cacfcb4b8429320085ef68b1342d" - integrity sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw== - dependencies: - find-cache-dir "^3.3.1" - loader-utils "^1.4.0" - make-dir "^3.1.0" - schema-utils "^2.6.5" - -babel-plugin-apply-mdx-type-prop@1.6.22: - version "1.6.22" - resolved "https://registry.yarnpkg.com/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz#d216e8fd0de91de3f1478ef3231e05446bc8705b" - integrity sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ== +"ansi-align@^3.0.0": + "integrity" "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==" + "resolved" "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "string-width" "^4.1.0" + +"ansi-html-community@^0.0.8": + "integrity" "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==" + "resolved" "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz" + "version" "0.0.8" + +"ansi-regex@^5.0.1": + "integrity" "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" + "version" "5.0.1" + +"ansi-regex@^6.0.1": + "integrity" "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz" + "version" "6.0.1" + +"ansi-styles@^3.2.1": + "integrity" "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==" + "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + "version" "3.2.1" + dependencies: + "color-convert" "^1.9.0" + +"ansi-styles@^4.0.0", "ansi-styles@^4.1.0": + "integrity" "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==" + "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + "version" "4.3.0" + dependencies: + "color-convert" "^2.0.1" + +"anymatch@~3.1.2": + "integrity" "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==" + "resolved" "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz" + "version" "3.1.2" + dependencies: + "normalize-path" "^3.0.0" + "picomatch" "^2.0.4" + +"arg@^5.0.0": + "integrity" "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==" + "resolved" "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz" + "version" "5.0.1" + +"argparse@^1.0.7": + "integrity" "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==" + "resolved" "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" + "version" "1.0.10" + dependencies: + "sprintf-js" "~1.0.2" + +"argparse@^2.0.1": + "integrity" "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "resolved" "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" + "version" "2.0.1" + +"array-flatten@^2.1.0": + "integrity" "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + "resolved" "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz" + "version" "2.1.2" + +"array-flatten@1.1.1": + "integrity" "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "resolved" "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" + "version" "1.1.1" + +"array-union@^2.1.0": + "integrity" "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + "resolved" "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" + "version" "2.1.0" + +"array-union@^3.0.1": + "integrity" "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==" + "resolved" "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz" + "version" "3.0.1" + +"asap@~2.0.3": + "integrity" "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + "resolved" "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz" + "version" "2.0.6" + +"async@^2.6.2": + "integrity" "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==" + "resolved" "https://registry.npmjs.org/async/-/async-2.6.4.tgz" + "version" "2.6.4" + dependencies: + "lodash" "^4.17.14" + +"at-least-node@^1.0.0": + "integrity" "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + "resolved" "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz" + "version" "1.0.0" + +"autoprefixer@^10.3.5", "autoprefixer@^10.3.7": + "integrity" "sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==" + "resolved" "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz" + "version" "10.4.2" + dependencies: + "browserslist" "^4.19.1" + "caniuse-lite" "^1.0.30001297" + "fraction.js" "^4.1.2" + "normalize-range" "^0.1.2" + "picocolors" "^1.0.0" + "postcss-value-parser" "^4.2.0" + +"axios@^0.25.0": + "integrity" "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==" + "resolved" "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz" + "version" "0.25.0" + dependencies: + "follow-redirects" "^1.14.7" + +"babel-loader@^8.2.2": + "integrity" "sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw==" + "resolved" "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.3.tgz" + "version" "8.2.3" + dependencies: + "find-cache-dir" "^3.3.1" + "loader-utils" "^1.4.0" + "make-dir" "^3.1.0" + "schema-utils" "^2.6.5" + +"babel-plugin-apply-mdx-type-prop@1.6.22": + "integrity" "sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ==" + "resolved" "https://registry.npmjs.org/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz" + "version" "1.6.22" dependencies: "@babel/helper-plugin-utils" "7.10.4" "@mdx-js/util" "1.6.22" -babel-plugin-dynamic-import-node@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" - integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== +"babel-plugin-dynamic-import-node@^2.3.3": + "integrity" "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==" + "resolved" "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz" + "version" "2.3.3" dependencies: - object.assign "^4.1.0" + "object.assign" "^4.1.0" -babel-plugin-dynamic-import-node@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" - integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== +"babel-plugin-dynamic-import-node@2.3.0": + "integrity" "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==" + "resolved" "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz" + "version" "2.3.0" dependencies: - object.assign "^4.1.0" + "object.assign" "^4.1.0" -babel-plugin-extract-import-names@1.6.22: - version "1.6.22" - resolved "https://registry.yarnpkg.com/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz#de5f9a28eb12f3eb2578bf74472204e66d1a13dc" - integrity sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ== +"babel-plugin-extract-import-names@1.6.22": + "integrity" "sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ==" + "resolved" "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz" + "version" "1.6.22" dependencies: "@babel/helper-plugin-utils" "7.10.4" -babel-plugin-polyfill-corejs2@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz#440f1b70ccfaabc6b676d196239b138f8a2cfba5" - integrity sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w== +"babel-plugin-polyfill-corejs2@^0.3.0": + "integrity" "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==" + "resolved" "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz" + "version" "0.3.1" dependencies: "@babel/compat-data" "^7.13.11" "@babel/helper-define-polyfill-provider" "^0.3.1" - semver "^6.1.1" + "semver" "^6.1.1" -babel-plugin-polyfill-corejs3@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz#aabe4b2fa04a6e038b688c5e55d44e78cd3a5f72" - integrity sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ== +"babel-plugin-polyfill-corejs3@^0.5.0": + "integrity" "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==" + "resolved" "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz" + "version" "0.5.2" dependencies: "@babel/helper-define-polyfill-provider" "^0.3.1" - core-js-compat "^3.21.0" + "core-js-compat" "^3.21.0" -babel-plugin-polyfill-regenerator@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz#2c0678ea47c75c8cc2fbb1852278d8fb68233990" - integrity sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A== +"babel-plugin-polyfill-regenerator@^0.3.0": + "integrity" "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==" + "resolved" "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz" + "version" "0.3.1" dependencies: "@babel/helper-define-polyfill-provider" "^0.3.1" -bail@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" - integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base16@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/base16/-/base16-1.0.0.tgz#e297f60d7ec1014a7a971a39ebc8a98c0b681e70" - integrity sha1-4pf2DX7BAUp6lxo568ipjAtoHnA= - -batch@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" - integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= - -big.js@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -bluebird@^3.7.1: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - -body-parser@1.19.2: - version "1.19.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.2.tgz#4714ccd9c157d44797b8b5607d72c0b89952f26e" - integrity sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw== - dependencies: - bytes "3.1.2" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.8.1" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.9.7" - raw-body "2.4.3" - type-is "~1.6.18" - -bonjour@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" - integrity sha1-jokKGD2O6aI5OzhExpGkK897yfU= - dependencies: - array-flatten "^2.1.0" - deep-equal "^1.0.1" - dns-equal "^1.0.0" - dns-txt "^2.0.2" - multicast-dns "^6.0.1" - multicast-dns-service-types "^1.1.0" - -boolbase@^1.0.0, boolbase@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= - -boxen@^5.0.0, boxen@^5.0.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" - integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== - dependencies: - ansi-align "^3.0.0" - camelcase "^6.2.0" - chalk "^4.1.0" - cli-boxes "^2.2.1" - string-width "^4.2.2" - type-fest "^0.20.2" - widest-line "^3.1.0" - wrap-ansi "^7.0.0" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^3.0.1, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.17.5, browserslist@^4.18.1, browserslist@^4.19.1: - version "4.19.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3" - integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A== - dependencies: - caniuse-lite "^1.0.30001286" - electron-to-chromium "^1.4.17" - escalade "^3.1.1" - node-releases "^2.0.1" - picocolors "^1.0.0" - -buble-jsx-only@^0.19.8: - version "0.19.8" - resolved "https://registry.yarnpkg.com/buble-jsx-only/-/buble-jsx-only-0.19.8.tgz#6e3524aa0f1c523de32496ac9aceb9cc2b493867" - integrity sha512-7AW19pf7PrKFnGTEDzs6u9+JZqQwM1VnLS19OlqYDhXomtFFknnoQJAPHeg84RMFWAvOhYrG7harizJNwUKJsA== - dependencies: - acorn "^6.1.1" - acorn-dynamic-import "^4.0.0" - acorn-jsx "^5.0.1" - chalk "^2.4.2" - magic-string "^0.25.3" - minimist "^1.2.0" - regexpu-core "^4.5.4" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -buffer-indexof@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" - integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== - -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^1.0.2" - -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camel-case@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" - integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== - dependencies: - pascal-case "^3.1.2" - tslib "^2.0.3" - -camelcase-css@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" - integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== - -camelcase@^6.2.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -caniuse-api@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" - integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== - dependencies: - browserslist "^4.0.0" - caniuse-lite "^1.0.0" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001297: - version "1.0.30001312" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz#e11eba4b87e24d22697dae05455d5aea28550d5f" - integrity sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ== - -ccount@^1.0.0, ccount@^1.0.3: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" - integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== - -chalk@^2.0.0, chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.1.0, chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -character-entities-legacy@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" - integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== - -character-entities@^1.0.0: - version "1.2.4" - resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" - integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== - -character-reference-invalid@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" - integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== - -cheerio-select@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-1.5.0.tgz#faf3daeb31b17c5e1a9dabcee288aaf8aafa5823" - integrity sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg== - dependencies: - css-select "^4.1.3" - css-what "^5.0.1" - domelementtype "^2.2.0" - domhandler "^4.2.0" - domutils "^2.7.0" - -cheerio@^0.22.0: - version "0.22.0" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" - integrity sha1-qbqoYKP5tZWmuBsahocxIe06Jp4= - dependencies: - css-select "~1.2.0" - dom-serializer "~0.1.0" - entities "~1.1.1" - htmlparser2 "^3.9.1" - lodash.assignin "^4.0.9" - lodash.bind "^4.1.4" - lodash.defaults "^4.0.1" - lodash.filter "^4.4.0" - lodash.flatten "^4.2.0" - lodash.foreach "^4.3.0" - lodash.map "^4.4.0" - lodash.merge "^4.4.0" - lodash.pick "^4.2.1" - lodash.reduce "^4.4.0" - lodash.reject "^4.4.0" - lodash.some "^4.4.0" - -cheerio@^1.0.0-rc.10: - version "1.0.0-rc.10" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.10.tgz#2ba3dcdfcc26e7956fc1f440e61d51c643379f3e" - integrity sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw== - dependencies: - cheerio-select "^1.5.0" - dom-serializer "^1.3.2" - domhandler "^4.2.0" - htmlparser2 "^6.1.0" - parse5 "^6.0.1" - parse5-htmlparser2-tree-adapter "^6.0.1" - tslib "^2.2.0" - -chokidar@^3.4.2, chokidar@^3.5.2, chokidar@^3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" +"bail@^1.0.0": + "integrity" "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==" + "resolved" "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz" + "version" "1.0.5" + +"balanced-match@^1.0.0": + "integrity" "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "resolved" "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + "version" "1.0.2" + +"base16@^1.0.0": + "integrity" "sha1-4pf2DX7BAUp6lxo568ipjAtoHnA=" + "resolved" "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz" + "version" "1.0.0" + +"batch@0.6.1": + "integrity" "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" + "resolved" "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz" + "version" "0.6.1" + +"big.js@^5.2.2": + "integrity" "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + "resolved" "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz" + "version" "5.2.2" + +"binary-extensions@^2.0.0": + "integrity" "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + "resolved" "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" + "version" "2.2.0" + +"bluebird@^3.7.1": + "integrity" "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + "resolved" "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz" + "version" "3.7.2" + +"body-parser@1.19.2": + "integrity" "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==" + "resolved" "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz" + "version" "1.19.2" + dependencies: + "bytes" "3.1.2" + "content-type" "~1.0.4" + "debug" "2.6.9" + "depd" "~1.1.2" + "http-errors" "1.8.1" + "iconv-lite" "0.4.24" + "on-finished" "~2.3.0" + "qs" "6.9.7" + "raw-body" "2.4.3" + "type-is" "~1.6.18" + +"bonjour@^3.5.0": + "integrity" "sha1-jokKGD2O6aI5OzhExpGkK897yfU=" + "resolved" "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz" + "version" "3.5.0" + dependencies: + "array-flatten" "^2.1.0" + "deep-equal" "^1.0.1" + "dns-equal" "^1.0.0" + "dns-txt" "^2.0.2" + "multicast-dns" "^6.0.1" + "multicast-dns-service-types" "^1.1.0" + +"boolbase@^1.0.0", "boolbase@~1.0.0": + "integrity" "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + "resolved" "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz" + "version" "1.0.0" + +"boxen@^5.0.0", "boxen@^5.0.1": + "integrity" "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==" + "resolved" "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz" + "version" "5.1.2" + dependencies: + "ansi-align" "^3.0.0" + "camelcase" "^6.2.0" + "chalk" "^4.1.0" + "cli-boxes" "^2.2.1" + "string-width" "^4.2.2" + "type-fest" "^0.20.2" + "widest-line" "^3.1.0" + "wrap-ansi" "^7.0.0" + +"brace-expansion@^1.1.7": + "integrity" "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==" + "resolved" "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + "version" "1.1.11" + dependencies: + "balanced-match" "^1.0.0" + "concat-map" "0.0.1" + +"braces@^3.0.1", "braces@~3.0.2": + "integrity" "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==" + "resolved" "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "fill-range" "^7.0.1" + +"browserslist@^4.0.0", "browserslist@^4.14.5", "browserslist@^4.16.6", "browserslist@^4.18.1", "browserslist@^4.19.1", "browserslist@^4.21.3", "browserslist@>= 4.21.0": + "integrity" "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==" + "resolved" "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz" + "version" "4.21.5" + dependencies: + "caniuse-lite" "^1.0.30001449" + "electron-to-chromium" "^1.4.284" + "node-releases" "^2.0.8" + "update-browserslist-db" "^1.0.10" + +"buble-jsx-only@^0.19.8": + "integrity" "sha512-7AW19pf7PrKFnGTEDzs6u9+JZqQwM1VnLS19OlqYDhXomtFFknnoQJAPHeg84RMFWAvOhYrG7harizJNwUKJsA==" + "resolved" "https://registry.npmjs.org/buble-jsx-only/-/buble-jsx-only-0.19.8.tgz" + "version" "0.19.8" + dependencies: + "acorn" "^6.1.1" + "acorn-dynamic-import" "^4.0.0" + "acorn-jsx" "^5.0.1" + "chalk" "^2.4.2" + "magic-string" "^0.25.3" + "minimist" "^1.2.0" + "regexpu-core" "^4.5.4" + +"buffer-from@^1.0.0": + "integrity" "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "resolved" "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" + "version" "1.1.2" + +"buffer-indexof@^1.0.0": + "integrity" "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==" + "resolved" "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz" + "version" "1.1.1" + +"bytes@3.0.0": + "integrity" "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + "resolved" "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz" + "version" "3.0.0" + +"bytes@3.1.2": + "integrity" "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + "resolved" "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" + "version" "3.1.2" + +"cacheable-request@^6.0.0": + "integrity" "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==" + "resolved" "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "clone-response" "^1.0.2" + "get-stream" "^5.1.0" + "http-cache-semantics" "^4.0.0" + "keyv" "^3.0.0" + "lowercase-keys" "^2.0.0" + "normalize-url" "^4.1.0" + "responselike" "^1.0.2" + +"call-bind@^1.0.0", "call-bind@^1.0.2": + "integrity" "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==" + "resolved" "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "function-bind" "^1.1.1" + "get-intrinsic" "^1.0.2" + +"callsites@^3.0.0": + "integrity" "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + "resolved" "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + "version" "3.1.0" + +"camel-case@^4.1.2": + "integrity" "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==" + "resolved" "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "pascal-case" "^3.1.2" + "tslib" "^2.0.3" + +"camelcase-css@2.0.1": + "integrity" "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==" + "resolved" "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz" + "version" "2.0.1" + +"camelcase@^6.2.0": + "integrity" "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + "resolved" "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + "version" "6.3.0" + +"caniuse-api@^3.0.0": + "integrity" "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==" + "resolved" "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "browserslist" "^4.0.0" + "caniuse-lite" "^1.0.0" + "lodash.memoize" "^4.1.2" + "lodash.uniq" "^4.5.0" + +"caniuse-lite@^1.0.0", "caniuse-lite@^1.0.30001297", "caniuse-lite@^1.0.30001449": + "integrity" "sha512-ewtFBSfWjEmxUgNBSZItFSmVtvk9zkwkl1OfRZlKA8slltRN+/C/tuGVrF9styXkN36Yu3+SeJ1qkXxDEyNZ5w==" + "resolved" "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001466.tgz" + "version" "1.0.30001466" + +"ccount@^1.0.0", "ccount@^1.0.3": + "integrity" "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==" + "resolved" "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz" + "version" "1.1.0" + +"chalk@^2.0.0": + "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "ansi-styles" "^3.2.1" + "escape-string-regexp" "^1.0.5" + "supports-color" "^5.3.0" + +"chalk@^2.4.2": + "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "ansi-styles" "^3.2.1" + "escape-string-regexp" "^1.0.5" + "supports-color" "^5.3.0" + +"chalk@^4.1.0", "chalk@^4.1.2": + "integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "ansi-styles" "^4.1.0" + "supports-color" "^7.1.0" + +"character-entities-legacy@^1.0.0": + "integrity" "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==" + "resolved" "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz" + "version" "1.1.4" + +"character-entities@^1.0.0": + "integrity" "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==" + "resolved" "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz" + "version" "1.2.4" + +"character-reference-invalid@^1.0.0": + "integrity" "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==" + "resolved" "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz" + "version" "1.1.4" + +"cheerio-select@^1.5.0": + "integrity" "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==" + "resolved" "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz" + "version" "1.5.0" + dependencies: + "css-select" "^4.1.3" + "css-what" "^5.0.1" + "domelementtype" "^2.2.0" + "domhandler" "^4.2.0" + "domutils" "^2.7.0" + +"cheerio@^0.22.0": + "integrity" "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=" + "resolved" "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz" + "version" "0.22.0" + dependencies: + "css-select" "~1.2.0" + "dom-serializer" "~0.1.0" + "entities" "~1.1.1" + "htmlparser2" "^3.9.1" + "lodash.assignin" "^4.0.9" + "lodash.bind" "^4.1.4" + "lodash.defaults" "^4.0.1" + "lodash.filter" "^4.4.0" + "lodash.flatten" "^4.2.0" + "lodash.foreach" "^4.3.0" + "lodash.map" "^4.4.0" + "lodash.merge" "^4.4.0" + "lodash.pick" "^4.2.1" + "lodash.reduce" "^4.4.0" + "lodash.reject" "^4.4.0" + "lodash.some" "^4.4.0" + +"cheerio@^1.0.0-rc.10": + "integrity" "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==" + "resolved" "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz" + "version" "1.0.0-rc.10" + dependencies: + "cheerio-select" "^1.5.0" + "dom-serializer" "^1.3.2" + "domhandler" "^4.2.0" + "htmlparser2" "^6.1.0" + "parse5" "^6.0.1" + "parse5-htmlparser2-tree-adapter" "^6.0.1" + "tslib" "^2.2.0" + +"chokidar@^3.4.2", "chokidar@^3.5.2", "chokidar@^3.5.3": + "integrity" "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==" + "resolved" "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" + "version" "3.5.3" + dependencies: + "anymatch" "~3.1.2" + "braces" "~3.0.2" + "glob-parent" "~5.1.2" + "is-binary-path" "~2.1.0" + "is-glob" "~4.0.1" + "normalize-path" "~3.0.0" + "readdirp" "~3.6.0" optionalDependencies: - fsevents "~2.3.2" - -chrome-trace-event@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" - integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== - -ci-info@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" - integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== - -classnames@^2.2.6: - version "2.3.1" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" - integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== - -clean-css@^5.1.5, clean-css@^5.2.2: - version "5.2.4" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.2.4.tgz#982b058f8581adb2ae062520808fb2429bd487a4" - integrity sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg== - dependencies: - source-map "~0.6.0" - -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - -cli-boxes@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" - integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== - -clone-deep@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" - integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== - dependencies: - is-plain-object "^2.0.4" - kind-of "^6.0.2" - shallow-clone "^3.0.0" - -clone-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= - dependencies: - mimic-response "^1.0.0" - -clsx@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" - integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== - -collapse-white-space@^1.0.2: - version "1.0.6" - resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287" - integrity sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -colord@^2.9.1: - version "2.9.2" - resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.2.tgz#25e2bacbbaa65991422c07ea209e2089428effb1" - integrity sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ== - -colorette@^2.0.10: - version "2.0.16" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" - integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== - -combine-promises@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/combine-promises/-/combine-promises-1.1.0.tgz#72db90743c0ca7aab7d0d8d2052fd7b0f674de71" - integrity sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg== - -comma-separated-tokens@^1.0.0: - version "1.0.8" - resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" - integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== - -commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -commander@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" - integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== - -commander@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== - -commander@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" - integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= - -compressible@~2.0.16: - version "2.0.18" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" - integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== - dependencies: - mime-db ">= 1.43.0 < 2" - -compression@^1.7.4: - version "1.7.4" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" - integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== - dependencies: - accepts "~1.3.5" - bytes "3.0.0" - compressible "~2.0.16" - debug "2.6.9" - on-headers "~1.0.2" - safe-buffer "5.1.2" - vary "~1.1.2" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -configstore@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" - integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== - dependencies: - dot-prop "^5.2.0" - graceful-fs "^4.1.2" - make-dir "^3.0.0" - unique-string "^2.0.0" - write-file-atomic "^3.0.0" - xdg-basedir "^4.0.0" - -connect-history-api-fallback@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" - integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== - -consola@^2.15.3: - version "2.15.3" - resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.3.tgz#2e11f98d6a4be71ff72e0bdf07bd23e12cb61550" - integrity sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw== - -content-disposition@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= - -content-disposition@0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" - integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== - dependencies: - safe-buffer "5.2.1" - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -convert-source-map@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" - integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== - dependencies: - safe-buffer "~5.1.1" - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" - integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== - -copy-text-to-clipboard@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz#8cbf8f90e0a47f12e4a24743736265d157bce69c" - integrity sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q== - -copy-webpack-plugin@^10.2.0: - version "10.2.4" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz#6c854be3fdaae22025da34b9112ccf81c63308fe" - integrity sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg== - dependencies: - fast-glob "^3.2.7" - glob-parent "^6.0.1" - globby "^12.0.2" - normalize-path "^3.0.0" - schema-utils "^4.0.0" - serialize-javascript "^6.0.0" - -core-js-compat@^3.20.2, core-js-compat@^3.21.0: - version "3.21.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.21.1.tgz#cac369f67c8d134ff8f9bd1623e3bc2c42068c82" - integrity sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g== - dependencies: - browserslist "^4.19.1" - semver "7.0.0" - -core-js-pure@^3.20.2: - version "3.21.1" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.21.1.tgz#8c4d1e78839f5f46208de7230cebfb72bc3bdb51" - integrity sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ== - -core-js@^3.18.0: - version "3.21.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.21.1.tgz#f2e0ddc1fc43da6f904706e8e955bc19d06a0d94" - integrity sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig== - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -cosmiconfig@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" - integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== + "fsevents" "~2.3.2" + +"chrome-trace-event@^1.0.2": + "integrity" "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==" + "resolved" "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz" + "version" "1.0.3" + +"ci-info@^2.0.0": + "integrity" "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + "resolved" "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz" + "version" "2.0.0" + +"classnames@^2.2.6": + "integrity" "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" + "resolved" "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz" + "version" "2.3.1" + +"clean-css@^5.1.5", "clean-css@^5.2.2": + "integrity" "sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg==" + "resolved" "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz" + "version" "5.2.4" + dependencies: + "source-map" "~0.6.0" + +"clean-stack@^2.0.0": + "integrity" "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + "resolved" "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz" + "version" "2.2.0" + +"cli-boxes@^2.2.1": + "integrity" "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==" + "resolved" "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz" + "version" "2.2.1" + +"clone-deep@^4.0.1": + "integrity" "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==" + "resolved" "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz" + "version" "4.0.1" + dependencies: + "is-plain-object" "^2.0.4" + "kind-of" "^6.0.2" + "shallow-clone" "^3.0.0" + +"clone-response@^1.0.2": + "integrity" "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=" + "resolved" "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "mimic-response" "^1.0.0" + +"clsx@^1.1.1": + "integrity" "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==" + "resolved" "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz" + "version" "1.1.1" + +"collapse-white-space@^1.0.2": + "integrity" "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==" + "resolved" "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz" + "version" "1.0.6" + +"color-convert@^1.9.0": + "integrity" "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==" + "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + "version" "1.9.3" + dependencies: + "color-name" "1.1.3" + +"color-convert@^2.0.1": + "integrity" "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==" + "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "color-name" "~1.1.4" + +"color-name@~1.1.4": + "integrity" "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + "version" "1.1.4" + +"color-name@1.1.3": + "integrity" "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + "version" "1.1.3" + +"colord@^2.9.1": + "integrity" "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==" + "resolved" "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz" + "version" "2.9.2" + +"colorette@^2.0.10": + "integrity" "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==" + "resolved" "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz" + "version" "2.0.16" + +"combine-promises@^1.1.0": + "integrity" "sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg==" + "resolved" "https://registry.npmjs.org/combine-promises/-/combine-promises-1.1.0.tgz" + "version" "1.1.0" + +"comma-separated-tokens@^1.0.0": + "integrity" "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==" + "resolved" "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz" + "version" "1.0.8" + +"commander@^2.20.0": + "integrity" "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "resolved" "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" + "version" "2.20.3" + +"commander@^5.1.0": + "integrity" "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" + "resolved" "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz" + "version" "5.1.0" + +"commander@^7.2.0": + "integrity" "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + "resolved" "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz" + "version" "7.2.0" + +"commander@^8.3.0": + "integrity" "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==" + "resolved" "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz" + "version" "8.3.0" + +"commondir@^1.0.1": + "integrity" "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + "resolved" "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" + "version" "1.0.1" + +"compressible@~2.0.16": + "integrity" "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==" + "resolved" "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz" + "version" "2.0.18" + dependencies: + "mime-db" ">= 1.43.0 < 2" + +"compression@^1.7.4": + "integrity" "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==" + "resolved" "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz" + "version" "1.7.4" + dependencies: + "accepts" "~1.3.5" + "bytes" "3.0.0" + "compressible" "~2.0.16" + "debug" "2.6.9" + "on-headers" "~1.0.2" + "safe-buffer" "5.1.2" + "vary" "~1.1.2" + +"concat-map@0.0.1": + "integrity" "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "resolved" "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + "version" "0.0.1" + +"configstore@^5.0.1": + "integrity" "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==" + "resolved" "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "dot-prop" "^5.2.0" + "graceful-fs" "^4.1.2" + "make-dir" "^3.0.0" + "unique-string" "^2.0.0" + "write-file-atomic" "^3.0.0" + "xdg-basedir" "^4.0.0" + +"connect-history-api-fallback@^1.6.0": + "integrity" "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==" + "resolved" "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz" + "version" "1.6.0" + +"consola@^2.15.3": + "integrity" "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" + "resolved" "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz" + "version" "2.15.3" + +"content-disposition@0.5.2": + "integrity" "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + "resolved" "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz" + "version" "0.5.2" + +"content-disposition@0.5.4": + "integrity" "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==" + "resolved" "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz" + "version" "0.5.4" + dependencies: + "safe-buffer" "5.2.1" + +"content-type@~1.0.4": + "integrity" "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + "resolved" "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz" + "version" "1.0.4" + +"convert-source-map@^1.7.0": + "integrity" "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==" + "resolved" "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz" + "version" "1.8.0" + dependencies: + "safe-buffer" "~5.1.1" + +"cookie-signature@1.0.6": + "integrity" "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "resolved" "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + "version" "1.0.6" + +"cookie@0.4.2": + "integrity" "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + "resolved" "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz" + "version" "0.4.2" + +"copy-text-to-clipboard@^3.0.1": + "integrity" "sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q==" + "resolved" "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz" + "version" "3.0.1" + +"copy-webpack-plugin@^10.2.0": + "integrity" "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==" + "resolved" "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz" + "version" "10.2.4" + dependencies: + "fast-glob" "^3.2.7" + "glob-parent" "^6.0.1" + "globby" "^12.0.2" + "normalize-path" "^3.0.0" + "schema-utils" "^4.0.0" + "serialize-javascript" "^6.0.0" + +"core-js-compat@^3.20.2", "core-js-compat@^3.21.0": + "integrity" "sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g==" + "resolved" "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.21.1.tgz" + "version" "3.21.1" + dependencies: + "browserslist" "^4.19.1" + "semver" "7.0.0" + +"core-js-pure@^3.20.2": + "integrity" "sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ==" + "resolved" "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.21.1.tgz" + "version" "3.21.1" + +"core-js@^3.18.0": + "integrity" "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==" + "resolved" "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz" + "version" "3.21.1" + +"core-util-is@~1.0.0": + "integrity" "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "resolved" "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" + "version" "1.0.3" + +"cosmiconfig@^6.0.0": + "integrity" "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==" + "resolved" "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz" + "version" "6.0.0" dependencies: "@types/parse-json" "^4.0.0" - import-fresh "^3.1.0" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.7.2" + "import-fresh" "^3.1.0" + "parse-json" "^5.0.0" + "path-type" "^4.0.0" + "yaml" "^1.7.2" -cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" - integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== +"cosmiconfig@^7.0.0", "cosmiconfig@^7.0.1": + "integrity" "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==" + "resolved" "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz" + "version" "7.0.1" dependencies: "@types/parse-json" "^4.0.0" - import-fresh "^3.2.1" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.10.0" - -cross-fetch@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" - integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== - dependencies: - node-fetch "2.6.7" - -cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -crypto-random-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" - integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== - -css-declaration-sorter@^6.0.3: - version "6.1.4" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz#b9bfb4ed9a41f8dcca9bf7184d849ea94a8294b4" - integrity sha512-lpfkqS0fctcmZotJGhnxkIyJWvBXgpyi2wsFd4J8VB7wzyrT6Ch/3Q+FMNJpjK4gu1+GN5khOnpU2ZVKrLbhCw== - dependencies: - timsort "^0.3.0" - -css-loader@^6.5.1: - version "6.6.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.6.0.tgz#c792ad5510bd1712618b49381bd0310574fafbd3" - integrity sha512-FK7H2lisOixPT406s5gZM1S3l8GrfhEBT3ZiL2UX1Ng1XWs0y2GPllz/OTyvbaHe12VgQrIXIzuEGVlbUhodqg== - dependencies: - icss-utils "^5.1.0" - postcss "^8.4.5" - postcss-modules-extract-imports "^3.0.0" - postcss-modules-local-by-default "^4.0.0" - postcss-modules-scope "^3.0.0" - postcss-modules-values "^4.0.0" - postcss-value-parser "^4.2.0" - semver "^7.3.5" - -css-minimizer-webpack-plugin@^3.3.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz#ab78f781ced9181992fe7b6e4f3422e76429878f" - integrity sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q== - dependencies: - cssnano "^5.0.6" - jest-worker "^27.0.2" - postcss "^8.3.5" - schema-utils "^4.0.0" - serialize-javascript "^6.0.0" - source-map "^0.6.1" - -css-select@^4.1.3: - version "4.2.1" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.2.1.tgz#9e665d6ae4c7f9d65dbe69d0316e3221fb274cdd" - integrity sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ== - dependencies: - boolbase "^1.0.0" - css-what "^5.1.0" - domhandler "^4.3.0" - domutils "^2.8.0" - nth-check "^2.0.1" - -css-select@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" - integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= - dependencies: - boolbase "~1.0.0" - css-what "2.1" - domutils "1.5.1" - nth-check "~1.0.1" - -css-tree@^1.1.2, css-tree@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" - integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== - dependencies: - mdn-data "2.0.14" - source-map "^0.6.1" - -css-what@2.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" - integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== - -css-what@^5.0.1, css-what@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" - integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== - -cssesc@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" - integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== - -cssnano-preset-advanced@^5.1.4: - version "5.1.12" - resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-5.1.12.tgz#11f5b0c4e3c32bcfd475465a283fa14dec8df972" - integrity sha512-5WWV9mbqVNwH4nRjs5UbhNl7eKo+16eYNzGogmz0Sa6iqWUeLdN8oo83WuTTqz5vjEKhTbRM5oX6WV1i6ees6g== - dependencies: - autoprefixer "^10.3.7" - cssnano-preset-default "^5.1.12" - postcss-discard-unused "^5.0.3" - postcss-merge-idents "^5.0.3" - postcss-reduce-idents "^5.0.3" - postcss-zindex "^5.0.2" - -cssnano-preset-default@^5.1.12: - version "5.1.12" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.1.12.tgz#64e2ad8e27a279e1413d2d2383ef89a41c909be9" - integrity sha512-rO/JZYyjW1QNkWBxMGV28DW7d98UDLaF759frhli58QFehZ+D/LSmwQ2z/ylBAe2hUlsIWTq6NYGfQPq65EF9w== - dependencies: - css-declaration-sorter "^6.0.3" - cssnano-utils "^3.0.2" - postcss-calc "^8.2.0" - postcss-colormin "^5.2.5" - postcss-convert-values "^5.0.4" - postcss-discard-comments "^5.0.3" - postcss-discard-duplicates "^5.0.3" - postcss-discard-empty "^5.0.3" - postcss-discard-overridden "^5.0.4" - postcss-merge-longhand "^5.0.6" - postcss-merge-rules "^5.0.6" - postcss-minify-font-values "^5.0.4" - postcss-minify-gradients "^5.0.6" - postcss-minify-params "^5.0.5" - postcss-minify-selectors "^5.1.3" - postcss-normalize-charset "^5.0.3" - postcss-normalize-display-values "^5.0.3" - postcss-normalize-positions "^5.0.4" - postcss-normalize-repeat-style "^5.0.4" - postcss-normalize-string "^5.0.4" - postcss-normalize-timing-functions "^5.0.3" - postcss-normalize-unicode "^5.0.4" - postcss-normalize-url "^5.0.5" - postcss-normalize-whitespace "^5.0.4" - postcss-ordered-values "^5.0.5" - postcss-reduce-initial "^5.0.3" - postcss-reduce-transforms "^5.0.4" - postcss-svgo "^5.0.4" - postcss-unique-selectors "^5.0.4" - -cssnano-utils@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.0.2.tgz#d82b4991a27ba6fec644b39bab35fe027137f516" - integrity sha512-KhprijuQv2sP4kT92sSQwhlK3SJTbDIsxcfIEySB0O+3m9esFOai7dP9bMx5enHAh2MwarVIcnwiWoOm01RIbQ== - -cssnano@^5.0.6, cssnano@^5.0.8: - version "5.0.17" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.0.17.tgz#ff45713c05cfc780a1aeb3e663b6f224d091cabf" - integrity sha512-fmjLP7k8kL18xSspeXTzRhaFtRI7DL9b8IcXR80JgtnWBpvAzHT7sCR/6qdn0tnxIaINUN6OEQu83wF57Gs3Xw== - dependencies: - cssnano-preset-default "^5.1.12" - lilconfig "^2.0.3" - yaml "^1.10.2" - -csso@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" - integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== - dependencies: - css-tree "^1.1.2" - -csstype@^3.0.2: - version "3.0.10" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.10.tgz#2ad3a7bed70f35b965707c092e5f30b327c290e5" - integrity sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA== - -debug@2.6.9, debug@^2.6.0: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^3.1.1: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -debug@^4.1.0, debug@^4.1.1: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== - dependencies: - ms "2.1.2" - -decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= - dependencies: - mimic-response "^1.0.0" - -deep-equal@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" - integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== - dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" - object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -deepmerge@^1.3.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-1.5.2.tgz#10499d868844cdad4fee0842df8c7f6f0c95a753" - integrity sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ== - -deepmerge@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" - integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== - -default-gateway@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" - integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== - dependencies: - execa "^5.0.0" - -defer-to-connect@^1.0.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" - integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== - -define-lazy-prop@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" - integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== - -define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -del@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/del/-/del-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952" - integrity sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ== - dependencies: - globby "^11.0.1" - graceful-fs "^4.2.4" - is-glob "^4.0.1" - is-path-cwd "^2.2.0" - is-path-inside "^3.0.2" - p-map "^4.0.0" - rimraf "^3.0.2" - slash "^3.0.0" - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - -detab@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/detab/-/detab-2.0.4.tgz#b927892069aff405fbb9a186fe97a44a92a94b43" - integrity sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g== - dependencies: - repeat-string "^1.5.4" - -detect-node@^2.0.4: - version "2.1.0" - resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" - integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== - -detect-port-alt@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/detect-port-alt/-/detect-port-alt-1.1.6.tgz#24707deabe932d4a3cf621302027c2b266568275" - integrity sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q== - dependencies: - address "^1.0.1" - debug "^2.6.0" - -detect-port@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.3.0.tgz#d9c40e9accadd4df5cac6a782aefd014d573d1f1" - integrity sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ== - dependencies: - address "^1.0.1" - debug "^2.6.0" - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -dns-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" - integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= - -dns-packet@^1.3.1: - version "1.3.4" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f" - integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA== - dependencies: - ip "^1.1.0" - safe-buffer "^5.0.1" - -dns-txt@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" - integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY= - dependencies: - buffer-indexof "^1.0.0" - -dom-converter@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" - integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== - dependencies: - utila "~0.4" - -dom-serializer@0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" - integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== - dependencies: - domelementtype "^2.0.1" - entities "^2.0.0" - -dom-serializer@^1.0.1, dom-serializer@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" - integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== - dependencies: - domelementtype "^2.0.1" - domhandler "^4.2.0" - entities "^2.0.0" - -dom-serializer@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" - integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== - dependencies: - domelementtype "^1.3.0" - entities "^1.1.1" - -domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== - -domelementtype@^2.0.1, domelementtype@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" - integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== - -domhandler@^2.3.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" - integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== - dependencies: - domelementtype "1" - -domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.0.tgz#16c658c626cf966967e306f966b431f77d4a5626" - integrity sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g== - dependencies: - domelementtype "^2.2.0" - -domutils@1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" - integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= - dependencies: - dom-serializer "0" - domelementtype "1" - -domutils@^1.5.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== - dependencies: - dom-serializer "0" - domelementtype "1" - -domutils@^2.5.2, domutils@^2.7.0, domutils@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" - integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== - dependencies: - dom-serializer "^1.0.1" - domelementtype "^2.2.0" - domhandler "^4.2.0" - -dot-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" - integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - -dot-prop@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" - integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== - dependencies: - is-obj "^2.0.0" - -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= - -duplexer@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" - integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -electron-to-chromium@^1.4.17: - version "1.4.71" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.71.tgz#17056914465da0890ce00351a3b946fd4cd51ff6" - integrity sha512-Hk61vXXKRb2cd3znPE9F+2pLWdIOmP7GjiTj45y6L3W/lO+hSnUSUhq+6lEaERWBdZOHbk2s3YV5c9xVl3boVw== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emojis-list@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" - integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== - -emoticon@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/emoticon/-/emoticon-3.2.0.tgz#c008ca7d7620fac742fe1bf4af8ff8fed154ae7f" - integrity sha512-SNujglcLTTg+lDAcApPNgEdudaqQFiAbJCqzjNxJkvN9vAwCGi0uu8IUVvx+f16h+V44KCY6Y2yboroc9pilHg== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -enhanced-resolve@^5.8.3: - version "5.9.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.0.tgz#49ac24953ac8452ed8fed2ef1340fc8e043667ee" - integrity sha512-weDYmzbBygL7HzGGS26M3hGQx68vehdEg6VUmqSOaFzXExFqlnKuSvsEJCVGQHScS8CQMbrAqftT+AzzHNt/YA== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -entities@^1.1.1, entities@~1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" - integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== - -entities@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" - integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== - -entities@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4" - integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-module-lexer@^0.9.0: - version "0.9.3" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" - integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-goat@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" - integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== - -escape-html@^1.0.3, escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-scope@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -eta@^1.12.3: - version "1.12.3" - resolved "https://registry.yarnpkg.com/eta/-/eta-1.12.3.tgz#2982d08adfbef39f9fa50e2fbd42d7337e7338b1" - integrity sha512-qHixwbDLtekO/d51Yr4glcaUJCIjGVJyTzuqV4GPlgZo1YpgOKG+avQynErZIYrfM6JIJdtiG2Kox8tbb+DoGg== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - -eval@^0.1.4: - version "0.1.6" - resolved "https://registry.yarnpkg.com/eval/-/eval-0.1.6.tgz#9620d7d8c85515e97e6b47c5814f46ae381cb3cc" - integrity sha512-o0XUw+5OGkXw4pJZzQoXUk+H87DHuC+7ZE//oSrRGtatTmr12oTnLfg6QOq9DyTt0c/p4TwzgmkKrBzWTSizyQ== - dependencies: - require-like ">= 0.1.1" - -eventemitter3@^4.0.0: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -events@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -execa@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - -express@^4.17.1: - version "4.17.3" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.3.tgz#f6c7302194a4fb54271b73a1fe7a06478c8f85a1" - integrity sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg== - dependencies: - accepts "~1.3.8" - array-flatten "1.1.1" - body-parser "1.19.2" - content-disposition "0.5.4" - content-type "~1.0.4" - cookie "0.4.2" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "~1.1.2" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.7" - qs "6.9.7" - range-parser "~1.2.1" - safe-buffer "5.2.1" - send "0.17.2" - serve-static "1.14.2" - setprototypeof "1.2.0" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-glob@^3.2.7, fast-glob@^3.2.9: - version "3.2.11" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" - integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== + "import-fresh" "^3.2.1" + "parse-json" "^5.0.0" + "path-type" "^4.0.0" + "yaml" "^1.10.0" + +"cross-fetch@^3.1.5": + "integrity" "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==" + "resolved" "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz" + "version" "3.1.5" + dependencies: + "node-fetch" "2.6.7" + +"cross-spawn@^7.0.3": + "integrity" "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==" + "resolved" "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" + "version" "7.0.3" + dependencies: + "path-key" "^3.1.0" + "shebang-command" "^2.0.0" + "which" "^2.0.1" + +"crypto-random-string@^2.0.0": + "integrity" "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" + "resolved" "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz" + "version" "2.0.0" + +"css-declaration-sorter@^6.0.3": + "integrity" "sha512-lpfkqS0fctcmZotJGhnxkIyJWvBXgpyi2wsFd4J8VB7wzyrT6Ch/3Q+FMNJpjK4gu1+GN5khOnpU2ZVKrLbhCw==" + "resolved" "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz" + "version" "6.1.4" + dependencies: + "timsort" "^0.3.0" + +"css-loader@^6.5.1": + "integrity" "sha512-FK7H2lisOixPT406s5gZM1S3l8GrfhEBT3ZiL2UX1Ng1XWs0y2GPllz/OTyvbaHe12VgQrIXIzuEGVlbUhodqg==" + "resolved" "https://registry.npmjs.org/css-loader/-/css-loader-6.6.0.tgz" + "version" "6.6.0" + dependencies: + "icss-utils" "^5.1.0" + "postcss" "^8.4.5" + "postcss-modules-extract-imports" "^3.0.0" + "postcss-modules-local-by-default" "^4.0.0" + "postcss-modules-scope" "^3.0.0" + "postcss-modules-values" "^4.0.0" + "postcss-value-parser" "^4.2.0" + "semver" "^7.3.5" + +"css-minimizer-webpack-plugin@^3.3.1": + "integrity" "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==" + "resolved" "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz" + "version" "3.4.1" + dependencies: + "cssnano" "^5.0.6" + "jest-worker" "^27.0.2" + "postcss" "^8.3.5" + "schema-utils" "^4.0.0" + "serialize-javascript" "^6.0.0" + "source-map" "^0.6.1" + +"css-select@^4.1.3": + "integrity" "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==" + "resolved" "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz" + "version" "4.2.1" + dependencies: + "boolbase" "^1.0.0" + "css-what" "^5.1.0" + "domhandler" "^4.3.0" + "domutils" "^2.8.0" + "nth-check" "^2.0.1" + +"css-select@~1.2.0": + "integrity" "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=" + "resolved" "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "boolbase" "~1.0.0" + "css-what" "2.1" + "domutils" "1.5.1" + "nth-check" "~1.0.1" + +"css-tree@^1.1.2", "css-tree@^1.1.3": + "integrity" "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==" + "resolved" "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz" + "version" "1.1.3" + dependencies: + "mdn-data" "2.0.14" + "source-map" "^0.6.1" + +"css-what@^5.0.1", "css-what@^5.1.0": + "integrity" "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==" + "resolved" "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz" + "version" "5.1.0" + +"css-what@2.1": + "integrity" "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" + "resolved" "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz" + "version" "2.1.3" + +"cssesc@^3.0.0": + "integrity" "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" + "resolved" "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz" + "version" "3.0.0" + +"cssnano-preset-advanced@^5.1.4": + "integrity" "sha512-5WWV9mbqVNwH4nRjs5UbhNl7eKo+16eYNzGogmz0Sa6iqWUeLdN8oo83WuTTqz5vjEKhTbRM5oX6WV1i6ees6g==" + "resolved" "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-5.1.12.tgz" + "version" "5.1.12" + dependencies: + "autoprefixer" "^10.3.7" + "cssnano-preset-default" "^5.1.12" + "postcss-discard-unused" "^5.0.3" + "postcss-merge-idents" "^5.0.3" + "postcss-reduce-idents" "^5.0.3" + "postcss-zindex" "^5.0.2" + +"cssnano-preset-default@^5.1.12": + "integrity" "sha512-rO/JZYyjW1QNkWBxMGV28DW7d98UDLaF759frhli58QFehZ+D/LSmwQ2z/ylBAe2hUlsIWTq6NYGfQPq65EF9w==" + "resolved" "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.1.12.tgz" + "version" "5.1.12" + dependencies: + "css-declaration-sorter" "^6.0.3" + "cssnano-utils" "^3.0.2" + "postcss-calc" "^8.2.0" + "postcss-colormin" "^5.2.5" + "postcss-convert-values" "^5.0.4" + "postcss-discard-comments" "^5.0.3" + "postcss-discard-duplicates" "^5.0.3" + "postcss-discard-empty" "^5.0.3" + "postcss-discard-overridden" "^5.0.4" + "postcss-merge-longhand" "^5.0.6" + "postcss-merge-rules" "^5.0.6" + "postcss-minify-font-values" "^5.0.4" + "postcss-minify-gradients" "^5.0.6" + "postcss-minify-params" "^5.0.5" + "postcss-minify-selectors" "^5.1.3" + "postcss-normalize-charset" "^5.0.3" + "postcss-normalize-display-values" "^5.0.3" + "postcss-normalize-positions" "^5.0.4" + "postcss-normalize-repeat-style" "^5.0.4" + "postcss-normalize-string" "^5.0.4" + "postcss-normalize-timing-functions" "^5.0.3" + "postcss-normalize-unicode" "^5.0.4" + "postcss-normalize-url" "^5.0.5" + "postcss-normalize-whitespace" "^5.0.4" + "postcss-ordered-values" "^5.0.5" + "postcss-reduce-initial" "^5.0.3" + "postcss-reduce-transforms" "^5.0.4" + "postcss-svgo" "^5.0.4" + "postcss-unique-selectors" "^5.0.4" + +"cssnano-utils@^3.0.2": + "integrity" "sha512-KhprijuQv2sP4kT92sSQwhlK3SJTbDIsxcfIEySB0O+3m9esFOai7dP9bMx5enHAh2MwarVIcnwiWoOm01RIbQ==" + "resolved" "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.0.2.tgz" + "version" "3.0.2" + +"cssnano@^5.0.6", "cssnano@^5.0.8": + "integrity" "sha512-fmjLP7k8kL18xSspeXTzRhaFtRI7DL9b8IcXR80JgtnWBpvAzHT7sCR/6qdn0tnxIaINUN6OEQu83wF57Gs3Xw==" + "resolved" "https://registry.npmjs.org/cssnano/-/cssnano-5.0.17.tgz" + "version" "5.0.17" + dependencies: + "cssnano-preset-default" "^5.1.12" + "lilconfig" "^2.0.3" + "yaml" "^1.10.2" + +"csso@^4.2.0": + "integrity" "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==" + "resolved" "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz" + "version" "4.2.0" + dependencies: + "css-tree" "^1.1.2" + +"csstype@^3.0.2": + "integrity" "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==" + "resolved" "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz" + "version" "3.0.10" + +"debug@^2.6.0", "debug@2.6.9": + "integrity" "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" + "resolved" "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + "version" "2.6.9" + dependencies: + "ms" "2.0.0" + +"debug@^3.1.1": + "integrity" "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==" + "resolved" "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" + "version" "3.2.7" + dependencies: + "ms" "^2.1.1" + +"debug@^4.1.0": + "integrity" "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==" + "resolved" "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz" + "version" "4.3.3" + dependencies: + "ms" "2.1.2" + +"debug@^4.1.1": + "integrity" "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==" + "resolved" "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz" + "version" "4.3.3" + dependencies: + "ms" "2.1.2" + +"decompress-response@^3.3.0": + "integrity" "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=" + "resolved" "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz" + "version" "3.3.0" + dependencies: + "mimic-response" "^1.0.0" + +"deep-equal@^1.0.1": + "integrity" "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==" + "resolved" "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "is-arguments" "^1.0.4" + "is-date-object" "^1.0.1" + "is-regex" "^1.0.4" + "object-is" "^1.0.1" + "object-keys" "^1.1.1" + "regexp.prototype.flags" "^1.2.0" + +"deep-extend@^0.6.0": + "integrity" "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + "resolved" "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz" + "version" "0.6.0" + +"deepmerge@^1.3.2": + "integrity" "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==" + "resolved" "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz" + "version" "1.5.2" + +"deepmerge@^4.2.2": + "integrity" "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" + "resolved" "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz" + "version" "4.2.2" + +"default-gateway@^6.0.3": + "integrity" "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==" + "resolved" "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz" + "version" "6.0.3" + dependencies: + "execa" "^5.0.0" + +"defer-to-connect@^1.0.1": + "integrity" "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + "resolved" "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz" + "version" "1.1.3" + +"define-lazy-prop@^2.0.0": + "integrity" "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" + "resolved" "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz" + "version" "2.0.0" + +"define-properties@^1.1.3": + "integrity" "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==" + "resolved" "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz" + "version" "1.1.3" + dependencies: + "object-keys" "^1.0.12" + +"del@^6.0.0": + "integrity" "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==" + "resolved" "https://registry.npmjs.org/del/-/del-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "globby" "^11.0.1" + "graceful-fs" "^4.2.4" + "is-glob" "^4.0.1" + "is-path-cwd" "^2.2.0" + "is-path-inside" "^3.0.2" + "p-map" "^4.0.0" + "rimraf" "^3.0.2" + "slash" "^3.0.0" + +"depd@~1.1.2": + "integrity" "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "resolved" "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" + "version" "1.1.2" + +"destroy@~1.0.4": + "integrity" "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "resolved" "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" + "version" "1.0.4" + +"detab@2.0.4": + "integrity" "sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g==" + "resolved" "https://registry.npmjs.org/detab/-/detab-2.0.4.tgz" + "version" "2.0.4" + dependencies: + "repeat-string" "^1.5.4" + +"detect-node@^2.0.4": + "integrity" "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + "resolved" "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz" + "version" "2.1.0" + +"detect-port-alt@^1.1.6": + "integrity" "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==" + "resolved" "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz" + "version" "1.1.6" + dependencies: + "address" "^1.0.1" + "debug" "^2.6.0" + +"detect-port@^1.3.0": + "integrity" "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==" + "resolved" "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz" + "version" "1.3.0" + dependencies: + "address" "^1.0.1" + "debug" "^2.6.0" + +"dir-glob@^3.0.1": + "integrity" "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==" + "resolved" "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "path-type" "^4.0.0" + +"dns-equal@^1.0.0": + "integrity" "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" + "resolved" "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz" + "version" "1.0.0" + +"dns-packet@^1.3.1": + "integrity" "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==" + "resolved" "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz" + "version" "1.3.4" + dependencies: + "ip" "^1.1.0" + "safe-buffer" "^5.0.1" + +"dns-txt@^2.0.2": + "integrity" "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=" + "resolved" "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "buffer-indexof" "^1.0.0" + +"dom-converter@^0.2.0": + "integrity" "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==" + "resolved" "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz" + "version" "0.2.0" + dependencies: + "utila" "~0.4" + +"dom-serializer@^1.0.1": + "integrity" "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==" + "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz" + "version" "1.3.2" + dependencies: + "domelementtype" "^2.0.1" + "domhandler" "^4.2.0" + "entities" "^2.0.0" + +"dom-serializer@^1.3.2": + "integrity" "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==" + "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz" + "version" "1.3.2" + dependencies: + "domelementtype" "^2.0.1" + "domhandler" "^4.2.0" + "entities" "^2.0.0" + +"dom-serializer@~0.1.0": + "integrity" "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==" + "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz" + "version" "0.1.1" + dependencies: + "domelementtype" "^1.3.0" + "entities" "^1.1.1" + +"dom-serializer@0": + "integrity" "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==" + "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz" + "version" "0.2.2" + dependencies: + "domelementtype" "^2.0.1" + "entities" "^2.0.0" + +"domelementtype@^1.3.0", "domelementtype@^1.3.1", "domelementtype@1": + "integrity" "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + "resolved" "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz" + "version" "1.3.1" + +"domelementtype@^2.0.1", "domelementtype@^2.2.0": + "integrity" "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" + "resolved" "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz" + "version" "2.2.0" + +"domhandler@^2.3.0": + "integrity" "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==" + "resolved" "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "domelementtype" "1" + +"domhandler@^4.0.0", "domhandler@^4.2.0", "domhandler@^4.3.0": + "integrity" "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==" + "resolved" "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz" + "version" "4.3.0" + dependencies: + "domelementtype" "^2.2.0" + +"domutils@^1.5.1": + "integrity" "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==" + "resolved" "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz" + "version" "1.7.0" + dependencies: + "dom-serializer" "0" + "domelementtype" "1" + +"domutils@^2.5.2", "domutils@^2.7.0", "domutils@^2.8.0": + "integrity" "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==" + "resolved" "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz" + "version" "2.8.0" + dependencies: + "dom-serializer" "^1.0.1" + "domelementtype" "^2.2.0" + "domhandler" "^4.2.0" + +"domutils@1.5.1": + "integrity" "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=" + "resolved" "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz" + "version" "1.5.1" + dependencies: + "dom-serializer" "0" + "domelementtype" "1" + +"dot-case@^3.0.4": + "integrity" "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==" + "resolved" "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "no-case" "^3.0.4" + "tslib" "^2.0.3" + +"dot-prop@^5.2.0": + "integrity" "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==" + "resolved" "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz" + "version" "5.3.0" + dependencies: + "is-obj" "^2.0.0" + +"duplexer@^0.1.2": + "integrity" "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + "resolved" "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz" + "version" "0.1.2" + +"duplexer3@^0.1.4": + "integrity" "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + "resolved" "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz" + "version" "0.1.4" + +"ee-first@1.1.1": + "integrity" "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "resolved" "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + "version" "1.1.1" + +"electron-to-chromium@^1.4.284": + "integrity" "sha512-DE9tTy2PNmy1v55AZAO542ui+MLC2cvINMK4P2LXGsJdput/ThVG9t+QGecPuAZZSgC8XoI+Jh9M1OG9IoNSCw==" + "resolved" "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.328.tgz" + "version" "1.4.328" + +"emoji-regex@^8.0.0": + "integrity" "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "resolved" "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + "version" "8.0.0" + +"emojis-list@^3.0.0": + "integrity" "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" + "resolved" "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz" + "version" "3.0.0" + +"emoticon@^3.2.0": + "integrity" "sha512-SNujglcLTTg+lDAcApPNgEdudaqQFiAbJCqzjNxJkvN9vAwCGi0uu8IUVvx+f16h+V44KCY6Y2yboroc9pilHg==" + "resolved" "https://registry.npmjs.org/emoticon/-/emoticon-3.2.0.tgz" + "version" "3.2.0" + +"encodeurl@~1.0.2": + "integrity" "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "resolved" "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" + "version" "1.0.2" + +"end-of-stream@^1.1.0": + "integrity" "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==" + "resolved" "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" + "version" "1.4.4" + dependencies: + "once" "^1.4.0" + +"enhanced-resolve@^5.8.3": + "integrity" "sha512-weDYmzbBygL7HzGGS26M3hGQx68vehdEg6VUmqSOaFzXExFqlnKuSvsEJCVGQHScS8CQMbrAqftT+AzzHNt/YA==" + "resolved" "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.0.tgz" + "version" "5.9.0" + dependencies: + "graceful-fs" "^4.2.4" + "tapable" "^2.2.0" + +"entities@^1.1.1", "entities@~1.1.1": + "integrity" "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + "resolved" "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz" + "version" "1.1.2" + +"entities@^2.0.0": + "integrity" "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + "resolved" "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz" + "version" "2.2.0" + +"entities@^3.0.1": + "integrity" "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==" + "resolved" "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz" + "version" "3.0.1" + +"error-ex@^1.3.1": + "integrity" "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==" + "resolved" "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" + "version" "1.3.2" + dependencies: + "is-arrayish" "^0.2.1" + +"es-module-lexer@^0.9.0": + "integrity" "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==" + "resolved" "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz" + "version" "0.9.3" + +"escalade@^3.1.1": + "integrity" "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + "resolved" "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" + "version" "3.1.1" + +"escape-goat@^2.0.0": + "integrity" "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==" + "resolved" "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz" + "version" "2.1.1" + +"escape-html@^1.0.3", "escape-html@~1.0.3": + "integrity" "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "resolved" "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + "version" "1.0.3" + +"escape-string-regexp@^1.0.5": + "integrity" "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + "version" "1.0.5" + +"escape-string-regexp@^4.0.0": + "integrity" "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + "version" "4.0.0" + +"eslint-scope@5.1.1": + "integrity" "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==" + "resolved" "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" + "version" "5.1.1" + dependencies: + "esrecurse" "^4.3.0" + "estraverse" "^4.1.1" + +"esprima@^4.0.0": + "integrity" "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "resolved" "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" + "version" "4.0.1" + +"esrecurse@^4.3.0": + "integrity" "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==" + "resolved" "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" + "version" "4.3.0" + dependencies: + "estraverse" "^5.2.0" + +"estraverse@^4.1.1": + "integrity" "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" + "version" "4.3.0" + +"estraverse@^5.2.0": + "integrity" "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" + "version" "5.3.0" + +"esutils@^2.0.2": + "integrity" "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + "resolved" "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" + "version" "2.0.3" + +"eta@^1.12.3": + "integrity" "sha512-qHixwbDLtekO/d51Yr4glcaUJCIjGVJyTzuqV4GPlgZo1YpgOKG+avQynErZIYrfM6JIJdtiG2Kox8tbb+DoGg==" + "resolved" "https://registry.npmjs.org/eta/-/eta-1.12.3.tgz" + "version" "1.12.3" + +"etag@~1.8.1": + "integrity" "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "resolved" "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" + "version" "1.8.1" + +"eval@^0.1.4": + "integrity" "sha512-o0XUw+5OGkXw4pJZzQoXUk+H87DHuC+7ZE//oSrRGtatTmr12oTnLfg6QOq9DyTt0c/p4TwzgmkKrBzWTSizyQ==" + "resolved" "https://registry.npmjs.org/eval/-/eval-0.1.6.tgz" + "version" "0.1.6" + dependencies: + "require-like" ">= 0.1.1" + +"eventemitter3@^4.0.0": + "integrity" "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + "resolved" "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz" + "version" "4.0.7" + +"events@^3.2.0": + "integrity" "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + "resolved" "https://registry.npmjs.org/events/-/events-3.3.0.tgz" + "version" "3.3.0" + +"execa@^5.0.0": + "integrity" "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==" + "resolved" "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" + "version" "5.1.1" + dependencies: + "cross-spawn" "^7.0.3" + "get-stream" "^6.0.0" + "human-signals" "^2.1.0" + "is-stream" "^2.0.0" + "merge-stream" "^2.0.0" + "npm-run-path" "^4.0.1" + "onetime" "^5.1.2" + "signal-exit" "^3.0.3" + "strip-final-newline" "^2.0.0" + +"express@^4.17.1": + "integrity" "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==" + "resolved" "https://registry.npmjs.org/express/-/express-4.17.3.tgz" + "version" "4.17.3" + dependencies: + "accepts" "~1.3.8" + "array-flatten" "1.1.1" + "body-parser" "1.19.2" + "content-disposition" "0.5.4" + "content-type" "~1.0.4" + "cookie" "0.4.2" + "cookie-signature" "1.0.6" + "debug" "2.6.9" + "depd" "~1.1.2" + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "etag" "~1.8.1" + "finalhandler" "~1.1.2" + "fresh" "0.5.2" + "merge-descriptors" "1.0.1" + "methods" "~1.1.2" + "on-finished" "~2.3.0" + "parseurl" "~1.3.3" + "path-to-regexp" "0.1.7" + "proxy-addr" "~2.0.7" + "qs" "6.9.7" + "range-parser" "~1.2.1" + "safe-buffer" "5.2.1" + "send" "0.17.2" + "serve-static" "1.14.2" + "setprototypeof" "1.2.0" + "statuses" "~1.5.0" + "type-is" "~1.6.18" + "utils-merge" "1.0.1" + "vary" "~1.1.2" + +"extend-shallow@^2.0.1": + "integrity" "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=" + "resolved" "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "is-extendable" "^0.1.0" + +"extend@^3.0.0": + "integrity" "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "resolved" "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz" + "version" "3.0.2" + +"fast-deep-equal@^3.1.1", "fast-deep-equal@^3.1.3": + "integrity" "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "resolved" "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" + "version" "3.1.3" + +"fast-glob@^3.2.7", "fast-glob@^3.2.9": + "integrity" "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==" + "resolved" "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz" + "version" "3.2.11" dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-url-parser@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" - integrity sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0= - dependencies: - punycode "^1.3.2" - -fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== - dependencies: - reusify "^1.0.4" - -faye-websocket@^0.11.3: - version "0.11.4" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" - integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== - dependencies: - websocket-driver ">=0.5.1" - -fbemitter@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/fbemitter/-/fbemitter-3.0.0.tgz#00b2a1af5411254aab416cd75f9e6289bee4bff3" - integrity sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw== - dependencies: - fbjs "^3.0.0" - -fbjs-css-vars@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8" - integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== - -fbjs@^3.0.0, fbjs@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.4.tgz#e1871c6bd3083bac71ff2da868ad5067d37716c6" - integrity sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ== - dependencies: - cross-fetch "^3.1.5" - fbjs-css-vars "^1.0.0" - loose-envify "^1.0.0" - object-assign "^4.1.0" - promise "^7.1.1" - setimmediate "^1.0.5" - ua-parser-js "^0.7.30" - -feed@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/feed/-/feed-4.2.2.tgz#865783ef6ed12579e2c44bbef3c9113bc4956a7e" - integrity sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ== - dependencies: - xml-js "^1.6.11" - -file-loader@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" - integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== - dependencies: - loader-utils "^2.0.0" - schema-utils "^3.0.0" - -filesize@^8.0.6: - version "8.0.7" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-8.0.7.tgz#695e70d80f4e47012c132d57a059e80c6b580bd8" - integrity sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ== - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - -find-cache-dir@^3.3.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" - integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== - dependencies: - commondir "^1.0.1" - make-dir "^3.0.2" - pkg-dir "^4.1.0" - -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -find-up@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flux@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/flux/-/flux-4.0.3.tgz#573b504a24982c4768fdfb59d8d2ea5637d72ee7" - integrity sha512-yKAbrp7JhZhj6uiT1FTuVMlIAT1J4jqEyBpFApi1kxpGZCvacMVc/t1pMQyotqHhAgvoE3bNvAykhCo2CLjnYw== - dependencies: - fbemitter "^3.0.0" - fbjs "^3.0.1" - -follow-redirects@^1.0.0, follow-redirects@^1.14.7: - version "1.14.9" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" - integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== - -fork-ts-checker-webpack-plugin@^6.5.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz#0282b335fa495a97e167f69018f566ea7d2a2b5e" - integrity sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw== + "glob-parent" "^5.1.2" + "merge2" "^1.3.0" + "micromatch" "^4.0.4" + +"fast-json-stable-stringify@^2.0.0": + "integrity" "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "resolved" "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" + "version" "2.1.0" + +"fast-url-parser@1.1.3": + "integrity" "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=" + "resolved" "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz" + "version" "1.1.3" + dependencies: + "punycode" "^1.3.2" + +"fastq@^1.6.0": + "integrity" "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==" + "resolved" "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz" + "version" "1.13.0" + dependencies: + "reusify" "^1.0.4" + +"faye-websocket@^0.11.3": + "integrity" "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==" + "resolved" "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz" + "version" "0.11.4" + dependencies: + "websocket-driver" ">=0.5.1" + +"fbemitter@^3.0.0": + "integrity" "sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==" + "resolved" "https://registry.npmjs.org/fbemitter/-/fbemitter-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "fbjs" "^3.0.0" + +"fbjs-css-vars@^1.0.0": + "integrity" "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" + "resolved" "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz" + "version" "1.0.2" + +"fbjs@^3.0.0", "fbjs@^3.0.1": + "integrity" "sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ==" + "resolved" "https://registry.npmjs.org/fbjs/-/fbjs-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "cross-fetch" "^3.1.5" + "fbjs-css-vars" "^1.0.0" + "loose-envify" "^1.0.0" + "object-assign" "^4.1.0" + "promise" "^7.1.1" + "setimmediate" "^1.0.5" + "ua-parser-js" "^0.7.30" + +"feed@^4.2.2": + "integrity" "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==" + "resolved" "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz" + "version" "4.2.2" + dependencies: + "xml-js" "^1.6.11" + +"file-loader@*", "file-loader@^6.2.0": + "integrity" "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==" + "resolved" "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz" + "version" "6.2.0" + dependencies: + "loader-utils" "^2.0.0" + "schema-utils" "^3.0.0" + +"filesize@^8.0.6": + "integrity" "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==" + "resolved" "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz" + "version" "8.0.7" + +"fill-range@^7.0.1": + "integrity" "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==" + "resolved" "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" + "version" "7.0.1" + dependencies: + "to-regex-range" "^5.0.1" + +"finalhandler@~1.1.2": + "integrity" "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==" + "resolved" "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz" + "version" "1.1.2" + dependencies: + "debug" "2.6.9" + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "on-finished" "~2.3.0" + "parseurl" "~1.3.3" + "statuses" "~1.5.0" + "unpipe" "~1.0.0" + +"find-cache-dir@^3.3.1": + "integrity" "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==" + "resolved" "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz" + "version" "3.3.2" + dependencies: + "commondir" "^1.0.1" + "make-dir" "^3.0.2" + "pkg-dir" "^4.1.0" + +"find-up@^3.0.0": + "integrity" "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==" + "resolved" "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "locate-path" "^3.0.0" + +"find-up@^4.0.0": + "integrity" "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==" + "resolved" "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "locate-path" "^5.0.0" + "path-exists" "^4.0.0" + +"find-up@^5.0.0": + "integrity" "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==" + "resolved" "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "locate-path" "^6.0.0" + "path-exists" "^4.0.0" + +"flux@^4.0.1": + "integrity" "sha512-yKAbrp7JhZhj6uiT1FTuVMlIAT1J4jqEyBpFApi1kxpGZCvacMVc/t1pMQyotqHhAgvoE3bNvAykhCo2CLjnYw==" + "resolved" "https://registry.npmjs.org/flux/-/flux-4.0.3.tgz" + "version" "4.0.3" + dependencies: + "fbemitter" "^3.0.0" + "fbjs" "^3.0.1" + +"follow-redirects@^1.0.0", "follow-redirects@^1.14.7": + "integrity" "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" + "resolved" "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz" + "version" "1.14.9" + +"fork-ts-checker-webpack-plugin@^6.5.0": + "integrity" "sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw==" + "resolved" "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz" + "version" "6.5.0" dependencies: "@babel/code-frame" "^7.8.3" "@types/json-schema" "^7.0.5" - chalk "^4.1.0" - chokidar "^3.4.2" - cosmiconfig "^6.0.0" - deepmerge "^4.2.2" - fs-extra "^9.0.0" - glob "^7.1.6" - memfs "^3.1.2" - minimatch "^3.0.4" - schema-utils "2.7.0" - semver "^7.3.2" - tapable "^1.0.0" - -forwarded@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" - integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== - -fraction.js@^4.1.2: - version "4.1.3" - resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.3.tgz#be65b0f20762ef27e1e793860bc2dfb716e99e65" - integrity sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg== - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - -fs-extra@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1" - integrity sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-extra@^9.0.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" - integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== - dependencies: - at-least-node "^1.0.0" - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-monkey@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" - integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-intrinsic@^1.0.2: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - -get-own-enumerable-property-symbols@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" - integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== - -get-stream@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -github-slugger@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.4.0.tgz#206eb96cdb22ee56fdc53a28d5a302338463444e" - integrity sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ== - -glob-parent@^5.1.2, glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob-to-regexp@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" - integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== - -glob@^7.0.0, glob@^7.1.3, glob@^7.1.6: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -global-dirs@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686" - integrity sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA== - dependencies: - ini "2.0.0" - -global-modules@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" - integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== - dependencies: - global-prefix "^3.0.0" - -global-prefix@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" - integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== - dependencies: - ini "^1.3.5" - kind-of "^6.0.2" - which "^1.3.1" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globby@^11.0.1, globby@^11.0.2, globby@^11.0.4: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -globby@^12.0.2: - version "12.2.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-12.2.0.tgz#2ab8046b4fba4ff6eede835b29f678f90e3d3c22" - integrity sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA== - dependencies: - array-union "^3.0.1" - dir-glob "^3.0.1" - fast-glob "^3.2.7" - ignore "^5.1.9" - merge2 "^1.4.1" - slash "^4.0.0" - -got@^9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + "chalk" "^4.1.0" + "chokidar" "^3.4.2" + "cosmiconfig" "^6.0.0" + "deepmerge" "^4.2.2" + "fs-extra" "^9.0.0" + "glob" "^7.1.6" + "memfs" "^3.1.2" + "minimatch" "^3.0.4" + "schema-utils" "2.7.0" + "semver" "^7.3.2" + "tapable" "^1.0.0" + +"forwarded@0.2.0": + "integrity" "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + "resolved" "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" + "version" "0.2.0" + +"fraction.js@^4.1.2": + "integrity" "sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg==" + "resolved" "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.3.tgz" + "version" "4.1.3" + +"fresh@0.5.2": + "integrity" "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "resolved" "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" + "version" "0.5.2" + +"fs-extra@^10.0.0": + "integrity" "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==" + "resolved" "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz" + "version" "10.0.0" + dependencies: + "graceful-fs" "^4.2.0" + "jsonfile" "^6.0.1" + "universalify" "^2.0.0" + +"fs-extra@^9.0.0": + "integrity" "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==" + "resolved" "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz" + "version" "9.1.0" + dependencies: + "at-least-node" "^1.0.0" + "graceful-fs" "^4.2.0" + "jsonfile" "^6.0.1" + "universalify" "^2.0.0" + +"fs-monkey@1.0.3": + "integrity" "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==" + "resolved" "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz" + "version" "1.0.3" + +"fs.realpath@^1.0.0": + "integrity" "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "resolved" "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + "version" "1.0.0" + +"function-bind@^1.1.1": + "integrity" "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "resolved" "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" + "version" "1.1.1" + +"gensync@^1.0.0-beta.1", "gensync@^1.0.0-beta.2": + "integrity" "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + "resolved" "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" + "version" "1.0.0-beta.2" + +"get-intrinsic@^1.0.2": + "integrity" "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==" + "resolved" "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "function-bind" "^1.1.1" + "has" "^1.0.3" + "has-symbols" "^1.0.1" + +"get-own-enumerable-property-symbols@^3.0.0": + "integrity" "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + "resolved" "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz" + "version" "3.0.2" + +"get-stream@^4.1.0": + "integrity" "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==" + "resolved" "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "pump" "^3.0.0" + +"get-stream@^5.1.0": + "integrity" "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==" + "resolved" "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz" + "version" "5.2.0" + dependencies: + "pump" "^3.0.0" + +"get-stream@^6.0.0": + "integrity" "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + "resolved" "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz" + "version" "6.0.1" + +"github-slugger@^1.4.0": + "integrity" "sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ==" + "resolved" "https://registry.npmjs.org/github-slugger/-/github-slugger-1.4.0.tgz" + "version" "1.4.0" + +"glob-parent@^5.1.2", "glob-parent@~5.1.2": + "integrity" "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==" + "resolved" "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + "version" "5.1.2" + dependencies: + "is-glob" "^4.0.1" + +"glob-parent@^6.0.1": + "integrity" "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==" + "resolved" "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" + "version" "6.0.2" + dependencies: + "is-glob" "^4.0.3" + +"glob-to-regexp@^0.4.1": + "integrity" "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + "resolved" "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz" + "version" "0.4.1" + +"glob@^7.0.0", "glob@^7.1.3", "glob@^7.1.6": + "integrity" "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==" + "resolved" "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz" + "version" "7.2.0" + dependencies: + "fs.realpath" "^1.0.0" + "inflight" "^1.0.4" + "inherits" "2" + "minimatch" "^3.0.4" + "once" "^1.3.0" + "path-is-absolute" "^1.0.0" + +"global-dirs@^3.0.0": + "integrity" "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==" + "resolved" "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "ini" "2.0.0" + +"global-modules@^2.0.0": + "integrity" "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==" + "resolved" "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "global-prefix" "^3.0.0" + +"global-prefix@^3.0.0": + "integrity" "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==" + "resolved" "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "ini" "^1.3.5" + "kind-of" "^6.0.2" + "which" "^1.3.1" + +"globals@^11.1.0": + "integrity" "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + "resolved" "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" + "version" "11.12.0" + +"globby@^11.0.1", "globby@^11.0.2", "globby@^11.0.4": + "integrity" "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==" + "resolved" "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" + "version" "11.1.0" + dependencies: + "array-union" "^2.1.0" + "dir-glob" "^3.0.1" + "fast-glob" "^3.2.9" + "ignore" "^5.2.0" + "merge2" "^1.4.1" + "slash" "^3.0.0" + +"globby@^12.0.2": + "integrity" "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==" + "resolved" "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz" + "version" "12.2.0" + dependencies: + "array-union" "^3.0.1" + "dir-glob" "^3.0.1" + "fast-glob" "^3.2.7" + "ignore" "^5.1.9" + "merge2" "^1.4.1" + "slash" "^4.0.0" + +"got@^9.6.0": + "integrity" "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==" + "resolved" "https://registry.npmjs.org/got/-/got-9.6.0.tgz" + "version" "9.6.0" dependencies: "@sindresorhus/is" "^0.14.0" "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" - -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: - version "4.2.9" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== - -gray-matter@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.3.tgz#e893c064825de73ea1f5f7d88c7a9f7274288798" - integrity sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q== - dependencies: - js-yaml "^3.13.1" - kind-of "^6.0.2" - section-matter "^1.0.0" - strip-bom-string "^1.0.0" - -gzip-size@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" - integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== - dependencies: - duplexer "^0.1.2" - -handle-thing@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" - integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-symbols@^1.0.1, has-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" - integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - -has-yarn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" - integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hast-to-hyperscript@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz#9b67fd188e4c81e8ad66f803855334173920218d" - integrity sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA== + "cacheable-request" "^6.0.0" + "decompress-response" "^3.3.0" + "duplexer3" "^0.1.4" + "get-stream" "^4.1.0" + "lowercase-keys" "^1.0.1" + "mimic-response" "^1.0.1" + "p-cancelable" "^1.0.0" + "to-readable-stream" "^1.0.0" + "url-parse-lax" "^3.0.0" + +"graceful-fs@^4.1.2", "graceful-fs@^4.1.6", "graceful-fs@^4.2.0", "graceful-fs@^4.2.4", "graceful-fs@^4.2.6", "graceful-fs@^4.2.9": + "integrity" "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" + "resolved" "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz" + "version" "4.2.9" + +"gray-matter@^4.0.3": + "integrity" "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==" + "resolved" "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz" + "version" "4.0.3" + dependencies: + "js-yaml" "^3.13.1" + "kind-of" "^6.0.2" + "section-matter" "^1.0.0" + "strip-bom-string" "^1.0.0" + +"gzip-size@^6.0.0": + "integrity" "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==" + "resolved" "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "duplexer" "^0.1.2" + +"handle-thing@^2.0.0": + "integrity" "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" + "resolved" "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz" + "version" "2.0.1" + +"has-flag@^3.0.0": + "integrity" "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" + "version" "3.0.0" + +"has-flag@^4.0.0": + "integrity" "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + "version" "4.0.0" + +"has-symbols@^1.0.1", "has-symbols@^1.0.2": + "integrity" "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + "resolved" "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz" + "version" "1.0.2" + +"has-tostringtag@^1.0.0": + "integrity" "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==" + "resolved" "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "has-symbols" "^1.0.2" + +"has-yarn@^2.1.0": + "integrity" "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==" + "resolved" "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz" + "version" "2.1.0" + +"has@^1.0.3": + "integrity" "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==" + "resolved" "https://registry.npmjs.org/has/-/has-1.0.3.tgz" + "version" "1.0.3" + dependencies: + "function-bind" "^1.1.1" + +"hast-to-hyperscript@^9.0.0": + "integrity" "sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA==" + "resolved" "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz" + "version" "9.0.1" dependencies: "@types/unist" "^2.0.3" - comma-separated-tokens "^1.0.0" - property-information "^5.3.0" - space-separated-tokens "^1.0.0" - style-to-object "^0.3.0" - unist-util-is "^4.0.0" - web-namespaces "^1.0.0" - -hast-util-from-parse5@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-5.0.3.tgz#3089dc0ee2ccf6ec8bc416919b51a54a589e097c" - integrity sha512-gOc8UB99F6eWVWFtM9jUikjN7QkWxB3nY0df5Z0Zq1/Nkwl5V4hAAsl0tmwlgWl/1shlTF8DnNYLO8X6wRV9pA== - dependencies: - ccount "^1.0.3" - hastscript "^5.0.0" - property-information "^5.0.0" - web-namespaces "^1.1.2" - xtend "^4.0.1" - -hast-util-from-parse5@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz#554e34abdeea25ac76f5bd950a1f0180e0b3bc2a" - integrity sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA== + "comma-separated-tokens" "^1.0.0" + "property-information" "^5.3.0" + "space-separated-tokens" "^1.0.0" + "style-to-object" "^0.3.0" + "unist-util-is" "^4.0.0" + "web-namespaces" "^1.0.0" + +"hast-util-from-parse5@^5.0.0": + "integrity" "sha512-gOc8UB99F6eWVWFtM9jUikjN7QkWxB3nY0df5Z0Zq1/Nkwl5V4hAAsl0tmwlgWl/1shlTF8DnNYLO8X6wRV9pA==" + "resolved" "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-5.0.3.tgz" + "version" "5.0.3" + dependencies: + "ccount" "^1.0.3" + "hastscript" "^5.0.0" + "property-information" "^5.0.0" + "web-namespaces" "^1.1.2" + "xtend" "^4.0.1" + +"hast-util-from-parse5@^6.0.0": + "integrity" "sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA==" + "resolved" "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz" + "version" "6.0.1" dependencies: "@types/parse5" "^5.0.0" - hastscript "^6.0.0" - property-information "^5.0.0" - vfile "^4.0.0" - vfile-location "^3.2.0" - web-namespaces "^1.0.0" - -hast-util-parse-selector@^2.0.0: - version "2.2.5" - resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz#d57c23f4da16ae3c63b3b6ca4616683313499c3a" - integrity sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ== - -hast-util-raw@6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/hast-util-raw/-/hast-util-raw-6.0.1.tgz#973b15930b7529a7b66984c98148b46526885977" - integrity sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig== + "hastscript" "^6.0.0" + "property-information" "^5.0.0" + "vfile" "^4.0.0" + "vfile-location" "^3.2.0" + "web-namespaces" "^1.0.0" + +"hast-util-parse-selector@^2.0.0": + "integrity" "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==" + "resolved" "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz" + "version" "2.2.5" + +"hast-util-raw@6.0.1": + "integrity" "sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig==" + "resolved" "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-6.0.1.tgz" + "version" "6.0.1" dependencies: "@types/hast" "^2.0.0" - hast-util-from-parse5 "^6.0.0" - hast-util-to-parse5 "^6.0.0" - html-void-elements "^1.0.0" - parse5 "^6.0.0" - unist-util-position "^3.0.0" - vfile "^4.0.0" - web-namespaces "^1.0.0" - xtend "^4.0.0" - zwitch "^1.0.0" - -hast-util-to-parse5@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz#1ec44650b631d72952066cea9b1445df699f8479" - integrity sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ== - dependencies: - hast-to-hyperscript "^9.0.0" - property-information "^5.0.0" - web-namespaces "^1.0.0" - xtend "^4.0.0" - zwitch "^1.0.0" - -hastscript@^5.0.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-5.1.2.tgz#bde2c2e56d04c62dd24e8c5df288d050a355fb8a" - integrity sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ== - dependencies: - comma-separated-tokens "^1.0.0" - hast-util-parse-selector "^2.0.0" - property-information "^5.0.0" - space-separated-tokens "^1.0.0" - -hastscript@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-6.0.0.tgz#e8768d7eac56c3fdeac8a92830d58e811e5bf640" - integrity sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w== + "hast-util-from-parse5" "^6.0.0" + "hast-util-to-parse5" "^6.0.0" + "html-void-elements" "^1.0.0" + "parse5" "^6.0.0" + "unist-util-position" "^3.0.0" + "vfile" "^4.0.0" + "web-namespaces" "^1.0.0" + "xtend" "^4.0.0" + "zwitch" "^1.0.0" + +"hast-util-to-parse5@^6.0.0": + "integrity" "sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ==" + "resolved" "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "hast-to-hyperscript" "^9.0.0" + "property-information" "^5.0.0" + "web-namespaces" "^1.0.0" + "xtend" "^4.0.0" + "zwitch" "^1.0.0" + +"hastscript@^5.0.0": + "integrity" "sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ==" + "resolved" "https://registry.npmjs.org/hastscript/-/hastscript-5.1.2.tgz" + "version" "5.1.2" + dependencies: + "comma-separated-tokens" "^1.0.0" + "hast-util-parse-selector" "^2.0.0" + "property-information" "^5.0.0" + "space-separated-tokens" "^1.0.0" + +"hastscript@^6.0.0": + "integrity" "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==" + "resolved" "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz" + "version" "6.0.0" dependencies: "@types/hast" "^2.0.0" - comma-separated-tokens "^1.0.0" - hast-util-parse-selector "^2.0.0" - property-information "^5.0.0" - space-separated-tokens "^1.0.0" + "comma-separated-tokens" "^1.0.0" + "hast-util-parse-selector" "^2.0.0" + "property-information" "^5.0.0" + "space-separated-tokens" "^1.0.0" -he@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +"he@^1.2.0": + "integrity" "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + "resolved" "https://registry.npmjs.org/he/-/he-1.2.0.tgz" + "version" "1.2.0" -history@^4.9.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" - integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew== +"history@^4.9.0": + "integrity" "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==" + "resolved" "https://registry.npmjs.org/history/-/history-4.10.1.tgz" + "version" "4.10.1" dependencies: "@babel/runtime" "^7.1.2" - loose-envify "^1.2.0" - resolve-pathname "^3.0.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - value-equal "^1.0.1" - -hoist-non-react-statics@^3.1.0: - version "3.3.2" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" - integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== - dependencies: - react-is "^16.7.0" - -hpack.js@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" - integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI= - dependencies: - inherits "^2.0.1" - obuf "^1.0.0" - readable-stream "^2.0.1" - wbuf "^1.1.0" - -html-entities@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.2.tgz#760b404685cb1d794e4f4b744332e3b00dcfe488" - integrity sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ== - -html-minifier-terser@^6.0.2: - version "6.1.0" - resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" - integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== - dependencies: - camel-case "^4.1.2" - clean-css "^5.2.2" - commander "^8.3.0" - he "^1.2.0" - param-case "^3.0.4" - relateurl "^0.2.7" - terser "^5.10.0" - -html-tags@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" - integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg== - -html-void-elements@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483" - integrity sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w== - -html-webpack-plugin@^5.4.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz#c3911936f57681c1f9f4d8b68c158cd9dfe52f50" - integrity sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw== + "loose-envify" "^1.2.0" + "resolve-pathname" "^3.0.0" + "tiny-invariant" "^1.0.2" + "tiny-warning" "^1.0.0" + "value-equal" "^1.0.1" + +"hoist-non-react-statics@^3.1.0": + "integrity" "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==" + "resolved" "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz" + "version" "3.3.2" + dependencies: + "react-is" "^16.7.0" + +"hpack.js@^2.1.6": + "integrity" "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=" + "resolved" "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz" + "version" "2.1.6" + dependencies: + "inherits" "^2.0.1" + "obuf" "^1.0.0" + "readable-stream" "^2.0.1" + "wbuf" "^1.1.0" + +"html-entities@^2.3.2": + "integrity" "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==" + "resolved" "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz" + "version" "2.3.2" + +"html-minifier-terser@^6.0.2": + "integrity" "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==" + "resolved" "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "camel-case" "^4.1.2" + "clean-css" "^5.2.2" + "commander" "^8.3.0" + "he" "^1.2.0" + "param-case" "^3.0.4" + "relateurl" "^0.2.7" + "terser" "^5.10.0" + +"html-tags@^3.1.0": + "integrity" "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==" + "resolved" "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz" + "version" "3.1.0" + +"html-void-elements@^1.0.0": + "integrity" "sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w==" + "resolved" "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz" + "version" "1.0.5" + +"html-webpack-plugin@^5.4.0": + "integrity" "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==" + "resolved" "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz" + "version" "5.5.0" dependencies: "@types/html-minifier-terser" "^6.0.0" - html-minifier-terser "^6.0.2" - lodash "^4.17.21" - pretty-error "^4.0.0" - tapable "^2.0.0" - -htmlparser2@^3.9.1: - version "3.10.1" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" - integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== - dependencies: - domelementtype "^1.3.1" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^3.1.1" - -htmlparser2@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" - integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== - dependencies: - domelementtype "^2.0.1" - domhandler "^4.0.0" - domutils "^2.5.2" - entities "^2.0.0" - -http-cache-semantics@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" - integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== - -http-deceiver@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" - integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= - -http-errors@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" - integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.1" - -http-errors@~1.6.2: - version "1.6.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - -http-parser-js@>=0.5.1: - version "0.5.5" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.5.tgz#d7c30d5d3c90d865b4a2e870181f9d6f22ac7ac5" - integrity sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA== - -http-proxy-middleware@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.3.tgz#5df04f69a89f530c2284cd71eeaa51ba52243289" - integrity sha512-1bloEwnrHMnCoO/Gcwbz7eSVvW50KPES01PecpagI+YLNLci4AcuKJrujW4Mc3sBLpFxMSlsLNHS5Nl/lvrTPA== + "html-minifier-terser" "^6.0.2" + "lodash" "^4.17.21" + "pretty-error" "^4.0.0" + "tapable" "^2.0.0" + +"htmlparser2@^3.9.1": + "integrity" "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==" + "resolved" "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz" + "version" "3.10.1" + dependencies: + "domelementtype" "^1.3.1" + "domhandler" "^2.3.0" + "domutils" "^1.5.1" + "entities" "^1.1.1" + "inherits" "^2.0.1" + "readable-stream" "^3.1.1" + +"htmlparser2@^6.1.0": + "integrity" "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==" + "resolved" "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "domelementtype" "^2.0.1" + "domhandler" "^4.0.0" + "domutils" "^2.5.2" + "entities" "^2.0.0" + +"http-cache-semantics@^4.0.0": + "integrity" "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + "resolved" "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz" + "version" "4.1.1" + +"http-deceiver@^1.2.7": + "integrity" "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" + "resolved" "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" + "version" "1.2.7" + +"http-errors@~1.6.2": + "integrity" "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=" + "resolved" "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz" + "version" "1.6.3" + dependencies: + "depd" "~1.1.2" + "inherits" "2.0.3" + "setprototypeof" "1.1.0" + "statuses" ">= 1.4.0 < 2" + +"http-errors@1.8.1": + "integrity" "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==" + "resolved" "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz" + "version" "1.8.1" + dependencies: + "depd" "~1.1.2" + "inherits" "2.0.4" + "setprototypeof" "1.2.0" + "statuses" ">= 1.5.0 < 2" + "toidentifier" "1.0.1" + +"http-parser-js@>=0.5.1": + "integrity" "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA==" + "resolved" "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz" + "version" "0.5.5" + +"http-proxy-middleware@^2.0.0": + "integrity" "sha512-1bloEwnrHMnCoO/Gcwbz7eSVvW50KPES01PecpagI+YLNLci4AcuKJrujW4Mc3sBLpFxMSlsLNHS5Nl/lvrTPA==" + "resolved" "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.3.tgz" + "version" "2.0.3" dependencies: "@types/http-proxy" "^1.17.8" - http-proxy "^1.18.1" - is-glob "^4.0.1" - is-plain-obj "^3.0.0" - micromatch "^4.0.2" - -http-proxy@^1.18.1: - version "1.18.1" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" - integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== - dependencies: - eventemitter3 "^4.0.0" - follow-redirects "^1.0.0" - requires-port "^1.0.0" - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -icss-utils@^5.0.0, icss-utils@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" - integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== - -ignore@^5.1.9, ignore@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== - -image-size@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.0.1.tgz#86d6cfc2b1d19eab5d2b368d4b9194d9e48541c5" - integrity sha512-VAwkvNSNGClRw9mDHhc5Efax8PLlsOGcUTh0T/LIriC8vPA3U5PdqXWqkz406MoYHMKW8Uf9gWr05T/rYB44kQ== - dependencies: - queue "6.0.2" - -immer@^9.0.7: - version "9.0.12" - resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.12.tgz#2d33ddf3ee1d247deab9d707ca472c8c942a0f20" - integrity sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA== - -import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.2.2, import-fresh@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-lazy@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" - integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -infima@0.2.0-alpha.37: - version "0.2.0-alpha.37" - resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.37.tgz#b87ff42d528d6d050098a560f0294fbdd12adb78" - integrity sha512-4GX7Baw+/lwS4PPW/UJNY89tWSvYG1DL6baKVdpK6mC593iRgMssxNtORMTFArLPJ/A/lzsGhRmx+z6MaMxj0Q== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -ini@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" - integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== - -ini@^1.3.5, ini@~1.3.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - -inline-style-parser@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" - integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== - -interpret@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" - integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== - -ip@^1.1.0: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= - -ipaddr.js@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -ipaddr.js@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" - integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== - -is-alphabetical@1.0.4, is-alphabetical@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" - integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== - -is-alphanumerical@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" - integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== - dependencies: - is-alphabetical "^1.0.0" - is-decimal "^1.0.0" - -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-buffer@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" - integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== - -is-ci@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" - integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== - dependencies: - ci-info "^2.0.0" - -is-core-module@^2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" - integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== - dependencies: - has "^1.0.3" - -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-decimal@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" - integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== - -is-docker@^2.0.0, is-docker@^2.1.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" - integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== - -is-extendable@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-hexadecimal@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" - integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== - -is-installed-globally@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" - integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ== - dependencies: - global-dirs "^3.0.0" - is-path-inside "^3.0.2" - -is-npm@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-5.0.0.tgz#43e8d65cc56e1b67f8d47262cf667099193f45a8" - integrity sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA== - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - -is-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" - integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== - -is-path-cwd@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" - integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== - -is-path-inside@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - -is-plain-obj@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - -is-plain-obj@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" - integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== - -is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-regex@^1.0.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" - integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= - -is-root@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" - integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg== - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-typedarray@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-whitespace-character@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7" - integrity sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w== - -is-word-character@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.4.tgz#ce0e73216f98599060592f62ff31354ddbeb0230" - integrity sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA== - -is-wsl@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== - dependencies: - is-docker "^2.0.0" - -is-yarn-global@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" - integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - -jest-worker@^27.0.2, jest-worker@^27.4.5: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" - integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + "http-proxy" "^1.18.1" + "is-glob" "^4.0.1" + "is-plain-obj" "^3.0.0" + "micromatch" "^4.0.2" + +"http-proxy@^1.18.1": + "integrity" "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==" + "resolved" "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz" + "version" "1.18.1" + dependencies: + "eventemitter3" "^4.0.0" + "follow-redirects" "^1.0.0" + "requires-port" "^1.0.0" + +"human-signals@^2.1.0": + "integrity" "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" + "resolved" "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" + "version" "2.1.0" + +"iconv-lite@0.4.24": + "integrity" "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==" + "resolved" "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" + "version" "0.4.24" + dependencies: + "safer-buffer" ">= 2.1.2 < 3" + +"icss-utils@^5.0.0", "icss-utils@^5.1.0": + "integrity" "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==" + "resolved" "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz" + "version" "5.1.0" + +"ignore@^5.1.9", "ignore@^5.2.0": + "integrity" "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==" + "resolved" "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz" + "version" "5.2.0" + +"image-size@^1.0.1": + "integrity" "sha512-VAwkvNSNGClRw9mDHhc5Efax8PLlsOGcUTh0T/LIriC8vPA3U5PdqXWqkz406MoYHMKW8Uf9gWr05T/rYB44kQ==" + "resolved" "https://registry.npmjs.org/image-size/-/image-size-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "queue" "6.0.2" + +"immer@^9.0.7": + "integrity" "sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA==" + "resolved" "https://registry.npmjs.org/immer/-/immer-9.0.12.tgz" + "version" "9.0.12" + +"import-fresh@^3.1.0", "import-fresh@^3.2.1", "import-fresh@^3.2.2", "import-fresh@^3.3.0": + "integrity" "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==" + "resolved" "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" + "version" "3.3.0" + dependencies: + "parent-module" "^1.0.0" + "resolve-from" "^4.0.0" + +"import-lazy@^2.1.0": + "integrity" "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" + "resolved" "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz" + "version" "2.1.0" + +"imurmurhash@^0.1.4": + "integrity" "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + "resolved" "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" + "version" "0.1.4" + +"indent-string@^4.0.0": + "integrity" "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + "resolved" "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" + "version" "4.0.0" + +"infima@0.2.0-alpha.37": + "integrity" "sha512-4GX7Baw+/lwS4PPW/UJNY89tWSvYG1DL6baKVdpK6mC593iRgMssxNtORMTFArLPJ/A/lzsGhRmx+z6MaMxj0Q==" + "resolved" "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.37.tgz" + "version" "0.2.0-alpha.37" + +"inflight@^1.0.4": + "integrity" "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=" + "resolved" "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + "version" "1.0.6" + dependencies: + "once" "^1.3.0" + "wrappy" "1" + +"inherits@^2.0.0", "inherits@^2.0.1", "inherits@^2.0.3", "inherits@~2.0.3", "inherits@2", "inherits@2.0.4": + "integrity" "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "resolved" "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + "version" "2.0.4" + +"inherits@2.0.3": + "integrity" "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "resolved" "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + "version" "2.0.3" + +"ini@^1.3.5", "ini@~1.3.0": + "integrity" "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + "resolved" "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" + "version" "1.3.8" + +"ini@2.0.0": + "integrity" "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==" + "resolved" "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz" + "version" "2.0.0" + +"inline-style-parser@0.1.1": + "integrity" "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" + "resolved" "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz" + "version" "0.1.1" + +"interpret@^1.0.0": + "integrity" "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + "resolved" "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz" + "version" "1.4.0" + +"ip@^1.1.0": + "integrity" "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + "resolved" "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz" + "version" "1.1.5" + +"ipaddr.js@^2.0.1": + "integrity" "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==" + "resolved" "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz" + "version" "2.0.1" + +"ipaddr.js@1.9.1": + "integrity" "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + "resolved" "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" + "version" "1.9.1" + +"is-alphabetical@^1.0.0", "is-alphabetical@1.0.4": + "integrity" "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==" + "resolved" "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz" + "version" "1.0.4" + +"is-alphanumerical@^1.0.0": + "integrity" "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==" + "resolved" "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz" + "version" "1.0.4" + dependencies: + "is-alphabetical" "^1.0.0" + "is-decimal" "^1.0.0" + +"is-arguments@^1.0.4": + "integrity" "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==" + "resolved" "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "call-bind" "^1.0.2" + "has-tostringtag" "^1.0.0" + +"is-arrayish@^0.2.1": + "integrity" "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + "resolved" "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + "version" "0.2.1" + +"is-binary-path@~2.1.0": + "integrity" "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==" + "resolved" "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "binary-extensions" "^2.0.0" + +"is-buffer@^2.0.0": + "integrity" "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" + "resolved" "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz" + "version" "2.0.5" + +"is-ci@^2.0.0": + "integrity" "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==" + "resolved" "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "ci-info" "^2.0.0" + +"is-core-module@^2.8.1": + "integrity" "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==" + "resolved" "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz" + "version" "2.8.1" + dependencies: + "has" "^1.0.3" + +"is-date-object@^1.0.1": + "integrity" "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==" + "resolved" "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz" + "version" "1.0.5" + dependencies: + "has-tostringtag" "^1.0.0" + +"is-decimal@^1.0.0": + "integrity" "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==" + "resolved" "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz" + "version" "1.0.4" + +"is-docker@^2.0.0", "is-docker@^2.1.1": + "integrity" "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" + "resolved" "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz" + "version" "2.2.1" + +"is-extendable@^0.1.0": + "integrity" "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + "resolved" "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" + "version" "0.1.1" + +"is-extglob@^2.1.1": + "integrity" "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + "resolved" "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + "version" "2.1.1" + +"is-fullwidth-code-point@^3.0.0": + "integrity" "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + "resolved" "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + "version" "3.0.0" + +"is-glob@^4.0.1", "is-glob@^4.0.3", "is-glob@~4.0.1": + "integrity" "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==" + "resolved" "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" + "version" "4.0.3" + dependencies: + "is-extglob" "^2.1.1" + +"is-hexadecimal@^1.0.0": + "integrity" "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==" + "resolved" "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz" + "version" "1.0.4" + +"is-installed-globally@^0.4.0": + "integrity" "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==" + "resolved" "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz" + "version" "0.4.0" + dependencies: + "global-dirs" "^3.0.0" + "is-path-inside" "^3.0.2" + +"is-npm@^5.0.0": + "integrity" "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==" + "resolved" "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz" + "version" "5.0.0" + +"is-number@^7.0.0": + "integrity" "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + "resolved" "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + "version" "7.0.0" + +"is-obj@^1.0.1": + "integrity" "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + "resolved" "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz" + "version" "1.0.1" + +"is-obj@^2.0.0": + "integrity" "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" + "resolved" "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz" + "version" "2.0.0" + +"is-path-cwd@^2.2.0": + "integrity" "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==" + "resolved" "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz" + "version" "2.2.0" + +"is-path-inside@^3.0.2": + "integrity" "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" + "resolved" "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" + "version" "3.0.3" + +"is-plain-obj@^2.0.0": + "integrity" "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" + "resolved" "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" + "version" "2.1.0" + +"is-plain-obj@^3.0.0": + "integrity" "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==" + "resolved" "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz" + "version" "3.0.0" + +"is-plain-object@^2.0.4": + "integrity" "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==" + "resolved" "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" + "version" "2.0.4" + dependencies: + "isobject" "^3.0.1" + +"is-regex@^1.0.4": + "integrity" "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==" + "resolved" "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz" + "version" "1.1.4" + dependencies: + "call-bind" "^1.0.2" + "has-tostringtag" "^1.0.0" + +"is-regexp@^1.0.0": + "integrity" "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=" + "resolved" "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz" + "version" "1.0.0" + +"is-root@^2.1.0": + "integrity" "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==" + "resolved" "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz" + "version" "2.1.0" + +"is-stream@^2.0.0": + "integrity" "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + "resolved" "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" + "version" "2.0.1" + +"is-typedarray@^1.0.0": + "integrity" "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "resolved" "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" + "version" "1.0.0" + +"is-whitespace-character@^1.0.0": + "integrity" "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==" + "resolved" "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz" + "version" "1.0.4" + +"is-word-character@^1.0.0": + "integrity" "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==" + "resolved" "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz" + "version" "1.0.4" + +"is-wsl@^2.2.0": + "integrity" "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==" + "resolved" "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz" + "version" "2.2.0" + dependencies: + "is-docker" "^2.0.0" + +"is-yarn-global@^0.3.0": + "integrity" "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" + "resolved" "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz" + "version" "0.3.0" + +"isarray@~1.0.0": + "integrity" "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "resolved" "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + "version" "1.0.0" + +"isarray@0.0.1": + "integrity" "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + "resolved" "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + "version" "0.0.1" + +"isexe@^2.0.0": + "integrity" "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "resolved" "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + "version" "2.0.0" + +"isobject@^3.0.1": + "integrity" "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + "resolved" "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" + "version" "3.0.1" + +"jest-worker@^27.0.2", "jest-worker@^27.4.5": + "integrity" "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==" + "resolved" "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz" + "version" "27.5.1" dependencies: "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^8.0.0" + "merge-stream" "^2.0.0" + "supports-color" "^8.0.0" -joi@^17.4.2, joi@^17.6.0: - version "17.6.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.6.0.tgz#0bb54f2f006c09a96e75ce687957bd04290054b2" - integrity sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw== +"joi@^17.4.2", "joi@^17.6.0": + "integrity" "sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw==" + "resolved" "https://registry.npmjs.org/joi/-/joi-17.6.0.tgz" + "version" "17.6.0" dependencies: "@hapi/hoek" "^9.0.0" "@hapi/topo" "^5.0.0" @@ -4684,2834 +4702,2879 @@ joi@^17.4.2, joi@^17.6.0: "@sideway/formula" "^3.0.0" "@sideway/pinpoint" "^2.0.0" -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= - -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= - -json-parse-better-errors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - -json5@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" - integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== - dependencies: - minimist "^1.2.0" - -json5@^2.1.2: - version "2.2.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" - integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== - dependencies: - minimist "^1.2.5" - -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" +"js-tokens@^3.0.0 || ^4.0.0", "js-tokens@^4.0.0": + "integrity" "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "resolved" "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + "version" "4.0.0" + +"js-yaml@^3.13.1": + "integrity" "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==" + "resolved" "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" + "version" "3.14.1" + dependencies: + "argparse" "^1.0.7" + "esprima" "^4.0.0" + +"js-yaml@^4.0.0": + "integrity" "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==" + "resolved" "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "argparse" "^2.0.1" + +"jsesc@^2.5.1": + "integrity" "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + "resolved" "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" + "version" "2.5.2" + +"jsesc@~0.5.0": + "integrity" "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + "resolved" "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" + "version" "0.5.0" + +"json-buffer@3.0.0": + "integrity" "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + "resolved" "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz" + "version" "3.0.0" + +"json-parse-better-errors@^1.0.2": + "integrity" "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + "resolved" "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz" + "version" "1.0.2" + +"json-parse-even-better-errors@^2.3.0": + "integrity" "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + "resolved" "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" + "version" "2.3.1" + +"json-schema-traverse@^0.4.1": + "integrity" "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "resolved" "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" + "version" "0.4.1" + +"json-schema-traverse@^1.0.0": + "integrity" "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "resolved" "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" + "version" "1.0.0" + +"json5@^1.0.1": + "integrity" "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==" + "resolved" "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "minimist" "^1.2.0" + +"json5@^2.1.2", "json5@^2.2.2": + "integrity" "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" + "resolved" "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" + "version" "2.2.3" + +"jsonfile@^6.0.1": + "integrity" "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==" + "resolved" "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "universalify" "^2.0.0" optionalDependencies: - graceful-fs "^4.1.6" - -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== - dependencies: - json-buffer "3.0.0" - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - -klona@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" - integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== - -latest-version@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" - integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== - dependencies: - package-json "^6.3.0" - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -lilconfig@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.4.tgz#f4507d043d7058b380b6a8f5cb7bcd4b34cee082" - integrity sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA== - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -loader-runner@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" - integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== - -loader-utils@^1.4.0: - version "1.4.2" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd3d151fec01a3" - integrity sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^1.0.1" - -loader-utils@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129" - integrity sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^2.1.2" - -loader-utils@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.0.tgz#bcecc51a7898bee7473d4bc6b845b23af8304d4f" - integrity sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ== - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.assignin@^4.0.9: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" - integrity sha1-uo31+4QesKPoBEIysOJjqNxqKKI= - -lodash.bind@^4.1.4: - version "4.2.1" - resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" - integrity sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU= - -lodash.curry@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.curry/-/lodash.curry-4.1.1.tgz#248e36072ede906501d75966200a86dab8b23170" - integrity sha1-JI42By7ekGUB11lmIAqG2riyMXA= - -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= - -lodash.defaults@^4.0.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" - integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= - -lodash.filter@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace" - integrity sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4= - -lodash.flatten@^4.2.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" - integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= - -lodash.flow@^3.3.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/lodash.flow/-/lodash.flow-3.5.0.tgz#87bf40292b8cf83e4e8ce1a3ae4209e20071675a" - integrity sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o= - -lodash.foreach@^4.3.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" - integrity sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM= - -lodash.map@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" - integrity sha1-dx7Hg540c9nEzeKLGTlMNWL09tM= - -lodash.memoize@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - -lodash.merge@^4.4.0: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.pick@^4.2.1: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" - integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM= - -lodash.reduce@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b" - integrity sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs= - -lodash.reject@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415" - integrity sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU= - -lodash.some@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" - integrity sha1-G7nzFO9ri63tE7VJFpsqlF62jk0= - -lodash.uniq@4.5.0, lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= - -lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lower-case@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" - integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== - dependencies: - tslib "^2.0.3" - -lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -magic-string@^0.25.3: - version "0.25.7" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" - integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== - dependencies: - sourcemap-codec "^1.4.4" - -make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - -markdown-escapes@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535" - integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg== - -mdast-squeeze-paragraphs@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz#7c4c114679c3bee27ef10b58e2e015be79f1ef97" - integrity sha512-zxdPn69hkQ1rm4J+2Cs2j6wDEv7O17TfXTJ33tl/+JPIoEmtV9t2ZzBM5LPHE8QlHsmVD8t3vPKCyY3oH+H8MQ== + "graceful-fs" "^4.1.6" + +"keyv@^3.0.0": + "integrity" "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==" + "resolved" "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "json-buffer" "3.0.0" + +"kind-of@^6.0.0", "kind-of@^6.0.2": + "integrity" "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + "resolved" "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" + "version" "6.0.3" + +"kleur@^3.0.3": + "integrity" "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" + "resolved" "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" + "version" "3.0.3" + +"klona@^2.0.5": + "integrity" "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==" + "resolved" "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz" + "version" "2.0.5" + +"latest-version@^5.1.0": + "integrity" "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==" + "resolved" "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "package-json" "^6.3.0" + +"leven@^3.1.0": + "integrity" "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" + "resolved" "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz" + "version" "3.1.0" + +"lilconfig@^2.0.3": + "integrity" "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==" + "resolved" "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz" + "version" "2.0.4" + +"lines-and-columns@^1.1.6": + "integrity" "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + "resolved" "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" + "version" "1.2.4" + +"loader-runner@^4.2.0": + "integrity" "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==" + "resolved" "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz" + "version" "4.2.0" + +"loader-utils@^1.4.0": + "integrity" "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==" + "resolved" "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz" + "version" "1.4.2" + dependencies: + "big.js" "^5.2.2" + "emojis-list" "^3.0.0" + "json5" "^1.0.1" + +"loader-utils@^2.0.0": + "integrity" "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==" + "resolved" "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "big.js" "^5.2.2" + "emojis-list" "^3.0.0" + "json5" "^2.1.2" + +"loader-utils@^3.2.0": + "integrity" "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==" + "resolved" "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz" + "version" "3.2.0" + +"locate-path@^3.0.0": + "integrity" "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==" + "resolved" "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "p-locate" "^3.0.0" + "path-exists" "^3.0.0" + +"locate-path@^5.0.0": + "integrity" "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==" + "resolved" "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "p-locate" "^4.1.0" + +"locate-path@^6.0.0": + "integrity" "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==" + "resolved" "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "p-locate" "^5.0.0" + +"lodash.assignin@^4.0.9": + "integrity" "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=" + "resolved" "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz" + "version" "4.2.0" + +"lodash.bind@^4.1.4": + "integrity" "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=" + "resolved" "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz" + "version" "4.2.1" + +"lodash.curry@^4.0.1": + "integrity" "sha1-JI42By7ekGUB11lmIAqG2riyMXA=" + "resolved" "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz" + "version" "4.1.1" + +"lodash.debounce@^4.0.8": + "integrity" "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + "resolved" "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" + "version" "4.0.8" + +"lodash.defaults@^4.0.1": + "integrity" "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" + "resolved" "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz" + "version" "4.2.0" + +"lodash.filter@^4.4.0": + "integrity" "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=" + "resolved" "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz" + "version" "4.6.0" + +"lodash.flatten@^4.2.0": + "integrity" "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + "resolved" "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz" + "version" "4.4.0" + +"lodash.flow@^3.3.0": + "integrity" "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o=" + "resolved" "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz" + "version" "3.5.0" + +"lodash.foreach@^4.3.0": + "integrity" "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" + "resolved" "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz" + "version" "4.5.0" + +"lodash.map@^4.4.0": + "integrity" "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=" + "resolved" "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz" + "version" "4.6.0" + +"lodash.memoize@^4.1.2": + "integrity" "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" + "resolved" "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz" + "version" "4.1.2" + +"lodash.merge@^4.4.0": + "integrity" "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "resolved" "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" + "version" "4.6.2" + +"lodash.pick@^4.2.1": + "integrity" "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" + "resolved" "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz" + "version" "4.4.0" + +"lodash.reduce@^4.4.0": + "integrity" "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" + "resolved" "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz" + "version" "4.6.0" + +"lodash.reject@^4.4.0": + "integrity" "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=" + "resolved" "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz" + "version" "4.6.0" + +"lodash.some@^4.4.0": + "integrity" "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" + "resolved" "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz" + "version" "4.6.0" + +"lodash.uniq@^4.5.0", "lodash.uniq@4.5.0": + "integrity" "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + "resolved" "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz" + "version" "4.5.0" + +"lodash@^4.17.14", "lodash@^4.17.19", "lodash@^4.17.20", "lodash@^4.17.21": + "integrity" "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "resolved" "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" + "version" "4.17.21" + +"loose-envify@^1.0.0", "loose-envify@^1.1.0", "loose-envify@^1.2.0", "loose-envify@^1.3.1", "loose-envify@^1.4.0": + "integrity" "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==" + "resolved" "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" + "version" "1.4.0" + dependencies: + "js-tokens" "^3.0.0 || ^4.0.0" + +"lower-case@^2.0.2": + "integrity" "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==" + "resolved" "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "tslib" "^2.0.3" + +"lowercase-keys@^1.0.0", "lowercase-keys@^1.0.1": + "integrity" "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + "resolved" "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz" + "version" "1.0.1" + +"lowercase-keys@^2.0.0": + "integrity" "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" + "resolved" "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz" + "version" "2.0.0" + +"lru-cache@^5.1.1": + "integrity" "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==" + "resolved" "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" + "version" "5.1.1" + dependencies: + "yallist" "^3.0.2" + +"lru-cache@^6.0.0": + "integrity" "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==" + "resolved" "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "yallist" "^4.0.0" + +"magic-string@^0.25.3": + "integrity" "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==" + "resolved" "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz" + "version" "0.25.7" + dependencies: + "sourcemap-codec" "^1.4.4" + +"make-dir@^3.0.0", "make-dir@^3.0.2", "make-dir@^3.1.0": + "integrity" "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==" + "resolved" "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "semver" "^6.0.0" + +"markdown-escapes@^1.0.0": + "integrity" "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==" + "resolved" "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz" + "version" "1.0.4" + +"mdast-squeeze-paragraphs@^4.0.0": + "integrity" "sha512-zxdPn69hkQ1rm4J+2Cs2j6wDEv7O17TfXTJ33tl/+JPIoEmtV9t2ZzBM5LPHE8QlHsmVD8t3vPKCyY3oH+H8MQ==" + "resolved" "https://registry.npmjs.org/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz" + "version" "4.0.0" dependencies: - unist-util-remove "^2.0.0" - -mdast-util-definitions@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz#c5c1a84db799173b4dcf7643cda999e440c24db2" - integrity sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ== - dependencies: - unist-util-visit "^2.0.0" + "unist-util-remove" "^2.0.0" -mdast-util-to-hast@10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz#0cfc82089494c52d46eb0e3edb7a4eb2aea021eb" - integrity sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA== +"mdast-util-definitions@^4.0.0": + "integrity" "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==" + "resolved" "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "unist-util-visit" "^2.0.0" + +"mdast-util-to-hast@10.0.1": + "integrity" "sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA==" + "resolved" "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz" + "version" "10.0.1" dependencies: "@types/mdast" "^3.0.0" "@types/unist" "^2.0.0" - mdast-util-definitions "^4.0.0" - mdurl "^1.0.0" - unist-builder "^2.0.0" - unist-util-generated "^1.0.0" - unist-util-position "^3.0.0" - unist-util-visit "^2.0.0" - -mdast-util-to-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b" - integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w== - -mdn-data@2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" - integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== - -mdurl@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" - integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - -memfs@^3.1.2, memfs@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.1.tgz#b78092f466a0dce054d63d39275b24c71d3f1305" - integrity sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw== - dependencies: - fs-monkey "1.0.3" - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - -micromatch@^4.0.2, micromatch@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== - dependencies: - braces "^3.0.1" - picomatch "^2.2.3" - -mime-db@1.51.0, "mime-db@>= 1.43.0 < 2": - version "1.51.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" - integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== - -mime-db@~1.33.0: - version "1.33.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" - integrity sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ== - -mime-types@2.1.18: - version "2.1.18" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" - integrity sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ== - dependencies: - mime-db "~1.33.0" - -mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: - version "2.1.34" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" - integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== - dependencies: - mime-db "1.51.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -mimic-response@^1.0.0, mimic-response@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - -mini-create-react-context@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz#072171561bfdc922da08a60c2197a497cc2d1d5e" - integrity sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ== + "mdast-util-definitions" "^4.0.0" + "mdurl" "^1.0.0" + "unist-builder" "^2.0.0" + "unist-util-generated" "^1.0.0" + "unist-util-position" "^3.0.0" + "unist-util-visit" "^2.0.0" + +"mdast-util-to-string@^2.0.0": + "integrity" "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==" + "resolved" "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz" + "version" "2.0.0" + +"mdn-data@2.0.14": + "integrity" "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + "resolved" "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz" + "version" "2.0.14" + +"mdurl@^1.0.0": + "integrity" "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" + "resolved" "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz" + "version" "1.0.1" + +"media-typer@0.3.0": + "integrity" "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "resolved" "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + "version" "0.3.0" + +"memfs@^3.1.2", "memfs@^3.4.1": + "integrity" "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==" + "resolved" "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz" + "version" "3.4.1" + dependencies: + "fs-monkey" "1.0.3" + +"merge-descriptors@1.0.1": + "integrity" "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "resolved" "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" + "version" "1.0.1" + +"merge-stream@^2.0.0": + "integrity" "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + "resolved" "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" + "version" "2.0.0" + +"merge2@^1.3.0", "merge2@^1.4.1": + "integrity" "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + "resolved" "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" + "version" "1.4.1" + +"methods@~1.1.2": + "integrity" "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "resolved" "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + "version" "1.1.2" + +"micromatch@^4.0.2", "micromatch@^4.0.4": + "integrity" "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==" + "resolved" "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz" + "version" "4.0.4" + dependencies: + "braces" "^3.0.1" + "picomatch" "^2.2.3" + +"mime-db@>= 1.43.0 < 2", "mime-db@1.51.0": + "integrity" "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" + "resolved" "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz" + "version" "1.51.0" + +"mime-db@~1.33.0": + "integrity" "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + "resolved" "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz" + "version" "1.33.0" + +"mime-types@^2.1.27", "mime-types@^2.1.31", "mime-types@~2.1.17", "mime-types@~2.1.24", "mime-types@~2.1.34": + "integrity" "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==" + "resolved" "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz" + "version" "2.1.34" + dependencies: + "mime-db" "1.51.0" + +"mime-types@2.1.18": + "integrity" "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==" + "resolved" "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz" + "version" "2.1.18" + dependencies: + "mime-db" "~1.33.0" + +"mime@1.6.0": + "integrity" "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + "resolved" "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" + "version" "1.6.0" + +"mimic-fn@^2.1.0": + "integrity" "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + "resolved" "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" + "version" "2.1.0" + +"mimic-response@^1.0.0", "mimic-response@^1.0.1": + "integrity" "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + "resolved" "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz" + "version" "1.0.1" + +"mini-create-react-context@^0.4.0": + "integrity" "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==" + "resolved" "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz" + "version" "0.4.1" dependencies: "@babel/runtime" "^7.12.1" - tiny-warning "^1.0.3" - -mini-css-extract-plugin@^1.6.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-1.6.2.tgz#83172b4fd812f8fc4a09d6f6d16f924f53990ca8" - integrity sha512-WhDvO3SjGm40oV5y26GjMJYjd2UMqrLAGKy5YS2/3QKJy2F7jgynuHTir/tgUUOiNQu5saXHdc8reo7YuhhT4Q== - dependencies: - loader-utils "^2.0.0" - schema-utils "^3.0.0" - webpack-sources "^1.1.0" - -minimalistic-assert@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimatch@3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^3.0.4: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.0, minimist@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" - integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== - -mkdirp@^0.5.5: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" - -mrmime@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.0.tgz#14d387f0585a5233d291baba339b063752a2398b" - integrity sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3, ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -multicast-dns-service-types@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" - integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE= - -multicast-dns@^6.0.1: - version "6.2.3" - resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" - integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== - dependencies: - dns-packet "^1.3.1" - thunky "^1.0.2" - -nanoid@^3.2.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" - integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== - -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - -neo-async@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -no-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" - integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== - dependencies: - lower-case "^2.0.2" - tslib "^2.0.3" - -node-emoji@^1.10.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c" - integrity sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A== - dependencies: - lodash "^4.17.21" - -node-fetch@2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== - dependencies: - whatwg-url "^5.0.0" - -node-forge@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.0.tgz#37a874ea723855f37db091e6c186e5b67a01d4b2" - integrity sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA== - -node-releases@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01" - integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg== - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -normalize-range@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= - -normalize-url@^4.1.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" - integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== - -normalize-url@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" - integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -nprogress@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1" - integrity sha1-y480xTIT2JVyP8urkH6UIq28r7E= - -nth-check@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2" - integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w== - dependencies: - boolbase "^1.0.0" - -nth-check@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" - integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== - dependencies: - boolbase "~1.0.0" - -object-assign@^4.1.0, object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-is@^1.0.1: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -object-keys@^1.0.12, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" - object-keys "^1.1.1" + "tiny-warning" "^1.0.3" + +"mini-css-extract-plugin@^1.6.0": + "integrity" "sha512-WhDvO3SjGm40oV5y26GjMJYjd2UMqrLAGKy5YS2/3QKJy2F7jgynuHTir/tgUUOiNQu5saXHdc8reo7YuhhT4Q==" + "resolved" "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.6.2.tgz" + "version" "1.6.2" + dependencies: + "loader-utils" "^2.0.0" + "schema-utils" "^3.0.0" + "webpack-sources" "^1.1.0" + +"minimalistic-assert@^1.0.0": + "integrity" "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + "resolved" "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" + "version" "1.0.1" + +"minimatch@^3.0.4": + "integrity" "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==" + "resolved" "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" + "version" "3.1.2" + dependencies: + "brace-expansion" "^1.1.7" + +"minimatch@3.0.4": + "integrity" "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==" + "resolved" "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "brace-expansion" "^1.1.7" + +"minimist@^1.2.0", "minimist@^1.2.5": + "integrity" "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==" + "resolved" "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz" + "version" "1.2.7" + +"mkdirp@^0.5.5": + "integrity" "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==" + "resolved" "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz" + "version" "0.5.5" + dependencies: + "minimist" "^1.2.5" + +"mrmime@^1.0.0": + "integrity" "sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ==" + "resolved" "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz" + "version" "1.0.0" + +"ms@^2.1.1", "ms@2.1.3": + "integrity" "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "resolved" "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + "version" "2.1.3" + +"ms@2.0.0": + "integrity" "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "resolved" "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + "version" "2.0.0" + +"ms@2.1.2": + "integrity" "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "resolved" "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" + "version" "2.1.2" + +"multicast-dns-service-types@^1.1.0": + "integrity" "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" + "resolved" "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz" + "version" "1.1.0" + +"multicast-dns@^6.0.1": + "integrity" "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==" + "resolved" "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz" + "version" "6.2.3" + dependencies: + "dns-packet" "^1.3.1" + "thunky" "^1.0.2" + +"nanoid@^3.2.0": + "integrity" "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==" + "resolved" "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz" + "version" "3.3.1" + +"negotiator@0.6.3": + "integrity" "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + "resolved" "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" + "version" "0.6.3" + +"neo-async@^2.6.2": + "integrity" "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + "resolved" "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" + "version" "2.6.2" + +"no-case@^3.0.4": + "integrity" "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==" + "resolved" "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "lower-case" "^2.0.2" + "tslib" "^2.0.3" + +"node-emoji@^1.10.0": + "integrity" "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==" + "resolved" "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz" + "version" "1.11.0" + dependencies: + "lodash" "^4.17.21" + +"node-fetch@2.6.7": + "integrity" "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==" + "resolved" "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz" + "version" "2.6.7" + dependencies: + "whatwg-url" "^5.0.0" + +"node-forge@^1.2.0": + "integrity" "sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA==" + "resolved" "https://registry.npmjs.org/node-forge/-/node-forge-1.3.0.tgz" + "version" "1.3.0" + +"node-releases@^2.0.8": + "integrity" "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" + "resolved" "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz" + "version" "2.0.10" + +"normalize-path@^3.0.0", "normalize-path@~3.0.0": + "integrity" "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + "resolved" "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + "version" "3.0.0" + +"normalize-range@^0.1.2": + "integrity" "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=" + "resolved" "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz" + "version" "0.1.2" + +"normalize-url@^4.1.0": + "integrity" "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==" + "resolved" "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz" + "version" "4.5.1" + +"normalize-url@^6.0.1": + "integrity" "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" + "resolved" "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz" + "version" "6.1.0" + +"npm-run-path@^4.0.1": + "integrity" "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==" + "resolved" "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz" + "version" "4.0.1" + dependencies: + "path-key" "^3.0.0" + +"nprogress@^0.2.0": + "integrity" "sha1-y480xTIT2JVyP8urkH6UIq28r7E=" + "resolved" "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz" + "version" "0.2.0" + +"nth-check@^2.0.1": + "integrity" "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==" + "resolved" "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "boolbase" "^1.0.0" + +"nth-check@~1.0.1": + "integrity" "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==" + "resolved" "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "boolbase" "~1.0.0" + +"object-assign@^4.1.0", "object-assign@^4.1.1": + "integrity" "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "resolved" "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + "version" "4.1.1" + +"object-is@^1.0.1": + "integrity" "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==" + "resolved" "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz" + "version" "1.1.5" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.3" + +"object-keys@^1.0.12", "object-keys@^1.1.1": + "integrity" "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + "resolved" "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" + "version" "1.1.1" + +"object.assign@^4.1.0": + "integrity" "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==" + "resolved" "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "call-bind" "^1.0.0" + "define-properties" "^1.1.3" + "has-symbols" "^1.0.1" + "object-keys" "^1.1.1" -obuf@^1.0.0, obuf@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" - integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== +"obuf@^1.0.0", "obuf@^1.1.2": + "integrity" "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + "resolved" "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz" + "version" "1.1.2" -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" +"on-finished@~2.3.0": + "integrity" "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=" + "resolved" "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" + "version" "2.3.0" + dependencies: + "ee-first" "1.1.1" -on-headers@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== - -once@^1.3.0, once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" +"on-headers@~1.0.2": + "integrity" "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + "resolved" "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz" + "version" "1.0.2" + +"once@^1.3.0", "once@^1.3.1", "once@^1.4.0": + "integrity" "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=" + "resolved" "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + "version" "1.4.0" + dependencies: + "wrappy" "1" -onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== +"onetime@^5.1.2": + "integrity" "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==" + "resolved" "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" + "version" "5.1.2" dependencies: - mimic-fn "^2.1.0" + "mimic-fn" "^2.1.0" -open@^8.0.9, open@^8.4.0: - version "8.4.0" - resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" - integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q== +"open@^8.0.9", "open@^8.4.0": + "integrity" "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==" + "resolved" "https://registry.npmjs.org/open/-/open-8.4.0.tgz" + "version" "8.4.0" dependencies: - define-lazy-prop "^2.0.0" - is-docker "^2.1.1" - is-wsl "^2.2.0" + "define-lazy-prop" "^2.0.0" + "is-docker" "^2.1.1" + "is-wsl" "^2.2.0" -opener@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" - integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== +"opener@^1.5.2": + "integrity" "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==" + "resolved" "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz" + "version" "1.5.2" -p-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== +"p-cancelable@^1.0.0": + "integrity" "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" + "resolved" "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz" + "version" "1.1.0" -p-limit@^2.0.0, p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== +"p-limit@^2.0.0", "p-limit@^2.2.0": + "integrity" "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==" + "resolved" "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" + "version" "2.3.0" dependencies: - p-try "^2.0.0" + "p-try" "^2.0.0" -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== +"p-limit@^3.0.2": + "integrity" "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==" + "resolved" "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" + "version" "3.1.0" dependencies: - yocto-queue "^0.1.0" + "yocto-queue" "^0.1.0" -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== +"p-locate@^3.0.0": + "integrity" "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==" + "resolved" "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz" + "version" "3.0.0" dependencies: - p-limit "^2.0.0" + "p-limit" "^2.0.0" -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== +"p-locate@^4.1.0": + "integrity" "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==" + "resolved" "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" + "version" "4.1.0" dependencies: - p-limit "^2.2.0" + "p-limit" "^2.2.0" -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== +"p-locate@^5.0.0": + "integrity" "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==" + "resolved" "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" + "version" "5.0.0" dependencies: - p-limit "^3.0.2" + "p-limit" "^3.0.2" -p-map@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" - integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== +"p-map@^4.0.0": + "integrity" "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==" + "resolved" "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz" + "version" "4.0.0" dependencies: - aggregate-error "^3.0.0" + "aggregate-error" "^3.0.0" -p-retry@^4.5.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.1.tgz#8fcddd5cdf7a67a0911a9cf2ef0e5df7f602316c" - integrity sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA== +"p-retry@^4.5.0": + "integrity" "sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==" + "resolved" "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz" + "version" "4.6.1" dependencies: "@types/retry" "^0.12.0" - retry "^0.13.1" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -package-json@^6.3.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" - integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== - dependencies: - got "^9.6.0" - registry-auth-token "^4.0.0" - registry-url "^5.0.0" - semver "^6.2.0" - -param-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" - integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== - dependencies: - dot-case "^3.0.4" - tslib "^2.0.3" - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-entities@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" - integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ== - dependencies: - character-entities "^1.0.0" - character-entities-legacy "^1.0.0" - character-reference-invalid "^1.0.0" - is-alphanumerical "^1.0.0" - is-decimal "^1.0.0" - is-hexadecimal "^1.0.0" - -parse-json@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + "retry" "^0.13.1" + +"p-try@^2.0.0": + "integrity" "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + "resolved" "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" + "version" "2.2.0" + +"package-json@^6.3.0": + "integrity" "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==" + "resolved" "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz" + "version" "6.5.0" + dependencies: + "got" "^9.6.0" + "registry-auth-token" "^4.0.0" + "registry-url" "^5.0.0" + "semver" "^6.2.0" + +"param-case@^3.0.4": + "integrity" "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==" + "resolved" "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "dot-case" "^3.0.4" + "tslib" "^2.0.3" + +"parent-module@^1.0.0": + "integrity" "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==" + "resolved" "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "callsites" "^3.0.0" + +"parse-entities@^2.0.0": + "integrity" "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==" + "resolved" "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "character-entities" "^1.0.0" + "character-entities-legacy" "^1.0.0" + "character-reference-invalid" "^1.0.0" + "is-alphanumerical" "^1.0.0" + "is-decimal" "^1.0.0" + "is-hexadecimal" "^1.0.0" + +"parse-json@^5.0.0": + "integrity" "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==" + "resolved" "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" + "version" "5.2.0" dependencies: "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -parse-numeric-range@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz#7c63b61190d61e4d53a1197f0c83c47bb670ffa3" - integrity sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ== - -parse5-htmlparser2-tree-adapter@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" - integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA== - dependencies: - parse5 "^6.0.1" - -parse5@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" - integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== - -parse5@^6.0.0, parse5@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" - integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== - -parseurl@~1.3.2, parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -pascal-case@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" - integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-is-inside@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= - -path-to-regexp@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.2.1.tgz#90b617025a16381a879bc82a38d4e8bdeb2bcf45" - integrity sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ== - -path-to-regexp@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" - integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== - dependencies: - isarray "0.0.1" - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pkg-dir@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -pkg-up@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" - integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== - dependencies: - find-up "^3.0.0" - -portfinder@^1.0.28: - version "1.0.28" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" - integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== - dependencies: - async "^2.6.2" - debug "^3.1.1" - mkdirp "^0.5.5" - -postcss-calc@^8.2.0: - version "8.2.4" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5" - integrity sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q== - dependencies: - postcss-selector-parser "^6.0.9" - postcss-value-parser "^4.2.0" - -postcss-colormin@^5.2.5: - version "5.2.5" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.2.5.tgz#d1fc269ac2ad03fe641d462b5d1dada35c69968a" - integrity sha512-+X30aDaGYq81mFqwyPpnYInsZQnNpdxMX0ajlY7AExCexEFkPVV+KrO7kXwayqEWL2xwEbNQ4nUO0ZsRWGnevg== - dependencies: - browserslist "^4.16.6" - caniuse-api "^3.0.0" - colord "^2.9.1" - postcss-value-parser "^4.2.0" - -postcss-convert-values@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.0.4.tgz#3e74dd97c581f475ae7b4500bc0a7c4fb3a6b1b6" - integrity sha512-bugzSAyjIexdObovsPZu/sBCTHccImJxLyFgeV0MmNBm/Lw5h5XnjfML6gzEmJ3A6nyfCW7hb1JXzcsA4Zfbdw== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-discard-comments@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.0.3.tgz#011acb63418d600fdbe18804e1bbecb543ad2f87" - integrity sha512-6W5BemziRoqIdAKT+1QjM4bNcJAQ7z7zk073730NHg4cUXh3/rQHHj7pmYxUB9aGhuRhBiUf0pXvIHkRwhQP0Q== - -postcss-discard-duplicates@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.3.tgz#10f202a4cfe9d407b73dfea7a477054d21ea0c1f" - integrity sha512-vPtm1Mf+kp7iAENTG7jI1MN1lk+fBqL5y+qxyi4v3H+lzsXEdfS3dwUZD45KVhgzDEgduur8ycB4hMegyMTeRw== - -postcss-discard-empty@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.0.3.tgz#ec185af4a3710b88933b0ff751aa157b6041dd6a" - integrity sha512-xGJugpaXKakwKI7sSdZjUuN4V3zSzb2Y0LOlmTajFbNinEjTfVs9PFW2lmKBaC/E64WwYppfqLD03P8l9BuueA== - -postcss-discard-overridden@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.0.4.tgz#cc999d6caf18ea16eff8b2b58f48ec3ddee35c9c" - integrity sha512-3j9QH0Qh1KkdxwiZOW82cId7zdwXVQv/gRXYDnwx5pBtR1sTkU4cXRK9lp5dSdiM0r0OICO/L8J6sV1/7m0kHg== - -postcss-discard-unused@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-5.0.3.tgz#89fd3ebdbed8320df77a4ad503bd83cff52409f5" - integrity sha512-WO6FJxL5fGnuE77ZbTcZ/nRZJ4+TOqNaqLBLWgkR4e+WdmHn77OHPyQmsRv7eOB2rLKL6tsq2bs1GwoKXD/++Q== - dependencies: - postcss-selector-parser "^6.0.5" - -postcss-loader@^6.1.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-6.2.1.tgz#0895f7346b1702103d30fdc66e4d494a93c008ef" - integrity sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q== - dependencies: - cosmiconfig "^7.0.0" - klona "^2.0.5" - semver "^7.3.5" - -postcss-merge-idents@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-5.0.3.tgz#04f333f32767bd7b7b002f0032da347ec3c8c484" - integrity sha512-Z4LCzh2WzMn69KaS2FaJcrIeDQ170V13QHq+0hnBEFKJJkD+y5qndZ/bl3AhpddrSrXWIVR+xAwjmHQIJI2Eog== - dependencies: - cssnano-utils "^3.0.2" - postcss-value-parser "^4.2.0" - -postcss-merge-longhand@^5.0.6: - version "5.0.6" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.0.6.tgz#090e60d5d3b3caad899f8774f8dccb33217d2166" - integrity sha512-rkmoPwQO6ymJSmWsX6l2hHeEBQa7C4kJb9jyi5fZB1sE8nSCv7sqchoYPixRwX/yvLoZP2y6FA5kcjiByeJqDg== - dependencies: - postcss-value-parser "^4.2.0" - stylehacks "^5.0.3" - -postcss-merge-rules@^5.0.6: - version "5.0.6" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.0.6.tgz#26b37411fe1e80202fcef61cab027265b8925f2b" - integrity sha512-nzJWJ9yXWp8AOEpn/HFAW72WKVGD2bsLiAmgw4hDchSij27bt6TF+sIK0cJUBAYT3SGcjtGGsOR89bwkkMuMgQ== + "error-ex" "^1.3.1" + "json-parse-even-better-errors" "^2.3.0" + "lines-and-columns" "^1.1.6" + +"parse-numeric-range@^1.3.0": + "integrity" "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" + "resolved" "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz" + "version" "1.3.0" + +"parse5-htmlparser2-tree-adapter@^6.0.1": + "integrity" "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==" + "resolved" "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "parse5" "^6.0.1" + +"parse5@^5.0.0": + "integrity" "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + "resolved" "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz" + "version" "5.1.1" + +"parse5@^6.0.0", "parse5@^6.0.1": + "integrity" "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + "resolved" "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz" + "version" "6.0.1" + +"parseurl@~1.3.2", "parseurl@~1.3.3": + "integrity" "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + "resolved" "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" + "version" "1.3.3" + +"pascal-case@^3.1.2": + "integrity" "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==" + "resolved" "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz" + "version" "3.1.2" + dependencies: + "no-case" "^3.0.4" + "tslib" "^2.0.3" + +"path-exists@^3.0.0": + "integrity" "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + "resolved" "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" + "version" "3.0.0" + +"path-exists@^4.0.0": + "integrity" "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + "resolved" "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" + "version" "4.0.0" + +"path-is-absolute@^1.0.0": + "integrity" "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "resolved" "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + "version" "1.0.1" + +"path-is-inside@1.0.2": + "integrity" "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + "resolved" "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz" + "version" "1.0.2" + +"path-key@^3.0.0", "path-key@^3.1.0": + "integrity" "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + "resolved" "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" + "version" "3.1.1" + +"path-parse@^1.0.7": + "integrity" "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "resolved" "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + "version" "1.0.7" + +"path-to-regexp@^1.7.0": + "integrity" "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==" + "resolved" "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz" + "version" "1.8.0" + dependencies: + "isarray" "0.0.1" + +"path-to-regexp@0.1.7": + "integrity" "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "resolved" "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" + "version" "0.1.7" + +"path-to-regexp@2.2.1": + "integrity" "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" + "resolved" "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz" + "version" "2.2.1" + +"path-type@^4.0.0": + "integrity" "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + "resolved" "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" + "version" "4.0.0" + +"picocolors@^1.0.0": + "integrity" "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "resolved" "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" + "version" "1.0.0" + +"picomatch@^2.0.4", "picomatch@^2.2.1", "picomatch@^2.2.3": + "integrity" "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + "resolved" "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + "version" "2.3.1" + +"pkg-dir@^4.1.0": + "integrity" "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==" + "resolved" "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" + "version" "4.2.0" + dependencies: + "find-up" "^4.0.0" + +"pkg-up@^3.1.0": + "integrity" "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==" + "resolved" "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "find-up" "^3.0.0" + +"portfinder@^1.0.28": + "integrity" "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==" + "resolved" "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz" + "version" "1.0.28" + dependencies: + "async" "^2.6.2" + "debug" "^3.1.1" + "mkdirp" "^0.5.5" + +"postcss-calc@^8.2.0": + "integrity" "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==" + "resolved" "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz" + "version" "8.2.4" + dependencies: + "postcss-selector-parser" "^6.0.9" + "postcss-value-parser" "^4.2.0" + +"postcss-colormin@^5.2.5": + "integrity" "sha512-+X30aDaGYq81mFqwyPpnYInsZQnNpdxMX0ajlY7AExCexEFkPVV+KrO7kXwayqEWL2xwEbNQ4nUO0ZsRWGnevg==" + "resolved" "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.2.5.tgz" + "version" "5.2.5" + dependencies: + "browserslist" "^4.16.6" + "caniuse-api" "^3.0.0" + "colord" "^2.9.1" + "postcss-value-parser" "^4.2.0" + +"postcss-convert-values@^5.0.4": + "integrity" "sha512-bugzSAyjIexdObovsPZu/sBCTHccImJxLyFgeV0MmNBm/Lw5h5XnjfML6gzEmJ3A6nyfCW7hb1JXzcsA4Zfbdw==" + "resolved" "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.0.4.tgz" + "version" "5.0.4" + dependencies: + "postcss-value-parser" "^4.2.0" + +"postcss-discard-comments@^5.0.3": + "integrity" "sha512-6W5BemziRoqIdAKT+1QjM4bNcJAQ7z7zk073730NHg4cUXh3/rQHHj7pmYxUB9aGhuRhBiUf0pXvIHkRwhQP0Q==" + "resolved" "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.0.3.tgz" + "version" "5.0.3" + +"postcss-discard-duplicates@^5.0.3": + "integrity" "sha512-vPtm1Mf+kp7iAENTG7jI1MN1lk+fBqL5y+qxyi4v3H+lzsXEdfS3dwUZD45KVhgzDEgduur8ycB4hMegyMTeRw==" + "resolved" "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.3.tgz" + "version" "5.0.3" + +"postcss-discard-empty@^5.0.3": + "integrity" "sha512-xGJugpaXKakwKI7sSdZjUuN4V3zSzb2Y0LOlmTajFbNinEjTfVs9PFW2lmKBaC/E64WwYppfqLD03P8l9BuueA==" + "resolved" "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.0.3.tgz" + "version" "5.0.3" + +"postcss-discard-overridden@^5.0.4": + "integrity" "sha512-3j9QH0Qh1KkdxwiZOW82cId7zdwXVQv/gRXYDnwx5pBtR1sTkU4cXRK9lp5dSdiM0r0OICO/L8J6sV1/7m0kHg==" + "resolved" "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.0.4.tgz" + "version" "5.0.4" + +"postcss-discard-unused@^5.0.3": + "integrity" "sha512-WO6FJxL5fGnuE77ZbTcZ/nRZJ4+TOqNaqLBLWgkR4e+WdmHn77OHPyQmsRv7eOB2rLKL6tsq2bs1GwoKXD/++Q==" + "resolved" "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-5.0.3.tgz" + "version" "5.0.3" + dependencies: + "postcss-selector-parser" "^6.0.5" + +"postcss-loader@^6.1.1": + "integrity" "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==" + "resolved" "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz" + "version" "6.2.1" + dependencies: + "cosmiconfig" "^7.0.0" + "klona" "^2.0.5" + "semver" "^7.3.5" + +"postcss-merge-idents@^5.0.3": + "integrity" "sha512-Z4LCzh2WzMn69KaS2FaJcrIeDQ170V13QHq+0hnBEFKJJkD+y5qndZ/bl3AhpddrSrXWIVR+xAwjmHQIJI2Eog==" + "resolved" "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-5.0.3.tgz" + "version" "5.0.3" + dependencies: + "cssnano-utils" "^3.0.2" + "postcss-value-parser" "^4.2.0" + +"postcss-merge-longhand@^5.0.6": + "integrity" "sha512-rkmoPwQO6ymJSmWsX6l2hHeEBQa7C4kJb9jyi5fZB1sE8nSCv7sqchoYPixRwX/yvLoZP2y6FA5kcjiByeJqDg==" + "resolved" "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.0.6.tgz" + "version" "5.0.6" + dependencies: + "postcss-value-parser" "^4.2.0" + "stylehacks" "^5.0.3" + +"postcss-merge-rules@^5.0.6": + "integrity" "sha512-nzJWJ9yXWp8AOEpn/HFAW72WKVGD2bsLiAmgw4hDchSij27bt6TF+sIK0cJUBAYT3SGcjtGGsOR89bwkkMuMgQ==" + "resolved" "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.0.6.tgz" + "version" "5.0.6" dependencies: - browserslist "^4.16.6" - caniuse-api "^3.0.0" - cssnano-utils "^3.0.2" - postcss-selector-parser "^6.0.5" + "browserslist" "^4.16.6" + "caniuse-api" "^3.0.0" + "cssnano-utils" "^3.0.2" + "postcss-selector-parser" "^6.0.5" -postcss-minify-font-values@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.0.4.tgz#627d824406b0712243221891f40a44fffe1467fd" - integrity sha512-RN6q3tyuEesvyCYYFCRGJ41J1XFvgV+dvYGHr0CeHv8F00yILlN8Slf4t8XW4IghlfZYCeyRrANO6HpJ948ieA== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-minify-gradients@^5.0.6: - version "5.0.6" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.0.6.tgz#b07cef51a93f075e94053fd972ff1cba2eaf6503" - integrity sha512-E/dT6oVxB9nLGUTiY/rG5dX9taugv9cbLNTFad3dKxOO+BQg25Q/xo2z2ddG+ZB1CbkZYaVwx5blY8VC7R/43A== - dependencies: - colord "^2.9.1" - cssnano-utils "^3.0.2" - postcss-value-parser "^4.2.0" +"postcss-minify-font-values@^5.0.4": + "integrity" "sha512-RN6q3tyuEesvyCYYFCRGJ41J1XFvgV+dvYGHr0CeHv8F00yILlN8Slf4t8XW4IghlfZYCeyRrANO6HpJ948ieA==" + "resolved" "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.0.4.tgz" + "version" "5.0.4" + dependencies: + "postcss-value-parser" "^4.2.0" + +"postcss-minify-gradients@^5.0.6": + "integrity" "sha512-E/dT6oVxB9nLGUTiY/rG5dX9taugv9cbLNTFad3dKxOO+BQg25Q/xo2z2ddG+ZB1CbkZYaVwx5blY8VC7R/43A==" + "resolved" "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.0.6.tgz" + "version" "5.0.6" + dependencies: + "colord" "^2.9.1" + "cssnano-utils" "^3.0.2" + "postcss-value-parser" "^4.2.0" -postcss-minify-params@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.0.5.tgz#86cb624358cd45c21946f8c317893f0449396646" - integrity sha512-YBNuq3Rz5LfLFNHb9wrvm6t859b8qIqfXsWeK7wROm3jSKNpO1Y5e8cOyBv6Acji15TgSrAwb3JkVNCqNyLvBg== +"postcss-minify-params@^5.0.5": + "integrity" "sha512-YBNuq3Rz5LfLFNHb9wrvm6t859b8qIqfXsWeK7wROm3jSKNpO1Y5e8cOyBv6Acji15TgSrAwb3JkVNCqNyLvBg==" + "resolved" "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.0.5.tgz" + "version" "5.0.5" dependencies: - browserslist "^4.16.6" - cssnano-utils "^3.0.2" - postcss-value-parser "^4.2.0" + "browserslist" "^4.16.6" + "cssnano-utils" "^3.0.2" + "postcss-value-parser" "^4.2.0" -postcss-minify-selectors@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.1.3.tgz#6ac12d52aa661fd509469d87ab2cebb0a1e3a1b5" - integrity sha512-9RJfTiQEKA/kZhMaEXND893nBqmYQ8qYa/G+uPdVnXF6D/FzpfI6kwBtWEcHx5FqDbA79O9n6fQJfrIj6M8jvQ== +"postcss-minify-selectors@^5.1.3": + "integrity" "sha512-9RJfTiQEKA/kZhMaEXND893nBqmYQ8qYa/G+uPdVnXF6D/FzpfI6kwBtWEcHx5FqDbA79O9n6fQJfrIj6M8jvQ==" + "resolved" "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.1.3.tgz" + "version" "5.1.3" dependencies: - postcss-selector-parser "^6.0.5" + "postcss-selector-parser" "^6.0.5" -postcss-modules-extract-imports@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" - integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== +"postcss-modules-extract-imports@^3.0.0": + "integrity" "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==" + "resolved" "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz" + "version" "3.0.0" -postcss-modules-local-by-default@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" - integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== +"postcss-modules-local-by-default@^4.0.0": + "integrity" "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==" + "resolved" "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz" + "version" "4.0.0" dependencies: - icss-utils "^5.0.0" - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.1.0" + "icss-utils" "^5.0.0" + "postcss-selector-parser" "^6.0.2" + "postcss-value-parser" "^4.1.0" -postcss-modules-scope@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" - integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== +"postcss-modules-scope@^3.0.0": + "integrity" "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==" + "resolved" "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz" + "version" "3.0.0" dependencies: - postcss-selector-parser "^6.0.4" + "postcss-selector-parser" "^6.0.4" -postcss-modules-values@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" - integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== +"postcss-modules-values@^4.0.0": + "integrity" "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==" + "resolved" "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz" + "version" "4.0.0" dependencies: - icss-utils "^5.0.0" + "icss-utils" "^5.0.0" -postcss-normalize-charset@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.0.3.tgz#719fb9f9ca9835fcbd4fed8d6e0d72a79e7b5472" - integrity sha512-iKEplDBco9EfH7sx4ut7R2r/dwTnUqyfACf62Unc9UiyFuI7uUqZZtY+u+qp7g8Qszl/U28HIfcsI3pEABWFfA== +"postcss-normalize-charset@^5.0.3": + "integrity" "sha512-iKEplDBco9EfH7sx4ut7R2r/dwTnUqyfACf62Unc9UiyFuI7uUqZZtY+u+qp7g8Qszl/U28HIfcsI3pEABWFfA==" + "resolved" "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.0.3.tgz" + "version" "5.0.3" -postcss-normalize-display-values@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.3.tgz#94cc82e20c51cc4ffba6b36e9618adc1e50db8c1" - integrity sha512-FIV5FY/qs4Ja32jiDb5mVj5iWBlS3N8tFcw2yg98+8MkRgyhtnBgSC0lxU+16AMHbjX5fbSJgw5AXLMolonuRQ== +"postcss-normalize-display-values@^5.0.3": + "integrity" "sha512-FIV5FY/qs4Ja32jiDb5mVj5iWBlS3N8tFcw2yg98+8MkRgyhtnBgSC0lxU+16AMHbjX5fbSJgw5AXLMolonuRQ==" + "resolved" "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.3.tgz" + "version" "5.0.3" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-positions@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.0.4.tgz#4001f38c99675437b83277836fb4291887fcc6cc" - integrity sha512-qynirjBX0Lc73ROomZE3lzzmXXTu48/QiEzKgMeqh28+MfuHLsuqC9po4kj84igZqqFGovz8F8hf44hA3dPYmQ== +"postcss-normalize-positions@^5.0.4": + "integrity" "sha512-qynirjBX0Lc73ROomZE3lzzmXXTu48/QiEzKgMeqh28+MfuHLsuqC9po4kj84igZqqFGovz8F8hf44hA3dPYmQ==" + "resolved" "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-repeat-style@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.4.tgz#d005adf9ee45fae78b673031a376c0c871315145" - integrity sha512-Innt+wctD7YpfeDR7r5Ik6krdyppyAg2HBRpX88fo5AYzC1Ut/l3xaxACG0KsbX49cO2n5EB13clPwuYVt8cMA== +"postcss-normalize-repeat-style@^5.0.4": + "integrity" "sha512-Innt+wctD7YpfeDR7r5Ik6krdyppyAg2HBRpX88fo5AYzC1Ut/l3xaxACG0KsbX49cO2n5EB13clPwuYVt8cMA==" + "resolved" "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-string@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.0.4.tgz#b5e00a07597e7aa8a871817bfeac2bfaa59c3333" - integrity sha512-Dfk42l0+A1CDnVpgE606ENvdmksttLynEqTQf5FL3XGQOyqxjbo25+pglCUvziicTxjtI2NLUR6KkxyUWEVubQ== +"postcss-normalize-string@^5.0.4": + "integrity" "sha512-Dfk42l0+A1CDnVpgE606ENvdmksttLynEqTQf5FL3XGQOyqxjbo25+pglCUvziicTxjtI2NLUR6KkxyUWEVubQ==" + "resolved" "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-timing-functions@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.3.tgz#47210227bfcba5e52650d7a18654337090de7072" - integrity sha512-QRfjvFh11moN4PYnJ7hia4uJXeFotyK3t2jjg8lM9mswleGsNw2Lm3I5wO+l4k1FzK96EFwEVn8X8Ojrp2gP4g== +"postcss-normalize-timing-functions@^5.0.3": + "integrity" "sha512-QRfjvFh11moN4PYnJ7hia4uJXeFotyK3t2jjg8lM9mswleGsNw2Lm3I5wO+l4k1FzK96EFwEVn8X8Ojrp2gP4g==" + "resolved" "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.3.tgz" + "version" "5.0.3" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-unicode@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.4.tgz#02866096937005cdb2c17116c690f29505a1623d" - integrity sha512-W79Regn+a+eXTzB+oV/8XJ33s3pDyFTND2yDuUCo0Xa3QSy1HtNIfRVPXNubHxjhlqmMFADr3FSCHT84ITW3ig== +"postcss-normalize-unicode@^5.0.4": + "integrity" "sha512-W79Regn+a+eXTzB+oV/8XJ33s3pDyFTND2yDuUCo0Xa3QSy1HtNIfRVPXNubHxjhlqmMFADr3FSCHT84ITW3ig==" + "resolved" "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.4.tgz" + "version" "5.0.4" dependencies: - browserslist "^4.16.6" - postcss-value-parser "^4.2.0" + "browserslist" "^4.16.6" + "postcss-value-parser" "^4.2.0" -postcss-normalize-url@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.0.5.tgz#c39efc12ff119f6f45f0b4f516902b12c8080e3a" - integrity sha512-Ws3tX+PcekYlXh+ycAt0wyzqGthkvVtZ9SZLutMVvHARxcpu4o7vvXcNoiNKyjKuWecnjS6HDI3fjBuDr5MQxQ== +"postcss-normalize-url@^5.0.5": + "integrity" "sha512-Ws3tX+PcekYlXh+ycAt0wyzqGthkvVtZ9SZLutMVvHARxcpu4o7vvXcNoiNKyjKuWecnjS6HDI3fjBuDr5MQxQ==" + "resolved" "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.0.5.tgz" + "version" "5.0.5" dependencies: - normalize-url "^6.0.1" - postcss-value-parser "^4.2.0" + "normalize-url" "^6.0.1" + "postcss-value-parser" "^4.2.0" -postcss-normalize-whitespace@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.4.tgz#1d477e7da23fecef91fc4e37d462272c7b55c5ca" - integrity sha512-wsnuHolYZjMwWZJoTC9jeI2AcjA67v4UuidDrPN9RnX8KIZfE+r2Nd6XZRwHVwUiHmRvKQtxiqo64K+h8/imaw== +"postcss-normalize-whitespace@^5.0.4": + "integrity" "sha512-wsnuHolYZjMwWZJoTC9jeI2AcjA67v4UuidDrPN9RnX8KIZfE+r2Nd6XZRwHVwUiHmRvKQtxiqo64K+h8/imaw==" + "resolved" "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-ordered-values@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.0.5.tgz#e878af822a130c3f3709737e24cb815ca7c6d040" - integrity sha512-mfY7lXpq+8bDEHfP+muqibDPhZ5eP9zgBEF9XRvoQgXcQe2Db3G1wcvjbnfjXG6wYsl+0UIjikqq4ym1V2jGMQ== +"postcss-ordered-values@^5.0.5": + "integrity" "sha512-mfY7lXpq+8bDEHfP+muqibDPhZ5eP9zgBEF9XRvoQgXcQe2Db3G1wcvjbnfjXG6wYsl+0UIjikqq4ym1V2jGMQ==" + "resolved" "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.0.5.tgz" + "version" "5.0.5" dependencies: - cssnano-utils "^3.0.2" - postcss-value-parser "^4.2.0" + "cssnano-utils" "^3.0.2" + "postcss-value-parser" "^4.2.0" -postcss-reduce-idents@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-5.0.3.tgz#b632796275b4fa1a4040799969dd17167eaf4d8b" - integrity sha512-9bj9/Xhwiti0Z35kkguJX4G6yUYVw8S1kRLU4jFSCTEuHu4yJggf4rNUoVnT45lm/vU97Wd593CxspMDbHxy4w== +"postcss-reduce-idents@^5.0.3": + "integrity" "sha512-9bj9/Xhwiti0Z35kkguJX4G6yUYVw8S1kRLU4jFSCTEuHu4yJggf4rNUoVnT45lm/vU97Wd593CxspMDbHxy4w==" + "resolved" "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-5.0.3.tgz" + "version" "5.0.3" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-reduce-initial@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.0.3.tgz#68891594defd648253703bbd8f1093162f19568d" - integrity sha512-c88TkSnQ/Dnwgb4OZbKPOBbCaauwEjbECP5uAuFPOzQ+XdjNjRH7SG0dteXrpp1LlIFEKK76iUGgmw2V0xeieA== +"postcss-reduce-initial@^5.0.3": + "integrity" "sha512-c88TkSnQ/Dnwgb4OZbKPOBbCaauwEjbECP5uAuFPOzQ+XdjNjRH7SG0dteXrpp1LlIFEKK76iUGgmw2V0xeieA==" + "resolved" "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.0.3.tgz" + "version" "5.0.3" dependencies: - browserslist "^4.16.6" - caniuse-api "^3.0.0" + "browserslist" "^4.16.6" + "caniuse-api" "^3.0.0" -postcss-reduce-transforms@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.4.tgz#717e72d30befe857f7d2784dba10eb1157863712" - integrity sha512-VIJB9SFSaL8B/B7AXb7KHL6/GNNbbCHslgdzS9UDfBZYIA2nx8NLY7iD/BXFSO/1sRUILzBTfHCoW5inP37C5g== +"postcss-reduce-transforms@^5.0.4": + "integrity" "sha512-VIJB9SFSaL8B/B7AXb7KHL6/GNNbbCHslgdzS9UDfBZYIA2nx8NLY7iD/BXFSO/1sRUILzBTfHCoW5inP37C5g==" + "resolved" "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: - version "6.0.9" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f" - integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ== +"postcss-selector-parser@^6.0.2", "postcss-selector-parser@^6.0.4", "postcss-selector-parser@^6.0.5", "postcss-selector-parser@^6.0.9": + "integrity" "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==" + "resolved" "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz" + "version" "6.0.9" dependencies: - cssesc "^3.0.0" - util-deprecate "^1.0.2" + "cssesc" "^3.0.0" + "util-deprecate" "^1.0.2" -postcss-sort-media-queries@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/postcss-sort-media-queries/-/postcss-sort-media-queries-4.2.1.tgz#a99bae69ef1098ee3b64a5fa94d258ec240d0355" - integrity sha512-9VYekQalFZ3sdgcTjXMa0dDjsfBVHXlraYJEMiOJ/2iMmI2JGCMavP16z3kWOaRu8NSaJCTgVpB/IVpH5yT9YQ== +"postcss-sort-media-queries@^4.1.0": + "integrity" "sha512-9VYekQalFZ3sdgcTjXMa0dDjsfBVHXlraYJEMiOJ/2iMmI2JGCMavP16z3kWOaRu8NSaJCTgVpB/IVpH5yT9YQ==" + "resolved" "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-4.2.1.tgz" + "version" "4.2.1" dependencies: - sort-css-media-queries "2.0.4" + "sort-css-media-queries" "2.0.4" -postcss-svgo@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.0.4.tgz#cfa8682f47b88f7cd75108ec499e133b43102abf" - integrity sha512-yDKHvULbnZtIrRqhZoA+rxreWpee28JSRH/gy9727u0UCgtpv1M/9WEWY3xySlFa0zQJcqf6oCBJPR5NwkmYpg== +"postcss-svgo@^5.0.4": + "integrity" "sha512-yDKHvULbnZtIrRqhZoA+rxreWpee28JSRH/gy9727u0UCgtpv1M/9WEWY3xySlFa0zQJcqf6oCBJPR5NwkmYpg==" + "resolved" "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-value-parser "^4.2.0" - svgo "^2.7.0" + "postcss-value-parser" "^4.2.0" + "svgo" "^2.7.0" -postcss-unique-selectors@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.0.4.tgz#08e188126b634ddfa615fb1d6c262bafdd64826e" - integrity sha512-5ampwoSDJCxDPoANBIlMgoBcYUHnhaiuLYJR5pj1DLnYQvMRVyFuTA5C3Bvt+aHtiqWpJkD/lXT50Vo1D0ZsAQ== +"postcss-unique-selectors@^5.0.4": + "integrity" "sha512-5ampwoSDJCxDPoANBIlMgoBcYUHnhaiuLYJR5pj1DLnYQvMRVyFuTA5C3Bvt+aHtiqWpJkD/lXT50Vo1D0ZsAQ==" + "resolved" "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.0.4.tgz" + "version" "5.0.4" dependencies: - postcss-selector-parser "^6.0.5" + "postcss-selector-parser" "^6.0.5" -postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" - integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== +"postcss-value-parser@^4.1.0", "postcss-value-parser@^4.2.0": + "integrity" "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "resolved" "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" + "version" "4.2.0" -postcss-zindex@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-5.0.2.tgz#7e48aee54062c93418593035229ea06b92381251" - integrity sha512-KPQFjQu73H35HLHmE8Wv31ygfQoucxD52oRm4FPFv1emYhFMzUQdF8adaXCevFLIHPRp2rRYfbaDiEqZ4YjVtw== +"postcss-zindex@^5.0.2": + "integrity" "sha512-KPQFjQu73H35HLHmE8Wv31ygfQoucxD52oRm4FPFv1emYhFMzUQdF8adaXCevFLIHPRp2rRYfbaDiEqZ4YjVtw==" + "resolved" "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-5.0.2.tgz" + "version" "5.0.2" -postcss@^8.3.11, postcss@^8.3.5, postcss@^8.3.7, postcss@^8.4.5: - version "8.4.6" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.6.tgz#c5ff3c3c457a23864f32cb45ac9b741498a09ae1" - integrity sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA== +"postcss@^7.0.0 || ^8.0.1", "postcss@^8.0.9", "postcss@^8.1.0", "postcss@^8.2.15", "postcss@^8.2.2", "postcss@^8.3.11", "postcss@^8.3.5", "postcss@^8.3.7", "postcss@^8.4.4", "postcss@^8.4.5": + "integrity" "sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA==" + "resolved" "https://registry.npmjs.org/postcss/-/postcss-8.4.6.tgz" + "version" "8.4.6" dependencies: - nanoid "^3.2.0" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= - -pretty-error@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" - integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw== - dependencies: - lodash "^4.17.20" - renderkid "^3.0.0" - -pretty-time@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pretty-time/-/pretty-time-1.1.0.tgz#ffb7429afabb8535c346a34e41873adf3d74dd0e" - integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA== - -prism-react-renderer@^1.2.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.3.1.tgz#88fc9d0df6bed06ca2b9097421349f8c2f24e30d" - integrity sha512-xUeDMEz074d0zc5y6rxiMp/dlC7C+5IDDlaEUlcBOFE2wddz7hz5PNupb087mPwTt7T9BrFmewObfCBuf/LKwQ== - -prismjs@^1.23.0: - version "1.27.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057" - integrity sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA== - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -promise@^7.1.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" - integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== - dependencies: - asap "~2.0.3" - -prompts@^2.4.1, prompts@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" - integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - -prop-types@^15.6.2, prop-types@^15.7.2: - version "15.8.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" - integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.13.1" - -property-information@^5.0.0, property-information@^5.3.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.6.0.tgz#61675545fb23002f245c6540ec46077d4da3ed69" - integrity sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA== - dependencies: - xtend "^4.0.0" - -proxy-addr@~2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" - integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== - dependencies: - forwarded "0.2.0" - ipaddr.js "1.9.1" - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - -punycode@^1.3.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -pupa@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" - integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A== - dependencies: - escape-goat "^2.0.0" - -pure-color@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/pure-color/-/pure-color-1.3.0.tgz#1fe064fb0ac851f0de61320a8bf796836422f33e" - integrity sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4= - -qs@6.9.7: - version "6.9.7" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe" - integrity sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw== - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -queue@6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.2.tgz#b91525283e2315c7553d2efa18d83e76432fed65" - integrity sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA== - dependencies: - inherits "~2.0.3" - -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -range-parser@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= - -range-parser@^1.2.1, range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.3.tgz#8f80305d11c2a0a545c2d9d89d7a0286fcead43c" - integrity sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g== - dependencies: - bytes "3.1.2" - http-errors "1.8.1" - iconv-lite "0.4.24" - unpipe "1.0.0" - -rc@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -react-base16-styling@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/react-base16-styling/-/react-base16-styling-0.6.0.tgz#ef2156d66cf4139695c8a167886cb69ea660792c" - integrity sha1-7yFW1mz0E5aVyKFniGy2nqZgeSw= - dependencies: - base16 "^1.0.0" - lodash.curry "^4.0.1" - lodash.flow "^3.3.0" - pure-color "^1.2.0" - -react-dev-utils@^12.0.0: - version "12.0.0" - resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.0.tgz#4eab12cdb95692a077616770b5988f0adf806526" - integrity sha512-xBQkitdxozPxt1YZ9O1097EJiVpwHr9FoAuEVURCKV0Av8NBERovJauzP7bo1ThvuhZ4shsQ1AJiu4vQpoT1AQ== + "nanoid" "^3.2.0" + "picocolors" "^1.0.0" + "source-map-js" "^1.0.2" + +"prepend-http@^2.0.0": + "integrity" "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + "resolved" "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz" + "version" "2.0.0" + +"pretty-error@^4.0.0": + "integrity" "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==" + "resolved" "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "lodash" "^4.17.20" + "renderkid" "^3.0.0" + +"pretty-time@^1.1.0": + "integrity" "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==" + "resolved" "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz" + "version" "1.1.0" + +"prism-react-renderer@^1.2.1": + "integrity" "sha512-xUeDMEz074d0zc5y6rxiMp/dlC7C+5IDDlaEUlcBOFE2wddz7hz5PNupb087mPwTt7T9BrFmewObfCBuf/LKwQ==" + "resolved" "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-1.3.1.tgz" + "version" "1.3.1" + +"prismjs@^1.23.0": + "integrity" "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==" + "resolved" "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz" + "version" "1.27.0" + +"process-nextick-args@~2.0.0": + "integrity" "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "resolved" "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" + "version" "2.0.1" + +"promise@^7.1.1": + "integrity" "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==" + "resolved" "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz" + "version" "7.3.1" + dependencies: + "asap" "~2.0.3" + +"prompts@^2.4.1", "prompts@^2.4.2": + "integrity" "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==" + "resolved" "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "kleur" "^3.0.3" + "sisteransi" "^1.0.5" + +"prop-types@^15.0.0", "prop-types@^15.6.2", "prop-types@^15.7.2": + "integrity" "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==" + "resolved" "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" + "version" "15.8.1" + dependencies: + "loose-envify" "^1.4.0" + "object-assign" "^4.1.1" + "react-is" "^16.13.1" + +"property-information@^5.0.0", "property-information@^5.3.0": + "integrity" "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==" + "resolved" "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz" + "version" "5.6.0" + dependencies: + "xtend" "^4.0.0" + +"proxy-addr@~2.0.7": + "integrity" "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==" + "resolved" "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" + "version" "2.0.7" + dependencies: + "forwarded" "0.2.0" + "ipaddr.js" "1.9.1" + +"pump@^3.0.0": + "integrity" "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==" + "resolved" "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "end-of-stream" "^1.1.0" + "once" "^1.3.1" + +"punycode@^1.3.2": + "integrity" "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + "resolved" "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" + "version" "1.4.1" + +"punycode@^2.1.0": + "integrity" "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "resolved" "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz" + "version" "2.1.1" + +"punycode@1.3.2": + "integrity" "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + "resolved" "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" + "version" "1.3.2" + +"pupa@^2.1.1": + "integrity" "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==" + "resolved" "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz" + "version" "2.1.1" + dependencies: + "escape-goat" "^2.0.0" + +"pure-color@^1.2.0": + "integrity" "sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4=" + "resolved" "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz" + "version" "1.3.0" + +"qs@6.9.7": + "integrity" "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" + "resolved" "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz" + "version" "6.9.7" + +"querystring@0.2.0": + "integrity" "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + "resolved" "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" + "version" "0.2.0" + +"queue-microtask@^1.2.2": + "integrity" "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" + "resolved" "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + "version" "1.2.3" + +"queue@6.0.2": + "integrity" "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==" + "resolved" "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz" + "version" "6.0.2" + dependencies: + "inherits" "~2.0.3" + +"randombytes@^2.1.0": + "integrity" "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==" + "resolved" "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "safe-buffer" "^5.1.0" + +"range-parser@^1.2.1", "range-parser@~1.2.1": + "integrity" "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + "resolved" "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" + "version" "1.2.1" + +"range-parser@1.2.0": + "integrity" "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + "resolved" "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz" + "version" "1.2.0" + +"raw-body@2.4.3": + "integrity" "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==" + "resolved" "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz" + "version" "2.4.3" + dependencies: + "bytes" "3.1.2" + "http-errors" "1.8.1" + "iconv-lite" "0.4.24" + "unpipe" "1.0.0" + +"rc@^1.2.8": + "integrity" "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==" + "resolved" "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz" + "version" "1.2.8" + dependencies: + "deep-extend" "^0.6.0" + "ini" "~1.3.0" + "minimist" "^1.2.0" + "strip-json-comments" "~2.0.1" + +"react-base16-styling@^0.6.0": + "integrity" "sha1-7yFW1mz0E5aVyKFniGy2nqZgeSw=" + "resolved" "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.6.0.tgz" + "version" "0.6.0" + dependencies: + "base16" "^1.0.0" + "lodash.curry" "^4.0.1" + "lodash.flow" "^3.3.0" + "pure-color" "^1.2.0" + +"react-dev-utils@^12.0.0": + "integrity" "sha512-xBQkitdxozPxt1YZ9O1097EJiVpwHr9FoAuEVURCKV0Av8NBERovJauzP7bo1ThvuhZ4shsQ1AJiu4vQpoT1AQ==" + "resolved" "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz" + "version" "12.0.0" dependencies: "@babel/code-frame" "^7.16.0" - address "^1.1.2" - browserslist "^4.18.1" - chalk "^4.1.2" - cross-spawn "^7.0.3" - detect-port-alt "^1.1.6" - escape-string-regexp "^4.0.0" - filesize "^8.0.6" - find-up "^5.0.0" - fork-ts-checker-webpack-plugin "^6.5.0" - global-modules "^2.0.0" - globby "^11.0.4" - gzip-size "^6.0.0" - immer "^9.0.7" - is-root "^2.1.0" - loader-utils "^3.2.0" - open "^8.4.0" - pkg-up "^3.1.0" - prompts "^2.4.2" - react-error-overlay "^6.0.10" - recursive-readdir "^2.2.2" - shell-quote "^1.7.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" - -react-dom@^16.10.2: - version "16.14.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.14.0.tgz#7ad838ec29a777fb3c75c3a190f661cf92ab8b89" - integrity sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - scheduler "^0.19.1" - -react-error-overlay@^6.0.10: - version "6.0.10" - resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.10.tgz#0fe26db4fa85d9dbb8624729580e90e7159a59a6" - integrity sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA== - -react-fast-compare@^3.1.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" - integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== - -react-helmet@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-6.1.0.tgz#a750d5165cb13cf213e44747502652e794468726" - integrity sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw== - dependencies: - object-assign "^4.1.1" - prop-types "^15.7.2" - react-fast-compare "^3.1.1" - react-side-effect "^2.1.0" - -react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -react-json-view@^1.21.3: - version "1.21.3" - resolved "https://registry.yarnpkg.com/react-json-view/-/react-json-view-1.21.3.tgz#f184209ee8f1bf374fb0c41b0813cff54549c475" - integrity sha512-13p8IREj9/x/Ye4WI/JpjhoIwuzEgUAtgJZNBJckfzJt1qyh24BdTm6UQNGnyTq9dapQdrqvquZTo3dz1X6Cjw== - dependencies: - flux "^4.0.1" - react-base16-styling "^0.6.0" - react-lifecycles-compat "^3.0.4" - react-textarea-autosize "^8.3.2" - -react-lifecycles-compat@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" - integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== - -react-loadable-ssr-addon-v5-slorber@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz#2cdc91e8a744ffdf9e3556caabeb6e4278689883" - integrity sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A== + "address" "^1.1.2" + "browserslist" "^4.18.1" + "chalk" "^4.1.2" + "cross-spawn" "^7.0.3" + "detect-port-alt" "^1.1.6" + "escape-string-regexp" "^4.0.0" + "filesize" "^8.0.6" + "find-up" "^5.0.0" + "fork-ts-checker-webpack-plugin" "^6.5.0" + "global-modules" "^2.0.0" + "globby" "^11.0.4" + "gzip-size" "^6.0.0" + "immer" "^9.0.7" + "is-root" "^2.1.0" + "loader-utils" "^3.2.0" + "open" "^8.4.0" + "pkg-up" "^3.1.0" + "prompts" "^2.4.2" + "react-error-overlay" "^6.0.10" + "recursive-readdir" "^2.2.2" + "shell-quote" "^1.7.3" + "strip-ansi" "^6.0.1" + "text-table" "^0.2.0" + +"react-dom@*", "react-dom@^16.10.2", "react-dom@^16.8.4 || ^17.0.0", "react-dom@^17.0.0 || ^16.3.0 || ^15.5.4", "react-dom@>= 16.8.0 < 18.0.0": + "integrity" "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==" + "resolved" "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz" + "version" "16.14.0" + dependencies: + "loose-envify" "^1.1.0" + "object-assign" "^4.1.1" + "prop-types" "^15.6.2" + "scheduler" "^0.19.1" + +"react-error-overlay@^6.0.10": + "integrity" "sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA==" + "resolved" "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz" + "version" "6.0.10" + +"react-fast-compare@^3.1.1": + "integrity" "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" + "resolved" "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz" + "version" "3.2.0" + +"react-helmet@^6.1.0": + "integrity" "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==" + "resolved" "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "object-assign" "^4.1.1" + "prop-types" "^15.7.2" + "react-fast-compare" "^3.1.1" + "react-side-effect" "^2.1.0" + +"react-is@^16.13.1", "react-is@^16.6.0", "react-is@^16.7.0": + "integrity" "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "resolved" "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" + "version" "16.13.1" + +"react-json-view@^1.21.3": + "integrity" "sha512-13p8IREj9/x/Ye4WI/JpjhoIwuzEgUAtgJZNBJckfzJt1qyh24BdTm6UQNGnyTq9dapQdrqvquZTo3dz1X6Cjw==" + "resolved" "https://registry.npmjs.org/react-json-view/-/react-json-view-1.21.3.tgz" + "version" "1.21.3" + dependencies: + "flux" "^4.0.1" + "react-base16-styling" "^0.6.0" + "react-lifecycles-compat" "^3.0.4" + "react-textarea-autosize" "^8.3.2" + +"react-lifecycles-compat@^3.0.4": + "integrity" "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + "resolved" "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz" + "version" "3.0.4" + +"react-loadable-ssr-addon-v5-slorber@^1.0.1": + "integrity" "sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==" + "resolved" "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz" + "version" "1.0.1" dependencies: "@babel/runtime" "^7.10.3" -react-popupbox@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/react-popupbox/-/react-popupbox-2.0.8.tgz#9e0c96dcf4ddbbea8d03c28ee6c0634f0d51b791" - integrity sha512-5DT0SxLMIchKgnUkdPwTzvFhtTL5SOQd6n5dzUnnELiimjFE8eaQwL1n58NZUxs9oJsHXF3qQNvcgwEfn8VHrw== +"react-loadable@*", "react-loadable@npm:@docusaurus/react-loadable@5.5.2": + "integrity" "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==" + "resolved" "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz" + "version" "5.5.2" + dependencies: + "@types/react" "*" + "prop-types" "^15.6.2" + +"react-popupbox@^2.0.8": + "integrity" "sha512-5DT0SxLMIchKgnUkdPwTzvFhtTL5SOQd6n5dzUnnELiimjFE8eaQwL1n58NZUxs9oJsHXF3qQNvcgwEfn8VHrw==" + "resolved" "https://registry.npmjs.org/react-popupbox/-/react-popupbox-2.0.8.tgz" + "version" "2.0.8" dependencies: - deepmerge "^1.3.2" - react "^16.3.1" + "deepmerge" "^1.3.2" + "react" "^16.3.1" -react-router-config@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/react-router-config/-/react-router-config-5.1.1.tgz#0f4263d1a80c6b2dc7b9c1902c9526478194a988" - integrity sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg== +"react-router-config@^5.1.1": + "integrity" "sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==" + "resolved" "https://registry.npmjs.org/react-router-config/-/react-router-config-5.1.1.tgz" + "version" "5.1.1" dependencies: "@babel/runtime" "^7.1.2" -react-router-dom@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.0.tgz#da1bfb535a0e89a712a93b97dd76f47ad1f32363" - integrity sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ== +"react-router-dom@^5.2.0": + "integrity" "sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ==" + "resolved" "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.0.tgz" + "version" "5.3.0" dependencies: "@babel/runtime" "^7.12.13" - history "^4.9.0" - loose-envify "^1.3.1" - prop-types "^15.6.2" - react-router "5.2.1" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - -react-router@5.2.1, react-router@^5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.1.tgz#4d2e4e9d5ae9425091845b8dbc6d9d276239774d" - integrity sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ== + "history" "^4.9.0" + "loose-envify" "^1.3.1" + "prop-types" "^15.6.2" + "react-router" "5.2.1" + "tiny-invariant" "^1.0.2" + "tiny-warning" "^1.0.0" + +"react-router@^5.2.0", "react-router@>=5", "react-router@5.2.1": + "integrity" "sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==" + "resolved" "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz" + "version" "5.2.1" dependencies: "@babel/runtime" "^7.12.13" - history "^4.9.0" - hoist-non-react-statics "^3.1.0" - loose-envify "^1.3.1" - mini-create-react-context "^0.4.0" - path-to-regexp "^1.7.0" - prop-types "^15.6.2" - react-is "^16.6.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - -react-side-effect@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-2.1.1.tgz#66c5701c3e7560ab4822a4ee2742dee215d72eb3" - integrity sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ== - -react-textarea-autosize@^8.3.2: - version "8.3.3" - resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz#f70913945369da453fd554c168f6baacd1fa04d8" - integrity sha512-2XlHXK2TDxS6vbQaoPbMOfQ8GK7+irc2fVK6QFIcC8GOnH3zI/v481n+j1L0WaPVvKxwesnY93fEfH++sus2rQ== + "history" "^4.9.0" + "hoist-non-react-statics" "^3.1.0" + "loose-envify" "^1.3.1" + "mini-create-react-context" "^0.4.0" + "path-to-regexp" "^1.7.0" + "prop-types" "^15.6.2" + "react-is" "^16.6.0" + "tiny-invariant" "^1.0.2" + "tiny-warning" "^1.0.0" + +"react-side-effect@^2.1.0": + "integrity" "sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ==" + "resolved" "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.1.tgz" + "version" "2.1.1" + +"react-textarea-autosize@^8.3.2": + "integrity" "sha512-2XlHXK2TDxS6vbQaoPbMOfQ8GK7+irc2fVK6QFIcC8GOnH3zI/v481n+j1L0WaPVvKxwesnY93fEfH++sus2rQ==" + "resolved" "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz" + "version" "8.3.3" dependencies: "@babel/runtime" "^7.10.2" - use-composed-ref "^1.0.0" - use-latest "^1.0.0" - -react@^16.10.2, react@^16.3.1: - version "16.14.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d" - integrity sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - -readable-stream@^2.0.1: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.0.6, readable-stream@^3.1.1: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -reading-time@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/reading-time/-/reading-time-1.5.0.tgz#d2a7f1b6057cb2e169beaf87113cc3411b5bc5bb" - integrity sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg== - -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= - dependencies: - resolve "^1.1.6" - -recursive-readdir@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" - integrity sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg== - dependencies: - minimatch "3.0.4" - -regenerate-unicode-properties@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56" - integrity sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw== - dependencies: - regenerate "^1.4.2" - -regenerate-unicode-properties@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz#54d09c7115e1f53dc2314a974b32c1c344efe326" - integrity sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA== - dependencies: - regenerate "^1.4.2" - -regenerate@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" - integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== - -regenerator-runtime@^0.13.4: - version "0.13.9" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" - integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== - -regenerator-transform@^0.14.2: - version "0.14.5" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" - integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== + "use-composed-ref" "^1.0.0" + "use-latest" "^1.0.0" + +"react@*", "react@^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", "react@^15.0.2 || ^16.0.0 || ^17.0.0", "react@^16.10.2", "react@^16.13.1", "react@^16.13.1 || ^17.0.0", "react@^16.14.0", "react@^16.3.0 || ^17.0.0", "react@^16.3.1", "react@^16.8.0 || ^17.0.0", "react@^16.8.4 || ^17.0.0", "react@^17.0.0 || ^16.3.0 || ^15.5.4", "react@>= 16.8.0 < 18.0.0", "react@>=0.14.9", "react@>=15", "react@>=16.3.0": + "integrity" "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==" + "resolved" "https://registry.npmjs.org/react/-/react-16.14.0.tgz" + "version" "16.14.0" + dependencies: + "loose-envify" "^1.1.0" + "object-assign" "^4.1.1" + "prop-types" "^15.6.2" + +"readable-stream@^2.0.1": + "integrity" "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==" + "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz" + "version" "2.3.7" + dependencies: + "core-util-is" "~1.0.0" + "inherits" "~2.0.3" + "isarray" "~1.0.0" + "process-nextick-args" "~2.0.0" + "safe-buffer" "~5.1.1" + "string_decoder" "~1.1.1" + "util-deprecate" "~1.0.1" + +"readable-stream@^3.0.6", "readable-stream@^3.1.1": + "integrity" "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==" + "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz" + "version" "3.6.0" + dependencies: + "inherits" "^2.0.3" + "string_decoder" "^1.1.1" + "util-deprecate" "^1.0.1" + +"readdirp@~3.6.0": + "integrity" "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==" + "resolved" "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" + "version" "3.6.0" + dependencies: + "picomatch" "^2.2.1" + +"reading-time@^1.5.0": + "integrity" "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==" + "resolved" "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz" + "version" "1.5.0" + +"rechoir@^0.6.2": + "integrity" "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=" + "resolved" "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz" + "version" "0.6.2" + dependencies: + "resolve" "^1.1.6" + +"recursive-readdir@^2.2.2": + "integrity" "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==" + "resolved" "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz" + "version" "2.2.2" + dependencies: + "minimatch" "3.0.4" + +"regenerate-unicode-properties@^10.0.1": + "integrity" "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==" + "resolved" "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz" + "version" "10.0.1" + dependencies: + "regenerate" "^1.4.2" + +"regenerate-unicode-properties@^9.0.0": + "integrity" "sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==" + "resolved" "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz" + "version" "9.0.0" + dependencies: + "regenerate" "^1.4.2" + +"regenerate@^1.4.2": + "integrity" "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + "resolved" "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" + "version" "1.4.2" + +"regenerator-runtime@^0.13.4": + "integrity" "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "resolved" "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz" + "version" "0.13.9" + +"regenerator-transform@^0.14.2": + "integrity" "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==" + "resolved" "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz" + "version" "0.14.5" dependencies: "@babel/runtime" "^7.8.4" -regexp.prototype.flags@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz#b3f4c0059af9e47eca9f3f660e51d81307e72307" - integrity sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -regexpu-core@^4.5.4: - version "4.8.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.8.0.tgz#e5605ba361b67b1718478501327502f4479a98f0" - integrity sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg== - dependencies: - regenerate "^1.4.2" - regenerate-unicode-properties "^9.0.0" - regjsgen "^0.5.2" - regjsparser "^0.7.0" - unicode-match-property-ecmascript "^2.0.0" - unicode-match-property-value-ecmascript "^2.0.0" - -regexpu-core@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.0.1.tgz#c531122a7840de743dcf9c83e923b5560323ced3" - integrity sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw== - dependencies: - regenerate "^1.4.2" - regenerate-unicode-properties "^10.0.1" - regjsgen "^0.6.0" - regjsparser "^0.8.2" - unicode-match-property-ecmascript "^2.0.0" - unicode-match-property-value-ecmascript "^2.0.0" - -registry-auth-token@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" - integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== - dependencies: - rc "^1.2.8" - -registry-url@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" - integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== - dependencies: - rc "^1.2.8" - -regjsgen@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" - integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== - -regjsgen@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.6.0.tgz#83414c5354afd7d6627b16af5f10f41c4e71808d" - integrity sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA== - -regjsparser@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.7.0.tgz#a6b667b54c885e18b52554cb4960ef71187e9968" - integrity sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ== - dependencies: - jsesc "~0.5.0" - -regjsparser@^0.8.2: - version "0.8.4" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.8.4.tgz#8a14285ffcc5de78c5b95d62bbf413b6bc132d5f" - integrity sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA== - dependencies: - jsesc "~0.5.0" - -rehype-parse@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-6.0.2.tgz#aeb3fdd68085f9f796f1d3137ae2b85a98406964" - integrity sha512-0S3CpvpTAgGmnz8kiCyFLGuW5yA4OQhyNTm/nwPopZ7+PI11WnGl1TTWTGv/2hPEe/g2jRLlhVVSsoDH8waRug== - dependencies: - hast-util-from-parse5 "^5.0.0" - parse5 "^5.0.0" - xtend "^4.0.0" - -relateurl@^0.2.7: - version "0.2.7" - resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" - integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= - -remark-admonitions@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/remark-admonitions/-/remark-admonitions-1.2.1.tgz#87caa1a442aa7b4c0cafa04798ed58a342307870" - integrity sha512-Ji6p68VDvD+H1oS95Fdx9Ar5WA2wcDA4kwrrhVU7fGctC6+d3uiMICu7w7/2Xld+lnU7/gi+432+rRbup5S8ow== - dependencies: - rehype-parse "^6.0.2" - unified "^8.4.2" - unist-util-visit "^2.0.1" - -remark-emoji@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/remark-emoji/-/remark-emoji-2.2.0.tgz#1c702090a1525da5b80e15a8f963ef2c8236cac7" - integrity sha512-P3cj9s5ggsUvWw5fS2uzCHJMGuXYRb0NnZqYlNecewXt8QBU9n5vW3DUUKOhepS8F9CwdMx9B8a3i7pqFWAI5w== - dependencies: - emoticon "^3.2.0" - node-emoji "^1.10.0" - unist-util-visit "^2.0.3" - -remark-footnotes@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/remark-footnotes/-/remark-footnotes-2.0.0.tgz#9001c4c2ffebba55695d2dd80ffb8b82f7e6303f" - integrity sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ== - -remark-mdx-remove-exports@^1.6.22: - version "1.6.22" - resolved "https://registry.yarnpkg.com/remark-mdx-remove-exports/-/remark-mdx-remove-exports-1.6.22.tgz#9e34f3d02c9c54b02ca0a1fde946449338d06ecb" - integrity sha512-7g2uiTmTGfz5QyVb+toeX25frbk1Y6yd03RXGPtqx0+DVh86Gb7MkNYbk7H2X27zdZ3CQv1W/JqlFO0Oo8IxVA== - dependencies: - unist-util-remove "2.0.0" - -remark-mdx-remove-imports@^1.6.22: - version "1.6.22" - resolved "https://registry.yarnpkg.com/remark-mdx-remove-imports/-/remark-mdx-remove-imports-1.6.22.tgz#79f711c95359cff437a120d1fbdc1326ec455826" - integrity sha512-lmjAXD8Ltw0TsvBzb45S+Dxx7LTJAtDaMneMAv8LAUIPEyYoKkmGbmVsiF0/pY6mhM1Q16swCmu1TN+ie/vn/A== - dependencies: - unist-util-remove "2.0.0" - -remark-mdx@1.6.22: - version "1.6.22" - resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-1.6.22.tgz#06a8dab07dcfdd57f3373af7f86bd0e992108bbd" - integrity sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ== +"regexp.prototype.flags@^1.2.0": + "integrity" "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==" + "resolved" "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz" + "version" "1.4.1" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.3" + +"regexpu-core@^4.5.4": + "integrity" "sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg==" + "resolved" "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz" + "version" "4.8.0" + dependencies: + "regenerate" "^1.4.2" + "regenerate-unicode-properties" "^9.0.0" + "regjsgen" "^0.5.2" + "regjsparser" "^0.7.0" + "unicode-match-property-ecmascript" "^2.0.0" + "unicode-match-property-value-ecmascript" "^2.0.0" + +"regexpu-core@^5.0.1": + "integrity" "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==" + "resolved" "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "regenerate" "^1.4.2" + "regenerate-unicode-properties" "^10.0.1" + "regjsgen" "^0.6.0" + "regjsparser" "^0.8.2" + "unicode-match-property-ecmascript" "^2.0.0" + "unicode-match-property-value-ecmascript" "^2.0.0" + +"registry-auth-token@^4.0.0": + "integrity" "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==" + "resolved" "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz" + "version" "4.2.1" + dependencies: + "rc" "^1.2.8" + +"registry-url@^5.0.0": + "integrity" "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==" + "resolved" "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "rc" "^1.2.8" + +"regjsgen@^0.5.2": + "integrity" "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==" + "resolved" "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz" + "version" "0.5.2" + +"regjsgen@^0.6.0": + "integrity" "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==" + "resolved" "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz" + "version" "0.6.0" + +"regjsparser@^0.7.0": + "integrity" "sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ==" + "resolved" "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz" + "version" "0.7.0" + dependencies: + "jsesc" "~0.5.0" + +"regjsparser@^0.8.2": + "integrity" "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==" + "resolved" "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz" + "version" "0.8.4" + dependencies: + "jsesc" "~0.5.0" + +"rehype-parse@^6.0.2": + "integrity" "sha512-0S3CpvpTAgGmnz8kiCyFLGuW5yA4OQhyNTm/nwPopZ7+PI11WnGl1TTWTGv/2hPEe/g2jRLlhVVSsoDH8waRug==" + "resolved" "https://registry.npmjs.org/rehype-parse/-/rehype-parse-6.0.2.tgz" + "version" "6.0.2" + dependencies: + "hast-util-from-parse5" "^5.0.0" + "parse5" "^5.0.0" + "xtend" "^4.0.0" + +"relateurl@^0.2.7": + "integrity" "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=" + "resolved" "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz" + "version" "0.2.7" + +"remark-admonitions@^1.2.1": + "integrity" "sha512-Ji6p68VDvD+H1oS95Fdx9Ar5WA2wcDA4kwrrhVU7fGctC6+d3uiMICu7w7/2Xld+lnU7/gi+432+rRbup5S8ow==" + "resolved" "https://registry.npmjs.org/remark-admonitions/-/remark-admonitions-1.2.1.tgz" + "version" "1.2.1" + dependencies: + "rehype-parse" "^6.0.2" + "unified" "^8.4.2" + "unist-util-visit" "^2.0.1" + +"remark-emoji@^2.1.0": + "integrity" "sha512-P3cj9s5ggsUvWw5fS2uzCHJMGuXYRb0NnZqYlNecewXt8QBU9n5vW3DUUKOhepS8F9CwdMx9B8a3i7pqFWAI5w==" + "resolved" "https://registry.npmjs.org/remark-emoji/-/remark-emoji-2.2.0.tgz" + "version" "2.2.0" + dependencies: + "emoticon" "^3.2.0" + "node-emoji" "^1.10.0" + "unist-util-visit" "^2.0.3" + +"remark-footnotes@2.0.0": + "integrity" "sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ==" + "resolved" "https://registry.npmjs.org/remark-footnotes/-/remark-footnotes-2.0.0.tgz" + "version" "2.0.0" + +"remark-mdx-remove-exports@^1.6.22": + "integrity" "sha512-7g2uiTmTGfz5QyVb+toeX25frbk1Y6yd03RXGPtqx0+DVh86Gb7MkNYbk7H2X27zdZ3CQv1W/JqlFO0Oo8IxVA==" + "resolved" "https://registry.npmjs.org/remark-mdx-remove-exports/-/remark-mdx-remove-exports-1.6.22.tgz" + "version" "1.6.22" + dependencies: + "unist-util-remove" "2.0.0" + +"remark-mdx-remove-imports@^1.6.22": + "integrity" "sha512-lmjAXD8Ltw0TsvBzb45S+Dxx7LTJAtDaMneMAv8LAUIPEyYoKkmGbmVsiF0/pY6mhM1Q16swCmu1TN+ie/vn/A==" + "resolved" "https://registry.npmjs.org/remark-mdx-remove-imports/-/remark-mdx-remove-imports-1.6.22.tgz" + "version" "1.6.22" + dependencies: + "unist-util-remove" "2.0.0" + +"remark-mdx@1.6.22": + "integrity" "sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ==" + "resolved" "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz" + "version" "1.6.22" dependencies: "@babel/core" "7.12.9" "@babel/helper-plugin-utils" "7.10.4" "@babel/plugin-proposal-object-rest-spread" "7.12.1" "@babel/plugin-syntax-jsx" "7.12.1" "@mdx-js/util" "1.6.22" - is-alphabetical "1.0.4" - remark-parse "8.0.3" - unified "9.2.0" - -remark-parse@8.0.3: - version "8.0.3" - resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-8.0.3.tgz#9c62aa3b35b79a486454c690472906075f40c7e1" - integrity sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q== - dependencies: - ccount "^1.0.0" - collapse-white-space "^1.0.2" - is-alphabetical "^1.0.0" - is-decimal "^1.0.0" - is-whitespace-character "^1.0.0" - is-word-character "^1.0.0" - markdown-escapes "^1.0.0" - parse-entities "^2.0.0" - repeat-string "^1.5.4" - state-toggle "^1.0.0" - trim "0.0.1" - trim-trailing-lines "^1.0.0" - unherit "^1.0.4" - unist-util-remove-position "^2.0.0" - vfile-location "^3.0.0" - xtend "^4.0.1" - -remark-squeeze-paragraphs@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz#76eb0e085295131c84748c8e43810159c5653ead" - integrity sha512-8qRqmL9F4nuLPIgl92XUuxI3pFxize+F1H0e/W3llTk0UsjJaj01+RrirkMw7P21RKe4X6goQhYRSvNWX+70Rw== - dependencies: - mdast-squeeze-paragraphs "^4.0.0" - -remarkable-admonitions@^0.2.1: - version "0.2.2" - resolved "https://registry.yarnpkg.com/remarkable-admonitions/-/remarkable-admonitions-0.2.2.tgz#8765f9ec66be4f4c651a4e1cfb559dd7f920819c" - integrity sha512-CcMTEcLYmJLXX3IVMk4LyW4oFD2NQxh5FeLzn4k89TAPpyWIeVix/B/g/gDbZAUpCNY9l6heovR5NNIktf8X5A== - -renderkid@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" - integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg== - dependencies: - css-select "^4.1.3" - dom-converter "^0.2.0" - htmlparser2 "^6.1.0" - lodash "^4.17.21" - strip-ansi "^6.0.1" - -repeat-string@^1.5.4: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + "is-alphabetical" "1.0.4" + "remark-parse" "8.0.3" + "unified" "9.2.0" + +"remark-parse@8.0.3": + "integrity" "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==" + "resolved" "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz" + "version" "8.0.3" + dependencies: + "ccount" "^1.0.0" + "collapse-white-space" "^1.0.2" + "is-alphabetical" "^1.0.0" + "is-decimal" "^1.0.0" + "is-whitespace-character" "^1.0.0" + "is-word-character" "^1.0.0" + "markdown-escapes" "^1.0.0" + "parse-entities" "^2.0.0" + "repeat-string" "^1.5.4" + "state-toggle" "^1.0.0" + "trim" "0.0.1" + "trim-trailing-lines" "^1.0.0" + "unherit" "^1.0.4" + "unist-util-remove-position" "^2.0.0" + "vfile-location" "^3.0.0" + "xtend" "^4.0.1" + +"remark-squeeze-paragraphs@4.0.0": + "integrity" "sha512-8qRqmL9F4nuLPIgl92XUuxI3pFxize+F1H0e/W3llTk0UsjJaj01+RrirkMw7P21RKe4X6goQhYRSvNWX+70Rw==" + "resolved" "https://registry.npmjs.org/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "mdast-squeeze-paragraphs" "^4.0.0" + +"remarkable-admonitions@^0.2.1": + "integrity" "sha512-CcMTEcLYmJLXX3IVMk4LyW4oFD2NQxh5FeLzn4k89TAPpyWIeVix/B/g/gDbZAUpCNY9l6heovR5NNIktf8X5A==" + "resolved" "https://registry.npmjs.org/remarkable-admonitions/-/remarkable-admonitions-0.2.2.tgz" + "version" "0.2.2" + +"renderkid@^3.0.0": + "integrity" "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==" + "resolved" "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "css-select" "^4.1.3" + "dom-converter" "^0.2.0" + "htmlparser2" "^6.1.0" + "lodash" "^4.17.21" + "strip-ansi" "^6.0.1" + +"repeat-string@^1.5.4": + "integrity" "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + "resolved" "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" + "version" "1.6.1" + +"require-from-string@^2.0.2": + "integrity" "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + "resolved" "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" + "version" "2.0.2" "require-like@>= 0.1.1": - version "0.1.2" - resolved "https://registry.yarnpkg.com/require-like/-/require-like-0.1.2.tgz#ad6f30c13becd797010c468afa775c0c0a6b47fa" - integrity sha1-rW8wwTvs15cBDEaK+ndcDAprR/o= - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-pathname@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" - integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== - -resolve@^1.1.6, resolve@^1.14.2, resolve@^1.3.2: - version "1.22.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" - integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== - dependencies: - is-core-module "^2.8.1" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -responselike@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= - dependencies: - lowercase-keys "^1.0.0" - -retry@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" - integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -rtl-detect@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/rtl-detect/-/rtl-detect-1.0.4.tgz#40ae0ea7302a150b96bc75af7d749607392ecac6" - integrity sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ== - -rtlcss@^3.3.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-3.5.0.tgz#c9eb91269827a102bac7ae3115dd5d049de636c3" - integrity sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A== - dependencies: - find-up "^5.0.0" - picocolors "^1.0.0" - postcss "^8.3.11" - strip-json-comments "^3.1.1" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -rxjs@^7.5.4: - version "7.5.4" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.4.tgz#3d6bd407e6b7ce9a123e76b1e770dc5761aa368d" - integrity sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ== - dependencies: - tslib "^2.1.0" - -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + "integrity" "sha1-rW8wwTvs15cBDEaK+ndcDAprR/o=" + "resolved" "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz" + "version" "0.1.2" + +"requires-port@^1.0.0": + "integrity" "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + "resolved" "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" + "version" "1.0.0" + +"resolve-from@^4.0.0": + "integrity" "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + "resolved" "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" + "version" "4.0.0" + +"resolve-pathname@^3.0.0": + "integrity" "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + "resolved" "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz" + "version" "3.0.0" + +"resolve@^1.1.6", "resolve@^1.14.2", "resolve@^1.3.2": + "integrity" "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==" + "resolved" "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz" + "version" "1.22.0" + dependencies: + "is-core-module" "^2.8.1" + "path-parse" "^1.0.7" + "supports-preserve-symlinks-flag" "^1.0.0" + +"responselike@^1.0.2": + "integrity" "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=" + "resolved" "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "lowercase-keys" "^1.0.0" + +"retry@^0.13.1": + "integrity" "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" + "resolved" "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz" + "version" "0.13.1" + +"reusify@^1.0.4": + "integrity" "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + "resolved" "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" + "version" "1.0.4" + +"rimraf@^3.0.2": + "integrity" "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==" + "resolved" "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "glob" "^7.1.3" + +"rtl-detect@^1.0.4": + "integrity" "sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ==" + "resolved" "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.0.4.tgz" + "version" "1.0.4" + +"rtlcss@^3.3.0": + "integrity" "sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A==" + "resolved" "https://registry.npmjs.org/rtlcss/-/rtlcss-3.5.0.tgz" + "version" "3.5.0" + dependencies: + "find-up" "^5.0.0" + "picocolors" "^1.0.0" + "postcss" "^8.3.11" + "strip-json-comments" "^3.1.1" + +"run-parallel@^1.1.9": + "integrity" "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==" + "resolved" "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "queue-microtask" "^1.2.2" + +"rxjs@^7.5.4": + "integrity" "sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ==" + "resolved" "https://registry.npmjs.org/rxjs/-/rxjs-7.5.4.tgz" + "version" "7.5.4" + dependencies: + "tslib" "^2.1.0" + +"safe-buffer@^5.0.1", "safe-buffer@^5.1.0", "safe-buffer@>=5.1.0", "safe-buffer@~5.2.0", "safe-buffer@5.2.1": + "integrity" "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + "version" "5.2.1" + +"safe-buffer@~5.1.0", "safe-buffer@~5.1.1": + "integrity" "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + "version" "5.1.2" + +"safe-buffer@5.1.2": + "integrity" "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + "version" "5.1.2" "safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + "integrity" "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "resolved" "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" + "version" "2.1.2" -sax@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== +"sax@^1.2.4": + "integrity" "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + "resolved" "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz" + "version" "1.2.4" -scheduler@^0.19.1: - version "0.19.1" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" - integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA== +"scheduler@^0.19.1": + "integrity" "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==" + "resolved" "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz" + "version" "0.19.1" dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" + "loose-envify" "^1.1.0" + "object-assign" "^4.1.1" -schema-utils@2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" - integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== - dependencies: - "@types/json-schema" "^7.0.4" - ajv "^6.12.2" - ajv-keywords "^3.4.1" - -schema-utils@^2.6.5: - version "2.7.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" - integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== +"schema-utils@^2.6.5": + "integrity" "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==" + "resolved" "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz" + "version" "2.7.1" dependencies: "@types/json-schema" "^7.0.5" - ajv "^6.12.4" - ajv-keywords "^3.5.2" + "ajv" "^6.12.4" + "ajv-keywords" "^3.5.2" -schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" - integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== +"schema-utils@^3.0.0", "schema-utils@^3.1.0", "schema-utils@^3.1.1": + "integrity" "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==" + "resolved" "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz" + "version" "3.1.1" dependencies: "@types/json-schema" "^7.0.8" - ajv "^6.12.5" - ajv-keywords "^3.5.2" + "ajv" "^6.12.5" + "ajv-keywords" "^3.5.2" -schema-utils@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" - integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== +"schema-utils@^4.0.0": + "integrity" "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==" + "resolved" "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz" + "version" "4.0.0" dependencies: "@types/json-schema" "^7.0.9" - ajv "^8.8.0" - ajv-formats "^2.1.1" - ajv-keywords "^5.0.0" - -section-matter@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167" - integrity sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA== - dependencies: - extend-shallow "^2.0.1" - kind-of "^6.0.0" - -select-hose@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" - integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= - -selfsigned@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.0.0.tgz#e927cd5377cbb0a1075302cff8df1042cc2bce5b" - integrity sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ== - dependencies: - node-forge "^1.2.0" - -semver-diff@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" - integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg== - dependencies: - semver "^6.3.0" - -semver@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" - integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== - -semver@^5.4.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: - version "7.3.5" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== - dependencies: - lru-cache "^6.0.0" - -send@0.17.2: - version "0.17.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820" - integrity sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "1.8.1" - mime "1.6.0" - ms "2.1.3" - on-finished "~2.3.0" - range-parser "~1.2.1" - statuses "~1.5.0" - -serialize-javascript@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== - dependencies: - randombytes "^2.1.0" - -serve-handler@^6.1.3: - version "6.1.3" - resolved "https://registry.yarnpkg.com/serve-handler/-/serve-handler-6.1.3.tgz#1bf8c5ae138712af55c758477533b9117f6435e8" - integrity sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w== - dependencies: - bytes "3.0.0" - content-disposition "0.5.2" - fast-url-parser "1.1.3" - mime-types "2.1.18" - minimatch "3.0.4" - path-is-inside "1.0.2" - path-to-regexp "2.2.1" - range-parser "1.2.0" - -serve-index@^1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" - integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= - dependencies: - accepts "~1.3.4" - batch "0.6.1" - debug "2.6.9" - escape-html "~1.0.3" - http-errors "~1.6.2" - mime-types "~2.1.17" - parseurl "~1.3.2" - -serve-static@1.14.2: - version "1.14.2" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa" - integrity sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.2" - -setimmediate@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= - -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -shallow-clone@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" - integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== - dependencies: - kind-of "^6.0.2" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -shell-quote@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" - integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== - -shelljs@^0.8.4: - version "0.8.5" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" - integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - -signal-exit@^3.0.2, signal-exit@^3.0.3: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -sirv@^1.0.7: - version "1.0.19" - resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49" - integrity sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ== + "ajv" "^8.8.0" + "ajv-formats" "^2.1.1" + "ajv-keywords" "^5.0.0" + +"schema-utils@2.7.0": + "integrity" "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==" + "resolved" "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz" + "version" "2.7.0" + dependencies: + "@types/json-schema" "^7.0.4" + "ajv" "^6.12.2" + "ajv-keywords" "^3.4.1" + +"section-matter@^1.0.0": + "integrity" "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==" + "resolved" "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "extend-shallow" "^2.0.1" + "kind-of" "^6.0.0" + +"select-hose@^2.0.0": + "integrity" "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" + "resolved" "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" + "version" "2.0.0" + +"selfsigned@^2.0.0": + "integrity" "sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ==" + "resolved" "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "node-forge" "^1.2.0" + +"semver-diff@^3.1.1": + "integrity" "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==" + "resolved" "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz" + "version" "3.1.1" + dependencies: + "semver" "^6.3.0" + +"semver@^5.4.1": + "integrity" "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "resolved" "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" + "version" "5.7.1" + +"semver@^6.0.0", "semver@^6.1.1", "semver@^6.1.2", "semver@^6.2.0", "semver@^6.3.0": + "integrity" "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "resolved" "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" + "version" "6.3.0" + +"semver@^7.3.2": + "integrity" "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==" + "resolved" "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" + "version" "7.3.5" + dependencies: + "lru-cache" "^6.0.0" + +"semver@^7.3.4": + "integrity" "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==" + "resolved" "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" + "version" "7.3.5" + dependencies: + "lru-cache" "^6.0.0" + +"semver@^7.3.5": + "integrity" "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==" + "resolved" "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" + "version" "7.3.5" + dependencies: + "lru-cache" "^6.0.0" + +"semver@7.0.0": + "integrity" "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" + "resolved" "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz" + "version" "7.0.0" + +"send@0.17.2": + "integrity" "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==" + "resolved" "https://registry.npmjs.org/send/-/send-0.17.2.tgz" + "version" "0.17.2" + dependencies: + "debug" "2.6.9" + "depd" "~1.1.2" + "destroy" "~1.0.4" + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "etag" "~1.8.1" + "fresh" "0.5.2" + "http-errors" "1.8.1" + "mime" "1.6.0" + "ms" "2.1.3" + "on-finished" "~2.3.0" + "range-parser" "~1.2.1" + "statuses" "~1.5.0" + +"serialize-javascript@^6.0.0": + "integrity" "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==" + "resolved" "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "randombytes" "^2.1.0" + +"serve-handler@^6.1.3": + "integrity" "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==" + "resolved" "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz" + "version" "6.1.3" + dependencies: + "bytes" "3.0.0" + "content-disposition" "0.5.2" + "fast-url-parser" "1.1.3" + "mime-types" "2.1.18" + "minimatch" "3.0.4" + "path-is-inside" "1.0.2" + "path-to-regexp" "2.2.1" + "range-parser" "1.2.0" + +"serve-index@^1.9.1": + "integrity" "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=" + "resolved" "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz" + "version" "1.9.1" + dependencies: + "accepts" "~1.3.4" + "batch" "0.6.1" + "debug" "2.6.9" + "escape-html" "~1.0.3" + "http-errors" "~1.6.2" + "mime-types" "~2.1.17" + "parseurl" "~1.3.2" + +"serve-static@1.14.2": + "integrity" "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==" + "resolved" "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz" + "version" "1.14.2" + dependencies: + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "parseurl" "~1.3.3" + "send" "0.17.2" + +"setimmediate@^1.0.5": + "integrity" "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + "resolved" "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" + "version" "1.0.5" + +"setprototypeof@1.1.0": + "integrity" "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + "resolved" "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz" + "version" "1.1.0" + +"setprototypeof@1.2.0": + "integrity" "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "resolved" "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" + "version" "1.2.0" + +"shallow-clone@^3.0.0": + "integrity" "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==" + "resolved" "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "kind-of" "^6.0.2" + +"shebang-command@^2.0.0": + "integrity" "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==" + "resolved" "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "shebang-regex" "^3.0.0" + +"shebang-regex@^3.0.0": + "integrity" "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + "resolved" "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" + "version" "3.0.0" + +"shell-quote@^1.7.3": + "integrity" "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==" + "resolved" "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz" + "version" "1.7.3" + +"shelljs@^0.8.4": + "integrity" "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==" + "resolved" "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz" + "version" "0.8.5" + dependencies: + "glob" "^7.0.0" + "interpret" "^1.0.0" + "rechoir" "^0.6.2" + +"signal-exit@^3.0.2", "signal-exit@^3.0.3": + "integrity" "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + "resolved" "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" + "version" "3.0.7" + +"sirv@^1.0.7": + "integrity" "sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==" + "resolved" "https://registry.npmjs.org/sirv/-/sirv-1.0.19.tgz" + "version" "1.0.19" dependencies: "@polka/url" "^1.0.0-next.20" - mrmime "^1.0.0" - totalist "^1.0.0" + "mrmime" "^1.0.0" + "totalist" "^1.0.0" -sisteransi@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== +"sisteransi@^1.0.5": + "integrity" "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + "resolved" "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" + "version" "1.0.5" -sitemap@^7.0.0: - version "7.1.1" - resolved "https://registry.yarnpkg.com/sitemap/-/sitemap-7.1.1.tgz#eeed9ad6d95499161a3eadc60f8c6dce4bea2bef" - integrity sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg== +"sitemap@^7.0.0": + "integrity" "sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg==" + "resolved" "https://registry.npmjs.org/sitemap/-/sitemap-7.1.1.tgz" + "version" "7.1.1" dependencies: "@types/node" "^17.0.5" "@types/sax" "^1.2.1" - arg "^5.0.0" - sax "^1.2.4" - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slash@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" - integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== - -sockjs@^0.3.21: - version "0.3.24" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" - integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== - dependencies: - faye-websocket "^0.11.3" - uuid "^8.3.2" - websocket-driver "^0.7.4" - -sort-css-media-queries@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/sort-css-media-queries/-/sort-css-media-queries-2.0.4.tgz#b2badfa519cb4a938acbc6d3aaa913d4949dc908" - integrity sha512-PAIsEK/XupCQwitjv7XxoMvYhT7EAfyzI3hsy/MyDgTvc+Ft55ctdkctJLOy6cQejaIC+zjpUL4djFVm2ivOOw== - -source-list-map@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== - -source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== - -source-map-support@~0.5.20: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.5.0: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -sourcemap-codec@^1.4.4: - version "1.4.8" - resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" - integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== - -space-separated-tokens@^1.0.0: - version "1.1.5" - resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" - integrity sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA== - -spdy-transport@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" - integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== - dependencies: - debug "^4.1.0" - detect-node "^2.0.4" - hpack.js "^2.1.6" - obuf "^1.1.2" - readable-stream "^3.0.6" - wbuf "^1.7.3" - -spdy@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" - integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== - dependencies: - debug "^4.1.0" - handle-thing "^2.0.0" - http-deceiver "^1.2.7" - select-hose "^2.0.0" - spdy-transport "^3.0.0" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -stable@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== - -state-toggle@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe" - integrity sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ== - -"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -std-env@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.0.1.tgz#bc4cbc0e438610197e34c2d79c3df30b491f5182" - integrity sha512-mC1Ps9l77/97qeOZc+HrOL7TIaOboHqMZ24dGVQrlxFcpPpfCHpH+qfUT7Dz+6mlG8+JPA1KfBQo19iC/+Ngcw== - -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.2: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -stringify-object@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" - integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== - dependencies: - get-own-enumerable-property-symbols "^3.0.0" - is-obj "^1.0.1" - is-regexp "^1.0.0" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" - integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== - dependencies: - ansi-regex "^6.0.1" - -strip-bom-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" - integrity sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI= - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -style-to-object@0.3.0, style-to-object@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.3.0.tgz#b1b790d205991cc783801967214979ee19a76e46" - integrity sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA== - dependencies: - inline-style-parser "0.1.1" - -stylehacks@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.0.3.tgz#2ef3de567bfa2be716d29a93bf3d208c133e8d04" - integrity sha512-ENcUdpf4yO0E1rubu8rkxI+JGQk4CgjchynZ4bDBJDfqdy+uhTRSWb8/F3Jtu+Bw5MW45Po3/aQGeIyyxgQtxg== - dependencies: - browserslist "^4.16.6" - postcss-selector-parser "^6.0.4" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" + "arg" "^5.0.0" + "sax" "^1.2.4" + +"slash@^3.0.0": + "integrity" "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + "resolved" "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" + "version" "3.0.0" + +"slash@^4.0.0": + "integrity" "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==" + "resolved" "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz" + "version" "4.0.0" + +"sockjs@^0.3.21": + "integrity" "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==" + "resolved" "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz" + "version" "0.3.24" + dependencies: + "faye-websocket" "^0.11.3" + "uuid" "^8.3.2" + "websocket-driver" "^0.7.4" + +"sort-css-media-queries@2.0.4": + "integrity" "sha512-PAIsEK/XupCQwitjv7XxoMvYhT7EAfyzI3hsy/MyDgTvc+Ft55ctdkctJLOy6cQejaIC+zjpUL4djFVm2ivOOw==" + "resolved" "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.0.4.tgz" + "version" "2.0.4" + +"source-list-map@^2.0.0": + "integrity" "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + "resolved" "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz" + "version" "2.0.1" + +"source-map-js@^1.0.2": + "integrity" "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" + "resolved" "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz" + "version" "1.0.2" + +"source-map-support@~0.5.20": + "integrity" "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==" + "resolved" "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" + "version" "0.5.21" + dependencies: + "buffer-from" "^1.0.0" + "source-map" "^0.6.0" + +"source-map@^0.5.0": + "integrity" "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "resolved" "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" + "version" "0.5.7" + +"source-map@^0.6.0", "source-map@^0.6.1", "source-map@~0.6.0", "source-map@~0.6.1": + "integrity" "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "resolved" "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + "version" "0.6.1" + +"sourcemap-codec@^1.4.4": + "integrity" "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + "resolved" "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz" + "version" "1.4.8" + +"space-separated-tokens@^1.0.0": + "integrity" "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==" + "resolved" "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz" + "version" "1.1.5" + +"spdy-transport@^3.0.0": + "integrity" "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==" + "resolved" "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "debug" "^4.1.0" + "detect-node" "^2.0.4" + "hpack.js" "^2.1.6" + "obuf" "^1.1.2" + "readable-stream" "^3.0.6" + "wbuf" "^1.7.3" + +"spdy@^4.0.2": + "integrity" "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==" + "resolved" "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz" + "version" "4.0.2" + dependencies: + "debug" "^4.1.0" + "handle-thing" "^2.0.0" + "http-deceiver" "^1.2.7" + "select-hose" "^2.0.0" + "spdy-transport" "^3.0.0" + +"sprintf-js@~1.0.2": + "integrity" "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "resolved" "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" + "version" "1.0.3" + +"stable@^0.1.8": + "integrity" "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" + "resolved" "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz" + "version" "0.1.8" + +"state-toggle@^1.0.0": + "integrity" "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==" + "resolved" "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz" + "version" "1.0.3" + +"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", "statuses@~1.5.0": + "integrity" "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "resolved" "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" + "version" "1.5.0" + +"std-env@^3.0.1": + "integrity" "sha512-mC1Ps9l77/97qeOZc+HrOL7TIaOboHqMZ24dGVQrlxFcpPpfCHpH+qfUT7Dz+6mlG8+JPA1KfBQo19iC/+Ngcw==" + "resolved" "https://registry.npmjs.org/std-env/-/std-env-3.0.1.tgz" + "version" "3.0.1" + +"string_decoder@^1.1.1": + "integrity" "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==" + "resolved" "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + "version" "1.3.0" + dependencies: + "safe-buffer" "~5.2.0" + +"string_decoder@~1.1.1": + "integrity" "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==" + "resolved" "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "safe-buffer" "~5.1.0" + +"string-width@^4.0.0", "string-width@^4.1.0", "string-width@^4.2.2": + "integrity" "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==" + "resolved" "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + "version" "4.2.3" + dependencies: + "emoji-regex" "^8.0.0" + "is-fullwidth-code-point" "^3.0.0" + "strip-ansi" "^6.0.1" + +"stringify-object@^3.3.0": + "integrity" "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==" + "resolved" "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz" + "version" "3.3.0" + dependencies: + "get-own-enumerable-property-symbols" "^3.0.0" + "is-obj" "^1.0.1" + "is-regexp" "^1.0.0" + +"strip-ansi@^6.0.0", "strip-ansi@^6.0.1": + "integrity" "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==" + "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "ansi-regex" "^5.0.1" + +"strip-ansi@^7.0.0": + "integrity" "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==" + "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz" + "version" "7.0.1" + dependencies: + "ansi-regex" "^6.0.1" + +"strip-bom-string@^1.0.0": + "integrity" "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=" + "resolved" "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz" + "version" "1.0.0" + +"strip-final-newline@^2.0.0": + "integrity" "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" + "resolved" "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz" + "version" "2.0.0" + +"strip-json-comments@^3.1.1": + "integrity" "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" + "resolved" "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + "version" "3.1.1" + +"strip-json-comments@~2.0.1": + "integrity" "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + "resolved" "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" + "version" "2.0.1" + +"style-to-object@^0.3.0", "style-to-object@0.3.0": + "integrity" "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==" + "resolved" "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz" + "version" "0.3.0" + dependencies: + "inline-style-parser" "0.1.1" + +"stylehacks@^5.0.3": + "integrity" "sha512-ENcUdpf4yO0E1rubu8rkxI+JGQk4CgjchynZ4bDBJDfqdy+uhTRSWb8/F3Jtu+Bw5MW45Po3/aQGeIyyxgQtxg==" + "resolved" "https://registry.npmjs.org/stylehacks/-/stylehacks-5.0.3.tgz" + "version" "5.0.3" + dependencies: + "browserslist" "^4.16.6" + "postcss-selector-parser" "^6.0.4" + +"supports-color@^5.3.0": + "integrity" "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + "version" "5.5.0" + dependencies: + "has-flag" "^3.0.0" -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== +"supports-color@^7.1.0": + "integrity" "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + "version" "7.2.0" dependencies: - has-flag "^4.0.0" + "has-flag" "^4.0.0" -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== +"supports-color@^8.0.0": + "integrity" "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" + "version" "8.1.1" dependencies: - has-flag "^4.0.0" + "has-flag" "^4.0.0" -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +"supports-preserve-symlinks-flag@^1.0.0": + "integrity" "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + "resolved" "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" + "version" "1.0.0" -svg-parser@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" - integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== +"svg-parser@^2.0.2": + "integrity" "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + "resolved" "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz" + "version" "2.0.4" -svgo@^2.5.0, svgo@^2.7.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" - integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg== +"svgo@^2.5.0", "svgo@^2.7.0": + "integrity" "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==" + "resolved" "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz" + "version" "2.8.0" dependencies: "@trysound/sax" "0.2.0" - commander "^7.2.0" - css-select "^4.1.3" - css-tree "^1.1.3" - csso "^4.2.0" - picocolors "^1.0.0" - stable "^0.1.8" - -tapable@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" - integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== - -tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== - -terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.2.4: - version "5.3.1" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz#0320dcc270ad5372c1e8993fabbd927929773e54" - integrity sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g== - dependencies: - jest-worker "^27.4.5" - schema-utils "^3.1.1" - serialize-javascript "^6.0.0" - source-map "^0.6.1" - terser "^5.7.2" - -terser@^5.10.0, terser@^5.7.2: - version "5.14.2" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.14.2.tgz#9ac9f22b06994d736174f4091aa368db896f1c10" - integrity sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA== + "commander" "^7.2.0" + "css-select" "^4.1.3" + "css-tree" "^1.1.3" + "csso" "^4.2.0" + "picocolors" "^1.0.0" + "stable" "^0.1.8" + +"tapable@^1.0.0": + "integrity" "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" + "resolved" "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz" + "version" "1.1.3" + +"tapable@^2.0.0", "tapable@^2.1.1", "tapable@^2.2.0": + "integrity" "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" + "resolved" "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz" + "version" "2.2.1" + +"terser-webpack-plugin@^5.1.3", "terser-webpack-plugin@^5.2.4": + "integrity" "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==" + "resolved" "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz" + "version" "5.3.1" + dependencies: + "jest-worker" "^27.4.5" + "schema-utils" "^3.1.1" + "serialize-javascript" "^6.0.0" + "source-map" "^0.6.1" + "terser" "^5.7.2" + +"terser@^5.10.0", "terser@^5.7.2": + "integrity" "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==" + "resolved" "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz" + "version" "5.14.2" dependencies: "@jridgewell/source-map" "^0.3.2" - acorn "^8.5.0" - commander "^2.20.0" - source-map-support "~0.5.20" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - -thunky@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" - integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== - -timsort@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" - integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= - -tiny-invariant@^1.0.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.2.0.tgz#a1141f86b672a9148c72e978a19a73b9b94a15a9" - integrity sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg== - -tiny-warning@^1.0.0, tiny-warning@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" - integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -totalist@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" - integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= - -trim-trailing-lines@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz#bd4abbec7cc880462f10b2c8b5ce1d8d1ec7c2c0" - integrity sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ== - -trim@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" - integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= - -trough@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" - integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== - -tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - -ua-parser-js@^0.7.30: - version "0.7.33" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.33.tgz#1d04acb4ccef9293df6f70f2c3d22f3030d8b532" - integrity sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw== - -unherit@^1.0.4: - version "1.1.3" - resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.3.tgz#6c9b503f2b41b262330c80e91c8614abdaa69c22" - integrity sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ== - dependencies: - inherits "^2.0.0" - xtend "^4.0.0" - -unicode-canonical-property-names-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" - integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== - -unicode-match-property-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" - integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== - dependencies: - unicode-canonical-property-names-ecmascript "^2.0.0" - unicode-property-aliases-ecmascript "^2.0.0" - -unicode-match-property-value-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz#1a01aa57247c14c568b89775a54938788189a714" - integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw== - -unicode-property-aliases-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8" - integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ== - -unified@9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.0.tgz#67a62c627c40589edebbf60f53edfd4d822027f8" - integrity sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg== - dependencies: - bail "^1.0.0" - extend "^3.0.0" - is-buffer "^2.0.0" - is-plain-obj "^2.0.0" - trough "^1.0.0" - vfile "^4.0.0" - -unified@^8.4.2: - version "8.4.2" - resolved "https://registry.yarnpkg.com/unified/-/unified-8.4.2.tgz#13ad58b4a437faa2751a4a4c6a16f680c500fff1" - integrity sha512-JCrmN13jI4+h9UAyKEoGcDZV+i1E7BLFuG7OsaDvTXI5P0qhHX+vZO/kOhz9jn8HGENDKbwSeB0nVOg4gVStGA== - dependencies: - bail "^1.0.0" - extend "^3.0.0" - is-plain-obj "^2.0.0" - trough "^1.0.0" - vfile "^4.0.0" - -unique-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" - integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== - dependencies: - crypto-random-string "^2.0.0" - -unist-builder@2.0.3, unist-builder@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-2.0.3.tgz#77648711b5d86af0942f334397a33c5e91516436" - integrity sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw== - -unist-util-generated@^1.0.0: - version "1.1.6" - resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.6.tgz#5ab51f689e2992a472beb1b35f2ce7ff2f324d4b" - integrity sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg== - -unist-util-is@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797" - integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg== - -unist-util-position@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-3.1.0.tgz#1c42ee6301f8d52f47d14f62bbdb796571fa2d47" - integrity sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA== - -unist-util-remove-position@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz#5d19ca79fdba712301999b2b73553ca8f3b352cc" - integrity sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA== - dependencies: - unist-util-visit "^2.0.0" - -unist-util-remove@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unist-util-remove/-/unist-util-remove-2.0.0.tgz#32c2ad5578802f2ca62ab808173d505b2c898488" - integrity sha512-HwwWyNHKkeg/eXRnE11IpzY8JT55JNM1YCwwU9YNCnfzk6s8GhPXrVBBZWiwLeATJbI7euvoGSzcy9M29UeW3g== - dependencies: - unist-util-is "^4.0.0" - -unist-util-remove@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/unist-util-remove/-/unist-util-remove-2.1.0.tgz#b0b4738aa7ee445c402fda9328d604a02d010588" - integrity sha512-J8NYPyBm4baYLdCbjmf1bhPu45Cr1MWTm77qd9istEkzWpnN6O9tMsEbB2JhNnBCqGENRqEWomQ+He6au0B27Q== - dependencies: - unist-util-is "^4.0.0" - -unist-util-stringify-position@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da" - integrity sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g== + "acorn" "^8.5.0" + "commander" "^2.20.0" + "source-map-support" "~0.5.20" + +"text-table@^0.2.0": + "integrity" "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + "resolved" "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" + "version" "0.2.0" + +"thunky@^1.0.2": + "integrity" "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + "resolved" "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz" + "version" "1.1.0" + +"timsort@^0.3.0": + "integrity" "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" + "resolved" "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz" + "version" "0.3.0" + +"tiny-invariant@^1.0.2": + "integrity" "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==" + "resolved" "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz" + "version" "1.2.0" + +"tiny-warning@^1.0.0", "tiny-warning@^1.0.3": + "integrity" "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + "resolved" "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz" + "version" "1.0.3" + +"to-fast-properties@^2.0.0": + "integrity" "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + "resolved" "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" + "version" "2.0.0" + +"to-readable-stream@^1.0.0": + "integrity" "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" + "resolved" "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz" + "version" "1.0.0" + +"to-regex-range@^5.0.1": + "integrity" "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==" + "resolved" "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "is-number" "^7.0.0" + +"toidentifier@1.0.1": + "integrity" "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + "resolved" "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" + "version" "1.0.1" + +"totalist@^1.0.0": + "integrity" "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==" + "resolved" "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz" + "version" "1.1.0" + +"tr46@~0.0.3": + "integrity" "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + "resolved" "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" + "version" "0.0.3" + +"trim-trailing-lines@^1.0.0": + "integrity" "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==" + "resolved" "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz" + "version" "1.1.4" + +"trim@0.0.1": + "integrity" "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + "resolved" "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz" + "version" "0.0.1" + +"trough@^1.0.0": + "integrity" "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==" + "resolved" "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz" + "version" "1.0.5" + +"tslib@^2.0.3", "tslib@^2.1.0", "tslib@^2.2.0", "tslib@^2.3.1": + "integrity" "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "resolved" "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz" + "version" "2.3.1" + +"type-fest@^0.20.2": + "integrity" "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + "resolved" "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" + "version" "0.20.2" + +"type-is@~1.6.18": + "integrity" "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==" + "resolved" "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" + "version" "1.6.18" + dependencies: + "media-typer" "0.3.0" + "mime-types" "~2.1.24" + +"typedarray-to-buffer@^3.1.5": + "integrity" "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==" + "resolved" "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz" + "version" "3.1.5" + dependencies: + "is-typedarray" "^1.0.0" + +"typescript@>= 2.7": + "integrity" "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==" + "resolved" "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz" + "version" "4.9.5" + +"ua-parser-js@^0.7.30": + "integrity" "sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw==" + "resolved" "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.33.tgz" + "version" "0.7.33" + +"unherit@^1.0.4": + "integrity" "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==" + "resolved" "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz" + "version" "1.1.3" + dependencies: + "inherits" "^2.0.0" + "xtend" "^4.0.0" + +"unicode-canonical-property-names-ecmascript@^2.0.0": + "integrity" "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==" + "resolved" "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz" + "version" "2.0.0" + +"unicode-match-property-ecmascript@^2.0.0": + "integrity" "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==" + "resolved" "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "unicode-canonical-property-names-ecmascript" "^2.0.0" + "unicode-property-aliases-ecmascript" "^2.0.0" + +"unicode-match-property-value-ecmascript@^2.0.0": + "integrity" "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==" + "resolved" "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz" + "version" "2.0.0" + +"unicode-property-aliases-ecmascript@^2.0.0": + "integrity" "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==" + "resolved" "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz" + "version" "2.0.0" + +"unified@^8.4.2": + "integrity" "sha512-JCrmN13jI4+h9UAyKEoGcDZV+i1E7BLFuG7OsaDvTXI5P0qhHX+vZO/kOhz9jn8HGENDKbwSeB0nVOg4gVStGA==" + "resolved" "https://registry.npmjs.org/unified/-/unified-8.4.2.tgz" + "version" "8.4.2" + dependencies: + "bail" "^1.0.0" + "extend" "^3.0.0" + "is-plain-obj" "^2.0.0" + "trough" "^1.0.0" + "vfile" "^4.0.0" + +"unified@9.2.0": + "integrity" "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==" + "resolved" "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz" + "version" "9.2.0" + dependencies: + "bail" "^1.0.0" + "extend" "^3.0.0" + "is-buffer" "^2.0.0" + "is-plain-obj" "^2.0.0" + "trough" "^1.0.0" + "vfile" "^4.0.0" + +"unique-string@^2.0.0": + "integrity" "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==" + "resolved" "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "crypto-random-string" "^2.0.0" + +"unist-builder@^2.0.0", "unist-builder@2.0.3": + "integrity" "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==" + "resolved" "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz" + "version" "2.0.3" + +"unist-util-generated@^1.0.0": + "integrity" "sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==" + "resolved" "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz" + "version" "1.1.6" + +"unist-util-is@^4.0.0": + "integrity" "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==" + "resolved" "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz" + "version" "4.1.0" + +"unist-util-position@^3.0.0": + "integrity" "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA==" + "resolved" "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz" + "version" "3.1.0" + +"unist-util-remove-position@^2.0.0": + "integrity" "sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA==" + "resolved" "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "unist-util-visit" "^2.0.0" + +"unist-util-remove@^2.0.0": + "integrity" "sha512-J8NYPyBm4baYLdCbjmf1bhPu45Cr1MWTm77qd9istEkzWpnN6O9tMsEbB2JhNnBCqGENRqEWomQ+He6au0B27Q==" + "resolved" "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "unist-util-is" "^4.0.0" + +"unist-util-remove@2.0.0": + "integrity" "sha512-HwwWyNHKkeg/eXRnE11IpzY8JT55JNM1YCwwU9YNCnfzk6s8GhPXrVBBZWiwLeATJbI7euvoGSzcy9M29UeW3g==" + "resolved" "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "unist-util-is" "^4.0.0" + +"unist-util-stringify-position@^2.0.0": + "integrity" "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==" + "resolved" "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz" + "version" "2.0.3" dependencies: "@types/unist" "^2.0.2" -unist-util-visit-parents@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz#65a6ce698f78a6b0f56aa0e88f13801886cdaef6" - integrity sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg== +"unist-util-visit-parents@^3.0.0": + "integrity" "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==" + "resolved" "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz" + "version" "3.1.1" dependencies: "@types/unist" "^2.0.0" - unist-util-is "^4.0.0" + "unist-util-is" "^4.0.0" -unist-util-visit@2.0.3, unist-util-visit@^2.0.0, unist-util-visit@^2.0.1, unist-util-visit@^2.0.2, unist-util-visit@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" - integrity sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q== +"unist-util-visit@^2.0.0", "unist-util-visit@^2.0.1", "unist-util-visit@^2.0.2", "unist-util-visit@^2.0.3", "unist-util-visit@2.0.3": + "integrity" "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==" + "resolved" "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz" + "version" "2.0.3" dependencies: "@types/unist" "^2.0.0" - unist-util-is "^4.0.0" - unist-util-visit-parents "^3.0.0" - -universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - -update-notifier@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-5.1.0.tgz#4ab0d7c7f36a231dd7316cf7729313f0214d9ad9" - integrity sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw== - dependencies: - boxen "^5.0.0" - chalk "^4.1.0" - configstore "^5.0.1" - has-yarn "^2.1.0" - import-lazy "^2.1.0" - is-ci "^2.0.0" - is-installed-globally "^0.4.0" - is-npm "^5.0.0" - is-yarn-global "^0.3.0" - latest-version "^5.1.0" - pupa "^2.1.1" - semver "^7.3.4" - semver-diff "^3.1.1" - xdg-basedir "^4.0.0" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -url-loader@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2" - integrity sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA== - dependencies: - loader-utils "^2.0.0" - mime-types "^2.1.27" - schema-utils "^3.0.0" - -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= - dependencies: - prepend-http "^2.0.0" - -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -use-composed-ref@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/use-composed-ref/-/use-composed-ref-1.2.1.tgz#9bdcb5ccd894289105da2325e1210079f56bf849" - integrity sha512-6+X1FLlIcjvFMAeAD/hcxDT8tmyrWnbSPMU0EnxQuDLIxokuFzWliXBiYZuGIx+mrAMLBw0WFfCkaPw8ebzAhw== - -use-isomorphic-layout-effect@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz#7bb6589170cd2987a152042f9084f9effb75c225" - integrity sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ== - -use-latest@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/use-latest/-/use-latest-1.2.0.tgz#a44f6572b8288e0972ec411bdd0840ada366f232" - integrity sha512-d2TEuG6nSLKQLAfW3By8mKr8HurOlTkul0sOpxbClIv4SQ4iOd7BYr7VIzdbktUCnv7dua/60xzd8igMU6jmyw== - dependencies: - use-isomorphic-layout-effect "^1.0.0" - -util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -utila@~0.4: - version "0.4.0" - resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" - integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= - -utility-types@^3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.10.0.tgz#ea4148f9a741015f05ed74fd615e1d20e6bed82b" - integrity sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg== - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - -uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -value-equal@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" - integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== - -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - -vfile-location@^3.0.0, vfile-location@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-3.2.0.tgz#d8e41fbcbd406063669ebf6c33d56ae8721d0f3c" - integrity sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA== - -vfile-message@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.4.tgz#5b43b88171d409eae58477d13f23dd41d52c371a" - integrity sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ== + "unist-util-is" "^4.0.0" + "unist-util-visit-parents" "^3.0.0" + +"universalify@^2.0.0": + "integrity" "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + "resolved" "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz" + "version" "2.0.0" + +"unpipe@~1.0.0", "unpipe@1.0.0": + "integrity" "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "resolved" "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + "version" "1.0.0" + +"update-browserslist-db@^1.0.10": + "integrity" "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==" + "resolved" "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz" + "version" "1.0.10" + dependencies: + "escalade" "^3.1.1" + "picocolors" "^1.0.0" + +"update-notifier@^5.1.0": + "integrity" "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==" + "resolved" "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "boxen" "^5.0.0" + "chalk" "^4.1.0" + "configstore" "^5.0.1" + "has-yarn" "^2.1.0" + "import-lazy" "^2.1.0" + "is-ci" "^2.0.0" + "is-installed-globally" "^0.4.0" + "is-npm" "^5.0.0" + "is-yarn-global" "^0.3.0" + "latest-version" "^5.1.0" + "pupa" "^2.1.1" + "semver" "^7.3.4" + "semver-diff" "^3.1.1" + "xdg-basedir" "^4.0.0" + +"uri-js@^4.2.2": + "integrity" "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==" + "resolved" "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" + "version" "4.4.1" + dependencies: + "punycode" "^2.1.0" + +"url-loader@^4.1.1": + "integrity" "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==" + "resolved" "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz" + "version" "4.1.1" + dependencies: + "loader-utils" "^2.0.0" + "mime-types" "^2.1.27" + "schema-utils" "^3.0.0" + +"url-parse-lax@^3.0.0": + "integrity" "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=" + "resolved" "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "prepend-http" "^2.0.0" + +"url@^0.11.0": + "integrity" "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=" + "resolved" "https://registry.npmjs.org/url/-/url-0.11.0.tgz" + "version" "0.11.0" + dependencies: + "punycode" "1.3.2" + "querystring" "0.2.0" + +"use-composed-ref@^1.0.0": + "integrity" "sha512-6+X1FLlIcjvFMAeAD/hcxDT8tmyrWnbSPMU0EnxQuDLIxokuFzWliXBiYZuGIx+mrAMLBw0WFfCkaPw8ebzAhw==" + "resolved" "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.2.1.tgz" + "version" "1.2.1" + +"use-isomorphic-layout-effect@^1.0.0": + "integrity" "sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ==" + "resolved" "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz" + "version" "1.1.1" + +"use-latest@^1.0.0": + "integrity" "sha512-d2TEuG6nSLKQLAfW3By8mKr8HurOlTkul0sOpxbClIv4SQ4iOd7BYr7VIzdbktUCnv7dua/60xzd8igMU6jmyw==" + "resolved" "https://registry.npmjs.org/use-latest/-/use-latest-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "use-isomorphic-layout-effect" "^1.0.0" + +"util-deprecate@^1.0.1", "util-deprecate@^1.0.2", "util-deprecate@~1.0.1": + "integrity" "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "resolved" "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + "version" "1.0.2" + +"utila@~0.4": + "integrity" "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=" + "resolved" "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz" + "version" "0.4.0" + +"utility-types@^3.10.0": + "integrity" "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==" + "resolved" "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz" + "version" "3.10.0" + +"utils-merge@1.0.1": + "integrity" "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "resolved" "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" + "version" "1.0.1" + +"uuid@^8.3.2": + "integrity" "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + "resolved" "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" + "version" "8.3.2" + +"value-equal@^1.0.1": + "integrity" "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + "resolved" "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz" + "version" "1.0.1" + +"vary@~1.1.2": + "integrity" "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + "resolved" "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" + "version" "1.1.2" + +"vfile-location@^3.0.0", "vfile-location@^3.2.0": + "integrity" "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==" + "resolved" "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz" + "version" "3.2.0" + +"vfile-message@^2.0.0": + "integrity" "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==" + "resolved" "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz" + "version" "2.0.4" dependencies: "@types/unist" "^2.0.0" - unist-util-stringify-position "^2.0.0" + "unist-util-stringify-position" "^2.0.0" -vfile@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.2.1.tgz#03f1dce28fc625c625bc6514350fbdb00fa9e624" - integrity sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA== +"vfile@^4.0.0": + "integrity" "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==" + "resolved" "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz" + "version" "4.2.1" dependencies: "@types/unist" "^2.0.0" - is-buffer "^2.0.0" - unist-util-stringify-position "^2.0.0" - vfile-message "^2.0.0" - -wait-on@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-6.0.1.tgz#16bbc4d1e4ebdd41c5b4e63a2e16dbd1f4e5601e" - integrity sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw== - dependencies: - axios "^0.25.0" - joi "^17.6.0" - lodash "^4.17.21" - minimist "^1.2.5" - rxjs "^7.5.4" - -watchpack@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25" - integrity sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA== - dependencies: - glob-to-regexp "^0.4.1" - graceful-fs "^4.1.2" - -wbuf@^1.1.0, wbuf@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" - integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== - dependencies: - minimalistic-assert "^1.0.0" - -web-namespaces@^1.0.0, web-namespaces@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" - integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw== - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= - -webpack-bundle-analyzer@^4.4.2: - version "4.5.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz#1b0eea2947e73528754a6f9af3e91b2b6e0f79d5" - integrity sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ== - dependencies: - acorn "^8.0.4" - acorn-walk "^8.0.0" - chalk "^4.1.0" - commander "^7.2.0" - gzip-size "^6.0.0" - lodash "^4.17.20" - opener "^1.5.2" - sirv "^1.0.7" - ws "^7.3.1" - -webpack-dev-middleware@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz#aa079a8dedd7e58bfeab358a9af7dab304cee57f" - integrity sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg== - dependencies: - colorette "^2.0.10" - memfs "^3.4.1" - mime-types "^2.1.31" - range-parser "^1.2.1" - schema-utils "^4.0.0" - -webpack-dev-server@^4.7.1: - version "4.7.4" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz#d0ef7da78224578384e795ac228d8efb63d5f945" - integrity sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A== + "is-buffer" "^2.0.0" + "unist-util-stringify-position" "^2.0.0" + "vfile-message" "^2.0.0" + +"wait-on@^6.0.0": + "integrity" "sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw==" + "resolved" "https://registry.npmjs.org/wait-on/-/wait-on-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "axios" "^0.25.0" + "joi" "^17.6.0" + "lodash" "^4.17.21" + "minimist" "^1.2.5" + "rxjs" "^7.5.4" + +"watchpack@^2.3.1": + "integrity" "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==" + "resolved" "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz" + "version" "2.3.1" + dependencies: + "glob-to-regexp" "^0.4.1" + "graceful-fs" "^4.1.2" + +"wbuf@^1.1.0", "wbuf@^1.7.3": + "integrity" "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==" + "resolved" "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz" + "version" "1.7.3" + dependencies: + "minimalistic-assert" "^1.0.0" + +"web-namespaces@^1.0.0", "web-namespaces@^1.1.2": + "integrity" "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==" + "resolved" "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz" + "version" "1.1.4" + +"webidl-conversions@^3.0.0": + "integrity" "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + "resolved" "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" + "version" "3.0.1" + +"webpack-bundle-analyzer@^4.4.2": + "integrity" "sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ==" + "resolved" "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz" + "version" "4.5.0" + dependencies: + "acorn" "^8.0.4" + "acorn-walk" "^8.0.0" + "chalk" "^4.1.0" + "commander" "^7.2.0" + "gzip-size" "^6.0.0" + "lodash" "^4.17.20" + "opener" "^1.5.2" + "sirv" "^1.0.7" + "ws" "^7.3.1" + +"webpack-dev-middleware@^5.3.1": + "integrity" "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==" + "resolved" "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz" + "version" "5.3.1" + dependencies: + "colorette" "^2.0.10" + "memfs" "^3.4.1" + "mime-types" "^2.1.31" + "range-parser" "^1.2.1" + "schema-utils" "^4.0.0" + +"webpack-dev-server@^4.7.1": + "integrity" "sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A==" + "resolved" "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz" + "version" "4.7.4" dependencies: "@types/bonjour" "^3.5.9" "@types/connect-history-api-fallback" "^1.3.5" @@ -7519,212 +7582,217 @@ webpack-dev-server@^4.7.1: "@types/serve-index" "^1.9.1" "@types/sockjs" "^0.3.33" "@types/ws" "^8.2.2" - ansi-html-community "^0.0.8" - bonjour "^3.5.0" - chokidar "^3.5.3" - colorette "^2.0.10" - compression "^1.7.4" - connect-history-api-fallback "^1.6.0" - default-gateway "^6.0.3" - del "^6.0.0" - express "^4.17.1" - graceful-fs "^4.2.6" - html-entities "^2.3.2" - http-proxy-middleware "^2.0.0" - ipaddr.js "^2.0.1" - open "^8.0.9" - p-retry "^4.5.0" - portfinder "^1.0.28" - schema-utils "^4.0.0" - selfsigned "^2.0.0" - serve-index "^1.9.1" - sockjs "^0.3.21" - spdy "^4.0.2" - strip-ansi "^7.0.0" - webpack-dev-middleware "^5.3.1" - ws "^8.4.2" - -webpack-merge@^5.8.0: - version "5.8.0" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" - integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== - dependencies: - clone-deep "^4.0.1" - wildcard "^2.0.0" - -webpack-sources@^1.1.0, webpack-sources@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" - integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== - dependencies: - source-list-map "^2.0.0" - source-map "~0.6.1" - -webpack-sources@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" - integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== - -webpack@^5.61.0: - version "5.69.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.69.1.tgz#8cfd92c192c6a52c99ab00529b5a0d33aa848dc5" - integrity sha512-+VyvOSJXZMT2V5vLzOnDuMz5GxEqLk7hKWQ56YxPW/PQRUuKimPqmEIJOx8jHYeyo65pKbapbW464mvsKbaj4A== + "ansi-html-community" "^0.0.8" + "bonjour" "^3.5.0" + "chokidar" "^3.5.3" + "colorette" "^2.0.10" + "compression" "^1.7.4" + "connect-history-api-fallback" "^1.6.0" + "default-gateway" "^6.0.3" + "del" "^6.0.0" + "express" "^4.17.1" + "graceful-fs" "^4.2.6" + "html-entities" "^2.3.2" + "http-proxy-middleware" "^2.0.0" + "ipaddr.js" "^2.0.1" + "open" "^8.0.9" + "p-retry" "^4.5.0" + "portfinder" "^1.0.28" + "schema-utils" "^4.0.0" + "selfsigned" "^2.0.0" + "serve-index" "^1.9.1" + "sockjs" "^0.3.21" + "spdy" "^4.0.2" + "strip-ansi" "^7.0.0" + "webpack-dev-middleware" "^5.3.1" + "ws" "^8.4.2" + +"webpack-merge@^5.8.0": + "integrity" "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==" + "resolved" "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz" + "version" "5.8.0" + dependencies: + "clone-deep" "^4.0.1" + "wildcard" "^2.0.0" + +"webpack-sources@^1.1.0", "webpack-sources@^1.4.3": + "integrity" "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==" + "resolved" "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz" + "version" "1.4.3" + dependencies: + "source-list-map" "^2.0.0" + "source-map" "~0.6.1" + +"webpack-sources@^3.2.3": + "integrity" "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==" + "resolved" "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz" + "version" "3.2.3" + +"webpack@^4.0.0 || ^5.0.0", "webpack@^4.37.0 || ^5.0.0", "webpack@^4.4.0 || ^5.0.0", "webpack@^5.0.0", "webpack@^5.1.0", "webpack@^5.20.0", "webpack@^5.61.0", "webpack@>= 4", "webpack@>=2", "webpack@>=4.41.1 || 5.x", "webpack@3 || 4 || 5", "webpack@5.x": + "integrity" "sha512-+VyvOSJXZMT2V5vLzOnDuMz5GxEqLk7hKWQ56YxPW/PQRUuKimPqmEIJOx8jHYeyo65pKbapbW464mvsKbaj4A==" + "resolved" "https://registry.npmjs.org/webpack/-/webpack-5.69.1.tgz" + "version" "5.69.1" dependencies: "@types/eslint-scope" "^3.7.3" "@types/estree" "^0.0.51" "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/wasm-edit" "1.11.1" "@webassemblyjs/wasm-parser" "1.11.1" - acorn "^8.4.1" - acorn-import-assertions "^1.7.6" - browserslist "^4.14.5" - chrome-trace-event "^1.0.2" - enhanced-resolve "^5.8.3" - es-module-lexer "^0.9.0" - eslint-scope "5.1.1" - events "^3.2.0" - glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" - json-parse-better-errors "^1.0.2" - loader-runner "^4.2.0" - mime-types "^2.1.27" - neo-async "^2.6.2" - schema-utils "^3.1.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" - watchpack "^2.3.1" - webpack-sources "^3.2.3" - -webpackbar@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/webpackbar/-/webpackbar-5.0.2.tgz#d3dd466211c73852741dfc842b7556dcbc2b0570" - integrity sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ== - dependencies: - chalk "^4.1.0" - consola "^2.15.3" - pretty-time "^1.1.0" - std-env "^3.0.1" - -websocket-driver@>=0.5.1, websocket-driver@^0.7.4: - version "0.7.4" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" - integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== - dependencies: - http-parser-js ">=0.5.1" - safe-buffer ">=5.1.0" - websocket-extensions ">=0.1.1" - -websocket-extensions@>=0.1.1: - version "0.1.4" - resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" - integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -which@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -widest-line@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" - integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== - dependencies: - string-width "^4.0.0" - -wildcard@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" - integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write-file-atomic@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" - integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== - dependencies: - imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^3.1.5" - -ws@^7.3.1: - version "7.5.7" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" - integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== - -ws@^8.4.2: - version "8.5.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" - integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== - -xdg-basedir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" - integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== - -xml-js@^1.6.11: - version "1.6.11" - resolved "https://registry.yarnpkg.com/xml-js/-/xml-js-1.6.11.tgz#927d2f6947f7f1c19a316dd8eea3614e8b18f8e9" - integrity sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g== - dependencies: - sax "^1.2.4" - -xtend@^4.0.0, xtend@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" - integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== - -yarn@^1.17.3: - version "1.22.17" - resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.17.tgz#bf910747d22497b573131f7341c0e1d15c74036c" - integrity sha512-H0p241BXaH0UN9IeH//RT82tl5PfNraVpSpEoW+ET7lmopNC61eZ+A+IDvU8FM6Go5vx162SncDL8J1ZjRBriQ== - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -zwitch@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920" - integrity sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw== + "acorn" "^8.4.1" + "acorn-import-assertions" "^1.7.6" + "browserslist" "^4.14.5" + "chrome-trace-event" "^1.0.2" + "enhanced-resolve" "^5.8.3" + "es-module-lexer" "^0.9.0" + "eslint-scope" "5.1.1" + "events" "^3.2.0" + "glob-to-regexp" "^0.4.1" + "graceful-fs" "^4.2.9" + "json-parse-better-errors" "^1.0.2" + "loader-runner" "^4.2.0" + "mime-types" "^2.1.27" + "neo-async" "^2.6.2" + "schema-utils" "^3.1.0" + "tapable" "^2.1.1" + "terser-webpack-plugin" "^5.1.3" + "watchpack" "^2.3.1" + "webpack-sources" "^3.2.3" + +"webpackbar@^5.0.2": + "integrity" "sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ==" + "resolved" "https://registry.npmjs.org/webpackbar/-/webpackbar-5.0.2.tgz" + "version" "5.0.2" + dependencies: + "chalk" "^4.1.0" + "consola" "^2.15.3" + "pretty-time" "^1.1.0" + "std-env" "^3.0.1" + +"websocket-driver@^0.7.4", "websocket-driver@>=0.5.1": + "integrity" "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==" + "resolved" "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz" + "version" "0.7.4" + dependencies: + "http-parser-js" ">=0.5.1" + "safe-buffer" ">=5.1.0" + "websocket-extensions" ">=0.1.1" + +"websocket-extensions@>=0.1.1": + "integrity" "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" + "resolved" "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz" + "version" "0.1.4" + +"whatwg-url@^5.0.0": + "integrity" "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=" + "resolved" "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "tr46" "~0.0.3" + "webidl-conversions" "^3.0.0" + +"which@^1.3.1": + "integrity" "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==" + "resolved" "https://registry.npmjs.org/which/-/which-1.3.1.tgz" + "version" "1.3.1" + dependencies: + "isexe" "^2.0.0" + +"which@^2.0.1": + "integrity" "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==" + "resolved" "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "isexe" "^2.0.0" + +"widest-line@^3.1.0": + "integrity" "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==" + "resolved" "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "string-width" "^4.0.0" + +"wildcard@^2.0.0": + "integrity" "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==" + "resolved" "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz" + "version" "2.0.0" + +"wrap-ansi@^7.0.0": + "integrity" "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==" + "resolved" "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + "version" "7.0.0" + dependencies: + "ansi-styles" "^4.0.0" + "string-width" "^4.1.0" + "strip-ansi" "^6.0.0" + +"wrappy@1": + "integrity" "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "resolved" "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + "version" "1.0.2" + +"write-file-atomic@^3.0.0": + "integrity" "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==" + "resolved" "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz" + "version" "3.0.3" + dependencies: + "imurmurhash" "^0.1.4" + "is-typedarray" "^1.0.0" + "signal-exit" "^3.0.2" + "typedarray-to-buffer" "^3.1.5" + +"ws@^7.3.1": + "integrity" "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==" + "resolved" "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz" + "version" "7.5.7" + +"ws@^8.4.2": + "integrity" "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==" + "resolved" "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz" + "version" "8.5.0" + +"xdg-basedir@^4.0.0": + "integrity" "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" + "resolved" "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz" + "version" "4.0.0" + +"xml-js@^1.6.11": + "integrity" "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==" + "resolved" "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz" + "version" "1.6.11" + dependencies: + "sax" "^1.2.4" + +"xtend@^4.0.0", "xtend@^4.0.1": + "integrity" "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + "resolved" "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" + "version" "4.0.2" + +"yallist@^3.0.2": + "integrity" "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "resolved" "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" + "version" "3.1.1" + +"yallist@^4.0.0": + "integrity" "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "resolved" "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" + "version" "4.0.0" + +"yaml@^1.10.0", "yaml@^1.10.2", "yaml@^1.7.2": + "integrity" "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" + "resolved" "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" + "version" "1.10.2" + +"yarn@^1.17.3": + "integrity" "sha512-H0p241BXaH0UN9IeH//RT82tl5PfNraVpSpEoW+ET7lmopNC61eZ+A+IDvU8FM6Go5vx162SncDL8J1ZjRBriQ==" + "resolved" "https://registry.npmjs.org/yarn/-/yarn-1.22.17.tgz" + "version" "1.22.17" + +"yocto-queue@^0.1.0": + "integrity" "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + "resolved" "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" + "version" "0.1.0" + +"zwitch@^1.0.0": + "integrity" "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==" + "resolved" "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz" + "version" "1.0.5" From 1e6b57209fbddefda6619b78d9d1e8d848e34c91 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 29 Mar 2023 14:47:33 +0200 Subject: [PATCH 723/898] Adding labelling to project action --- .github/pr-branch-labeler.yml | 15 +++++++++++++++ .github/pr-glob-labeler.yml | 7 +++++++ .github/workflows/project_actions.yml | 24 +++++++++++++++++++++++- 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 .github/pr-branch-labeler.yml create mode 100644 .github/pr-glob-labeler.yml diff --git a/.github/pr-branch-labeler.yml b/.github/pr-branch-labeler.yml new file mode 100644 index 00000000000..bf4045442a2 --- /dev/null +++ b/.github/pr-branch-labeler.yml @@ -0,0 +1,15 @@ +# Apply label "feature" if head matches "feature/*" +type: feature: + head: "feature/*" + +# Apply label "feature" if head matches "feature/*" +type: enhancement: + head: "enhancement/*" + +# Apply label "bugfix" if head matches one of "bugfix/*" or "hotfix/*" +type: bugfix: + head: ["bugfix/*", "hotfix/*"] + +# Apply label "release" if base matches "release/*" +Bump Minor: + base: "release/next-minor" \ No newline at end of file diff --git a/.github/pr-glob-labeler.yml b/.github/pr-glob-labeler.yml new file mode 100644 index 00000000000..367cb166255 --- /dev/null +++ b/.github/pr-glob-labeler.yml @@ -0,0 +1,7 @@ +# Add type: unittest label if any changes in tests folders +type: unittest: +- any: ['tests/**/*', 'openpype/tests/**/*'] + +# any changes in documentation structure +type: documentation: +- any: ['website/**/*', 'docs/**/*'] \ No newline at end of file diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index dc68a9dc0ef..dfa9bdf61f8 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -20,6 +20,7 @@ jobs: project_id: 11 resource_node_id: ${{ github.event.pull_request.node_id }} status_value: Change Requested + size-label: name: pr_size_label runs-on: ubuntu-latest @@ -42,4 +43,25 @@ jobs: "1000": "L", "1500": "XL", "2500": "XXL" - } \ No newline at end of file + } + + label_prs_branch: + name: pr_branch_label + runs-on: ubuntu-latest + if: github.event.action == 'opened' + steps: + - name: Label PRs - Branch name detection + uses: ffittschen/pr-branch-labeler@v1 + with: + repo-token: ${{ secrets.YNPUT_BOT_TOKEN }} + + label_prs_globe: + name: pr_globe_label + runs-on: ubuntu-latest + if: github.event.action == 'opened' + steps: + - name: Label PRs - Globe detection + uses: actions/labeler@v4 + with: + repo-token: ${{ secrets.YNPUT_BOT_TOKEN }} + configuration-path: ".github/pr-glob-labeler.yml" \ No newline at end of file From cca97a036bcf9acc1c7a8d1bf55d0df203fd2388 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 29 Mar 2023 14:57:33 +0200 Subject: [PATCH 724/898] Use `get_output_parameter` --- openpype/hosts/houdini/plugins/publish/extract_opengl.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/houdini/plugins/publish/extract_opengl.py b/openpype/hosts/houdini/plugins/publish/extract_opengl.py index 8357e188a80..280d69b287a 100644 --- a/openpype/hosts/houdini/plugins/publish/extract_opengl.py +++ b/openpype/hosts/houdini/plugins/publish/extract_opengl.py @@ -2,7 +2,7 @@ import pyblish.api import openpype.api -from openpype.hosts.houdini.api.lib import render_rop +from openpype.hosts.houdini.api.lib import render_rop, get_output_parameter import hou @@ -21,7 +21,7 @@ def process(self, instance): # Get the filename from the filename parameter # `.evalParm(parameter)` will make sure all tokens are resolved - output = ropnode.evalParm("picture") + output = get_output_parameter(ropnode).eval() staging_dir = os.path.dirname(output) instance.data["stagingDir"] = staging_dir file_name = os.path.basename(output) From 14ed02e2a9eecad85372a97bad5ec4cde7872bcb Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 29 Mar 2023 15:08:22 +0200 Subject: [PATCH 725/898] adding pr glob config for hosts --- .github/pr-glob-labeler.yml | 38 ++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/.github/pr-glob-labeler.yml b/.github/pr-glob-labeler.yml index 367cb166255..6a71b1616a5 100644 --- a/.github/pr-glob-labeler.yml +++ b/.github/pr-glob-labeler.yml @@ -4,4 +4,40 @@ type: unittest: # any changes in documentation structure type: documentation: -- any: ['website/**/*', 'docs/**/*'] \ No newline at end of file +- any: ['website/**/*', 'docs/**/*'] + +# hosts triage +host: Nuke: +- openpype/hosts/nuke/**/* +host: Photoshop: +- openpype/hosts/photoshop/**/* +host: Harmony: +- openpype/hosts/harmony/**/* +host: UE: +- openpype/hosts/unreal/**/* +host: Houdini: +- openpype/hosts/houdini/**/* +host: Maya: +- openpype/hosts/maya/**/* +host: Resolve: +- openpype/hosts/resolve/**/* +host: Blender: +- openpype/hosts/blender/**/* +host: Hiero: +- openpype/hosts/hiero/**/* +host: Fusion: +- openpype/hosts/fusion/**/* +host: Flame: +- openpype/hosts/flame/**/* +host: TrayPublisher: +- openpype/hosts/traypublisher/**/* +host: 3dsmax: +- openpype/hosts/max/**/* +host: TV Paint: +- openpype/hosts/tvpaint/**/* +host: CelAction: +- openpype/hosts/celaction/**/* +host: After Effects: +- openpype/hosts/aftereffects/**/* +host: Substance Painter: +- openpype/hosts/substancepainter/**/* From e7bcf5509626d321b2f2028b293da5bdbaf24c28 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 29 Mar 2023 15:23:13 +0200 Subject: [PATCH 726/898] yaml is not supporting spaces in keys --- .github/pr-branch-labeler.yml | 8 +++--- .github/pr-glob-labeler.yml | 54 +++++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/.github/pr-branch-labeler.yml b/.github/pr-branch-labeler.yml index bf4045442a2..58bcbcb72ae 100644 --- a/.github/pr-branch-labeler.yml +++ b/.github/pr-branch-labeler.yml @@ -1,15 +1,15 @@ # Apply label "feature" if head matches "feature/*" -type: feature: +'type: feature': head: "feature/*" # Apply label "feature" if head matches "feature/*" -type: enhancement: +'type: enhancement': head: "enhancement/*" # Apply label "bugfix" if head matches one of "bugfix/*" or "hotfix/*" -type: bugfix: +'type: bugfix': head: ["bugfix/*", "hotfix/*"] # Apply label "release" if base matches "release/*" -Bump Minor: +'Bump Minor': base: "release/next-minor" \ No newline at end of file diff --git a/.github/pr-glob-labeler.yml b/.github/pr-glob-labeler.yml index 6a71b1616a5..0c1164f659c 100644 --- a/.github/pr-glob-labeler.yml +++ b/.github/pr-glob-labeler.yml @@ -1,43 +1,59 @@ # Add type: unittest label if any changes in tests folders -type: unittest: +'type: unittest': - any: ['tests/**/*', 'openpype/tests/**/*'] # any changes in documentation structure -type: documentation: +'type: documentation': - any: ['website/**/*', 'docs/**/*'] # hosts triage -host: Nuke: +'host: Nuke': - openpype/hosts/nuke/**/* -host: Photoshop: + +'host: Photoshop': - openpype/hosts/photoshop/**/* -host: Harmony: + +'host: Harmony': - openpype/hosts/harmony/**/* -host: UE: + +'host: UE': - openpype/hosts/unreal/**/* -host: Houdini: + +'host: Houdini': - openpype/hosts/houdini/**/* -host: Maya: + +'host: Maya': - openpype/hosts/maya/**/* -host: Resolve: + +'host: Resolve': - openpype/hosts/resolve/**/* -host: Blender: + +'host: Blender': - openpype/hosts/blender/**/* -host: Hiero: + +'host: Hiero': - openpype/hosts/hiero/**/* -host: Fusion: + +'host: Fusion': - openpype/hosts/fusion/**/* -host: Flame: + +'host: Flame': - openpype/hosts/flame/**/* -host: TrayPublisher: + +'host: TrayPublisher': - openpype/hosts/traypublisher/**/* -host: 3dsmax: + +'host: 3dsmax': - openpype/hosts/max/**/* -host: TV Paint: + +'host: TV Paint': - openpype/hosts/tvpaint/**/* -host: CelAction: + +'host: CelAction': - openpype/hosts/celaction/**/* -host: After Effects: + +'host: After Effects': - openpype/hosts/aftereffects/**/* -host: Substance Painter: + +'host: Substance Painter': - openpype/hosts/substancepainter/**/* From 6b94d073a9549b097ee6075aed9c39107ec6252b Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 29 Mar 2023 15:36:32 +0200 Subject: [PATCH 727/898] updating project actions --- .github/pr-glob-labeler.yml | 10 ++++++++-- .github/workflows/project_actions.yml | 8 ++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/.github/pr-glob-labeler.yml b/.github/pr-glob-labeler.yml index 0c1164f659c..90e497fbd55 100644 --- a/.github/pr-glob-labeler.yml +++ b/.github/pr-glob-labeler.yml @@ -1,10 +1,16 @@ # Add type: unittest label if any changes in tests folders 'type: unittest': -- any: ['tests/**/*', 'openpype/tests/**/*'] +- tests/**/* +- tests/** +- openpype/tests/**/* +- openpype/tests/** # any changes in documentation structure 'type: documentation': -- any: ['website/**/*', 'docs/**/*'] +- website/**/* +- website/** +- docs/**/* +- docs/** # hosts triage 'host: Nuke': diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index dfa9bdf61f8..ad8e8b9e133 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -48,7 +48,9 @@ jobs: label_prs_branch: name: pr_branch_label runs-on: ubuntu-latest - if: github.event.action == 'opened' + if: | + ${{(github.event_name == 'pull_request' && github.event.action == 'synchronize') + || (github.event_name == 'pull_request' && github.event.action == 'opened')}} steps: - name: Label PRs - Branch name detection uses: ffittschen/pr-branch-labeler@v1 @@ -58,7 +60,9 @@ jobs: label_prs_globe: name: pr_globe_label runs-on: ubuntu-latest - if: github.event.action == 'opened' + if: | + ${{(github.event_name == 'pull_request' && github.event.action == 'synchronize') + || (github.event_name == 'pull_request' && github.event.action == 'opened')}} steps: - name: Label PRs - Globe detection uses: actions/labeler@v4 From 081cd507791703b23fed0d1031f966986bad1e76 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 29 Mar 2023 16:02:25 +0200 Subject: [PATCH 728/898] updating pr globe labeler config adding modules --- .github/pr-glob-labeler.yml | 42 +++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/.github/pr-glob-labeler.yml b/.github/pr-glob-labeler.yml index 90e497fbd55..f990c6dfbec 100644 --- a/.github/pr-glob-labeler.yml +++ b/.github/pr-glob-labeler.yml @@ -15,51 +15,93 @@ # hosts triage 'host: Nuke': - openpype/hosts/nuke/**/* +- openpype/hosts/nuke/** 'host: Photoshop': - openpype/hosts/photoshop/**/* +- openpype/hosts/photoshop/** 'host: Harmony': - openpype/hosts/harmony/**/* +- openpype/hosts/harmony/** 'host: UE': - openpype/hosts/unreal/**/* +- openpype/hosts/unreal/** 'host: Houdini': - openpype/hosts/houdini/**/* +- openpype/hosts/houdini/** 'host: Maya': - openpype/hosts/maya/**/* +- openpype/hosts/maya/** 'host: Resolve': - openpype/hosts/resolve/**/* +- openpype/hosts/resolve/** 'host: Blender': - openpype/hosts/blender/**/* +- openpype/hosts/blender/** 'host: Hiero': - openpype/hosts/hiero/**/* +- openpype/hosts/hiero/** 'host: Fusion': - openpype/hosts/fusion/**/* +- openpype/hosts/fusion/** 'host: Flame': - openpype/hosts/flame/**/* +- openpype/hosts/flame/** 'host: TrayPublisher': - openpype/hosts/traypublisher/**/* +- openpype/hosts/traypublisher/** 'host: 3dsmax': - openpype/hosts/max/**/* +- openpype/hosts/max/** 'host: TV Paint': - openpype/hosts/tvpaint/**/* +- openpype/hosts/tvpaint/** 'host: CelAction': - openpype/hosts/celaction/**/* +- openpype/hosts/celaction/** 'host: After Effects': - openpype/hosts/aftereffects/**/* +- openpype/hosts/aftereffects/** 'host: Substance Painter': - openpype/hosts/substancepainter/**/* +- openpype/hosts/substancepainter/** + +# modules triage +'module: Deadline': +- openpype/modules/deadline/**/* +- openpype/modules/deadline/** + +'module: RoyalRender': +- openpype/modules/royalrender/**/* +- openpype/modules/royalrender/** + +'module: Sitesync': +- openpype/modules/sync_server/**/* +- openpype/modules/sync_server/** + +'module: Ftrack': +- openpype/modules/ftrack/**/* +- openpype/modules/ftrack/** + +'module: Shotgrid': +- openpype/modules/shotgrid/**/* +- openpype/modules/shotgrid/** + +'module: Kitsu': +- openpype/modules/kitsu/**/* +- openpype/modules/kitsu/** From 72dcd437fcf9da715a9fd12888bed07d421670ac Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 29 Mar 2023 16:22:21 +0200 Subject: [PATCH 729/898] Fix import --- openpype/hosts/houdini/plugins/publish/extract_opengl.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/houdini/plugins/publish/extract_opengl.py b/openpype/hosts/houdini/plugins/publish/extract_opengl.py index 280d69b287a..4875d9b98d7 100644 --- a/openpype/hosts/houdini/plugins/publish/extract_opengl.py +++ b/openpype/hosts/houdini/plugins/publish/extract_opengl.py @@ -1,13 +1,13 @@ import os import pyblish.api -import openpype.api +from openpype.pipeline import publish from openpype.hosts.houdini.api.lib import render_rop, get_output_parameter import hou -class ExtractOpenGL(openpype.api.Extractor): +class ExtractOpenGL(publish.Extractor): order = pyblish.api.ExtractorOrder label = "Extract OpenGL" From 711089fc9cc7d0c1b9ccc6335ec67f3632042af8 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 29 Mar 2023 16:29:35 +0200 Subject: [PATCH 730/898] improving glob expressions to include settings --- .github/pr-glob-labeler.yml | 103 +++++++++++++++++------------------- 1 file changed, 49 insertions(+), 54 deletions(-) diff --git a/.github/pr-glob-labeler.yml b/.github/pr-glob-labeler.yml index f990c6dfbec..e05421f5d70 100644 --- a/.github/pr-glob-labeler.yml +++ b/.github/pr-glob-labeler.yml @@ -1,107 +1,102 @@ # Add type: unittest label if any changes in tests folders 'type: unittest': -- tests/**/* -- tests/** -- openpype/tests/**/* -- openpype/tests/** +- /**/*tests*/**/* # any changes in documentation structure 'type: documentation': -- website/**/* -- website/** -- docs/**/* -- docs/** +- /**/*website*/**/* +- /**/*docs*/**/* # hosts triage 'host: Nuke': -- openpype/hosts/nuke/**/* -- openpype/hosts/nuke/** +- /**/*nuke* +- /**/*nuke*/**/* 'host: Photoshop': -- openpype/hosts/photoshop/**/* -- openpype/hosts/photoshop/** +- /**/*photoshop* +- /**/*photoshop*/**/* 'host: Harmony': -- openpype/hosts/harmony/**/* -- openpype/hosts/harmony/** +- /**/*harmony* +- /**/*harmony*/**/* 'host: UE': -- openpype/hosts/unreal/**/* -- openpype/hosts/unreal/** +- /**/*unreal* +- /**/*unreal*/**/* 'host: Houdini': -- openpype/hosts/houdini/**/* -- openpype/hosts/houdini/** +- /**/*houdini* +- /**/*houdini*/**/* 'host: Maya': -- openpype/hosts/maya/**/* -- openpype/hosts/maya/** +- /**/*maya* +- /**/*maya*/**/* 'host: Resolve': -- openpype/hosts/resolve/**/* -- openpype/hosts/resolve/** +- /**/*resolve* +- /**/*resolve*/**/* 'host: Blender': -- openpype/hosts/blender/**/* -- openpype/hosts/blender/** +- /**/*blender* +- /**/*blender*/**/* 'host: Hiero': -- openpype/hosts/hiero/**/* -- openpype/hosts/hiero/** +- /**/*hiero* +- /**/*hiero*/**/* 'host: Fusion': -- openpype/hosts/fusion/**/* -- openpype/hosts/fusion/** +- /**/*fusion* +- /**/*fusion*/**/* 'host: Flame': -- openpype/hosts/flame/**/* -- openpype/hosts/flame/** +- /**/*flame* +- /**/*flame*/**/* 'host: TrayPublisher': -- openpype/hosts/traypublisher/**/* -- openpype/hosts/traypublisher/** +- /**/*traypublisher* +- /**/*traypublisher*/**/* 'host: 3dsmax': -- openpype/hosts/max/**/* -- openpype/hosts/max/** +- /**/*max* +- /**/*max*/**/* 'host: TV Paint': -- openpype/hosts/tvpaint/**/* -- openpype/hosts/tvpaint/** +- /**/*tvpaint* +- /**/*tvpaint*/**/* 'host: CelAction': -- openpype/hosts/celaction/**/* -- openpype/hosts/celaction/** +- /**/*celaction* +- /**/*celaction*/**/* 'host: After Effects': -- openpype/hosts/aftereffects/**/* -- openpype/hosts/aftereffects/** +- /**/*aftereffects* +- /**/*aftereffects*/**/* 'host: Substance Painter': -- openpype/hosts/substancepainter/**/* -- openpype/hosts/substancepainter/** +- /**/*substancepainter* +- /**/*substancepainter*/**/* # modules triage 'module: Deadline': -- openpype/modules/deadline/**/* -- openpype/modules/deadline/** +- /**/*deadline* +- /**/*deadline*/**/* 'module: RoyalRender': -- openpype/modules/royalrender/**/* -- openpype/modules/royalrender/** +- /**/*royalrender* +- /**/*royalrender*/**/* 'module: Sitesync': -- openpype/modules/sync_server/**/* -- openpype/modules/sync_server/** +- /**/*sync_server* +- /**/*sync_server*/**/* 'module: Ftrack': -- openpype/modules/ftrack/**/* -- openpype/modules/ftrack/** +- /**/*ftrack* +- /**/*ftrack*/**/* 'module: Shotgrid': -- openpype/modules/shotgrid/**/* -- openpype/modules/shotgrid/** +- /**/*shotgrid* +- /**/*shotgrid*/**/* 'module: Kitsu': -- openpype/modules/kitsu/**/* -- openpype/modules/kitsu/** +- /**/*kitsu* +- /**/*kitsu*/**/* From 73b369a32d26e2c01d3140b9074d1fd83402a772 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Wed, 29 Mar 2023 15:37:36 +0100 Subject: [PATCH 731/898] Update openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py Co-authored-by: Roy Nieterau --- .../hosts/maya/plugins/publish/extract_arnold_scene_source.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index 8344f028940..ece53edc234 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -144,7 +144,7 @@ def _extract(self, nodes, attribute_data, kwargs): duplicate_transform, world=True )[0] - basename = node.split("|")[-1].split(":")[-1] + basename = node.rsplit("|", 1)[-1].rsplit(":", 1)[-1] duplicate_transform = cmds.rename( duplicate_transform, basename ) From dea30d2f689a330488c9a5e0a91a7a2d769dbf89 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 29 Mar 2023 16:06:27 +0100 Subject: [PATCH 732/898] BigRoy feedback --- .../publish/collect_arnold_scene_source.py | 7 ++++--- .../publish/extract_arnold_scene_source.py | 8 +------- .../tools/mayalookassigner/arnold_standin.py | 18 ++++++++---------- .../maya/tools/mayalookassigner/commands.py | 12 +++++------- .../tools/mayalookassigner/vray_proxies.py | 8 +++++--- 5 files changed, 23 insertions(+), 30 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/collect_arnold_scene_source.py index ab15d0419fe..0845f653b13 100644 --- a/openpype/hosts/maya/plugins/publish/collect_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/collect_arnold_scene_source.py @@ -22,9 +22,10 @@ def process(self, instance): self.log.warning("Skipped empty instance: \"%s\" " % objset) continue if objset.endswith("content_SET"): - set_members = get_all_children(cmds.ls(members, long=True)) - instance.data["contentMembers"] = set_members - self.log.debug("content members: {}".format(set_members)) + members = cmds.ls(members, long=True) + children = get_all_children(members) + instance.data["contentMembers"] = children + self.log.debug("content members: {}".format(children)) elif objset.endswith("proxy_SET"): set_members = get_all_children(cmds.ls(members, long=True)) instance.data["proxy"] = set_members diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index 8344f028940..ce5dc27bbdb 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -126,18 +126,12 @@ def _extract(self, nodes, attribute_data, kwargs): # Only interested in transforms with shapes. shapes = cmds.listRelatives( - node, shapes=True, fullPath=True + node, shapes=True, noIntermediate=True ) or [] if not shapes: continue - parent = cmds.listRelatives( - node, parent=True, fullPath=True - )[0] duplicate_transform = cmds.duplicate(node)[0] - duplicate_transform = "{}|{}".format( - parent, duplicate_transform - ) if cmds.listRelatives(duplicate_transform, parent=True): duplicate_transform = cmds.parent( diff --git a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py index dfffbc59615..771b256614b 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py +++ b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py @@ -58,17 +58,17 @@ def calculate_visibility_mask(attributes): return mask -def get_cbid_by_node(path): - """Get cbid from Arnold Scene Source. +def get_id_by_node(path): + """Get node id from Arnold Scene Source. Args: path (string): Path to Arnold Scene Source. Returns: - (dict): Dictionary with node full name/path and CBID. + (dict): Dictionary with node full name/path and id. """ import arnold - results = {} + results = defaultdict(list) arnold.AiBegin() @@ -82,10 +82,7 @@ def get_cbid_by_node(path): node = arnold.AiNodeIteratorGetNext(iter) if arnold.AiNodeIs(node, "polymesh"): node_name = arnold.AiNodeGetName(node) - try: - results[arnold.AiNodeGetStr(node, "cbId")].append(node_name) - except KeyError: - results[arnold.AiNodeGetStr(node, "cbId")] = [node_name] + results[arnold.AiNodeGetStr(node, "cbId")].append(node_name) arnold.AiNodeIteratorDestroy(iter) arnold.AiEnd() @@ -139,7 +136,7 @@ def shading_engine_assignments(shading_engine, attribute, nodes, assignments): def assign_look(standin, subset): log.info("Assigning {} to {}.".format(subset, standin)) - nodes_by_id = get_cbid_by_node(get_standin_path(standin)) + nodes_by_id = get_id_by_node(get_standin_path(standin)) # Group by asset id so we run over the look per asset node_ids_by_asset_id = defaultdict(set) @@ -164,7 +161,8 @@ def assign_look(standin, subset): continue relationships = lib.get_look_relationships(version["_id"]) - shader_nodes, container_node = lib.load_look(version["_id"]) + shader_nodes, container_nodes = lib.load_look(version["_id"]) + container_node = container_nodes[0] namespace = shader_nodes[0].split(":")[0] # Get only the node ids and paths related to this asset diff --git a/openpype/hosts/maya/tools/mayalookassigner/commands.py b/openpype/hosts/maya/tools/mayalookassigner/commands.py index d7061f12e1e..d78e31111d9 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/commands.py +++ b/openpype/hosts/maya/tools/mayalookassigner/commands.py @@ -121,15 +121,13 @@ def create_asset_id_hash(nodes): path = cmds.getAttr("{}.fileName".format(node)) ids = get_alembic_ids_cache(path) for k, _ in ids.items(): - pid = k.split(":")[0] - if node not in node_id_hash[pid]: - node_id_hash[pid].append(node) + id = k.split(":")[0] + node_id_hash[id].append(node) elif shapes and cmds.nodeType(shapes[0]) == "aiStandIn": path = arnold_standin.get_standin_path(shapes[0]) - for id, _ in arnold_standin.get_cbid_by_node(path).items(): - pid = id.split(":")[0] - if shapes[0] not in node_id_hash[pid]: - node_id_hash[pid].append(shapes[0]) + for id, _ in arnold_standin.get_id_by_node(path).items(): + id = id.split(":")[0] + node_id_hash[id].append(shapes[0]) else: value = lib.get_id(node) if value is None: diff --git a/openpype/hosts/maya/tools/mayalookassigner/vray_proxies.py b/openpype/hosts/maya/tools/mayalookassigner/vray_proxies.py index 6ee618f37a8..1d2ec5fd87e 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/vray_proxies.py +++ b/openpype/hosts/maya/tools/mayalookassigner/vray_proxies.py @@ -11,7 +11,7 @@ from openpype.client import get_last_version_by_subset_name from openpype.pipeline import legacy_io -from openpype.hosts.maya import api +import openpype.hosts.maya.lib as maya_lib from . import lib @@ -189,8 +189,10 @@ def vrayproxy_assign_look(vrayproxy, subset="lookDefault"): node_id: nodes_by_id[node_id] for node_id in node_ids } edits = list( - api.lib.iter_shader_edits( - relationships, shadernodes, asset_nodes_by_id)) + maya_lib.iter_shader_edits( + relationships, shadernodes, asset_nodes_by_id + ) + ) # Create assignments assignments = {} From 14cfe2b9938998a91e15a12cb5bb8092b567405d Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 29 Mar 2023 17:12:41 +0200 Subject: [PATCH 733/898] project action with pr target trigger --- .github/workflows/project_actions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index ad8e8b9e133..4fc32d99860 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -1,7 +1,7 @@ name: project-actions on: - pull_request: + pull_request_target: types: [opened, synchronize, assigned, review_requested] pull_request_review: types: [submitted] From 5ccc8cd745c0c0cc83480eed4ee835b3f82f757e Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 29 Mar 2023 17:30:38 +0200 Subject: [PATCH 734/898] fixing target to include pull_request also fix globes --- .github/pr-glob-labeler.yml | 98 +++++++++++++-------------- .github/workflows/project_actions.yml | 1 + 2 files changed, 50 insertions(+), 49 deletions(-) diff --git a/.github/pr-glob-labeler.yml b/.github/pr-glob-labeler.yml index e05421f5d70..f23f74f3107 100644 --- a/.github/pr-glob-labeler.yml +++ b/.github/pr-glob-labeler.yml @@ -1,102 +1,102 @@ # Add type: unittest label if any changes in tests folders 'type: unittest': -- /**/*tests*/**/* +- **/*tests*/**/* # any changes in documentation structure 'type: documentation': -- /**/*website*/**/* -- /**/*docs*/**/* +- **/*website*/**/* +- **/*docs*/**/* # hosts triage 'host: Nuke': -- /**/*nuke* -- /**/*nuke*/**/* +- **/*nuke* +- **/*nuke*/**/* 'host: Photoshop': -- /**/*photoshop* -- /**/*photoshop*/**/* +- **/*photoshop* +- **/*photoshop*/**/* 'host: Harmony': -- /**/*harmony* -- /**/*harmony*/**/* +- **/*harmony* +- **/*harmony*/**/* 'host: UE': -- /**/*unreal* -- /**/*unreal*/**/* +- **/*unreal* +- **/*unreal*/**/* 'host: Houdini': -- /**/*houdini* -- /**/*houdini*/**/* +- **/*houdini* +- **/*houdini*/**/* 'host: Maya': -- /**/*maya* -- /**/*maya*/**/* +- **/*maya* +- **/*maya*/**/* 'host: Resolve': -- /**/*resolve* -- /**/*resolve*/**/* +- **/*resolve* +- **/*resolve*/**/* 'host: Blender': -- /**/*blender* -- /**/*blender*/**/* +- **/*blender* +- **/*blender*/**/* 'host: Hiero': -- /**/*hiero* -- /**/*hiero*/**/* +- **/*hiero* +- **/*hiero*/**/* 'host: Fusion': -- /**/*fusion* -- /**/*fusion*/**/* +- **/*fusion* +- **/*fusion*/**/* 'host: Flame': -- /**/*flame* -- /**/*flame*/**/* +- **/*flame* +- **/*flame*/**/* 'host: TrayPublisher': -- /**/*traypublisher* -- /**/*traypublisher*/**/* +- **/*traypublisher* +- **/*traypublisher*/**/* 'host: 3dsmax': -- /**/*max* -- /**/*max*/**/* +- **/*max* +- **/*max*/**/* 'host: TV Paint': -- /**/*tvpaint* -- /**/*tvpaint*/**/* +- **/*tvpaint* +- **/*tvpaint*/**/* 'host: CelAction': -- /**/*celaction* -- /**/*celaction*/**/* +- **/*celaction* +- **/*celaction*/**/* 'host: After Effects': -- /**/*aftereffects* -- /**/*aftereffects*/**/* +- **/*aftereffects* +- **/*aftereffects*/**/* 'host: Substance Painter': -- /**/*substancepainter* -- /**/*substancepainter*/**/* +- **/*substancepainter* +- **/*substancepainter*/**/* # modules triage 'module: Deadline': -- /**/*deadline* -- /**/*deadline*/**/* +- **/*deadline* +- **/*deadline*/**/* 'module: RoyalRender': -- /**/*royalrender* -- /**/*royalrender*/**/* +- **/*royalrender* +- **/*royalrender*/**/* 'module: Sitesync': -- /**/*sync_server* -- /**/*sync_server*/**/* +- **/*sync_server* +- **/*sync_server*/**/* 'module: Ftrack': -- /**/*ftrack* -- /**/*ftrack*/**/* +- **/*ftrack* +- **/*ftrack*/**/* 'module: Shotgrid': -- /**/*shotgrid* -- /**/*shotgrid*/**/* +- **/*shotgrid* +- **/*shotgrid*/**/* 'module: Kitsu': -- /**/*kitsu* -- /**/*kitsu*/**/* +- **/*kitsu* +- **/*kitsu*/**/* diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index 4fc32d99860..605a0ae422f 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -2,6 +2,7 @@ name: project-actions on: pull_request_target: + pull_request: types: [opened, synchronize, assigned, review_requested] pull_request_review: types: [submitted] From fb1d4ea5b1e401cd7ab3b320dfcab14dd5fdc665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Je=C5=BEek?= Date: Wed, 29 Mar 2023 17:35:48 +0200 Subject: [PATCH 735/898] removing pr target --- .github/workflows/project_actions.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index 605a0ae422f..c66e378a5a3 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -1,7 +1,6 @@ name: project-actions on: - pull_request_target: pull_request: types: [opened, synchronize, assigned, review_requested] pull_request_review: @@ -69,4 +68,4 @@ jobs: uses: actions/labeler@v4 with: repo-token: ${{ secrets.YNPUT_BOT_TOKEN }} - configuration-path: ".github/pr-glob-labeler.yml" \ No newline at end of file + configuration-path: ".github/pr-glob-labeler.yml" From 429d4fbd5cfbd62d5352f39d039b5268ade8983a Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 29 Mar 2023 17:45:13 +0200 Subject: [PATCH 736/898] Fix burnin frame range + add support for focal length in burnin (incl. animated focal length) --- .../plugins/publish/collect_review_data.py | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 openpype/hosts/houdini/plugins/publish/collect_review_data.py diff --git a/openpype/hosts/houdini/plugins/publish/collect_review_data.py b/openpype/hosts/houdini/plugins/publish/collect_review_data.py new file mode 100644 index 00000000000..7c20f9bea88 --- /dev/null +++ b/openpype/hosts/houdini/plugins/publish/collect_review_data.py @@ -0,0 +1,52 @@ +import hou +import pyblish.api + + +class CollectHoudiniReviewData(pyblish.api.InstancePlugin): + """Collect Review Data.""" + + label = "Collect Review Data" + order = pyblish.api.CollectorOrder + 0.1 + hosts = ["houdini"] + families = ["review"] + + def process(self, instance): + + # This fixes the burnin having the incorrect start/end timestamps + # because without this it would take it from the context instead + # which isn't the actual frame range that this instance renders. + instance.data["handleStart"] = 0 + instance.data["handleEnd"] = 0 + + # Get the camera from the rop node to collect the focal length + ropnode_path = instance.data["instance_node"] + ropnode = hou.node(ropnode_path) + + try: + camera = ropnode.parm("camera").evalAsNode() + except TypeError: + # Not a valid node path set + self.log.error("No valid camera node found on review node: " + "{}".format(ropnode.path())) + return + + # Collect focal length. + focal_length_parm = camera.parm("focal") + if not focal_length_parm: + self.log.warning("No 'focal' (focal length) parameter found on " + "camera: {}".format(camera.path())) + return + + if focal_length_parm.isTimeDependent(): + start = instance.data["frameStart"] + end = instance.data["frameEnd"] + 1 + focal_length = [ + focal_length_parm.evalAsFloatAtFrame(t) + for t in range(int(start), int(end)) + ] + else: + focal_length = focal_length_parm.evalAsFloat() + + # Store focal length in `burninDataMembers` + burnin_members = instance.data.setdefault("burninDataMembers", {}) + burnin_members["focalLength"] = focal_length From 11c7256a2aa2e41d67667349f16b4c4a139d70a5 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 29 Mar 2023 17:51:04 +0200 Subject: [PATCH 737/898] Fix `families` filtering --- openpype/hosts/houdini/plugins/publish/collect_current_file.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/houdini/plugins/publish/collect_current_file.py b/openpype/hosts/houdini/plugins/publish/collect_current_file.py index 9cca07fdc7c..bd4ab31d599 100644 --- a/openpype/hosts/houdini/plugins/publish/collect_current_file.py +++ b/openpype/hosts/houdini/plugins/publish/collect_current_file.py @@ -11,7 +11,7 @@ class CollectHoudiniCurrentFile(pyblish.api.InstancePlugin): order = pyblish.api.CollectorOrder - 0.01 label = "Houdini Current File" hosts = ["houdini"] - family = ["workfile"] + families = ["workfile"] def process(self, instance): """Inject the current working file""" From 8b74d0958da7d2545cd74d8df91b43ef9bf922d4 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 29 Mar 2023 17:51:13 +0200 Subject: [PATCH 738/898] Remove unused import --- openpype/hosts/houdini/plugins/publish/collect_current_file.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/houdini/plugins/publish/collect_current_file.py b/openpype/hosts/houdini/plugins/publish/collect_current_file.py index bd4ab31d599..3a391f22bd0 100644 --- a/openpype/hosts/houdini/plugins/publish/collect_current_file.py +++ b/openpype/hosts/houdini/plugins/publish/collect_current_file.py @@ -1,7 +1,6 @@ import os import hou -from openpype.pipeline import legacy_io import pyblish.api From 71adb2964b5807742622949045899c845b5ada94 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 29 Mar 2023 17:52:54 +0200 Subject: [PATCH 739/898] Fix set correct variable --- openpype/hosts/houdini/plugins/publish/collect_current_file.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/houdini/plugins/publish/collect_current_file.py b/openpype/hosts/houdini/plugins/publish/collect_current_file.py index 3a391f22bd0..caf679f98be 100644 --- a/openpype/hosts/houdini/plugins/publish/collect_current_file.py +++ b/openpype/hosts/houdini/plugins/publish/collect_current_file.py @@ -20,7 +20,7 @@ def process(self, instance): # By default, Houdini will even point a new scene to a path. # However if the file is not saved at all and does not exist, # we assume the user never set it. - filepath = "" + current_file = "" elif os.path.basename(current_file) == "untitled.hip": # Due to even a new file being called 'untitled.hip' we are unable From 911c089319b7b90fc6e5726555d9fc9aa5d21a80 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 29 Mar 2023 17:54:17 +0200 Subject: [PATCH 740/898] Fix collect current file - Fix families filtering - Remove unused import - Fix correct detection if scene is new but unsaved scene --- .../hosts/houdini/plugins/publish/collect_current_file.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/houdini/plugins/publish/collect_current_file.py b/openpype/hosts/houdini/plugins/publish/collect_current_file.py index 9cca07fdc7c..caf679f98be 100644 --- a/openpype/hosts/houdini/plugins/publish/collect_current_file.py +++ b/openpype/hosts/houdini/plugins/publish/collect_current_file.py @@ -1,7 +1,6 @@ import os import hou -from openpype.pipeline import legacy_io import pyblish.api @@ -11,7 +10,7 @@ class CollectHoudiniCurrentFile(pyblish.api.InstancePlugin): order = pyblish.api.CollectorOrder - 0.01 label = "Houdini Current File" hosts = ["houdini"] - family = ["workfile"] + families = ["workfile"] def process(self, instance): """Inject the current working file""" @@ -21,7 +20,7 @@ def process(self, instance): # By default, Houdini will even point a new scene to a path. # However if the file is not saved at all and does not exist, # we assume the user never set it. - filepath = "" + current_file = "" elif os.path.basename(current_file) == "untitled.hip": # Due to even a new file being called 'untitled.hip' we are unable From 9a71cfec41577ce7c766a99d41c3cfc5c24b5956 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 29 Mar 2023 17:57:12 +0200 Subject: [PATCH 741/898] Allow passing an empty environment explicitly like `env = {}` --- openpype/lib/execute.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/lib/execute.py b/openpype/lib/execute.py index 6f9a0952851..c01aad734fc 100644 --- a/openpype/lib/execute.py +++ b/openpype/lib/execute.py @@ -198,7 +198,7 @@ def run_openpype_process(*args, **kwargs): args = get_openpype_execute_args(*args) env = kwargs.pop("env", None) # Keep env untouched if are passed and not empty - if not env: + if env is None: # Skip envs that can affect OpenPype process # - fill more if you find more env = clean_envs_for_openpype_process(os.environ) From 391b7450dd98bc748253c39630fc45c023ca7be9 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 29 Mar 2023 17:58:22 +0200 Subject: [PATCH 742/898] Don't pass empty `env` since it didn't do that prior to this either --- openpype/pipeline/colorspace.py | 3 +-- openpype/plugins/publish/extract_burnin.py | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/openpype/pipeline/colorspace.py b/openpype/pipeline/colorspace.py index 2085e2d37f2..4cea92a4e46 100644 --- a/openpype/pipeline/colorspace.py +++ b/openpype/pipeline/colorspace.py @@ -218,8 +218,7 @@ def get_data_subprocess(config_path, data_type): log.info("Executing: {}".format(" ".join(args))) process_kwargs = { - "logger": log, - "env": {} + "logger": log } run_openpype_process(*args, **process_kwargs) diff --git a/openpype/plugins/publish/extract_burnin.py b/openpype/plugins/publish/extract_burnin.py index 95575444b27..ed39bd93544 100644 --- a/openpype/plugins/publish/extract_burnin.py +++ b/openpype/plugins/publish/extract_burnin.py @@ -336,8 +336,7 @@ def main_process(self, instance): # Run burnin script process_kwargs = { - "logger": self.log, - "env": {} + "logger": self.log } run_openpype_process(*args, **process_kwargs) From 168a49dba66b1dca067b0909300290487ae94e49 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 29 Mar 2023 18:00:03 +0200 Subject: [PATCH 743/898] Remove both `PYTHONPATH` and `PYTHONHOME` - Fixes an issue with Houdini Py3.7 conflict with OpenPype Py3.9 because Houdini sets `PYTHONHOME` --- openpype/lib/execute.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/openpype/lib/execute.py b/openpype/lib/execute.py index c01aad734fc..0c5ae2df8aa 100644 --- a/openpype/lib/execute.py +++ b/openpype/lib/execute.py @@ -170,11 +170,13 @@ def clean_envs_for_openpype_process(env=None): """ if env is None: env = os.environ - return { - key: value - for key, value in env.items() - if key not in ("PYTHONPATH",) - } + + # Exclude some environment variables from a copy of the environment + env = env.copy() + for key in ["PYTHONPATH", "PYTHONHOME"]: + env.pop(key, None) + + return env def run_openpype_process(*args, **kwargs): From 0d8a8af3711d6e696778ef8af611859886beebd6 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 29 Mar 2023 17:26:25 +0100 Subject: [PATCH 744/898] Use lib.get_all_children --- .../maya/tools/mayalookassigner/commands.py | 24 +------------------ 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/openpype/hosts/maya/tools/mayalookassigner/commands.py b/openpype/hosts/maya/tools/mayalookassigner/commands.py index d78e31111d9..3fd367e8604 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/commands.py +++ b/openpype/hosts/maya/tools/mayalookassigner/commands.py @@ -45,33 +45,11 @@ def get_namespace_from_node(node): return parts[0] if len(parts) > 1 else u":" -def list_descendents(nodes): - """Include full descendant hierarchy of given nodes. - - This is a workaround to cmds.listRelatives(allDescendents=True) because - this way correctly keeps children instance paths (see Maya documentation) - - This fixes LKD-26: assignments not working as expected on instanced shapes. - - Return: - list: List of children descendents of nodes - - """ - result = [] - while True: - nodes = cmds.listRelatives(nodes, - fullPath=True) - if nodes: - result.extend(nodes) - else: - return result - - def get_selected_nodes(): """Get information from current selection""" selection = cmds.ls(selection=True, long=True) - hierarchy = list_descendents(selection) + hierarchy = lib.get_all_children(selection) return list(set(selection + hierarchy)) From 6e04f620d949d80e20c315694cead3c0dc71d913 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 29 Mar 2023 22:06:14 +0200 Subject: [PATCH 745/898] project action fix glob path --- .github/pr-glob-labeler.yml | 98 ++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/.github/pr-glob-labeler.yml b/.github/pr-glob-labeler.yml index f23f74f3107..69df5ace755 100644 --- a/.github/pr-glob-labeler.yml +++ b/.github/pr-glob-labeler.yml @@ -1,102 +1,102 @@ # Add type: unittest label if any changes in tests folders 'type: unittest': -- **/*tests*/**/* +- ./**/*tests*/**/* # any changes in documentation structure 'type: documentation': -- **/*website*/**/* -- **/*docs*/**/* +- /**/*website*/**/* +- /**/*docs*/**/* # hosts triage 'host: Nuke': -- **/*nuke* -- **/*nuke*/**/* +- /**/*nuke* +- ./**/*nuke*/**/* 'host: Photoshop': -- **/*photoshop* -- **/*photoshop*/**/* +- ./**/*photoshop* +- ./**/*photoshop*/**/* 'host: Harmony': -- **/*harmony* -- **/*harmony*/**/* +- ./**/*harmony* +- ./**/*harmony*/**/* 'host: UE': -- **/*unreal* -- **/*unreal*/**/* +- ./**/*unreal* +- ./**/*unreal*/**/* 'host: Houdini': -- **/*houdini* -- **/*houdini*/**/* +- ./**/*houdini* +- ./**/*houdini*/**/* 'host: Maya': -- **/*maya* -- **/*maya*/**/* +- ./**/*maya* +- ./**/*maya*/**/* 'host: Resolve': -- **/*resolve* -- **/*resolve*/**/* +- ./**/*resolve* +- ./**/*resolve*/**/* 'host: Blender': -- **/*blender* -- **/*blender*/**/* +- ./**/*blender* +- ./**/*blender*/**/* 'host: Hiero': -- **/*hiero* -- **/*hiero*/**/* +- ./**/*hiero* +- ./**/*hiero*/**/* 'host: Fusion': -- **/*fusion* -- **/*fusion*/**/* +- ./**/*fusion* +- ./**/*fusion*/**/* 'host: Flame': -- **/*flame* -- **/*flame*/**/* +- ./**/*flame* +- ./**/*flame*/**/* 'host: TrayPublisher': -- **/*traypublisher* -- **/*traypublisher*/**/* +- ./**/*traypublisher* +- ./**/*traypublisher*/**/* 'host: 3dsmax': -- **/*max* -- **/*max*/**/* +- ./**/*max* +- ./**/*max*/**/* 'host: TV Paint': -- **/*tvpaint* -- **/*tvpaint*/**/* +- ./**/*tvpaint* +- ./**/*tvpaint*/**/* 'host: CelAction': -- **/*celaction* -- **/*celaction*/**/* +- ./**/*celaction* +- ./**/*celaction*/**/* 'host: After Effects': -- **/*aftereffects* -- **/*aftereffects*/**/* +- ./**/*aftereffects* +- ./**/*aftereffects*/**/* 'host: Substance Painter': -- **/*substancepainter* -- **/*substancepainter*/**/* +- ./**/*substancepainter* +- ./**/*substancepainter*/**/* # modules triage 'module: Deadline': -- **/*deadline* -- **/*deadline*/**/* +- ./**/*deadline* +- ./**/*deadline*/**/* 'module: RoyalRender': -- **/*royalrender* -- **/*royalrender*/**/* +- ./**/*royalrender* +- ./**/*royalrender*/**/* 'module: Sitesync': -- **/*sync_server* -- **/*sync_server*/**/* +- ./**/*sync_server* +- ./**/*sync_server*/**/* 'module: Ftrack': -- **/*ftrack* -- **/*ftrack*/**/* +- ./**/*ftrack* +- ./**/*ftrack*/**/* 'module: Shotgrid': -- **/*shotgrid* -- **/*shotgrid*/**/* +- ./**/*shotgrid* +- ./**/*shotgrid*/**/* 'module: Kitsu': -- **/*kitsu* -- **/*kitsu*/**/* +- ./**/*kitsu* +- ./**/*kitsu*/**/* From 9dd6b3bbe225065d66d0d77afa71ef2db2460b14 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 29 Mar 2023 22:11:42 +0200 Subject: [PATCH 746/898] fix the glob expression --- .github/pr-glob-labeler.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/pr-glob-labeler.yml b/.github/pr-glob-labeler.yml index 69df5ace755..f5eae1067ed 100644 --- a/.github/pr-glob-labeler.yml +++ b/.github/pr-glob-labeler.yml @@ -1,15 +1,16 @@ # Add type: unittest label if any changes in tests folders 'type: unittest': -- ./**/*tests*/**/* +- /tests/**/* +- openpype/tests/**/* # any changes in documentation structure 'type: documentation': -- /**/*website*/**/* -- /**/*docs*/**/* +- '*/**/*website*/**/*' +- '*/**/*docs*/**/*' # hosts triage 'host: Nuke': -- /**/*nuke* +- ./**/*nuke* - ./**/*nuke*/**/* 'host: Photoshop': From 07f09b0fd691f59db61dea7dd125777c4a18ad90 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 29 Mar 2023 22:15:35 +0200 Subject: [PATCH 747/898] glob final fix of expressions with yaml compatibilty --- .github/pr-glob-labeler.yml | 95 ++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/.github/pr-glob-labeler.yml b/.github/pr-glob-labeler.yml index f5eae1067ed..286e7768b5e 100644 --- a/.github/pr-glob-labeler.yml +++ b/.github/pr-glob-labeler.yml @@ -1,7 +1,6 @@ # Add type: unittest label if any changes in tests folders 'type: unittest': -- /tests/**/* -- openpype/tests/**/* +- '*/*tests*/**/*' # any changes in documentation structure 'type: documentation': @@ -10,94 +9,94 @@ # hosts triage 'host: Nuke': -- ./**/*nuke* -- ./**/*nuke*/**/* +- '*/**/*nuke*' +- '*/**/*nuke*/**/*' 'host: Photoshop': -- ./**/*photoshop* -- ./**/*photoshop*/**/* +- '*/**/*photoshop*' +- '*/**/*photoshop*/**/*' 'host: Harmony': -- ./**/*harmony* -- ./**/*harmony*/**/* +- '*/**/*harmony*' +- '*/**/*harmony*/**/*' 'host: UE': -- ./**/*unreal* -- ./**/*unreal*/**/* +- '*/**/*unreal*' +- '*/**/*unreal*/**/*' 'host: Houdini': -- ./**/*houdini* -- ./**/*houdini*/**/* +- '*/**/*houdini*' +- '*/**/*houdini*/**/*' 'host: Maya': -- ./**/*maya* -- ./**/*maya*/**/* +- '*/**/*maya*' +- '*/**/*maya*/**/*' 'host: Resolve': -- ./**/*resolve* -- ./**/*resolve*/**/* +- '*/**/*resolve*' +- '*/**/*resolve*/**/*' 'host: Blender': -- ./**/*blender* -- ./**/*blender*/**/* +- '*/**/*blender*' +- '*/**/*blender*/**/*' 'host: Hiero': -- ./**/*hiero* -- ./**/*hiero*/**/* +- '*/**/*hiero*' +- '*/**/*hiero*/**/*' 'host: Fusion': -- ./**/*fusion* -- ./**/*fusion*/**/* +- '*/**/*fusion*' +- '*/**/*fusion*/**/*' 'host: Flame': -- ./**/*flame* -- ./**/*flame*/**/* +- '*/**/*flame*' +- '*/**/*flame*/**/*' 'host: TrayPublisher': -- ./**/*traypublisher* -- ./**/*traypublisher*/**/* +- '*/**/*traypublisher*' +- '*/**/*traypublisher*/**/*' 'host: 3dsmax': -- ./**/*max* -- ./**/*max*/**/* +- '*/**/*max*' +- '*/**/*max*/**/*' 'host: TV Paint': -- ./**/*tvpaint* -- ./**/*tvpaint*/**/* +- '*/**/*tvpaint*' +- '*/**/*tvpaint*/**/*' 'host: CelAction': -- ./**/*celaction* -- ./**/*celaction*/**/* +- '*/**/*celaction*' +- '*/**/*celaction*/**/*' 'host: After Effects': -- ./**/*aftereffects* -- ./**/*aftereffects*/**/* +- '*/**/*aftereffects*' +- '*/**/*aftereffects*/**/*' 'host: Substance Painter': -- ./**/*substancepainter* -- ./**/*substancepainter*/**/* +- '*/**/*substancepainter*' +- '*/**/*substancepainter*/**/*' # modules triage 'module: Deadline': -- ./**/*deadline* -- ./**/*deadline*/**/* +- '*/**/*deadline*' +- '*/**/*deadline*/**/*' 'module: RoyalRender': -- ./**/*royalrender* -- ./**/*royalrender*/**/* +- '*/**/*royalrender*' +- '*/**/*royalrender*/**/*' 'module: Sitesync': -- ./**/*sync_server* -- ./**/*sync_server*/**/* +- '*/**/*sync_server*' +- '*/**/*sync_server*/**/*' 'module: Ftrack': -- ./**/*ftrack* -- ./**/*ftrack*/**/* +- '*/**/*ftrack*' +- '*/**/*ftrack*/**/*' 'module: Shotgrid': -- ./**/*shotgrid* -- ./**/*shotgrid*/**/* +- '*/**/*shotgrid*' +- '*/**/*shotgrid*/**/*' 'module: Kitsu': -- ./**/*kitsu* -- ./**/*kitsu*/**/* +- '*/**/*kitsu*' +- '*/**/*kitsu*/**/*' From 9a2ef0738f1c26a9abbe5d64fa46a8584173f568 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 29 Mar 2023 22:19:42 +0200 Subject: [PATCH 748/898] bug label rather then bugfix --- .github/pr-branch-labeler.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pr-branch-labeler.yml b/.github/pr-branch-labeler.yml index 58bcbcb72ae..ca820510068 100644 --- a/.github/pr-branch-labeler.yml +++ b/.github/pr-branch-labeler.yml @@ -7,7 +7,7 @@ head: "enhancement/*" # Apply label "bugfix" if head matches one of "bugfix/*" or "hotfix/*" -'type: bugfix': +'type: bug': head: ["bugfix/*", "hotfix/*"] # Apply label "release" if base matches "release/*" From 2b540f1b2e0b6fbd9642d50bc4a81c94b3e58a89 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 29 Mar 2023 22:26:59 +0200 Subject: [PATCH 749/898] project action trigger to target pr --- .github/workflows/project_actions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index c66e378a5a3..769f40e0b8b 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -1,7 +1,7 @@ name: project-actions on: - pull_request: + pull_request_target: types: [opened, synchronize, assigned, review_requested] pull_request_review: types: [submitted] From 32a30127a37da7ee0ac8aee6d4a69265b70c110e Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 29 Mar 2023 23:06:21 +0200 Subject: [PATCH 750/898] Fix playblasting in Maya 2020 with override viewport options #4730 --- openpype/vendor/python/common/capture.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/openpype/vendor/python/common/capture.py b/openpype/vendor/python/common/capture.py index 09a42d84d1e..e99ea5438d9 100644 --- a/openpype/vendor/python/common/capture.py +++ b/openpype/vendor/python/common/capture.py @@ -733,6 +733,14 @@ def _applied_viewport_options(options, panel): options = dict(ViewportOptions, **(options or {})) + # BUGFIX Maya 2020 some keys in viewport options dict may not be unicode + # This is a local OpenPype edit to capture.py for issue #4730 + # TODO: Remove when dropping Maya 2020 compatibility + if int(cmds.about(version=True)) <= 2020: + options = { + str(key): value for key, value in options.items() + } + # separate the plugin display filter options since they need to # be set differently (see #55) plugins = cmds.pluginDisplayFilter(query=True, listFilters=True) From c304ccabcdc81094b0f9776f4c79668a2afb0eb8 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 29 Mar 2023 23:17:59 +0200 Subject: [PATCH 751/898] Change node type for OpenPypeContext `null` -> `subnet` - Plugins sometimes tend to add spare parameters to node, like Redshift making querying our custom parameters trickier since it's mixed in there. --- openpype/hosts/houdini/api/pipeline.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/houdini/api/pipeline.py b/openpype/hosts/houdini/api/pipeline.py index 9793679b45d..45e2f8f87fb 100644 --- a/openpype/hosts/houdini/api/pipeline.py +++ b/openpype/hosts/houdini/api/pipeline.py @@ -144,13 +144,10 @@ def create_context_node(): """ obj_network = hou.node("/obj") - op_ctx = obj_network.createNode("null", node_name="OpenPypeContext") - - # A null in houdini by default comes with content inside to visualize - # the null. However since we explicitly want to hide the node lets - # remove the content and disable the display flag of the node - for node in op_ctx.children(): - node.destroy() + op_ctx = obj_network.createNode("subnet", + node_name="OpenPypeContext", + run_init_scripts=False, + load_contents=False) op_ctx.moveToGoodPosition() op_ctx.setBuiltExplicitly(False) From d958f989e05dd8c7d58733abacf0b1ab335cb763 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 29 Mar 2023 23:57:35 +0200 Subject: [PATCH 752/898] Remove "handles" backwards compatibility --- openpype/hosts/fusion/plugins/load/actions.py | 5 ++--- openpype/hosts/houdini/api/lib.py | 6 ------ openpype/hosts/max/api/lib.py | 6 +----- openpype/hosts/maya/api/lib.py | 10 ++------- .../maya/plugins/publish/collect_instances.py | 7 ------- .../maya/plugins/publish/collect_review.py | 1 - .../maya/plugins/publish/extract_vrayproxy.py | 4 +--- .../plugins/publish/validate_frame_range.py | 4 +--- openpype/hosts/nuke/plugins/load/actions.py | 5 ++--- .../nuke/plugins/load/load_script_precomp.py | 1 - .../plugins/publish/collect_context_data.py | 2 -- .../nuke/plugins/publish/collect_gizmo.py | 1 - .../nuke/plugins/publish/collect_model.py | 1 - .../nuke/plugins/publish/collect_reads.py | 4 ++-- openpype/hosts/tvpaint/api/pipeline.py | 5 ----- .../publish/collect_context_entities.py | 21 +++---------------- openpype/plugins/publish/extract_burnin.py | 6 ------ openpype/plugins/publish/integrate.py | 2 +- openpype/plugins/publish/integrate_legacy.py | 2 +- openpype/tools/loader/model.py | 2 -- 20 files changed, 16 insertions(+), 79 deletions(-) diff --git a/openpype/hosts/fusion/plugins/load/actions.py b/openpype/hosts/fusion/plugins/load/actions.py index 3b14f022e51..f83ab433ee5 100644 --- a/openpype/hosts/fusion/plugins/load/actions.py +++ b/openpype/hosts/fusion/plugins/load/actions.py @@ -72,8 +72,7 @@ def load(self, context, name, namespace, data): return # Include handles - handles = version_data.get("handles", 0) - start -= handles - end += handles + start -= version_data.get("handleStart", 0) + end += version_data.get("handleEnd", 0) lib.update_frame_range(start, end) diff --git a/openpype/hosts/houdini/api/lib.py b/openpype/hosts/houdini/api/lib.py index 13f5a62ec33..674fe663021 100644 --- a/openpype/hosts/houdini/api/lib.py +++ b/openpype/hosts/houdini/api/lib.py @@ -488,14 +488,8 @@ def reset_framerange(): log.warning("No edit information found for %s" % asset_name) return - handles = asset_data.get("handles") or 0 handle_start = asset_data.get("handleStart") - if handle_start is None: - handle_start = handles - handle_end = asset_data.get("handleEnd") - if handle_end is None: - handle_end = handles frame_start -= int(handle_start) frame_end += int(handle_end) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index ac7d75db086..46051e770a6 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -215,13 +215,9 @@ def get_frame_range() -> dict: frame_end = asset["data"].get("edit_out") if frame_start is None or frame_end is None: return - handles = asset["data"].get("handles") or 0 + handle_start = asset["data"].get("handleStart") - if handle_start is None: - handle_start = handles handle_end = asset["data"].get("handleEnd") - if handle_end is None: - handle_end = handles return { "frameStart": frame_start, "frameEnd": frame_end, diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index aa1e501578c..8643d07848a 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -2082,14 +2082,8 @@ def get_frame_range(): cmds.warning("No edit information found for %s" % asset_name) return - handles = asset["data"].get("handles") or 0 - handle_start = asset["data"].get("handleStart") - if handle_start is None: - handle_start = handles - - handle_end = asset["data"].get("handleEnd") - if handle_end is None: - handle_end = handles + handle_start = asset["data"].get("handleStart") or 0 + handle_end = asset["data"].get("handleEnd") or 0 return { "frameStart": frame_start, diff --git a/openpype/hosts/maya/plugins/publish/collect_instances.py b/openpype/hosts/maya/plugins/publish/collect_instances.py index c5946265698..56fb38bc0ec 100644 --- a/openpype/hosts/maya/plugins/publish/collect_instances.py +++ b/openpype/hosts/maya/plugins/publish/collect_instances.py @@ -149,13 +149,6 @@ def process(self, context): # Append start frame and end frame to label if present if "frameStart" and "frameEnd" in data: - - # Backwards compatibility for 'handles' data - if "handles" in data: - data["handleStart"] = data["handles"] - data["handleEnd"] = data["handles"] - data.pop('handles') - # Take handles from context if not set locally on the instance for key in ["handleStart", "handleEnd"]: if key not in data: diff --git a/openpype/hosts/maya/plugins/publish/collect_review.py b/openpype/hosts/maya/plugins/publish/collect_review.py index 00565c5819b..3613d51c60c 100644 --- a/openpype/hosts/maya/plugins/publish/collect_review.py +++ b/openpype/hosts/maya/plugins/publish/collect_review.py @@ -74,7 +74,6 @@ def process(self, instance): data['frameEndHandle'] = instance.data["frameEndHandle"] data["frameStart"] = instance.data["frameStart"] data["frameEnd"] = instance.data["frameEnd"] - data['handles'] = instance.data.get('handles', None) data['step'] = instance.data['step'] data['fps'] = instance.data['fps'] data['review_width'] = instance.data['review_width'] diff --git a/openpype/hosts/maya/plugins/publish/extract_vrayproxy.py b/openpype/hosts/maya/plugins/publish/extract_vrayproxy.py index 9b10d2737de..df16c6c3572 100644 --- a/openpype/hosts/maya/plugins/publish/extract_vrayproxy.py +++ b/openpype/hosts/maya/plugins/publish/extract_vrayproxy.py @@ -30,9 +30,7 @@ def process(self, instance): # non-animated subsets keys = ["frameStart", "frameEnd", "handleStart", "handleEnd", - "frameStartHandle", "frameEndHandle", - # Backwards compatibility - "handles"] + "frameStartHandle", "frameEndHandle"] for key in keys: instance.data.pop(key, None) diff --git a/openpype/hosts/maya/plugins/publish/validate_frame_range.py b/openpype/hosts/maya/plugins/publish/validate_frame_range.py index 59b06874b3f..ccb351c880b 100644 --- a/openpype/hosts/maya/plugins/publish/validate_frame_range.py +++ b/openpype/hosts/maya/plugins/publish/validate_frame_range.py @@ -4,6 +4,7 @@ from openpype.pipeline.publish import ( RepairAction, ValidateContentsOrder, + PublishValidationError ) from openpype.hosts.maya.api.lib_rendersetup import ( get_attr_overrides, @@ -49,7 +50,6 @@ def process(self, instance): frame_start_handle = int(context.data.get("frameStartHandle")) frame_end_handle = int(context.data.get("frameEndHandle")) - handles = int(context.data.get("handles")) handle_start = int(context.data.get("handleStart")) handle_end = int(context.data.get("handleEnd")) frame_start = int(context.data.get("frameStart")) @@ -66,8 +66,6 @@ def process(self, instance): assert frame_start_handle <= frame_end_handle, ( "start frame is lower then end frame") - assert handles >= 0, ("handles cannot have negative values") - # compare with data on instance errors = [] if [ef for ef in self.exclude_families diff --git a/openpype/hosts/nuke/plugins/load/actions.py b/openpype/hosts/nuke/plugins/load/actions.py index e562c74c58c..3227a7ed987 100644 --- a/openpype/hosts/nuke/plugins/load/actions.py +++ b/openpype/hosts/nuke/plugins/load/actions.py @@ -74,8 +74,7 @@ def load(self, context, name, namespace, data): return # Include handles - handles = version_data.get("handles", 0) - start -= handles - end += handles + start -= version_data.get("handleStart", 0) + end += version_data.get("handleEnd", 0) lib.update_frame_range(start, end) diff --git a/openpype/hosts/nuke/plugins/load/load_script_precomp.py b/openpype/hosts/nuke/plugins/load/load_script_precomp.py index 90581c2f228..53e9a760031 100644 --- a/openpype/hosts/nuke/plugins/load/load_script_precomp.py +++ b/openpype/hosts/nuke/plugins/load/load_script_precomp.py @@ -138,7 +138,6 @@ def update(self, container, representation): "version": version_doc.get("name"), "colorspace": version_data.get("colorspace"), "source": version_data.get("source"), - "handles": version_data.get("handles"), "fps": version_data.get("fps"), "author": version_data.get("author") }) diff --git a/openpype/hosts/nuke/plugins/publish/collect_context_data.py b/openpype/hosts/nuke/plugins/publish/collect_context_data.py index b487c946f05..f1b49652057 100644 --- a/openpype/hosts/nuke/plugins/publish/collect_context_data.py +++ b/openpype/hosts/nuke/plugins/publish/collect_context_data.py @@ -49,8 +49,6 @@ def process(self, context): # sourcery skip: avoid-builtin-shadow "resolutionHeight": resolution_height, "pixelAspect": pixel_aspect, - # backward compatibility handles - "handles": handle_start, "handleStart": handle_start, "handleEnd": handle_end, "step": 1, diff --git a/openpype/hosts/nuke/plugins/publish/collect_gizmo.py b/openpype/hosts/nuke/plugins/publish/collect_gizmo.py index 3a877fc194a..e3c40a7a907 100644 --- a/openpype/hosts/nuke/plugins/publish/collect_gizmo.py +++ b/openpype/hosts/nuke/plugins/publish/collect_gizmo.py @@ -28,7 +28,6 @@ def process(self, instance): # Add version data to instance version_data = { - "handles": handle_start, "handleStart": handle_start, "handleEnd": handle_end, "frameStart": first_frame + handle_start, diff --git a/openpype/hosts/nuke/plugins/publish/collect_model.py b/openpype/hosts/nuke/plugins/publish/collect_model.py index 9da056052be..3fdf376d0c7 100644 --- a/openpype/hosts/nuke/plugins/publish/collect_model.py +++ b/openpype/hosts/nuke/plugins/publish/collect_model.py @@ -28,7 +28,6 @@ def process(self, instance): # Add version data to instance version_data = { - "handles": handle_start, "handleStart": handle_start, "handleEnd": handle_end, "frameStart": first_frame + handle_start, diff --git a/openpype/hosts/nuke/plugins/publish/collect_reads.py b/openpype/hosts/nuke/plugins/publish/collect_reads.py index a1144fbcc31..831ae29a27b 100644 --- a/openpype/hosts/nuke/plugins/publish/collect_reads.py +++ b/openpype/hosts/nuke/plugins/publish/collect_reads.py @@ -103,7 +103,6 @@ def process(self, instance): # Add version data to instance version_data = { - "handles": handle_start, "handleStart": handle_start, "handleEnd": handle_end, "frameStart": first_frame + handle_start, @@ -123,7 +122,8 @@ def process(self, instance): "frameStart": first_frame, "frameEnd": last_frame, "colorspace": colorspace, - "handles": int(asset_doc["data"].get("handles", 0)), + "handleStart": handle_start, + "handleEnd": handle_end, "step": 1, "fps": int(nuke.root()['fps'].value()) }) diff --git a/openpype/hosts/tvpaint/api/pipeline.py b/openpype/hosts/tvpaint/api/pipeline.py index 575e6aa7553..58fbd095452 100644 --- a/openpype/hosts/tvpaint/api/pipeline.py +++ b/openpype/hosts/tvpaint/api/pipeline.py @@ -504,14 +504,9 @@ def set_context_settings(project_name, asset_doc): print("Frame range was not found!") return - handles = asset_doc["data"].get("handles") or 0 handle_start = asset_doc["data"].get("handleStart") handle_end = asset_doc["data"].get("handleEnd") - if handle_start is None or handle_end is None: - handle_start = handles - handle_end = handles - # Always start from 0 Mark In and set only Mark Out mark_in = 0 mark_out = mark_in + (frame_end - frame_start) + handle_start + handle_end diff --git a/openpype/plugins/publish/collect_context_entities.py b/openpype/plugins/publish/collect_context_entities.py index 31fbeb5dbd3..312f5f0eb57 100644 --- a/openpype/plugins/publish/collect_context_entities.py +++ b/openpype/plugins/publish/collect_context_entities.py @@ -72,24 +72,9 @@ def process(self, context): context.data["frameStart"] = frame_start context.data["frameEnd"] = frame_end - handles = data.get("handles") or 0 - handle_start = data.get("handleStart") - if handle_start is None: - handle_start = handles - self.log.info(( - "Key \"handleStart\" is not set." - " Using value from \"handles\" key {}." - ).format(handle_start)) - - handle_end = data.get("handleEnd") - if handle_end is None: - handle_end = handles - self.log.info(( - "Key \"handleEnd\" is not set." - " Using value from \"handles\" key {}." - ).format(handle_end)) - - context.data["handles"] = int(handles) + handle_start = data.get("handleStart") or 0 + handle_end = data.get("handleEnd") or 0 + context.data["handleStart"] = int(handle_start) context.data["handleEnd"] = int(handle_end) diff --git a/openpype/plugins/publish/extract_burnin.py b/openpype/plugins/publish/extract_burnin.py index 95575444b27..3732a226364 100644 --- a/openpype/plugins/publish/extract_burnin.py +++ b/openpype/plugins/publish/extract_burnin.py @@ -457,12 +457,6 @@ def prepare_basic_data(self, instance): frame_end = 1 frame_end = int(frame_end) - handles = instance.data.get("handles") - if handles is None: - handles = context.data.get("handles") - if handles is None: - handles = 0 - handle_start = instance.data.get("handleStart") if handle_start is None: handle_start = context.data.get("handleStart") diff --git a/openpype/plugins/publish/integrate.py b/openpype/plugins/publish/integrate.py index 760b1a6b370..d38b5caa9d1 100644 --- a/openpype/plugins/publish/integrate.py +++ b/openpype/plugins/publish/integrate.py @@ -912,7 +912,7 @@ def create_version_data(self, instance): # Include optional data if present in optionals = [ - "frameStart", "frameEnd", "step", "handles", + "frameStart", "frameEnd", "step", "handleEnd", "handleStart", "sourceHashes" ] for key in optionals: diff --git a/openpype/plugins/publish/integrate_legacy.py b/openpype/plugins/publish/integrate_legacy.py index 1d0177f1515..3f1f6ad0c92 100644 --- a/openpype/plugins/publish/integrate_legacy.py +++ b/openpype/plugins/publish/integrate_legacy.py @@ -987,7 +987,7 @@ def create_version_data(self, context, instance): # Include optional data if present in optionals = [ - "frameStart", "frameEnd", "step", "handles", + "frameStart", "frameEnd", "step", "handleEnd", "handleStart", "sourceHashes" ] for key in optionals: diff --git a/openpype/tools/loader/model.py b/openpype/tools/loader/model.py index 5944808f8bb..39e0bd98c34 100644 --- a/openpype/tools/loader/model.py +++ b/openpype/tools/loader/model.py @@ -365,8 +365,6 @@ def set_version(self, index, version): handle_end = version_data.get("handleEnd", None) if handle_start is not None and handle_end is not None: handles = "{}-{}".format(str(handle_start), str(handle_end)) - else: - handles = version_data.get("handles", None) if frame_start is not None and frame_end is not None: # Remove superfluous zeros from numbers (3.0 -> 3) to improve From 227b5620fb202b73ccb444d026e9eb4ea1defbc0 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 29 Mar 2023 23:58:36 +0200 Subject: [PATCH 753/898] Remove `edit_in` and `edit_out` backwards compatibility --- openpype/hosts/houdini/api/lib.py | 4 ---- openpype/hosts/max/api/lib.py | 5 +---- openpype/hosts/maya/api/lib.py | 4 ---- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/openpype/hosts/houdini/api/lib.py b/openpype/hosts/houdini/api/lib.py index 674fe663021..9e13c7d1b4a 100644 --- a/openpype/hosts/houdini/api/lib.py +++ b/openpype/hosts/houdini/api/lib.py @@ -479,10 +479,6 @@ def reset_framerange(): frame_start = asset_data.get("frameStart") frame_end = asset_data.get("frameEnd") - # Backwards compatibility - if frame_start is None or frame_end is None: - frame_start = asset_data.get("edit_in") - frame_end = asset_data.get("edit_out") if frame_start is None or frame_end is None: log.warning("No edit information found for %s" % asset_name) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index 46051e770a6..afa8440d3a3 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -209,10 +209,7 @@ def get_frame_range() -> dict: asset = get_current_project_asset() frame_start = asset["data"].get("frameStart") frame_end = asset["data"].get("frameEnd") - # Backwards compatibility - if frame_start is None or frame_end is None: - frame_start = asset["data"].get("edit_in") - frame_end = asset["data"].get("edit_out") + if frame_start is None or frame_end is None: return diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index 8643d07848a..cc02c586519 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -2073,10 +2073,6 @@ def get_frame_range(): frame_start = asset["data"].get("frameStart") frame_end = asset["data"].get("frameEnd") - # Backwards compatibility - if frame_start is None or frame_end is None: - frame_start = asset["data"].get("edit_in") - frame_end = asset["data"].get("edit_out") if frame_start is None or frame_end is None: cmds.warning("No edit information found for %s" % asset_name) From 36f1a1103ee6e148c0dd42aa66f81fff05b352cf Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 30 Mar 2023 00:23:43 +0200 Subject: [PATCH 754/898] Fix #4693: Add `displayGradient` key to allow disabling gradient background --- openpype/hosts/maya/api/lib.py | 4 ++-- openpype/settings/defaults/project_settings/maya.json | 3 ++- .../projects_schema/schemas/schema_maya_capture.json | 10 +++++++--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index aa1e501578c..1a62e7dbc31 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -2478,8 +2478,8 @@ def load_capture_preset(data=None): float(value[2]) / 255 ] disp_options[key] = value - else: - disp_options['displayGradient'] = True + elif key == "displayGradient": + disp_options[key] = value options['display_options'] = disp_options diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index e914eb29f98..fda053e6e6a 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -795,6 +795,7 @@ "quality": 95 }, "Display Options": { + "override_display": true, "background": [ 125, 125, @@ -813,7 +814,7 @@ 125, 255 ], - "override_display": true + "displayGradient": true }, "Generic": { "isolate_view": true, diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json index 416e530db2e..a4a986bad89 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json @@ -48,7 +48,11 @@ "type": "label", "label": "Display Options" }, - + { + "type": "boolean", + "key": "override_display", + "label": "Override display options" + }, { "type": "color", "key": "background", @@ -66,8 +70,8 @@ }, { "type": "boolean", - "key": "override_display", - "label": "Override display options" + "key": "displayGradient", + "label": "Display background gradient" } ] }, From 0d7b42957f56e637a32ee489cd56588ddc7f7627 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 30 Mar 2023 07:08:24 +0100 Subject: [PATCH 755/898] Add shape to container when loading. --- openpype/hosts/maya/plugins/load/load_arnold_standin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/load/load_arnold_standin.py b/openpype/hosts/maya/plugins/load/load_arnold_standin.py index 3097ba21aaa..a527844f7bb 100644 --- a/openpype/hosts/maya/plugins/load/load_arnold_standin.py +++ b/openpype/hosts/maya/plugins/load/load_arnold_standin.py @@ -84,7 +84,7 @@ def load(self, context, name, namespace, options): sequence = is_sequence(os.listdir(os.path.dirname(self.fname))) cmds.setAttr(standin_shape + ".useFrameExtension", sequence) - nodes = [root, standin] + nodes = [root, standin, standin_shape] if operator is not None: nodes.append(operator) self[:] = nodes From 4889ffdd0b4f1f62ffb87418d5b903064e013bb2 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 30 Mar 2023 07:08:44 +0100 Subject: [PATCH 756/898] Dont query shapes when creating id hashes. --- openpype/hosts/maya/tools/mayalookassigner/commands.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/maya/tools/mayalookassigner/commands.py b/openpype/hosts/maya/tools/mayalookassigner/commands.py index 3fd367e8604..a71cb361a4a 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/commands.py +++ b/openpype/hosts/maya/tools/mayalookassigner/commands.py @@ -86,7 +86,6 @@ def create_asset_id_hash(nodes): """ node_id_hash = defaultdict(list) for node in nodes: - shapes = cmds.listRelatives(node, shapes=True, fullPath=True) # iterate over content of reference node if cmds.nodeType(node) == "reference": ref_hashes = create_asset_id_hash( @@ -101,11 +100,11 @@ def create_asset_id_hash(nodes): for k, _ in ids.items(): id = k.split(":")[0] node_id_hash[id].append(node) - elif shapes and cmds.nodeType(shapes[0]) == "aiStandIn": - path = arnold_standin.get_standin_path(shapes[0]) + elif cmds.nodeType(node) == "aiStandIn": + path = arnold_standin.get_standin_path(node) for id, _ in arnold_standin.get_id_by_node(path).items(): id = id.split(":")[0] - node_id_hash[id].append(shapes[0]) + node_id_hash[id].append(node) else: value = lib.get_id(node) if value is None: From 4ee44bcfec4b06f2ba95881261de7a79b0ae99a1 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 30 Mar 2023 09:15:48 +0200 Subject: [PATCH 757/898] update project action workflow --- .github/workflows/project_actions.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index 769f40e0b8b..4c09549ac4f 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -69,3 +69,4 @@ jobs: with: repo-token: ${{ secrets.YNPUT_BOT_TOKEN }} configuration-path: ".github/pr-glob-labeler.yml" + sync-labels: false From b752035022dd21abdf192a74084aefd6dfcf276f Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 30 Mar 2023 09:19:05 +0200 Subject: [PATCH 758/898] project actions sync labels true --- .github/workflows/project_actions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index 4c09549ac4f..8080d68156a 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -69,4 +69,4 @@ jobs: with: repo-token: ${{ secrets.YNPUT_BOT_TOKEN }} configuration-path: ".github/pr-glob-labeler.yml" - sync-labels: false + sync-labels: true From c3e4bc6409a91d88a481dffa98ecc9ff1454e32a Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 30 Mar 2023 09:29:55 +0200 Subject: [PATCH 759/898] project actions sync labels off update labeler --- .github/workflows/project_actions.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index 8080d68156a..cfee1405410 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -65,8 +65,8 @@ jobs: || (github.event_name == 'pull_request' && github.event.action == 'opened')}} steps: - name: Label PRs - Globe detection - uses: actions/labeler@v4 + uses: actions/labeler@v4.0.3 with: repo-token: ${{ secrets.YNPUT_BOT_TOKEN }} configuration-path: ".github/pr-glob-labeler.yml" - sync-labels: true + sync-labels: false From 18efd5276df132909d8eae592f09cd6d7b011cbb Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Thu, 30 Mar 2023 11:57:36 +0200 Subject: [PATCH 760/898] :art: add camera loader --- .../hosts/maya/plugins/load/load_camera.py | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 openpype/hosts/maya/plugins/load/load_camera.py diff --git a/openpype/hosts/maya/plugins/load/load_camera.py b/openpype/hosts/maya/plugins/load/load_camera.py new file mode 100644 index 00000000000..5e26e8c02f0 --- /dev/null +++ b/openpype/hosts/maya/plugins/load/load_camera.py @@ -0,0 +1,76 @@ +import openpype.hosts.maya.api.plugin +from openpype.hosts.maya.api.lib import get_container_members + + +class CameraLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): + """Reference Camera""" + + families = ["camera", "camerarig"] + label = "Reference camera" + representations = ["abc", "ma"] + order = -10 + icon = "code-fork" + color = "orange" + + def process_reference(self, context, name, namespace, data): + + import maya.cmds as cmds + # Get family type from the context + + cmds.loadPlugin("AbcImport.mll", quiet=True) + nodes = cmds.file(self.fname, + namespace=namespace, + sharedReferenceFile=False, + groupReference=True, + groupName="{}:{}".format(namespace, name), + reference=True, + returnNewNodes=True) + + cameras = cmds.ls(nodes, type="camera") + + # Check the Maya version, lockTransform has been introduced since + # Maya 2016.5 Ext 2 + version = int(cmds.about(version=True)) + if version >= 2016: + for camera in cameras: + cmds.camera(camera, edit=True, lockTransform=True) + else: + self.log.warning("This version of Maya does not support locking of" + " transforms of cameras.") + + self[:] = nodes + + return nodes + + def update(self, container, representation): + + from maya import cmds + + # Get the modelPanels that used the old camera + members = get_container_members(container) + old_cameras = cmds.ls(members, type="camera", long=True) + update_panels = [] + for panel in cmds.getPanel(type="modelPanel"): + cam = cmds.ls(cmds.modelPanel(panel, query=True, camera=True), + long=True) + + # Often but not always maya returns the transform from the + # modelPanel as opposed to the camera shape, so we convert it + # to explicitly be the camera shape + if cmds.nodeType(cam) != "camera": + cam = cmds.listRelatives(cam, + children=True, + fullPath=True, + type="camera")[0] + if cam in old_cameras: + update_panels.append(panel) + + # Perform regular reference update + super(CameraLoader, self).update(container, representation) + + # Update the modelPanels to contain the new camera + members = get_container_members(container) + new_cameras = cmds.ls(members, type="camera", long=True) + new_camera = new_cameras[0] + for panel in update_panels: + cmds.modelPanel(panel, edit=True, camera=new_camera) From 2e4fe5d7a57bf3ade0c5181bcfb0acc70ce74a90 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 30 Mar 2023 12:18:00 +0200 Subject: [PATCH 761/898] Ensure fallback to integer value if data does not exist Correctly Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- openpype/hosts/houdini/api/lib.py | 4 ++-- openpype/hosts/max/api/lib.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/houdini/api/lib.py b/openpype/hosts/houdini/api/lib.py index 9e13c7d1b4a..f19dc649925 100644 --- a/openpype/hosts/houdini/api/lib.py +++ b/openpype/hosts/houdini/api/lib.py @@ -484,8 +484,8 @@ def reset_framerange(): log.warning("No edit information found for %s" % asset_name) return - handle_start = asset_data.get("handleStart") - handle_end = asset_data.get("handleEnd") + handle_start = asset_data.get("handleStart", 0) + handle_end = asset_data.get("handleEnd", 0) frame_start -= int(handle_start) frame_end += int(handle_end) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index afa8440d3a3..ad9a450cad3 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -213,8 +213,8 @@ def get_frame_range() -> dict: if frame_start is None or frame_end is None: return - handle_start = asset["data"].get("handleStart") - handle_end = asset["data"].get("handleEnd") + handle_start = asset["data"].get("handleStart", 0) + handle_end = asset["data"].get("handleEnd", 0) return { "frameStart": frame_start, "frameEnd": frame_end, From ea2490ce5618f556d8374e488364cabefea51a7a Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 30 Mar 2023 13:37:52 +0200 Subject: [PATCH 762/898] project action - reducing job triggering --- .github/workflows/project_actions.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index cfee1405410..1e1a1441f7a 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -25,8 +25,8 @@ jobs: name: pr_size_label runs-on: ubuntu-latest if: | - ${{(github.event_name == 'pull_request' && github.event.action == 'synchronize') - || (github.event_name == 'pull_request' && github.event.action == 'assigned')}} + ${{(github.event_name == 'pull_request' && github.event.action == 'assigned') + || (github.event_name == 'pull_request' && github.event.action == 'opened')}} steps: - name: Add size label @@ -49,7 +49,7 @@ jobs: name: pr_branch_label runs-on: ubuntu-latest if: | - ${{(github.event_name == 'pull_request' && github.event.action == 'synchronize') + ${{(github.event_name == 'pull_request' && github.event.action == 'assigned') || (github.event_name == 'pull_request' && github.event.action == 'opened')}} steps: - name: Label PRs - Branch name detection @@ -61,7 +61,7 @@ jobs: name: pr_globe_label runs-on: ubuntu-latest if: | - ${{(github.event_name == 'pull_request' && github.event.action == 'synchronize') + ${{(github.event_name == 'pull_request' && github.event.action == 'assigned') || (github.event_name == 'pull_request' && github.event.action == 'opened')}} steps: - name: Label PRs - Globe detection From 3fae1f852194ee0b7ce69ca584c2f4605a3e1147 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 30 Mar 2023 13:59:22 +0200 Subject: [PATCH 763/898] Just some grammar tweaks --- openpype/client/entities.py | 8 +-- openpype/client/notes.md | 4 +- openpype/client/operations.py | 10 ++-- openpype/host/dirmap.py | 4 +- openpype/host/host.py | 6 +-- openpype/host/interfaces.py | 8 +-- .../api/extension/jsx/hostscript.jsx | 2 +- openpype/hosts/aftereffects/api/ws_stub.py | 2 +- openpype/hosts/blender/api/ops.py | 2 +- .../plugins/publish/extract_playblast.py | 2 +- openpype/hosts/flame/api/lib.py | 4 +- openpype/hosts/flame/api/pipeline.py | 2 +- openpype/hosts/flame/api/plugin.py | 54 +++++++++---------- .../hosts/flame/api/scripts/wiretap_com.py | 2 +- openpype/hosts/flame/api/utils.py | 2 +- openpype/hosts/flame/hooks/pre_flame_setup.py | 2 +- .../flame/plugins/create/create_shot_clip.py | 2 +- .../hosts/flame/plugins/load/load_clip.py | 6 +-- .../flame/plugins/load/load_clip_batch.py | 8 +-- .../publish/collect_timeline_instances.py | 4 +- .../publish/extract_subset_resources.py | 4 +- .../plugins/publish/integrate_batch_group.py | 2 +- openpype/hosts/harmony/api/README.md | 8 +-- openpype/hosts/harmony/api/TB_sceneOpened.js | 10 ++-- openpype/hosts/harmony/api/lib.py | 6 +-- openpype/hosts/harmony/api/server.py | 2 +- .../harmony/vendor/OpenHarmony/README.md | 6 +-- .../harmony/vendor/OpenHarmony/openHarmony.js | 8 +-- .../openHarmony/openHarmony_actions.js | 6 +-- .../openHarmony/openHarmony_application.js | 6 +-- .../openHarmony/openHarmony_attribute.js | 8 +-- .../openHarmony/openHarmony_backdrop.js | 4 +- .../openHarmony/openHarmony_color.js | 6 +-- .../openHarmony/openHarmony_column.js | 4 +- .../openHarmony/openHarmony_database.js | 4 +- .../openHarmony/openHarmony_dialog.js | 18 +++---- .../openHarmony/openHarmony_drawing.js | 18 +++---- .../openHarmony/openHarmony_element.js | 4 +- .../openHarmony/openHarmony_file.js | 6 +-- .../openHarmony/openHarmony_frame.js | 10 ++-- .../openHarmony/openHarmony_list.js | 6 +-- .../openHarmony/openHarmony_math.js | 16 +++--- .../openHarmony/openHarmony_metadata.js | 4 +- .../openHarmony/openHarmony_misc.js | 6 +-- .../openHarmony/openHarmony_network.js | 8 +-- .../openHarmony/openHarmony_node.js | 22 ++++---- .../openHarmony/openHarmony_nodeLink.js | 24 ++++----- .../vendor/OpenHarmony/openHarmony_tools.js | 8 +-- .../harmony/vendor/OpenHarmony/package.json | 2 +- openpype/hosts/hiero/api/__init__.py | 2 +- openpype/hosts/hiero/api/pipeline.py | 4 +- openpype/hosts/hiero/api/plugin.py | 26 ++++----- openpype/hosts/houdini/api/plugin.py | 2 +- openpype/hosts/houdini/api/shelves.py | 2 +- .../houdini/plugins/create/convert_legacy.py | 4 +- openpype/hosts/maya/api/commands.py | 2 +- openpype/hosts/maya/api/lib_renderproducts.py | 4 +- .../maya/api/workfile_template_builder.py | 4 +- openpype/hosts/maya/plugins/load/actions.py | 2 +- .../maya/plugins/load/load_arnold_standin.py | 2 +- .../publish/collect_multiverse_look.py | 2 +- .../maya/plugins/publish/extract_look.py | 2 +- .../publish/extract_multiverse_usd_over.py | 2 +- .../plugins/publish/reset_xgen_attributes.py | 2 +- .../publish/validate_camera_attributes.py | 2 +- .../plugins/publish/validate_maya_units.py | 4 +- .../publish/validate_mvlook_contents.py | 2 +- .../publish/validate_renderlayer_aovs.py | 4 +- .../validate_transform_naming_suffix.py | 2 +- openpype/hosts/nuke/api/lib.py | 18 +++---- openpype/hosts/nuke/api/plugin.py | 4 +- openpype/hosts/nuke/api/utils.py | 2 +- .../nuke/api/workfile_template_builder.py | 10 ++-- .../nuke/plugins/create/convert_legacy.py | 2 +- .../nuke/plugins/create/create_source.py | 2 +- .../nuke/plugins/publish/collect_writes.py | 2 +- .../nuke/plugins/publish/validate_backdrop.py | 2 +- .../photoshop/api/extension/host/index.jsx | 6 +-- openpype/hosts/resolve/api/lib.py | 6 +-- openpype/hosts/resolve/api/menu_style.qss | 2 +- openpype/hosts/resolve/api/plugin.py | 16 +++--- .../publish/collect_bulk_mov_instances.py | 4 +- .../plugins/publish/collect_context.py | 4 +- .../plugins/publish/collect_editorial.py | 2 +- .../plugins/publish/validate_frame_ranges.py | 2 +- openpype/hosts/traypublisher/api/editorial.py | 38 ++++++------- .../plugins/create/create_editorial.py | 14 ++--- .../publish/collect_simple_instances.py | 2 +- .../help/validate_layers_visibility.xml | 2 +- .../help/validate_workfile_metadata.xml | 2 +- .../help/validate_workfile_project_name.xml | 2 +- .../plugins/publish/validate_asset_name.py | 2 +- openpype/hosts/unreal/api/pipeline.py | 2 +- .../Source/OpenPype/Private/OpenPypeLib.cpp | 2 +- .../Public/Commandlets/OPActionResult.h | 12 ++--- .../Source/OpenPype/Private/OpenPypeLib.cpp | 2 +- .../Public/Commandlets/OPActionResult.h | 12 ++--- .../hosts/unreal/plugins/load/load_camera.py | 2 +- openpype/hosts/webpublisher/lib.py | 2 +- openpype/lib/applications.py | 2 +- openpype/lib/attribute_definitions.py | 6 +-- openpype/lib/events.py | 2 +- openpype/lib/execute.py | 2 +- openpype/lib/file_transaction.py | 2 +- openpype/lib/transcoding.py | 6 +-- openpype/lib/vendor_bin_utils.py | 4 +- openpype/modules/base.py | 14 ++--- openpype/modules/clockify/clockify_api.py | 2 +- openpype/modules/clockify/clockify_module.py | 2 +- openpype/modules/clockify/widgets.py | 2 +- .../plugins/publish/submit_nuke_deadline.py | 2 +- .../plugins/publish/submit_publish_job.py | 16 +++--- .../action_clone_review_session.py | 2 +- .../action_create_review_session.py | 2 +- .../action_prepare_project.py | 2 +- .../action_tranfer_hierarchical_values.py | 4 +- .../event_next_task_update.py | 2 +- .../event_push_frame_values_to_task.py | 2 +- .../event_radio_buttons.py | 2 +- .../event_sync_to_avalon.py | 14 ++--- .../event_task_to_parent_status.py | 4 +- .../event_user_assigment.py | 4 +- .../event_version_to_task_statuses.py | 2 +- .../action_batch_task_creation.py | 2 +- .../action_create_cust_attrs.py | 6 +-- .../action_create_folders.py | 2 +- .../action_delete_asset.py | 2 +- .../action_delete_old_versions.py | 4 +- .../event_handlers_user/action_delivery.py | 2 +- .../action_fill_workfile_attr.py | 2 +- .../event_handlers_user/action_job_killer.py | 6 +-- .../action_prepare_project.py | 4 +- .../ftrack/event_handlers_user/action_rv.py | 2 +- .../ftrack/event_handlers_user/action_seed.py | 10 ++-- .../action_store_thumbnails_to_avalon.py | 2 +- .../ftrack/ftrack_server/event_server_cli.py | 6 +-- openpype/modules/ftrack/lib/avalon_sync.py | 12 ++--- .../modules/ftrack/lib/custom_attributes.py | 2 +- .../ftrack/lib/ftrack_action_handler.py | 2 +- .../modules/ftrack/lib/ftrack_base_handler.py | 4 +- .../publish/collect_custom_attributes_data.py | 2 +- .../plugins/publish/integrate_ftrack_api.py | 2 +- .../publish/integrate_hierarchy_ftrack.py | 2 +- openpype/modules/ftrack/tray/ftrack_tray.py | 2 +- openpype/modules/interfaces.py | 2 +- openpype/modules/settings_action.py | 6 +-- openpype/pipeline/colorspace.py | 2 +- openpype/plugins/publish/extract_review.py | 2 +- .../schemas/schema_global_publish.json | 2 +- .../publisher/widgets/validations_widget.py | 4 +- 150 files changed, 412 insertions(+), 412 deletions(-) diff --git a/openpype/client/entities.py b/openpype/client/entities.py index c415be8816f..7054658c645 100644 --- a/openpype/client/entities.py +++ b/openpype/client/entities.py @@ -3,7 +3,7 @@ Goal is that most of functions here are called on (or with) an object that has project name as a context (e.g. on 'ProjectEntity'?). -+ We will need more specific functions doing wery specific queires really fast. ++ We will need more specific functions doing very specific queries really fast. """ import re @@ -193,7 +193,7 @@ def _get_assets( be found. asset_names (Iterable[str]): Name assets that should be found. parent_ids (Iterable[Union[str, ObjectId]]): Parent asset ids. - standard (bool): Query standart assets (type 'asset'). + standard (bool): Query standard assets (type 'asset'). archived (bool): Query archived assets (type 'archived_asset'). fields (Iterable[str]): Fields that should be returned. All fields are returned if 'None' is passed. @@ -1185,7 +1185,7 @@ def get_representations( standard=True, fields=None ): - """Representaion entities data from one project filtered by filters. + """Representation entities data from one project filtered by filters. Filters are additive (all conditions must pass to return subset). @@ -1231,7 +1231,7 @@ def get_archived_representations( names_by_version_ids=None, fields=None ): - """Archived representaion entities data from project with applied filters. + """Archived representation entities data from project with applied filters. Filters are additive (all conditions must pass to return subset). diff --git a/openpype/client/notes.md b/openpype/client/notes.md index a261b86eca9..59743892eb6 100644 --- a/openpype/client/notes.md +++ b/openpype/client/notes.md @@ -2,7 +2,7 @@ ## Reason Preparation for OpenPype v4 server. Goal is to remove direct mongo calls in code to prepare a little bit for different source of data for code before. To start think about database calls less as mongo calls but more universally. To do so was implemented simple wrapper around database calls to not use pymongo specific code. -Current goal is not to make universal database model which can be easily replaced with any different source of data but to make it close as possible. Current implementation of OpenPype is too tighly connected to pymongo and it's abilities so we're trying to get closer with long term changes that can be used even in current state. +Current goal is not to make universal database model which can be easily replaced with any different source of data but to make it close as possible. Current implementation of OpenPype is too tightly connected to pymongo and it's abilities so we're trying to get closer with long term changes that can be used even in current state. ## Queries Query functions don't use full potential of mongo queries like very specific queries based on subdictionaries or unknown structures. We try to avoid these calls as much as possible because they'll probably won't be available in future. If it's really necessary a new function can be added but only if it's reasonable for overall logic. All query functions were moved to `~/client/entities.py`. Each function has arguments with available filters and possible reduce of returned keys for each entity. @@ -14,7 +14,7 @@ Changes are a little bit complicated. Mongo has many options how update can happ Create operations expect already prepared document data, for that are prepared functions creating skeletal structures of documents (do not fill all required data), except `_id` all data should be right. Existence of entity is not validated so if the same creation operation is send n times it will create the entity n times which can cause issues. ### Update -Update operation require entity id and keys that should be changed, update dictionary must have {"key": value}. If value should be set in nested dictionary the key must have also all subkeys joined with dot `.` (e.g. `{"data": {"fps": 25}}` -> `{"data.fps": 25}`). To simplify update dictionaries were prepared functions which does that for you, their name has template `prepare__update_data` - they work on comparison of previous document and new document. If there is missing function for requested entity type it is because we didn't need it yet and require implementaion. +Update operation require entity id and keys that should be changed, update dictionary must have {"key": value}. If value should be set in nested dictionary the key must have also all subkeys joined with dot `.` (e.g. `{"data": {"fps": 25}}` -> `{"data.fps": 25}`). To simplify update dictionaries were prepared functions which does that for you, their name has template `prepare__update_data` - they work on comparison of previous document and new document. If there is missing function for requested entity type it is because we didn't need it yet and require implementation. ### Delete Delete operation need entity id. Entity will be deleted from mongo. diff --git a/openpype/client/operations.py b/openpype/client/operations.py index fd639c34a7c..ef48f2a1c49 100644 --- a/openpype/client/operations.py +++ b/openpype/client/operations.py @@ -368,7 +368,7 @@ def prepare_workfile_info_update_data(old_doc, new_doc, replace=True): class AbstractOperation(object): """Base operation class. - Opration represent a call into database. The call can create, change or + Operation represent a call into database. The call can create, change or remove data. Args: @@ -409,7 +409,7 @@ def to_mongo_operation(self): pass def to_data(self): - """Convert opration to data that can be converted to json or others. + """Convert operation to data that can be converted to json or others. Warning: Current state returns ObjectId objects which cannot be parsed by @@ -428,7 +428,7 @@ def to_data(self): class CreateOperation(AbstractOperation): - """Opeartion to create an entity. + """Operation to create an entity. Args: project_name (str): On which project operation will happen. @@ -485,7 +485,7 @@ def to_data(self): class UpdateOperation(AbstractOperation): - """Opeartion to update an entity. + """Operation to update an entity. Args: project_name (str): On which project operation will happen. @@ -552,7 +552,7 @@ def to_data(self): class DeleteOperation(AbstractOperation): - """Opeartion to delete an entity. + """Operation to delete an entity. Args: project_name (str): On which project operation will happen. diff --git a/openpype/host/dirmap.py b/openpype/host/dirmap.py index 1d084cccad5..42bf80ececc 100644 --- a/openpype/host/dirmap.py +++ b/openpype/host/dirmap.py @@ -2,7 +2,7 @@ Idea for current dirmap implementation was used from Maya where is possible to enter source and destination roots and maya will try each found source -in referenced file replace with each destionation paths. First path which +in referenced file replace with each destination paths. First path which exists is used. """ @@ -183,7 +183,7 @@ def _get_local_sync_dirmap(self): project_name, remote_site ) # dirmap has sense only with regular disk provider, in the workfile - # wont be root on cloud or sftp provider + # won't be root on cloud or sftp provider if remote_provider != "local_drive": remote_site = "studio" for root_name, active_site_dir in active_overrides.items(): diff --git a/openpype/host/host.py b/openpype/host/host.py index d2335c00621..630fb873a81 100644 --- a/openpype/host/host.py +++ b/openpype/host/host.py @@ -18,7 +18,7 @@ class HostBase(object): Compared to 'avalon' concept: What was before considered as functions in host implementation folder. The host implementation should primarily care about adding ability of creation - (mark subsets to be published) and optionaly about referencing published + (mark subsets to be published) and optionally about referencing published representations as containers. Host may need extend some functionality like working with workfiles @@ -129,9 +129,9 @@ def get_current_context(self): """Get current context information. This method should be used to get current context of host. Usage of - this method can be crutial for host implementations in DCCs where + this method can be crucial for host implementations in DCCs where can be opened multiple workfiles at one moment and change of context - can't be catched properly. + can't be caught properly. Default implementation returns values from 'legacy_io.Session'. diff --git a/openpype/host/interfaces.py b/openpype/host/interfaces.py index 999aefd2547..39581a3c691 100644 --- a/openpype/host/interfaces.py +++ b/openpype/host/interfaces.py @@ -81,7 +81,7 @@ def validate_load_methods(host): @abstractmethod def get_containers(self): - """Retreive referenced containers from scene. + """Retrieve referenced containers from scene. This can be implemented in hosts where referencing can be used. @@ -191,7 +191,7 @@ def open_workfile(self, filepath): @abstractmethod def get_current_workfile(self): - """Retreive path to current opened file. + """Retrieve path to current opened file. Returns: str: Path to file which is currently opened. @@ -220,7 +220,7 @@ def work_root(self, session): Default implementation keeps workdir untouched. Warnings: - We must handle this modification with more sofisticated way because + We must handle this modification with more sophisticated way because this can't be called out of DCC so opening of last workfile (calculated before DCC is launched) is complicated. Also breaking defined work template is not a good idea. @@ -302,7 +302,7 @@ def get_missing_publish_methods(host): required methods. Returns: - list[str]: Missing method implementations for new publsher + list[str]: Missing method implementations for new publisher workflow. """ diff --git a/openpype/hosts/aftereffects/api/extension/jsx/hostscript.jsx b/openpype/hosts/aftereffects/api/extension/jsx/hostscript.jsx index 9b211207de9..5c1d1634398 100644 --- a/openpype/hosts/aftereffects/api/extension/jsx/hostscript.jsx +++ b/openpype/hosts/aftereffects/api/extension/jsx/hostscript.jsx @@ -504,7 +504,7 @@ function addItemAsLayerToComp(comp_id, item_id, found_comp){ * Args: * comp_id (int): id of target composition * item_id (int): FootageItem.id - * found_comp (CompItem, optional): to limit quering if + * found_comp (CompItem, optional): to limit querying if * comp already found previously */ var comp = found_comp || app.project.itemByID(comp_id); diff --git a/openpype/hosts/aftereffects/api/ws_stub.py b/openpype/hosts/aftereffects/api/ws_stub.py index e5d6d9ed893..f094c7fa2a6 100644 --- a/openpype/hosts/aftereffects/api/ws_stub.py +++ b/openpype/hosts/aftereffects/api/ws_stub.py @@ -80,7 +80,7 @@ def get_metadata(self): Get complete stored JSON with metadata from AE.Metadata.Label field. - It contains containers loaded by any Loader OR instances creted + It contains containers loaded by any Loader OR instances created by Creator. Returns: diff --git a/openpype/hosts/blender/api/ops.py b/openpype/hosts/blender/api/ops.py index 158c32fb5a2..91cbfe524f9 100644 --- a/openpype/hosts/blender/api/ops.py +++ b/openpype/hosts/blender/api/ops.py @@ -24,7 +24,7 @@ PREVIEW_COLLECTIONS: Dict = dict() # This seems like a good value to keep the Qt app responsive and doesn't slow -# down Blender. At least on macOS I the interace of Blender gets very laggy if +# down Blender. At least on macOS I the interface of Blender gets very laggy if # you make it smaller. TIMER_INTERVAL: float = 0.01 if platform.system() == "Windows" else 0.1 diff --git a/openpype/hosts/blender/plugins/publish/extract_playblast.py b/openpype/hosts/blender/plugins/publish/extract_playblast.py index 8dc2f66c22a..5c3a138c3ad 100644 --- a/openpype/hosts/blender/plugins/publish/extract_playblast.py +++ b/openpype/hosts/blender/plugins/publish/extract_playblast.py @@ -50,7 +50,7 @@ def process(self, instance): # get isolate objects list isolate = instance.data("isolate", None) - # get ouput path + # get output path stagingdir = self.staging_dir(instance) filename = instance.name path = os.path.join(stagingdir, filename) diff --git a/openpype/hosts/flame/api/lib.py b/openpype/hosts/flame/api/lib.py index 6aca5c5ce61..ab713aed841 100644 --- a/openpype/hosts/flame/api/lib.py +++ b/openpype/hosts/flame/api/lib.py @@ -773,7 +773,7 @@ def __init__(self, path, logger=None): if logger: self.log = logger - # test if `dl_get_media_info` paht exists + # test if `dl_get_media_info` path exists self._validate_media_script_path() # derivate other feed variables @@ -993,7 +993,7 @@ def file_pattern(self, fpattern): def _validate_media_script_path(self): if not os.path.isfile(self.MEDIA_SCRIPT_PATH): - raise IOError("Media Scirpt does not exist: `{}`".format( + raise IOError("Media Script does not exist: `{}`".format( self.MEDIA_SCRIPT_PATH)) def _generate_media_info_file(self, fpath, feed_ext, feed_dir): diff --git a/openpype/hosts/flame/api/pipeline.py b/openpype/hosts/flame/api/pipeline.py index 3a233899619..d6fbf750ba0 100644 --- a/openpype/hosts/flame/api/pipeline.py +++ b/openpype/hosts/flame/api/pipeline.py @@ -38,7 +38,7 @@ def install(): pyblish.register_plugin_path(PUBLISH_PATH) register_loader_plugin_path(LOAD_PATH) register_creator_plugin_path(CREATE_PATH) - log.info("OpenPype Flame plug-ins registred ...") + log.info("OpenPype Flame plug-ins registered ...") # register callback for switching publishable pyblish.register_callback("instanceToggled", on_pyblish_instance_toggled) diff --git a/openpype/hosts/flame/api/plugin.py b/openpype/hosts/flame/api/plugin.py index 983d7486b39..df8c1ac8872 100644 --- a/openpype/hosts/flame/api/plugin.py +++ b/openpype/hosts/flame/api/plugin.py @@ -157,7 +157,7 @@ def create_row(self, layout, type_name, text, **kwargs): # convert label text to normal capitalized text with spaces label_text = self.camel_case_split(text) - # assign the new text to lable widget + # assign the new text to label widget label = QtWidgets.QLabel(label_text) label.setObjectName("LineLabel") @@ -345,8 +345,8 @@ class PublishableClip: "track": "sequence", } - # parents search patern - parents_search_patern = r"\{([a-z]*?)\}" + # parents search pattern + parents_search_pattern = r"\{([a-z]*?)\}" # default templates for non-ui use rename_default = False @@ -445,7 +445,7 @@ def convert(self): return self.current_segment def _populate_segment_default_data(self): - """ Populate default formating data from segment. """ + """ Populate default formatting data from segment. """ self.current_segment_default_data = { "_folder_": "shots", @@ -538,7 +538,7 @@ def _convert_to_marker_data(self): if not self.index_from_segment: self.count_steps *= self.rename_index - hierarchy_formating_data = {} + hierarchy_formatting_data = {} hierarchy_data = deepcopy(self.hierarchy_data) _data = self.current_segment_default_data.copy() if self.ui_inputs: @@ -552,7 +552,7 @@ def _convert_to_marker_data(self): # mark review layer if self.review_track and ( self.review_track not in self.review_track_default): - # if review layer is defined and not the same as defalut + # if review layer is defined and not the same as default self.review_layer = self.review_track # shot num calculate @@ -578,13 +578,13 @@ def _convert_to_marker_data(self): # fill up pythonic expresisons in hierarchy data for k, _v in hierarchy_data.items(): - hierarchy_formating_data[k] = _v["value"].format(**_data) + hierarchy_formatting_data[k] = _v["value"].format(**_data) else: # if no gui mode then just pass default data - hierarchy_formating_data = hierarchy_data + hierarchy_formatting_data = hierarchy_data tag_hierarchy_data = self._solve_tag_hierarchy_data( - hierarchy_formating_data + hierarchy_formatting_data ) tag_hierarchy_data.update({"heroTrack": True}) @@ -615,27 +615,27 @@ def _convert_to_marker_data(self): # in case track name and subset name is the same then add if self.subset_name == self.track_name: _hero_data["subset"] = self.subset - # assing data to return hierarchy data to tag + # assign data to return hierarchy data to tag tag_hierarchy_data = _hero_data break # add data to return data dict self.marker_data.update(tag_hierarchy_data) - def _solve_tag_hierarchy_data(self, hierarchy_formating_data): + def _solve_tag_hierarchy_data(self, hierarchy_formatting_data): """ Solve marker data from hierarchy data and templates. """ # fill up clip name and hierarchy keys - hierarchy_filled = self.hierarchy.format(**hierarchy_formating_data) - clip_name_filled = self.clip_name.format(**hierarchy_formating_data) + hierarchy_filled = self.hierarchy.format(**hierarchy_formatting_data) + clip_name_filled = self.clip_name.format(**hierarchy_formatting_data) # remove shot from hierarchy data: is not needed anymore - hierarchy_formating_data.pop("shot") + hierarchy_formatting_data.pop("shot") return { "newClipName": clip_name_filled, "hierarchy": hierarchy_filled, "parents": self.parents, - "hierarchyData": hierarchy_formating_data, + "hierarchyData": hierarchy_formatting_data, "subset": self.subset, "family": self.subset_family, "families": [self.family] @@ -650,17 +650,17 @@ def _convert_to_entity(self, type, template): type ) - # first collect formating data to use for formating template - formating_data = {} + # first collect formatting data to use for formatting template + formatting_data = {} for _k, _v in self.hierarchy_data.items(): value = _v["value"].format( **self.current_segment_default_data) - formating_data[_k] = value + formatting_data[_k] = value return { "entity_type": entity_type, "entity_name": template.format( - **formating_data + **formatting_data ) } @@ -668,9 +668,9 @@ def _create_parents(self): """ Create parents and return it in list. """ self.parents = [] - patern = re.compile(self.parents_search_patern) + pattern = re.compile(self.parents_search_pattern) - par_split = [(patern.findall(t).pop(), t) + par_split = [(pattern.findall(t).pop(), t) for t in self.hierarchy.split("/")] for type, template in par_split: @@ -902,22 +902,22 @@ def _rename_track_name(self, xml_track_data): ): return - formating_data = self._update_formating_data( + formatting_data = self._update_formatting_data( layerName=layer_name, layerUID=layer_uid ) name_obj.text = StringTemplate( self.layer_rename_template - ).format(formating_data) + ).format(formatting_data) - def _update_formating_data(self, **kwargs): - """ Updating formating data for layer rename + def _update_formatting_data(self, **kwargs): + """ Updating formatting data for layer rename Attributes: - key=value (optional): will be included to formating data + key=value (optional): will be included to formatting data as {key: value} Returns: - dict: anatomy context data for formating + dict: anatomy context data for formatting """ self.log.debug(">> self.clip_data: {}".format(self.clip_data)) clip_name_obj = self.clip_data.find("name") diff --git a/openpype/hosts/flame/api/scripts/wiretap_com.py b/openpype/hosts/flame/api/scripts/wiretap_com.py index 4825ff43865..a74172c4056 100644 --- a/openpype/hosts/flame/api/scripts/wiretap_com.py +++ b/openpype/hosts/flame/api/scripts/wiretap_com.py @@ -203,7 +203,7 @@ def _get_all_volumes(self): list: all available volumes in server Rises: - AttributeError: unable to get any volumes childs from server + AttributeError: unable to get any volumes children from server """ root = WireTapNodeHandle(self._server, "/volumes") children_num = WireTapInt(0) diff --git a/openpype/hosts/flame/api/utils.py b/openpype/hosts/flame/api/utils.py index fb8bdee42df..80a5c47e892 100644 --- a/openpype/hosts/flame/api/utils.py +++ b/openpype/hosts/flame/api/utils.py @@ -108,7 +108,7 @@ def _sync_utility_scripts(env=None): shutil.copy2(src, dst) except (PermissionError, FileExistsError) as msg: log.warning( - "Not able to coppy to: `{}`, Problem with: `{}`".format( + "Not able to copy to: `{}`, Problem with: `{}`".format( dst, msg ) diff --git a/openpype/hosts/flame/hooks/pre_flame_setup.py b/openpype/hosts/flame/hooks/pre_flame_setup.py index 713daf10317..8034885c478 100644 --- a/openpype/hosts/flame/hooks/pre_flame_setup.py +++ b/openpype/hosts/flame/hooks/pre_flame_setup.py @@ -153,7 +153,7 @@ def _get_flame_fps(self, fps_num): def _add_pythonpath(self): pythonpath = self.launch_context.env.get("PYTHONPATH") - # separate it explicity by `;` that is what we use in settings + # separate it explicitly by `;` that is what we use in settings new_pythonpath = self.flame_pythonpath.split(os.pathsep) new_pythonpath += pythonpath.split(os.pathsep) diff --git a/openpype/hosts/flame/plugins/create/create_shot_clip.py b/openpype/hosts/flame/plugins/create/create_shot_clip.py index 4fb041a4b26..b01354c3137 100644 --- a/openpype/hosts/flame/plugins/create/create_shot_clip.py +++ b/openpype/hosts/flame/plugins/create/create_shot_clip.py @@ -209,7 +209,7 @@ def get_gui_inputs(self): "type": "QComboBox", "label": "Subset Name", "target": "ui", - "toolTip": "chose subset name patern, if [ track name ] is selected, name of track layer will be used", # noqa + "toolTip": "chose subset name pattern, if [ track name ] is selected, name of track layer will be used", # noqa "order": 0}, "subsetFamily": { "value": ["plate", "take"], diff --git a/openpype/hosts/flame/plugins/load/load_clip.py b/openpype/hosts/flame/plugins/load/load_clip.py index 25b31c94a32..dfb2d2b6f00 100644 --- a/openpype/hosts/flame/plugins/load/load_clip.py +++ b/openpype/hosts/flame/plugins/load/load_clip.py @@ -61,9 +61,9 @@ def load(self, context, name, namespace, options): self.layer_rename_template = self.layer_rename_template.replace( "output", "representation") - formating_data = deepcopy(context["representation"]["context"]) + formatting_data = deepcopy(context["representation"]["context"]) clip_name = StringTemplate(self.clip_name_template).format( - formating_data) + formatting_data) # convert colorspace with ocio to flame mapping # in imageio flame section @@ -88,7 +88,7 @@ def load(self, context, name, namespace, options): "version": "v{:0>3}".format(version_name), "layer_rename_template": self.layer_rename_template, "layer_rename_patterns": self.layer_rename_patterns, - "context_data": formating_data + "context_data": formatting_data } self.log.debug(pformat( loading_context diff --git a/openpype/hosts/flame/plugins/load/load_clip_batch.py b/openpype/hosts/flame/plugins/load/load_clip_batch.py index 86bc0f8f1e8..5c5a77f0d09 100644 --- a/openpype/hosts/flame/plugins/load/load_clip_batch.py +++ b/openpype/hosts/flame/plugins/load/load_clip_batch.py @@ -58,11 +58,11 @@ def load(self, context, name, namespace, options): self.layer_rename_template = self.layer_rename_template.replace( "output", "representation") - formating_data = deepcopy(context["representation"]["context"]) - formating_data["batch"] = self.batch.name.get_value() + formatting_data = deepcopy(context["representation"]["context"]) + formatting_data["batch"] = self.batch.name.get_value() clip_name = StringTemplate(self.clip_name_template).format( - formating_data) + formatting_data) # convert colorspace with ocio to flame mapping # in imageio flame section @@ -88,7 +88,7 @@ def load(self, context, name, namespace, options): "version": "v{:0>3}".format(version_name), "layer_rename_template": self.layer_rename_template, "layer_rename_patterns": self.layer_rename_patterns, - "context_data": formating_data + "context_data": formatting_data } self.log.debug(pformat( loading_context diff --git a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py index 76d48dded24..23fdf5e7851 100644 --- a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py +++ b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py @@ -203,7 +203,7 @@ def _get_comment_attributes(self, segment): self._get_xml_preset_attrs( attributes, split) - # add xml overides resolution to instance data + # add xml overrides resolution to instance data xml_overrides = attributes["xml_overrides"] if xml_overrides.get("width"): attributes.update({ @@ -284,7 +284,7 @@ def _get_head_tail(self, clip_data, otio_clip, handle_start, handle_end): self.log.debug("__ head: `{}`".format(head)) self.log.debug("__ tail: `{}`".format(tail)) - # HACK: it is here to serve for versions bellow 2021.1 + # HACK: it is here to serve for versions below 2021.1 if not any([head, tail]): retimed_attributes = get_media_range_with_retimes( otio_clip, handle_start, handle_end) diff --git a/openpype/hosts/flame/plugins/publish/extract_subset_resources.py b/openpype/hosts/flame/plugins/publish/extract_subset_resources.py index 5082217db06..a7979ab4d53 100644 --- a/openpype/hosts/flame/plugins/publish/extract_subset_resources.py +++ b/openpype/hosts/flame/plugins/publish/extract_subset_resources.py @@ -227,7 +227,7 @@ def process(self, instance): self.hide_others( exporting_clip, segment_name, s_track_name) - # change name patern + # change name pattern name_patern_xml = ( "__{}.").format( unique_name) @@ -358,7 +358,7 @@ def process(self, instance): representation_data["stagingDir"] = n_stage_dir files = n_files - # add files to represetation but add + # add files to representation but add # imagesequence as list if ( # first check if path in files is not mov extension diff --git a/openpype/hosts/flame/plugins/publish/integrate_batch_group.py b/openpype/hosts/flame/plugins/publish/integrate_batch_group.py index 4d45f67ded2..4f3945bb0fd 100644 --- a/openpype/hosts/flame/plugins/publish/integrate_batch_group.py +++ b/openpype/hosts/flame/plugins/publish/integrate_batch_group.py @@ -50,7 +50,7 @@ def process(self, instance): self._load_clip_to_context(instance, bgroup) def _add_nodes_to_batch_with_links(self, instance, task_data, batch_group): - # get write file node properties > OrederDict because order does mater + # get write file node properties > OrederDict because order does matter write_pref_data = self._get_write_prefs(instance, task_data) batch_nodes = [ diff --git a/openpype/hosts/harmony/api/README.md b/openpype/hosts/harmony/api/README.md index b39f900886a..12f21f551a2 100644 --- a/openpype/hosts/harmony/api/README.md +++ b/openpype/hosts/harmony/api/README.md @@ -432,11 +432,11 @@ copy_files = """function copyFile(srcFilename, dstFilename) import_files = """function %s_import_files() { - var PNGTransparencyMode = 0; // Premultiplied wih Black - var TGATransparencyMode = 0; // Premultiplied wih Black - var SGITransparencyMode = 0; // Premultiplied wih Black + var PNGTransparencyMode = 0; // Premultiplied with Black + var TGATransparencyMode = 0; // Premultiplied with Black + var SGITransparencyMode = 0; // Premultiplied with Black var LayeredPSDTransparencyMode = 1; // Straight - var FlatPSDTransparencyMode = 2; // Premultiplied wih White + var FlatPSDTransparencyMode = 2; // Premultiplied with White function getUniqueColumnName( column_prefix ) { diff --git a/openpype/hosts/harmony/api/TB_sceneOpened.js b/openpype/hosts/harmony/api/TB_sceneOpened.js index e7cd555332e..6614f14f9ef 100644 --- a/openpype/hosts/harmony/api/TB_sceneOpened.js +++ b/openpype/hosts/harmony/api/TB_sceneOpened.js @@ -142,10 +142,10 @@ function Client() { }; /** - * Process recieved request. This will eval recieved function and produce + * Process received request. This will eval received function and produce * results. * @function - * @param {object} request - recieved request JSON + * @param {object} request - received request JSON * @return {object} result of evaled function. */ self.processRequest = function(request) { @@ -245,7 +245,7 @@ function Client() { var request = JSON.parse(to_parse); var mid = request.message_id; // self.logDebug('[' + mid + '] - Request: ' + '\n' + JSON.stringify(request)); - self.logDebug('[' + mid + '] Recieved.'); + self.logDebug('[' + mid + '] Received.'); request.result = self.processRequest(request); self.logDebug('[' + mid + '] Processing done.'); @@ -286,8 +286,8 @@ function Client() { /** Harmony 21.1 doesn't have QDataStream anymore. This means we aren't able to write bytes into QByteArray so we had - modify how content lenght is sent do the server. - Content lenght is sent as string of 8 char convertible into integer + modify how content length is sent do the server. + Content length is sent as string of 8 char convertible into integer (instead of 0x00000001[4 bytes] > "000000001"[8 bytes]) */ var codec_name = new QByteArray().append("UTF-8"); diff --git a/openpype/hosts/harmony/api/lib.py b/openpype/hosts/harmony/api/lib.py index e1e77bfbee0..8048705dc8d 100644 --- a/openpype/hosts/harmony/api/lib.py +++ b/openpype/hosts/harmony/api/lib.py @@ -394,7 +394,7 @@ def get_scene_data(): "function": "AvalonHarmony.getSceneData" })["result"] except json.decoder.JSONDecodeError: - # Means no sceen metadata has been made before. + # Means no scene metadata has been made before. return {} except KeyError: # Means no existing scene metadata has been made. @@ -465,7 +465,7 @@ def imprint(node_id, data, remove=False): Example: >>> from openpype.hosts.harmony.api import lib >>> node = "Top/Display" - >>> data = {"str": "someting", "int": 1, "float": 0.32, "bool": True} + >>> data = {"str": "something", "int": 1, "float": 0.32, "bool": True} >>> lib.imprint(layer, data) """ scene_data = get_scene_data() @@ -550,7 +550,7 @@ def save_scene(): method prevents this double request and safely saves the scene. """ - # Need to turn off the backgound watcher else the communication with + # Need to turn off the background watcher else the communication with # the server gets spammed with two requests at the same time. scene_path = send( {"function": "AvalonHarmony.saveScene"})["result"] diff --git a/openpype/hosts/harmony/api/server.py b/openpype/hosts/harmony/api/server.py index ecf339d91bd..04048e5c84d 100644 --- a/openpype/hosts/harmony/api/server.py +++ b/openpype/hosts/harmony/api/server.py @@ -61,7 +61,7 @@ def process_request(self, request): "module": (str), # Module of method. "method" (str), # Name of method in module. "args" (list), # Arguments to pass to method. - "kwargs" (dict), # Keywork arguments to pass to method. + "kwargs" (dict), # Keyword arguments to pass to method. "reply" (bool), # Optional wait for method completion. } """ diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/README.md b/openpype/hosts/harmony/vendor/OpenHarmony/README.md index 7c77fbfcfa8..064afca86ca 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/README.md +++ b/openpype/hosts/harmony/vendor/OpenHarmony/README.md @@ -6,7 +6,7 @@ Ever tried to make a simple script for toonboom Harmony, then got stumped by the Toonboom Harmony is a very powerful software, with hundreds of functions and tools, and it unlocks a great amount of possibilities for animation studios around the globe. And... being the produce of the hard work of a small team forced to prioritise, it can also be a bit rustic at times! -We are users at heart, animators and riggers, who just want to interact with the software as simply as possible. Simplicity is at the heart of the design of openHarmony. But we also are developpers, and we made the library for people like us who can't resist tweaking the software and bend it in all possible ways, and are looking for powerful functions to help them do it. +We are users at heart, animators and riggers, who just want to interact with the software as simply as possible. Simplicity is at the heart of the design of openHarmony. But we also are developers, and we made the library for people like us who can't resist tweaking the software and bend it in all possible ways, and are looking for powerful functions to help them do it. This library's aim is to create a more direct way to interact with Toonboom through scripts, by providing a more intuitive way to access its elements, and help with the cumbersome and repetitive tasks as well as help unlock untapped potential in its many available systems. So we can go from having to do things like this: @@ -78,7 +78,7 @@ All you have to do is call : ```javascript include("openHarmony.js"); ``` -at the beggining of your script. +at the beginning of your script. You can ask your users to download their copy of the library and store it alongside, or bundle it as you wish as long as you include the license file provided on this repository. @@ -129,7 +129,7 @@ Check that the environment variable `LIB_OPENHARMONY_PATH` is set correctly to t ## How to add openHarmony to vscode intellisense for autocompletion Although not fully supported, you can get most of the autocompletion features to work by adding the following lines to a `jsconfig.json` file placed at the root of your working folder. -The paths need to be relative which means the openHarmony source code must be placed directly in your developping environnement. +The paths need to be relative which means the openHarmony source code must be placed directly in your developping environment. For example, if your working folder contains the openHarmony source in a folder called `OpenHarmony` and your working scripts in a folder called `myScripts`, place the `jsconfig.json` file at the root of the folder and add these lines to the file: diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony.js index 530c0902c52..ae65d32a2b4 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -78,7 +78,7 @@ * $.log("hello"); // prints out a message to the MessageLog. * var myPoint = new $.oPoint(0,0,0); // create a new class instance from an openHarmony class. * - * // function members of the $ objects get published to the global scope, which means $ can be ommited + * // function members of the $ objects get published to the global scope, which means $ can be omitted * * log("hello"); * var myPoint = new oPoint(0,0,0); // This is all valid @@ -118,7 +118,7 @@ Object.defineProperty( $, "directory", { /** - * Wether Harmony is run with the interface or simply from command line + * Whether Harmony is run with the interface or simply from command line */ Object.defineProperty( $, "batchMode", { get: function(){ diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_actions.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_actions.js index ad1efc91beb..a54f74e1477 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_actions.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_actions.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -67,7 +67,7 @@ * @hideconstructor * @namespace * @example - * // To check wether an action is available, call the synthax: + * // To check whether an action is available, call the synthax: * Action.validate (, ); * * // To launch an action, call the synthax: diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_application.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_application.js index 9e9acb766c5..5809cee6942 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_application.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_application.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -409,7 +409,7 @@ $.oApp.prototype.getToolByName = function(toolName){ /** - * returns the list of stencils useable by the specified tool + * returns the list of stencils usable by the specified tool * @param {$.oTool} tool the tool object we want valid stencils for * @return {$.oStencil[]} the list of stencils compatible with the specified tool */ diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_attribute.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_attribute.js index d4d2d791ae2..fa044d5b742 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_attribute.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_attribute.js @@ -4,7 +4,7 @@ // openHarmony Library v0.01 // // -// Developped by Mathieu Chaptel, Chris Fourney... +// Developed by Mathieu Chaptel, Chris Fourney... // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -338,7 +338,7 @@ Object.defineProperty($.oAttribute.prototype, "useSeparate", { * Returns the default value of the attribute for most keywords * @name $.oAttribute#defaultValue * @type {bool} - * @todo switch the implentation to types? + * @todo switch the implementation to types? * @example * // to reset an attribute to its default value: * // (mostly used for position/angle/skew parameters of pegs and drawing nodes) @@ -449,7 +449,7 @@ $.oAttribute.prototype.getLinkedColumns = function(){ /** * Recursively sets an attribute to the same value as another. Both must have the same keyword. - * @param {bool} [duplicateColumns=false] In the case that the attribute has a column, wether to duplicate the column before linking + * @param {bool} [duplicateColumns=false] In the case that the attribute has a column, whether to duplicate the column before linking * @private */ $.oAttribute.prototype.setToAttributeValue = function(attributeToCopy, duplicateColumns){ diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_backdrop.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_backdrop.js index c98e1945394..1d359f93c4f 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_backdrop.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_backdrop.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_color.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_color.js index 7726be6cd6d..ff06688e66d 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_color.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_color.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -158,7 +158,7 @@ $.oColorValue.prototype.fromColorString = function (hexString){ /** - * Uses a color integer (used in backdrops) and parses the INT; applies the RGBA components of the INT to thos oColorValue + * Uses a color integer (used in backdrops) and parses the INT; applies the RGBA components of the INT to the oColorValue * @param { int } colorInt 24 bit-shifted integer containing RGBA values */ $.oColorValue.prototype.parseColorFromInt = function(colorInt){ diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_column.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_column.js index 1b73c7943e9..f73309049ea 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_column.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_column.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_database.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_database.js index 73964c5c38a..5440b92875b 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_database.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_database.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_dialog.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_dialog.js index a6e16ecb782..3ab78b87d6c 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_dialog.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_dialog.js @@ -5,7 +5,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -17,7 +17,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -250,7 +250,7 @@ $.oDialog.prototype.prompt = function( labelText, title, prefilledText){ /** * Prompts with a file selector window * @param {string} [text="Select a file:"] The title of the confirmation dialog. - * @param {string} [filter="*"] The filter for the file type and/or file name that can be selected. Accepts wildcard charater "*". + * @param {string} [filter="*"] The filter for the file type and/or file name that can be selected. Accepts wildcard character "*". * @param {string} [getExisting=true] Whether to select an existing file or a save location * @param {string} [acceptMultiple=false] Whether or not selecting more than one file is ok. Is ignored if getExisting is falses. * @param {string} [startDirectory] The directory showed at the opening of the dialog. @@ -327,14 +327,14 @@ $.oDialog.prototype.browseForFolder = function(text, startDirectory){ * @constructor * @classdesc An simple progress dialog to display the progress of a task. * To react to the user clicking the cancel button, connect a function to $.oProgressDialog.canceled() signal. - * When $.batchmode is true, the progress will be outputed as a "Progress : value/range" string to the Harmony stdout. + * When $.batchmode is true, the progress will be outputted as a "Progress : value/range" string to the Harmony stdout. * @param {string} [labelText] The text displayed above the progress bar. * @param {string} [range=100] The maximum value that represents a full progress bar. * @param {string} [title] The title of the dialog * @param {bool} [show=false] Whether to immediately show the dialog. * * @property {bool} wasCanceled Whether the progress bar was cancelled. - * @property {$.oSignal} canceled A Signal emited when the dialog is canceled. Can be connected to a callback. + * @property {$.oSignal} canceled A Signal emitted when the dialog is canceled. Can be connected to a callback. */ $.oProgressDialog = function( labelText, range, title, show ){ if (typeof title === 'undefined') var title = "Progress"; @@ -608,7 +608,7 @@ $.oPieMenu = function( name, widgets, show, minAngle, maxAngle, radius, position this.maxAngle = maxAngle; this.globalCenter = position; - // how wide outisde the icons is the slice drawn + // how wide outside the icons is the slice drawn this._circleMargin = 30; // set these values before calling show() to customize the menu appearance @@ -974,7 +974,7 @@ $.oPieMenu.prototype.getMenuRadius = function(){ var _minRadius = UiLoader.dpiScale(30); var _speed = 10; // the higher the value, the slower the progression - // hyperbolic tangent function to determin the radius + // hyperbolic tangent function to determine the radius var exp = Math.exp(2*itemsNumber/_speed); var _radius = ((exp-1)/(exp+1))*_maxRadius+_minRadius; @@ -1383,7 +1383,7 @@ $.oActionButton.prototype.activate = function(){ * This class is a subclass of QPushButton and all the methods from that class are available to modify this button. * @param {string} paletteName The name of the palette that contains the color * @param {string} colorName The name of the color (if more than one is present, will pick the first match) - * @param {bool} showName Wether to display the name of the color on the button + * @param {bool} showName Whether to display the name of the color on the button * @param {QWidget} parent The parent QWidget for the button. Automatically set during initialisation of the menu. * */ @@ -1437,7 +1437,7 @@ $.oColorButton.prototype.activate = function(){ * @name $.oScriptButton * @constructor * @classdescription This subclass of QPushButton provides an easy way to create a button for a widget that will launch a function from another script file.
    - * The buttons created this way automatically load the icon named after the script if it finds one named like the funtion in a script-icons folder next to the script file.
    + * The buttons created this way automatically load the icon named after the script if it finds one named like the function in a script-icons folder next to the script file.
    * It will also automatically set the callback to lanch the function from the script.
    * This class is a subclass of QPushButton and all the methods from that class are available to modify this button. * @param {string} scriptFile The path to the script file that will be launched diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_drawing.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_drawing.js index bad735f2370..6f2bc19c0c2 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_drawing.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_drawing.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -426,7 +426,7 @@ Object.defineProperty($.oDrawing.prototype, 'drawingData', { /** * Import a given file into an existing drawing. * @param {$.oFile} file The path to the file - * @param {bool} [convertToTvg=false] Wether to convert the bitmap to the tvg format (this doesn't vectorise the drawing) + * @param {bool} [convertToTvg=false] Whether to convert the bitmap to the tvg format (this doesn't vectorise the drawing) * * @return { $.oFile } the oFile object pointing to the drawing file after being it has been imported into the element folder. */ @@ -878,8 +878,8 @@ $.oArtLayer.prototype.drawCircle = function(center, radius, lineStyle, fillStyle * @param {$.oVertex[]} path an array of $.oVertex objects that describe a path. * @param {$.oLineStyle} [lineStyle] the line style to draw with. (By default, will use the current stencil selection) * @param {$.oFillStyle} [fillStyle] the fill information for the path. (By default, will use the current palette selection) - * @param {bool} [polygon] Wether bezier handles should be created for the points in the path (ignores "onCurve" properties of oVertex from path) - * @param {bool} [createUnderneath] Wether the new shape will appear on top or underneath the contents of the layer. (not working yet) + * @param {bool} [polygon] Whether bezier handles should be created for the points in the path (ignores "onCurve" properties of oVertex from path) + * @param {bool} [createUnderneath] Whether the new shape will appear on top or underneath the contents of the layer. (not working yet) */ $.oArtLayer.prototype.drawShape = function(path, lineStyle, fillStyle, polygon, createUnderneath){ if (typeof fillStyle === 'undefined') var fillStyle = new this.$.oFillStyle(); @@ -959,7 +959,7 @@ $.oArtLayer.prototype.drawContour = function(path, fillStyle){ * @param {float} width the width of the rectangle. * @param {float} height the height of the rectangle. * @param {$.oLineStyle} lineStyle a line style to use for the rectangle stroke. - * @param {$.oFillStyle} fillStyle a fill style to use for the rectange fill. + * @param {$.oFillStyle} fillStyle a fill style to use for the rectangle fill. * @returns {$.oShape} the shape containing the added stroke. */ $.oArtLayer.prototype.drawRectangle = function(x, y, width, height, lineStyle, fillStyle){ @@ -1514,7 +1514,7 @@ Object.defineProperty($.oStroke.prototype, "path", { /** - * The oVertex that are on the stroke (Bezier handles exluded.) + * The oVertex that are on the stroke (Bezier handles excluded.) * The first is repeated at the last position when the stroke is closed. * @name $.oStroke#points * @type {$.oVertex[]} @@ -1583,7 +1583,7 @@ Object.defineProperty($.oStroke.prototype, "style", { /** - * wether the stroke is a closed shape. + * whether the stroke is a closed shape. * @name $.oStroke#closed * @type {bool} */ @@ -1919,7 +1919,7 @@ $.oContour.prototype.toString = function(){ * @constructor * @classdesc * The $.oVertex class represents a single control point on a stroke. This class is used to get the index of the point in the stroke path sequence, as well as its position as a float along the stroke's length. - * The onCurve property describes wether this control point is a bezier handle or a point on the curve. + * The onCurve property describes whether this control point is a bezier handle or a point on the curve. * * @param {$.oStroke} stroke the stroke that this vertex belongs to * @param {float} x the x coordinate of the vertex, in drawing space diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_element.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_element.js index ed50d6e50b4..b64c8169ecc 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_element.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_element.js @@ -4,7 +4,7 @@ // openHarmony Library v0.01 // // -// Developped by Mathieu Chaptel, Chris Fourney... +// Developed by Mathieu Chaptel, Chris Fourney... // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_file.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_file.js index 14dafa3b638..50e4b0d4758 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_file.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_file.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -509,7 +509,7 @@ Object.defineProperty($.oFile.prototype, 'fullName', { /** - * The name of the file without extenstion. + * The name of the file without extension. * @name $.oFile#name * @type {string} */ diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_frame.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_frame.js index 37bdede02a9..e1d1dd7fad3 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_frame.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_frame.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -263,7 +263,7 @@ Object.defineProperty($.oFrame.prototype, 'duration', { return _sceneLength; } - // walk up the frames of the scene to the next keyFrame to determin duration + // walk up the frames of the scene to the next keyFrame to determine duration var _frames = this.column.frames for (var i=this.frameNumber+1; i<_sceneLength; i++){ if (_frames[i].isKeyframe) return _frames[i].frameNumber - _startFrame; @@ -426,7 +426,7 @@ Object.defineProperty($.oFrame.prototype, 'velocity', { * easeIn : a $.oPoint object representing the left handle for bezier columns, or a {point, ease} object for ease columns. * easeOut : a $.oPoint object representing the left handle for bezier columns, or a {point, ease} object for ease columns. * continuity : the type of bezier used by the point. - * constant : wether the frame is interpolated or a held value. + * constant : whether the frame is interpolated or a held value. * @name $.oFrame#ease * @type {oPoint/object} */ @@ -520,7 +520,7 @@ Object.defineProperty($.oFrame.prototype, 'easeOut', { /** - * Determines the frame's continuity setting. Can take the values "CORNER", (two independant bezier handles on each side), "SMOOTH"(handles are aligned) or "STRAIGHT" (no handles and in straight lines). + * Determines the frame's continuity setting. Can take the values "CORNER", (two independent bezier handles on each side), "SMOOTH"(handles are aligned) or "STRAIGHT" (no handles and in straight lines). * @name $.oFrame#continuity * @type {string} */ diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_list.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_list.js index 9d02b1c2aa6..63a5c0eeb82 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_list.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_list.js @@ -4,7 +4,7 @@ // openHarmony Library v0.01 // // -// Developped by Mathieu Chaptel, Chris Fourney... +// Developed by Mathieu Chaptel, Chris Fourney... // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -516,5 +516,5 @@ Object.defineProperty($.oList.prototype, 'toString', { -//Needs all filtering, limiting. mapping, pop, concat, join, ect +//Needs all filtering, limiting. mapping, pop, concat, join, etc //Speed up by finessing the way it extends and tracks the enumerable properties. \ No newline at end of file diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_math.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_math.js index c0d4ca99a74..06bfb51f306 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_math.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_math.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -193,7 +193,7 @@ $.oPoint.prototype.pointSubtract = function( sub_pt ){ /** * Subtracts the point to the coordinates of the current oPoint and returns a new oPoint with the result. * @param {$.oPoint} point The point to subtract to this point. - * @returns {$.oPoint} a new independant oPoint. + * @returns {$.oPoint} a new independent oPoint. */ $.oPoint.prototype.subtractPoint = function( point ){ var x = this.x - point.x; @@ -298,9 +298,9 @@ $.oPoint.prototype.convertToWorldspace = function(){ /** - * Linearily Interpolate between this (0.0) and the provided point (1.0) + * Linearly Interpolate between this (0.0) and the provided point (1.0) * @param {$.oPoint} point The target point at 100% - * @param {double} perc 0-1.0 value to linearily interp + * @param {double} perc 0-1.0 value to linearly interp * * @return: { $.oPoint } The interpolated value. */ @@ -410,9 +410,9 @@ $.oBox.prototype.include = function(box){ /** - * Checks wether the box contains another $.oBox. + * Checks whether the box contains another $.oBox. * @param {$.oBox} box The $.oBox to check for. - * @param {bool} [partial=false] wether to accept partially contained boxes. + * @param {bool} [partial=false] whether to accept partially contained boxes. */ $.oBox.prototype.contains = function(box, partial){ if (typeof partial === 'undefined') var partial = false; @@ -537,7 +537,7 @@ $.oMatrix.prototype.toString = function(){ * @classdesc The $.oVector is a replacement for the Vector3d objects of Harmony. * @param {float} x a x coordinate for this vector. * @param {float} y a y coordinate for this vector. - * @param {float} [z=0] a z coordinate for this vector. If ommited, will be set to 0 and vector will be 2D. + * @param {float} [z=0] a z coordinate for this vector. If omitted, will be set to 0 and vector will be 2D. */ $.oVector = function(x, y, z){ if (typeof z === "undefined" || isNaN(z)) var z = 0; diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_metadata.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_metadata.js index c19e6d12f41..29afeb522cf 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_metadata.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_metadata.js @@ -4,7 +4,7 @@ // openHarmony Library v0.01 // // -// Developped by Mathieu Chaptel, Chris Fourney... +// Developed by Mathieu Chaptel, Chris Fourney... // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_misc.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_misc.js index fec5d328164..6ef75f55604 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_misc.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_misc.js @@ -4,7 +4,7 @@ // openHarmony Library v0.01 // // -// Developped by Mathieu Chaptel, Chris Fourney... +// Developed by Mathieu Chaptel, Chris Fourney... // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -54,7 +54,7 @@ /** - * The $.oUtils helper class -- providing generic utilities. Doesn't need instanciation. + * The $.oUtils helper class -- providing generic utilities. Doesn't need instantiation. * @classdesc $.oUtils utility Class */ $.oUtils = function(){ diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_network.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_network.js index a4476d75914..2a6aa3519ac 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_network.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_network.js @@ -4,7 +4,7 @@ // openHarmony Library v0.01 // // -// Developped by Mathieu Chaptel, Chris Fourney... +// Developed by Mathieu Chaptel, Chris Fourney... // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -87,7 +87,7 @@ $.oNetwork = function( ){ * @param {function} callback_func Providing a callback function prevents blocking, and will respond on this function. The callback function is in form func( results ){} * @param {bool} use_json In the event of a JSON api, this will return an object converted from the returned JSON. * - * @return: {string/object} The resulting object/string from the query -- otherwise a bool as false when an error occured.. + * @return: {string/object} The resulting object/string from the query -- otherwise a bool as false when an error occurred.. */ $.oNetwork.prototype.webQuery = function ( address, callback_func, use_json ){ if (typeof callback_func === 'undefined') var callback_func = false; @@ -272,7 +272,7 @@ $.oNetwork.prototype.webQuery = function ( address, callback_func, use_json ){ * @param {function} path The local file path to save the download. * @param {bool} replace Replace the file if it exists. * - * @return: {string/object} The resulting object/string from the query -- otherwise a bool as false when an error occured.. + * @return: {string/object} The resulting object/string from the query -- otherwise a bool as false when an error occurred.. */ $.oNetwork.prototype.downloadSingle = function ( address, path, replace ){ if (typeof replace === 'undefined') var replace = false; diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_node.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_node.js index 5590d7b7e94..deb18543578 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_node.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_node.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -562,7 +562,7 @@ Object.defineProperty($.oNode.prototype, 'height', { /** - * The list of oNodeLinks objects descibing the connections to the inport of this node, in order of inport. + * The list of oNodeLinks objects describing the connections to the inport of this node, in order of inport. * @name $.oNode#inLinks * @readonly * @deprecated returns $.oNodeLink instances but $.oLink is preferred. Use oNode.getInLinks() instead. @@ -658,7 +658,7 @@ Object.defineProperty($.oNode.prototype, 'outPorts', { /** - * The list of oNodeLinks objects descibing the connections to the outports of this node, in order of outport. + * The list of oNodeLinks objects describing the connections to the outports of this node, in order of outport. * @name $.oNode#outLinks * @readonly * @type {$.oNodeLink[]} @@ -1666,7 +1666,7 @@ $.oNode.prototype.refreshAttributes = function( ){ * It represents peg nodes in the scene. * @constructor * @augments $.oNode - * @classdesc Peg Moudle Class + * @classdesc Peg Module Class * @param {string} path Path to the node in the network. * @param {oScene} oSceneObject Access to the oScene object of the DOM. */ @@ -1886,7 +1886,7 @@ $.oDrawingNode.prototype.getDrawingAtFrame = function(frameNumber){ /** - * Gets the list of palettes containing colors used by a drawing node. This only gets palettes with the first occurence of the colors. + * Gets the list of palettes containing colors used by a drawing node. This only gets palettes with the first occurrence of the colors. * @return {$.oPalette[]} The palettes that contain the color IDs used by the drawings of the node. */ $.oDrawingNode.prototype.getUsedPalettes = function(){ @@ -1968,7 +1968,7 @@ $.oDrawingNode.prototype.unlinkPalette = function(oPaletteObject){ * Duplicates a node by creating an independent copy. * @param {string} [newName] The new name for the duplicated node. * @param {oPoint} [newPosition] The new position for the duplicated node. - * @param {bool} [duplicateElement] Wether to also duplicate the element. + * @param {bool} [duplicateElement] Whether to also duplicate the element. */ $.oDrawingNode.prototype.duplicate = function(newName, newPosition, duplicateElement){ if (typeof newPosition === 'undefined') var newPosition = this.nodePosition; @@ -2464,7 +2464,7 @@ $.oGroupNode.prototype.getNodeByName = function(name){ * Returns all the nodes of a certain type in the group. * Pass a value to recurse to look into the groups as well. * @param {string} typeName The type of the nodes. - * @param {bool} recurse Wether to look inside the groups. + * @param {bool} recurse Whether to look inside the groups. * * @return {$.oNode[]} The nodes found. */ @@ -2626,7 +2626,7 @@ $.oGroupNode.prototype.orderNodeView = function(recurse){ * * peg.linkOutNode(drawingNode); * - * //through all this we didn't specify nodePosition parameters so we'll sort evertything at once + * //through all this we didn't specify nodePosition parameters so we'll sort everything at once * * sceneRoot.orderNodeView(); * @@ -3333,7 +3333,7 @@ $.oGroupNode.prototype.importImageAsTVG = function(path, alignment, nodePosition * imports an image sequence as a node into the current group. * @param {$.oFile[]} imagePaths a list of paths to the images to import (can pass a list of strings or $.oFile) * @param {number} [exposureLength=1] the number of frames each drawing should be exposed at. If set to 0/false, each drawing will use the numbering suffix of the file to set its frame. - * @param {boolean} [convertToTvg=false] wether to convert the files to tvg during import + * @param {boolean} [convertToTvg=false] whether to convert the files to tvg during import * @param {string} [alignment="ASIS"] the alignment to apply to the node * @param {$.oPoint} [nodePosition] the position of the node in the nodeview * @@ -3346,7 +3346,7 @@ $.oGroupNode.prototype.importImageSequence = function(imagePaths, exposureLength if (typeof extendScene === 'undefined') var extendScene = false; - // match anything but capture trailing numbers and separates punctuation preceeding it + // match anything but capture trailing numbers and separates punctuation preceding it var numberingRe = /(.*?)([\W_]+)?(\d*)$/i; // sanitize imagePaths diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_nodeLink.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_nodeLink.js index 279a8716911..07a4d147da3 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_nodeLink.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_nodeLink.js @@ -4,7 +4,7 @@ // openHarmony Library v0.01 // // -// Developped by Mathieu Chaptel, Chris Fourney... +// Developed by Mathieu Chaptel, Chris Fourney... // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -174,7 +174,7 @@ Object.defineProperty($.oNodeLink.prototype, 'outNode', { return; } - this.apply(); // do we really want to apply everytime we set? + this.apply(); // do we really want to apply every time we set? } }); @@ -198,7 +198,7 @@ Object.defineProperty($.oNodeLink.prototype, 'inNode', { return; } - this.apply(); // do we really want to apply everytime we set? + this.apply(); // do we really want to apply every time we set? } }); @@ -222,7 +222,7 @@ Object.defineProperty($.oNodeLink.prototype, 'outPort', { return; } - this.apply(); // do we really want to apply everytime we set? + this.apply(); // do we really want to apply every time we set? } }); @@ -256,7 +256,7 @@ Object.defineProperty($.oNodeLink.prototype, 'inPort', { return; } - this.apply(); // do we really want to apply everytime we set? + this.apply(); // do we really want to apply every time we set? } }); @@ -983,7 +983,7 @@ $.oNodeLink.prototype.validate = function ( ) { * @return {bool} Whether the connection is a valid connection that exists currently in the node system. */ $.oNodeLink.prototype.validateUpwards = function( inport, outportProvided ) { - //IN THE EVENT OUTNODE WASNT PROVIDED. + //IN THE EVENT OUTNODE WASN'T PROVIDED. this.path = this.findInputPath( this._inNode, inport, [] ); if( !this.path || this.path.length == 0 ){ return false; @@ -1173,7 +1173,7 @@ Object.defineProperty($.oLink.prototype, 'outPort', { /** - * The index of the link comming out of the out-port. + * The index of the link coming out of the out-port. *
    In the event this value wasn't known by the link object but the link is actually connected, the correct value will be found. * @name $.oLink#outLink * @readonly @@ -1323,7 +1323,7 @@ $.oLink.prototype.getValidLink = function(createOutPorts, createInPorts){ /** - * Attemps to connect a link. Will guess the ports if not provided. + * Attempts to connect a link. Will guess the ports if not provided. * @return {bool} */ $.oLink.prototype.connect = function(){ @@ -1623,11 +1623,11 @@ $.oLinkPath.prototype.findExistingPath = function(){ /** - * Gets a link object from two nodes that can be succesfully connected. Provide port numbers if there are specific requirements to match. If a link already exists, it will be returned. + * Gets a link object from two nodes that can be successfully connected. Provide port numbers if there are specific requirements to match. If a link already exists, it will be returned. * @param {$.oNode} start The node from which the link originates. * @param {$.oNode} end The node at which the link ends. - * @param {int} [outPort] A prefered out-port for the link to use. - * @param {int} [inPort] A prefered in-port for the link to use. + * @param {int} [outPort] A preferred out-port for the link to use. + * @param {int} [inPort] A preferred in-port for the link to use. * * @return {$.oLink} the valid $.oLink object. Returns null if no such link could be created (for example if the node's in-port is already linked) */ diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony_tools.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony_tools.js index 57d4a63e961..9014929fc48 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony_tools.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony_tools.js @@ -4,7 +4,7 @@ // openHarmony Library v0.01 // // -// Developped by Mathieu Chaptel, ... +// Developed by Mathieu Chaptel, ... // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -212,7 +212,7 @@ function openHarmony_toolInstaller(){ //---------------------------------------------- - //-- GET THE FILE CONTENTS IN A DIRCTORY ON GIT + //-- GET THE FILE CONTENTS IN A DIRECTORY ON GIT this.recurse_files = function( contents, arr_files ){ with( context.$.global ){ try{ @@ -501,7 +501,7 @@ function openHarmony_toolInstaller(){ var download_item = item["download_url"]; var query = $.network.webQuery( download_item, false, false ); if( query ){ - //INSTALL TYPES ARE script, package, ect. + //INSTALL TYPES ARE script, package, etc. if( install_types[ m.install_cache[ item["url"] ] ] ){ m.installLabel.text = install_types[ m.install_cache[ item["url"] ] ]; diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/package.json b/openpype/hosts/harmony/vendor/OpenHarmony/package.json index c62ecbc9d80..7a535cdcf6f 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/package.json +++ b/openpype/hosts/harmony/vendor/OpenHarmony/package.json @@ -1,7 +1,7 @@ { "name": "openharmony", "version": "0.0.1", - "description": "An Open Source Imlementation of a Document Object Model for the Toonboom Harmony scripting interface", + "description": "An Open Source Implementation of a Document Object Model for the Toonboom Harmony scripting interface", "main": "openHarmony.js", "scripts": { "test": "$", diff --git a/openpype/hosts/hiero/api/__init__.py b/openpype/hosts/hiero/api/__init__.py index 1fa40c9f745..b95c0fe1d73 100644 --- a/openpype/hosts/hiero/api/__init__.py +++ b/openpype/hosts/hiero/api/__init__.py @@ -108,7 +108,7 @@ "apply_colorspace_project", "apply_colorspace_clips", "get_sequence_pattern_and_padding", - # depricated + # deprecated "get_track_item_pype_tag", "set_track_item_pype_tag", "get_track_item_pype_data", diff --git a/openpype/hosts/hiero/api/pipeline.py b/openpype/hosts/hiero/api/pipeline.py index 4ab73e7d194..d88aeac8100 100644 --- a/openpype/hosts/hiero/api/pipeline.py +++ b/openpype/hosts/hiero/api/pipeline.py @@ -193,8 +193,8 @@ def data_to_container(item, data): return # convert the data to list and validate them for _, obj_data in _data.items(): - cotnainer = data_to_container(item, obj_data) - return_list.append(cotnainer) + container = data_to_container(item, obj_data) + return_list.append(container) return return_list else: _data = lib.get_trackitem_openpype_data(item) diff --git a/openpype/hosts/hiero/api/plugin.py b/openpype/hosts/hiero/api/plugin.py index 5ca901caaa2..a3f8a6c5243 100644 --- a/openpype/hosts/hiero/api/plugin.py +++ b/openpype/hosts/hiero/api/plugin.py @@ -411,7 +411,7 @@ def __init__(self, cls, context, **options): self.with_handles = options.get("handles") or bool( options.get("handles") is True) # try to get value from options or evaluate key value for `load_how` - self.sequencial_load = options.get("sequencially") or bool( + self.sequencial_load = options.get("sequentially") or bool( "Sequentially in order" in options.get("load_how", "")) # try to get value from options or evaluate key value for `load_to` self.new_sequence = options.get("newSequence") or bool( @@ -836,7 +836,7 @@ def _convert_to_tag_data(self): # increasing steps by index of rename iteration self.count_steps *= self.rename_index - hierarchy_formating_data = {} + hierarchy_formatting_data = {} hierarchy_data = deepcopy(self.hierarchy_data) _data = self.track_item_default_data.copy() if self.ui_inputs: @@ -871,13 +871,13 @@ def _convert_to_tag_data(self): # fill up pythonic expresisons in hierarchy data for k, _v in hierarchy_data.items(): - hierarchy_formating_data[k] = _v["value"].format(**_data) + hierarchy_formatting_data[k] = _v["value"].format(**_data) else: # if no gui mode then just pass default data - hierarchy_formating_data = hierarchy_data + hierarchy_formatting_data = hierarchy_data tag_hierarchy_data = self._solve_tag_hierarchy_data( - hierarchy_formating_data + hierarchy_formatting_data ) tag_hierarchy_data.update({"heroTrack": True}) @@ -905,20 +905,20 @@ def _convert_to_tag_data(self): # add data to return data dict self.tag_data.update(tag_hierarchy_data) - def _solve_tag_hierarchy_data(self, hierarchy_formating_data): + def _solve_tag_hierarchy_data(self, hierarchy_formatting_data): """ Solve tag data from hierarchy data and templates. """ # fill up clip name and hierarchy keys - hierarchy_filled = self.hierarchy.format(**hierarchy_formating_data) - clip_name_filled = self.clip_name.format(**hierarchy_formating_data) + hierarchy_filled = self.hierarchy.format(**hierarchy_formatting_data) + clip_name_filled = self.clip_name.format(**hierarchy_formatting_data) # remove shot from hierarchy data: is not needed anymore - hierarchy_formating_data.pop("shot") + hierarchy_formatting_data.pop("shot") return { "newClipName": clip_name_filled, "hierarchy": hierarchy_filled, "parents": self.parents, - "hierarchyData": hierarchy_formating_data, + "hierarchyData": hierarchy_formatting_data, "subset": self.subset, "family": self.subset_family, "families": [self.data["family"]] @@ -934,16 +934,16 @@ def _convert_to_entity(self, type, template): ) # first collect formatting data to use for formatting template - formating_data = {} + formatting_data = {} for _k, _v in self.hierarchy_data.items(): value = _v["value"].format( **self.track_item_default_data) - formating_data[_k] = value + formatting_data[_k] = value return { "entity_type": entity_type, "entity_name": template.format( - **formating_data + **formatting_data ) } diff --git a/openpype/hosts/houdini/api/plugin.py b/openpype/hosts/houdini/api/plugin.py index f0985973a61..340a7f07704 100644 --- a/openpype/hosts/houdini/api/plugin.py +++ b/openpype/hosts/houdini/api/plugin.py @@ -60,7 +60,7 @@ def process(self): def process(self): instance = super(CreateEpicNode, self, process() - # Set paramaters for Alembic node + # Set parameters for Alembic node instance.setParms( {"sop_path": "$HIP/%s.abc" % self.nodes[0]} ) diff --git a/openpype/hosts/houdini/api/shelves.py b/openpype/hosts/houdini/api/shelves.py index ebd668e9e48..6e0f367f624 100644 --- a/openpype/hosts/houdini/api/shelves.py +++ b/openpype/hosts/houdini/api/shelves.py @@ -69,7 +69,7 @@ def generate_shelves(): mandatory_attributes = {'label', 'script'} for tool_definition in shelf_definition.get('tools_list'): - # We verify that the name and script attibutes of the tool + # We verify that the name and script attributes of the tool # are set if not all( tool_definition[key] for key in mandatory_attributes diff --git a/openpype/hosts/houdini/plugins/create/convert_legacy.py b/openpype/hosts/houdini/plugins/create/convert_legacy.py index 4b8041b4f55..e549c9dc26b 100644 --- a/openpype/hosts/houdini/plugins/create/convert_legacy.py +++ b/openpype/hosts/houdini/plugins/create/convert_legacy.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -"""Convertor for legacy Houdini subsets.""" +"""Converter for legacy Houdini subsets.""" from openpype.pipeline.create.creator_plugins import SubsetConvertorPlugin from openpype.hosts.houdini.api.lib import imprint @@ -7,7 +7,7 @@ class HoudiniLegacyConvertor(SubsetConvertorPlugin): """Find and convert any legacy subsets in the scene. - This Convertor will find all legacy subsets in the scene and will + This Converter will find all legacy subsets in the scene and will transform them to the current system. Since the old subsets doesn't retain any information about their original creators, the only mapping we can do is based on their families. diff --git a/openpype/hosts/maya/api/commands.py b/openpype/hosts/maya/api/commands.py index 018340d86c7..3e31875fd8c 100644 --- a/openpype/hosts/maya/api/commands.py +++ b/openpype/hosts/maya/api/commands.py @@ -69,7 +69,7 @@ def _resolution_from_document(doc): resolution_width = doc["data"].get("resolution_width") resolution_height = doc["data"].get("resolution_height") - # Make sure both width and heigh are set + # Make sure both width and height are set if resolution_width is None or resolution_height is None: cmds.warning( "No resolution information found for \"{}\"".format(doc["name"]) diff --git a/openpype/hosts/maya/api/lib_renderproducts.py b/openpype/hosts/maya/api/lib_renderproducts.py index a54256c59a1..324496c9645 100644 --- a/openpype/hosts/maya/api/lib_renderproducts.py +++ b/openpype/hosts/maya/api/lib_renderproducts.py @@ -339,7 +339,7 @@ def extract_separator(file_prefix): aov_tokens = ["", ""] def match_last(tokens, text): - """regex match the last occurence from a list of tokens""" + """regex match the last occurrence from a list of tokens""" pattern = "(?:.*)({})".format("|".join(tokens)) return re.search(pattern, text, re.IGNORECASE) @@ -1051,7 +1051,7 @@ class RenderProductsRedshift(ARenderProducts): def get_files(self, product): # When outputting AOVs we need to replace Redshift specific AOV tokens # with Maya render tokens for generating file sequences. We validate to - # a specific AOV fileprefix so we only need to accout for one + # a specific AOV fileprefix so we only need to account for one # replacement. if not product.multipart and product.driver: file_prefix = self._get_attr(product.driver + ".filePrefix") diff --git a/openpype/hosts/maya/api/workfile_template_builder.py b/openpype/hosts/maya/api/workfile_template_builder.py index 90ab6e21e04..4bee0664ef7 100644 --- a/openpype/hosts/maya/api/workfile_template_builder.py +++ b/openpype/hosts/maya/api/workfile_template_builder.py @@ -33,7 +33,7 @@ def import_template(self, path): get_template_preset implementation) Returns: - bool: Wether the template was succesfully imported or not + bool: Whether the template was successfully imported or not """ if cmds.objExists(PLACEHOLDER_SET): @@ -116,7 +116,7 @@ def _create_placeholder_name(self, placeholder_data): placeholder_name_parts = placeholder_data["builder_type"].split("_") pos = 1 - # add famlily in any + # add family in any placeholder_family = placeholder_data["family"] if placeholder_family: placeholder_name_parts.insert(pos, placeholder_family) diff --git a/openpype/hosts/maya/plugins/load/actions.py b/openpype/hosts/maya/plugins/load/actions.py index 2574624dbb8..ba69debc405 100644 --- a/openpype/hosts/maya/plugins/load/actions.py +++ b/openpype/hosts/maya/plugins/load/actions.py @@ -118,7 +118,7 @@ class ImportMayaLoader(load.LoaderPlugin): "clean_import", label="Clean import", default=False, - help="Should all occurences of cbId be purged?" + help="Should all occurrences of cbId be purged?" ) ] diff --git a/openpype/hosts/maya/plugins/load/load_arnold_standin.py b/openpype/hosts/maya/plugins/load/load_arnold_standin.py index 11a2bd19669..21b2246f6ca 100644 --- a/openpype/hosts/maya/plugins/load/load_arnold_standin.py +++ b/openpype/hosts/maya/plugins/load/load_arnold_standin.py @@ -180,7 +180,7 @@ def update(self, container, representation): proxy_basename, proxy_path = self._get_proxy_path(path) # Whether there is proxy or so, we still update the string operator. - # If no proxy exists, the string operator wont replace anything. + # If no proxy exists, the string operator won't replace anything. cmds.setAttr( string_replace_operator + ".match", "resources/" + proxy_basename, diff --git a/openpype/hosts/maya/plugins/publish/collect_multiverse_look.py b/openpype/hosts/maya/plugins/publish/collect_multiverse_look.py index a7cb14855b2..33fc7a025f8 100644 --- a/openpype/hosts/maya/plugins/publish/collect_multiverse_look.py +++ b/openpype/hosts/maya/plugins/publish/collect_multiverse_look.py @@ -255,7 +255,7 @@ class CollectMultiverseLookData(pyblish.api.InstancePlugin): Searches through the overrides finding all material overrides. From there it extracts the shading group and then finds all texture files in the shading group network. It also checks for mipmap versions of texture files - and adds them to the resouces to get published. + and adds them to the resources to get published. """ diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 447c9a615cc..0572073d7d7 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -95,7 +95,7 @@ def maketx(source, destination, args, logger): try: out = run_subprocess(subprocess_args) except Exception: - logger.error("Maketx converion failed", exc_info=True) + logger.error("Maketx conversion failed", exc_info=True) raise return out diff --git a/openpype/hosts/maya/plugins/publish/extract_multiverse_usd_over.py b/openpype/hosts/maya/plugins/publish/extract_multiverse_usd_over.py index 0628623e887..cf610ac6b42 100644 --- a/openpype/hosts/maya/plugins/publish/extract_multiverse_usd_over.py +++ b/openpype/hosts/maya/plugins/publish/extract_multiverse_usd_over.py @@ -102,7 +102,7 @@ def process(self, instance): long=True) self.log.info("Collected object {}".format(members)) - # TODO: Deal with asset, composition, overide with options. + # TODO: Deal with asset, composition, override with options. import multiverse time_opts = None diff --git a/openpype/hosts/maya/plugins/publish/reset_xgen_attributes.py b/openpype/hosts/maya/plugins/publish/reset_xgen_attributes.py index b90885663c3..d8e8554b686 100644 --- a/openpype/hosts/maya/plugins/publish/reset_xgen_attributes.py +++ b/openpype/hosts/maya/plugins/publish/reset_xgen_attributes.py @@ -30,7 +30,7 @@ def process(self, instance): cmds.setAttr(palette + ".xgExportAsDelta", True) # Need to save the scene, cause the attribute changes above does not - # mark the scene as modified so user can exit without commiting the + # mark the scene as modified so user can exit without committing the # changes. self.log.info("Saving changes.") cmds.file(save=True) diff --git a/openpype/hosts/maya/plugins/publish/validate_camera_attributes.py b/openpype/hosts/maya/plugins/publish/validate_camera_attributes.py index bd1529e2527..13ea53a357e 100644 --- a/openpype/hosts/maya/plugins/publish/validate_camera_attributes.py +++ b/openpype/hosts/maya/plugins/publish/validate_camera_attributes.py @@ -8,7 +8,7 @@ class ValidateCameraAttributes(pyblish.api.InstancePlugin): """Validates Camera has no invalid attribute keys or values. - The Alembic file format does not a specifc subset of attributes as such + The Alembic file format does not a specific subset of attributes as such we validate that no values are set there as the output will not match the current scene. For example the preScale, film offsets and film roll. diff --git a/openpype/hosts/maya/plugins/publish/validate_maya_units.py b/openpype/hosts/maya/plugins/publish/validate_maya_units.py index 357dde692c3..011df0846c7 100644 --- a/openpype/hosts/maya/plugins/publish/validate_maya_units.py +++ b/openpype/hosts/maya/plugins/publish/validate_maya_units.py @@ -34,7 +34,7 @@ def process(self, context): fps = context.data.get('fps') - # TODO repace query with using 'context.data["assetEntity"]' + # TODO replace query with using 'context.data["assetEntity"]' asset_doc = get_current_project_asset() asset_fps = mayalib.convert_to_maya_fps(asset_doc["data"]["fps"]) @@ -86,7 +86,7 @@ def repair(cls, context): cls.log.debug(current_linear) cls.log.info("Setting time unit to match project") - # TODO repace query with using 'context.data["assetEntity"]' + # TODO replace query with using 'context.data["assetEntity"]' asset_doc = get_current_project_asset() asset_fps = asset_doc["data"]["fps"] mayalib.set_scene_fps(asset_fps) diff --git a/openpype/hosts/maya/plugins/publish/validate_mvlook_contents.py b/openpype/hosts/maya/plugins/publish/validate_mvlook_contents.py index e583c1edbab..36971bb1449 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mvlook_contents.py +++ b/openpype/hosts/maya/plugins/publish/validate_mvlook_contents.py @@ -42,7 +42,7 @@ def process(self, instance): resources = instance.data.get("resources", []) for resource in resources: files = resource["files"] - self.log.debug("Resouce '{}', files: [{}]".format(resource, files)) + self.log.debug("Resource '{}', files: [{}]".format(resource, files)) node = resource["node"] if len(files) == 0: self.log.error("File node '{}' uses no or non-existing " diff --git a/openpype/hosts/maya/plugins/publish/validate_renderlayer_aovs.py b/openpype/hosts/maya/plugins/publish/validate_renderlayer_aovs.py index 6b6fb03eec7..7919a6eaa10 100644 --- a/openpype/hosts/maya/plugins/publish/validate_renderlayer_aovs.py +++ b/openpype/hosts/maya/plugins/publish/validate_renderlayer_aovs.py @@ -37,8 +37,8 @@ def get_invalid(self, instance): project_name = legacy_io.active_project() asset_doc = instance.data["assetEntity"] - render_passses = instance.data.get("renderPasses", []) - for render_pass in render_passses: + render_passes = instance.data.get("renderPasses", []) + for render_pass in render_passes: is_valid = self.validate_subset_registered( project_name, asset_doc, render_pass ) diff --git a/openpype/hosts/maya/plugins/publish/validate_transform_naming_suffix.py b/openpype/hosts/maya/plugins/publish/validate_transform_naming_suffix.py index 0147aa8a52a..b2a83a80fb0 100644 --- a/openpype/hosts/maya/plugins/publish/validate_transform_naming_suffix.py +++ b/openpype/hosts/maya/plugins/publish/validate_transform_naming_suffix.py @@ -21,7 +21,7 @@ class ValidateTransformNamingSuffix(pyblish.api.InstancePlugin): - nurbsSurface: _NRB - locator: _LOC - null/group: _GRP - Suffices can also be overriden by project settings. + Suffices can also be overridden by project settings. .. warning:: This grabs the first child shape as a reference and doesn't use the diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index 2a14096f0eb..157a02b9aaa 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -148,7 +148,7 @@ def get_main_window(): def set_node_data(node, knobname, data): """Write data to node invisible knob - Will create new in case it doesnt exists + Will create new in case it doesn't exists or update the one already created. Args: @@ -506,7 +506,7 @@ def get_avalon_knob_data(node, prefix="avalon:", create=True): try: # check if data available on the node test = node[AVALON_DATA_GROUP].value() - log.debug("Only testing if data avalable: `{}`".format(test)) + log.debug("Only testing if data available: `{}`".format(test)) except NameError as e: # if it doesn't then create it log.debug("Creating avalon knob: `{}`".format(e)) @@ -908,11 +908,11 @@ def get_view_process_node(): continue if not ipn_node: - # in case a Viewer node is transfered from + # in case a Viewer node is transferred from # different workfile with old values raise NameError(( "Input process node name '{}' set in " - "Viewer '{}' is does't exists in nodes" + "Viewer '{}' is doesn't exists in nodes" ).format(ipn, v_.name())) ipn_node.setSelected(True) @@ -1662,7 +1662,7 @@ def create_write_node_legacy( tile_color = _data.get("tile_color", "0xff0000ff") GN["tile_color"].setValue(tile_color) - # overrie knob values from settings + # override knob values from settings for knob in knob_overrides: knob_type = knob["type"] knob_name = knob["name"] @@ -2117,7 +2117,7 @@ def set_writes_colorspace(self): write_node[knob["name"]].setValue(value) except TypeError: log.warning( - "Legacy workflow didnt work, switching to current") + "Legacy workflow didn't work, switching to current") set_node_knobs_from_settings( write_node, nuke_imageio_writes["knobs"]) @@ -2543,7 +2543,7 @@ def reset_selection(): def select_nodes(nodes): - """Selects all inputed nodes + """Selects all inputted nodes Arguments: nodes (list): nuke nodes to be selected @@ -2560,7 +2560,7 @@ def launch_workfiles_app(): Trigger to show workfiles tool on application launch. Can be executed only once all other calls are ignored. - Workfiles tool show is deffered after application initialization using + Workfiles tool show is deferred after application initialization using QTimer. """ @@ -2581,7 +2581,7 @@ def launch_workfiles_app(): # Show workfiles tool using timer # - this will be probably triggered during initialization in that case # the application is not be able to show uis so it must be - # deffered using timer + # deferred using timer # - timer should be processed when initialization ends # When applications starts to process events. timer = QtCore.QTimer() diff --git a/openpype/hosts/nuke/api/plugin.py b/openpype/hosts/nuke/api/plugin.py index aec87be5ab6..cc3af2a38f8 100644 --- a/openpype/hosts/nuke/api/plugin.py +++ b/openpype/hosts/nuke/api/plugin.py @@ -594,7 +594,7 @@ def get_representation_data( Defaults to None. range (bool, optional): flag for adding ranges. Defaults to False. - custom_tags (list[str], optional): user inputed custom tags. + custom_tags (list[str], optional): user inputted custom tags. Defaults to None. """ add_tags = tags or [] @@ -1110,7 +1110,7 @@ def process(self): def is_legacy(self): """Check if it needs to run legacy code - In case where `type` key is missing in singe + In case where `type` key is missing in single knob it is legacy project anatomy. Returns: diff --git a/openpype/hosts/nuke/api/utils.py b/openpype/hosts/nuke/api/utils.py index 6bcb752dd1d..2b3c35c23ad 100644 --- a/openpype/hosts/nuke/api/utils.py +++ b/openpype/hosts/nuke/api/utils.py @@ -87,7 +87,7 @@ def bake_gizmos_recursively(in_group=None): def colorspace_exists_on_node(node, colorspace_name): """ Check if colorspace exists on node - Look through all options in the colorpsace knob, and see if we have an + Look through all options in the colorspace knob, and see if we have an exact match to one of the items. Args: diff --git a/openpype/hosts/nuke/api/workfile_template_builder.py b/openpype/hosts/nuke/api/workfile_template_builder.py index fb0afb3d553..cf85a5ea056 100644 --- a/openpype/hosts/nuke/api/workfile_template_builder.py +++ b/openpype/hosts/nuke/api/workfile_template_builder.py @@ -42,7 +42,7 @@ def import_template(self, path): get_template_preset implementation) Returns: - bool: Wether the template was successfully imported or not + bool: Whether the template was successfully imported or not """ # TODO check if the template is already imported @@ -222,7 +222,7 @@ def cleanup_placeholder(self, placeholder, failed): self._imprint_siblings(placeholder) if placeholder.data["nb_children"] == 0: - # save initial nodes postions and dimensions, update them + # save initial nodes positions and dimensions, update them # and set inputs and outputs of loaded nodes self._imprint_inits() @@ -231,7 +231,7 @@ def cleanup_placeholder(self, placeholder, failed): elif placeholder.data["siblings"]: # create copies of placeholder siblings for the new loaded nodes, - # set their inputs and outpus and update all nodes positions and + # set their inputs and outputs and update all nodes positions and # dimensions and siblings names siblings = get_nodes_by_names(placeholder.data["siblings"]) @@ -632,7 +632,7 @@ def cleanup_placeholder(self, placeholder, failed): self._imprint_siblings(placeholder) if placeholder.data["nb_children"] == 0: - # save initial nodes postions and dimensions, update them + # save initial nodes positions and dimensions, update them # and set inputs and outputs of created nodes self._imprint_inits() @@ -641,7 +641,7 @@ def cleanup_placeholder(self, placeholder, failed): elif placeholder.data["siblings"]: # create copies of placeholder siblings for the new created nodes, - # set their inputs and outpus and update all nodes positions and + # set their inputs and outputs and update all nodes positions and # dimensions and siblings names siblings = get_nodes_by_names(placeholder.data["siblings"]) diff --git a/openpype/hosts/nuke/plugins/create/convert_legacy.py b/openpype/hosts/nuke/plugins/create/convert_legacy.py index d7341c625f4..c143e4cb278 100644 --- a/openpype/hosts/nuke/plugins/create/convert_legacy.py +++ b/openpype/hosts/nuke/plugins/create/convert_legacy.py @@ -39,7 +39,7 @@ def find_instances(self): break if legacy_found: - # if not item do not add legacy instance convertor + # if not item do not add legacy instance converter self.add_convertor_item("Convert legacy instances") def convert(self): diff --git a/openpype/hosts/nuke/plugins/create/create_source.py b/openpype/hosts/nuke/plugins/create/create_source.py index 06cf4e6cbf5..57504b5d53f 100644 --- a/openpype/hosts/nuke/plugins/create/create_source.py +++ b/openpype/hosts/nuke/plugins/create/create_source.py @@ -85,4 +85,4 @@ def set_selected_nodes(self, pre_create_data): raise NukeCreatorError("Creator error: No active selection") else: NukeCreatorError( - "Creator error: only supprted with active selection") + "Creator error: only supported with active selection") diff --git a/openpype/hosts/nuke/plugins/publish/collect_writes.py b/openpype/hosts/nuke/plugins/publish/collect_writes.py index 0008a756bc4..536a0698f3b 100644 --- a/openpype/hosts/nuke/plugins/publish/collect_writes.py +++ b/openpype/hosts/nuke/plugins/publish/collect_writes.py @@ -189,7 +189,7 @@ def process(self, instance): }) # make sure rendered sequence on farm will - # be used for exctract review + # be used for extract review if not instance.data["review"]: instance.data["useSequenceForReview"] = False diff --git a/openpype/hosts/nuke/plugins/publish/validate_backdrop.py b/openpype/hosts/nuke/plugins/publish/validate_backdrop.py index 208d4a24985..5f4a5c3ab0c 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_backdrop.py +++ b/openpype/hosts/nuke/plugins/publish/validate_backdrop.py @@ -48,7 +48,7 @@ def process(self, context, plugin): class ValidateBackdrop(pyblish.api.InstancePlugin): """ Validate amount of nodes on backdrop node in case user - forgoten to add nodes above the publishing backdrop node. + forgotten to add nodes above the publishing backdrop node. """ order = pyblish.api.ValidatorOrder diff --git a/openpype/hosts/photoshop/api/extension/host/index.jsx b/openpype/hosts/photoshop/api/extension/host/index.jsx index 2acec1ebc13..e2711fb960e 100644 --- a/openpype/hosts/photoshop/api/extension/host/index.jsx +++ b/openpype/hosts/photoshop/api/extension/host/index.jsx @@ -199,7 +199,7 @@ function getActiveDocumentName(){ function getActiveDocumentFullName(){ /** * Returns file name of active document with file path. - * activeDocument.fullName returns path in URI (eg /c/.. insted of c:/) + * activeDocument.fullName returns path in URI (eg /c/.. instead of c:/) * */ if (documents.length == 0){ return null; @@ -225,7 +225,7 @@ function getSelectedLayers(doc) { * Returns json representation of currently selected layers. * Works in three steps - 1) creates new group with selected layers * 2) traverses this group - * 3) deletes newly created group, not neede + * 3) deletes newly created group, not needed * Bit weird, but Adobe.. **/ if (doc == null){ @@ -284,7 +284,7 @@ function selectLayers(selectedLayers){ existing_ids.push(existing_layers[y]["id"]); } for (var i = 0; i < selectedLayers.length; i++) { - // a check to see if the id stil exists + // a check to see if the id still exists var id = selectedLayers[i]; if(existing_ids.toString().indexOf(id)>=0){ layers[i] = charIDToTypeID( "Lyr " ); diff --git a/openpype/hosts/resolve/api/lib.py b/openpype/hosts/resolve/api/lib.py index f41eb36cafe..b3ad20df399 100644 --- a/openpype/hosts/resolve/api/lib.py +++ b/openpype/hosts/resolve/api/lib.py @@ -250,7 +250,7 @@ def create_timeline_item(media_pool_item: object, media_pool_item, timeline) assert output_timeline_item, AssertionError( - "Track Item with name `{}` doesnt exist on the timeline: `{}`".format( + "Track Item with name `{}` doesn't exist on the timeline: `{}`".format( clip_name, timeline.GetName() )) return output_timeline_item @@ -571,7 +571,7 @@ def create_compound_clip(clip_data, name, folder): # Set current folder to input media_pool_folder: mp.SetCurrentFolder(folder) - # check if clip doesnt exist already: + # check if clip doesn't exist already: clips = folder.GetClipList() cct = next((c for c in clips if c.GetName() in name), None) @@ -582,7 +582,7 @@ def create_compound_clip(clip_data, name, folder): # Create empty timeline in current folder and give name: cct = mp.CreateEmptyTimeline(name) - # check if clip doesnt exist already: + # check if clip doesn't exist already: clips = folder.GetClipList() cct = next((c for c in clips if c.GetName() in name), None) diff --git a/openpype/hosts/resolve/api/menu_style.qss b/openpype/hosts/resolve/api/menu_style.qss index d2d3d1ed37a..3d51c7139fa 100644 --- a/openpype/hosts/resolve/api/menu_style.qss +++ b/openpype/hosts/resolve/api/menu_style.qss @@ -61,7 +61,7 @@ QVBoxLayout { background-color: #282828; } -#Devider { +#Divider { border: 1px solid #090909; background-color: #585858; } diff --git a/openpype/hosts/resolve/api/plugin.py b/openpype/hosts/resolve/api/plugin.py index 77e30149fd6..4fa73e82cd3 100644 --- a/openpype/hosts/resolve/api/plugin.py +++ b/openpype/hosts/resolve/api/plugin.py @@ -715,7 +715,7 @@ def _convert_to_tag_data(self): # increasing steps by index of rename iteration self.count_steps *= self.rename_index - hierarchy_formating_data = dict() + hierarchy_formatting_data = dict() _data = self.timeline_item_default_data.copy() if self.ui_inputs: # adding tag metadata from ui @@ -749,13 +749,13 @@ def _convert_to_tag_data(self): # fill up pythonic expresisons in hierarchy data for k, _v in self.hierarchy_data.items(): - hierarchy_formating_data[k] = _v["value"].format(**_data) + hierarchy_formatting_data[k] = _v["value"].format(**_data) else: # if no gui mode then just pass default data - hierarchy_formating_data = self.hierarchy_data + hierarchy_formatting_data = self.hierarchy_data tag_hierarchy_data = self._solve_tag_hierarchy_data( - hierarchy_formating_data + hierarchy_formatting_data ) tag_hierarchy_data.update({"heroTrack": True}) @@ -793,17 +793,17 @@ def _convert_to_tag_data(self): self.tag_data.update({"reviewTrack": None}) - def _solve_tag_hierarchy_data(self, hierarchy_formating_data): + def _solve_tag_hierarchy_data(self, hierarchy_formatting_data): """ Solve tag data from hierarchy data and templates. """ # fill up clip name and hierarchy keys - hierarchy_filled = self.hierarchy.format(**hierarchy_formating_data) - clip_name_filled = self.clip_name.format(**hierarchy_formating_data) + hierarchy_filled = self.hierarchy.format(**hierarchy_formatting_data) + clip_name_filled = self.clip_name.format(**hierarchy_formatting_data) return { "newClipName": clip_name_filled, "hierarchy": hierarchy_filled, "parents": self.parents, - "hierarchyData": hierarchy_formating_data, + "hierarchyData": hierarchy_formatting_data, "subset": self.subset, "family": self.subset_family, "families": ["clip"] diff --git a/openpype/hosts/standalonepublisher/plugins/publish/collect_bulk_mov_instances.py b/openpype/hosts/standalonepublisher/plugins/publish/collect_bulk_mov_instances.py index 7925b0ecf3a..6c3b0c3efdb 100644 --- a/openpype/hosts/standalonepublisher/plugins/publish/collect_bulk_mov_instances.py +++ b/openpype/hosts/standalonepublisher/plugins/publish/collect_bulk_mov_instances.py @@ -83,9 +83,9 @@ def process(self, instance): self.log.info(f"Created new instance: {instance_name}") - def convertor(value): + def converter(value): return str(value) self.log.debug("Instance data: {}".format( - json.dumps(new_instance.data, indent=4, default=convertor) + json.dumps(new_instance.data, indent=4, default=converter) )) diff --git a/openpype/hosts/standalonepublisher/plugins/publish/collect_context.py b/openpype/hosts/standalonepublisher/plugins/publish/collect_context.py index 2bf3917e2f2..a7746530e74 100644 --- a/openpype/hosts/standalonepublisher/plugins/publish/collect_context.py +++ b/openpype/hosts/standalonepublisher/plugins/publish/collect_context.py @@ -104,7 +104,7 @@ def multiple_instances(self, context, in_data): if repr.get(k): repr.pop(k) - # convert files to list if it isnt + # convert files to list if it isn't if not isinstance(files, (tuple, list)): files = [files] @@ -174,7 +174,7 @@ def prepare_mov_batch_instances(self, in_data): continue files = repre["files"] - # Convert files to list if it isnt + # Convert files to list if it isn't if not isinstance(files, (tuple, list)): files = [files] diff --git a/openpype/hosts/standalonepublisher/plugins/publish/collect_editorial.py b/openpype/hosts/standalonepublisher/plugins/publish/collect_editorial.py index 8633d4bf9dd..391cace7617 100644 --- a/openpype/hosts/standalonepublisher/plugins/publish/collect_editorial.py +++ b/openpype/hosts/standalonepublisher/plugins/publish/collect_editorial.py @@ -116,7 +116,7 @@ def process(self, instance): kwargs = {} if extension == ".edl": # EDL has no frame rate embedded so needs explicit - # frame rate else 24 is asssumed. + # frame rate else 24 is assumed. kwargs["rate"] = get_current_project_asset()["data"]["fps"] instance.data["otio_timeline"] = otio.adapters.read_from_file( diff --git a/openpype/hosts/standalonepublisher/plugins/publish/validate_frame_ranges.py b/openpype/hosts/standalonepublisher/plugins/publish/validate_frame_ranges.py index 074c62ea0e9..e46fbe60988 100644 --- a/openpype/hosts/standalonepublisher/plugins/publish/validate_frame_ranges.py +++ b/openpype/hosts/standalonepublisher/plugins/publish/validate_frame_ranges.py @@ -29,7 +29,7 @@ def process(self, instance): for pattern in self.skip_timelines_check): self.log.info("Skipping for {} task".format(instance.data["task"])) - # TODO repace query with using 'instance.data["assetEntity"]' + # TODO replace query with using 'instance.data["assetEntity"]' asset_data = get_current_project_asset(instance.data["asset"])["data"] frame_start = asset_data["frameStart"] frame_end = asset_data["frameEnd"] diff --git a/openpype/hosts/traypublisher/api/editorial.py b/openpype/hosts/traypublisher/api/editorial.py index 293db542a98..e8f76bd3141 100644 --- a/openpype/hosts/traypublisher/api/editorial.py +++ b/openpype/hosts/traypublisher/api/editorial.py @@ -8,10 +8,10 @@ class ShotMetadataSolver: """ Solving hierarchical metadata - Used during editorial publishing. Works with imput + Used during editorial publishing. Works with input clip name and settings defining python formatable template. Settings also define searching patterns - and its token keys used for formating in templates. + and its token keys used for formatting in templates. """ NO_DECOR_PATERN = re.compile(r"\{([a-z]*?)\}") @@ -40,13 +40,13 @@ def _rename_template(self, data): """Shot renaming function Args: - data (dict): formating data + data (dict): formatting data Raises: CreatorError: If missing keys Returns: - str: formated new name + str: formatted new name """ shot_rename_template = self.shot_rename[ "shot_rename_template"] @@ -58,7 +58,7 @@ def _rename_template(self, data): "Make sure all keys in settings are correct:: \n\n" f"From template string {shot_rename_template} > " f"`{_E}` has no equivalent in \n" - f"{list(data.keys())} input formating keys!" + f"{list(data.keys())} input formatting keys!" )) def _generate_tokens(self, clip_name, source_data): @@ -68,7 +68,7 @@ def _generate_tokens(self, clip_name, source_data): Args: clip_name (str): name of clip in editorial - source_data (dict): data for formating + source_data (dict): data for formatting Raises: CreatorError: if missing key @@ -106,14 +106,14 @@ def _generate_tokens(self, clip_name, source_data): return output_data def _create_parents_from_settings(self, parents, data): - """Formating parent components. + """formatting parent components. Args: parents (list): list of dict parent components - data (dict): formating data + data (dict): formatting data Raises: - CreatorError: missing formating key + CreatorError: missing formatting key CreatorError: missing token key KeyError: missing parent token @@ -126,7 +126,7 @@ def _create_parents_from_settings(self, parents, data): # fill parent keys data template from anatomy data try: - _parent_tokens_formating_data = { + _parent_tokens_formatting_data = { parent_token["name"]: parent_token["value"].format(**data) for parent_token in hierarchy_parents } @@ -143,17 +143,17 @@ def _create_parents_from_settings(self, parents, data): for _index, _parent in enumerate( shot_hierarchy["parents_path"].split("/") ): - # format parent token with value which is formated + # format parent token with value which is formatted try: parent_name = _parent.format( - **_parent_tokens_formating_data) + **_parent_tokens_formatting_data) except KeyError as _E: raise CreatorError(( "Make sure all keys in settings are correct : \n\n" f"`{_E}` from template string " f"{shot_hierarchy['parents_path']}, " f" has no equivalent in \n" - f"{list(_parent_tokens_formating_data.keys())} parents" + f"{list(_parent_tokens_formatting_data.keys())} parents" )) parent_token_name = ( @@ -225,7 +225,7 @@ def _get_parents_from_selected_asset( visual_hierarchy = [asset_doc] current_doc = asset_doc - # looping trought all available visual parents + # looping through all available visual parents # if they are not available anymore than it breaks while True: visual_parent_id = current_doc["data"]["visualParent"] @@ -288,7 +288,7 @@ def generate_data(self, clip_name, source_data): Args: clip_name (str): clip name - source_data (dict): formating data + source_data (dict): formatting data Returns: (str, dict): shot name and hierarchy data @@ -301,19 +301,19 @@ def generate_data(self, clip_name, source_data): # match clip to shot name at start shot_name = clip_name - # parse all tokens and generate formating data - formating_data = self._generate_tokens(shot_name, source_data) + # parse all tokens and generate formatting data + formatting_data = self._generate_tokens(shot_name, source_data) # generate parents from selected asset parents = self._get_parents_from_selected_asset(asset_doc, project_doc) if self.shot_rename["enabled"]: - shot_name = self._rename_template(formating_data) + shot_name = self._rename_template(formatting_data) self.log.info(f"Renamed shot name: {shot_name}") if self.shot_hierarchy["enabled"]: parents = self._create_parents_from_settings( - parents, formating_data) + parents, formatting_data) if self.shot_add_tasks: tasks = self._generate_tasks_from_settings( diff --git a/openpype/hosts/traypublisher/plugins/create/create_editorial.py b/openpype/hosts/traypublisher/plugins/create/create_editorial.py index 73be43444e8..0630dfb3da1 100644 --- a/openpype/hosts/traypublisher/plugins/create/create_editorial.py +++ b/openpype/hosts/traypublisher/plugins/create/create_editorial.py @@ -260,7 +260,7 @@ def create(self, subset_name, instance_data, pre_create_data): ) if not first_otio_timeline: - # assing otio timeline for multi file to layer + # assign otio timeline for multi file to layer first_otio_timeline = otio_timeline # create otio editorial instance @@ -283,7 +283,7 @@ def _create_otio_instance( Args: subset_name (str): name of subset - data (dict): instnance data + data (dict): instance data sequence_path (str): path to sequence file media_path (str): path to media file otio_timeline (otio.Timeline): otio timeline object @@ -315,7 +315,7 @@ def _create_otio_timeline(self, sequence_path, fps): kwargs = {} if extension == ".edl": # EDL has no frame rate embedded so needs explicit - # frame rate else 24 is asssumed. + # frame rate else 24 is assumed. kwargs["rate"] = fps kwargs["ignore_timecode_mismatch"] = True @@ -358,7 +358,7 @@ def _get_clip_instances( sequence_file_name, first_otio_timeline=None ): - """Helping function fro creating clip instance + """Helping function for creating clip instance Args: otio_timeline (otio.Timeline): otio timeline object @@ -527,7 +527,7 @@ def _make_subset_instance( Args: otio_clip (otio.Clip): otio clip object - preset (dict): sigle family preset + preset (dict): single family preset instance_data (dict): instance data parenting_data (dict): shot instance parent data @@ -767,7 +767,7 @@ def _get_allowed_family_presets(self, pre_create_data): ] def _validate_clip_for_processing(self, otio_clip): - """Validate otio clip attribues + """Validate otio clip attributes Args: otio_clip (otio.Clip): otio clip object @@ -843,7 +843,7 @@ def get_pre_create_attr_defs(self): single_item=False, label="Media files", ), - # TODO: perhpas better would be timecode and fps input + # TODO: perhaps better would be timecode and fps input NumberDef( "timeline_offset", default=0, diff --git a/openpype/hosts/traypublisher/plugins/publish/collect_simple_instances.py b/openpype/hosts/traypublisher/plugins/publish/collect_simple_instances.py index 183195a5155..c081216481c 100644 --- a/openpype/hosts/traypublisher/plugins/publish/collect_simple_instances.py +++ b/openpype/hosts/traypublisher/plugins/publish/collect_simple_instances.py @@ -14,7 +14,7 @@ class CollectSettingsSimpleInstances(pyblish.api.InstancePlugin): There is also possibility to have reviewable representation which can be stored under 'reviewable' attribute stored on instance data. If there was - already created representation with the same files as 'revieable' containes + already created representation with the same files as 'reviewable' contains Representations can be marked for review and in that case is also added 'review' family to instance families. For review can be marked only one diff --git a/openpype/hosts/tvpaint/plugins/publish/help/validate_layers_visibility.xml b/openpype/hosts/tvpaint/plugins/publish/help/validate_layers_visibility.xml index e7be7358881..5832c743500 100644 --- a/openpype/hosts/tvpaint/plugins/publish/help/validate_layers_visibility.xml +++ b/openpype/hosts/tvpaint/plugins/publish/help/validate_layers_visibility.xml @@ -1,7 +1,7 @@ -Layers visiblity +Layers visibility ## All layers are not visible Layers visibility was changed during publishing which caused that all layers for subset "{instance_name}" are hidden. diff --git a/openpype/hosts/tvpaint/plugins/publish/help/validate_workfile_metadata.xml b/openpype/hosts/tvpaint/plugins/publish/help/validate_workfile_metadata.xml index 7397f6ef0b1..0fc03c2948b 100644 --- a/openpype/hosts/tvpaint/plugins/publish/help/validate_workfile_metadata.xml +++ b/openpype/hosts/tvpaint/plugins/publish/help/validate_workfile_metadata.xml @@ -11,7 +11,7 @@ Your scene does not contain metadata about {missing_metadata}. Resave the scene using Workfiles tool or hit the "Repair" button on the right. -### How this could happend? +### How this could happen? You're using scene file that was not created using Workfiles tool. diff --git a/openpype/hosts/tvpaint/plugins/publish/help/validate_workfile_project_name.xml b/openpype/hosts/tvpaint/plugins/publish/help/validate_workfile_project_name.xml index c4ffafc8b5f..bb57e93bf25 100644 --- a/openpype/hosts/tvpaint/plugins/publish/help/validate_workfile_project_name.xml +++ b/openpype/hosts/tvpaint/plugins/publish/help/validate_workfile_project_name.xml @@ -13,7 +13,7 @@ If the workfile belongs to project "{env_project_name}" then use Workfiles tool Otherwise close TVPaint and launch it again from project you want to publish in. -### How this could happend? +### How this could happen? You've opened workfile from different project. You've opened TVPaint on a task from "{env_project_name}" then you've opened TVPaint again on task from "{workfile_project_name}" without closing the TVPaint. Because TVPaint can run only once the project didn't change. diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_asset_name.py b/openpype/hosts/tvpaint/plugins/publish/validate_asset_name.py index d7984ce9719..9347960d3f4 100644 --- a/openpype/hosts/tvpaint/plugins/publish/validate_asset_name.py +++ b/openpype/hosts/tvpaint/plugins/publish/validate_asset_name.py @@ -38,7 +38,7 @@ class ValidateAssetName( OptionalPyblishPluginMixin, pyblish.api.ContextPlugin ): - """Validate assset name present on instance. + """Validate asset name present on instance. Asset name on instance should be the same as context's. """ diff --git a/openpype/hosts/unreal/api/pipeline.py b/openpype/hosts/unreal/api/pipeline.py index 8a5a4591949..1a7c6269842 100644 --- a/openpype/hosts/unreal/api/pipeline.py +++ b/openpype/hosts/unreal/api/pipeline.py @@ -306,7 +306,7 @@ def imprint(node, data): def show_tools_popup(): """Show popup with tools. - Popup will disappear on click or loosing focus. + Popup will disappear on click or losing focus. """ from openpype.hosts.unreal.api import tools_ui diff --git a/openpype/hosts/unreal/integration/UE_4.7/OpenPype/Source/OpenPype/Private/OpenPypeLib.cpp b/openpype/hosts/unreal/integration/UE_4.7/OpenPype/Source/OpenPype/Private/OpenPypeLib.cpp index 008025e8166..34faba1f499 100644 --- a/openpype/hosts/unreal/integration/UE_4.7/OpenPype/Source/OpenPype/Private/OpenPypeLib.cpp +++ b/openpype/hosts/unreal/integration/UE_4.7/OpenPype/Source/OpenPype/Private/OpenPypeLib.cpp @@ -31,7 +31,7 @@ bool UOpenPypeLib::SetFolderColor(const FString& FolderPath, const FLinearColor& } /** - * Returns all poperties on given object + * Returns all properties on given object * @param cls - class * @return TArray of properties */ diff --git a/openpype/hosts/unreal/integration/UE_4.7/OpenPype/Source/OpenPype/Public/Commandlets/OPActionResult.h b/openpype/hosts/unreal/integration/UE_4.7/OpenPype/Source/OpenPype/Public/Commandlets/OPActionResult.h index c960bbf190d..322a23a3e81 100644 --- a/openpype/hosts/unreal/integration/UE_4.7/OpenPype/Source/OpenPype/Public/Commandlets/OPActionResult.h +++ b/openpype/hosts/unreal/integration/UE_4.7/OpenPype/Source/OpenPype/Public/Commandlets/OPActionResult.h @@ -16,7 +16,7 @@ /** * @brief This enum values are humanly readable mapping of error codes. * Here should be all error codes to be possible find what went wrong. -* TODO: In the future should exists an web document where is mapped error code & what problem occured & how to repair it... +* TODO: In the future a web document should exists with the mapped error code & what problem occurred & how to repair it... */ UENUM() namespace EOP_ActionResult @@ -27,11 +27,11 @@ namespace EOP_ActionResult ProjectNotCreated, ProjectNotLoaded, ProjectNotSaved, - //....Here insert another values + //....Here insert another values //Do not remove! //Usable for looping through enum values - __Last UMETA(Hidden) + __Last UMETA(Hidden) }; } @@ -63,10 +63,10 @@ struct FOP_ActionResult private: /** @brief Action status */ - EOP_ActionResult::Type Status; + EOP_ActionResult::Type Status; /** @brief Optional reason of fail */ - FText Reason; + FText Reason; public: /** @@ -77,7 +77,7 @@ struct FOP_ActionResult EOP_ActionResult::Type& GetStatus(); FText& GetReason(); -private: +private: void TryLog() const; }; diff --git a/openpype/hosts/unreal/integration/UE_5.0/OpenPype/Source/OpenPype/Private/OpenPypeLib.cpp b/openpype/hosts/unreal/integration/UE_5.0/OpenPype/Source/OpenPype/Private/OpenPypeLib.cpp index 008025e8166..34faba1f499 100644 --- a/openpype/hosts/unreal/integration/UE_5.0/OpenPype/Source/OpenPype/Private/OpenPypeLib.cpp +++ b/openpype/hosts/unreal/integration/UE_5.0/OpenPype/Source/OpenPype/Private/OpenPypeLib.cpp @@ -31,7 +31,7 @@ bool UOpenPypeLib::SetFolderColor(const FString& FolderPath, const FLinearColor& } /** - * Returns all poperties on given object + * Returns all properties on given object * @param cls - class * @return TArray of properties */ diff --git a/openpype/hosts/unreal/integration/UE_5.0/OpenPype/Source/OpenPype/Public/Commandlets/OPActionResult.h b/openpype/hosts/unreal/integration/UE_5.0/OpenPype/Source/OpenPype/Public/Commandlets/OPActionResult.h index c960bbf190d..322a23a3e81 100644 --- a/openpype/hosts/unreal/integration/UE_5.0/OpenPype/Source/OpenPype/Public/Commandlets/OPActionResult.h +++ b/openpype/hosts/unreal/integration/UE_5.0/OpenPype/Source/OpenPype/Public/Commandlets/OPActionResult.h @@ -16,7 +16,7 @@ /** * @brief This enum values are humanly readable mapping of error codes. * Here should be all error codes to be possible find what went wrong. -* TODO: In the future should exists an web document where is mapped error code & what problem occured & how to repair it... +* TODO: In the future a web document should exists with the mapped error code & what problem occurred & how to repair it... */ UENUM() namespace EOP_ActionResult @@ -27,11 +27,11 @@ namespace EOP_ActionResult ProjectNotCreated, ProjectNotLoaded, ProjectNotSaved, - //....Here insert another values + //....Here insert another values //Do not remove! //Usable for looping through enum values - __Last UMETA(Hidden) + __Last UMETA(Hidden) }; } @@ -63,10 +63,10 @@ struct FOP_ActionResult private: /** @brief Action status */ - EOP_ActionResult::Type Status; + EOP_ActionResult::Type Status; /** @brief Optional reason of fail */ - FText Reason; + FText Reason; public: /** @@ -77,7 +77,7 @@ struct FOP_ActionResult EOP_ActionResult::Type& GetStatus(); FText& GetReason(); -private: +private: void TryLog() const; }; diff --git a/openpype/hosts/unreal/plugins/load/load_camera.py b/openpype/hosts/unreal/plugins/load/load_camera.py index ca6b0ce7368..2496440e5f0 100644 --- a/openpype/hosts/unreal/plugins/load/load_camera.py +++ b/openpype/hosts/unreal/plugins/load/load_camera.py @@ -171,7 +171,7 @@ def load(self, context, name, namespace, data): project_name = legacy_io.active_project() # TODO refactor - # - Creationg of hierarchy should be a function in unreal integration + # - Creating of hierarchy should be a function in unreal integration # - it's used in multiple loaders but must not be loader's logic # - hard to say what is purpose of the loop # - variables does not match their meaning diff --git a/openpype/hosts/webpublisher/lib.py b/openpype/hosts/webpublisher/lib.py index 4bc3f1db80d..b207f85b46e 100644 --- a/openpype/hosts/webpublisher/lib.py +++ b/openpype/hosts/webpublisher/lib.py @@ -30,7 +30,7 @@ def parse_json(path): Returns: (dict) or None if unparsable Raises: - AsssertionError if 'path' doesn't exist + AssertionError if 'path' doesn't exist """ path = path.strip('\"') assert os.path.isfile(path), ( diff --git a/openpype/lib/applications.py b/openpype/lib/applications.py index 127d31d042d..8adae348276 100644 --- a/openpype/lib/applications.py +++ b/openpype/lib/applications.py @@ -969,7 +969,7 @@ def _collect_addons_launch_hook_paths(self): """Helper to collect application launch hooks from addons. Module have to have implemented 'get_launch_hook_paths' method which - can expect appliction as argument or nothing. + can expect application as argument or nothing. Returns: List[str]: Paths to launch hook directories. diff --git a/openpype/lib/attribute_definitions.py b/openpype/lib/attribute_definitions.py index b5cd15f41af..6054d2a92ae 100644 --- a/openpype/lib/attribute_definitions.py +++ b/openpype/lib/attribute_definitions.py @@ -9,7 +9,7 @@ import six import clique -# Global variable which store attribude definitions by type +# Global variable which store attribute definitions by type # - default types are registered on import _attr_defs_by_type = {} @@ -93,7 +93,7 @@ def __call__(self, *args, **kwargs): @six.add_metaclass(AbstractAttrDefMeta) class AbstractAttrDef(object): - """Abstraction of attribute definiton. + """Abstraction of attribute definition. Each attribute definition must have implemented validation and conversion method. @@ -427,7 +427,7 @@ class EnumDef(AbstractAttrDef): """Enumeration of single item from items. Args: - items: Items definition that can be coverted using + items: Items definition that can be converted using 'prepare_enum_items'. default: Default value. Must be one key(value) from passed items. """ diff --git a/openpype/lib/events.py b/openpype/lib/events.py index 096201312fb..bed00fe6591 100644 --- a/openpype/lib/events.py +++ b/openpype/lib/events.py @@ -156,7 +156,7 @@ def set_enabled(self, enabled): self._enabled = enabled def deregister(self): - """Calling this funcion will cause that callback will be removed.""" + """Calling this function will cause that callback will be removed.""" # Fake reference self._ref_valid = False diff --git a/openpype/lib/execute.py b/openpype/lib/execute.py index 6f9a0952851..834394b02f5 100644 --- a/openpype/lib/execute.py +++ b/openpype/lib/execute.py @@ -163,7 +163,7 @@ def run_subprocess(*args, **kwargs): def clean_envs_for_openpype_process(env=None): - """Modify environemnts that may affect OpenPype process. + """Modify environments that may affect OpenPype process. Main reason to implement this function is to pop PYTHONPATH which may be affected by in-host environments. diff --git a/openpype/lib/file_transaction.py b/openpype/lib/file_transaction.py index 81332a88915..80f4e81f2c3 100644 --- a/openpype/lib/file_transaction.py +++ b/openpype/lib/file_transaction.py @@ -130,7 +130,7 @@ def process(self): path_same = self._same_paths(src, dst) if path_same: self.log.debug( - "Source and destionation are same files {} -> {}".format( + "Source and destination are same files {} -> {}".format( src, dst)) continue diff --git a/openpype/lib/transcoding.py b/openpype/lib/transcoding.py index 799693554fa..57968b37002 100644 --- a/openpype/lib/transcoding.py +++ b/openpype/lib/transcoding.py @@ -540,7 +540,7 @@ def convert_for_ffmpeg( continue # Remove attributes that have string value longer than allowed length - # for ffmpeg or when containt unallowed symbols + # for ffmpeg or when contain unallowed symbols erase_reason = "Missing reason" erase_attribute = False if len(attr_value) > MAX_FFMPEG_STRING_LEN: @@ -680,7 +680,7 @@ def convert_input_paths_for_ffmpeg( continue # Remove attributes that have string value longer than allowed - # length for ffmpeg or when containt unallowed symbols + # length for ffmpeg or when containing unallowed symbols erase_reason = "Missing reason" erase_attribute = False if len(attr_value) > MAX_FFMPEG_STRING_LEN: @@ -968,7 +968,7 @@ def _ffmpeg_dnxhd_codec_args(stream_data, source_ffmpeg_cmd): if source_ffmpeg_cmd: # Define bitrate arguments bit_rate_args = ("-b:v", "-vb",) - # Seprate the two variables in case something else should be copied + # Separate the two variables in case something else should be copied # from source command copy_args = [] copy_args.extend(bit_rate_args) diff --git a/openpype/lib/vendor_bin_utils.py b/openpype/lib/vendor_bin_utils.py index e5deb7a6b23..f27c78d486c 100644 --- a/openpype/lib/vendor_bin_utils.py +++ b/openpype/lib/vendor_bin_utils.py @@ -260,7 +260,7 @@ def _oiio_executable_validation(filepath): that it can be executed. For that is used '--help' argument which is fast and does not need any other inputs. - Any possible crash of missing libraries or invalid build should be catched. + Any possible crash of missing libraries or invalid build should be caught. Main reason is to validate if executable can be executed on OS just running which can be issue ob linux machines. @@ -329,7 +329,7 @@ def _ffmpeg_executable_validation(filepath): that it can be executed. For that is used '-version' argument which is fast and does not need any other inputs. - Any possible crash of missing libraries or invalid build should be catched. + Any possible crash of missing libraries or invalid build should be caught. Main reason is to validate if executable can be executed on OS just running which can be issue ob linux machines. diff --git a/openpype/modules/base.py b/openpype/modules/base.py index 0fd21492e82..730585212b1 100644 --- a/openpype/modules/base.py +++ b/openpype/modules/base.py @@ -472,7 +472,7 @@ def modify_application_launch_arguments(self, application, env): Args: application (Application): Application that is launched. - env (dict): Current environemnt variables. + env (dict): Current environment variables. """ pass @@ -622,7 +622,7 @@ def initialize_modules(self): # Check if class is abstract (Developing purpose) if inspect.isabstract(modules_item): - # Find missing implementations by convetion on `abc` module + # Find missing implementations by convention on `abc` module not_implemented = [] for attr_name in dir(modules_item): attr = getattr(modules_item, attr_name, None) @@ -708,13 +708,13 @@ def get_enabled_modules(self): ] def collect_global_environments(self): - """Helper to collect global enviornment variabled from modules. + """Helper to collect global environment variabled from modules. Returns: dict: Global environment variables from enabled modules. Raises: - AssertionError: Gobal environment variables must be unique for + AssertionError: Global environment variables must be unique for all modules. """ module_envs = {} @@ -1174,7 +1174,7 @@ def on_exit(self): def get_module_settings_defs(): - """Check loaded addons/modules for existence of thei settings definition. + """Check loaded addons/modules for existence of their settings definition. Check if OpenPype addon/module as python module has class that inherit from `ModuleSettingsDef` in python module variables (imported @@ -1204,7 +1204,7 @@ def get_module_settings_defs(): continue if inspect.isabstract(attr): - # Find missing implementations by convetion on `abc` module + # Find missing implementations by convention on `abc` module not_implemented = [] for attr_name in dir(attr): attr = getattr(attr, attr_name, None) @@ -1293,7 +1293,7 @@ def save_defaults(self, top_key, data): class ModuleSettingsDef(BaseModuleSettingsDef): - """Settings definiton with separated system and procect settings parts. + """Settings definition with separated system and procect settings parts. Reduce conditions that must be checked and adds predefined methods for each case. diff --git a/openpype/modules/clockify/clockify_api.py b/openpype/modules/clockify/clockify_api.py index 80979c83ab2..47af002f7ab 100644 --- a/openpype/modules/clockify/clockify_api.py +++ b/openpype/modules/clockify/clockify_api.py @@ -247,7 +247,7 @@ def start_time_entry( current_timer = self.get_in_progress() # Check if is currently run another times and has same values - # DO not restart the timer, if it is already running for curent task + # DO not restart the timer, if it is already running for current task if current_timer: current_timer_hierarchy = current_timer.get("description") current_project_id = current_timer.get("projectId") diff --git a/openpype/modules/clockify/clockify_module.py b/openpype/modules/clockify/clockify_module.py index 200a268ad7c..b6efec79074 100644 --- a/openpype/modules/clockify/clockify_module.py +++ b/openpype/modules/clockify/clockify_module.py @@ -76,7 +76,7 @@ def tray_exit(self, *_a, **_kw): return def get_plugin_paths(self): - """Implementaton of IPluginPaths to get plugin paths.""" + """Implementation of IPluginPaths to get plugin paths.""" actions_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "launcher_actions" ) diff --git a/openpype/modules/clockify/widgets.py b/openpype/modules/clockify/widgets.py index 8c28f38b6ef..86e67569f2b 100644 --- a/openpype/modules/clockify/widgets.py +++ b/openpype/modules/clockify/widgets.py @@ -34,7 +34,7 @@ def __init__(self, messages, title): def _ui_layout(self, messages): if not messages: - messages = ["*Misssing messages (This is a bug)*", ] + messages = ["*Missing messages (This is a bug)*", ] elif not isinstance(messages, (tuple, list)): messages = [messages, ] diff --git a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py index cc069cf51a8..0c899a500cc 100644 --- a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py @@ -66,7 +66,7 @@ def get_attribute_defs(cls): ), NumberDef( "concurrency", - label="Concurency", + label="Concurrency", default=cls.concurrent_tasks, decimals=0, minimum=1, diff --git a/openpype/modules/deadline/plugins/publish/submit_publish_job.py b/openpype/modules/deadline/plugins/publish/submit_publish_job.py index 0d0698c21f9..f6a794fbc07 100644 --- a/openpype/modules/deadline/plugins/publish/submit_publish_job.py +++ b/openpype/modules/deadline/plugins/publish/submit_publish_job.py @@ -85,10 +85,10 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): These jobs are dependent on a deadline or muster job submission prior to this plug-in. - - In case of Deadline, it creates dependend job on farm publishing + - In case of Deadline, it creates dependent job on farm publishing rendered image sequence. - - In case of Muster, there is no need for such thing as dependend job, + - In case of Muster, there is no need for such thing as dependent job, post action will be executed and rendered sequence will be published. Options in instance.data: @@ -108,7 +108,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): - publishJobState (str, Optional): "Active" or "Suspended" This defaults to "Suspended" - - expectedFiles (list or dict): explained bellow + - expectedFiles (list or dict): explained below """ @@ -158,7 +158,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): # regex for finding frame number in string R_FRAME_NUMBER = re.compile(r'.+\.(?P[0-9]+)\..+') - # mapping of instance properties to be transfered to new instance for every + # mapping of instance properties to be transferred to new instance for every # specified family instance_transfer = { "slate": ["slateFrames", "slate"], @@ -398,7 +398,7 @@ def _copy_extend_frames(self, instance, representation): continue r_col.indexes.remove(frame) - # now we need to translate published names from represenation + # now we need to translate published names from representation # back. This is tricky, right now we'll just use same naming # and only switch frame numbers resource_files = [] @@ -535,7 +535,7 @@ def _create_instances_for_aov( if preview: new_instance["review"] = True - # create represenation + # create representation if isinstance(col, (list, tuple)): files = [os.path.basename(f) for f in col] else: @@ -748,7 +748,7 @@ def process(self, instance): # type: (pyblish.api.Instance) -> None """Process plugin. - Detect type of renderfarm submission and create and post dependend job + Detect type of renderfarm submission and create and post dependent job in case of Deadline. It creates json file with metadata needed for publishing in directory of render. @@ -986,7 +986,7 @@ def process(self, instance): instances = [instance_skeleton_data] # if we are attaching to other subsets, create copy of existing - # instances, change data to match thats subset and replace + # instances, change data to match its subset and replace # existing instances with modified data if instance.data.get("attachTo"): self.log.info("Attaching render to subset:") diff --git a/openpype/modules/ftrack/event_handlers_server/action_clone_review_session.py b/openpype/modules/ftrack/event_handlers_server/action_clone_review_session.py index 1ad7a17785e..333228c6999 100644 --- a/openpype/modules/ftrack/event_handlers_server/action_clone_review_session.py +++ b/openpype/modules/ftrack/event_handlers_server/action_clone_review_session.py @@ -44,7 +44,7 @@ def clone_review_session(session, entity): class CloneReviewSession(ServerAction): '''Generate Client Review action - `label` a descriptive string identifing your action. + `label` a descriptive string identifying your action. `varaint` To group actions together, give them the same label and specify a unique variant per action. `identifier` a unique identifier for your action. diff --git a/openpype/modules/ftrack/event_handlers_server/action_create_review_session.py b/openpype/modules/ftrack/event_handlers_server/action_create_review_session.py index 21382007a0f..42a279e3333 100644 --- a/openpype/modules/ftrack/event_handlers_server/action_create_review_session.py +++ b/openpype/modules/ftrack/event_handlers_server/action_create_review_session.py @@ -230,7 +230,7 @@ def _process_review_session( if not today_session_name: continue - # Find matchin review session + # Find matching review session project_review_sessions = review_sessions_by_project_id[project_id] todays_session = None yesterdays_session = None diff --git a/openpype/modules/ftrack/event_handlers_server/action_prepare_project.py b/openpype/modules/ftrack/event_handlers_server/action_prepare_project.py index 332648cd028..02231cbe3ce 100644 --- a/openpype/modules/ftrack/event_handlers_server/action_prepare_project.py +++ b/openpype/modules/ftrack/event_handlers_server/action_prepare_project.py @@ -124,7 +124,7 @@ def prepare_root_items(self, project_anatom_settings): root_items.append({ "type": "label", "value": ( - "

    NOTE: Roots are crutial for path filling" + "

    NOTE: Roots are crucial for path filling" " (and creating folder structure).

    " ) }) diff --git a/openpype/modules/ftrack/event_handlers_server/action_tranfer_hierarchical_values.py b/openpype/modules/ftrack/event_handlers_server/action_tranfer_hierarchical_values.py index d160b7200db..f6899843a39 100644 --- a/openpype/modules/ftrack/event_handlers_server/action_tranfer_hierarchical_values.py +++ b/openpype/modules/ftrack/event_handlers_server/action_tranfer_hierarchical_values.py @@ -12,7 +12,7 @@ class TransferHierarchicalValues(ServerAction): - """Transfer values across hierarhcical attributes. + """Transfer values across hierarchical attributes. Aalso gives ability to convert types meanwhile. That is limited to conversions between numbers and strings @@ -67,7 +67,7 @@ def _selection_interface(self, session, event_values=None): "type": "label", "value": ( "Didn't found custom attributes" - " that can be transfered." + " that can be transferred." ) }] } diff --git a/openpype/modules/ftrack/event_handlers_server/event_next_task_update.py b/openpype/modules/ftrack/event_handlers_server/event_next_task_update.py index a65ae46545c..a100c34f679 100644 --- a/openpype/modules/ftrack/event_handlers_server/event_next_task_update.py +++ b/openpype/modules/ftrack/event_handlers_server/event_next_task_update.py @@ -279,7 +279,7 @@ def set_next_task_statuses( except Exception: session.rollback() self.log.warning( - "\"{}\" status couldnt be set to \"{}\"".format( + "\"{}\" status couldn't be set to \"{}\"".format( ent_path, new_status["name"] ), exc_info=True diff --git a/openpype/modules/ftrack/event_handlers_server/event_push_frame_values_to_task.py b/openpype/modules/ftrack/event_handlers_server/event_push_frame_values_to_task.py index 0f10145c066..ed630ad59d9 100644 --- a/openpype/modules/ftrack/event_handlers_server/event_push_frame_values_to_task.py +++ b/openpype/modules/ftrack/event_handlers_server/event_push_frame_values_to_task.py @@ -394,7 +394,7 @@ def process_by_project( project_id: str, entities_info: list[dict[str, Any]] ): - """Proces changes in single project. + """Process changes in single project. Args: session (ftrack_api.Session): Ftrack session. diff --git a/openpype/modules/ftrack/event_handlers_server/event_radio_buttons.py b/openpype/modules/ftrack/event_handlers_server/event_radio_buttons.py index 99ad3aec374..358a8d2310d 100644 --- a/openpype/modules/ftrack/event_handlers_server/event_radio_buttons.py +++ b/openpype/modules/ftrack/event_handlers_server/event_radio_buttons.py @@ -7,7 +7,7 @@ class RadioButtons(BaseEvent): ignore_me = True def launch(self, session, event): - '''Provides a readio button behaviour to any bolean attribute in + '''Provides a radio button behaviour to any boolean attribute in radio_button group.''' # start of event procedure ---------------------------------- diff --git a/openpype/modules/ftrack/event_handlers_server/event_sync_to_avalon.py b/openpype/modules/ftrack/event_handlers_server/event_sync_to_avalon.py index 0058a428e33..0aa0b9f9f54 100644 --- a/openpype/modules/ftrack/event_handlers_server/event_sync_to_avalon.py +++ b/openpype/modules/ftrack/event_handlers_server/event_sync_to_avalon.py @@ -787,7 +787,7 @@ def launch(self, session, event): # Filter updates where name is changing for ftrack_id, ent_info in updated.items(): ent_keys = ent_info["keys"] - # Seprate update info from rename + # Separate update info from rename if "name" not in ent_keys: continue @@ -827,7 +827,7 @@ def launch(self, session, event): # 5.) Process updated self.process_updated() time_6 = time.time() - # 6.) Process changes in hierarchy or hier custom attribues + # 6.) Process changes in hierarchy or hier custom attributes self.process_hier_cleanup() time_7 = time.time() self.process_task_updates() @@ -1094,7 +1094,7 @@ def process_removed(self): def check_names_synchronizable(self, names): """Check if entities with specific names are importable. - This check should happend after removing entity or renaming entity. + This check should happen after removing entity or renaming entity. When entity was removed or renamed then it's name is possible to sync. """ joined_passed_names = ", ".join( @@ -1743,7 +1743,7 @@ def process_added(self): def process_moved(self): """ - Handles moved entities to different place in hiearchy. + Handles moved entities to different place in hierarchy. (Not tasks - handled separately.) """ if not self.ftrack_moved: @@ -1792,7 +1792,7 @@ def process_moved(self): self.log.warning("{} <{}>".format(error_msg, ent_path)) continue - # THIS MUST HAPPEND AFTER CREATING NEW ENTITIES !!!! + # THIS MUST HAPPEN AFTER CREATING NEW ENTITIES !!!! # - because may be moved to new created entity if "data" not in self.updates[mongo_id]: self.updates[mongo_id]["data"] = {} @@ -2323,7 +2323,7 @@ def process_hier_cleanup(self): items.append("{} - \"{}\"".format(ent_path, value)) self.report_items["error"][fps_msg] = items - # Get dictionary with not None hierarchical values to pull to childs + # Get dictionary with not None hierarchical values to pull to children project_values = {} for key, value in ( entities_dict[ftrack_project_id]["hier_attrs"].items() @@ -2460,7 +2460,7 @@ def process_task_updates(self): def update_entities(self): """ Update Avalon entities by mongo bulk changes. - Expects self.updates which are transfered to $set part of update + Expects self.updates which are transferred to $set part of update command. Resets self.updates afterwards. """ diff --git a/openpype/modules/ftrack/event_handlers_server/event_task_to_parent_status.py b/openpype/modules/ftrack/event_handlers_server/event_task_to_parent_status.py index a0e039926e0..25fa3b0535b 100644 --- a/openpype/modules/ftrack/event_handlers_server/event_task_to_parent_status.py +++ b/openpype/modules/ftrack/event_handlers_server/event_task_to_parent_status.py @@ -291,7 +291,7 @@ def process_by_project(self, session, event, project_id, entities_info): except Exception: session.rollback() self.log.warning( - "\"{}\" status couldnt be set to \"{}\"".format( + "\"{}\" status couldn't be set to \"{}\"".format( ent_path, new_status["name"] ), exc_info=True @@ -399,7 +399,7 @@ def new_status_by_remainders( # For cases there are multiple tasks in changes # - task status which match any new status item by order in the - # list `single_match` is preffered + # list `single_match` is preferred best_order = len(single_match) best_order_status = None for task_entity in task_entities: diff --git a/openpype/modules/ftrack/event_handlers_server/event_user_assigment.py b/openpype/modules/ftrack/event_handlers_server/event_user_assigment.py index c4e48b92f0d..9539a34f5e1 100644 --- a/openpype/modules/ftrack/event_handlers_server/event_user_assigment.py +++ b/openpype/modules/ftrack/event_handlers_server/event_user_assigment.py @@ -10,11 +10,11 @@ class UserAssigmentEvent(BaseEvent): """ - This script will intercept user assigment / de-assigment event and + This script will intercept user assignment / de-assignment event and run shell script, providing as much context as possible. It expects configuration file ``presets/ftrack/user_assigment_event.json``. - In it, you define paths to scripts to be run for user assigment event and + In it, you define paths to scripts to be run for user assignment event and for user-deassigment:: { "add": [ diff --git a/openpype/modules/ftrack/event_handlers_server/event_version_to_task_statuses.py b/openpype/modules/ftrack/event_handlers_server/event_version_to_task_statuses.py index e36c3eecd98..fb40fd6417f 100644 --- a/openpype/modules/ftrack/event_handlers_server/event_version_to_task_statuses.py +++ b/openpype/modules/ftrack/event_handlers_server/event_version_to_task_statuses.py @@ -102,7 +102,7 @@ def process_by_project(self, session, event, project_id, entities_info): asset_version_entities.append(asset_version) task_ids.add(asset_version["task_id"]) - # Skipt if `task_ids` are empty + # Skip if `task_ids` are empty if not task_ids: return diff --git a/openpype/modules/ftrack/event_handlers_user/action_batch_task_creation.py b/openpype/modules/ftrack/event_handlers_user/action_batch_task_creation.py index c7fb1af98b9..06d572601dc 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_batch_task_creation.py +++ b/openpype/modules/ftrack/event_handlers_user/action_batch_task_creation.py @@ -7,7 +7,7 @@ class BatchTasksAction(BaseAction): '''Batch Tasks action - `label` a descriptive string identifing your action. + `label` a descriptive string identifying your action. `varaint` To group actions together, give them the same label and specify a unique variant per action. `identifier` a unique identifier for your action. diff --git a/openpype/modules/ftrack/event_handlers_user/action_create_cust_attrs.py b/openpype/modules/ftrack/event_handlers_user/action_create_cust_attrs.py index c19cfd1502f..471a8c41824 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_create_cust_attrs.py +++ b/openpype/modules/ftrack/event_handlers_user/action_create_cust_attrs.py @@ -82,9 +82,9 @@ write_security_roles/read_security_roles (array of strings) - default: ["ALL"] - strings should be role names (e.g.: ["API", "Administrator"]) - - if set to ["ALL"] - all roles will be availabled + - if set to ["ALL"] - all roles will be available - if first is 'except' - roles will be set to all except roles in array - - Warning: Be carefull with except - roles can be different by company + - Warning: Be careful with except - roles can be different by company - example: write_security_roles = ["except", "User"] read_security_roles = ["ALL"] # (User is can only read) @@ -500,7 +500,7 @@ def process_attr_data(self, cust_attr_data, event): data = {} # Get key, label, type data.update(self.get_required(cust_attr_data)) - # Get hierachical/ entity_type/ object_id + # Get hierarchical/ entity_type/ object_id data.update(self.get_entity_type(cust_attr_data)) # Get group, default, security roles data.update(self.get_optional(cust_attr_data)) diff --git a/openpype/modules/ftrack/event_handlers_user/action_create_folders.py b/openpype/modules/ftrack/event_handlers_user/action_create_folders.py index 9806f83773d..cbeff5343fb 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_create_folders.py +++ b/openpype/modules/ftrack/event_handlers_user/action_create_folders.py @@ -51,7 +51,7 @@ def interface(self, session, entities, event): }, { "type": "label", - "value": "With all chilren entities" + "value": "With all children entities" }, { "name": "children_included", diff --git a/openpype/modules/ftrack/event_handlers_user/action_delete_asset.py b/openpype/modules/ftrack/event_handlers_user/action_delete_asset.py index 03d029b0c18..72a5efbcfee 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_delete_asset.py +++ b/openpype/modules/ftrack/event_handlers_user/action_delete_asset.py @@ -18,7 +18,7 @@ class DeleteAssetSubset(BaseAction): # Action label. label = "Delete Asset/Subsets" # Action description. - description = "Removes from Avalon with all childs and asset from Ftrack" + description = "Removes from Avalon with all children and asset from Ftrack" icon = statics_icon("ftrack", "action_icons", "DeleteAsset.svg") settings_key = "delete_asset_subset" diff --git a/openpype/modules/ftrack/event_handlers_user/action_delete_old_versions.py b/openpype/modules/ftrack/event_handlers_user/action_delete_old_versions.py index c543dc8834f..ec14c6918bf 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_delete_old_versions.py +++ b/openpype/modules/ftrack/event_handlers_user/action_delete_old_versions.py @@ -27,7 +27,7 @@ class DeleteOldVersions(BaseAction): variant = "- Delete old versions" description = ( "Delete files from older publishes so project can be" - " archived with only lates versions." + " archived with only latest versions." ) icon = statics_icon("ftrack", "action_icons", "OpenPypeAdmin.svg") @@ -307,7 +307,7 @@ def sort_func(ent): file_path, seq_path = self.path_from_represenation(repre, anatomy) if file_path is None: self.log.warning(( - "Could not format path for represenation \"{}\"" + "Could not format path for representation \"{}\"" ).format(str(repre))) continue diff --git a/openpype/modules/ftrack/event_handlers_user/action_delivery.py b/openpype/modules/ftrack/event_handlers_user/action_delivery.py index a400c8f5f03..559de3a24d7 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_delivery.py +++ b/openpype/modules/ftrack/event_handlers_user/action_delivery.py @@ -601,7 +601,7 @@ def real_launch(self, session, entities, event): return self.report(report_items) def report(self, report_items): - """Returns dict with final status of delivery (succes, fail etc.).""" + """Returns dict with final status of delivery (success, fail etc.).""" items = [] for msg, _items in report_items.items(): diff --git a/openpype/modules/ftrack/event_handlers_user/action_fill_workfile_attr.py b/openpype/modules/ftrack/event_handlers_user/action_fill_workfile_attr.py index fb1cdf340e2..36d29db96b6 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_fill_workfile_attr.py +++ b/openpype/modules/ftrack/event_handlers_user/action_fill_workfile_attr.py @@ -246,7 +246,7 @@ def in_job_process( project_name = project_entity["full_name"] - # Find matchin asset documents and map them by ftrack task entities + # Find matching asset documents and map them by ftrack task entities # - result stored to 'asset_docs_with_task_entities' is list with # tuple `(asset document, [task entitis, ...])` # Quety all asset documents diff --git a/openpype/modules/ftrack/event_handlers_user/action_job_killer.py b/openpype/modules/ftrack/event_handlers_user/action_job_killer.py index f489c0c54c3..dd68c75f846 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_job_killer.py +++ b/openpype/modules/ftrack/event_handlers_user/action_job_killer.py @@ -54,14 +54,14 @@ def interface(self, session, entities, event): for job in jobs: try: data = json.loads(job["data"]) - desctiption = data["description"] + description = data["description"] except Exception: - desctiption = "*No description*" + description = "*No description*" user_id = job["user_id"] username = usernames_by_id.get(user_id) or "Unknown user" created = job["created_at"].strftime('%d.%m.%Y %H:%M:%S') label = "{} - {} - {}".format( - username, desctiption, created + username, description, created ) item_label = { "type": "label", diff --git a/openpype/modules/ftrack/event_handlers_user/action_prepare_project.py b/openpype/modules/ftrack/event_handlers_user/action_prepare_project.py index e8251981803..19d5701e084 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_prepare_project.py +++ b/openpype/modules/ftrack/event_handlers_user/action_prepare_project.py @@ -24,7 +24,7 @@ class PrepareProjectLocal(BaseAction): settings_key = "prepare_project" - # Key to store info about trigerring create folder structure + # Key to store info about triggering create folder structure create_project_structure_key = "create_folder_structure" create_project_structure_identifier = "create.project.structure" item_splitter = {"type": "label", "value": "---"} @@ -146,7 +146,7 @@ def prepare_root_items(self, project_anatom_settings): root_items.append({ "type": "label", "value": ( - "

    NOTE: Roots are crutial for path filling" + "

    NOTE: Roots are crucial for path filling" " (and creating folder structure).

    " ) }) diff --git a/openpype/modules/ftrack/event_handlers_user/action_rv.py b/openpype/modules/ftrack/event_handlers_user/action_rv.py index d05f0c47f6d..39cf33d6056 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_rv.py +++ b/openpype/modules/ftrack/event_handlers_user/action_rv.py @@ -66,7 +66,7 @@ def preregister(self): def get_components_from_entity(self, session, entity, components): """Get components from various entity types. - The components dictionary is modifid in place, so nothing is returned. + The components dictionary is modified in place, so nothing is returned. Args: entity (Ftrack entity) diff --git a/openpype/modules/ftrack/event_handlers_user/action_seed.py b/openpype/modules/ftrack/event_handlers_user/action_seed.py index 4021d70c0ac..657cd07a9fd 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_seed.py +++ b/openpype/modules/ftrack/event_handlers_user/action_seed.py @@ -325,8 +325,8 @@ def create_assets(self, project, asset_count): ): index = 0 - self.log.debug("*** Commiting Assets") - self.log.debug("Commiting entities. {}/{}".format( + self.log.debug("*** Committing Assets") + self.log.debug("Committing entities. {}/{}".format( created_entities, to_create_length )) self.session.commit() @@ -414,8 +414,8 @@ def create_shots(self, project, seq_count, shots_count): ): index = 0 - self.log.debug("*** Commiting Shots") - self.log.debug("Commiting entities. {}/{}".format( + self.log.debug("*** Committing Shots") + self.log.debug("Committing entities. {}/{}".format( created_entities, to_create_length )) self.session.commit() @@ -423,7 +423,7 @@ def create_shots(self, project, seq_count, shots_count): def temp_commit(self, index, created_entities, to_create_length): if index < self.max_entities_created_at_one_commit: return False - self.log.debug("Commiting {} entities. {}/{}".format( + self.log.debug("Committing {} entities. {}/{}".format( index, created_entities, to_create_length )) self.session.commit() diff --git a/openpype/modules/ftrack/event_handlers_user/action_store_thumbnails_to_avalon.py b/openpype/modules/ftrack/event_handlers_user/action_store_thumbnails_to_avalon.py index 8748f426bdc..c9e0901623b 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_store_thumbnails_to_avalon.py +++ b/openpype/modules/ftrack/event_handlers_user/action_store_thumbnails_to_avalon.py @@ -184,7 +184,7 @@ def launch(self, session, entities, event): self.db_con.install() for entity in entities: - # Skip if entity is not AssetVersion (never should happend, but..) + # Skip if entity is not AssetVersion (should never happen, but..) if entity.entity_type.lower() != "assetversion": continue diff --git a/openpype/modules/ftrack/ftrack_server/event_server_cli.py b/openpype/modules/ftrack/ftrack_server/event_server_cli.py index ad7ffd8e25f..77f479ee207 100644 --- a/openpype/modules/ftrack/ftrack_server/event_server_cli.py +++ b/openpype/modules/ftrack/ftrack_server/event_server_cli.py @@ -33,7 +33,7 @@ class MongoPermissionsError(Exception): """Is used when is created multiple objects of same RestApi class.""" def __init__(self, message=None): if not message: - message = "Exiting because have issue with acces to MongoDB" + message = "Exiting because have issue with access to MongoDB" super().__init__(message) @@ -340,7 +340,7 @@ def on_exit(processor_thread, storer_thread, statuser_thread): return 1 # ====== STORER ======= - # Run backup thread which does not requeire mongo to work + # Run backup thread which does not require mongo to work if storer_thread is None: if storer_failed_count < max_fail_count: storer_thread = socket_thread.SocketThread( @@ -399,7 +399,7 @@ def on_exit(processor_thread, storer_thread, statuser_thread): elif not processor_thread.is_alive(): if processor_thread.mongo_error: raise Exception( - "Exiting because have issue with acces to MongoDB" + "Exiting because have issue with access to MongoDB" ) processor_thread.join() processor_thread = None diff --git a/openpype/modules/ftrack/lib/avalon_sync.py b/openpype/modules/ftrack/lib/avalon_sync.py index 0341c257178..08dcf2e6715 100644 --- a/openpype/modules/ftrack/lib/avalon_sync.py +++ b/openpype/modules/ftrack/lib/avalon_sync.py @@ -891,7 +891,7 @@ def filter_by_ignore_sync(self): parent_dict = self.entities_dict.get(parent_id, {}) for child_id in parent_dict.get("children", []): - # keep original `remove` value for all childs + # keep original `remove` value for all children _remove = (remove is True) if not _remove: if self.entities_dict[child_id]["avalon_attrs"].get( @@ -1191,8 +1191,8 @@ def set_hierarchical_attribute( avalon_hier = [] for item in items: value = item["value"] - # WARNING It is not possible to propage enumerate hierachical - # attributes with multiselection 100% right. Unseting all values + # WARNING It is not possible to propagate enumerate hierarchical + # attributes with multiselection 100% right. Unsetting all values # will cause inheritance from parent. if ( value is None @@ -1231,7 +1231,7 @@ def set_hierarchical_attribute( items.append("{} - \"{}\"".format(ent_path, value)) self.report_items["error"][fps_msg] = items - # Get dictionary with not None hierarchical values to pull to childs + # Get dictionary with not None hierarchical values to pull to children top_id = self.ft_project_id project_values = {} for key, value in self.entities_dict[top_id]["hier_attrs"].items(): @@ -1749,7 +1749,7 @@ def prepare_changes(self): # TODO logging ent_path = self.get_ent_path(ftrack_id) msg = ( - " It is not possible" + " It is not possible" " to change the hierarchy of an entity or it's parents," " if it already contained published data." ) @@ -2584,7 +2584,7 @@ def delete_entities(self): # # ent_dict = self.entities_dict[found_by_name_id] - # TODO report - CRITICAL entity with same name alread exists in + # TODO report - CRITICAL entity with same name already exists in # different hierarchy - can't recreate entity continue diff --git a/openpype/modules/ftrack/lib/custom_attributes.py b/openpype/modules/ftrack/lib/custom_attributes.py index 2f538153680..3e40bb02f21 100644 --- a/openpype/modules/ftrack/lib/custom_attributes.py +++ b/openpype/modules/ftrack/lib/custom_attributes.py @@ -65,7 +65,7 @@ def get_openpype_attr(session, split_hierarchical=True, query_keys=None): cust_attrs_query = ( "select {}" " from CustomAttributeConfiguration" - # Kept `pype` for Backwards Compatiblity + # Kept `pype` for Backwards Compatibility " where group.name in (\"pype\", \"{}\")" ).format(", ".join(query_keys), CUST_ATTR_GROUP) all_avalon_attr = session.query(cust_attrs_query).all() diff --git a/openpype/modules/ftrack/lib/ftrack_action_handler.py b/openpype/modules/ftrack/lib/ftrack_action_handler.py index b24fe5f12ae..07b3a780a2b 100644 --- a/openpype/modules/ftrack/lib/ftrack_action_handler.py +++ b/openpype/modules/ftrack/lib/ftrack_action_handler.py @@ -12,7 +12,7 @@ def statics_icon(*icon_statics_file_parts): class BaseAction(BaseHandler): '''Custom Action base class - `label` a descriptive string identifing your action. + `label` a descriptive string identifying your action. `varaint` To group actions together, give them the same label and specify a unique variant per action. diff --git a/openpype/modules/ftrack/lib/ftrack_base_handler.py b/openpype/modules/ftrack/lib/ftrack_base_handler.py index c0b03f8a417..55400c22aba 100644 --- a/openpype/modules/ftrack/lib/ftrack_base_handler.py +++ b/openpype/modules/ftrack/lib/ftrack_base_handler.py @@ -30,7 +30,7 @@ def __init__(self, message=None): class BaseHandler(object): '''Custom Action base class - + + +
    +Data Exchanges: Point Cloud for 3dsMax #4532 + +Publish PRT format with tyFlow in 3dsmax + +Publish PRT format with tyFlow in 3dsmax and possibly set up loader to load the format too. +- [x] creator +- [x] extractor +- [x] validator +- [x] loader + + +___ + +
    + + +
    +Global: persistent staging directory for renders #4583 + +Allows configure if staging directory (`stagingDir`) should be persistent with use of profiles. + +With this feature, users can specify a transient data folder path based on presets, which can be used during the creation and publishing stages. In some cases, these DCCs automatically add a rendering path during the creation stage, which is then used in publishing.One of the key advantages of this feature is that it allows users to take advantage of faster storages for rendering, which can help improve workflow efficiency. Additionally, this feature allows users to keep their rendered data persistent, and use their own infrastructure for regular cleaning.However, it should be noted that some productions may want to use this feature without persistency. Furthermore, there may be a need for retargeting the rendering folder to faster storages, which is also not supported at the moment.It is studio responsibility to clean up obsolete folders with data.Location of the folder is configured in `project_anatomy/templates/others`. ('transient' key is expected, with 'folder' key, could be more templates)Which family/task type/subset is applicable is configured in:`project_settings/global/tools/publish/transient_dir_profiles` + + +___ + +
    + + +
    +Kitsu custom comment template #4599 + +Kitsu allows to write markdown in its comment field. This can be something very powerful to deliver dynamic comments with the help the data from the instance.This feature is defaults to off so the admin have to manually set up the comment field the way they want.I have added a basic example on how the comment can look like as the comment-fields default value.To this I want to add some documentation also but that's on its way when the code itself looks good for the reviewers. + + +___ + +
    + + +
    +MaxScene Family #4615 + +Introduction of the Max Scene Family + + +___ + +
    + +### **🚀 Enhancements** + + +
    +Maya: Multiple values on single render attribute - OP-4131 #4631 + +When validating render attributes, this adds support for multiple values. When repairing first value in list is used. + + +___ + +
    + + +
    +Maya: enable 2D Pan/Zoom for playblasts - OP-5213 #4687 + +Setting for enabling 2D Pan/Zoom on reviews. + + +___ + +
    + + +
    +Copy existing or generate new Fusion profile on prelaunch #4572 + +Fusion preferences will be copied to the predefined `~/.openpype/hosts/fusion/prefs` folder (or any other folder set in system settings) on launch. + +The idea is to create a copy of existing Fusion profile, adding an OpenPype menu to the Fusion instance.By default the copy setting is turned off, so no file copying is performed. Instead the clean Fusion profile is created by Fusion in the predefined folder. The default locaion is set to `~/.openpype/hosts/fusion/prefs`, to better comply with the other os platforms. After creating the default profile, some modifications are applied: +- forced Python3 +- forced English interface +- setup Openpype specific path maps.If the `copy_prefs` checkbox is toggled, a copy of existing Fusion profile folder will be placed in the mentioned location. Then they are altered the same way as described above. The operation is run only once, on the first launch, unless the `force_sync [Resync profile on each launch]` is toggled.English interface is forced because the `FUSION16_PROFILE_DIR` environment variable is not read otherwise (seems to be a Fusion bug). + + +___ + +
    + + +
    +Houdini: Create button open new publisher's "create" tab #4601 + +During a talk with @maxpareschi he mentioned that the new publisher in Houdini felt super confusing due to "Create" going to the older creator but now being completely empty and the publish button directly went to the publish tab.This resolves that by fixing the Create button to now open the new publisher but on the Create tab.Also made publish button enforce going to the "publish" tab for consistency in usage.@antirotor I think changing the Create button's callback was just missed in this commit or was there a specific reason to not change that around yet? + + +___ + +
    + + +
    +Clockify: refresh and fix the integration #4607 + +Due to recent API changes, Clockify requires `user_id` to operate with the timers. I updated this part and currently it is a WIP for making it fully functional. Most functions, such as start and stop timer, and projects sync are currently working. For the rate limiting task new dependency is added: https://pypi.org/project/ratelimiter/ + + +___ + +
    + + +
    +Fusion publish existing frames #4611 + +This PR adds the function to publish existing frames instead of having to re-render all of them for each new publish.I have split the render_locally plugin so the review-part is its own plugin now.I also change the saver-creator-plugin's label from Saver to Render (saver) as I intend to add a Prerender creator like in Nuke. + + +___ + +
    + + +
    +Resolution settings referenced from DB record for 3dsMax #4652 + +- Add Callback for setting the resolution according to DB after the new scene is created. +- Add a new Action into openpype menu which allows the user to reset the resolution in 3dsMax + + +___ + +
    + + +
    +3dsmax: render instance settings in Publish tab #4658 + +Allows user preset the pools, group and use_published settings in Render Creator in the Max Hosts.User can set the settings before or after creating instance in the new publisher + + +___ + +
    + + +
    +scene length setting referenced from DB record for 3dsMax #4665 + +Setting the timeline length based on DB record in 3dsMax Hosts + + +___ + +
    + + +
    +Publisher: Windows reduce command window pop-ups during Publishing #4672 + +Reduce the command line pop-ups that show on Windows during publishing. + + +___ + +
    + + +
    +Publisher: Explicit save #4676 + +Publisher have explicit button to save changes, so reset can happen without saving any changes. Save still happens automatically when publishing is started or on publisher window close. But a popup is shown if context of host has changed. Important context was enhanced by workfile path (if host integration supports it) so workfile changes are captured too. In that case a dialog with confirmation is shown to user. All callbacks that may require save of context were moved to main window to be able handle dialog show at one place. Save changes now returns success so the rest of logic is skipped -> publishing won't start, when save of instances fails.Save and reset buttons have shortcuts (Ctrl + s and Ctrls + r). + + +___ + +
    + + +
    +CelAction: conditional workfile parameters from settings #4677 + +Since some productions were requesting excluding some workfile parameters from publishing submission, we needed to move them to settings so those could be altered per project. + + +___ + +
    + + +
    +Improve logging of used app + tool envs on application launch #4682 + +Improve logging of what apps + tool environments got loaded for an application launch. + + +___ + +
    + + +
    +Fix name and docstring for Create Workdir Extra Folders prelaunch hook #4683 + +Fix class name and docstring for Create Workdir Extra Folders prelaunch hookThe class name and docstring were originally copied from another plug-in and didn't match the plug-in logic.This also fixes potentially seeing this twice in your logs. Before:After:Where it was actually running both this prelaunch hook and the actual `AddLastWorkfileToLaunchArgs` plugin. + + +___ + +
    + + +
    +Application launch context: Include app group name in logger #4684 + +Clarify in logs better what app group the ApplicationLaunchContext belongs to and what application is being launched.Before:After: + + +___ + +
    + + +
    +increment workfile version 3dsmax #4685 + +increment workfile version in 3dsmax as if in blender and maya hosts. + + +___ + +
    + +### **🐛 Bug fixes** + + +
    +Maya: Fix getting non-active model panel. #2968 + +When capturing multiple cameras with image planes that have file sequences playing, only the active (first) camera will play through the file sequence. + + +___ + +
    + + +
    +Maya: Fix broken review publishing. #4549 + +Resolves #4547 + + +___ + +
    + + +
    +Maya: Avoid error on right click in Loader if `mtoa` is not loaded #4616 + +Fix an error on right clicking in the Loader when `mtoa` is not a loaded plug-in.Additionally if `mtoa` isn't loaded the loader will now load the plug-in before trying to create the arnold standin. + + +___ + +
    + + +
    +Maya: Fix extract look colorspace detection #4618 + +Fix the logic which guesses the colorspace using `arnold` python library. +- Previously it'd error if `mtoa` was not available on path so it still required `mtoa` to be available. +- The guessing colorspace logic doesn't actually require `mtoa` to be loaded, but just the `arnold` python library to be available. This changes the logic so it doesn't require the `mtoa` plugin to get loaded to guess the colorspace. +- The if/else branch was likely not doing what was intended `cmds.loadPlugin("mtoa", quiet=True)` returns None if the plug-in was already loaded. So this would only ever be true if it ends up loading the `mtoa` plugin the first time. +```python +# Tested in Maya 2022.1 +print(cmds.loadPlugin("mtoa", quiet=True)) +# ['mtoa'] +print(cmds.loadPlugin("mtoa", quiet=True)) +# None +``` + + +___ + +
    + + +
    +Maya: Maya Playblast Options overrides - OP-3847 #4634 + +When publishing a review in Maya, the extractor would fail due to wrong (long) panel name. + + +___ + +
    + + +
    +Bugfix/op 2834 fix extract playblast #4701 + +Paragraphs contain detailed information on the changes made to the product or service, providing an in-depth description of the updates and enhancements. They can be used to explain the reasoning behind the changes, or to highlight the importance of the new features. Paragraphs can often include links to further information or support documentation. + + +___ + +
    + + +
    +Bugfix/op 2834 fix extract playblast #4704 + +Paragraphs contain detailed information on the changes made to the product or service, providing an in-depth description of the updates and enhancements. They can be used to explain the reasoning behind the changes, or to highlight the importance of the new features. Paragraphs can often include links to further information or support documentation. + + +___ + +
    + + +
    +Maya: bug fix for passing zoom settings if review is attached to subset #4716 + +Fix for attaching review to subset with pan/zoom option. + + +___ + +
    + + +
    +Maya: tile assembly fail in draft - OP-4820 #4416 + +Tile assembly in Deadline was broken. + +Initial bug report revealed other areas of the tile assembly that needed fixing. + + +___ + +
    + + +
    +Maya: Yeti Validate Rig Input - OP-3454 #4554 + +Fix Yeti Validate Rig Input + +Existing workflow was broken due to this #3297. + + +___ + +
    + + +
    +Scene inventory: Fix code errors when "not found" entries are found #4594 + +Whenever a "NOT FOUND" entry is present a lot of errors happened in the Scene Inventory: +- It started spamming a lot of errors for the VersionDelegate since it had no numeric version (no version at all).Error reported on Discord: +```python +Traceback (most recent call last): + File "C:\Users\videopro\Documents\github\OpenPype\openpype\tools\utils\delegates.py", line 65, in paint + text = self.displayText( + File "C:\Users\videopro\Documents\github\OpenPype\openpype\tools\utils\delegates.py", line 33, in displayText + assert isinstance(value, numbers.Integral), ( +AssertionError: Version is not integer. "None" +``` +- Right click menu would error on NOT FOUND entries, and thus not show. With this PR it will now _disregard_ not found items for "Set version" and "Remove" but still allow actions.This PR resolves those. + + +___ + +
    + + +
    +Kitsu: Sync OP with zou, make sure value-data is int or float #4596 + +Currently the data zou pulls is a string and not a value causing some bugs in the pipe where a value is expected (like `Set frame range` in Fusion). + + + +This PR makes sure each value is set with int() or float() so these bugs can't happen later on. + + + +_(A request to cgwire has also bin sent to allow force values only for some metadata columns, but currently the user can enter what ever they want in there)_ + + +___ + +
    + + +
    +Max: fix the bug of removing an instance #4617 + +fix the bug of removing an instance in 3dsMax + + +___ + +
    + + +
    +Global | Nuke: fixing farm publishing workflow #4623 + +After Nuke had adopted new publisher with new creators new issues were introduced. Those issues were addressed with this PR. Those are for example broken reviewable video files publishing if published via farm. Also fixed local publishing. + + +___ + +
    + + +
    +Ftrack: Ftrack additional families filtering #4633 + +Ftrack family collector makes sure the subset family is also in instance families for additional families filtering. + + +___ + +
    + + +
    +Ftrack: Hierarchical <> Non-Hierarchical attributes sync fix #4635 + +Sync between hierarchical and non-hierarchical attributes should be fixed and work as expected. Action should sync the values as expected and event handler should do it too and only on newly created entities. + + +___ + +
    + + +
    +bugfix for 3dsmax publishing error #4637 + +fix the bug of failing publishing job in 3dsMax + + +___ + +
    + + +
    +General: Use right validation for ffmpeg executable #4640 + +Use ffmpeg exec validation for ffmpeg executables instead of oiio exec validation. The validation is used as last possible source of ffmpeg from `PATH` environment variables, which is an edge case but can cause issues. + + +___ + +
    + + +
    +3dsmax: opening last workfile #4644 + +Supports opening last saved workfile in 3dsmax host. + + +___ + +
    + + +
    +Fixed a bug where a QThread in the splash screen could be destroyed before finishing execution #4647 + +This should fix the occasional behavior of the QThread being destroyed before even its worker returns from the `run()` function.After quiting, it should wait for the QThread object to properly close itself. + + +___ + +
    + + +
    +General: Use right plugin class for Collect Comment #4653 + +Collect Comment plugin is instance plugin so should inherit from `InstancePlugin` instead of `ContextPlugin`. + + +___ + +
    + + +
    +Global: add tags field to thumbnail representation #4660 + +Thumbnail representation might be missing tags field. + + +___ + +
    + + +
    +Integrator: Enforce unique destination transfers, disallow overwrites in queued transfers #4662 + +Fix #4656 by enforcing unique destination transfers in the Integrator. It's now disallowed to a destination in the file transaction queue with a new source path during the publish. + + +___ + +
    + + +
    +Hiero: Creator with correct workfile numeric padding input #4666 + +Creator was showing 99 in workfile input for long time, even if users set default value to 1001 in studio settings. This has been fixed now. + + +___ + +
    + + +
    +Nuke: Nukenodes family instance without frame range #4669 + +No need to add frame range data into `nukenodes` (backdrop) family publishes - since those are timeless. + + +___ + +
    + + +
    +TVPaint: Optional Validation plugins can be de/activated by user #4674 + +Added `OptionalPyblishPluginMixin` to TVpaint plugins that can be optional. + + +___ + +
    + + +
    +Kitsu: Slightly less strict with instance data #4678 + +- Allow to take task name from context if asset doesn't have any. Fixes an issue with Photoshop's review instance not having `task` in data. +- Allow to match "review" against both `instance.data["family"]` and `instance.data["families"]` because some instances don't have the primary family in families, e.g. in Photoshop and TVPaint. +- Do not error on Integrate Kitsu Review whenever for whatever reason Integrate Kitsu Note did not created a comment but just log the message that it was unable to connect a review. + + +___ + +
    + + +
    +Publisher: Fix reset shortcut sequence #4694 + +Fix bug created in https://github.com/ynput/OpenPype/pull/4676 where key sequence is checked using unsupported method. The check was changed to convert event into `QKeySequence` object which can be compared to prepared sequence. + + +___ + +
    + + +
    +Refactor _capture #4702 + +Paragraphs contain detailed information on the changes made to the product or service, providing an in-depth description of the updates and enhancements. They can be used to explain the reasoning behind the changes, or to highlight the importance of the new features. Paragraphs can often include links to further information or support documentation. + + +___ + +
    + + +
    +Hiero: correct container colors if UpToDate #4708 + +Colors on loaded containers are now correctly identifying real state of version. `Red` for out of date and `green` for up to date. + + +___ + +
    + +### **🔀 Refactored code** + + +
    +Look Assigner: Move Look Assigner tool since it's Maya only #4604 + +Fix #4357: Move Look Assigner tool to maya since it's Maya only + + +___ + +
    + + +
    +Maya: Remove unused functions from Extract Look #4671 + +Remove unused functions from Maya Extract Look plug-in + + +___ + +
    + + +
    +Extract Review code refactor #3930 + +Trying to reduce complexity of Extract Review plug-in +- Re-use profile filtering from lib +- Remove "combination families" additional filtering which supposedly was from OP v2 +- Simplify 'formatting' for filling gaps +- Use `legacy_io.Session` over `os.environ` + + +___ + +
    + + +
    +Maya: Replace last usages of Qt module #4610 + +Replace last usage of `Qt` module with `qtpy`. This change is needed for `PySide6` support. All changes happened in Maya loader plugins. + + +___ + +
    + + +
    +Update tests and documentation for `ColormanagedPyblishPluginMixin` #4612 + +Refactor `ExtractorColormanaged` to `ColormanagedPyblishPluginMixin` in tests and documentation. + + +___ + +
    + + +
    +Improve logging of used app + tool envs on application launch (minor tweak) #4686 + +Use `app.full_name` for change done in #4682 + + +___ + +
    + +### **📃 Documentation** + + +
    +Docs/add architecture document #4344 + +Add `ARCHITECTURE.md` document. + +his document attemps to give a quick overview of the project to help onboarding, it's not an extensive documentation but more of a elevator pitch one-line descriptions of files/directories and what the attempt to do. + + +___ + +
    + + +
    +Documentation: Tweak grammar and fix some typos #4613 + +This resolves some grammar and typos in the documentation.Also fixes the extension of some images in after effects docs which used uppercase extension even though files were lowercase extension. + + +___ + +
    + + +
    +Docs: Fix some minor grammar/typos #4680 + +Typo/grammar fixes in documentation. + + +___ + +
    + +### **Merged pull requests** + + +
    +Maya: Implement image file node loader #4313 + +Implements a loader for loading texture image into a `file` node in Maya. + +Similar to Maya's hypershade creation of textures on load you have the option to choose for three modes of creating: +- Texture +- Projection +- StencilThese should match what Maya generates if you create those in Maya. +- [x] Load and manage file nodes +- [x] Apply color spaces after #4195 +- [x] Support for _either_ UDIM or image sequence - currently it seems to always load sequences as UDIM automatically. +- [ ] Add support for animation sequences of UDIM textures using the `..exr` path format? + + +___ + +
    + + +
    +Maya Look Assigner: Don't rely on containers for get all assets #4600 + +This resolves #4044 by not actually relying on containers in the scene but instead just rely on finding nodes with `cbId` attributes. As such, imported nodes would also be found and a shader can be assigned (similar to when using get from selection).**Please take into consideration the potential downsides below**Potential downsides would be: +- IF an already loaded look has any dagNodes, say a 3D Projection node - then that will also show up as a loaded asset where previously nodes from loaded looks were ignored. +- If any dag nodes were created locally - they would have gotten `cbId` attributes on scene save and thus the current asset would almost always show? + + +___ + +
    + + +
    +Maya: Unify menu labels for "Set Frame Range" and "Set Resolution" #4605 + +Fix #4109: Unify menu labels for "Set Frame Range" and "Set Resolution"This also tweaks it in Houdini from Reset Frame Range to Set Frame Range. + + +___ + +
    + + +
    +Resolve missing OPENPYPE_MONGO in deadline global job preload #4484 + +In the GlobalJobPreLoad plugin, we propose to replace the SpawnProcess by a sub-process and to pass the environment variables in the parameters, since the SpawnProcess under Centos Linux does not pass the environment variables. + +In the GlobalJobPreLoad plugin, the Deadline SpawnProcess is used to start the OpenPype process. The problem is that the SpawnProcess does not pass environment variables, including OPENPYPE_MONGO, to the process when it is under Centos7 linux, and the process gets stuck. We propose to replace it by a subprocess and to pass the variable in the parameters. + + +___ + +
    + + +
    +Tests: Added setup_only to tests #4591 + +Allows to download test zip, unzip and restore DB in preparation for new test. + + +___ + +
    + + +
    +Maya: Arnold don't reset maya timeline frame range on render creation (or setting render settings) #4603 + +Fix #4429: Do not reset fps or playback timeline on applying or creating render settings + + +___ + +
    + + +
    +Bump @sideway/formula from 3.0.0 to 3.0.1 in /website #4609 + +Bumps [@sideway/formula](https://github.com/sideway/formula) from 3.0.0 to 3.0.1. +
    +Commits + +
    +
    +Maintainer changes +

    This version was pushed to npm by marsup, a new releaser for @​sideway/formula since your current version.

    +
    +
    + + +[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@sideway/formula&package-manager=npm_and_yarn&previous-version=3.0.0&new-version=3.0.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) + +Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. + +[//]: # (dependabot-automerge-start) +[//]: # (dependabot-automerge-end) + +--- + +
    +Dependabot commands and options +
    + +You can trigger Dependabot actions by commenting on this PR: +- `@dependabot rebase` will rebase this PR +- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it +- `@dependabot merge` will merge this PR after your CI passes on it +- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it +- `@dependabot cancel merge` will cancel a previously requested merge and block automerging +- `@dependabot reopen` will reopen this PR if it is closed +- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually +- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) +- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) +- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) +- `@dependabot use these labels` will set the current labels as the default for future PRs for this repo and language +- `@dependabot use these reviewers` will set the current reviewers as the default for future PRs for this repo and language +- `@dependabot use these assignees` will set the current assignees as the default for future PRs for this repo and language +- `@dependabot use this milestone` will set the current milestone as the default for future PRs for this repo and language + +You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/ynput/OpenPype/network/alerts). + +
    +___ + +
    + + +
    +Update artist_hosts_maya_arnold.md #4626 + +Correct Arnold docs. +___ + +
    + + +
    +Maya: Add "Include Parent Hierarchy" option in animation creator plugin #4645 + +Add an option in Project Settings > Maya > Creator Plugins > Create Animation to include (or not) parent hierarchy. This is to avoid artists to check manually the option for all create animation. + + +___ + +
    + + +
    +General: Filter available applications #4667 + +Added option to filter applications that don't have valid executable available in settings in launcher and ftrack actions. This option can be disabled in new settings category `Applications`. The filtering is by default disabled. + + +___ + +
    + + +
    +3dsmax: make sure that startup script executes #4695 + +Fixing reliability of OpenPype startup in 3dsmax. + + +___ + +
    + + +
    +Project Manager: Change minimum frame start/end to '0' #4719 + +Project manager can have frame start/end set to `0`. + + +___ + +
    + + + +## [3.15.2](https://github.com/ynput/OpenPype/tree/3.15.2) [Full Changelog](https://github.com/ynput/OpenPype/compare/3.15.1...3.15.2) diff --git a/openpype/hosts/hiero/api/lib.py b/openpype/hosts/hiero/api/lib.py index bbd1edc14a3..0d4368529f5 100644 --- a/openpype/hosts/hiero/api/lib.py +++ b/openpype/hosts/hiero/api/lib.py @@ -1221,7 +1221,7 @@ def set_track_color(track_item, color): def check_inventory_versions(track_items=None): """ - Actual version color idetifier of Loaded containers + Actual version color identifier of Loaded containers Check all track items and filter only Loader nodes for its version. It will get all versions from database @@ -1249,10 +1249,10 @@ def check_inventory_versions(track_items=None): project_name = legacy_io.active_project() filter_result = filter_containers(containers, project_name) for container in filter_result.latest: - set_track_color(container["_item"], clip_color) + set_track_color(container["_item"], clip_color_last) for container in filter_result.outdated: - set_track_color(container["_item"], clip_color_last) + set_track_color(container["_item"], clip_color) def selection_changed_timeline(event): diff --git a/openpype/hosts/houdini/plugins/publish/collect_current_file.py b/openpype/hosts/houdini/plugins/publish/collect_current_file.py index 9cca07fdc7c..caf679f98be 100644 --- a/openpype/hosts/houdini/plugins/publish/collect_current_file.py +++ b/openpype/hosts/houdini/plugins/publish/collect_current_file.py @@ -1,7 +1,6 @@ import os import hou -from openpype.pipeline import legacy_io import pyblish.api @@ -11,7 +10,7 @@ class CollectHoudiniCurrentFile(pyblish.api.InstancePlugin): order = pyblish.api.CollectorOrder - 0.01 label = "Houdini Current File" hosts = ["houdini"] - family = ["workfile"] + families = ["workfile"] def process(self, instance): """Inject the current working file""" @@ -21,7 +20,7 @@ def process(self, instance): # By default, Houdini will even point a new scene to a path. # However if the file is not saved at all and does not exist, # we assume the user never set it. - filepath = "" + current_file = "" elif os.path.basename(current_file) == "untitled.hip": # Due to even a new file being called 'untitled.hip' we are unable diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index 39657a25256..ac7d75db086 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -182,7 +182,6 @@ def reset_scene_resolution(): scene resolution can be overwritten by an asset if the asset.data contains any information regarding scene resolution . - Returns: None """ @@ -200,6 +199,59 @@ def reset_scene_resolution(): set_scene_resolution(width, height) +def get_frame_range() -> dict: + """Get the current assets frame range and handles. + + Returns: + dict: with frame start, frame end, handle start, handle end. + """ + # Set frame start/end + asset = get_current_project_asset() + frame_start = asset["data"].get("frameStart") + frame_end = asset["data"].get("frameEnd") + # Backwards compatibility + if frame_start is None or frame_end is None: + frame_start = asset["data"].get("edit_in") + frame_end = asset["data"].get("edit_out") + if frame_start is None or frame_end is None: + return + handles = asset["data"].get("handles") or 0 + handle_start = asset["data"].get("handleStart") + if handle_start is None: + handle_start = handles + handle_end = asset["data"].get("handleEnd") + if handle_end is None: + handle_end = handles + return { + "frameStart": frame_start, + "frameEnd": frame_end, + "handleStart": handle_start, + "handleEnd": handle_end + } + + +def reset_frame_range(fps: bool = True): + """Set frame range to current asset. + This is part of 3dsmax documentation: + + animationRange: A System Global variable which lets you get and + set an Interval value that defines the start and end frames + of the Active Time Segment. + frameRate: A System Global variable which lets you get + and set an Integer value that defines the current + scene frame rate in frames-per-second. + """ + if fps: + data_fps = get_current_project(fields=["data.fps"]) + fps_number = float(data_fps["data"]["fps"]) + rt.frameRate = fps_number + frame_range = get_frame_range() + frame_start = frame_range["frameStart"] - int(frame_range["handleStart"]) + frame_end = frame_range["frameEnd"] + int(frame_range["handleEnd"]) + frange_cmd = f"animationRange = interval {frame_start} {frame_end}" + rt.execute(frange_cmd) + + def set_context_setting(): """Apply the project settings from the project definition diff --git a/openpype/hosts/max/api/menu.py b/openpype/hosts/max/api/menu.py index 1f189723945..066cc900394 100644 --- a/openpype/hosts/max/api/menu.py +++ b/openpype/hosts/max/api/menu.py @@ -6,6 +6,7 @@ from openpype.tools.utils import host_tools from openpype.hosts.max.api import lib + class OpenPypeMenu(object): """Object representing OpenPype menu. @@ -114,6 +115,10 @@ def build_openpype_menu(self) -> QtWidgets.QAction: res_action.triggered.connect(self.resolution_callback) openpype_menu.addAction(res_action) + frame_action = QtWidgets.QAction("Set Frame Range", openpype_menu) + frame_action.triggered.connect(self.frame_range_callback) + openpype_menu.addAction(frame_action) + return openpype_menu def load_callback(self): @@ -139,3 +144,7 @@ def workfiles_callback(self): def resolution_callback(self): """Callback to reset scene resolution""" return lib.reset_scene_resolution() + + def frame_range_callback(self): + """Callback to reset frame range""" + return lib.reset_frame_range() diff --git a/openpype/hosts/max/plugins/publish/collect_render.py b/openpype/hosts/max/plugins/publish/collect_render.py index 7c9e311c2fb..63e4108c849 100644 --- a/openpype/hosts/max/plugins/publish/collect_render.py +++ b/openpype/hosts/max/plugins/publish/collect_render.py @@ -61,7 +61,7 @@ def process(self, instance): "plugin": "3dsmax", "frameStart": context.data['frameStart'], "frameEnd": context.data['frameEnd'], - "version": version_int + "version": version_int, } self.log.info("data: {0}".format(data)) instance.data.update(data) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index aa1e501578c..1a62e7dbc31 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -2478,8 +2478,8 @@ def load_capture_preset(data=None): float(value[2]) / 255 ] disp_options[key] = value - else: - disp_options['displayGradient'] = True + elif key == "displayGradient": + disp_options[key] = value options['display_options'] = disp_options diff --git a/openpype/hosts/maya/plugins/load/load_reference.py b/openpype/hosts/maya/plugins/load/load_reference.py index d93702a16d6..82c15ab8994 100644 --- a/openpype/hosts/maya/plugins/load/load_reference.py +++ b/openpype/hosts/maya/plugins/load/load_reference.py @@ -1,4 +1,6 @@ import os +import difflib +import contextlib from maya import cmds from openpype.settings import get_project_settings @@ -8,7 +10,82 @@ get_legacy_creator_by_name, ) import openpype.hosts.maya.api.plugin -from openpype.hosts.maya.api.lib import maintained_selection +from openpype.hosts.maya.api.lib import ( + maintained_selection, + get_container_members +) + + +@contextlib.contextmanager +def preserve_modelpanel_cameras(container, log=None): + """Preserve camera members of container in the modelPanels. + + This is used to ensure a camera remains in the modelPanels after updating + to a new version. + + """ + + # Get the modelPanels that used the old camera + members = get_container_members(container) + old_cameras = set(cmds.ls(members, type="camera", long=True)) + if not old_cameras: + # No need to manage anything + yield + return + + panel_cameras = {} + for panel in cmds.getPanel(type="modelPanel"): + cam = cmds.ls(cmds.modelPanel(panel, query=True, camera=True), + long=True) + + # Often but not always maya returns the transform from the + # modelPanel as opposed to the camera shape, so we convert it + # to explicitly be the camera shape + if cmds.nodeType(cam) != "camera": + cam = cmds.listRelatives(cam, + children=True, + fullPath=True, + type="camera")[0] + if cam in old_cameras: + panel_cameras[panel] = cam + + if not panel_cameras: + # No need to manage anything + yield + return + + try: + yield + finally: + new_members = get_container_members(container) + new_cameras = set(cmds.ls(new_members, type="camera", long=True)) + if not new_cameras: + return + + for panel, cam_name in panel_cameras.items(): + new_camera = None + if cam_name in new_cameras: + new_camera = cam_name + elif len(new_cameras) == 1: + new_camera = next(iter(new_cameras)) + else: + # Multiple cameras in the updated container but not an exact + # match detected by name. Find the closest match + matches = difflib.get_close_matches(word=cam_name, + possibilities=new_cameras, + n=1) + if matches: + new_camera = matches[0] # best match + if log: + log.info("Camera in '{}' restored with " + "closest match camera: {} (before: {})" + .format(panel, new_camera, cam_name)) + + if not new_camera: + # Unable to find the camera to re-apply in the modelpanel + continue + + cmds.modelPanel(panel, edit=True, camera=new_camera) class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): @@ -68,6 +145,9 @@ def process_reference(self, context, name, namespace, options): new_nodes = (list(set(nodes) - set(shapes))) + # if there are cameras, try to lock their transforms + self._lock_camera_transforms(new_nodes) + current_namespace = pm.namespaceInfo(currentNamespace=True) if current_namespace != ":": @@ -136,6 +216,15 @@ def process_reference(self, context, name, namespace, options): def switch(self, container, representation): self.update(container, representation) + def update(self, container, representation): + with preserve_modelpanel_cameras(container, log=self.log): + super(ReferenceLoader, self).update(container, representation) + + # We also want to lock camera transforms on any new cameras in the + # reference or for a camera which might have changed names. + members = get_container_members(container) + self._lock_camera_transforms(members) + def _post_process_rig(self, name, namespace, context, options): output = next((node for node in self if @@ -168,3 +257,18 @@ def _post_process_rig(self, name, namespace, context, options): options={"useSelection": True}, data={"dependencies": dependency} ) + + def _lock_camera_transforms(self, nodes): + cameras = cmds.ls(nodes, type="camera") + if not cameras: + return + + # Check the Maya version, lockTransform has been introduced since + # Maya 2016.5 Ext 2 + version = int(cmds.about(version=True)) + if version >= 2016: + for camera in cameras: + cmds.camera(camera, edit=True, lockTransform=True) + else: + self.log.warning("This version of Maya does not support locking of" + " transforms of cameras.") diff --git a/openpype/lib/execute.py b/openpype/lib/execute.py index 7a929a0ade1..6f9a0952851 100644 --- a/openpype/lib/execute.py +++ b/openpype/lib/execute.py @@ -8,6 +8,8 @@ from .log import Logger from .vendor_bin_utils import find_executable +from .openpype_version import is_running_from_build + # MSDN process creation flag (Windows only) CREATE_NO_WINDOW = 0x08000000 @@ -200,6 +202,11 @@ def run_openpype_process(*args, **kwargs): # Skip envs that can affect OpenPype process # - fill more if you find more env = clean_envs_for_openpype_process(os.environ) + + # Only keep OpenPype version if we are running from build. + if not is_running_from_build(): + env.pop("OPENPYPE_VERSION", None) + return run_subprocess(args, env=env, **kwargs) diff --git a/openpype/modules/deadline/plugins/publish/collect_pools.py b/openpype/modules/deadline/plugins/publish/collect_pools.py index 48130848d51..e221eb00ea6 100644 --- a/openpype/modules/deadline/plugins/publish/collect_pools.py +++ b/openpype/modules/deadline/plugins/publish/collect_pools.py @@ -3,21 +3,60 @@ """ import pyblish.api +from openpype.lib import TextDef +from openpype.pipeline.publish import OpenPypePyblishPluginMixin -class CollectDeadlinePools(pyblish.api.InstancePlugin): +class CollectDeadlinePools(pyblish.api.InstancePlugin, + OpenPypePyblishPluginMixin): """Collect pools from instance if present, from Setting otherwise.""" order = pyblish.api.CollectorOrder + 0.420 label = "Collect Deadline Pools" - families = ["rendering", "render.farm", "renderFarm", "renderlayer"] + families = ["rendering", + "render.farm", + "renderFarm", + "renderlayer", + "maxrender"] primary_pool = None secondary_pool = None + @classmethod + def apply_settings(cls, project_settings, system_settings): + # deadline.publish.CollectDeadlinePools + settings = project_settings["deadline"]["publish"]["CollectDeadlinePools"] # noqa + cls.primary_pool = settings.get("primary_pool", None) + cls.secondary_pool = settings.get("secondary_pool", None) + def process(self, instance): + + attr_values = self.get_attr_values_from_data(instance.data) if not instance.data.get("primaryPool"): - instance.data["primaryPool"] = self.primary_pool or "none" + instance.data["primaryPool"] = ( + attr_values.get("primaryPool") or self.primary_pool or "none" + ) if not instance.data.get("secondaryPool"): - instance.data["secondaryPool"] = self.secondary_pool or "none" + instance.data["secondaryPool"] = ( + attr_values.get("secondaryPool") or self.secondary_pool or "none" # noqa + ) + + @classmethod + def get_attribute_defs(cls): + # TODO: Preferably this would be an enum for the user + # but the Deadline server URL can be dynamic and + # can be set per render instance. Since get_attribute_defs + # can't be dynamic unfortunately EnumDef isn't possible (yet?) + # pool_names = self.deadline_module.get_deadline_pools(deadline_url, + # self.log) + # secondary_pool_names = ["-"] + pool_names + + return [ + TextDef("primaryPool", + label="Primary Pool", + default=cls.primary_pool), + TextDef("secondaryPool", + label="Secondary Pool", + default=cls.secondary_pool) + ] diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index 417a03de744..c728b6b9c72 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -3,7 +3,15 @@ import copy import attr -from openpype.pipeline import legacy_io +from openpype.lib import ( + TextDef, + BoolDef, + NumberDef, +) +from openpype.pipeline import ( + legacy_io, + OpenPypePyblishPluginMixin +) from openpype.settings import get_project_settings from openpype.hosts.max.api.lib import ( get_current_renderer, @@ -22,7 +30,8 @@ class MaxPluginInfo(object): IgnoreInputs = attr.ib(default=True) -class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline): +class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, + OpenPypePyblishPluginMixin): label = "Submit Render to Deadline" hosts = ["max"] @@ -31,14 +40,22 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline): use_published = True priority = 50 - tile_priority = 50 chunk_size = 1 jobInfo = {} pluginInfo = {} group = None - deadline_pool = None - deadline_pool_secondary = None - framePerTask = 1 + + @classmethod + def apply_settings(cls, project_settings, system_settings): + settings = project_settings["deadline"]["publish"]["MaxSubmitDeadline"] # noqa + + # Take some defaults from settings + cls.use_published = settings.get("use_published", + cls.use_published) + cls.priority = settings.get("priority", + cls.priority) + cls.chuck_size = settings.get("chunk_size", cls.chunk_size) + cls.group = settings.get("group", cls.group) def get_job_info(self): job_info = DeadlineJobInfo(Plugin="3dsmax") @@ -49,11 +66,11 @@ def get_job_info(self): instance = self._instance context = instance.context - # Always use the original work file name for the Job name even when # rendering is done from the published Work File. The original work # file name is clearer because it can also have subversion strings, # etc. which are stripped for the published file. + src_filepath = context.data["currentFile"] src_filename = os.path.basename(src_filepath) @@ -71,13 +88,13 @@ def get_job_info(self): job_info.Pool = instance.data.get("primaryPool") job_info.SecondaryPool = instance.data.get("secondaryPool") - job_info.ChunkSize = instance.data.get("chunkSize", 1) - job_info.Comment = context.data.get("comment") - job_info.Priority = instance.data.get("priority", self.priority) - job_info.FramesPerTask = instance.data.get("framesPerTask", 1) - if self.group: - job_info.Group = self.group + attr_values = self.get_attr_values_from_data(instance.data) + + job_info.ChunkSize = attr_values.get("chunkSize", 1) + job_info.Comment = context.data.get("comment") + job_info.Priority = attr_values.get("priority", self.priority) + job_info.Group = attr_values.get("group", self.group) # Add options from RenderGlobals render_globals = instance.data.get("renderGlobals", {}) @@ -216,3 +233,32 @@ def _clean_name(path): plugin_info.update(plugin_data) return job_info, plugin_info + + @classmethod + def get_attribute_defs(cls): + defs = super(MaxSubmitDeadline, cls).get_attribute_defs() + defs.extend([ + BoolDef("use_published", + default=cls.use_published, + label="Use Published Scene"), + + NumberDef("priority", + minimum=1, + maximum=250, + decimals=0, + default=cls.priority, + label="Priority"), + + NumberDef("chunkSize", + minimum=1, + maximum=50, + decimals=0, + default=cls.chunk_size, + label="Frame Per Task"), + + TextDef("group", + default=cls.group, + label="Group Name"), + ]) + + return defs diff --git a/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py b/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py index 05afa5080d8..7c8ab62d4d8 100644 --- a/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py +++ b/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py @@ -17,7 +17,11 @@ class ValidateDeadlinePools(OptionalPyblishPluginMixin, label = "Validate Deadline Pools" order = pyblish.api.ValidatorOrder - families = ["rendering", "render.farm", "renderFarm", "renderlayer"] + families = ["rendering", + "render.farm", + "renderFarm", + "renderlayer", + "maxrender"] optional = True def process(self, instance): diff --git a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py index 6be14b3bdf1..f8e56377bb8 100644 --- a/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py +++ b/openpype/modules/kitsu/plugins/publish/integrate_kitsu_note.py @@ -14,7 +14,10 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin): # status settings set_status_note = False note_status_shortname = "wfa" - status_conditions = list() + status_change_conditions = { + "status_conditions": [], + "family_requirements": [], + } # comment settings custom_comment_template = { @@ -55,7 +58,7 @@ def process(self, context): continue kitsu_task = instance.data.get("kitsu_task") - if kitsu_task is None: + if not kitsu_task: continue # Get note status, by default uses the task status for the note @@ -65,13 +68,39 @@ def process(self, context): # Check if any status condition is not met allow_status_change = True - for status_cond in self.status_conditions: + for status_cond in self.status_change_conditions[ + "status_conditions" + ]: condition = status_cond["condition"] == "equal" match = status_cond["short_name"].upper() == shortname if match and not condition or condition and not match: allow_status_change = False break + if allow_status_change: + # Get families + families = { + instance.data.get("family") + for instance in context + if instance.data.get("publish") + } + + # Check if any family requirement is met + for family_requirement in self.status_change_conditions[ + "family_requirements" + ]: + condition = family_requirement["condition"] == "equal" + + for family in families: + match = family_requirement["family"].lower() == family + if match and not condition or condition and not match: + allow_status_change = False + break + + if allow_status_change: + break + + # Set note status if self.set_status_note and allow_status_change: kitsu_status = gazu.task.get_task_status_by_short_name( self.note_status_shortname diff --git a/openpype/plugins/publish/extract_burnin.py b/openpype/plugins/publish/extract_burnin.py index 44ba4a5025d..95575444b27 100644 --- a/openpype/plugins/publish/extract_burnin.py +++ b/openpype/plugins/publish/extract_burnin.py @@ -252,6 +252,9 @@ def main_process(self, instance): # Add context data burnin_data. burnin_data["custom"] = custom_data + # Add data members. + burnin_data.update(instance.data.get("burninDataMembers", {})) + # Add source camera name to burnin data camera_name = repre.get("camera_name") if camera_name: diff --git a/openpype/scripts/otio_burnin.py b/openpype/scripts/otio_burnin.py index ef449f4f74e..d0a42669412 100644 --- a/openpype/scripts/otio_burnin.py +++ b/openpype/scripts/otio_burnin.py @@ -4,8 +4,10 @@ import subprocess import platform import json -import opentimelineio_contrib.adapters.ffmpeg_burnins as ffmpeg_burnins +import tempfile +from string import Formatter +import opentimelineio_contrib.adapters.ffmpeg_burnins as ffmpeg_burnins from openpype.lib import ( get_ffmpeg_tool_path, get_ffmpeg_codec_args, @@ -23,7 +25,7 @@ ).format(ffmpeg_path) DRAWTEXT = ( - "drawtext=fontfile='%(font)s':text=\\'%(text)s\\':" + "drawtext@'%(label)s'=fontfile='%(font)s':text=\\'%(text)s\\':" "x=%(x)s:y=%(y)s:fontcolor=%(color)s@%(opacity).1f:fontsize=%(size)d" ) TIMECODE = ( @@ -39,6 +41,45 @@ SOURCE_TIMECODE_KEY = "{source_timecode}" +def convert_list_to_command(list_to_convert, fps, label=""): + """Convert a list of values to a drawtext command file for ffmpeg `sendcmd` + + The list of values is expected to have a value per frame. If the video + file ends up being longer than the amount of samples per frame than the + last value will be held. + + Args: + list_to_convert (list): List of values per frame. + fps (float or int): The expected frame per seconds of the output file. + label (str): Label for the drawtext, if specific drawtext filter is + required + + Returns: + str: Filepath to the temporary drawtext command file. + + """ + + with tempfile.NamedTemporaryFile(mode="w", delete=False) as f: + for i, value in enumerate(list_to_convert): + seconds = i / fps + + # Escape special character + value = str(value).replace(":", "\\:") + + filter = "drawtext" + if label: + filter += "@" + label + + line = ( + "{start} {filter} reinit text='{value}';" + "\n".format(start=seconds, filter=filter, value=value) + ) + + f.write(line) + f.flush() + return f.name + + def _get_ffprobe_data(source): """Reimplemented from otio burnins to be able use full path to ffprobe :param str source: source media file @@ -144,7 +185,13 @@ def __init__( self.options_init.update(options_init) def add_text( - self, text, align, frame_start=None, frame_end=None, options=None + self, + text, + align, + frame_start=None, + frame_end=None, + options=None, + cmd="" ): """ Adding static text to a filter. @@ -165,7 +212,13 @@ def add_text( if frame_end is not None: options["frame_end"] = frame_end - self._add_burnin(text, align, options, DRAWTEXT) + draw_text = DRAWTEXT + if cmd: + draw_text = "{}, {}".format(cmd, DRAWTEXT) + + options["label"] = align + + self._add_burnin(text, align, options, draw_text) def add_timecode( self, align, frame_start=None, frame_end=None, frame_start_tc=None, @@ -408,11 +461,13 @@ def burnins_from_data( True by default. Presets must be set separately. Should be dict with 2 keys: - - "options" - sets look of burnins - colors, opacity,...(more info: ModifiedBurnins doc) + - "options" - sets look of burnins - colors, opacity,... + (more info: ModifiedBurnins doc) - *OPTIONAL* default values are used when not included - "burnins" - contains dictionary with burnins settings - *OPTIONAL* burnins won't be added (easier is not to use this) - - each key of "burnins" represents Alignment, there are 6 possibilities: + - each key of "burnins" represents Alignment, + there are 6 possibilities: TOP_LEFT TOP_CENTERED TOP_RIGHT BOTTOM_LEFT BOTTOM_CENTERED BOTTOM_RIGHT - value must be string with text you want to burn-in @@ -491,13 +546,14 @@ def burnins_from_data( if source_timecode is not None: data[SOURCE_TIMECODE_KEY[1:-1]] = SOURCE_TIMECODE_KEY + clean_up_paths = [] for align_text, value in burnin_values.items(): if not value: continue - if isinstance(value, (dict, list, tuple)): + if isinstance(value, dict): raise TypeError(( - "Expected string or number type." + "Expected string, number or list type." " Got: {} - \"{}\"" " (Make sure you have new burnin presets)." ).format(str(type(value)), str(value))) @@ -533,8 +589,48 @@ def burnins_from_data( print("Source does not have set timecode value.") value = value.replace(SOURCE_TIMECODE_KEY, MISSING_KEY_VALUE) - key_pattern = re.compile(r"(\{.*?[^{0]*\})") + # Convert lists. + cmd = "" + text = None + keys = [i[1] for i in Formatter().parse(value) if i[1] is not None] + list_to_convert = [] + # Warn about nested dictionary support for lists. Ei. we dont support + # it. + if "[" in "".join(keys): + print( + "We dont support converting nested dictionaries to lists," + " so skipping {}".format(value) + ) + else: + for key in keys: + data_value = data[key] + + # Multiple lists are not supported. + if isinstance(data_value, list) and list_to_convert: + raise ValueError( + "Found multiple lists to convert, which is not " + "supported: {}".format(value) + ) + + if isinstance(data_value, list): + print("Found list to convert: {}".format(data_value)) + for v in data_value: + data[key] = v + list_to_convert.append(value.format(**data)) + + if list_to_convert: + value = list_to_convert[0] + path = convert_list_to_command( + list_to_convert, data["fps"], label=align + ) + cmd = "sendcmd=f='{}'".format(path) + cmd = cmd.replace("\\", "/") + cmd = cmd.replace(":", "\\:") + clean_up_paths.append(path) + + # Failsafe for missing keys. + key_pattern = re.compile(r"(\{.*?[^{0]*\})") missing_keys = [] for group in key_pattern.findall(value): try: @@ -568,7 +664,8 @@ def burnins_from_data( continue text = value.format(**data) - burnin.add_text(text, align, frame_start, frame_end) + + burnin.add_text(text, align, frame_start, frame_end, cmd=cmd) ffmpeg_args = [] if codec_data: @@ -599,6 +696,8 @@ def burnins_from_data( burnin.render( output_path, args=ffmpeg_args_str, overwrite=overwrite, **data ) + for path in clean_up_paths: + os.remove(path) if __name__ == "__main__": diff --git a/openpype/settings/defaults/project_settings/deadline.json b/openpype/settings/defaults/project_settings/deadline.json index 0cbd3232993..fdd70f1a44a 100644 --- a/openpype/settings/defaults/project_settings/deadline.json +++ b/openpype/settings/defaults/project_settings/deadline.json @@ -43,10 +43,7 @@ "use_published": true, "priority": 50, "chunk_size": 10, - "group": "none", - "deadline_pool": "", - "deadline_pool_secondary": "", - "framePerTask": 1 + "group": "none" }, "NukeSubmitDeadline": { "enabled": true, diff --git a/openpype/settings/defaults/project_settings/global.json b/openpype/settings/defaults/project_settings/global.json index aba840da786..30e56300d13 100644 --- a/openpype/settings/defaults/project_settings/global.json +++ b/openpype/settings/defaults/project_settings/global.json @@ -249,6 +249,29 @@ } } } + }, + { + "families": [], + "hosts": [ + "maya" + ], + "task_types": [], + "task_names": [], + "subsets": [], + "burnins": { + "maya_burnin": { + "TOP_LEFT": "{yy}-{mm}-{dd}", + "TOP_CENTERED": "{focalLength:.2f} mm", + "TOP_RIGHT": "{anatomy[version]}", + "BOTTOM_LEFT": "{username}", + "BOTTOM_CENTERED": "{asset}", + "BOTTOM_RIGHT": "{frame_start}-{current_frame}-{frame_end}", + "filter": { + "families": [], + "tags": [] + } + } + } } ] }, diff --git a/openpype/settings/defaults/project_settings/kitsu.json b/openpype/settings/defaults/project_settings/kitsu.json index 0638450595a..59a36d8b97d 100644 --- a/openpype/settings/defaults/project_settings/kitsu.json +++ b/openpype/settings/defaults/project_settings/kitsu.json @@ -8,7 +8,10 @@ "IntegrateKitsuNote": { "set_status_note": false, "note_status_shortname": "wfa", - "status_conditions": [], + "status_change_conditions": { + "status_conditions": [], + "family_requirements": [] + }, "custom_comment_template": { "enabled": false, "comment_template": "{comment}\n\n| | |\n|--|--|\n| version| `{version}` |\n| family | `{family}` |\n| name | `{name}` |" diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index e914eb29f98..fda053e6e6a 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -795,6 +795,7 @@ "quality": 95 }, "Display Options": { + "override_display": true, "background": [ 125, 125, @@ -813,7 +814,7 @@ 125, 255 ], - "override_display": true + "displayGradient": true }, "Generic": { "isolate_view": true, diff --git a/openpype/settings/defaults/system_settings/applications.json b/openpype/settings/defaults/system_settings/applications.json index 5fd9b926fb1..eb3a88ce665 100644 --- a/openpype/settings/defaults/system_settings/applications.json +++ b/openpype/settings/defaults/system_settings/applications.json @@ -133,7 +133,7 @@ "linux": [] }, "arguments": { - "windows": [], + "windows": ["-U MAXScript {OPENPYPE_ROOT}\\openpype\\hosts\\max\\startup\\startup.ms"], "darwin": [], "linux": [] }, diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json b/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json index 9906939cc73..d8b5e4dc1fa 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_deadline.json @@ -239,27 +239,12 @@ { "type": "number", "key": "chunk_size", - "label": "Chunk Size" + "label": "Frame per Task" }, { "type": "text", "key": "group", "label": "Group Name" - }, - { - "type": "text", - "key": "deadline_pool", - "label": "Deadline pool" - }, - { - "type": "text", - "key": "deadline_pool_secondary", - "label": "Deadline pool (secondary)" - }, - { - "type": "number", - "key": "framePerTask", - "label": "Frame Per Task" } ] }, diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json index ee309f63a72..8aeed00542e 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -54,30 +54,62 @@ "label": "Note shortname" }, { - "type": "list", - "key": "status_conditions", - "label": "Status conditions", - "object_type": { - "type": "dict", - "key": "conditions_dict", - "children": [ - { - "type": "enum", - "key": "condition", - "label": "Condition", - "enum_items": [ - {"equal": "Equal"}, - {"not_equal": "Not equal"} + "type": "dict", + "collapsible": true, + "key": "status_change_conditions", + "label": "Status change conditions", + "children": [ + { + "type": "list", + "key": "status_conditions", + "label": "Status conditions", + "object_type": { + "type": "dict", + "key": "condition_dict", + "children": [ + { + "type": "enum", + "key": "condition", + "label": "Condition", + "enum_items": [ + {"equal": "Equal"}, + {"not_equal": "Not equal"} + ] + }, + { + "type": "text", + "key": "short_name", + "label": "Short name" + } ] - }, - { - "type": "text", - "key": "short_name", - "label": "Short name" } - ] - }, - "label": "Status shortname" + }, + { + "type": "list", + "key": "family_requirements", + "label": "Family requirements", + "object_type": { + "type": "dict", + "key": "requirement_dict", + "children": [ + { + "type": "enum", + "key": "condition", + "label": "Condition", + "enum_items": [ + {"equal": "Equal"}, + {"not_equal": "Not equal"} + ] + }, + { + "type": "text", + "key": "family", + "label": "Family" + } + ] + } + } + ] }, { "type": "dict", diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json index dec5a5cdc26..a4a986bad89 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json @@ -19,12 +19,12 @@ { "type": "text", "key": "compression", - "label": "Compression type" + "label": "Encoding" }, { "type": "text", "key": "format", - "label": "Data format" + "label": "Format" }, { "type": "number", @@ -48,7 +48,11 @@ "type": "label", "label": "Display Options" }, - + { + "type": "boolean", + "key": "override_display", + "label": "Override display options" + }, { "type": "color", "key": "background", @@ -66,8 +70,8 @@ }, { "type": "boolean", - "key": "override_display", - "label": "Override display options" + "key": "displayGradient", + "label": "Display background gradient" } ] }, diff --git a/openpype/tools/project_manager/project_manager/view.py b/openpype/tools/project_manager/project_manager/view.py index b35491c5b21..2cf11b702d8 100644 --- a/openpype/tools/project_manager/project_manager/view.py +++ b/openpype/tools/project_manager/project_manager/view.py @@ -72,8 +72,8 @@ class HierarchyView(QtWidgets.QTreeView): column_delegate_defs = { "name": NameDef(), "type": TypeDef(), - "frameStart": NumberDef(1), - "frameEnd": NumberDef(1), + "frameStart": NumberDef(0), + "frameEnd": NumberDef(0), "fps": NumberDef(1, decimals=3, step=1), "resolutionWidth": NumberDef(0), "resolutionHeight": NumberDef(0), diff --git a/openpype/version.py b/openpype/version.py index bc5ea7fe7ca..4d6ee5590e3 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.15.3-nightly.4" +__version__ = "3.15.4-nightly.1" diff --git a/pyproject.toml b/pyproject.toml index 02370a4f10d..42ce5aa32c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "OpenPype" -version = "3.15.2" # OpenPype +version = "3.15.3" # OpenPype description = "Open VFX and Animation pipeline with support." authors = ["OpenPype Team "] license = "MIT License" diff --git a/website/docs/assets/integrate_kitsu_note_settings.png b/website/docs/assets/integrate_kitsu_note_settings.png index 127e79ab8063dae0408f90a82d6bb4b5e233ed47..9c59f0bf5cc9a748de1a8b66b248f539ee8014b5 100644 GIT binary patch literal 48874 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 diff --git a/website/docs/module_kitsu.md b/website/docs/module_kitsu.md index 23898fba2e7..05cff87fccc 100644 --- a/website/docs/module_kitsu.md +++ b/website/docs/module_kitsu.md @@ -43,10 +43,11 @@ Task status can be automatically set during publish thanks to `Integrate Kitsu N `Admin -> Studio Settings -> Project Settings -> Kitsu -> Integrate Kitsu Note`. -There are three settings available: -- `Set status on note` -> turns on and off this integrator. +There are four settings available: +- `Set status on note` -> Turns on and off this integrator. - `Note shortname` -> Which status shortname should be set automatically (Case sensitive). -- `Status conditions` -> Conditions that need to be met for kitsu status to be changed. You can add as many conditions as you like. There are two fields to each conditions: `Condition` (Whether current status should be equal or not equal to the condition status) and `Short name` (Kitsu Shortname of the condition status). +- `Status change conditions - Status conditions` -> Conditions that need to be met for kitsu status to be changed. You can add as many conditions as you like. There are two fields to each conditions: `Condition` (Whether current status should be equal or not equal to the condition status) and `Short name` (Kitsu Shortname of the condition status). +- `Status change conditions - Family requirements` -> With this option you can add requirements to which families must be pushed or not in order to have the task status set by this integrator. There are two fields for each requirements: `Condition` (Same as the above) and `Family` (name of the family concerned by this requirement). For instance, adding one item set to `Not equal` and `workfile`, would mean the task status would change if a subset from another family than workfile is published (workfile can still be included), but not if you publish the workfile subset only. ![Integrate Kitsu Note project settings](assets/integrate_kitsu_note_settings.png) diff --git a/website/docs/pype2/admin_presets_plugins.md b/website/docs/pype2/admin_presets_plugins.md index e589f7d14be..44c2a28dec7 100644 --- a/website/docs/pype2/admin_presets_plugins.md +++ b/website/docs/pype2/admin_presets_plugins.md @@ -293,6 +293,7 @@ If source representation has suffix **"h264"** and burnin suffix is **"client"** - It is allowed to use [Anatomy templates](admin_config#anatomy) themselves in burnins if they can be filled with available data. - Additional keys in burnins: + | Burnin key | Description | | --- | --- | | frame_start | First frame number. | @@ -303,6 +304,7 @@ If source representation has suffix **"h264"** and burnin suffix is **"client"** | resolution_height | Resolution height. | | fps | Fps of an output. | | timecode | Timecode by frame start and fps. | + | focalLength | **Only available in Maya**

    Camera focal length per frame. Use syntax `{focalLength:.2f}` for decimal truncating. Eg. `35.234985` with `{focalLength:.2f}` would produce `35.23`, whereas `{focalLength:.0f}` would produce `35`. | :::warning `timecode` is specific key that can be **only at the end of content**. (`"BOTTOM_RIGHT": "TC: {timecode}"`) From 10fdeb5243eafd09badd0d7ad868ee13bc8c0d99 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 31 Mar 2023 11:23:12 +0100 Subject: [PATCH 785/898] Use json sidecar instead of querying ass file for IDs. --- .../publish/extract_arnold_scene_source.py | 27 +++++++-- .../tools/mayalookassigner/arnold_standin.py | 57 +++++-------------- .../maya/tools/mayalookassigner/commands.py | 3 +- .../hosts/maya/tools/mayalookassigner/lib.py | 2 +- 4 files changed, 37 insertions(+), 52 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index e12268282c0..2ac9d4c6a2e 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -1,4 +1,6 @@ import os +from collections import defaultdict +import json from maya import cmds import arnold @@ -17,8 +19,7 @@ class ExtractArnoldSceneSource(publish.Extractor): def process(self, instance): staging_dir = self.staging_dir(instance) - filename = "{}.ass".format(instance.name) - file_path = os.path.join(staging_dir, filename) + file_path = os.path.join(staging_dir, "{}.ass".format(instance.name)) # Mask mask = arnold.AI_NODE_ALL @@ -69,7 +70,7 @@ def process(self, instance): "mask": mask } - filenames = self._extract( + filenames, nodes_by_id = self._extract( instance.data["contentMembers"], attribute_data, kwargs ) @@ -86,6 +87,19 @@ def process(self, instance): instance.data["representations"].append(representation) + json_path = os.path.join(staging_dir, "{}.json".format(instance.name)) + with open(json_path, "w") as f: + json.dump(nodes_by_id, f) + + representation = { + "name": "json", + "ext": "json", + "files": os.path.basename(json_path), + "stagingDir": staging_dir + } + + instance.data["representations"].append(representation) + self.log.info( "Extracted instance {} to: {}".format(instance.name, staging_dir) ) @@ -95,7 +109,7 @@ def process(self, instance): return kwargs["filename"] = file_path.replace(".ass", "_proxy.ass") - filenames = self._extract( + filenames, _ = self._extract( instance.data["proxy"], attribute_data, kwargs ) @@ -115,6 +129,7 @@ def _extract(self, nodes, attribute_data, kwargs): "Writing {} with:\n{}".format(kwargs["filename"], kwargs) ) filenames = [] + nodes_by_id = defaultdict(list) # Duplicating nodes so they are direct children of the world. This # makes the hierarchy of any exported ass file the same. with lib.delete_after() as delete_bin: @@ -158,7 +173,7 @@ def _extract(self, nodes, attribute_data, kwargs): # Copy cbId to mtoa_constant. for node in duplicate_nodes: - lib.set_attribute("mtoa_constant_cbId", lib.get_id(node), node) + nodes_by_id[lib.get_id(node)].append(node.replace("|", "/")) with lib.attribute_values(attribute_data): with lib.maintained_selection(): @@ -178,4 +193,4 @@ def _extract(self, nodes, attribute_data, kwargs): self.log.info("Exported: {}".format(filenames)) - return filenames + return filenames, nodes_by_id diff --git a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py index 771b256614b..08e7746eda7 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py +++ b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py @@ -1,5 +1,5 @@ import os -import re +import json from collections import defaultdict import logging @@ -58,52 +58,24 @@ def calculate_visibility_mask(attributes): return mask -def get_id_by_node(path): - """Get node id from Arnold Scene Source. +def get_nodes_by_id(standin): + """Get node id from aiStandIn via json sidecar. Args: - path (string): Path to Arnold Scene Source. + standin (string): aiStandIn node. Returns: (dict): Dictionary with node full name/path and id. """ - import arnold - results = defaultdict(list) + path = cmds.getAttr(standin + ".dso") + json_path = None + for f in os.listdir(os.path.dirname(path)): + if f.endswith(".json"): + json_path = os.path.join(os.path.dirname(path), f) + break - arnold.AiBegin() - - arnold.AiMsgSetConsoleFlags(arnold.AI_LOG_ALL) - - arnold.AiSceneLoad(None, path, None) - - # Iterate over all shader nodes - iter = arnold.AiUniverseGetNodeIterator(arnold.AI_NODE_SHAPE) - while not arnold.AiNodeIteratorFinished(iter): - node = arnold.AiNodeIteratorGetNext(iter) - if arnold.AiNodeIs(node, "polymesh"): - node_name = arnold.AiNodeGetName(node) - results[arnold.AiNodeGetStr(node, "cbId")].append(node_name) - - arnold.AiNodeIteratorDestroy(iter) - arnold.AiEnd() - - return results - - -def get_standin_path(node): - path = cmds.getAttr(node + ".dso") - - # Account for frame extension. - basename = os.path.basename(path) - current_frame = 1 - pattern = "(#+)" - matches = re.findall(pattern, basename) - if matches: - substring = "%{}d".format(str(len(matches[0])).zfill(2)) - path = path.replace(matches[0], substring) - path = path % current_frame - - return path + with open(json_path, "r") as f: + return json.load(f) def shading_engine_assignments(shading_engine, attribute, nodes, assignments): @@ -136,7 +108,7 @@ def shading_engine_assignments(shading_engine, attribute, nodes, assignments): def assign_look(standin, subset): log.info("Assigning {} to {}.".format(subset, standin)) - nodes_by_id = get_id_by_node(get_standin_path(standin)) + nodes_by_id = get_nodes_by_id(standin) # Group by asset id so we run over the look per asset node_ids_by_asset_id = defaultdict(set) @@ -161,8 +133,7 @@ def assign_look(standin, subset): continue relationships = lib.get_look_relationships(version["_id"]) - shader_nodes, container_nodes = lib.load_look(version["_id"]) - container_node = container_nodes[0] + shader_nodes, container_node = lib.load_look(version["_id"]) namespace = shader_nodes[0].split(":")[0] # Get only the node ids and paths related to this asset diff --git a/openpype/hosts/maya/tools/mayalookassigner/commands.py b/openpype/hosts/maya/tools/mayalookassigner/commands.py index 3e070c2efe7..c5e6c973cfd 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/commands.py +++ b/openpype/hosts/maya/tools/mayalookassigner/commands.py @@ -87,8 +87,7 @@ def create_asset_id_hash(nodes): id = k.split(":")[0] node_id_hash[id].append(node) elif cmds.nodeType(node) == "aiStandIn": - path = arnold_standin.get_standin_path(node) - for id, _ in arnold_standin.get_id_by_node(path).items(): + for id, _ in arnold_standin.get_nodes_by_id(node).items(): id = id.split(":")[0] node_id_hash[id].append(node) else: diff --git a/openpype/hosts/maya/tools/mayalookassigner/lib.py b/openpype/hosts/maya/tools/mayalookassigner/lib.py index 5594c53c33e..fddaf6112dd 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/lib.py +++ b/openpype/hosts/maya/tools/mayalookassigner/lib.py @@ -82,6 +82,6 @@ def load_look(version_id): # Reference the look file with lib.maintained_selection(): - container_node = load_container(loader, look_representation) + container_node = load_container(loader, look_representation)[0] return lib.get_container_members(container_node), container_node From 777864461376cf2efa3080984ae90d2461e1621e Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 31 Mar 2023 12:33:58 +0200 Subject: [PATCH 786/898] Update openpype/hosts/houdini/plugins/create/create_review.py Co-authored-by: Kayla Man <64118225+moonyuet@users.noreply.github.com> --- openpype/hosts/houdini/plugins/create/create_review.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/houdini/plugins/create/create_review.py b/openpype/hosts/houdini/plugins/create/create_review.py index 8dd3f1429f3..8817b174bb6 100644 --- a/openpype/hosts/houdini/plugins/create/create_review.py +++ b/openpype/hosts/houdini/plugins/create/create_review.py @@ -57,9 +57,13 @@ def create(self, subset_name, instance_data, pre_create_data): }) if self.selected_nodes: - # todo: allow only object paths? - node_paths = " ".join(node.path() for node in self.selected_nodes) - parms.update({"scenepath": node_paths}) + for node in self.selected_nodes: + path = node.path() + if node.type().name() == "cam": + parms.update({"camera": path}) + else: + node_paths = " ".join(path) + parms.update({"forceobjects": node_paths}) instance_node.setParms(parms) From 5b0a9772f0d9fb51fc109038c3bcf9d5008b3f88 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 31 Mar 2023 12:45:40 +0200 Subject: [PATCH 787/898] Update openpype/vendor/python/common/capture.py --- openpype/vendor/python/common/capture.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/vendor/python/common/capture.py b/openpype/vendor/python/common/capture.py index 2263640d754..224699f916b 100644 --- a/openpype/vendor/python/common/capture.py +++ b/openpype/vendor/python/common/capture.py @@ -757,7 +757,6 @@ def _applied_viewport_options(options, panel): try: cmds.modelEditor(panel, edit=True, **options) except TypeError as e: - logger.error("Cannot apply options {}".format(e)) # Try to set as much as possible of the state by setting them one by # one. This way we can also report the failing key values explicitly. for key, value in options.items(): From 6d4e01dad5d0cedda46ba72f6aecb290b51a4e32 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 31 Mar 2023 12:55:11 +0200 Subject: [PATCH 788/898] Update openpype/hosts/maya/plugins/publish/collect_review.py Co-authored-by: Toke Jepsen --- openpype/hosts/maya/plugins/publish/collect_review.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_review.py b/openpype/hosts/maya/plugins/publish/collect_review.py index 92c3aeab754..153f7315ec5 100644 --- a/openpype/hosts/maya/plugins/publish/collect_review.py +++ b/openpype/hosts/maya/plugins/publish/collect_review.py @@ -36,7 +36,7 @@ def process(self, instance): # validate required settings if len(cameras) == 0: - raise KnownPublishError("Not camera found in review " + raise KnownPublishError("No camera found in review " "instance: {}".format(instance)) elif len(cameras) > 2: raise KnownPublishError( From 194387d329dd1221b063d2e9fc87ab93101de9ec Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 31 Mar 2023 13:59:04 +0200 Subject: [PATCH 789/898] Improve selection handling --- .../houdini/plugins/create/create_review.py | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/houdini/plugins/create/create_review.py b/openpype/hosts/houdini/plugins/create/create_review.py index 8817b174bb6..ab06b30c35c 100644 --- a/openpype/hosts/houdini/plugins/create/create_review.py +++ b/openpype/hosts/houdini/plugins/create/create_review.py @@ -57,13 +57,28 @@ def create(self, subset_name, instance_data, pre_create_data): }) if self.selected_nodes: + # The first camera found in selection we will use as camera + # Other node types we set in force objects + camera = None + force_objects = [] for node in self.selected_nodes: path = node.path() if node.type().name() == "cam": - parms.update({"camera": path}) + if camera: + continue + camera = path else: - node_paths = " ".join(path) - parms.update({"forceobjects": node_paths}) + force_objects.append(path) + + if not camera: + self.log.warning("No camera found in selection.") + + parms.update({ + "camera": camera or "", + "scenepath": "/obj", + "forceobjects": " ".join(force_objects), + "vobjects": "" # clear candidate objects from '*' value + }) instance_node.setParms(parms) From 78130f9de31d84f74c0d0c22c64c20af98ab0359 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 31 Mar 2023 15:08:47 +0200 Subject: [PATCH 790/898] project actions trigger remove redundant action --- .github/workflows/project_actions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index 1e1a1441f7a..e3d4e142d4e 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -2,7 +2,7 @@ name: project-actions on: pull_request_target: - types: [opened, synchronize, assigned, review_requested] + types: [opened, assigned, review_requested] pull_request_review: types: [submitted] From 1967ab34fb8e80f4aeb8497a77586f9e852d19b8 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 31 Mar 2023 15:21:33 +0200 Subject: [PATCH 791/898] project actions: narrowing triggers even farer --- .github/workflows/project_actions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index e3d4e142d4e..f425b233d4b 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -2,7 +2,7 @@ name: project-actions on: pull_request_target: - types: [opened, assigned, review_requested] + types: [opened, assigned] pull_request_review: types: [submitted] From 889fafbd25dd1af8df9cbd43c704ed99e267d55c Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 31 Mar 2023 16:12:41 +0200 Subject: [PATCH 792/898] Add docs (+ tweak some of the existing ones) --- website/docs/artist_hosts_houdini.md | 31 ++++++++++++++---- .../assets/houdini_review_create_attrs.png | Bin 0 -> 37048 bytes 2 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 website/docs/assets/houdini_review_create_attrs.png diff --git a/website/docs/artist_hosts_houdini.md b/website/docs/artist_hosts_houdini.md index f2b128ffc6e..8874a0b5cfe 100644 --- a/website/docs/artist_hosts_houdini.md +++ b/website/docs/artist_hosts_houdini.md @@ -14,20 +14,29 @@ sidebar_label: Houdini - [Library Loader](artist_tools_library-loader) ## Publishing Alembic Cameras -You can publish baked camera in Alembic format. Select your camera and go **OpenPype -> Create** and select **Camera (abc)**. +You can publish baked camera in Alembic format. + +Select your camera and go **OpenPype -> Create** and select **Camera (abc)**. This will create Alembic ROP in **out** with path and frame range already set. This node will have a name you've assigned in the **Creator** menu. For example if you name the subset `Default`, output Alembic Driver will be named `cameraDefault`. After that, you can **OpenPype -> Publish** and after some validations your camera will be published to `abc` file. ## Publishing Composites - Image Sequences -You can publish image sequence directly from Houdini. You can use any `cop` network you have and publish image -sequence generated from it. For example I've created simple **cop** graph to generate some noise: +You can publish image sequences directly from Houdini's image COP networks. + +You can use any COP node and publish the image sequence generated from it. For example this simple graph to generate some noise: + ![Noise COP](assets/houdini_imagesequence_cop.png) -If I want to publish it, I'll select node I like - in this case `radialblur1` and go **OpenPype -> Create** and -select **Composite (Image Sequence)**. This will create `/out/imagesequenceNoise` Composite ROP (I've named my subset -*Noise*) with frame range set. When you hit **Publish** it will render image sequence from selected node. +To publish the output of the `radialblur1` go to **OpenPype -> Create** and +select **Composite (Image Sequence)**. If you name the variant *Noise* this will create the `/out/imagesequenceNoise` Composite ROP with the frame range set. + +When you hit **Publish** it will render image sequence from selected node. + +:::info Use selection +With *Use selection* is enabled on create the node you have selected when creating will be the node used for published. (It set the Composite ROP node's COP path to it). If you don't do this you'll have to manually set the path as needed on e.g. `/out/imagesequenceNoise` to ensure it outputs what you want. +::: ## Publishing Point Caches (alembic) Publishing point caches in alembic format is pretty straightforward, but it is by default enforcing better compatibility @@ -46,6 +55,16 @@ you handle `path` attribute is up to you, this is just an example.* Now select the `output0` node and go **OpenPype -> Create** and select **Point Cache**. It will create Alembic ROP `/out/pointcacheStrange` +## Publishing Reviews (OpenGL) +To generate a review output from Houdini you need to create a **review** instance. +Go to **OpenPype -> Create** and select **Review**. + +![Houdini Create Review](assets/houdini_review_create_attrs.png) + +On create, with the **Use Selection** checkbox enabled it will set up the first +camera found in your selection as the camera for the OpenGL ROP node and other +non-cameras are set in **Force Objects**. It will then render those even if +their display flag is disabled in your scene. ## Redshift :::note Work in progress diff --git a/website/docs/assets/houdini_review_create_attrs.png b/website/docs/assets/houdini_review_create_attrs.png new file mode 100644 index 0000000000000000000000000000000000000000..8735e79914033db1b9afb2ca3da4d33b1aad668f GIT binary patch literal 37048 zcmZs@1yodF*EVc`AShkZAw3KY($Z4WJp;uU6yERJn*4uh`eH%~OhK`FB3_VB)obajh9(msWqDSvS=sB_!Y8s z23s8wt0L{k>ublDEbc5Ugw%RGRRWfbeQ$-I)VAXKOYIz1Tk-Yt$0kB{ zf7af$StHyx_PT8g-GejL^#A*56|B6Z>GC5#)2H^Ex(lX1FDc&|j&>so9Xh+1%d;j2 zC(5Sz60_fmlLUE3BX>7`WmkCSMyIttg9M_Tq4JJz%s5VK411_Hse^0TwKLrJC2Ztk zGDs9v(KnSRz+;V@{wNJ^jnfy{OTA@Gjm|o`S~*HuG)iYTa5ftBO_kFh@cx`v_Sv&v z{Q_7PnYC{gf-j?8rMKfrMFiBdfhb$h&Ylc0mTav^dS3l<^@{lGMItl37s@`kf2BHf zQ}ku9MV_-O$@B!Dtali~6KmAWuWHmP=!28Z^*p0afxS)Pt%&Q+f`#k(k)~p5nHpb`MPVor?Kg1PgioDYKsVYX9*tvVx+XCM{c5+M>zuP;%ok zOMdLY>We>D_}fhE7_X~ex{Y5ZF8+3lxZWP0kLk4ClukP)R4-5*>=#Gy=0Cqc7YpXW z)EKLDk0O_V8g=;KX7PELO(SY877Mci*$E#uInRrqEN|O37GdDz#FMrK7!{c3k6ZnX z`9sAuw$OYf(`qQxNTulyM(9?M()D_zUehr!y+PgGknz~W=g%LK+^mk(ia0Nkl2Q{< z)bGcw(ufCGfgz2=y2%0@`i+vUIcH76-Yd#|6yolmy)G~1PmUK=T@I3r9TN_Jm!7xz zUbhw$=lBFFW&6n8KmtbF)#K%>vlfAw<1IHx;kzPab@o+oL_R zXolF7xC}?xlwF5{XfuBw$+#t?eNltil*0nPUK5_eZv7rkEsdvoV{(*z6K=ZpE@J+1 z9`hiVuES5xpD|gnC=47bL*I%S>?~4Fiy3**G5<2wObX{l0jBazl{AJlIw)lp3>@N??5LhyFAF!QPCXjNt&kyc1nN;$Aq@_u{v-Mt zpWi<_G`!F+S9p#UZ$rh=ay)5W!XeU9CuOcqAQY??C&9p8lNChlIv*Y(Te3? z?Y;VuRy0hbdTYNYQJ7_h+mYa5>l2?d3Z}NX#cP()P`H%V<>TkbolGvb7$N^lQ-~1a zPJ<(AviD+NOvvT9`D>cJ3@Inuxo6o2J-k`D%(tn+oDGh=8z2(f%z(E*zRg?xeYP?- z_80QE`QqT+e(ur??C$CtE>_6La>OCxPaymuHJo?JJ48D|oZhWlCgo84r6u+*(R_)F z?&nKQF^S6jA%jY(@+x4Dwdt3E{R&!rm=1cA0zBu3Aiu5Zp-$@hAj53qD#lClVVB(sGBwCk!g zJ|6xQgy`Q2CB?@%SZ2&a@j%?B*aQR41$&2(#Kr^eY@@4?u*2={ z1{#dk6X3}o7T&Jg3WSew++uh6y+1CUtT(4Cd?Srk(C;xa-ZFxR|31|32?hy|k(|Ge zubt0=C#wvyR_n;c_u>}Ux%W5yk!*@>(vCJCUuEJ2=Zic42M3*fyc>uH>E?^x*F2-4 zTYqGyzs@4o(WANp@e>@x8XOm@^-!Mb)zRy@OCLvbU0E#T3;mwN`+*y%V{;mbe2puO z8auk~{Fmd6s|1cNpp`Grsfg-i@LhWZkOMSs5e3+EBLbTWOel@X!zFBEn7$|2DXYu! z(hF#WIq5uvP-%G;0wt^}G965OU6WN=4KY41H3Im60In&7<_b4UnO#EgixO8n_H=&| z#ra_SuT@3?1cn5+y1+Zq^I-b~gng{vQw`jQ`xzcYZ7i7ZUYn@`ABovsmoDrdq|gC> z?1`f2h8@orjTh=jY(zR$T9|FP@y+w}uQ*hX`(#KDr0*=G#nAW(ad}_4t1fsKH@$Z{ zLf~MNJv>F5sTpzOsweNQ8M%R1e_&x`9v6SyCr%0yoe~@L*w`IvTD?rYyLtWNcV2rm zyAqLE*!vDFOO8h006fLBho)vIvW5=vDTAQ9az^jr4q|#td%s%`5$&7X7N;Bv#qx(mT_V{MP-5EFBRN)l*P!?9QeE#EDQL6za-WK3Ix{a*o0}5^^`bg7)(NLO zibaDy^f7!`5FZr6#q~M1e$0>w5iFXgh6rMcR0N*oyt;yNdE;+z8gb~bKzODd#fUs2 z*-=jGM;eK%Ij#84=JM*7oG;G(e5m+lNh*HBb=&S%?pOev}G$nvVx?3COkjw;ec`qAiqo_$K!qU9_wGdckK2 z;sx9aI`uYf;1xYfL~LDB9tC*m61&X1B?&da5w7F-(1w!h<46qxJm?_)MiD!Z)imm( zrxe;MFn*h#I*)3dPw+AiH%qrP`U(C)!jk)cg>!_YUjUjIv2|G#aO5LfqVw196Y5xY=t-e0LVA%q+`-P9L3}(B7*o#!Re%^yz%YG%8zQG1D6OqyX-ZI)e%~R!c zaSkBef@;m5NbE|_ixCwT-O9Ib$7>F0d0}0iZn$yXD=4)a+^0>FsCL@&k3?!(8EV=#eh&>P!?m3qTjj_ z_N%}qKj+v}w|LsR)4Vd3i%KKvufJ}!^gFR?E5%O6Sd)i0$RKymYj+0j zU^3I8>`NKZ^Jl3XB4^zNU*^Ad+RdQY!TTct=i2?E1v@Li>j=Al&*HkD^S9D@%(7=& zuRd*$2NVnW-6}$;r7R{IN;ZBR)oe^&Nu+*b=)uy9bUzRQCFgBAO27*SiMdvpNBD5F zo0G3aaI+CgqZ=2<(!1rjjbGz}8^d{<8%?(LvSf^eQ2RMI0S}rsF1MQWNVkK5Iep2W zVH`~|Q5U`W{hFV_{xshcvv0!syhHuH2kNp^HV^_zX6EH@cuR)fcr6w=$Tk2 z%N!aMudDfY`3Ok2woi`iRg#LdIIhJ%vcj4-9sMI+8DnyIrhPqbV(b{gaA+i~sM|c5 zA8qvyT@?bvAbuJkTYI>%PwSaEmofm#q;T0|f7LaYG<<~FdV$c*z)&?-N>iFXNX-<; zl5xsvfl0UCo#(XjoKv^JiH!SXrbAe3x-OLhDz~rkuFjfvEl)4Yoso#m2PO~d4h=Q2agDf`tstZ%!%#;k;?cKm_cqBqsda*1 z5`wvdvZUkS->>bK8pExBG+4Api^M9oePhU1rXO9$=x9P>m!`Pg>El5#Iq&|)nH7bg zEgbVx5JpxIT5+cJjc@kUrks@DdfOI*zS_*IFT7N5t4mmC)y8PUO$^!h!ReOyUiU8N z@Nn;9AowN*dIc|t+<$IZg%iLq56_#HxHgT+X?;)5XHAtjOE6&E?BZw8%kX*1ZU%h8 zZz^Sbn44gEle`!oyNi2*b^KIvomT@a9*Ija8+!>9=>YD7QN{5msU`=X{b}M z;d#yzucaj)f)LE#px2b9+Lk%LA6=&P__9XEvjVgrmCGw#zuG*4%lY_^nm-SaC5eq& z^sj%CihekaX!oj9qDR5;e~~)qxX0`Xj@UDELq&aWR`FHz=8myZeg6BG(Tu;v6=C=j zSI7G!-&o|a+XkJ5j-_6|UI}_h#U1)%m9#!lDZWSxdM&O-aEU|4I`y(lNyX5O>(G?G zgH+g!qK>O^AC>NH{WCt`d7kSM(d zr(C_p>pxoeMejN)3(}q-!apVFPcSYNg#gd@Zl?@=rLZe2h~lFe0hI)70`2KkoBvgA zlo8~suRTy@i#hZiE~i&lmfzvdD?Gket6#eF*p_@hp77a^>h!-H__yn_Jk?8eI^>Rb zzFc73=$btY5?w(JLs1R@v9aqUxzp=SwhpH@)2U_Hf1dK7`2G^${=kUNQP7j zD|Zs<=EH0EC*;#%BamT#W5h5DVhM2C-&+ma?jFldUo&xYYN^>_6TxChQ4V2mJphtRN z5+cBN;pzANO)&`g^J4J#)oX=qEj@Dw312XSaZS2!CNl7YcL>3}^5XA(55a^;CMQ|l z!rmq%;?>JWz*BrK9Yl!=jX;2Io*!VtZ zQ$woOBEc)HPcwU4zQefln3a=0J}}hzw|3zFtnKxBPxJf<2h zgJjoqx|!~?iHFT{0?ndY2KXso%X_pm>b@qpfw)9H3I+%c4KW?c7;bZI4e?tclQz`=@tt32#%n=1UywV>w>yA1BN*;6)+_#AqD|TES;CV+L-U;cb1Atfx4$?y@TE3TX`kOzC+Wjy{ z@zuoknuj{)@mIgIAd6hsRFc_Di-h@N&I<{`RN0(9`Wslm@vrlT_nN4JY$F_u*4J6& zXiiNnc*A*%vRn|~C1)}uy99vB#)$tpcg}HNSn}Ozikq}G$?(Zl`q3_Xp|FIP^1*iv zCV%P^T>FJO=C2`m$lb0qg!QDV4@7BJx0a$`L*e>-fGr8T4fmhm%GM8o(b1>=#{0G2 zRt)mPc$N_HTt6he53ee6w%IMi{rk!cDA@uYrhf1X4e!b9!bKdNsWAv`wb%CA^Q4#%3cTfJ`2q%(g93+xLItjyoTEPh<)_a|iq zwj+UgV@x|%Ja2S;qjN+x0bY8!gMsf>@ydcn5mM!EnAjh>gmJGIGZI^XQ9Jy0I?WD- z16{6vCq^8=M@Dv57MrQ}TRgddHS5)&=*@DUEoz%X%j0IO>%dB6choqROvqJ;zfmu*m8M13uxE`ApUBT0kFP7NViL_U(tb! zKglOKSk-=$P(s#H=qJzN^}?Hj0pX490h&kZ3d>g)1A@W6GNelB4ZVZVuk@G|o0lYC zSd5-9M(#J^Mmqf&Pr8rPXI^0Y=hIi2OMRkpuN!{mIHjl;a5Ek0G%x)Cw4u-15{4l- zh{a1zwtS&wq2<=e~_qOTqu ziTb&&`e(kbpkbH7{}kWFXQPDF85>)hDO*dM35DyAK#G^(_-fael<2qV?=_}c*;w%7 zu1lvOzzr@Z+4?}cV4-rtAShaYf{^gNWqJ#1#GWrCfOdH>R#VDGRA_B_NWS@n1slgx zO(+^kLU9;+90-=S{baj{ORh-$KHqp)Y3KN}bp!-K3B$kx+b1b1ci$MK0rkEE*k|IN zi0YZ*l1V@TN+uj!fS}3u7X}J;N6<6G>+}}a^3UIrZwrtBXkJCbNoqZ|M>bX8n~zN* zr&5JTL<74_0)@0?eI6jcoizP$hh#Lc&GxEX08M-2ymm!ia%C((I!fm&H#D^6Qi*!y zpl4rR(&y<4Gv-pyNA94}7*u}N1kE~*HXA9hbvP_*bakx%QL$L#na#izf_7MPUem_6M-+&m)~_KX z$=nhxAi6q4Tn;ev5CX`qg7tJs$_svf)C)j_x6WGPPt1XjZ+=O4Xn7Jg#vWN5uAtw! zQdLW_7BZ$JotJsW#4b4>(e{0K`<=~HEVbKO2TOs@zRy2)2Kx6Yks6QgA=Q-qob`c( zpN0E@m>mwam~D2;<+rsuB~{NwVAS+yM?y5w$e?h@h*A+jzhj~?1=|x6{e}4{e#~lS zkc^i;R9o^(T;a&?G^QrmUbSr1{W8k&f)FDl4rLEgVhgZi*&()6d-uk5zwGa5xcwYydWJ_%NWUEZDc8}FyxMJ?*bff%EC<=b!0-^YJJ)ufblD1L2o zAm(iXfHi8H1f_{iG%O5dzGxTW)Pu*&>EfMM-yc7b9B&+988`buH17IcYaC@3muL@F zGoK^Ii4hU6m!=udz54N~B5Y{B?@ZS%J+-+aSa~FsYe&fQ^Y)Bc16&wnA{MSp$So%X z328Cgw4W+8RI>`F?o>uxQ&&fCb=c3=zK1M$8P*=!&%t&`MK(iT!|3p^y`#BWOzjKz z7cW)0POA~Jpv_#ckEngY&x2qlglAq>1KXl2fCXCM-futuR}hM?+-&F8e-W4p?)sR~ zOT>=8C>{x}Q>eMZ%pYGe;&!7T@mLnZ)=k~5r;bD~wHj5c($gQ%U(NK@{G#sM2#m5K z*a_K5EzYTgO{N^?SiNpAVp(eoO0U`#=o@zU9jNk6^sA3ll?xTqn97B_`@gcfp9+z* zQdcztGu9v!xqu_*d?VEryh*(b!p$A>(PqA&4KvS(d(>j}tHIhi-{NJoAi9`5(X_(t zkL_wvj4Mn=G(xFzqqANC#SF6`tfMsp)Q+Gvq1~q2i+9IO&*S&!s)R3NQia$MGak${e09B&N<9-XA7HA*Yx@nW%CvE_+3m0-jms^&k9~`7Ftug|(suIZ zxL*;*?`TN2ck+SmEf#`E>KX8^Bc7(NNIrmGMf0o76ZKZ{zn^+rrZ7~Avt=K(@{Hee3C}J){pBV=i^#qHEHzCn z%Om^d^HZA}aW#X>=P&F5fvpdi7iygOjZT(Svb;oH;;@lCAX$hIyLz5rzYy1elhbnh z4&a^Cpy`v1UWs&IP?8Gh4^Px$nyU$*IxGr}mKXHm!l%?PFdSr#o%^ar-2JB|1M!Y` zr5fB~o-)+qK%&<85fK7s`n%6cNe(98w#Xy8%e2FPGPTXilNJ&~^(xESZAk|lf7Z=V z0YU7d`gYtvKi?ZdMIy40za|?2mXn)1LAz+%XOGml0g^l!v9%If`)->}|4q7VLH&U+ zEhi7t-Jby+OG{2YOF7k4@;zq5Vqs#2-nVhH`}?nIhT zUib;`V$q z*=M`*L6e>2k^U%33R_&at8FlRmpN9=S74XcNPMWF5ZN5~TzpR_B8d-8G6Q(e7; zOn0WH*9dnumX{!?z<)whGmt`Q2K#PZfAh zREB)t3m_QQ6keO0OV2=B+jU~>BJwgR&`tt<1U;r)s?#7^f4G)!ChU1a*@DCIBzL!UfbUTur>`r{%6{wE!?d+Plr$5<#yfG&# z8CGOVyD>oOQn5wAKL0z-dEZTz^xG}aNm)r?gcD;0EQ)e6V$1^&nEt?Eri}fDwgPE^wETS0wv-&JX0|Pk~1X zCjh<1q@+NEOjcB$fA~bXG6+a%byRp3opP#NOVB2caeJnQsLMZw?IYzC1lacDtCGebNAWTu_#H zfUMCUlKQOVB|m-n;Z2kpog%F9NCOjZdNQmu&TLP7itQ|d)a>IUhp#~uEiZ9RzQLu> zee?B4lN{##DtTP89mK9822z9--F|uqgc25NnEh!=X87>KnEgXoS%pkqj~XWtth2&>k-7X zHMFw>_Ly!!Q~CPih5-tXOhAHawEHWOfJ7y%wqJGE*Fks+Uyh{u5NP0GoG2&1xPwB* zN4YCakUW_bikU2B*e`E}jb36Gz1*@b)YV_v1+lIcU?CpsCfpqK^X~@u<@3WB*zqj^ z$x71>7)b10@(MG-yLlzSN29gQ^VH5Im#0z_H!iZ%zqtuzwJv)LYs@tHgzcx3dY+eu|#aqzs0EP z7XLQcP-UmATYUnM1Ax=68$4h}j_**&p~hp|&Rz z^(jMp6O%#OY;yw>?`JHt%kae=$D}p9QAZid=en0`YDv*t?POJpX8I!L#$tqVh z!ANX8vaaVQ&K=sF*iKu;PvgU7BbMEbexf1F_FrGmm;q{cCEQ6I^y=C}o|6gK>%8Z} zDX;@SxOMetHzEw|k)2u4gM(UG+*>2yC_E@MR05>CaAdR<5pk(Dz-JV5O>b8>k; zKn(p*T$3X-t>FJz;IZ2besTn$JG%jf#NdZberQ%EBX_ z80jsj7o-J+4%`jWejdW)0i~C;V*Asm0Xt=)R$|lEXH4G#JqwHd9(&1VJ+EN5kt{Xh zb7XD2pCVF5*CNQPt8mDG?4GcExHpmJOUde@2U!##r}SU;V0%z%%Hv&yVpo?<#etqD zL18A_F3|gj|IfWhML0MlN`gTBf=o2q?rCo16AvREkFCw1|B)ZHrC_Xzva9ET$`>aR zcdkHT7euZ~TxkPWp8^pqlyQ^0zqW&SnyLF=9XpL+@&zy#OZ+T7;c6tCqEW%+`C<7Y zlKgdhBIV$@1+zH^=RGJ;&r(-c#Kv|N+@9`(=?P5`9gtgjQ>K3WcvO^}wu<{Dz4ve_ zqh8|1hPutiF=nCJ+*_3*58Ibr@dfZ%fJl^-VT`8?+36@dI0zcH7)qwP3JR@GLxTac zm0TWmu5iMdkGwQVIr4bIyTXqM-}7wSOl0bqF%N$XO}+WUqUR5&lTQ&(a0ErpsIdx~ z@QQzyzIR$X)#6ib*cm=B8asS)p7PWPxRV3~wa_V_Cs5>6`rofDU0x_ucr*5m&Ut-& zw_T=YeS`btY*V5Sty4Vzi-b@6gf+F1;9K>?KM~%;DS$U*V{5xXzni11)XEB-6L(=7 zQ}4Dr>!J7yWt{#oE_K494Yw_(njKe_LDS*A{XqwDx2d28mn)nscm}$}i@~=N-W|Qx zgnEKJi}+y+63K^04s8vq^`k5v*foxEkoK=r|mr^{(2>OH&cb=JmYSGOaW z1?-F%16tvHXr#0azPZHR)7-xbNH}F#g_3k&Nw7lacLL5nzQV4rt9srsZA!zc&|)&e zQcbo~6~;TJw>tPp)OnAZ;9OpRM8|IA3~yEeBMbl;IT5mE7bhnVlv0g3fBcj=eM-P z2@qt{;Z3{O>lwiOULd~BVH~H*oz7IRHx7f+mgT3H9;g+MH?gQ3!h1e$@C)eNAvn9w zO}|Lh_vLXwu(yW{ z*9Y>y>OHg;v^Bi6f5Gc)P^p7tTs)KmgkIShm!F3fizKB5>?l3L1Yf3rf+1kEfhdi2 zW8A0TTn_}ITJREC>hG?kS?XV-re8eI)e@6A`BE?!e!TnUC2Gb>UH8sYNyojkT}o=U zsp?Qbhqo;gcT?3;zeN9wby+~ZN7m$X(+1x_VsvguYlC9XuZ$F_O@JYZv1!5ZdwJjg zO?{;YpKH~Nh?9E1jAcs09jXLR5xN5X+-u9kmnc6$$m))M!lwt9g%$%4_4s2Ya)6lG z-FXeLFh=T0v(WA6Ma>SKa|i(@lTn8l>v&C2{(}CI5N;6e0RE;S%B3Z-7NOFFZEdDc zKT->$t4!alOR!(*t(=?b?$C^=;HRid4;`5LE^zL&*R?H4-O)eQSu0?t0TSNqLZeOQ zHjHtjUo_i$G+h?^-Rga}bFBE|1OpTaSl?bJ0O}jdvF$4e-2qG<`{1N;R9Cel#A zge~p%ZSBR$P)jO2Mc62S>m<2MK|h=mwPVg7>!*5_2AC5N%VJJ{6XCB6M<(WxOY32oP#P z)1_#@>@eWfR}}qqsI6y5`ST|)Y{`?>O2sGNPH!85p;{~!F*K!OQ9$IJDkd1C(68z^ z-naqgw%`nyQm{d+0ED(6J8e7(-R^RX}V&ypCSnE zoUP|z2h;PoZT({MXpe%PvJ+gC$V~UUWk}~Z3ok|gGGj`wA^p-#)hpz8PH(?nBi&w; zTAv|5NO?Y_!v1gTO@mixZh|wo39b4CO!H;uO}_=|HQxO8!Xp&$J0K7m{(`+rmXjwI z^VTs|K?jI138%3YAZ4@bfXCowkS6P*wbK_|QZkzU%I~XGMagy8L7Ef43{Y~t73+U4 zN~^N~Yd(GX``;|HjuXx0jV`O%fSP9np}6-6IDTI_D2;&@?5o=)%cwMTg7*R&eH>`M2_1>m~ZkEw?EUaVJ!~1CB8Bzj; zcXZl>R5EfZpYKg#<^bmAj87jbT;ZiOfUSz?P~W9}my?O6*J=bc1R0+6F~`{M3|`P< zIe%GkfQ@(^jJZ`&$B^s#;^JF<&G6X|vWU9YLSm~oo9_2Ce1)}AGz3=3pe`V701D0D zpK(=#^d!y$HZn+&p+7*6SmnKvpS0ncD>5Om1HV~GJGB^E4h%oG96!5Z`tm7Ujcj03 zoX>VvT#II@h@+{Mn`7SnZ4-_$Y!P*?)%B4>#BA8Ks$D^>3Z+}NNGa^d1`GhZ$Tz5Y z9gacxi+1w@YisV$j+vFS%m5DxnXs;#90xQ~{ zMJXa%CgLCtHe^R_fFa-m!z(Y7z*TD0dUx$b##MvpJ)W5v_Wae);aq=lp=*k?-6~e7 zjxMk{yI$WI?j)rja}tdA2M%#G-eKaU=y)AX29^DfuM-f@g;S8Xf4LM3%Jnj}ToQHNZn zUJ4E8TT_(Xr|arTimo{erOxlb0F$eI~7@h$my4(`xIgcGM zSU!T#Hi;(crTJU#pk*Or_nL)w2i#?WXcfH2vDL~2fwlcc*nt;l+ciTA2ELXNa-!~R zdkiEbf*e_gPjWE0fn9CUoaP+#n4@e<>I0q3>;|v2mdnV(<-KO1x7Ys|NUg~IDBs@2 zzijQHVXtWT_`tN$lz50gQ1T}Mh39;q3GfKf34Kc->50bG&u+PzEw*bjSOVo|nT-uR`lkmLpp#HF$w)KgJK zvLEyz&Rqf&dRN{bqMwJ^(&gB$rKi4378QTI5FJHrPE;6RB*Qi>OC`Xuc=+VuT_zzZ zJ^jbs8lc$vJc2|Y{f<~d+AVmQNj2W9>L-cBfY*{}{zZ6nHt69Ba5yO0uM3?X^BhT4 z@+LEpYBGHOa53CiC77wao4yNku8t~lwYYt;?j2*l{WSkfuYE*!)V{gf-yo~m&(ZYB zuj!0hGUAFs8$a0)Va@4w7EaCN z)Gm}dEIY4!uUEgzVXuTMyk!lZkH?Qf`%(0{lT=g`1dQp}bzbeX2Sxh)n5uEwHo#Yl z((pY#Zcz?WyaXIRrYl#>Ro?WskWqBm$MOnS@E3Vhz;P+;g$RF&*Rr~NX+v)U_;R}u zFtn86H(yu^@-!kVK4Xq6G&qPaAoL=xT_zu{bX4k~PC}EI;ZmTmDSmyUdsvMWHgm5L zc)IzEUO-U}O?aiV!1=9zzfc*ufIY+J?{VIe$L}BKQRQvyNKuZy6?}r7YBp%_9odfT zc+(>@U6e21W6LStKu~{1&kaGHA(4sC)knODq3aJ$FH~VM#~`7y!G!1S;S5hFjQ8Yq}vhtf-KE!=MVGwforGx`N_R=w|KZ1;DTCI$n2B< z9lRoi^X`u)y1~7N0oVCI=Pz>k$yHpZEN$%JP?uPV{V z)h$#1hkj(J{%{(HD3nfn#`eQ(rJF8`7`}4%J5pFokOChm2+GKt2h3SDrtI=n(lR@l zXP=!Zo&t8M|0m6CU64s>n!rBMse;!?)QFN)7SHzNeS%E-Fz3~0NDD4-#(NK2WxQ?KKJ&&C!Ly$?? zZ0}2Cne_W|Ie;1@)!yz^O*d;oxDVmah@E?*ffHG=^iK z-u?N-pou}W64}S$;lt&=t^Y~4JY*s|u>B65iD9hI{s9JR{Q>@&1UtV1VplJC&KRmK z_bzlf@8{lWgr}Ln_n!nz^ZJ@NN8Q2*%+!vbk6*?5PUOD5E47<4FgWM-|e_o>fbAex%NhQzH)4!fnT1fSdhaj%l#%@Cmq*RD7ffx%G~$ zE;I$*o4~9?Wv{)Ief`u+)&Eig(uK-|EAT3()39|ds?5rC^n%KWu_RqDuag>%fx~fp zMXfE6Od2}Wf@fvVkl{dQ=K(Vz6wXL30Q$bSc|n`V(ssV=%xinAp^$fj&@IDGsztK1 zi!i^T5OS{;a#_i=8#n5rFdcRQ$Q;5O$p15Q@JyB^~o%dddGqYl^Vr4h;;f{5>T;fo_)`CaB)^nr* z!e62`T5C2UiLa)ISkNm=b0tM+f9JS2LFyNM+-Di>elOkRh#tGB%7m)?tS*qIPgPIj z&~8@5nL0Fo9wFj-=7?L+**lW{RMRpvrpn&Qto^;9TcsGF>_;$2hct3|k9|?P5CxRh zd!X{_EYEzS*+Np7e(%?bM`7j2@(=EH*`f}5*S$f;3uivRgLpN6i${`|z!^_h(W#$V zKDfR93kw1wXH-vJ`}sqNR^`(>87Fs1U#Ap&aK7h=wZjZW)2EL7F$ zYw6^}M_(C7FKi~PGymjjv^hJl4570p=WJ91M^%9{8G#L7(@)dG`WZ`$jPgiW59N8{ z{YcvRnff{wVB!tn^7KOjAHiyj>L0S0=v7oabq z^k}wRmQ{1q?e|Pt{>HI?uzad6U@w)6%^@Eg>SpOj>8q#!PPu$A#kj1R*pa0U?39XY zaKZ1ogU@bE<1B*RjL(#9l+oFiGvK4^yl>E6LbQvP_&;f@b<5_SLHKXRy^yeQfHZD2 zQsql5+}OAGjA>H@iyHO7@jw!KI=GbLjE^Fk)mMu$pjWZ!Er9v13D-CkFue2Z3hYM_ zs)Ad$kUs%Vr!)r~N;a?TZ_hQ8{atwnoT9BFJr|Vp3K{vex|vUD-{Nx8s#jolyZmdl zAlhlYM~v68kG#hI{2OhXPY#{S&DW&W@R&?88wR_GtR=B8BZ+C)1%4CG+jCS2#y@z! z53p~UfR`HB?HdS1MnXzX2Fo!6P`}!S2!}gcDO((qFcW zkzn`LILCPI zz=`MebusUbs2@UhUb-;*h^G`re=wh)SwD6tDXAgp^9L-yGNQ2k3+}UL(=5r9b%J(_ zRB(p=R_}AyJ^8^mvyMsA`jBF{)ENZ;0qA>BS|T2Y%qv~l^XR%PHy)i+EzU?BZ<6Qy z^=3DTCsnbfe_WKWt5lj&b7FmZ#Bo~zdky|Ko7keCK@K#sr1SZ+H|D^2W4CYMywJ^G zcUHdAxh=icj`M23^wIvrMX5{q-n;;l?Fj&JR?wKvha9fB6h}#Q`aU(^WxWjv089X5 zc^xvk!dzH*_!=ZNC_=+f^dZ%A0MEtgHC$gbRQhs9j&V9lLe$%c!_q$RN1t47_isku zgED~WM_1lv#|2_z5|Q`A7N$hGU^U-cUboL)zF@FV0=41D3a)I z{9P;o9ZlM)S@w7Kug`)*=Gp~FYW=0gXi&#K5lhJjtj5%4HcZVOiHh;uTv$0cvvi%j~!J>E#`eD z0LyB4xoGA~&Tr37AAeFE0I){a)w4V`F-&mRvt*WYPdOVvE}8n=!I8OTt&5}lFwzQSCV#vZvb6Dcd?_uHn_QuJJ1Rs*EWf6 zu~6X1I4!EDYv;9I!^QSku973Zbc3#QH{H7%o)4$dE(d=I;KI5vF~6IOq{zX3QOmrq z8rl+Dh|qy?v8@;ZXOf5+bWNF;wK;RttlV1-#?_@JL6&+ zS>>d1n|3bfaW<*wgA~tpUjteLii~j@g%Y@_#sc%ebnxzHL-R5Jh2u!UE}*E&)NhOF$aw20=nX8tHDN zLy%5sSadf?cXxN!8Mxj1j^{b=?>*Cju%z)|AbX@+r}d&{Sl^ zx&7fzd%wRAu2A3ngW?@g4S`fNwTgyza>RJjTC%=qd>`6LJZk0=&nsZ{dYFO)jQig> z1Rxd?swmpsW>h=PU+|s3eSSDO=*6;)lIt1(iN_vCEi+UKMNgv!g2}&Q6TQbN zUBN#tBIpx5riD~BjfxbCqy!`G>QyMH{uA2hD9elsKwS?iI?Zz!>Yxgs{h-i~?{{KD z6ik(>0*a>2t`c86WBowxF-XOskOXpXGE+H68ir*2YG=&hRfMUQjO>>KIsF)J`;BS| z^;p9g0%*RgvD@7!{xHiKEA0X#W$%Vry~n1MQ@YL<86Mux@{7VMmOJ58o!&qH2|!Z> z{QJK1&p_A}=_4ATK5(4xJY6}TMA6@B#!CLY-Y9Y4L&iPblGHJi@pJU+Siz=R!%g}p zhaTVq@+TL{8*CrSpB+2G=U}voCoSM-HF`8^v(PPg2y8s4pVH7H{(8Fo8$5FaI^`EE zf`=$>p4J%CpK}GH4N0DDlH4pqOLgChS-p>{dm4ZLL(R4HLZIgd=2~41Xl%5+< zEjRMUVm8fYv%1Qq{@HUbg3oQ2Znw8&z5g-*1Y5Bqj_!&sHSwVxkr1Fp4HldMkxXJ^3Sg~GiO+i^j@j7#q1f@1*i=eoB$52NICNqA z=$xuSz#Y468zXA*E8!2_q*7AfTRtV`j~{S?BjZLzn>7y=&Wrl^rb_nx3pQfdkRm&* zEvJ6=KkvRvHdrznPVsp;Pa4Z}asD?tCWAq+yJZ4BS0{H(A6ho+>aF^ie@vL|cnz|1 z^xjYR<(G7xQEqV(Wag;5>$|RL-vYB4k$G-NAwf38%yeQT;j#y$oZYVm{AefMVdbin zJP-BQBTiyD-;4pt7~xzk(}|Vs%LQr&9Lv2iEYvimI*}ie)Mh7%cbV5*OXs){^wo@Yyjk2O`N8U1=K1sX*}fV~^=*FjnD$uHP6OjD3h-M@c;9T*pyj91&hdlIQb zfaA@+oxDJB^Mu!qS}fO2Ur;e2mrQ>d)NIGo_ATjMjl za&m2;zvi=F6l@GZ^%U>nM)n!q7^pG(DHRZ9yj}#!?KKq8P8d5CMAs#PVHAkaz^tXLy7U9^Ci*RZmn3ID1VG{C!0hb>FX6BZ;(bx4tf@#io{gvm@mJyKrnN0do9$@Ie`#+G82qqC-4h>w%+U0pgz z34~a0zbCOP-7x67QdDwAWHcZl4F5p{i%xevDBs~mkHS8`^Y|?~zK4$iBOB^58r17@ zAny_QFn75}?W~2DK4w2~Q<=iTv0!=DT_0*xSr_lDHs5M6e_jo41ZD4Yqq?vqQcL6J{`+%dogZ+5D1OZs1KGnbDLtiW(S|d#d?;e)nZFd zIp2C`M%y3mCoMJN1U~td7)RQ+>^B)J3SUAD6zI4@3p&x@S7_V(_S*H_ZK zYhKcyT2j_usxV5IS6`Kmk(j^F{-s|`_J`!6w7THGmNjebB0y6&qfR$Wrt)qE`i1ot z9V14^fVQI(ad4IP@wY4qtDPB*bW1|ofzL-np3;?4Ezyse1TZhwF)+$%&6gu9FVE7( z9oACsigWBvF5H!?EW81#aU=rGUxw^9+t0U(zp{$^4V#8Mr&J03*VW&RT~Gfa1>S(Z zB~&#UMcM)*TM^e$itoZOeU<%wIQY-CF zeeJHB=*Y;+bz;=W-8Q$lrekK!GzK7V_2T&LqG5adZ|Rx zp;F@up&g^+FP(zSE4KpK?h|x1`=F*sGa*ne}APr7y$)9z8MP);u9qTA$#Z)wf z*Vq1WLF}=$X2MkeVn(Oae&3H*@}ZerrPiBe9%p)YZX2vSCQXzCR@Ur+K&LvTwbiFm zBBp*MYd{m`G^Je80z1Kh;J8D|-oB zE=Dq&U{pqDcJm$_V;a|zNpVqf>%Z0)`A9a4ZB>A`8Y}4GxEt8Q+FR|D2-K z6V*ZHt+(u`ZcJ0#s2$S>1rLpINW5r#{^8IL~A#T@#JTk{K-O4%Rvc?_{cApRFn#??hFVomFMv3KNVdD0cFTwz_c2v zLH3+}pYqZWB#c^km&vf@a$7f zwPfVx7dsSgQyoo#EgQ%?g}@x@X}#WGTz)X{rGa!E4{l^Y@ah}9#rrYi?-l)1Ma@k6 zd}iZiV>0d`>&t;w)Lokrq%g0bSd!HS1L*g^B? zk#&~SPQJ{U9YsEHIKs+I5zk@~IL?yDH1A)gh4Yw8F1{Qj*n^0?ru6E)iP9Jf1Jtvi z+6`QjA8pV(xdKnEnf!Jlk=Nny1AV zSB2Ls`6}tRbOXXVh>i~tC!0ygu)fVn9(Z<(oE&5v|$ zU?RFlsGX;P=tuJwB^u<45zh4pVPR_I`|s&yZwa$_05mrBrCQ|J8kB5CzkdlVEeOko zRNRqUob`?1>6Oi89|rCMRr-f(&&+ z94bRVfCc;`f9=B%O1!kAe?u_TPv5a`(rOD95qUpCK#6{)ViV&KtRXgYGX2QiyK@dz zN3TX0pcf5`hp4l5XHx-~Z^t^xc#S_FYlJJfzK#eZd!^2PT4=4p0tXuR2r+>_LR%G@(WYN%Tu+{ZRL}NU@z-0MBO>X^@9)_B39o|k?cPq!8ZK_3n(G!euFlq)6ikbP)##eGN@3fqaD zvrQFb$5&i=*;G&>={;gf_0M;NT^fvg!$B=v)Y6wx(>Q?Px^7xOIdlUk!{6306mzIY zA}z%coMqhql_Xm)Z!sj6VxJIk_F1p&%=OQ%1aL`9L_+8W(^ao8!+mq41 zWb71EP)LRK0@`nx{mKgJK!^5?-wL(P^O(B-I#a$*IX*KWCH2$|Rw=X@`z|UI`cT{V zj7Es)qA)Fn2NAwcXQ2ra=Ukg2Czx^}MJ~a) zy&MBo2hED1E~^cevSSWB(uy?*Ev}g(1J=tcoXU9K{meUTsPaCntj|zAM5kAx6o9=g z-}l_~XKjyK1;<$$XmQbSyRo3x?k2&?-X3YHeB-q#s7pj}y%^Ey{}&#Me6+K*-hJ+| z-1;Fng8sciWuGhfz$rPFr?tsPRt-#ANoH4b(@t|ffSUj8Cxh+_w!ifJZ;(c`^0+Iq z$5>JNRSI14JflGaW5*wm#?I-QsbB>R>_iI)U*=}q+uqd(^^oAcx89iSve=%x&v40# zB%|z;A7$neY23IKbQ!J@%Hnc7suM9cRJJEw6_X@by`YW;=5Ik;m%y=QDP}poMc&wYSumg6;s9 zwG5!$SnyOUKv#Krf5Wo7axJXDcK5GN8gjg3DgI;Law%QbNQ^I^%f79DL6!8i~4N!CCRULx)5SEAZ`{zG?``|p+>e%J7&z{we-(jHry(Wj0HDmCxzTq(hM z1)%*6&X_-qH1gC7&ij*2IImA^*E@+$W*&m1P(vv_E<6+0qPCuujvVK|I2c)SnfXIykh~1@exo%*Nw!Z6 zNeuOfE=N_9D9{uhfT##^S?XBC|3-*{xiPr&&(Y)1Nh6=YPSB!$1kw@DMVwcf;}1Bi zrg;Y^F~9rF^`s@!KB5l<-S3D#IRFjsu>5SryDi~QwnrsEI+m5`_niCqt0WH;7ZkUz zI#&ARTWQ^3l92|+>brLEO_RP-t<9d67UH~EPlMllnSLZ^>6qpg%JuZ#uer1AKl_wY zOcW3VlS7{(sOX-6Iy2l-?UZc&nuYTdz}zK)X5`LQzdsDa|H*Cezu6a}e1XFDB_&0U z>Tg*2hvE7E;7d=5xcB!03^ejhzq_zz#8p6M_N;1+!FxnTqI;F4w{q5$v$B7Ay0R@* z2khuGam1{2F*Ad$BAm|Cekr;_zj?*c@0FX~sq$~Tn=##2oj!d)iNm4{r=UT2$NE-M zm2q4!oX^frrvD%D-s{6VONq-gcm9RWj8Ru#{jMIJ70~?_Hq7NHqTzD#HEXb1Z|zPC zm-_3chnI85xSX5a*4W)N;dkTTw$!oQF1lQs74Ou?NLNa%(d*aR-FD4J$MX*U^NX%} z$IAG>FxfXgWwIHd9!ztnlRiK2dei`>?&lxgJb@j5Ybm}y>TCuBOLst}IA}u~0JX4= z2+kL)_mWip!}|KaDp#HmkP^Urx@PC-^=elCry_~W;*wFt(^6}XI- zH-7s0Vb{Hj&{#!K+;%(9eXDq=al3QNG#g(>xb98sY?jYui>Ej`Q>@r?3bK^6&oN@^ zZZB_jUY^Fqmju1@u46t`uSE&cfE{Myj2cgT9$!7Xy_&s|RQ>K;g-!|@r|vF`R;~2? z$nzefL5lXA(M(S^`wh2omo?qB3f-Yk(G^TOh3y~1u!~fI4$a8C!SeW9`LDCGdW1pGLRm8 z<_}ur8IfnJU$BEdqxF5zQI=gpF1SWeJLYmdSfIb!v8(&mWeMl7;P%?(busG>>$N_} zxNW-J))+DCdM%;W9h==;yD&1<&KScaRjC{EL~phGzhws9w;YMS-3Kcqz0;6`-<@=G zG8;`JOxJ$%3w~2DHOpFp;@O?X#7<0iLtcoF_?|Ye+6`|7Wb+t-FxpcoKHB4vWw~%5 z6@T3;kyyx6meH+hcn9W*7C;p=S>1O7>7bT{OJqzV(-|ji5L@&gDz})dRdPBM7^|_r z^}j2wFzSc#l;zzs20a#)j)%3>LN2HCNX3rFtw6@$AXE6+YSAl9H{)k}RB%7@R4g}f zUMIc1bRbc#O)8N=Bi9KuvY{i*Rg)UKRRcX%G|mud`z8CqqQSghKC;?{SdFO)=+!2Q z6xg{O7iSfaGoJ-8pK!td(tN91IJCdmFtgHmGdX@2H1)`oqq|15@KvtPJvQp{A7cuJ zfx5hxUwZwBGq1%g=&PNOqgz(T076^mck;1N*NcCxtGmk9%1nF zp4H*3&I6O1NcWWv>}%VIEz5#Ravyn>$VG2pOuSTDhWLV{Wzbs#@VLwo_*=66 zORnY<9PQsV^~YqlKQ9BWh8Z70?4H}}x?2L?6WR*Y4)VD~r!u-JXX>`%ZNGdu>$#NX zCoINI&W8tW++tJE1uC;1_eSzz_Jpcj_SW#7SDZu0YA#TsoTijcJe?PJbeJ?nEWREV%0ip< zyh%IY=LNV@x<<5o{hU4vLK~kcevg~|u^Yl;W$nK_$Z{L+ADQR>wzXh1J&nBRq*0dMHeQ2Yr*1w+9-EQwn#LXACT(=FOkQYoNxh-G~w?{zAI9w0EXjC)d z-yG4oy;ihJ%l>h_X2;NQ!cB^oJICr;s@?b4cl+X4<0ekp0sZd>koK^z{rg3Q<{Cq| zK42^Ul<({^Yeh+o28}~!P;ybYv#ig^p!I(Pe34HIyK;~F6>k$cP+$GABY$3uXRTWJ zp{cFo^_4Qk?wy%gC@6(R=8eBlM7ZPpCu{P7RV*6x&_NUga+d`FIM0NjGP2yl<)9Od314d6mlZ%32^ zz|)_2BG6B;aN@hrWt1i}tNOm8@?O%a*L=Eb1EMrOk4W*~6gAM6`*o+3YiH8;f1_>w zp!Kb2Bs)wR!}^t2`rYU=)hkl{Vo-?Sfo(t22V}))m!}GN>R$Po4}|E5sv+nBMQ8W7%zN`R_)3+2gc@>G`!Ko3_sjFqadL0dB z!dg`6>Md|ZFvf-681nf;*AZzGLe<}k38y_*12Eu^Wl_oCXM4mDtiJI5q2f0Lp>3`8 zgF%|^V$x410`f2t_FAn$mdB4U2^@XA4+npI-&V>)o0e6L56C_mq`_&cygHFrFfi=bR=Vf?$5OWor+zYd|K&>ke+gRtYoPt3+yW!g%lmq2m3 zA8jt=0XQn(KO;O-oVD^jRPB3La74Wt-_X>W>9NF>$kngg>qdG%v}8~gpTgZcSiX+i zKD%~jXnOD@4ZJ5M>}tFFVx+yYi#5J*p~`Zx7w(vQ*6Q%cm@@s@S&M#v2ZV0|x$M-j z*eBn(+*wgJz3*gb@sasJ2@%^)I5Uqtw?mp_VpR&|$!$vhOmzk&vYgl?kaLG7xo_SJ zOR0s}_=HX<;>%fdi1jfuw{$6F$F7VcY^qBZP^>WK ze`w_|bzrMb@HDCJhW~h*d(2XjfAp!acWV7I>yt0^J-!^7m^svtu=+IX!~-%(?SqfT1fbDu2FWIE`|{)kA@qXK z3iIRi*vlrFjDSU9DUEEGKB-P{|#LNMSo`j#5INp~trB%xazP!xita zc;bW_VA{`Y)%<2$a;aevI*_4xV3o0LBVYQG*)+vO_~4>xmXd;*$uJ)48liKQnOiY) zKc8|kHz=WY&4+ag>C{UkmR%<(V6&c%T#uS=#xa6E^Kv3N-+%S{tq>#^lXZhIq!fxg zI$N{rGX*zV&q8I`#Ej3CC)>9%(^YF<$SE6t$$Vr2$;zPQX+>zj34r8@R|=?JBe_;fadYS2Dfog$Hfx8R(H*E9?;S#o?z zU+csRA$KEisHdku!9LEr`njoE4Das}wm*lt@MP3e@gX0=1NaoZ!?Gtv-lJQ?m$z@Y zSK9IUU&;FC@9fve_4u<&Vp4tCLqvV+n}sFg1^GJHc}8L?LC_8+c}zK|Y4skh8VVw} z&$o(ZIaJEMhbejHD~{*X?1cCaQ1}cc0xF-WL;LQhKnN$I>u+OAGr<7#9TE5RIF!zl zvC(Ds=Bi-AVK3SiHmBy^er_>NX=K)2%R0 zg4?4t;J^Gh45R6_g9t)wcZ~C>CsR-G+4|?Kk1gp1^C)0@<5Syov)Aaa#UY7rrr_EF z?N~lQ9ypTEO%LeBtvx`5)2ZI`<2_opm$l;kwdkOgI4dWCz31P9`Plb`Z6&4*Nvidp zb=wZwM)~jCsTz1KNu#tr=fnQytYbnV)kt23wMFtVkOL@h#++;^=N(7=h*hSBmauK@)TxTXhZUcEQtrG+^C-LR z$Ft~SRTK{;gk0W=awzV=%om59!0U<9XRh|^4z8?lTR%OiU_)}2GoVv5+k;)OMcZkn zuQ4`RpQ#*o;ci6qLs#c282a=*HpkZ()`}=#A;MmL&*r`A9&?!N+^iJ0enC(dRSUxS zb4M0>wa9x@5{r@<;aT6SHhO_4#CwYAj&m7d34tA@N`< z-uje|uetL1aVU40K7ZvZhvsu^aPBR8iGqLeypr+HZ%jGgI5>WrxcO0nP}6PPuKnHT zyDy8U0$CeD$9%O_YijSP^0INTba!tbp}^Pyx&DQkQe?w4o}|^e6HEG9W2I?-spGJH zOn-J8VkoYp6`|E8vZ4^u-#gDU#Xn?3&>y77jzbJmU3~W8eDUpVVIha^?78B@St=+Q zPQw#D8=Zj{_y*-`jZaH+;|Yl>LXbS-2@ajX??RL(GV#6q9)Pd0gi(3ec2xMzq(Trn z5jyC3+$J3)B@v!#P6L~>%W*mr z*s}|%KsF0Uc8}$&NBCU)QzW;FcF2~HXph5+8&SN3m`%+aiXxvFwqIX`sHNSjUZOU7 zg2N*#0NpzTR|3E96HhJinr8=k&_i#kx;xX9QRIwyLkp|3H&F=T$2zqv$@1XYSys0(6RhOQFXWMtkP$MU}TO{(!`5&M#t_iluQnW z($n?T7OuOeXWwB%-SUCm#x^Y)Q0#Cz~W_oJ`p7*+FiE z)leC0OQ+5EbW5yH)5aY~u|&(}=M72`Lb(5)B^YgA> zgbM^_W$I?BCEfZ*1qmNg63qMjrm=NP)j_dnuEpQX+JS`hJRk%k35kk4J z9bKm0V$GfZnEFKv4>5tAoikf{p?k*JNZVpr^fK{BuevJBtor|V6rL{ z9C>3FQ!rj=+wf>swrJi&5Xl$T4Gb1!&Bb!>vSZ3UDs*B6h6HOW1+ynt&dq;2c{-Pm0GX87Ra)dNv#xvcPQ4%?CH? zbas@s5zg5>s6SAwsDVC6+#_4y`)=(MZm|B!R7+7}9Ie5_9bYV1h09I|gCwWNP|?6~ z;vqAGE5qg`I9VK4r+8dQ8=KA;&jRb1pNm<2gXh8~!z7Fvq=DUwl@ot-ld$HxD#5 z&M-!jYQLW^J0W;y4t%!thtg$6-h*G}!(@)v#;L69U<#Zr*YER`s#=VwXtR=-FDgz- z?UiJqXX@1E6H|OT?LLl``3@%Bv?@74INVfjn*+yHjENf)iW~jm?5G-oht6^tbn0I& zf~j7~eaZf~86VY@`?q>|My zW*XoSC)6jXR5>1dg&?UtA5c$T`$$fpx`x~my3+91Ize7S=pY)ebVjHfjowIZhyTdN z8}|F^c2>XSUt4*+0Pi(bWmcoa8-yt!qp)L6!T+5ng4g!@7KWPLj|0-wbv*1=@ZvmD zHm^3sl&4bZNn@G`y^TYJ6B|j_I@$NfMl%4^@1f-laOK;2s|? zGGf-JD)%Oz*tpZ|;iGZ?rHX?g!OGqMp7X1W%fLi>d4ZG@5nhqNTT>X06x9WyVQ zs!{Rs%*5dF^w7A1)M#J+>*jP(UK78WWG!P_>BjApq80*I~ebJM|sja!2yciTk9h+ioGlw}te|l~S zjr3VXZ2MqU`Fv>=dP}0keaiOIhspNcLij~{#oW5M>SD&X~plRF0`UBE-g zK($U!@z-$(-Dt?##HXc<25}bqtEKO-5lLBr(XWKWdNglO1<0@3o@t3L#Vl~&AFF(D z9DUEdE@P57m{ctUTVFjYV>vdkOx9*>ZdIWU1RT?t62!QvHWQH zQhe@EiYHVn074Z_LOGZ(e)P42#kfQJ7?fmnP(~$|hP6QPM)#hOT z?Pb?E-X?vog}8pOBCO>TdXG#-{dfU$(4;HvZ;;n7&RMLGmH2}=S zxS}SDSHb^%kUw3)xn>_7pCUNgY*d_^(iJcFOC7wS!9%IGWs375o95X}Ww~I}0JXgl zR_nncRZ?#b>Rt=M0#!}I*o3LgJ>ZZR$>hA%{gp28*tX1NS+7aO?E^(z|yOHIo zwLficn`a?$-%~x?Cxmz7kO5O}NL`aPfM_Q}FS9@DwDCSbMOi zL|E{+4MOuuhn>6m-b1X1$Q;tI_;sgXiZo1^$JAWXMW5Xfp|&<5R0zpGCMA+xA%uJZ z(T{z8;T<%Tfa%+y*7h)CDTH^eQV`0sz}5PI*TcbdrmXETxeyU-B$qBq*<*zf^QT}! zU%G`qEuw7hp{F?&*J+2PBI&KTKWz!|Lth-y1aEyVB&VJ-TG*a*^K8o@YSH?}MHLQazd@l-Z6c{xq? z-Ll&0RdY4-17B)-+EwF(Qr&|q(CD~|5$jsptz@Zpiy6~_VlQbkQdKo3#N{~+8I0^5RT#~ODQkMw zB_mBs?Fd5H1q#keNmGvJI2}YE);l%wsPPfer_CTv-qDfv5tjR*Ud_^9YAR(IRhRV> zu&?MO3*PL4(_rIie|~QZ)o3KN%>NHz5IUfm;txT?0>9;_a8xA&^N2-5b_>kJkM>@n z#}rzPcM=7x-Yf5|Za>!-+^-^y&W;du{Wye6cJ&%Nsgv8LTKB#0m4ZXnp5l5FuTLmF zCUF*B*BYbEr-hR+G6dY{SxiP&pW!k{HqwgFda~vNN}#Vsbg~KD#Kr!^rUso(vNcYwqWGdGicx=o0835-+jxkl-AD@BoOoiR8s2h_7K5B2vGV$x=kM= zrj)x}5sR+FI3w0zpBM8#{Ire1;kV+5y@U0 z&#UCyc^v~eQKOh4!X%R(ug_8%G_Wbz41-?fOv%I=>b61sZuETwh74XqYngfKzEY9N zyNTxas`yInWUyNY-?Z*{KyIyqM4yi7YHT{xDhoh4_z)Mh$cPmfTlKScP5`)ODj}0h zAZ#n!BdS*0p-&Sk2#e<==o?ITZF{Q4V>>f4j0t!5*uEpW`r^NDnYMMUOk+ovo4UXnY?Ntco# z-D`7totdSd`TTOcXg>Qy0fc@O-U;C!s?Uwo2=}rxk|EO6-t3i2xQ|$m8A$lk`p{d> z^JvD^tYN4jN)fenaRiq*{Q=oVPb@^SC>dykt$oE6aM?W*sRa;yxezIAb`mjvHmIVX ziYkrI9QKgG04o`_WV0nQOT$Hx`OcrVo1_^H(tgT!z+M*q%V{b_d{wc*U(W8JdR6@% z9-}H$MSiWcl0E@TMM)Ev-iJJ4&@_psuIJ}1KAE!3Ict)FMBw4wY*~!AfT)d- zBgmcOP;h5?_5TjLAKK7bfXyjJ1`2v23rTzlDWe4GAeL_>X|41F$z_^~yutNq2X`j2y$hOpe&Y z!yByAtGmZY2}9zWFM`u{djbiSdpR)YOIMQti1M5CJ|2BW{UDT{-e&a zlQy{0%%x^`9Q*3jmaE-{^0Y(g?k@)G`3)NDo6dJn==dCYz*4_p04jrN|1t&^$gtg+>rkmBt+^Z&{CK6w9ci)_y_ByGi6lOsQlS)`*NeTGQo*MzGsxNr$5-8_F;oAs=UcC zS$X19hYzQc`FVnxvp04dJ5B#Wh{c`|S8&1UYcH9!Vr>!k$M;O8l6H5l$r;ITn)ns% z7OJzIuDt_L`gTWWcXGCPiPLcVQXE(BTd$8!9#ALMU3?c4+uY@Lk}QlrJ(x~97-zky zZez+H;nM-btS2A?Plw!{EBS}J%3XZx`OaG=gDC-voB=`w&px&#@+Tf5656~1$Cl`? zu`O1kny>kOGqe*_k;?%hB5ZMpi!FQOeIDXd+fOsjSHj0Vc~Cm~r5UG39SonF3Brm# zdy8W=K1neF?G`dN{`uAK&(Q{~f}bt2*=&U2G%>;VFP~WPUa3|*fPQ~=?;gZbRDf6R zLghM|@sSTbMf3-f<%j@P>&+eFbDUTFs`FPglc#=A3NnIL@E*YoAXj5rNj*z!yF+1j zdAa)4k(3<8T^v-uyO(|)fB@65KdXx$k6`7-z9sWb)%xdv%f!cs0vu9P_>GSjdDUM| zfU@-($ASx#T&R|}B9w#v;rRFYk*l z7D;$x*n~Cq4$Z>_m!^D#20rSaxB^ zgC#@2wwH${A@q%}?T0T{LrRJ7V`h=YBk&JL6W!aEDgeQ@_dy3Z54;csVSQ~951zMZ>GXJxOG3p9HOb)5+f=?KT*~QMFBu%ERN? zJuqjl&o#cqM=lTbDDVAX2NteXM?N3i{~aOj{~JOi6Tp17eC;ijX{};|aO^tgw%1q) zAXLuD!L^Iq1)rf|zvt3{c?yzxPM24PaW4v~E9@+FStIdhdPuVaC^gLxuQg!%#XE z;^h^HT01d+pMC?&;k)iKf+$Pf>0Zo|U!}oK3?CdJp9dzx zCQ30R6eS%XxHr#zH`)o^e_8s|erT_K?C52}61RK7T-g?>A`O5-cL1B6~&f z)E8c!fof>$)a>pVKl0D80e;SF6htKL{*lNri7WBYkO>W^LDHE+PEwB&4qW!OM<$Gu z7ymiHM4T--XUm=n^qodP1`hrK2md)^&Gm=_u@@KCY*(8DPz@;sjbh7@L~-qZO>U|( zUSbkm@6{H<;e6L+ZzQ_p!s3N25Yzdl>Zu8?Z%{IBT=fzv@RtNBP(bP0UGr|t88 zQk^eQqRIsSbH@8)J^1%25s~oIqyHcOC^gH<_g$pZ>*s?P4roq~346Rr2FMNIxBEXj z^vMEp=8lB8GZwt|%-`=Q(iLbkeY}w)In6n%%qMc_ic84eLeg$;SLlnS4dluHoGz^b z#pOlsHw;q{fEkk#%$W5LT70vvTWCN1=O8T75J|je9y2Qopb%Uz6ilJNCyc*@;=Rud zsUjkqbDKfaq(f%^`I-JpTKo6a_^*-kZr=V23IDTw(iu*AaMOhXleX4JCoumPNd=$# zpGlMa#!$pc?+80{fblcOu_^nP%`AWklhb>ne`q_TJ}kZNW1Swln>#PI;3+wo&e-QC z5RD4{;kJwdfFE6!ZssZrP3EORNDsURzQ;G^0yc{sKiJ`%FT3TuqV@F&oc!sD6sn{? zH};=V5@8tkPPT{x!7JkUwGTi(t~p1No099IwoMfIYVrH(a3B)7Zsj;F;4Yu zpekul-Qv5a$o+eAU>X6kLC)RSSDYJa?K%&E;8eK;JYS7uz6H zI=sJPW`cvuzUp9W6h_i53pmO}fs+p&oX1WSu1YKQml}3Fu|65F-v5wXo#j|Qp>Dww zWC@Hfr3GAXW(wRWn1*V+rLawiQ#t>+wV3KqQ>bMiDg&o{lid!GfyD2B#%gFe z!%V(CH6F2T?%e*%H&y{dKc1p`IMPLE<Ij2Y(_RORJJeoAOr zx8gZ?+qP^x42G)DcM?Hj-NhW@OWSW~vc*eh6M2*xiTUR(R01Ttj>++%oC1wL_7Vl$ zSK9$DI_IXr8AuO4U40o`#;nwa_$pU6rE%yA)FQsS<`6OD^QG;H+@2R4{q}V%>FU}f zBjAe8hupRnL^eI?If)9O8MDkpDfT3t|&LL~nF}(BC6`Lqgot z<#}?{&HE8h`!X6}Y6Ehdzy@J_xAam9Db?_KPF=_T`r+tO8_MHd(~D=A`3ku+B=aPe z65kmB5PHmKDr@J-?sBd#eHnYaOq2@xfO9DyG@{IR6`l{K=7EWCpRjt(R09f81)|kq zfcwKiIUoz)EGV_D28K`Q4zw=8-gk0bg^ zv!QZXIsIOG?^%3KSx+G@d6|#gs0;?Q>QRgW(1YqJr#V!1+oJ%SCgT#VP1-)EhAB@{ zyoPkwN4bRkX-)pNb{v^mvc=qDfOnm^mgxYscBd5cN;`n zL^?|xlIV25d^LyQ%x`*e@t+%();D^uU$V8zKvoN;tR}Rd%M4X<-%`!|H2<{1iD)GC z_Z<%@0QFoNS}=W5@-2TnS2Cdv+W>K;3ydD!0aq#+kLu&?rRDLln z>izc~4=>^gbp#^_2yaGeKJJ^W$2hZtmsKoO!!Gx-Jn&s+tbZ{%pf)0{Ho;jhbn9h& zIykZ;GPe?WKFZH2faB3?R;Tz@^xPB({sgH%N$!WO_o>wqvS}!FA*tu-WYDsuAZb6* z$+DNDB9t8heElosO5WB0N9KTc!Tug?1#1_;X2xTCn@>nXP8jyt=iwJcM-n5w)mT>fL$ z&eyw2{6DO5TmN&Jcg%z8Y46rNy?VpU>6S9Ap$i=Kv3Dqm{h-oq!itcxcK$|RI}4Qap{)d7=Xaj)z4*}Q$iB}Y0Z-P literal 0 HcmV?d00001 From 74f73969ad84ecd754c36f298088967b98b54205 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 31 Mar 2023 17:08:58 +0200 Subject: [PATCH 793/898] Remove "preview" data from representation (#4759) * Remove "preview" data from representation * pop "preview" from component in standalone publisher --------- Co-authored-by: Jakub Trllo Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- openpype/hosts/blender/plugins/publish/extract_playblast.py | 1 - openpype/hosts/maya/plugins/publish/extract_playblast.py | 1 - openpype/hosts/photoshop/plugins/publish/extract_review.py | 1 - .../standalonepublisher/plugins/publish/collect_context.py | 4 +++- openpype/plugins/publish/extract_review.py | 1 - 5 files changed, 3 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/blender/plugins/publish/extract_playblast.py b/openpype/hosts/blender/plugins/publish/extract_playblast.py index 5c3a138c3ad..196e75b8ccb 100644 --- a/openpype/hosts/blender/plugins/publish/extract_playblast.py +++ b/openpype/hosts/blender/plugins/publish/extract_playblast.py @@ -116,7 +116,6 @@ def process(self, instance): "frameStart": start, "frameEnd": end, "fps": fps, - "preview": True, "tags": tags, "camera_name": camera } diff --git a/openpype/hosts/maya/plugins/publish/extract_playblast.py b/openpype/hosts/maya/plugins/publish/extract_playblast.py index 72b14895222..27bd7dc8eab 100644 --- a/openpype/hosts/maya/plugins/publish/extract_playblast.py +++ b/openpype/hosts/maya/plugins/publish/extract_playblast.py @@ -241,7 +241,6 @@ def process(self, instance): "frameStart": start, "frameEnd": end, "fps": fps, - "preview": True, "tags": tags, "camera_name": camera_node_name } diff --git a/openpype/hosts/photoshop/plugins/publish/extract_review.py b/openpype/hosts/photoshop/plugins/publish/extract_review.py index 01022ce0b29..9d7eff02113 100644 --- a/openpype/hosts/photoshop/plugins/publish/extract_review.py +++ b/openpype/hosts/photoshop/plugins/publish/extract_review.py @@ -129,7 +129,6 @@ def _generate_mov(self, ffmpeg_path, instance, fps, no_of_frames, "frameStart": 1, "frameEnd": no_of_frames, "fps": fps, - "preview": True, "tags": self.mov_options['tags'] }) diff --git a/openpype/hosts/standalonepublisher/plugins/publish/collect_context.py b/openpype/hosts/standalonepublisher/plugins/publish/collect_context.py index a7746530e74..96aaae23dc2 100644 --- a/openpype/hosts/standalonepublisher/plugins/publish/collect_context.py +++ b/openpype/hosts/standalonepublisher/plugins/publish/collect_context.py @@ -255,7 +255,9 @@ def create_instance(self, context, in_data): if ext.startswith("."): component["ext"] = ext[1:] - if component["preview"]: + # Remove 'preview' key from representation data + preview = component.pop("preview") + if preview: instance.data["families"].append("review") component["tags"] = ["review"] self.log.debug("Adding review family") diff --git a/openpype/plugins/publish/extract_review.py b/openpype/plugins/publish/extract_review.py index 8709d3bb03b..6b2fd32a2a8 100644 --- a/openpype/plugins/publish/extract_review.py +++ b/openpype/plugins/publish/extract_review.py @@ -414,7 +414,6 @@ def _render_output_definitions( }) # Force to pop these key if are in new repre - new_repre.pop("preview", None) new_repre.pop("thumbnail", None) if "clean_name" in new_repre.get("tags", []): new_repre.pop("outputName") From 26d1c8df556facf9c03b5bc5eef9b5fb3f6a05b8 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Fri, 31 Mar 2023 17:25:19 +0100 Subject: [PATCH 794/898] Update openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py Co-authored-by: Roy Nieterau --- .../hosts/maya/plugins/publish/extract_arnold_scene_source.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index 2ac9d4c6a2e..83295683db7 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -142,7 +142,7 @@ def _extract(self, nodes, attribute_data, kwargs): # Only interested in transforms with shapes. shapes = cmds.listRelatives( node, shapes=True, noIntermediate=True - ) or [] + ) if not shapes: continue From 90113168cfc129953ab3924d0bd91fbc7d646130 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 31 Mar 2023 17:53:32 +0100 Subject: [PATCH 795/898] Doc string for shading_engine_assignments --- .../hosts/maya/tools/mayalookassigner/arnold_standin.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py index 08e7746eda7..64fab2fa27e 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py +++ b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py @@ -79,6 +79,14 @@ def get_nodes_by_id(standin): def shading_engine_assignments(shading_engine, attribute, nodes, assignments): + """Full assignments with shader or disp_map. + + Args: + shading_engine (string): Shading engine for material. + attribute (string): "surfaceShader" or "displacementShader" + nodes: (list): Nodes paths relative to aiStandIn. + assignments (dict): Assignments by nodes. + """ shader_inputs = cmds.listConnections( shading_engine + "." + attribute, source=True ) From 89f9003c91dd324c58857b124bd2237ef956203f Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Fri, 31 Mar 2023 19:31:54 +0100 Subject: [PATCH 796/898] Update openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py --- .../hosts/maya/plugins/publish/extract_arnold_scene_source.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index 83295683db7..7f063f15580 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -173,6 +173,7 @@ def _extract(self, nodes, attribute_data, kwargs): # Copy cbId to mtoa_constant. for node in duplicate_nodes: + # Converting Maya hierarchy separator "|" to Arnold separator "/". nodes_by_id[lib.get_id(node)].append(node.replace("|", "/")) with lib.attribute_values(attribute_data): From e244778b3a399645b60f82f20ac48010467c6309 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 31 Mar 2023 19:41:22 +0100 Subject: [PATCH 797/898] Log --- openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py index 64fab2fa27e..7eeeb725530 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py +++ b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py @@ -74,6 +74,10 @@ def get_nodes_by_id(standin): json_path = os.path.join(os.path.dirname(path), f) break + if not json_path: + log.warning("Could not find json file for {}.".format(standin)) + return {} + with open(json_path, "r") as f: return json.load(f) From b17f5218fe7c02885e8a163fe42ed7c2c031f815 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 31 Mar 2023 19:42:50 +0100 Subject: [PATCH 798/898] Hound --- .../hosts/maya/plugins/publish/extract_arnold_scene_source.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index 7f063f15580..14bcc71da6c 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -173,7 +173,8 @@ def _extract(self, nodes, attribute_data, kwargs): # Copy cbId to mtoa_constant. for node in duplicate_nodes: - # Converting Maya hierarchy separator "|" to Arnold separator "/". + # Converting Maya hierarchy separator "|" to Arnold + # separator "/". nodes_by_id[lib.get_id(node)].append(node.replace("|", "/")) with lib.attribute_values(attribute_data): From aa8b4b970b258415d1a7238d88e1200cc48f9de6 Mon Sep 17 00:00:00 2001 From: Ynbot Date: Sat, 1 Apr 2023 03:25:23 +0000 Subject: [PATCH 799/898] [Automated] Bump version --- openpype/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/version.py b/openpype/version.py index 4d6ee5590e3..77b853aa9cd 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.15.4-nightly.1" +__version__ = "3.15.4-nightly.2" From 73e173b7d7fac68c14334467b64414d51d8e2ecc Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Sat, 1 Apr 2023 14:37:08 +0200 Subject: [PATCH 800/898] project action > removing expression from if --- .github/workflows/project_actions.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index f425b233d4b..95e63b564fa 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -25,8 +25,8 @@ jobs: name: pr_size_label runs-on: ubuntu-latest if: | - ${{(github.event_name == 'pull_request' && github.event.action == 'assigned') - || (github.event_name == 'pull_request' && github.event.action == 'opened')}} + (github.event_name == 'pull_request' && github.event.action == 'assigned') || + (github.event_name == 'pull_request' && github.event.action == 'opened') steps: - name: Add size label @@ -49,8 +49,8 @@ jobs: name: pr_branch_label runs-on: ubuntu-latest if: | - ${{(github.event_name == 'pull_request' && github.event.action == 'assigned') - || (github.event_name == 'pull_request' && github.event.action == 'opened')}} + (github.event_name == 'pull_request' && github.event.action == 'assigned') || + (github.event_name == 'pull_request' && github.event.action == 'opened') steps: - name: Label PRs - Branch name detection uses: ffittschen/pr-branch-labeler@v1 @@ -61,8 +61,8 @@ jobs: name: pr_globe_label runs-on: ubuntu-latest if: | - ${{(github.event_name == 'pull_request' && github.event.action == 'assigned') - || (github.event_name == 'pull_request' && github.event.action == 'opened')}} + (github.event_name == 'pull_request' && github.event.action == 'assigned') || + (github.event_name == 'pull_request' && github.event.action == 'opened') steps: - name: Label PRs - Globe detection uses: actions/labeler@v4.0.3 From c3e3f592e0e79ab270d1d1fdbe283dab0e94a33a Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Sat, 1 Apr 2023 22:31:02 +0200 Subject: [PATCH 801/898] updating project actions for `Review in Progress` disabling Changes Requested they will be refactored --- .github/workflows/project_actions.yml | 37 +++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index 95e63b564fa..36b88f2886c 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -5,21 +5,48 @@ on: types: [opened, assigned] pull_request_review: types: [submitted] + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] jobs: - pr_review_requested: - name: pr_review_requested + pr_review_started: + name: pr_review_started runs-on: ubuntu-latest - if: github.event_name == 'pull_request_review' && github.event.review.state == 'changes_requested' + # ----------------------------- + # conditions are: + # - PR issue comment which is not form Ynbot + # - PR review comment which is not Hound (or any other bot) + # - PR review submitted which is not from Hound (or any other bot) and is not 'Changes requested' + # ----------------------------- + if: | + (github.event_name == 'issue_comment' && github.event.comment.user.id != 82967070) || + (github.event_name == 'pull_request_review_comment' && github.event.comment.user.type != 'Bot') || + (github.event_name == 'pull_request_review' && github.event.review.state != 'changes_requested' && github.event.review.user.type != 'Bot') steps: - - name: Move PR to 'Change Requested' + - name: Move PR to 'Review In Progress' uses: leonsteinhaeuser/project-beta-automations@v2.1.0 with: gh_token: ${{ secrets.YNPUT_BOT_TOKEN }} organization: ynput project_id: 11 resource_node_id: ${{ github.event.pull_request.node_id }} - status_value: Change Requested + status_value: Review In Progress + + # pr_review_requested: + # name: pr_review_requested + # runs-on: ubuntu-latest + # if: github.event_name == 'pull_request_review' && github.event.review.state == 'changes_requested' + # steps: + # - name: Move PR to 'Change Requested' + # uses: leonsteinhaeuser/project-beta-automations@v2.1.0 + # with: + # gh_token: ${{ secrets.YNPUT_BOT_TOKEN }} + # organization: ynput + # project_id: 11 + # resource_node_id: ${{ github.event.pull_request.node_id }} + # status_value: Change Requested size-label: name: pr_size_label From 8f42a4351fe49fb389350eda408d57a003cfd5da Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Sat, 1 Apr 2023 22:42:06 +0200 Subject: [PATCH 802/898] project worlfow adding switch --- .github/workflows/project_actions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index 36b88f2886c..0d097331d7e 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -31,7 +31,7 @@ jobs: gh_token: ${{ secrets.YNPUT_BOT_TOKEN }} organization: ynput project_id: 11 - resource_node_id: ${{ github.event.pull_request.node_id }} + resource_node_id: ${{ github.event.pull_request.node_id }} || ${{ github.event.issue.node_id }} status_value: Review In Progress # pr_review_requested: From 5fa64d9af90ace6b3a8aed3f74c050788bebad09 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Sat, 1 Apr 2023 22:44:19 +0200 Subject: [PATCH 803/898] project action: improving switch expression --- .github/workflows/project_actions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index 0d097331d7e..8ee869be93d 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -31,7 +31,7 @@ jobs: gh_token: ${{ secrets.YNPUT_BOT_TOKEN }} organization: ynput project_id: 11 - resource_node_id: ${{ github.event.pull_request.node_id }} || ${{ github.event.issue.node_id }} + resource_node_id: ${{ github.event.pull_request.node_id || github.event.issue.node_id }} status_value: Review In Progress # pr_review_requested: From ee22eff316ac63618153c223c5dc8eb82bd9e061 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Sun, 2 Apr 2023 23:04:17 +0200 Subject: [PATCH 804/898] project action > changes requested CU task In progress --- .github/workflows/project_actions.yml | 44 +++++++++++++++++++-------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index 8ee869be93d..6e56f125ea8 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -11,6 +11,7 @@ on: types: [created] jobs: + pr_review_started: name: pr_review_started runs-on: ubuntu-latest @@ -34,19 +35,36 @@ jobs: resource_node_id: ${{ github.event.pull_request.node_id || github.event.issue.node_id }} status_value: Review In Progress - # pr_review_requested: - # name: pr_review_requested - # runs-on: ubuntu-latest - # if: github.event_name == 'pull_request_review' && github.event.review.state == 'changes_requested' - # steps: - # - name: Move PR to 'Change Requested' - # uses: leonsteinhaeuser/project-beta-automations@v2.1.0 - # with: - # gh_token: ${{ secrets.YNPUT_BOT_TOKEN }} - # organization: ynput - # project_id: 11 - # resource_node_id: ${{ github.event.pull_request.node_id }} - # status_value: Change Requested + pr_review_requested: + # ----------------------------- + # Resets Clickup Task status to 'In Progress' after 'Changes Requested' were submitted to PR + # It only runs if custom clickup task id was found in ref branch of PR + # ----------------------------- + name: pr_review_requested + runs-on: ubuntu-latest + if: github.event_name == 'pull_request_review' && github.event.review.state == 'changes_requested' + steps: + - name: Set branch env + run: echo "BRANCH_NAME=${{ github.event.pull_request.head.ref}}" >> $GITHUB_ENV + - name: Get ClickUp ID from ref head name + id: get_cuID + run: | + echo ${{ env.BRANCH_NAME }} + echo "cuID=$(echo $BRANCH_NAME | sed 's/.*\/\(OP\-[0-9]\{4\}\).*/\1/')" >> $GITHUB_OUTPUT + + - name: Print ClickUp ID + run: echo ${{ steps.get_cuID.outputs.cuID }} + + - name: Move found Clickup task to 'Review in Progress' + if: steps.get_cuID.outputs.cuID + run: | + curl -i -X PUT \ + 'https://api.clickup.com/api/v2/task/${{ steps.get_cuID.outputs.cuID }}?custom_task_ids=true&team_id=${{secrets.CLICKUP_TEAM_ID}}' \ + -H 'Authorization: ${{secrets.CLICKUP_API_KEY}}' \ + -H 'Content-Type: application/json' \ + -d '{ + "status": "in progress" + }' size-label: name: pr_size_label From 007b2a6853707e6659fd9ce4e2685a34bec1e1e4 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 3 Apr 2023 12:04:34 +0200 Subject: [PATCH 805/898] Documentation: Add Extract Burnin documentation (#4765) * Add Extract Burnin documentation * Add links / fix links * Simplify documentation * Remove mention of houdini --- .../settings_project_global.md | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/website/docs/project_settings/settings_project_global.md b/website/docs/project_settings/settings_project_global.md index 821585ae21d..2de9038f3f1 100644 --- a/website/docs/project_settings/settings_project_global.md +++ b/website/docs/project_settings/settings_project_global.md @@ -194,6 +194,74 @@ A profile may generate multiple outputs from a single input. Each output must de - Nuke extractor settings path: `project_settings/nuke/publish/ExtractReviewDataMov/outputs/baking/add_custom_tags` - Filtering by input length. Input may be video, sequence or single image. It is possible that `.mp4` should be created only when input is video or sequence and to create review `.png` when input is single frame. In some cases the output should be created even if it's single frame or multi frame input. + +### Extract Burnin + +Plugin is responsible for adding burnins into review representations. + +Burnins are text values painted on top of input and may be surrounded with box in 6 available positions `Top Left`, `Top Center`, `Top Right`, `Bottom Left`, `Bottom Center`, `Bottom Right`. + +![presets_plugins_extract_burnin](../assets/presets_plugins_extract_burnin_01.png) + +The Extract Burnin plugin creates new representations based on plugin presets, representations in instance and whether the reviewable matches the profile filter. +A burnin can also be directly linked by name in the output definitions of the [Extract Review plug-in settings](#extract-review) so _can_ be triggered without a matching profile. + +#### Burnin formatting options (`options`) + +The formatting options define the font style for the burnin texts. +The X and Y offset define the margin around texts and (background) boxes. + +#### Burnin profiles (`profiles`) + +Plugin process is skipped if `profiles` are not set at all. Profiles contain list of profile items. Each burnin profile may specify filters for **hosts**, **tasks** and **families**. Filters work the same way as described in [Profile Filters](#profile-filters). + +#### Profile burnins + +A burnin profile may set multiple burnin outputs from one input. The burnin's name represents the unique **filename suffix** to avoid overriding files with same name. + +| Key | Description | Type | Example | +| --- | --- | --- | --- | +| **Top Left** | Top left corner content. | str | "{dd}.{mm}.{yyyy}" | +| **Top Centered** | Top center content. | str | "v{version:0>3}" | +| **Top Right** | Top right corner content. | str | "Static text" | +| **Bottom Left** | Bottom left corner content. | str | "{asset}" | +| **Bottom Centered** | Bottom center content. | str | "{username}" | +| **Bottom Right** | Bottom right corner content. | str | "{frame_start}-{current_frame}-{frame_end}" | + +Each burnin profile can be configured with additional family filtering and can +add additional tags to the burnin representation, these can be configured under +the profile's **Additional filtering** section. + +:::note Filename suffix +The filename suffix is appended to filename of the source representation. For +example, if the source representation has suffix **"h264"** and the burnin +suffix is **"client"** then the final suffix is **"h264_client"**. +::: + +**Available keys in burnin content** + +- It is possible to use same keys as in [Anatomy](admin_settings_project_anatomy.md#available-template-keys). +- It is allowed to use Anatomy templates themselves in burnins if they can be filled with available data. + +- Additional keys in burnins: + + | Burnin key | Description | + | --- | --- | + | frame_start | First frame number. | + | frame_end | Last frame number. | + | current_frame | Frame number for each frame. | + | duration | Count number of frames. | + | resolution_width | Resolution width. | + | resolution_height | Resolution height. | + | fps | Fps of an output. | + | timecode | Timecode by frame start and fps. | + | focalLength | **Only available in Maya**

    Camera focal length per frame. Use syntax `{focalLength:.2f}` for decimal truncating. Eg. `35.234985` with `{focalLength:.2f}` would produce `35.23`, whereas `{focalLength:.0f}` would produce `35`. | + +:::warning +`timecode` is a specific key that can be **only at the end of content**. (`"BOTTOM_RIGHT": "TC: {timecode}"`) +::: + + ### IntegrateAssetNew Saves information for all published subsets into DB, published assets are available for other hosts, tools and tasks after. From 34528b6eeb26c6d463b3e9a7b0afbd3937866d99 Mon Sep 17 00:00:00 2001 From: Thomas Fricard <51854004+friquette@users.noreply.github.com> Date: Mon, 3 Apr 2023 12:11:53 +0200 Subject: [PATCH 806/898] Deactivate closed Kitsu projects on OP (#4619) * update openpype projects status from kitsu settings * fix linting errors * get all projects and verify the project status for each project * optimizing project status name verification * sync only if project exists and is active in OP * remove noqa Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> * break from all_status for loop and add comment for non sync projects --------- Co-authored-by: jeremy.oblet Co-authored-by: Thomas Fricard Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- .../modules/kitsu/utils/update_op_with_zou.py | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/openpype/modules/kitsu/utils/update_op_with_zou.py b/openpype/modules/kitsu/utils/update_op_with_zou.py index 1f38648dfa4..4f4f0810bc3 100644 --- a/openpype/modules/kitsu/utils/update_op_with_zou.py +++ b/openpype/modules/kitsu/utils/update_op_with_zou.py @@ -329,6 +329,7 @@ def write_project_to_op(project: dict, dbcon: AvalonMongoDB) -> UpdateOne: "code": project_code, "fps": float(project["fps"]), "zou_id": project["id"], + "active": project['project_status_name'] != "Closed", } ) @@ -379,7 +380,7 @@ def sync_all_projects( # Iterate projects dbcon = AvalonMongoDB() dbcon.install() - all_projects = gazu.project.all_open_projects() + all_projects = gazu.project.all_projects() for project in all_projects: if ignore_projects and project["name"] in ignore_projects: continue @@ -404,7 +405,21 @@ def sync_project_from_kitsu(dbcon: AvalonMongoDB, project: dict): if not project: project = gazu.project.get_project_by_name(project["name"]) - log.info("Synchronizing {}...".format(project["name"])) + # Get all statuses for projects from Kitsu + all_status = gazu.project.all_project_status() + for status in all_status: + if project['project_status_id'] == status['id']: + project['project_status_name'] = status['name'] + break + + # Do not sync closed kitsu project that is not found in openpype + if ( + project['project_status_name'] == "Closed" + and not get_project(project['name']) + ): + return + + log.info(f"Synchronizing {project['name']}...") # Get all assets from zou all_assets = gazu.asset.all_assets_for_project(project) @@ -429,6 +444,9 @@ def sync_project_from_kitsu(dbcon: AvalonMongoDB, project: dict): log.info("Project created: {}".format(project_name)) bulk_writes.append(write_project_to_op(project, dbcon)) + if project['project_status_name'] == "Closed": + return + # Try to find project document if not project_dict: project_dict = get_project(project_name) From 7facba7905059d9bde7034e8a73bf1ce3b221733 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 3 Apr 2023 12:28:52 +0200 Subject: [PATCH 807/898] Update documentation --- website/docs/project_settings/settings_project_global.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/project_settings/settings_project_global.md b/website/docs/project_settings/settings_project_global.md index 2de9038f3f1..c17f7078302 100644 --- a/website/docs/project_settings/settings_project_global.md +++ b/website/docs/project_settings/settings_project_global.md @@ -255,7 +255,7 @@ suffix is **"client"** then the final suffix is **"h264_client"**. | resolution_height | Resolution height. | | fps | Fps of an output. | | timecode | Timecode by frame start and fps. | - | focalLength | **Only available in Maya**

    Camera focal length per frame. Use syntax `{focalLength:.2f}` for decimal truncating. Eg. `35.234985` with `{focalLength:.2f}` would produce `35.23`, whereas `{focalLength:.0f}` would produce `35`. | + | focalLength | **Only available in Maya and Houdini**

    Camera focal length per frame. Use syntax `{focalLength:.2f}` for decimal truncating. Eg. `35.234985` with `{focalLength:.2f}` would produce `35.23`, whereas `{focalLength:.0f}` would produce `35`. | :::warning `timecode` is a specific key that can be **only at the end of content**. (`"BOTTOM_RIGHT": "TC: {timecode}"`) From 6353251ee0f967aea5a7aa17b16e55ffcf7b1c04 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 3 Apr 2023 12:29:58 +0200 Subject: [PATCH 808/898] Cosmetics --- website/docs/pype2/admin_presets_plugins.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/website/docs/pype2/admin_presets_plugins.md b/website/docs/pype2/admin_presets_plugins.md index 0491ce70b31..6a057f4bb45 100644 --- a/website/docs/pype2/admin_presets_plugins.md +++ b/website/docs/pype2/admin_presets_plugins.md @@ -294,16 +294,16 @@ If source representation has suffix **"h264"** and burnin suffix is **"client"** - Additional keys in burnins: - | Burnin key | Description | - |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| --- | - | frame_start | First frame number. | - | frame_end | Last frame number. | - | current_frame | Frame number for each frame. | - | duration | Count number of frames. | - | resolution_width | Resolution width. | - | resolution_height | Resolution height. | - | fps | Fps of an output. | - | timecode | Timecode by frame start and fps. | + | Burnin key | Description | + | --- | --- | + | frame_start | First frame number. | + | frame_end | Last frame number. | + | current_frame | Frame number for each frame. | + | duration | Count number of frames. | + | resolution_width | Resolution width. | + | resolution_height | Resolution height. | + | fps | Fps of an output. | + | timecode | Timecode by frame start and fps. | | focalLength | **Only available in Maya and Houdini**

    Camera focal length per frame. Use syntax `{focalLength:.2f}` for decimal truncating. Eg. `35.234985` with `{focalLength:.2f}` would produce `35.23`, whereas `{focalLength:.0f}` would produce `35`. | :::warning From e218fb4b6d0d24581c35d5a935058bfbecc918b9 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Mon, 3 Apr 2023 12:58:28 +0100 Subject: [PATCH 809/898] Update openpype/hosts/maya/plugins/publish/extract_gpu_cache.py Co-authored-by: Roy Nieterau --- openpype/hosts/maya/plugins/publish/extract_gpu_cache.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py index deee4569821..422f5ad019b 100644 --- a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py +++ b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py @@ -20,6 +20,8 @@ class ExtractGPUCache(publish.Extractor): useBaseTessellation = True def process(self, instance): + cmds.loadPlugin("gpuCache", quiet=True) + staging_dir = self.staging_dir(instance) filename = "{}_gpu_cache".format(instance.name) From 12084d1f9ed9aaf91f66ae9cd856c02c843729e1 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Mon, 3 Apr 2023 14:09:51 +0200 Subject: [PATCH 810/898] Maya: Validate Render Settings. (#4735) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixes error message when using attribute validation * BigRoy feedback * Failsafe for empty values. --------- Co-authored-by: Jakub Ježek --- .../publish/validate_rendersettings.py | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_rendersettings.py b/openpype/hosts/maya/plugins/publish/validate_rendersettings.py index 53f340cd2c0..ebf7b3138d1 100644 --- a/openpype/hosts/maya/plugins/publish/validate_rendersettings.py +++ b/openpype/hosts/maya/plugins/publish/validate_rendersettings.py @@ -275,15 +275,6 @@ def get_invalid(cls, instance): # go through definitions and test if such node.attribute exists. # if so, compare its value from the one required. for attribute, data in cls.get_nodes(instance, renderer).items(): - # Validate the settings has values. - if not data["values"]: - cls.log.error( - "Settings for {}.{} is missing values.".format( - node, attribute - ) - ) - continue - for node in data["nodes"]: try: render_value = cmds.getAttr( @@ -316,6 +307,15 @@ def get_nodes(cls, instance, renderer): ) result = {} for attr, values in OrderedDict(validation_settings).items(): + values = [convert_to_int_or_float(v) for v in values if v] + + # Validate the settings has values. + if not values: + cls.log.error( + "Settings for {} is missing values.".format(attr) + ) + continue + cls.log.debug("{}: {}".format(attr, values)) if "." not in attr: cls.log.warning( @@ -324,8 +324,6 @@ def get_nodes(cls, instance, renderer): ) continue - values = [convert_to_int_or_float(v) for v in values] - node_type, attribute_name = attr.split(".", 1) # first get node of that type From 4bdf5b79b8ceb0bdaacaed97786163620e6e710c Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 3 Apr 2023 17:44:21 +0200 Subject: [PATCH 811/898] Improve speed of Collect Custom Staging Directory --- .../plugins/publish/collect_custom_staging_dir.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/openpype/plugins/publish/collect_custom_staging_dir.py b/openpype/plugins/publish/collect_custom_staging_dir.py index 72ab0fe34d2..b749b251c0f 100644 --- a/openpype/plugins/publish/collect_custom_staging_dir.py +++ b/openpype/plugins/publish/collect_custom_staging_dir.py @@ -42,16 +42,17 @@ def process(self, instance): subset_name = instance.data["subset"] host_name = instance.context.data["hostName"] project_name = instance.context.data["projectName"] - + project_settings = instance.context.data["project_settings"] anatomy = instance.context.data["anatomy"] - anatomy_data = copy.deepcopy(instance.data["anatomyData"]) - task = anatomy_data.get("task", {}) + task = instance.data["anatomyData"].get("task", {}) transient_tml, is_persistent = get_custom_staging_dir_info( project_name, host_name, family, task.get("name"), - task.get("type"), subset_name, anatomy=anatomy, log=self.log) - result_str = "Not adding" + task.get("type"), subset_name, project_settings=project_settings, + anatomy=anatomy, log=self.log) + if transient_tml: + anatomy_data = copy.deepcopy(instance.data["anatomyData"]) anatomy_data["root"] = anatomy.roots scene_name = instance.context.data.get("currentFile") if scene_name: @@ -61,6 +62,8 @@ def process(self, instance): instance.data["stagingDir_persistent"] = is_persistent result_str = "Adding '{}' as".format(transient_dir) + else: + result_str = "Not adding" self.log.info("{} custom staging dir for instance with '{}'".format( result_str, family From 177cce233cb88bb7a51a5195204e7a57f3d2e2f8 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 3 Apr 2023 18:01:33 +0200 Subject: [PATCH 812/898] Workfiles: keep Browse always enabled (#4766) * OP-5494 - keep Browse always enable din Workfiles Browse might make sense even if there are no workfiles present, better in that case it makes the most sense (eg. I want to locate workfile from outside). * use last existing directory of workfile root instead of goint to cwd * use lstring instead of index cut --------- Co-authored-by: Jakub Trllo --- openpype/tools/workfiles/files_widget.py | 22 ++++++++++++++++------ openpype/tools/workfiles/save_as_dialog.py | 6 +++--- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/openpype/tools/workfiles/files_widget.py b/openpype/tools/workfiles/files_widget.py index 18be746d497..2f338cf5169 100644 --- a/openpype/tools/workfiles/files_widget.py +++ b/openpype/tools/workfiles/files_widget.py @@ -379,7 +379,7 @@ def _update_asset_task(self): # Disable/Enable buttons based on available files in model has_valid_items = self._workarea_files_model.has_valid_items() - self._btn_browse.setEnabled(has_valid_items) + self._btn_browse.setEnabled(True) self._btn_open.setEnabled(has_valid_items) if self._publish_context_select_mode: @@ -617,14 +617,24 @@ def on_browse_pressed(self): ext_filter = "Work File (*{0})".format( " *".join(self._get_host_extensions()) ) + dir_key = "directory" + if qtpy.API in ("pyside", "pyside2", "pyside6"): + dir_key = "dir" + + workfile_root = self._workfiles_root + # Find existing directory of workfile root + # - Qt will use 'cwd' instead, if path does not exist, which may lead + # to igniter directory + while workfile_root: + if os.path.exists(workfile_root): + break + workfile_root = os.path.dirname(workfile_root) + kwargs = { "caption": "Work Files", - "filter": ext_filter + "filter": ext_filter, + dir_key: workfile_root } - if qtpy.API in ("pyside", "pyside2", "pyside6"): - kwargs["dir"] = self._workfiles_root - else: - kwargs["directory"] = self._workfiles_root work_file = QtWidgets.QFileDialog.getOpenFileName(**kwargs)[0] if work_file: diff --git a/openpype/tools/workfiles/save_as_dialog.py b/openpype/tools/workfiles/save_as_dialog.py index de21deee424..aa881e79468 100644 --- a/openpype/tools/workfiles/save_as_dialog.py +++ b/openpype/tools/workfiles/save_as_dialog.py @@ -51,7 +51,7 @@ def __init__(self, anatomy, template_key, data): # Create a regex group for extensions extensions = registered_host().file_extensions() any_extension = "(?:{})".format( - "|".join(re.escape(ext[1:]) for ext in extensions) + "|".join(re.escape(ext.lstrip(".")) for ext in extensions) ) # Use placeholders that will never be in the filename @@ -373,7 +373,7 @@ def get_work_file(self): if not data["comment"]: data.pop("comment", None) - data["ext"] = data["ext"][1:] + data["ext"] = data["ext"].lstrip(".") anatomy_filled = self.anatomy.format(data) return anatomy_filled[self.template_key]["file"] @@ -413,7 +413,7 @@ def refresh(self): if not data["comment"]: data.pop("comment", None) - data["ext"] = data["ext"][1:] + data["ext"] = data["ext"].lstrip(".") version = get_last_workfile_with_version( self.root, template, data, extensions From d593c63b98c0c5588a24a17c7b2b1df8fb5a0325 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 4 Apr 2023 10:53:32 +0200 Subject: [PATCH 813/898] make sure project actions review only runs if not fork --- .github/workflows/project_actions.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index 6e56f125ea8..b21946f0eea 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -20,11 +20,12 @@ jobs: # - PR issue comment which is not form Ynbot # - PR review comment which is not Hound (or any other bot) # - PR review submitted which is not from Hound (or any other bot) and is not 'Changes requested' + # - make sure it only runs if not forked repo # ----------------------------- if: | - (github.event_name == 'issue_comment' && github.event.comment.user.id != 82967070) || - (github.event_name == 'pull_request_review_comment' && github.event.comment.user.type != 'Bot') || - (github.event_name == 'pull_request_review' && github.event.review.state != 'changes_requested' && github.event.review.user.type != 'Bot') + (github.event_name == 'issue_comment' && github.event.pull_request.head.repo.owner.login == 'ynput' && github.event.comment.user.id != 82967070) || + (github.event_name == 'pull_request_review_comment' && github.event.pull_request.head.repo.owner.login == 'ynput' && github.event.comment.user.type != 'Bot') || + (github.event_name == 'pull_request_review' && github.event.pull_request.head.repo.owner.login == 'ynput' && github.event.review.state != 'changes_requested' && github.event.review.user.type != 'Bot') steps: - name: Move PR to 'Review In Progress' uses: leonsteinhaeuser/project-beta-automations@v2.1.0 @@ -42,7 +43,7 @@ jobs: # ----------------------------- name: pr_review_requested runs-on: ubuntu-latest - if: github.event_name == 'pull_request_review' && github.event.review.state == 'changes_requested' + if: github.event_name == 'pull_request_review' && github.event.pull_request.head.repo.owner.login == 'ynput' && github.event.review.state == 'changes_requested' steps: - name: Set branch env run: echo "BRANCH_NAME=${{ github.event.pull_request.head.ref}}" >> $GITHUB_ENV From a93b63561814ed2d6bed0b97503b3f51acd2c757 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 4 Apr 2023 11:23:19 +0200 Subject: [PATCH 814/898] Maya: Remove pymel dependency (#4724) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove pymel from `validate_no_namespace` * Refactor `ValidateRigOutputIds` to remove pymel dependency * Remove pymel dependency * Fix logic * Remove pymel dependency * Remove py * Remove pymel dependency * Remove pymel dependency * Remove pymel dependency * Opt-out early if possible * Remove pymel dependency * Remove pymel dependency * Remove pymel dependency * Remove pymel dependency * Remove pymel dependency * Remove code that should've been removed * Cosmetics * Shush hound * Refactor `get_parent` -> `get_node_parent` * Fix argument * Refactor logic for Validate Mesh Arnold Attributes * Fix load image plane camera transform name * Merge remote-tracking branch 'upstream/develop' into maya_remove_pymel # Conflicts: # openpype/hosts/maya/plugins/load/load_reference.py # openpype/hosts/maya/plugins/publish/collect_review.py * Fix bug * Improve labels on messagebox buttons * Fix repair * Create empty mesh instead of cube * Tweak code style based on comments by @fabiaserra --------- Co-authored-by: Jakub Ježek --- .github/pr-branch-labeler.yml | 2 +- openpype/hosts/maya/api/lib.py | 157 +++++++++++++++--- openpype/hosts/maya/api/lib_rendersetup.py | 15 +- .../hosts/maya/plugins/load/load_audio.py | 22 +-- .../maya/plugins/load/load_image_plane.py | 151 +++++++++-------- .../hosts/maya/plugins/load/load_reference.py | 53 +++--- .../maya/plugins/publish/collect_review.py | 50 +++--- .../maya/plugins/publish/extract_playblast.py | 11 +- .../maya/plugins/publish/extract_thumbnail.py | 9 +- .../plugins/publish/validate_attributes.py | 114 +++++++------ .../validate_mesh_arnold_attributes.py | 82 +++++---- .../publish/validate_mesh_overlapping_uvs.py | 58 ++++--- .../plugins/publish/validate_no_namespace.py | 19 +-- .../publish/validate_rig_output_ids.py | 79 +++++---- website/docs/module_kitsu.md | 2 +- 15 files changed, 482 insertions(+), 342 deletions(-) diff --git a/.github/pr-branch-labeler.yml b/.github/pr-branch-labeler.yml index ca820510068..b4343262366 100644 --- a/.github/pr-branch-labeler.yml +++ b/.github/pr-branch-labeler.yml @@ -12,4 +12,4 @@ # Apply label "release" if base matches "release/*" 'Bump Minor': - base: "release/next-minor" \ No newline at end of file + base: "release/next-minor" diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index e4be31b427f..22803a2e3a9 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -1367,6 +1367,71 @@ def set_id(node, unique_id, overwrite=False): cmds.setAttr(attr, unique_id, type="string") +def get_attribute(plug, + asString=False, + expandEnvironmentVariables=False, + **kwargs): + """Maya getAttr with some fixes based on `pymel.core.general.getAttr()`. + + Like Pymel getAttr this applies some changes to `maya.cmds.getAttr` + - maya pointlessly returned vector results as a tuple wrapped in a list + (ex. '[(1,2,3)]'). This command unpacks the vector for you. + - when getting a multi-attr, maya would raise an error, but this will + return a list of values for the multi-attr + - added support for getting message attributes by returning the + connections instead + + Note that the asString + expandEnvironmentVariables argument naming + convention matches the `maya.cmds.getAttr` arguments so that it can + act as a direct replacement for it. + + Args: + plug (str): Node's attribute plug as `node.attribute` + asString (bool): Return string value for enum attributes instead + of the index. Note that the return value can be dependent on the + UI language Maya is running in. + expandEnvironmentVariables (bool): Expand any environment variable and + (tilde characters on UNIX) found in string attributes which are + returned. + + Kwargs: + Supports the keyword arguments of `maya.cmds.getAttr` + + Returns: + object: The value of the maya attribute. + + """ + attr_type = cmds.getAttr(plug, type=True) + if asString: + kwargs["asString"] = True + if expandEnvironmentVariables: + kwargs["expandEnvironmentVariables"] = True + try: + res = cmds.getAttr(plug, **kwargs) + except RuntimeError: + if attr_type == "message": + return cmds.listConnections(plug) + + node, attr = plug.split(".", 1) + children = cmds.attributeQuery(attr, node=node, listChildren=True) + if children: + return [ + get_attribute("{}.{}".format(node, child)) + for child in children + ] + + raise + + # Convert vector result wrapped in tuple + if isinstance(res, list) and len(res): + if isinstance(res[0], tuple) and len(res): + if attr_type in {'pointArray', 'vectorArray'}: + return res + return res[0] + + return res + + def set_attribute(attribute, value, node): """Adjust attributes based on the value from the attribute data @@ -1881,6 +1946,12 @@ def remove_other_uv_sets(mesh): cmds.removeMultiInstance(attr, b=True) +def get_node_parent(node): + """Return full path name for parent of node""" + parents = cmds.listRelatives(node, parent=True, fullPath=True) + return parents[0] if parents else None + + def get_id_from_sibling(node, history_only=True): """Return first node id in the history chain that matches this node. @@ -1904,10 +1975,6 @@ def get_id_from_sibling(node, history_only=True): """ - def _get_parent(node): - """Return full path name for parent of node""" - return cmds.listRelatives(node, parent=True, fullPath=True) - node = cmds.ls(node, long=True)[0] # Find all similar nodes in history @@ -1919,8 +1986,8 @@ def _get_parent(node): similar_nodes = [x for x in similar_nodes if x != node] # The node *must be* under the same parent - parent = _get_parent(node) - similar_nodes = [i for i in similar_nodes if _get_parent(i) == parent] + parent = get_node_parent(node) + similar_nodes = [i for i in similar_nodes if get_node_parent(i) == parent] # Check all of the remaining similar nodes and take the first one # with an id and assume it's the original. @@ -3166,38 +3233,78 @@ def _colormanage(**kwargs): def parent_nodes(nodes, parent=None): # type: (list, str) -> list """Context manager to un-parent provided nodes and return them back.""" - import pymel.core as pm # noqa - parent_node = None - delete_parent = False + def _as_mdagpath(node): + """Return MDagPath for node path.""" + if not node: + return + sel = OpenMaya.MSelectionList() + sel.add(node) + return sel.getDagPath(0) + + # We can only parent dag nodes so we ensure input contains only dag nodes + nodes = cmds.ls(nodes, type="dagNode", long=True) + if not nodes: + # opt-out early + yield + return + parent_node_path = None + delete_parent = False if parent: if not cmds.objExists(parent): - parent_node = pm.createNode("transform", n=parent, ss=False) + parent_node = cmds.createNode("transform", + name=parent, + skipSelect=False) delete_parent = True else: - parent_node = pm.PyNode(parent) + parent_node = parent + parent_node_path = cmds.ls(parent_node, long=True)[0] + + # Store original parents node_parents = [] for node in nodes: - n = pm.PyNode(node) - try: - root = pm.listRelatives(n, parent=1)[0] - except IndexError: - root = None - node_parents.append((n, root)) + node_parent = get_node_parent(node) + node_parents.append((_as_mdagpath(node), _as_mdagpath(node_parent))) + try: - for node in node_parents: - if not parent: - node[0].setParent(world=True) + for node, node_parent in node_parents: + node_parent_path = node_parent.fullPathName() if node_parent else None # noqa + if node_parent_path == parent_node_path: + # Already a child + continue + + if parent_node_path: + cmds.parent(node.fullPathName(), parent_node_path) else: - node[0].setParent(parent_node) + cmds.parent(node.fullPathName(), world=True) + yield finally: - for node in node_parents: - if node[1]: - node[0].setParent(node[1]) + # Reparent to original parents + for node, original_parent in node_parents: + node_path = node.fullPathName() + if not node_path: + # Node must have been deleted + continue + + node_parent_path = get_node_parent(node_path) + + original_parent_path = None + if original_parent: + original_parent_path = original_parent.fullPathName() + if not original_parent_path: + # Original parent node must have been deleted + continue + + if node_parent_path != original_parent_path: + if not original_parent_path: + cmds.parent(node_path, world=True) + else: + cmds.parent(node_path, original_parent_path) + if delete_parent: - pm.delete(parent_node) + cmds.delete(parent_node_path) @contextlib.contextmanager diff --git a/openpype/hosts/maya/api/lib_rendersetup.py b/openpype/hosts/maya/api/lib_rendersetup.py index e616f26e1b4..440ee21a524 100644 --- a/openpype/hosts/maya/api/lib_rendersetup.py +++ b/openpype/hosts/maya/api/lib_rendersetup.py @@ -19,6 +19,8 @@ UniqueOverride ) +from openpype.hosts.maya.api.lib import get_attribute + EXACT_MATCH = 0 PARENT_MATCH = 1 CLIENT_MATCH = 2 @@ -96,9 +98,6 @@ def get_attr_in_layer(node_attr, layer): """ - # Delay pymel import to here because it's slow to load - import pymel.core as pm - def _layer_needs_update(layer): """Return whether layer needs updating.""" # Use `getattr` as e.g. DEFAULT_RENDER_LAYER does not have @@ -125,7 +124,7 @@ def get_default_layer_value(node_attr_): node = history_overrides[-1] if history_overrides else override node_attr_ = node + ".original" - return pm.getAttr(node_attr_, asString=True) + return get_attribute(node_attr_, asString=True) layer = get_rendersetup_layer(layer) rs = renderSetup.instance() @@ -145,7 +144,7 @@ def get_default_layer_value(node_attr_): # we will let it error out. rs.switchToLayer(current_layer) - return pm.getAttr(node_attr, asString=True) + return get_attribute(node_attr, asString=True) overrides = get_attr_overrides(node_attr, layer) default_layer_value = get_default_layer_value(node_attr) @@ -156,7 +155,7 @@ def get_default_layer_value(node_attr_): for match, layer_override, index in overrides: if isinstance(layer_override, AbsOverride): # Absolute override - value = pm.getAttr(layer_override.name() + ".attrValue") + value = get_attribute(layer_override.name() + ".attrValue") if match == EXACT_MATCH: # value = value pass @@ -168,8 +167,8 @@ def get_default_layer_value(node_attr_): elif isinstance(layer_override, RelOverride): # Relative override # Value = Original * Multiply + Offset - multiply = pm.getAttr(layer_override.name() + ".multiply") - offset = pm.getAttr(layer_override.name() + ".offset") + multiply = get_attribute(layer_override.name() + ".multiply") + offset = get_attribute(layer_override.name() + ".offset") if match == EXACT_MATCH: value = value * multiply + offset diff --git a/openpype/hosts/maya/plugins/load/load_audio.py b/openpype/hosts/maya/plugins/load/load_audio.py index 6f60cb57265..9e7fd96bdb7 100644 --- a/openpype/hosts/maya/plugins/load/load_audio.py +++ b/openpype/hosts/maya/plugins/load/load_audio.py @@ -11,7 +11,7 @@ get_representation_path, ) from openpype.hosts.maya.api.pipeline import containerise -from openpype.hosts.maya.api.lib import unique_namespace +from openpype.hosts.maya.api.lib import unique_namespace, get_container_members class AudioLoader(load.LoaderPlugin): @@ -52,17 +52,15 @@ def load(self, context, name, namespace, data): ) def update(self, container, representation): - import pymel.core as pm - audio_node = None - for node in pm.PyNode(container["objectName"]).members(): - if node.nodeType() == "audio": - audio_node = node + members = get_container_members(container) + audio_nodes = cmds.ls(members, type="audio") - assert audio_node is not None, "Audio node not found." + assert audio_nodes is not None, "Audio node not found." + audio_node = audio_nodes[0] path = get_representation_path(representation) - audio_node.filename.set(path) + cmds.setAttr("{}.filename".format(audio_node), path, type="string") cmds.setAttr( container["objectName"] + ".representation", str(representation["_id"]), @@ -80,8 +78,12 @@ def update(self, container, representation): asset = get_asset_by_id( project_name, subset["parent"], fields=["parent"] ) - audio_node.sourceStart.set(1 - asset["data"]["frameStart"]) - audio_node.sourceEnd.set(asset["data"]["frameEnd"]) + + source_start = 1 - asset["data"]["frameStart"] + source_end = asset["data"]["frameEnd"] + + cmds.setAttr("{}.sourceStart".format(audio_node), source_start) + cmds.setAttr("{}.sourceEnd".format(audio_node), source_end) def switch(self, container, representation): self.update(container, representation) diff --git a/openpype/hosts/maya/plugins/load/load_image_plane.py b/openpype/hosts/maya/plugins/load/load_image_plane.py index 6421f3ffe2c..bf13708e9b6 100644 --- a/openpype/hosts/maya/plugins/load/load_image_plane.py +++ b/openpype/hosts/maya/plugins/load/load_image_plane.py @@ -11,11 +11,26 @@ get_representation_path ) from openpype.hosts.maya.api.pipeline import containerise -from openpype.hosts.maya.api.lib import unique_namespace +from openpype.hosts.maya.api.lib import ( + unique_namespace, + namespaced, + pairwise, + get_container_members +) from maya import cmds +def disconnect_inputs(plug): + overrides = cmds.listConnections(plug, + source=True, + destination=False, + plugs=True, + connections=True) or [] + for dest, src in pairwise(overrides): + cmds.disconnectAttr(src, dest) + + class CameraWindow(QtWidgets.QDialog): def __init__(self, cameras): @@ -74,6 +89,7 @@ def on_cancel_pressed(self): self.camera = None self.close() + class ImagePlaneLoader(load.LoaderPlugin): """Specific loader of plate for image planes on selected camera.""" @@ -84,9 +100,7 @@ class ImagePlaneLoader(load.LoaderPlugin): color = "orange" def load(self, context, name, namespace, data, options=None): - import pymel.core as pm - new_nodes = [] image_plane_depth = 1000 asset = context['asset']['name'] namespace = namespace or unique_namespace( @@ -96,16 +110,20 @@ def load(self, context, name, namespace, data, options=None): ) # Get camera from user selection. - camera = None # is_static_image_plane = None # is_in_all_views = None - if data: - camera = pm.PyNode(data.get("camera")) + camera = data.get("camera") if data else None if not camera: - cameras = pm.ls(type="camera") - camera_names = {x.getParent().name(): x for x in cameras} - camera_names["Create new camera."] = "create_camera" + cameras = cmds.ls(type="camera") + + # Cameras by names + camera_names = {} + for camera in cameras: + parent = cmds.listRelatives(camera, parent=True, path=True)[0] + camera_names[parent] = camera + + camera_names["Create new camera."] = "create-camera" window = CameraWindow(camera_names.keys()) window.exec_() # Skip if no camera was selected (Dialog was closed) @@ -113,43 +131,48 @@ def load(self, context, name, namespace, data, options=None): return camera = camera_names[window.camera] - if camera == "create_camera": - camera = pm.createNode("camera") + if camera == "create-camera": + camera = cmds.createNode("camera") if camera is None: return try: - camera.displayResolution.set(1) - camera.farClipPlane.set(image_plane_depth * 10) + cmds.setAttr("{}.displayResolution".format(camera), True) + cmds.setAttr("{}.farClipPlane".format(camera), + image_plane_depth * 10) except RuntimeError: pass # Create image plane - image_plane_transform, image_plane_shape = pm.imagePlane( - fileName=context["representation"]["data"]["path"], - camera=camera) - image_plane_shape.depth.set(image_plane_depth) - - - start_frame = pm.playbackOptions(q=True, min=True) - end_frame = pm.playbackOptions(q=True, max=True) - - image_plane_shape.frameOffset.set(0) - image_plane_shape.frameIn.set(start_frame) - image_plane_shape.frameOut.set(end_frame) - image_plane_shape.frameCache.set(end_frame) - image_plane_shape.useFrameExtension.set(1) + with namespaced(namespace): + # Create inside the namespace + image_plane_transform, image_plane_shape = cmds.imagePlane( + fileName=context["representation"]["data"]["path"], + camera=camera + ) + start_frame = cmds.playbackOptions(query=True, min=True) + end_frame = cmds.playbackOptions(query=True, max=True) + + for attr, value in { + "depth": image_plane_depth, + "frameOffset": 0, + "frameIn": start_frame, + "frameOut": end_frame, + "frameCache": end_frame, + "useFrameExtension": True + }.items(): + plug = "{}.{}".format(image_plane_shape, attr) + cmds.setAttr(plug, value) movie_representations = ["mov", "preview"] if context["representation"]["name"] in movie_representations: - # Need to get "type" by string, because its a method as well. - pm.Attribute(image_plane_shape + ".type").set(2) + cmds.setAttr(image_plane_shape + ".type", 2) # Ask user whether to use sequence or still image. if context["representation"]["name"] == "exr": # Ensure OpenEXRLoader plugin is loaded. - pm.loadPlugin("OpenEXRLoader.mll", quiet=True) + cmds.loadPlugin("OpenEXRLoader", quiet=True) message = ( "Hold image sequence on first frame?" @@ -161,32 +184,18 @@ def load(self, context, name, namespace, data, options=None): None, "Frame Hold.", message, - QtWidgets.QMessageBox.Ok, - QtWidgets.QMessageBox.Cancel + QtWidgets.QMessageBox.Yes, + QtWidgets.QMessageBox.No ) - if reply == QtWidgets.QMessageBox.Ok: - # find the input and output of frame extension - expressions = image_plane_shape.frameExtension.inputs() - frame_ext_output = image_plane_shape.frameExtension.outputs() - if expressions: - # the "time1" node is non-deletable attr - # in Maya, use disconnectAttr instead - pm.disconnectAttr(expressions, frame_ext_output) - - if not image_plane_shape.frameExtension.isFreeToChange(): - raise RuntimeError("Can't set frame extension for {}".format(image_plane_shape)) # noqa - # get the node of time instead and set the time for it. - image_plane_shape.frameExtension.set(start_frame) - - new_nodes.extend( - [ - image_plane_transform.longName().split("|")[-1], - image_plane_shape.longName().split("|")[-1] - ] - ) + if reply == QtWidgets.QMessageBox.Yes: + frame_extension_plug = "{}.frameExtension".format(image_plane_shape) # noqa - for node in new_nodes: - pm.rename(node, "{}:{}".format(namespace, node)) + # Remove current frame expression + disconnect_inputs(frame_extension_plug) + + cmds.setAttr(frame_extension_plug, start_frame) + + new_nodes = [image_plane_transform, image_plane_shape] return containerise( name=name, @@ -197,21 +206,19 @@ def load(self, context, name, namespace, data, options=None): ) def update(self, container, representation): - import pymel.core as pm - image_plane_shape = None - for node in pm.PyNode(container["objectName"]).members(): - if node.nodeType() == "imagePlane": - image_plane_shape = node - assert image_plane_shape is not None, "Image plane not found." + members = get_container_members(container) + image_planes = cmds.ls(members, type="imagePlane") + assert image_planes, "Image plane not found." + image_plane_shape = image_planes[0] path = get_representation_path(representation) - image_plane_shape.imageName.set(path) - cmds.setAttr( - container["objectName"] + ".representation", - str(representation["_id"]), - type="string" - ) + cmds.setAttr("{}.imageName".format(image_plane_shape), + path, + type="string") + cmds.setAttr("{}.representation".format(container["objectName"]), + str(representation["_id"]), + type="string") # Set frame range. project_name = legacy_io.active_project() @@ -227,10 +234,14 @@ def update(self, container, representation): start_frame = asset["data"]["frameStart"] end_frame = asset["data"]["frameEnd"] - image_plane_shape.frameOffset.set(0) - image_plane_shape.frameIn.set(start_frame) - image_plane_shape.frameOut.set(end_frame) - image_plane_shape.frameCache.set(end_frame) + for attr, value in { + "frameOffset": 0, + "frameIn": start_frame, + "frameOut": end_frame, + "frameCache": end_frame + }: + plug = "{}.{}".format(image_plane_shape, attr) + cmds.setAttr(plug, value) def switch(self, container, representation): self.update(container, representation) diff --git a/openpype/hosts/maya/plugins/load/load_reference.py b/openpype/hosts/maya/plugins/load/load_reference.py index 82c15ab8994..461f4258aad 100644 --- a/openpype/hosts/maya/plugins/load/load_reference.py +++ b/openpype/hosts/maya/plugins/load/load_reference.py @@ -12,7 +12,8 @@ import openpype.hosts.maya.api.plugin from openpype.hosts.maya.api.lib import ( maintained_selection, - get_container_members + get_container_members, + parent_nodes ) @@ -118,7 +119,6 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): def process_reference(self, context, name, namespace, options): import maya.cmds as cmds - import pymel.core as pm try: family = context["representation"]["context"]["family"] @@ -148,7 +148,7 @@ def process_reference(self, context, name, namespace, options): # if there are cameras, try to lock their transforms self._lock_camera_transforms(new_nodes) - current_namespace = pm.namespaceInfo(currentNamespace=True) + current_namespace = cmds.namespaceInfo(currentNamespace=True) if current_namespace != ":": group_name = current_namespace + ":" + group_name @@ -158,37 +158,29 @@ def process_reference(self, context, name, namespace, options): self[:] = new_nodes if attach_to_root: - group_node = pm.PyNode(group_name) - roots = set() + roots = cmds.listRelatives(group_name, + children=True, + fullPath=True) or [] - for node in new_nodes: - try: - roots.add(pm.PyNode(node).getAllParents()[-2]) - except: # noqa: E722 - pass + if family not in {"layout", "setdress", + "mayaAscii", "mayaScene"}: + # QUESTION Why do we need to exclude these families? + with parent_nodes(roots, parent=None): + cmds.xform(group_name, zeroTransformPivots=True) - if family not in ["layout", "setdress", - "mayaAscii", "mayaScene"]: - for root in roots: - root.setParent(world=True) - - group_node.zeroTransformPivots() - for root in roots: - root.setParent(group_node) - - cmds.setAttr(group_name + ".displayHandle", 1) + cmds.setAttr("{}.displayHandle".format(group_name), 1) settings = get_project_settings(os.environ['AVALON_PROJECT']) colors = settings['maya']['load']['colors'] c = colors.get(family) if c is not None: - group_node.useOutlinerColor.set(1) - group_node.outlinerColor.set( - (float(c[0]) / 255), - (float(c[1]) / 255), - (float(c[2]) / 255)) + cmds.setAttr("{}.useOutlinerColor".format(group_name), 1) + cmds.setAttr("{}.outlinerColor".format(group_name), + (float(c[0]) / 255), + (float(c[1]) / 255), + (float(c[2]) / 255)) - cmds.setAttr(group_name + ".displayHandle", 1) + cmds.setAttr("{}.displayHandle".format(group_name), 1) # get bounding box bbox = cmds.exactWorldBoundingBox(group_name) # get pivot position on world space @@ -202,15 +194,16 @@ def process_reference(self, context, name, namespace, options): cy = cy + pivot[1] cz = cz + pivot[2] # set selection handle offset to center of bounding box - cmds.setAttr(group_name + ".selectHandleX", cx) - cmds.setAttr(group_name + ".selectHandleY", cy) - cmds.setAttr(group_name + ".selectHandleZ", cz) + cmds.setAttr("{}.selectHandleX".format(group_name), cx) + cmds.setAttr("{}.selectHandleY".format(group_name), cy) + cmds.setAttr("{}.selectHandleZ".format(group_name), cz) if family == "rig": self._post_process_rig(name, namespace, context, options) else: if "translate" in options: - cmds.setAttr(group_name + ".t", *options["translate"]) + cmds.setAttr("{}.translate".format(group_name), + *options["translate"]) return new_nodes def switch(self, container, representation): diff --git a/openpype/hosts/maya/plugins/publish/collect_review.py b/openpype/hosts/maya/plugins/publish/collect_review.py index 065c6d73ad5..0b039880023 100644 --- a/openpype/hosts/maya/plugins/publish/collect_review.py +++ b/openpype/hosts/maya/plugins/publish/collect_review.py @@ -1,5 +1,4 @@ from maya import cmds, mel -import pymel.core as pm import pyblish.api @@ -123,43 +122,42 @@ def process(self, instance): # Collect audio playback_slider = mel.eval('$tmpVar=$gPlayBackSlider') - audio_name = cmds.timeControl(playback_slider, q=True, s=True) + audio_name = cmds.timeControl(playback_slider, + query=True, + sound=True) display_sounds = cmds.timeControl( - playback_slider, q=True, displaySound=True + playback_slider, query=True, displaySound=True ) - audio_nodes = [] + def get_audio_node_data(node): + return { + "offset": cmds.getAttr("{}.offset".format(node)), + "filename": cmds.getAttr("{}.filename".format(node)) + } + + audio_data = [] if audio_name: - audio_nodes.append(pm.PyNode(audio_name)) + audio_data.append(get_audio_node_data(audio_name)) - if not audio_name and display_sounds: - start_frame = int(pm.playbackOptions(q=True, min=True)) - end_frame = float(pm.playbackOptions(q=True, max=True)) - frame_range = range(int(start_frame), int(end_frame)) + elif display_sounds: + start_frame = int(cmds.playbackOptions(query=True, min=True)) + end_frame = int(cmds.playbackOptions(query=True, max=True)) - for node in pm.ls(type="audio"): + for node in cmds.ls(type="audio"): # Check if frame range and audio range intersections, # for whether to include this audio node or not. - start_audio = node.offset.get() - end_audio = node.offset.get() + node.duration.get() - audio_range = range(int(start_audio), int(end_audio)) - - if bool(set(frame_range).intersection(audio_range)): - audio_nodes.append(node) - - instance.data["audio"] = [] - for node in audio_nodes: - instance.data["audio"].append( - { - "offset": node.offset.get(), - "filename": node.filename.get() - } - ) + duration = cmds.getAttr("{}.duration".format(node)) + start_audio = cmds.getAttr("{}.offset".format(node)) + end_audio = start_audio + duration + + if start_audio <= end_frame and end_audio > start_frame: + audio_data.append(get_audio_node_data(node)) + + instance.data["audio"] = audio_data # Collect focal length. attr = camera + ".focalLength" - focal_length = None if get_attribute_input(attr): start = instance.data["frameStart"] end = instance.data["frameEnd"] + 1 diff --git a/openpype/hosts/maya/plugins/publish/extract_playblast.py b/openpype/hosts/maya/plugins/publish/extract_playblast.py index 27bd7dc8eab..0f3425a1deb 100644 --- a/openpype/hosts/maya/plugins/publish/extract_playblast.py +++ b/openpype/hosts/maya/plugins/publish/extract_playblast.py @@ -9,7 +9,6 @@ from openpype.hosts.maya.api import lib from maya import cmds -import pymel.core as pm @contextlib.contextmanager @@ -110,11 +109,11 @@ def process(self, instance): preset["filename"] = path preset["overwrite"] = True - pm.refresh(f=True) + cmds.refresh(force=True) - refreshFrameInt = int(pm.playbackOptions(q=True, minTime=True)) - pm.currentTime(refreshFrameInt - 1, edit=True) - pm.currentTime(refreshFrameInt, edit=True) + refreshFrameInt = int(cmds.playbackOptions(q=True, minTime=True)) + cmds.currentTime(refreshFrameInt - 1, edit=True) + cmds.currentTime(refreshFrameInt, edit=True) # Override transparency if requested. transparency = instance.data.get("transparency", 0) @@ -226,7 +225,7 @@ def process(self, instance): tags.append("delete") # Add camera node name to representation data - camera_node_name = pm.ls(camera)[0].getTransform().name() + camera_node_name = cmds.listRelatives(camera, parent=True)[0] collected_files = list(frame_collection) # single frame file shouldn't be in list, only as a string diff --git a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py index f2d084b8281..b4ed8dce4c1 100644 --- a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py +++ b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py @@ -8,7 +8,6 @@ from openpype.hosts.maya.api import lib from maya import cmds -import pymel.core as pm class ExtractThumbnail(publish.Extractor): @@ -99,11 +98,11 @@ def process(self, instance): preset["filename"] = path preset["overwrite"] = True - pm.refresh(f=True) + cmds.refresh(force=True) - refreshFrameInt = int(pm.playbackOptions(q=True, minTime=True)) - pm.currentTime(refreshFrameInt - 1, edit=True) - pm.currentTime(refreshFrameInt, edit=True) + refreshFrameInt = int(cmds.playbackOptions(q=True, minTime=True)) + cmds.currentTime(refreshFrameInt - 1, edit=True) + cmds.currentTime(refreshFrameInt, edit=True) # Override transparency if requested. transparency = instance.data.get("transparency", 0) diff --git a/openpype/hosts/maya/plugins/publish/validate_attributes.py b/openpype/hosts/maya/plugins/publish/validate_attributes.py index 7a1f0cf086a..6ca9afb9a4e 100644 --- a/openpype/hosts/maya/plugins/publish/validate_attributes.py +++ b/openpype/hosts/maya/plugins/publish/validate_attributes.py @@ -1,13 +1,17 @@ -import pymel.core as pm +from collections import defaultdict + +from maya import cmds import pyblish.api + +from openpype.hosts.maya.api.lib import set_attribute from openpype.pipeline.publish import ( RepairContextAction, ValidateContentsOrder, ) -class ValidateAttributes(pyblish.api.ContextPlugin): +class ValidateAttributes(pyblish.api.InstancePlugin): """Ensure attributes are consistent. Attributes to validate and their values comes from the @@ -27,86 +31,80 @@ class ValidateAttributes(pyblish.api.ContextPlugin): attributes = None - def process(self, context): + def process(self, instance): # Check for preset existence. - if not self.attributes: return - invalid = self.get_invalid(context, compute=True) + invalid = self.get_invalid(instance, compute=True) if invalid: raise RuntimeError( "Found attributes with invalid values: {}".format(invalid) ) @classmethod - def get_invalid(cls, context, compute=False): - invalid = context.data.get("invalid_attributes", []) + def get_invalid(cls, instance, compute=False): if compute: - invalid = cls.get_invalid_attributes(context) - - return invalid + return cls.get_invalid_attributes(instance) + else: + return instance.data.get("invalid_attributes", []) @classmethod - def get_invalid_attributes(cls, context): + def get_invalid_attributes(cls, instance): invalid_attributes = [] - for instance in context: - # Filter publisable instances. - if not instance.data["publish"]: + + # Filter families. + families = [instance.data["family"]] + families += instance.data.get("families", []) + families = set(families) & set(cls.attributes.keys()) + if not families: + return [] + + # Get all attributes to validate. + attributes = defaultdict(dict) + for family in families: + if family not in cls.attributes: + # No attributes to validate for family continue - # Filter families. - families = [instance.data["family"]] - families += instance.data.get("families", []) - families = list(set(families) & set(cls.attributes.keys())) - if not families: + for preset_attr, preset_value in cls.attributes[family].items(): + node_name, attribute_name = preset_attr.split(".", 1) + attributes[node_name][attribute_name] = preset_value + + if not attributes: + return [] + + # Get invalid attributes. + nodes = cmds.ls(long=True) + for node in nodes: + node_name = node.rsplit("|", 1)[-1].rsplit(":", 1)[-1] + if node_name not in attributes: continue - # Get all attributes to validate. - attributes = {} - for family in families: - for preset in cls.attributes[family]: - [node_name, attribute_name] = preset.split(".") - try: - attributes[node_name].update( - {attribute_name: cls.attributes[family][preset]} - ) - except KeyError: - attributes.update({ - node_name: { - attribute_name: cls.attributes[family][preset] - } - }) - - # Get invalid attributes. - nodes = pm.ls() - for node in nodes: - name = node.name(stripNamespace=True) - if name not in attributes.keys(): + for attr_name, expected in attributes.items(): + + # Skip if attribute does not exist + if not cmds.attributeQuery(attr_name, node=node, exists=True): continue - presets_to_validate = attributes[name] - for attribute in node.listAttr(): - names = [attribute.shortName(), attribute.longName()] - attribute_name = list( - set(names) & set(presets_to_validate.keys()) + plug = "{}.{}".format(node, attr_name) + value = cmds.getAttr(plug) + if value != expected: + invalid_attributes.append( + { + "attribute": plug, + "expected": expected, + "current": value + } ) - if attribute_name: - expected = presets_to_validate[attribute_name[0]] - if attribute.get() != expected: - invalid_attributes.append( - { - "attribute": attribute, - "expected": expected, - "current": attribute.get() - } - ) - - context.data["invalid_attributes"] = invalid_attributes + + instance.data["invalid_attributes"] = invalid_attributes return invalid_attributes @classmethod def repair(cls, instance): invalid = cls.get_invalid(instance) for data in invalid: - data["attribute"].set(data["expected"]) + node, attr = data["attribute"].split(".", 1) + value = data["expected"] + set_attribute(node=node, attribute=attr, value=value) diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py b/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py index fa4c66952c8..a580a1c7874 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py @@ -1,8 +1,14 @@ -import pymel.core as pc from maya import cmds import pyblish.api + import openpype.hosts.maya.api.action -from openpype.hosts.maya.api.lib import maintained_selection +from openpype.hosts.maya.api.lib import ( + maintained_selection, + delete_after, + undo_chunk, + get_attribute, + set_attribute +) from openpype.pipeline.publish import ( RepairAction, ValidateMeshOrder, @@ -31,60 +37,68 @@ class ValidateMeshArnoldAttributes(pyblish.api.InstancePlugin): else: active = False + @classmethod + def get_default_attributes(cls): + # Get default arnold attribute values for mesh type. + defaults = {} + with delete_after() as tmp: + transform = cmds.createNode("transform") + tmp.append(transform) + + mesh = cmds.createNode("mesh", parent=transform) + for attr in cmds.listAttr(mesh, string="ai*"): + plug = "{}.{}".format(mesh, attr) + try: + defaults[attr] = get_attribute(plug) + except RuntimeError: + cls.log.debug("Ignoring arnold attribute: {}".format(attr)) + + return defaults + @classmethod def get_invalid_attributes(cls, instance, compute=False): invalid = [] if compute: - # Get default arnold attributes. - temp_transform = pc.polyCube()[0] - - for shape in pc.ls(instance, type="mesh"): - for attr in temp_transform.getShape().listAttr(): - if not attr.attrName().startswith("ai"): - continue - target_attr = pc.PyNode( - "{}.{}".format(shape.name(), attr.attrName()) - ) - if attr.get() != target_attr.get(): - invalid.append(target_attr) + meshes = cmds.ls(instance, type="mesh", long=True) + if not meshes: + return [] - pc.delete(temp_transform) + # Compare the values against the defaults + defaults = cls.get_default_attributes() + for mesh in meshes: + for attr_name, default_value in defaults.items(): + plug = "{}.{}".format(mesh, attr_name) + if get_attribute(plug) != default_value: + invalid.append(plug) instance.data["nondefault_arnold_attributes"] = invalid - else: - invalid.extend(instance.data["nondefault_arnold_attributes"]) - return invalid + return instance.data.get("nondefault_arnold_attributes", []) @classmethod def get_invalid(cls, instance): - invalid = [] - - for attr in cls.get_invalid_attributes(instance, compute=False): - invalid.append(attr.node().name()) - - return invalid + invalid_attrs = cls.get_invalid_attributes(instance, compute=False) + invalid_nodes = set(attr.split(".", 1)[0] for attr in invalid_attrs) + return sorted(invalid_nodes) @classmethod def repair(cls, instance): with maintained_selection(): - with pc.UndoChunk(): - temp_transform = pc.polyCube()[0] - + with undo_chunk(): + defaults = cls.get_default_attributes() attributes = cls.get_invalid_attributes( instance, compute=False ) for attr in attributes: - source = pc.PyNode( - "{}.{}".format( - temp_transform.getShape(), attr.attrName() - ) + node, attr_name = attr.split(".", 1) + value = defaults[attr_name] + set_attribute( + node=node, + attribute=attr_name, + value=value ) - attr.set(source.get()) - - pc.delete(temp_transform) def process(self, instance): diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_overlapping_uvs.py b/openpype/hosts/maya/plugins/publish/validate_mesh_overlapping_uvs.py index be23f61ec50..74269cc5068 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_overlapping_uvs.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_overlapping_uvs.py @@ -1,10 +1,11 @@ -import pyblish.api -import openpype.hosts.maya.api.action import math +from six.moves import xrange + +from maya import cmds import maya.api.OpenMaya as om -import pymel.core as pm +import pyblish.api -from six.moves import xrange +import openpype.hosts.maya.api.action from openpype.pipeline.publish import ValidateMeshOrder @@ -185,8 +186,7 @@ def _getOverlapUVFaces(self, meshName): center, radius = self._createBoundingCircle(meshfn) for i in xrange(meshfn.numPolygons): # noqa: F821 - rayb1, face1Orig, face1Vec = self._createRayGivenFace( - meshfn, i) + rayb1, face1Orig, face1Vec = self._createRayGivenFace(meshfn, i) if not rayb1: continue cui = center[2*i] @@ -206,8 +206,8 @@ def _getOverlapUVFaces(self, meshName): if (dsqr >= (ri + rj) * (ri + rj)): continue - rayb2, face2Orig, face2Vec = self._createRayGivenFace( - meshfn, j) + rayb2, face2Orig, face2Vec = self._createRayGivenFace(meshfn, + j) if not rayb2: continue # Exclude the degenerate face @@ -240,37 +240,45 @@ class ValidateMeshHasOverlappingUVs(pyblish.api.InstancePlugin): optional = True @classmethod - def _get_overlapping_uvs(cls, node): - """ Check if mesh has overlapping UVs. + def _get_overlapping_uvs(cls, mesh): + """Return overlapping UVs of mesh. + + Args: + mesh (str): Mesh node name + + Returns: + list: Overlapping uvs for the input mesh in all uv sets. - :param node: node to check - :type node: str - :returns: True is has overlapping UVs, False otherwise - :rtype: bool """ ovl = GetOverlappingUVs() + # Store original uv set + original_current_uv_set = cmds.polyUVSet(mesh, + query=True, + currentUVSet=True) + overlapping_faces = [] - for i, uv in enumerate(pm.polyUVSet(node, q=1, auv=1)): - pm.polyUVSet(node, cuv=1, uvSet=uv) - overlapping_faces.extend(ovl._getOverlapUVFaces(str(node))) + for uv_set in cmds.polyUVSet(mesh, query=True, allUVSets=True): + cmds.polyUVSet(mesh, currentUVSet=True, uvSet=uv_set) + overlapping_faces.extend(ovl._getOverlapUVFaces(mesh)) + + # Restore original uv set + cmds.polyUVSet(mesh, currentUVSet=True, uvSet=original_current_uv_set) return overlapping_faces @classmethod def get_invalid(cls, instance, compute=False): - invalid = [] + if compute: - instance.data["overlapping_faces"] = [] - for node in pm.ls(instance, type="mesh"): + invalid = [] + for node in cmds.ls(instance, type="mesh"): faces = cls._get_overlapping_uvs(node) invalid.extend(faces) - # Store values for later. - instance.data["overlapping_faces"].extend(faces) - else: - invalid.extend(instance.data["overlapping_faces"]) - return invalid + instance.data["overlapping_faces"] = invalid + + return instance.data.get("overlapping_faces", []) def process(self, instance): diff --git a/openpype/hosts/maya/plugins/publish/validate_no_namespace.py b/openpype/hosts/maya/plugins/publish/validate_no_namespace.py index e91b99359dd..0ff03f91650 100644 --- a/openpype/hosts/maya/plugins/publish/validate_no_namespace.py +++ b/openpype/hosts/maya/plugins/publish/validate_no_namespace.py @@ -1,4 +1,3 @@ -import pymel.core as pm import maya.cmds as cmds import pyblish.api @@ -12,7 +11,7 @@ def get_namespace(node_name): # ensure only node's name (not parent path) - node_name = node_name.rsplit("|")[-1] + node_name = node_name.rsplit("|", 1)[-1] # ensure only namespace return node_name.rpartition(":")[0] @@ -45,13 +44,11 @@ def repair(cls, instance): invalid = cls.get_invalid(instance) - # Get nodes with pymel since we'll be renaming them - # Since we don't want to keep checking the hierarchy - # or full paths - nodes = pm.ls(invalid) + # Iterate over the nodes by long to short names to iterate the lowest + # in hierarchy nodes first. This way we avoid having renamed parents + # before renaming children nodes + for node in sorted(invalid, key=len, reverse=True): - for node in nodes: - namespace = node.namespace() - if namespace: - name = node.nodeName() - node.rename(name[len(namespace):]) + node_name = node.rsplit("|", 1)[-1] + node_name_without_namespace = node_name.rsplit(":")[-1] + cmds.rename(node, node_name_without_namespace) diff --git a/openpype/hosts/maya/plugins/publish/validate_rig_output_ids.py b/openpype/hosts/maya/plugins/publish/validate_rig_output_ids.py index f3ed1a36efb..499bfd4e375 100644 --- a/openpype/hosts/maya/plugins/publish/validate_rig_output_ids.py +++ b/openpype/hosts/maya/plugins/publish/validate_rig_output_ids.py @@ -1,14 +1,22 @@ -import pymel.core as pc +from collections import defaultdict + +from maya import cmds import pyblish.api import openpype.hosts.maya.api.action +from openpype.hosts.maya.api.lib import get_id, set_id from openpype.pipeline.publish import ( RepairAction, ValidateContentsOrder, ) +def get_basename(node): + """Return node short name without namespace""" + return node.rsplit("|", 1)[-1].rsplit(":", 1)[-1] + + class ValidateRigOutputIds(pyblish.api.InstancePlugin): """Validate rig output ids. @@ -30,43 +38,48 @@ def process(self, instance): @classmethod def get_invalid(cls, instance, compute=False): - invalid = cls.get_invalid_matches(instance, compute=compute) - return [x["node"].longName() for x in invalid] + invalid_matches = cls.get_invalid_matches(instance, compute=compute) + return list(invalid_matches.keys()) @classmethod def get_invalid_matches(cls, instance, compute=False): - invalid = [] + invalid = {} if compute: out_set = next(x for x in instance if x.endswith("out_SET")) - instance_nodes = pc.sets(out_set, query=True) - instance_nodes.extend( - [x.getShape() for x in instance_nodes if x.getShape()]) - scene_nodes = pc.ls(type="transform") + pc.ls(type="mesh") + instance_nodes = cmds.sets(out_set, query=True, nodesOnly=True) + instance_nodes = cmds.ls(instance_nodes, long=True) + for node in instance_nodes: + shapes = cmds.listRelatives(node, shapes=True, fullPath=True) + if shapes: + instance_nodes.extend(shapes) + + scene_nodes = cmds.ls(type="transform") + cmds.ls(type="mesh") scene_nodes = set(scene_nodes) - set(instance_nodes) + scene_nodes_by_basename = defaultdict(list) + for node in scene_nodes: + basename = get_basename(node) + scene_nodes_by_basename[basename].append(node) + for instance_node in instance_nodes: - matches = [] - basename = instance_node.name(stripNamespace=True) - for scene_node in scene_nodes: - if scene_node.name(stripNamespace=True) == basename: - matches.append(scene_node) - - if matches: - ids = [instance_node.cbId.get()] - ids.extend([x.cbId.get() for x in matches]) - ids = set(ids) - - if len(ids) > 1: - cls.log.error( - "\"{}\" id mismatch to: {}".format( - instance_node.longName(), matches - ) - ) - invalid.append( - {"node": instance_node, "matches": matches} + basename = get_basename(instance_node) + if basename not in scene_nodes_by_basename: + continue + + matches = scene_nodes_by_basename[basename] + + ids = set(get_id(node) for node in matches) + ids.add(get_id(instance_node)) + + if len(ids) > 1: + cls.log.error( + "\"{}\" id mismatch to: {}".format( + instance_node.longName(), matches ) + ) + invalid[instance_node] = matches instance.data["mismatched_output_ids"] = invalid else: @@ -76,19 +89,21 @@ def get_invalid_matches(cls, instance, compute=False): @classmethod def repair(cls, instance): - invalid = cls.get_invalid_matches(instance) + invalid_matches = cls.get_invalid_matches(instance) multiple_ids_match = [] - for data in invalid: - ids = [x.cbId.get() for x in data["matches"]] + for instance_node, matches in invalid_matches.items(): + ids = set(get_id(node) for node in matches) # If there are multiple scene ids matched, and error needs to be # raised for manual correction. if len(ids) > 1: - multiple_ids_match.append(data) + multiple_ids_match.append({"node": instance_node, + "matches": matches}) continue - data["node"].cbId.set(ids[0]) + id_to_set = next(iter(ids)) + set_id(instance_node, id_to_set, overwrite=True) if multiple_ids_match: raise RuntimeError( diff --git a/website/docs/module_kitsu.md b/website/docs/module_kitsu.md index 05cff87fccc..d79c78fecf7 100644 --- a/website/docs/module_kitsu.md +++ b/website/docs/module_kitsu.md @@ -53,5 +53,5 @@ There are four settings available: ## Q&A ### Is it safe to rename an entity from Kitsu? -Absolutely! Entities are linked by their unique IDs between the two databases. +Absolutely! Entities are linked by their unique IDs between the two databases. But renaming from the OP's Project Manager won't apply the change to Kitsu, it'll be overridden during the next synchronization. From 3b680e2afaff0bcaebfeeb980d1e82cfa9abaa42 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 4 Apr 2023 12:58:07 +0100 Subject: [PATCH 815/898] Replace hardcode with find_root_template_from_path --- .../plugins/publish/submit_publish_job.py | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_publish_job.py b/openpype/modules/deadline/plugins/publish/submit_publish_job.py index 41bc103d5ca..4765772bcff 100644 --- a/openpype/modules/deadline/plugins/publish/submit_publish_job.py +++ b/openpype/modules/deadline/plugins/publish/submit_publish_job.py @@ -944,17 +944,28 @@ def process(self, instance): # we cannot attach AOVs to other subsets as we consider every # AOV subset of its own. - config = instance.data["colorspaceConfig"] additional_data = { "renderProducts": instance.data["renderProducts"], "colorspaceConfig": instance.data["colorspaceConfig"], "display": instance.data["colorspaceDisplay"], - "view": instance.data["colorspaceView"], - "colorspaceTemplate": config.replace( - str(context.data["anatomy"].roots["work"]), "{root[work]}" - ) + "view": instance.data["colorspaceView"] } + # Get templated path from absolute config path. + anatomy = instance.context.data["anatomy"] + colorspaceTemplate = instance.data["colorspaceConfig"] + success, rootless_staging_dir = ( + anatomy.find_root_template_from_path(colorspaceTemplate) + ) + if success: + colorspaceTemplate = rootless_staging_dir + else: + self.log.warning(( + "Could not find root path for remapping \"{}\"." + " This may cause issues on farm." + ).format(colorspaceTemplate)) + additional_data["colorspaceTemplate"] = colorspaceTemplate + if len(data.get("attachTo")) > 0: assert len(data.get("expectedFiles")[0].keys()) == 1, ( "attaching multiple AOVs or renderable cameras to " From 49ff12da3cebedc5e41b57f8b7c1dd7401ce204d Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 4 Apr 2023 15:19:36 +0200 Subject: [PATCH 816/898] Documentation: Move publisher related tips to publisher area (#4772) * Move publisher related documentation to the publisher block * Fix typo --- website/docs/artist_hosts_aftereffects.md | 36 +++++++++++------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/website/docs/artist_hosts_aftereffects.md b/website/docs/artist_hosts_aftereffects.md index 939ef4034ca..d9522d57659 100644 --- a/website/docs/artist_hosts_aftereffects.md +++ b/website/docs/artist_hosts_aftereffects.md @@ -90,7 +90,7 @@ If there is an option of automatic repair, there will be `Repair` button on the There are currently 2 options of `render` item: - Render of farm - allows offload rendering and publishing to Deadline - requires Deadline module being enabled -- Validate Scene Settings - enables validation plugin which controls setting in DB (or asset control system like Ftrak) and scene itself +- Validate Scene Settings - enables validation plugin which controls setting in DB (or asset control system like Ftrack) and scene itself ![Configuration of render instance](assets/aftereffects_render_instance.png) @@ -100,6 +100,23 @@ There are currently 2 options of `render` item: - `Validate` - if you would like to run only collecting and validating phases (nothing will be published yet) - `Publish` - standard way how to kick off full publishing process +#### Support help +If you would like to ask for help admin or support, you could use any of the three options on the `Note` button on bottom left: +- `Go to details` - switches into a more detailed list of published instances and plugins. +- `Copy report` - stash full publishing log to a clipboard +- `Export report` - save log into a file for sending it via mail or any communication tool + +If you are able to fix the workfile yourself, use the first button on the right to set the UI to initial state before publish. (Click the `Publish` button to start again.) + +#### Legacy instances + +All screenshots from Publish are from updated dialog, before publishing was being done by regular `Pyblish` tool. +New publishing process should be backward compatible, eg. if you have a workfile with instances created in the previous publishing approach, they will be translated automatically and +could be used right away. + +If you hit on unexpected behaviour with old instances, contact support first, then you could try to delete and recreate instances from scratch. +Nuclear option is to purge workfile metadata in `Window > Metadata > Basic > Label`. This is only for most determined daredevils though! + ### Load When you want to load existing published work, you can use the `Loader` tool. You can reach it in the extension's panel. @@ -134,20 +151,3 @@ You can switch to a previous version of the image or update to the latest. ![Loader](assets/photoshop_manage_switch.gif) ![Loader](assets/photoshop_manage_update.gif) - -#### Support help -If you would like to ask for help admin or support, you could use any of the three options on the `Note` button on bottom left: -- `Go to details` - switches into a more detailed list of published instances and plugins. -- `Copy report` - stash full publishing log to a clipboard -- `Export report` - save log into a file for sending it via mail or any communication tool - -If you are able to fix the workfile yourself, use the first button on the right to set the UI to initial state before publish. (Click the `Publish` button to start again.) - -#### Legacy instances - -All screenshots from Publish are from updated dialog, before publishing was being done by regular `Pyblish` tool. -New publishing process should be backward compatible, eg. if you have a workfile with instances created in the previous publishing approach, they will be translated automatically and -could be used right away. - -If you hit on unexpected behaviour with old instances, contact support first, then you could try to delete and recreate instances from scratch. -Nuclear option is to purge workfile metadata in `Window > Metadata > Basic > Label`. This is only for most determined daredevils though! From 1cbcd66da80632ff654d7d54a4f0c2cf0025c64c Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 4 Apr 2023 16:54:36 +0200 Subject: [PATCH 817/898] removing older instance attributes --- openpype/hosts/nuke/api/plugin.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/openpype/hosts/nuke/api/plugin.py b/openpype/hosts/nuke/api/plugin.py index 3806f291c28..3566cb64c17 100644 --- a/openpype/hosts/nuke/api/plugin.py +++ b/openpype/hosts/nuke/api/plugin.py @@ -208,6 +208,12 @@ def create(self, subset_name, instance_data, pre_create_data): def collect_instances(self): cached_instances = _collect_and_cache_nodes(self) + attr_def_keys = { + attr_def.key + for attr_def in self.get_instance_attr_defs() + } + attr_def_keys.discard(None) + for (node, data) in cached_instances[self.identifier]: created_instance = CreatedInstance.from_existing( data, self @@ -215,6 +221,12 @@ def collect_instances(self): created_instance.transient_data["node"] = node self._add_instance_to_context(created_instance) + for key in ( + set(created_instance["creator_attributes"].keys()) + - attr_def_keys + ): + created_instance["creator_attributes"].pop(key) + def update_instances(self, update_list): for created_inst, _changes in update_list: instance_node = created_inst.transient_data["node"] From a708885abb91ff4f8bf0212857ed3d134088db2c Mon Sep 17 00:00:00 2001 From: Ynbot Date: Wed, 5 Apr 2023 03:25:57 +0000 Subject: [PATCH 818/898] [Automated] Bump version --- openpype/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/version.py b/openpype/version.py index 77b853aa9cd..d9e29d691ef 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.15.4-nightly.2" +__version__ = "3.15.4-nightly.3" From 0cdeda539693632ade1d012713b98a000503d89f Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 5 Apr 2023 11:06:43 +0200 Subject: [PATCH 819/898] remove UnknownDef attributes on pop from attributes value (#4776) --- openpype/pipeline/create/context.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/openpype/pipeline/create/context.py b/openpype/pipeline/create/context.py index 22cab28e4b9..382bbea05ed 100644 --- a/openpype/pipeline/create/context.py +++ b/openpype/pipeline/create/context.py @@ -596,7 +596,14 @@ def update(self, value): self[_key] = _value def pop(self, key, default=None): - return self._data.pop(key, default) + value = self._data.pop(key, default) + # Remove attribute definition if is 'UnknownDef' + # - gives option to get rid of unknown values + attr_def = self._attr_defs_by_key.get(key) + if isinstance(attr_def, UnknownDef): + self._attr_defs_by_key.pop(key) + self._attr_defs.remove(attr_def) + return value def reset_values(self): self._data = {} From 1944643d780a4e711c473963102f0a67af06ecc0 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 5 Apr 2023 11:39:28 +0200 Subject: [PATCH 820/898] make label key optional on instance.data --- openpype/plugins/publish/collect_otio_review.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/plugins/publish/collect_otio_review.py b/openpype/plugins/publish/collect_otio_review.py index 4d8147e70d4..f0157282a11 100644 --- a/openpype/plugins/publish/collect_otio_review.py +++ b/openpype/plugins/publish/collect_otio_review.py @@ -87,7 +87,9 @@ def process(self, instance): otio_review_clips.append(otio_gap) if otio_review_clips: - instance.data["label"] += " (review)" + # add review track to instance and change label to reflect it + label = instance.data.get("label", instance.data["subset"]) + instance.data["label"] = label + " (review)" instance.data["families"] += ["review", "ftrack"] instance.data["otioReviewClips"] = otio_review_clips self.log.info( From 68caaf65c8a2e486d6a86b85012ad1493f6f3608 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 5 Apr 2023 12:14:54 +0200 Subject: [PATCH 821/898] fixing skipping of project actions --- .github/workflows/project_actions.yml | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml index b21946f0eea..3589b4acc20 100644 --- a/.github/workflows/project_actions.yml +++ b/.github/workflows/project_actions.yml @@ -25,7 +25,11 @@ jobs: if: | (github.event_name == 'issue_comment' && github.event.pull_request.head.repo.owner.login == 'ynput' && github.event.comment.user.id != 82967070) || (github.event_name == 'pull_request_review_comment' && github.event.pull_request.head.repo.owner.login == 'ynput' && github.event.comment.user.type != 'Bot') || - (github.event_name == 'pull_request_review' && github.event.pull_request.head.repo.owner.login == 'ynput' && github.event.review.state != 'changes_requested' && github.event.review.user.type != 'Bot') + (github.event_name == 'pull_request_review' && + github.event.pull_request.head.repo.owner.login == 'ynput' && + github.event.review.state != 'changes_requested' && + github.event.review.state != 'approved' && + github.event.review.user.type != 'Bot') steps: - name: Move PR to 'Review In Progress' uses: leonsteinhaeuser/project-beta-automations@v2.1.0 @@ -70,10 +74,7 @@ jobs: size-label: name: pr_size_label runs-on: ubuntu-latest - if: | - (github.event_name == 'pull_request' && github.event.action == 'assigned') || - (github.event_name == 'pull_request' && github.event.action == 'opened') - + if: github.event.action == 'assigned' || github.event.action == 'opened' steps: - name: Add size label uses: "pascalgn/size-label-action@v0.4.3" @@ -94,9 +95,7 @@ jobs: label_prs_branch: name: pr_branch_label runs-on: ubuntu-latest - if: | - (github.event_name == 'pull_request' && github.event.action == 'assigned') || - (github.event_name == 'pull_request' && github.event.action == 'opened') + if: github.event.action == 'assigned' || github.event.action == 'opened' steps: - name: Label PRs - Branch name detection uses: ffittschen/pr-branch-labeler@v1 @@ -106,9 +105,7 @@ jobs: label_prs_globe: name: pr_globe_label runs-on: ubuntu-latest - if: | - (github.event_name == 'pull_request' && github.event.action == 'assigned') || - (github.event_name == 'pull_request' && github.event.action == 'opened') + if: github.event.action == 'assigned' || github.event.action == 'opened' steps: - name: Label PRs - Globe detection uses: actions/labeler@v4.0.3 From 105e03344c28ba44f61c6ade2c1c82450cc93ad6 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 5 Apr 2023 14:34:26 +0200 Subject: [PATCH 822/898] nuke: capture exception so popup is not rised --- openpype/hosts/nuke/api/lib.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index 157a02b9aaa..fe3a2d2bd1e 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -23,6 +23,9 @@ from openpype.host import HostDirmap from openpype.tools.utils import host_tools +from openpype.pipeline.workfile.workfile_template_builder import ( + TemplateProfileNotFound +) from openpype.lib import ( env_value_to_bool, Logger, @@ -2684,7 +2687,10 @@ def start_workfile_template_builder(): # to avoid looping of the callback, remove it! log.info("Starting workfile template builder...") - build_workfile_template(workfile_creation_enabled=True) + try: + build_workfile_template(workfile_creation_enabled=True) + except TemplateProfileNotFound: + log.warning("Template profile not found. Skipping...") # remove callback since it would be duplicating the workfile nuke.removeOnCreate(start_workfile_template_builder, nodeClass="Root") From 17bfa7f628a1d19e5754047b3ba9598cc4576f8c Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 5 Apr 2023 14:34:57 +0200 Subject: [PATCH 823/898] add positional knobs only if keep_placeholder --- .../nuke/api/workfile_template_builder.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/nuke/api/workfile_template_builder.py b/openpype/hosts/nuke/api/workfile_template_builder.py index cf85a5ea056..72d4ffb4762 100644 --- a/openpype/hosts/nuke/api/workfile_template_builder.py +++ b/openpype/hosts/nuke/api/workfile_template_builder.py @@ -219,14 +219,17 @@ def cleanup_placeholder(self, placeholder, failed): # fix the problem of z_order for backdrops self._fix_z_order(placeholder) - self._imprint_siblings(placeholder) + + if placeholder.data.get("keep_placeholder"): + self._imprint_siblings(placeholder) if placeholder.data["nb_children"] == 0: # save initial nodes positions and dimensions, update them # and set inputs and outputs of loaded nodes + if placeholder.data.get("keep_placeholder"): + self._imprint_inits() + self._update_nodes(placeholder, nuke.allNodes(), nodes_loaded) - self._imprint_inits() - self._update_nodes(placeholder, nuke.allNodes(), nodes_loaded) self._set_loaded_connections(placeholder) elif placeholder.data["siblings"]: @@ -629,14 +632,18 @@ def cleanup_placeholder(self, placeholder, failed): # fix the problem of z_order for backdrops self._fix_z_order(placeholder) - self._imprint_siblings(placeholder) + + if placeholder.data.get("keep_placeholder"): + self._imprint_siblings(placeholder) if placeholder.data["nb_children"] == 0: # save initial nodes positions and dimensions, update them # and set inputs and outputs of created nodes - self._imprint_inits() - self._update_nodes(placeholder, nuke.allNodes(), nodes_created) + if placeholder.data.get("keep_placeholder"): + self._imprint_inits() + self._update_nodes(placeholder, nuke.allNodes(), nodes_created) + self._set_created_connections(placeholder) elif placeholder.data["siblings"]: From 199f70e1caabfc2f59ae563bd4f12c4bb04f8d3d Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 5 Apr 2023 14:35:07 +0200 Subject: [PATCH 824/898] add missing variable 'handles' to loader (#4781) --- openpype/tools/loader/model.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openpype/tools/loader/model.py b/openpype/tools/loader/model.py index 39e0bd98c34..14671e341f0 100644 --- a/openpype/tools/loader/model.py +++ b/openpype/tools/loader/model.py @@ -361,10 +361,11 @@ def set_version(self, index, version): version_data.get("endFrame", None) ) + handles_label = None handle_start = version_data.get("handleStart", None) handle_end = version_data.get("handleEnd", None) if handle_start is not None and handle_end is not None: - handles = "{}-{}".format(str(handle_start), str(handle_end)) + handles_label = "{}-{}".format(str(handle_start), str(handle_end)) if frame_start is not None and frame_end is not None: # Remove superfluous zeros from numbers (3.0 -> 3) to improve @@ -401,7 +402,7 @@ def set_version(self, index, version): "frameStart": frame_start, "frameEnd": frame_end, "duration": duration, - "handles": handles, + "handles": handles_label, "frames": frames, "step": version_data.get("step", None), }) From 70087468c346ad3e91b9980e7c5a5920cd44320b Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 5 Apr 2023 15:59:36 +0200 Subject: [PATCH 825/898] General: Anatomy templates formatting (#4773) * TemplatesDict can create different type of template * anatomy templates can be formatted on their own * return objected templates on get item * '_rootless_path' is public classmethod 'rootless_path_from_result' * 'AnatomyStringTemplate' expect anatomy templates * remove key getters * fix typo 'create_ojected_templates' -> 'create_objected_templates' * Fix type of argument * Fix long line --- openpype/lib/path_templates.py | 26 ++++++++++---- openpype/pipeline/anatomy.py | 64 +++++++++++++++++++++++++--------- 2 files changed, 67 insertions(+), 23 deletions(-) diff --git a/openpype/lib/path_templates.py b/openpype/lib/path_templates.py index 0f99efb430a..9be1736abf0 100644 --- a/openpype/lib/path_templates.py +++ b/openpype/lib/path_templates.py @@ -256,17 +256,18 @@ def set_templates(self, templates): elif isinstance(templates, dict): self._raw_templates = copy.deepcopy(templates) self._templates = templates - self._objected_templates = self.create_ojected_templates(templates) + self._objected_templates = self.create_objected_templates( + templates) else: raise TypeError("<{}> argument must be a dict, not {}.".format( self.__class__.__name__, str(type(templates)) )) def __getitem__(self, key): - return self.templates[key] + return self.objected_templates[key] def get(self, key, *args, **kwargs): - return self.templates.get(key, *args, **kwargs) + return self.objected_templates.get(key, *args, **kwargs) @property def raw_templates(self): @@ -280,8 +281,21 @@ def templates(self): def objected_templates(self): return self._objected_templates - @classmethod - def create_ojected_templates(cls, templates): + def _create_template_object(self, template): + """Create template object from a template string. + + Separated into method to give option change class of templates. + + Args: + template (str): Template string. + + Returns: + StringTemplate: Object of template. + """ + + return StringTemplate(template) + + def create_objected_templates(self, templates): if not isinstance(templates, dict): raise TypeError("Expected dict object, got {}".format( str(type(templates)) @@ -297,7 +311,7 @@ def create_ojected_templates(cls, templates): for key in tuple(item.keys()): value = item[key] if isinstance(value, six.string_types): - item[key] = StringTemplate(value) + item[key] = self._create_template_object(value) elif isinstance(value, dict): inner_queue.append(value) return objected_templates diff --git a/openpype/pipeline/anatomy.py b/openpype/pipeline/anatomy.py index 683960f3d89..30748206a38 100644 --- a/openpype/pipeline/anatomy.py +++ b/openpype/pipeline/anatomy.py @@ -19,6 +19,7 @@ from openpype.lib.path_templates import ( TemplateUnsolved, TemplateResult, + StringTemplate, TemplatesDict, FormatObject, ) @@ -606,6 +607,32 @@ def normalized(self): return self.__class__(tmp, self.rootless) +class AnatomyStringTemplate(StringTemplate): + """String template which has access to anatomy.""" + + def __init__(self, anatomy_templates, template): + self.anatomy_templates = anatomy_templates + super(AnatomyStringTemplate, self).__init__(template) + + def format(self, data): + """Format template and add 'root' key to data if not available. + + Args: + data (dict[str, Any]): Formatting data for template. + + Returns: + AnatomyTemplateResult: Formatting result. + """ + + anatomy_templates = self.anatomy_templates + if not data.get("root"): + data = copy.deepcopy(data) + data["root"] = anatomy_templates.anatomy.roots + result = StringTemplate.format(self, data) + rootless_path = anatomy_templates.rootless_path_from_result(result) + return AnatomyTemplateResult(result, rootless_path) + + class AnatomyTemplates(TemplatesDict): inner_key_pattern = re.compile(r"(\{@.*?[^{}0]*\})") inner_key_name_pattern = re.compile(r"\{@(.*?[^{}0]*)\}") @@ -615,12 +642,6 @@ def __init__(self, anatomy): self.anatomy = anatomy self.loaded_project = None - def __getitem__(self, key): - return self.templates[key] - - def get(self, key, default=None): - return self.templates.get(key, default) - def reset(self): self._raw_templates = None self._templates = None @@ -655,12 +676,7 @@ def _validate_discovery(self): def _format_value(self, value, data): if isinstance(value, RootItem): return self._solve_dict(value, data) - - result = super(AnatomyTemplates, self)._format_value(value, data) - if isinstance(result, TemplateResult): - rootless_path = self._rootless_path(result, data) - result = AnatomyTemplateResult(result, rootless_path) - return result + return super(AnatomyTemplates, self)._format_value(value, data) def set_templates(self, templates): if not templates: @@ -689,10 +705,13 @@ def set_templates(self, templates): solved_templates = self.solve_template_inner_links(templates) self._templates = solved_templates - self._objected_templates = self.create_ojected_templates( + self._objected_templates = self.create_objected_templates( solved_templates ) + def _create_template_object(self, template): + return AnatomyStringTemplate(self, template) + def default_templates(self): """Return default templates data with solved inner keys.""" return self.solve_template_inner_links( @@ -886,7 +905,8 @@ def solve_template_inner_links(cls, templates): return keys_by_subkey - def _dict_to_subkeys_list(self, subdict, pre_keys=None): + @classmethod + def _dict_to_subkeys_list(cls, subdict, pre_keys=None): if pre_keys is None: pre_keys = [] output = [] @@ -895,7 +915,7 @@ def _dict_to_subkeys_list(self, subdict, pre_keys=None): result = list(pre_keys) result.append(key) if isinstance(value, dict): - for item in self._dict_to_subkeys_list(value, result): + for item in cls._dict_to_subkeys_list(value, result): output.append(item) else: output.append(result) @@ -908,7 +928,17 @@ def _keys_to_dicts(self, key_list, value): return {key_list[0]: value} return {key_list[0]: self._keys_to_dicts(key_list[1:], value)} - def _rootless_path(self, result, final_data): + @classmethod + def rootless_path_from_result(cls, result): + """Calculate rootless path from formatting result. + + Args: + result (TemplateResult): Result of StringTemplate formatting. + + Returns: + str: Rootless path if result contains one of anatomy roots. + """ + used_values = result.used_values missing_keys = result.missing_keys template = result.template @@ -924,7 +954,7 @@ def _rootless_path(self, result, final_data): if "root" in invalid_type: return - root_keys = self._dict_to_subkeys_list({"root": used_values["root"]}) + root_keys = cls._dict_to_subkeys_list({"root": used_values["root"]}) if not root_keys: return From c2fede9798b45985f05ae02dd27f4f6cff0ecce7 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 5 Apr 2023 16:59:27 +0200 Subject: [PATCH 826/898] Handle Harmony zip files with deeper structure (#4782) External Harmony zip files might contain one additional level with scene name. --- openpype/hosts/harmony/api/lib.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/harmony/api/lib.py b/openpype/hosts/harmony/api/lib.py index 8048705dc8d..b009dabb447 100644 --- a/openpype/hosts/harmony/api/lib.py +++ b/openpype/hosts/harmony/api/lib.py @@ -242,9 +242,15 @@ def launch_zip_file(filepath): print(f"Localizing {filepath}") temp_path = get_local_harmony_path(filepath) + scene_name = os.path.basename(temp_path) + if os.path.exists(os.path.join(temp_path, scene_name)): + # unzipped with duplicated scene_name + temp_path = os.path.join(temp_path, scene_name) + scene_path = os.path.join( - temp_path, os.path.basename(temp_path) + ".xstage" + temp_path, scene_name + ".xstage" ) + unzip = False if os.path.exists(scene_path): # Check remote scene is newer than local. @@ -262,6 +268,10 @@ def launch_zip_file(filepath): with _ZipFile(filepath, "r") as zip_ref: zip_ref.extractall(temp_path) + if os.path.exists(os.path.join(temp_path, scene_name)): + # unzipped with duplicated scene_name + temp_path = os.path.join(temp_path, scene_name) + # Close existing scene. if ProcessContext.pid: os.kill(ProcessContext.pid, signal.SIGTERM) @@ -309,7 +319,7 @@ def launch_zip_file(filepath): ) if not os.path.exists(scene_path): - print("error: cannot determine scene file") + print("error: cannot determine scene file {}".format(scene_path)) ProcessContext.server.stop() return From 25295c86772d468fbc98b8a22fda5b39370917c5 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 6 Apr 2023 11:38:28 +0200 Subject: [PATCH 827/898] Merge remote-tracking branch 'upstream/develop' into deadline_remove_framespertask # Conflicts: # openpype/modules/deadline/plugins/publish/submit_max_deadline.py --- .github/pr-branch-labeler.yml | 15 + .github/pr-glob-labeler.yml | 102 + .github/workflows/project_actions.yml | 115 + ARCHITECTURE.md | 77 + CHANGELOG.md | 926 ++ openpype/client/entities.py | 8 +- openpype/client/notes.md | 4 +- openpype/client/operations.py | 10 +- .../hooks/pre_create_extra_workdir_folders.py | 9 +- openpype/hooks/pre_foundry_apps.py | 4 +- openpype/host/dirmap.py | 4 +- openpype/host/host.py | 6 +- openpype/host/interfaces.py | 10 +- .../api/extension/jsx/hostscript.jsx | 2 +- openpype/hosts/aftereffects/api/ws_stub.py | 2 +- openpype/hosts/blender/api/ops.py | 6 +- .../plugins/publish/extract_playblast.py | 3 +- .../celaction/hooks/pre_celaction_setup.py | 36 +- .../publish/collect_celaction_cli_kwargs.py | 2 +- openpype/hosts/flame/api/lib.py | 4 +- openpype/hosts/flame/api/pipeline.py | 2 +- openpype/hosts/flame/api/plugin.py | 54 +- .../hosts/flame/api/scripts/wiretap_com.py | 2 +- openpype/hosts/flame/api/utils.py | 2 +- openpype/hosts/flame/hooks/pre_flame_setup.py | 2 +- .../flame/plugins/create/create_shot_clip.py | 2 +- .../hosts/flame/plugins/load/load_clip.py | 6 +- .../flame/plugins/load/load_clip_batch.py | 8 +- .../publish/collect_timeline_instances.py | 4 +- .../publish/extract_subset_resources.py | 4 +- .../plugins/publish/integrate_batch_group.py | 2 +- openpype/hosts/fusion/api/action.py | 13 +- openpype/hosts/fusion/api/menu.py | 13 - .../fusion/plugins/create/create_saver.py | 81 +- openpype/hosts/fusion/plugins/load/actions.py | 5 +- .../publish/collect_expected_frames.py | 50 + .../plugins/publish/collect_render_target.py | 44 - .../fusion/plugins/publish/collect_renders.py | 25 + .../plugins/publish/extract_render_local.py | 109 + .../fusion/plugins/publish/render_local.py | 100 - .../publish/validate_create_folder_checked.py | 14 +- .../validate_expected_frames_existence.py | 78 + .../hosts/fusion/scripts/set_rendermode.py | 112 - openpype/hosts/harmony/api/README.md | 8 +- openpype/hosts/harmony/api/TB_sceneOpened.js | 29 +- openpype/hosts/harmony/api/lib.py | 20 +- openpype/hosts/harmony/api/pipeline.py | 2 +- openpype/hosts/harmony/api/server.py | 2 +- .../harmony/plugins/publish/extract_render.py | 13 +- .../publish/validate_scene_settings.py | 25 +- .../harmony/vendor/OpenHarmony/README.md | 6 +- .../harmony/vendor/OpenHarmony/openHarmony.js | 8 +- .../openHarmony/openHarmony_actions.js | 6 +- .../openHarmony/openHarmony_application.js | 6 +- .../openHarmony/openHarmony_attribute.js | 8 +- .../openHarmony/openHarmony_backdrop.js | 4 +- .../openHarmony/openHarmony_color.js | 6 +- .../openHarmony/openHarmony_column.js | 4 +- .../openHarmony/openHarmony_database.js | 4 +- .../openHarmony/openHarmony_dialog.js | 18 +- .../openHarmony/openHarmony_drawing.js | 18 +- .../openHarmony/openHarmony_element.js | 4 +- .../openHarmony/openHarmony_file.js | 6 +- .../openHarmony/openHarmony_frame.js | 10 +- .../openHarmony/openHarmony_list.js | 6 +- .../openHarmony/openHarmony_math.js | 16 +- .../openHarmony/openHarmony_metadata.js | 4 +- .../openHarmony/openHarmony_misc.js | 6 +- .../openHarmony/openHarmony_network.js | 8 +- .../openHarmony/openHarmony_node.js | 22 +- .../openHarmony/openHarmony_nodeLink.js | 24 +- .../vendor/OpenHarmony/openHarmony_tools.js | 8 +- .../harmony/vendor/OpenHarmony/package.json | 2 +- openpype/hosts/hiero/api/__init__.py | 2 +- openpype/hosts/hiero/api/lib.py | 6 +- openpype/hosts/hiero/api/pipeline.py | 4 +- openpype/hosts/hiero/api/plugin.py | 46 +- openpype/hosts/houdini/api/lib.py | 14 +- openpype/hosts/houdini/api/pipeline.py | 11 +- openpype/hosts/houdini/api/plugin.py | 2 +- openpype/hosts/houdini/api/shelves.py | 2 +- .../houdini/plugins/create/convert_legacy.py | 4 +- .../plugins/publish/collect_current_file.py | 5 +- openpype/hosts/max/api/lib.py | 104 + openpype/hosts/max/api/menu.py | 20 + openpype/hosts/max/api/pipeline.py | 5 + .../max/plugins/publish/collect_render.py | 2 +- .../publish/increment_workfile_version.py | 19 + openpype/hosts/maya/api/commands.py | 2 +- openpype/hosts/maya/api/lib.py | 215 +- openpype/hosts/maya/api/lib_renderproducts.py | 31 +- openpype/hosts/maya/api/lib_rendersetup.py | 15 +- .../maya/api/workfile_template_builder.py | 4 +- .../hosts/maya/plugins/create/create_look.py | 4 +- .../maya/plugins/create/create_review.py | 2 + openpype/hosts/maya/plugins/load/actions.py | 2 +- .../maya/plugins/load/load_arnold_standin.py | 6 +- .../hosts/maya/plugins/load/load_audio.py | 22 +- .../hosts/maya/plugins/load/load_gpucache.py | 23 +- .../maya/plugins/load/load_image_plane.py | 151 +- .../hosts/maya/plugins/load/load_reference.py | 157 +- .../publish/collect_arnold_scene_source.py | 14 +- .../maya/plugins/publish/collect_instances.py | 49 +- .../maya/plugins/publish/collect_look.py | 2 +- .../publish/collect_multiverse_look.py | 2 +- .../maya/plugins/publish/collect_review.py | 176 +- .../publish/extract_arnold_scene_source.py | 84 +- .../maya/plugins/publish/extract_gpu_cache.py | 65 + .../maya/plugins/publish/extract_look.py | 892 +- .../publish/extract_multiverse_usd_over.py | 2 +- .../maya/plugins/publish/extract_playblast.py | 128 +- .../maya/plugins/publish/extract_thumbnail.py | 61 +- .../maya/plugins/publish/extract_vrayproxy.py | 4 +- .../plugins/publish/reset_xgen_attributes.py | 2 +- .../publish/validate_arnold_scene_source.py | 38 +- .../validate_arnold_scene_source_cbid.py | 74 + .../plugins/publish/validate_attributes.py | 114 +- .../publish/validate_camera_attributes.py | 2 +- .../plugins/publish/validate_frame_range.py | 4 +- .../publish/validate_look_color_space.py | 26 - .../plugins/publish/validate_look_contents.py | 22 + .../plugins/publish/validate_maya_units.py | 4 +- .../validate_mesh_arnold_attributes.py | 82 +- .../publish/validate_mesh_overlapping_uvs.py | 58 +- .../publish/validate_mvlook_contents.py | 3 +- .../plugins/publish/validate_no_namespace.py | 19 +- .../publish/validate_renderlayer_aovs.py | 4 +- .../publish/validate_rendersettings.py | 20 +- .../publish/validate_rig_output_ids.py | 79 +- .../validate_transform_naming_suffix.py | 2 +- .../hosts/maya/tools/mayalookassigner/app.py | 34 +- .../tools/mayalookassigner/arnold_standin.py | 247 + .../maya/tools/mayalookassigner/commands.py | 51 +- .../hosts/maya/tools/mayalookassigner/lib.py | 87 + .../tools/mayalookassigner/vray_proxies.py | 101 +- openpype/hosts/nuke/api/lib.py | 26 +- openpype/hosts/nuke/api/plugin.py | 23 +- openpype/hosts/nuke/api/utils.py | 2 +- .../nuke/api/workfile_template_builder.py | 29 +- .../nuke/plugins/create/convert_legacy.py | 2 +- .../nuke/plugins/create/create_source.py | 2 +- .../nuke/plugins/create/create_write_image.py | 7 - .../plugins/create/create_write_prerender.py | 7 - .../plugins/create/create_write_render.py | 7 - openpype/hosts/nuke/plugins/load/actions.py | 5 +- .../hosts/nuke/plugins/load/load_backdrop.py | 22 +- .../nuke/plugins/load/load_script_precomp.py | 1 - .../nuke/plugins/publish/collect_backdrop.py | 32 +- .../plugins/publish/collect_context_data.py | 2 - .../nuke/plugins/publish/collect_gizmo.py | 1 - .../nuke/plugins/publish/collect_model.py | 1 - .../nuke/plugins/publish/collect_reads.py | 4 +- .../nuke/plugins/publish/collect_writes.py | 2 +- .../plugins/publish/extract_review_data.py | 2 +- .../publish/extract_review_data_lut.py | 7 +- .../publish/extract_review_data_mov.py | 5 +- .../nuke/plugins/publish/extract_thumbnail.py | 2 +- .../nuke/plugins/publish/validate_backdrop.py | 2 +- .../photoshop/api/extension/host/index.jsx | 6 +- openpype/hosts/photoshop/api/launch_logic.py | 4 +- .../plugins/publish/extract_review.py | 1 - openpype/hosts/resolve/api/lib.py | 6 +- openpype/hosts/resolve/api/menu_style.qss | 2 +- openpype/hosts/resolve/api/plugin.py | 17 +- .../publish/collect_bulk_mov_instances.py | 4 +- .../plugins/publish/collect_context.py | 8 +- .../plugins/publish/collect_editorial.py | 2 +- .../plugins/publish/validate_frame_ranges.py | 2 +- openpype/hosts/traypublisher/api/editorial.py | 38 +- .../plugins/create/create_editorial.py | 14 +- .../publish/collect_simple_instances.py | 2 +- .../hosts/tvpaint/api/communication_server.py | 4 +- openpype/hosts/tvpaint/api/pipeline.py | 5 - .../tvpaint/plugins/create/convert_legacy.py | 4 +- .../tvpaint/plugins/create/create_render.py | 15 +- .../publish/collect_instance_frames.py | 2 + .../help/validate_layers_visibility.xml | 2 +- .../help/validate_workfile_metadata.xml | 2 +- .../help/validate_workfile_project_name.xml | 2 +- .../plugins/publish/validate_asset_name.py | 14 +- .../publish/validate_layers_visibility.py | 2 +- .../tvpaint/plugins/publish/validate_marks.py | 13 +- .../publish/validate_scene_settings.py | 13 +- .../plugins/publish/validate_start_frame.py | 13 +- openpype/hosts/unreal/api/pipeline.py | 2 +- .../Source/OpenPype/Private/OpenPypeLib.cpp | 2 +- .../Public/Commandlets/OPActionResult.h | 12 +- .../Source/OpenPype/Private/OpenPypeLib.cpp | 2 +- .../Public/Commandlets/OPActionResult.h | 12 +- .../hosts/unreal/plugins/load/load_camera.py | 2 +- openpype/hosts/unreal/ue_workers.py | 142 +- openpype/hosts/webpublisher/lib.py | 2 +- openpype/lib/applications.py | 20 +- openpype/lib/attribute_definitions.py | 6 +- openpype/lib/events.py | 2 +- openpype/lib/execute.py | 25 +- openpype/lib/file_transaction.py | 24 +- openpype/lib/path_templates.py | 26 +- openpype/lib/transcoding.py | 6 +- openpype/lib/vendor_bin_utils.py | 16 +- openpype/modules/base.py | 14 +- openpype/modules/clockify/clockify_api.py | 2 +- openpype/modules/clockify/clockify_module.py | 2 +- openpype/modules/clockify/widgets.py | 2 +- .../deadline/plugins/publish/collect_pools.py | 47 +- .../publish/submit_celaction_deadline.py | 2 +- .../plugins/publish/submit_nuke_deadline.py | 21 +- .../plugins/publish/submit_publish_job.py | 43 +- .../publish/validate_deadline_pools.py | 10 +- .../example_addons/example_addon/addon.py | 2 +- .../action_clone_review_session.py | 2 +- .../action_create_review_session.py | 2 +- .../action_prepare_project.py | 2 +- .../action_push_frame_values_to_task.py | 316 +- .../action_tranfer_hierarchical_values.py | 4 +- .../event_next_task_update.py | 2 +- .../event_push_frame_values_to_task.py | 1102 +- .../event_radio_buttons.py | 2 +- .../event_sync_to_avalon.py | 14 +- .../event_task_to_parent_status.py | 4 +- .../event_user_assigment.py | 4 +- .../event_version_to_task_statuses.py | 2 +- .../action_applications.py | 9 + .../action_batch_task_creation.py | 2 +- .../action_create_cust_attrs.py | 6 +- .../action_create_folders.py | 2 +- .../action_delete_asset.py | 2 +- .../action_delete_old_versions.py | 4 +- .../event_handlers_user/action_delivery.py | 2 +- .../action_fill_workfile_attr.py | 2 +- .../event_handlers_user/action_job_killer.py | 6 +- .../action_prepare_project.py | 4 +- .../ftrack/event_handlers_user/action_rv.py | 2 +- .../ftrack/event_handlers_user/action_seed.py | 10 +- .../action_store_thumbnails_to_avalon.py | 2 +- .../ftrack/ftrack_server/event_server_cli.py | 6 +- openpype/modules/ftrack/lib/avalon_sync.py | 14 +- .../modules/ftrack/lib/custom_attributes.py | 2 +- .../ftrack/lib/ftrack_action_handler.py | 2 +- .../modules/ftrack/lib/ftrack_base_handler.py | 4 +- .../publish/collect_custom_attributes_data.py | 2 +- .../plugins/publish/integrate_ftrack_api.py | 2 +- .../publish/integrate_hierarchy_ftrack.py | 2 +- openpype/modules/ftrack/tray/ftrack_tray.py | 2 +- openpype/modules/interfaces.py | 2 +- .../plugins/publish/collect_kitsu_entities.py | 2 +- .../plugins/publish/integrate_kitsu_note.py | 107 +- .../plugins/publish/integrate_kitsu_review.py | 8 +- .../modules/kitsu/utils/update_op_with_zou.py | 56 +- openpype/modules/settings_action.py | 6 +- openpype/pipeline/anatomy.py | 64 +- openpype/pipeline/colorspace.py | 5 +- openpype/pipeline/create/context.py | 100 +- openpype/pipeline/publish/contants.py | 1 + openpype/pipeline/publish/lib.py | 80 +- openpype/plugins/publish/cleanup.py | 4 + openpype/plugins/publish/cleanup_farm.py | 2 +- .../publish/collect_context_entities.py | 21 +- .../publish/collect_custom_staging_dir.py | 70 + .../plugins/publish/collect_otio_review.py | 4 +- openpype/plugins/publish/extract_burnin.py | 51 +- openpype/plugins/publish/extract_review.py | 405 +- openpype/plugins/publish/integrate.py | 20 +- .../plugins/publish/integrate_hero_version.py | 33 +- openpype/plugins/publish/integrate_legacy.py | 2 +- .../preintegrate_thumbnail_representation.py | 2 + openpype/scripts/otio_burnin.py | 125 +- .../defaults/project_anatomy/templates.json | 6 +- .../project_settings/applications.json | 3 + .../defaults/project_settings/celaction.json | 7 + .../defaults/project_settings/deadline.json | 5 +- .../defaults/project_settings/global.json | 26 +- .../defaults/project_settings/kitsu.json | 10 +- .../defaults/project_settings/maya.json | 33 +- .../defaults/project_settings/tvpaint.json | 1 + .../system_settings/applications.json | 2 +- .../schemas/projects_schema/schema_main.json | 4 + .../schema_project_applications.json | 14 + .../schema_project_celaction.json | 25 + .../schema_project_deadline.json | 17 +- .../projects_schema/schema_project_kitsu.json | 84 +- .../schema_project_tvpaint.json | 6 + .../schemas/schema_global_publish.json | 2 +- .../schemas/schema_global_tools.json | 65 + .../schemas/schema_maya_capture.json | 32 +- .../schemas/schema_maya_create.json | 5 + .../schemas/schema_maya_publish.json | 88 + openpype/tools/launcher/models.py | 6 + openpype/tools/loader/model.py | 7 +- .../project_manager/project_manager/view.py | 4 +- openpype/tools/publisher/constants.py | 5 +- openpype/tools/publisher/control.py | 185 +- openpype/tools/publisher/widgets/__init__.py | 6 +- .../publisher/widgets/card_view_widgets.py | 19 + .../tools/publisher/widgets/images/save.png | Bin 0 -> 3961 bytes .../publisher/widgets/list_view_widgets.py | 27 + .../publisher/widgets/overview_widget.py | 38 +- .../publisher/widgets/validations_widget.py | 4 +- openpype/tools/publisher/widgets/widgets.py | 34 +- openpype/tools/publisher/window.py | 129 +- openpype/tools/sceneinventory/model.py | 16 +- openpype/tools/sceneinventory/view.py | 7 + openpype/tools/traypublisher/window.py | 2 +- openpype/tools/utils/delegates.py | 8 +- openpype/tools/utils/lib.py | 4 +- openpype/tools/workfiles/files_widget.py | 22 +- openpype/tools/workfiles/save_as_dialog.py | 6 +- openpype/vendor/python/common/capture.py | 25 +- openpype/version.py | 2 +- openpype/widgets/splash_screen.py | 11 +- pyproject.toml | 2 +- .../nuke/test_deadline_publish_in_nuke.py | 18 + .../hosts/nuke/test_publish_in_nuke.py | 20 +- website/docs/admin_hosts_maya.md | 68 +- website/docs/artist_hosts_aftereffects.md | 36 +- .../assets/integrate_kitsu_note_settings.png | Bin 0 -> 48874 bytes .../maya-admin_extract_playblast_settings.png | Bin 0 -> 26814 bytes ...ract_playblast_settings_camera_options.png | Bin 0 -> 16732 bytes ...ct_playblast_settings_viewport_options.png | Bin 0 -> 1064191 bytes website/docs/assets/maya-admin_gpu_cache.png | Bin 0 -> 20248 bytes website/docs/module_kitsu.md | 15 +- .../global_tools_custom_staging_dir.png | Bin 0 -> 9940 bytes .../settings_project_global.md | 107 +- website/docs/pype2/admin_presets_plugins.md | 4 +- website/yarn.lock | 11812 +++++++--------- 325 files changed, 12368 insertions(+), 10079 deletions(-) create mode 100644 .github/pr-branch-labeler.yml create mode 100644 .github/pr-glob-labeler.yml create mode 100644 .github/workflows/project_actions.yml create mode 100644 ARCHITECTURE.md create mode 100644 openpype/hosts/fusion/plugins/publish/collect_expected_frames.py delete mode 100644 openpype/hosts/fusion/plugins/publish/collect_render_target.py create mode 100644 openpype/hosts/fusion/plugins/publish/collect_renders.py create mode 100644 openpype/hosts/fusion/plugins/publish/extract_render_local.py delete mode 100644 openpype/hosts/fusion/plugins/publish/render_local.py create mode 100644 openpype/hosts/fusion/plugins/publish/validate_expected_frames_existence.py delete mode 100644 openpype/hosts/fusion/scripts/set_rendermode.py create mode 100644 openpype/hosts/max/plugins/publish/increment_workfile_version.py create mode 100644 openpype/hosts/maya/plugins/publish/extract_gpu_cache.py create mode 100644 openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py delete mode 100644 openpype/hosts/maya/plugins/publish/validate_look_color_space.py create mode 100644 openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py create mode 100644 openpype/hosts/maya/tools/mayalookassigner/lib.py create mode 100644 openpype/plugins/publish/collect_custom_staging_dir.py create mode 100644 openpype/settings/defaults/project_settings/applications.json create mode 100644 openpype/settings/entities/schemas/projects_schema/schema_project_applications.json create mode 100644 openpype/tools/publisher/widgets/images/save.png create mode 100644 website/docs/assets/integrate_kitsu_note_settings.png create mode 100644 website/docs/assets/maya-admin_extract_playblast_settings.png create mode 100644 website/docs/assets/maya-admin_extract_playblast_settings_camera_options.png create mode 100644 website/docs/assets/maya-admin_extract_playblast_settings_viewport_options.png create mode 100644 website/docs/assets/maya-admin_gpu_cache.png create mode 100644 website/docs/project_settings/assets/global_tools_custom_staging_dir.png diff --git a/.github/pr-branch-labeler.yml b/.github/pr-branch-labeler.yml new file mode 100644 index 00000000000..b4343262366 --- /dev/null +++ b/.github/pr-branch-labeler.yml @@ -0,0 +1,15 @@ +# Apply label "feature" if head matches "feature/*" +'type: feature': + head: "feature/*" + +# Apply label "feature" if head matches "feature/*" +'type: enhancement': + head: "enhancement/*" + +# Apply label "bugfix" if head matches one of "bugfix/*" or "hotfix/*" +'type: bug': + head: ["bugfix/*", "hotfix/*"] + +# Apply label "release" if base matches "release/*" +'Bump Minor': + base: "release/next-minor" diff --git a/.github/pr-glob-labeler.yml b/.github/pr-glob-labeler.yml new file mode 100644 index 00000000000..286e7768b5e --- /dev/null +++ b/.github/pr-glob-labeler.yml @@ -0,0 +1,102 @@ +# Add type: unittest label if any changes in tests folders +'type: unittest': +- '*/*tests*/**/*' + +# any changes in documentation structure +'type: documentation': +- '*/**/*website*/**/*' +- '*/**/*docs*/**/*' + +# hosts triage +'host: Nuke': +- '*/**/*nuke*' +- '*/**/*nuke*/**/*' + +'host: Photoshop': +- '*/**/*photoshop*' +- '*/**/*photoshop*/**/*' + +'host: Harmony': +- '*/**/*harmony*' +- '*/**/*harmony*/**/*' + +'host: UE': +- '*/**/*unreal*' +- '*/**/*unreal*/**/*' + +'host: Houdini': +- '*/**/*houdini*' +- '*/**/*houdini*/**/*' + +'host: Maya': +- '*/**/*maya*' +- '*/**/*maya*/**/*' + +'host: Resolve': +- '*/**/*resolve*' +- '*/**/*resolve*/**/*' + +'host: Blender': +- '*/**/*blender*' +- '*/**/*blender*/**/*' + +'host: Hiero': +- '*/**/*hiero*' +- '*/**/*hiero*/**/*' + +'host: Fusion': +- '*/**/*fusion*' +- '*/**/*fusion*/**/*' + +'host: Flame': +- '*/**/*flame*' +- '*/**/*flame*/**/*' + +'host: TrayPublisher': +- '*/**/*traypublisher*' +- '*/**/*traypublisher*/**/*' + +'host: 3dsmax': +- '*/**/*max*' +- '*/**/*max*/**/*' + +'host: TV Paint': +- '*/**/*tvpaint*' +- '*/**/*tvpaint*/**/*' + +'host: CelAction': +- '*/**/*celaction*' +- '*/**/*celaction*/**/*' + +'host: After Effects': +- '*/**/*aftereffects*' +- '*/**/*aftereffects*/**/*' + +'host: Substance Painter': +- '*/**/*substancepainter*' +- '*/**/*substancepainter*/**/*' + +# modules triage +'module: Deadline': +- '*/**/*deadline*' +- '*/**/*deadline*/**/*' + +'module: RoyalRender': +- '*/**/*royalrender*' +- '*/**/*royalrender*/**/*' + +'module: Sitesync': +- '*/**/*sync_server*' +- '*/**/*sync_server*/**/*' + +'module: Ftrack': +- '*/**/*ftrack*' +- '*/**/*ftrack*/**/*' + +'module: Shotgrid': +- '*/**/*shotgrid*' +- '*/**/*shotgrid*/**/*' + +'module: Kitsu': +- '*/**/*kitsu*' +- '*/**/*kitsu*/**/*' diff --git a/.github/workflows/project_actions.yml b/.github/workflows/project_actions.yml new file mode 100644 index 00000000000..3589b4acc20 --- /dev/null +++ b/.github/workflows/project_actions.yml @@ -0,0 +1,115 @@ +name: project-actions + +on: + pull_request_target: + types: [opened, assigned] + pull_request_review: + types: [submitted] + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + +jobs: + + pr_review_started: + name: pr_review_started + runs-on: ubuntu-latest + # ----------------------------- + # conditions are: + # - PR issue comment which is not form Ynbot + # - PR review comment which is not Hound (or any other bot) + # - PR review submitted which is not from Hound (or any other bot) and is not 'Changes requested' + # - make sure it only runs if not forked repo + # ----------------------------- + if: | + (github.event_name == 'issue_comment' && github.event.pull_request.head.repo.owner.login == 'ynput' && github.event.comment.user.id != 82967070) || + (github.event_name == 'pull_request_review_comment' && github.event.pull_request.head.repo.owner.login == 'ynput' && github.event.comment.user.type != 'Bot') || + (github.event_name == 'pull_request_review' && + github.event.pull_request.head.repo.owner.login == 'ynput' && + github.event.review.state != 'changes_requested' && + github.event.review.state != 'approved' && + github.event.review.user.type != 'Bot') + steps: + - name: Move PR to 'Review In Progress' + uses: leonsteinhaeuser/project-beta-automations@v2.1.0 + with: + gh_token: ${{ secrets.YNPUT_BOT_TOKEN }} + organization: ynput + project_id: 11 + resource_node_id: ${{ github.event.pull_request.node_id || github.event.issue.node_id }} + status_value: Review In Progress + + pr_review_requested: + # ----------------------------- + # Resets Clickup Task status to 'In Progress' after 'Changes Requested' were submitted to PR + # It only runs if custom clickup task id was found in ref branch of PR + # ----------------------------- + name: pr_review_requested + runs-on: ubuntu-latest + if: github.event_name == 'pull_request_review' && github.event.pull_request.head.repo.owner.login == 'ynput' && github.event.review.state == 'changes_requested' + steps: + - name: Set branch env + run: echo "BRANCH_NAME=${{ github.event.pull_request.head.ref}}" >> $GITHUB_ENV + - name: Get ClickUp ID from ref head name + id: get_cuID + run: | + echo ${{ env.BRANCH_NAME }} + echo "cuID=$(echo $BRANCH_NAME | sed 's/.*\/\(OP\-[0-9]\{4\}\).*/\1/')" >> $GITHUB_OUTPUT + + - name: Print ClickUp ID + run: echo ${{ steps.get_cuID.outputs.cuID }} + + - name: Move found Clickup task to 'Review in Progress' + if: steps.get_cuID.outputs.cuID + run: | + curl -i -X PUT \ + 'https://api.clickup.com/api/v2/task/${{ steps.get_cuID.outputs.cuID }}?custom_task_ids=true&team_id=${{secrets.CLICKUP_TEAM_ID}}' \ + -H 'Authorization: ${{secrets.CLICKUP_API_KEY}}' \ + -H 'Content-Type: application/json' \ + -d '{ + "status": "in progress" + }' + + size-label: + name: pr_size_label + runs-on: ubuntu-latest + if: github.event.action == 'assigned' || github.event.action == 'opened' + steps: + - name: Add size label + uses: "pascalgn/size-label-action@v0.4.3" + env: + GITHUB_TOKEN: "${{ secrets.YNPUT_BOT_TOKEN }}" + IGNORED: ".gitignore\n*.md\n*.json" + with: + sizes: > + { + "0": "XS", + "100": "S", + "500": "M", + "1000": "L", + "1500": "XL", + "2500": "XXL" + } + + label_prs_branch: + name: pr_branch_label + runs-on: ubuntu-latest + if: github.event.action == 'assigned' || github.event.action == 'opened' + steps: + - name: Label PRs - Branch name detection + uses: ffittschen/pr-branch-labeler@v1 + with: + repo-token: ${{ secrets.YNPUT_BOT_TOKEN }} + + label_prs_globe: + name: pr_globe_label + runs-on: ubuntu-latest + if: github.event.action == 'assigned' || github.event.action == 'opened' + steps: + - name: Label PRs - Globe detection + uses: actions/labeler@v4.0.3 + with: + repo-token: ${{ secrets.YNPUT_BOT_TOKEN }} + configuration-path: ".github/pr-glob-labeler.yml" + sync-labels: false diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 00000000000..912780d803b --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,77 @@ +# Architecture + +OpenPype is a monolithic Python project that bundles several parts, this document will try to give a birds eye overview of the project and, to a certain degree, each of the sub-projects. +The current file structure looks like this: + +``` +. +├── common - Code in this folder is backend portion of Addon distribution logic for v4 server. +├── docs - Documentation of the source code. +├── igniter - The OpenPype bootstrapper, deals with running version resolution and setting up the connection to the mongodb. +├── openpype - The actual OpenPype core package. +├── schema - Collection of JSON files describing schematics of objects. This follows Avalon's convention. +├── tests - Integration and unit tests. +├── tools - Conveninece scripts to perform common actions (in both bash and ps1). +├── vendor - When using the igniter, it deploys third party tools in here, such as ffmpeg. +└── website - Source files for https://openpype.io/ which is Docusaursus (https://docusaurus.io/). +``` + +The core functionality of the pipeline can be found in `igniter` and `openpype`, which in turn rely on the `schema` files, whenever you build (or download a pre-built) version of OpenPype, these two are bundled in there, and `Igniter` is the entry point. + + +## Igniter + +It's the setup and update tool for OpenPype, unless you want to package `openpype` separately and deal with all the config manually, this will most likely be your entry point. + +``` +igniter/ +├── bootstrap_repos.py - Module that will find or install OpenPype versions in the system. +├── __init__.py - Igniter entry point. +├── install_dialog.py- Show dialog for choosing central pype repository. +├── install_thread.py - Threading helpers for the install process. +├── __main__.py - Like `__init__.py` ? +├── message_dialog.py - Qt Dialog with a message and "Ok" button. +├── nice_progress_bar.py - Fancy Qt progress bar. +├── splash.txt - ASCII art for the terminal installer. +├── stylesheet.css - Installer Qt styles. +├── terminal_splash.py - Terminal installer animation, relies in `splash.txt`. +├── tools.py - Collection of methods that don't fit in other modules. +├── update_thread.py - Threading helper to update existing OpenPype installs. +├── update_window.py - Qt UI to update OpenPype installs. +├── user_settings.py - Interface for the OpenPype user settings. +└── version.py - Igniter's version number. +``` + +## OpenPype + +This is the main package of the OpenPype logic, it could be loosely described as a combination of [Avalon](https://getavalon.github.io), [Pyblish](https://pyblish.com/) and glue around those with custom OpenPype only elements, things are in progress of being moved around to better prepare for V4, which will be released under a new name AYON. + +``` +openpype/ +├── client - Interface for the MongoDB. +├── hooks - Hooks to be executed on certain OpenPype Applications defined in `openpype.lib.applications`. +├── host - Base class for the different hosts. +├── hosts - Integration with the different DCCs (hosts) using the `host` base class. +├── lib - Libraries that stitch together the package, some have been moved into other parts. +├── modules - OpenPype modules should contain separated logic of specific kind of implementation, such as Ftrack connection and its python API. +├── pipeline - Core of the OpenPype pipeline, handles creation of data, publishing, etc. +├── plugins - Global/core plugins for loader and publisher tool. +├── resources - Icons, fonts, etc. +├── scripts - Loose scipts that get run by tools/publishers. +├── settings - OpenPype settings interface. +├── style - Qt styling. +├── tests - Unit tests. +├── tools - Core tools, check out https://openpype.io/docs/artist_tools. +├── vendor - Vendoring of needed required Python packes. +├── widgets - Common re-usable Qt Widgets. +├── action.py - LEGACY: Lives now in `openpype.pipeline.publish.action` Pyblish actions. +├── cli.py - Command line interface, leverages `click`. +├── __init__.py - Sets two constants. +├── __main__.py - Entry point, calls the `cli.py` +├── plugin.py - Pyblish plugins. +├── pype_commands.py - Implementation of OpenPype commands. +└── version.py - Current version number. +``` + + + diff --git a/CHANGELOG.md b/CHANGELOG.md index 145c2e2c1ac..4e22b783c4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,931 @@ # Changelog +## [3.15.3](https://github.com/ynput/OpenPype/tree/3.15.3) + + +[Full Changelog](https://github.com/ynput/OpenPype/compare/3.15.2...3.15.3) + +### **🆕 New features** + + +

    +Blender: Extract Review #3616 + +Added Review to Blender. + +This implementation is based on #3508 but made compatible for the current implementation of OpenPype for Blender. + + +___ + +
    + + +
    +Data Exchanges: Point Cloud for 3dsMax #4532 + +Publish PRT format with tyFlow in 3dsmax + +Publish PRT format with tyFlow in 3dsmax and possibly set up loader to load the format too. +- [x] creator +- [x] extractor +- [x] validator +- [x] loader + + +___ + +
    + + +
    +Global: persistent staging directory for renders #4583 + +Allows configure if staging directory (`stagingDir`) should be persistent with use of profiles. + +With this feature, users can specify a transient data folder path based on presets, which can be used during the creation and publishing stages. In some cases, these DCCs automatically add a rendering path during the creation stage, which is then used in publishing.One of the key advantages of this feature is that it allows users to take advantage of faster storages for rendering, which can help improve workflow efficiency. Additionally, this feature allows users to keep their rendered data persistent, and use their own infrastructure for regular cleaning.However, it should be noted that some productions may want to use this feature without persistency. Furthermore, there may be a need for retargeting the rendering folder to faster storages, which is also not supported at the moment.It is studio responsibility to clean up obsolete folders with data.Location of the folder is configured in `project_anatomy/templates/others`. ('transient' key is expected, with 'folder' key, could be more templates)Which family/task type/subset is applicable is configured in:`project_settings/global/tools/publish/transient_dir_profiles` + + +___ + +
    + + +
    +Kitsu custom comment template #4599 + +Kitsu allows to write markdown in its comment field. This can be something very powerful to deliver dynamic comments with the help the data from the instance.This feature is defaults to off so the admin have to manually set up the comment field the way they want.I have added a basic example on how the comment can look like as the comment-fields default value.To this I want to add some documentation also but that's on its way when the code itself looks good for the reviewers. + + +___ + +
    + + +
    +MaxScene Family #4615 + +Introduction of the Max Scene Family + + +___ + +
    + +### **🚀 Enhancements** + + +
    +Maya: Multiple values on single render attribute - OP-4131 #4631 + +When validating render attributes, this adds support for multiple values. When repairing first value in list is used. + + +___ + +
    + + +
    +Maya: enable 2D Pan/Zoom for playblasts - OP-5213 #4687 + +Setting for enabling 2D Pan/Zoom on reviews. + + +___ + +
    + + +
    +Copy existing or generate new Fusion profile on prelaunch #4572 + +Fusion preferences will be copied to the predefined `~/.openpype/hosts/fusion/prefs` folder (or any other folder set in system settings) on launch. + +The idea is to create a copy of existing Fusion profile, adding an OpenPype menu to the Fusion instance.By default the copy setting is turned off, so no file copying is performed. Instead the clean Fusion profile is created by Fusion in the predefined folder. The default locaion is set to `~/.openpype/hosts/fusion/prefs`, to better comply with the other os platforms. After creating the default profile, some modifications are applied: +- forced Python3 +- forced English interface +- setup Openpype specific path maps.If the `copy_prefs` checkbox is toggled, a copy of existing Fusion profile folder will be placed in the mentioned location. Then they are altered the same way as described above. The operation is run only once, on the first launch, unless the `force_sync [Resync profile on each launch]` is toggled.English interface is forced because the `FUSION16_PROFILE_DIR` environment variable is not read otherwise (seems to be a Fusion bug). + + +___ + +
    + + +
    +Houdini: Create button open new publisher's "create" tab #4601 + +During a talk with @maxpareschi he mentioned that the new publisher in Houdini felt super confusing due to "Create" going to the older creator but now being completely empty and the publish button directly went to the publish tab.This resolves that by fixing the Create button to now open the new publisher but on the Create tab.Also made publish button enforce going to the "publish" tab for consistency in usage.@antirotor I think changing the Create button's callback was just missed in this commit or was there a specific reason to not change that around yet? + + +___ + +
    + + +
    +Clockify: refresh and fix the integration #4607 + +Due to recent API changes, Clockify requires `user_id` to operate with the timers. I updated this part and currently it is a WIP for making it fully functional. Most functions, such as start and stop timer, and projects sync are currently working. For the rate limiting task new dependency is added: https://pypi.org/project/ratelimiter/ + + +___ + +
    + + +
    +Fusion publish existing frames #4611 + +This PR adds the function to publish existing frames instead of having to re-render all of them for each new publish.I have split the render_locally plugin so the review-part is its own plugin now.I also change the saver-creator-plugin's label from Saver to Render (saver) as I intend to add a Prerender creator like in Nuke. + + +___ + +
    + + +
    +Resolution settings referenced from DB record for 3dsMax #4652 + +- Add Callback for setting the resolution according to DB after the new scene is created. +- Add a new Action into openpype menu which allows the user to reset the resolution in 3dsMax + + +___ + +
    + + +
    +3dsmax: render instance settings in Publish tab #4658 + +Allows user preset the pools, group and use_published settings in Render Creator in the Max Hosts.User can set the settings before or after creating instance in the new publisher + + +___ + +
    + + +
    +scene length setting referenced from DB record for 3dsMax #4665 + +Setting the timeline length based on DB record in 3dsMax Hosts + + +___ + +
    + + +
    +Publisher: Windows reduce command window pop-ups during Publishing #4672 + +Reduce the command line pop-ups that show on Windows during publishing. + + +___ + +
    + + +
    +Publisher: Explicit save #4676 + +Publisher have explicit button to save changes, so reset can happen without saving any changes. Save still happens automatically when publishing is started or on publisher window close. But a popup is shown if context of host has changed. Important context was enhanced by workfile path (if host integration supports it) so workfile changes are captured too. In that case a dialog with confirmation is shown to user. All callbacks that may require save of context were moved to main window to be able handle dialog show at one place. Save changes now returns success so the rest of logic is skipped -> publishing won't start, when save of instances fails.Save and reset buttons have shortcuts (Ctrl + s and Ctrls + r). + + +___ + +
    + + +
    +CelAction: conditional workfile parameters from settings #4677 + +Since some productions were requesting excluding some workfile parameters from publishing submission, we needed to move them to settings so those could be altered per project. + + +___ + +
    + + +
    +Improve logging of used app + tool envs on application launch #4682 + +Improve logging of what apps + tool environments got loaded for an application launch. + + +___ + +
    + + +
    +Fix name and docstring for Create Workdir Extra Folders prelaunch hook #4683 + +Fix class name and docstring for Create Workdir Extra Folders prelaunch hookThe class name and docstring were originally copied from another plug-in and didn't match the plug-in logic.This also fixes potentially seeing this twice in your logs. Before:After:Where it was actually running both this prelaunch hook and the actual `AddLastWorkfileToLaunchArgs` plugin. + + +___ + +
    + + +
    +Application launch context: Include app group name in logger #4684 + +Clarify in logs better what app group the ApplicationLaunchContext belongs to and what application is being launched.Before:After: + + +___ + +
    + + +
    +increment workfile version 3dsmax #4685 + +increment workfile version in 3dsmax as if in blender and maya hosts. + + +___ + +
    + +### **🐛 Bug fixes** + + +
    +Maya: Fix getting non-active model panel. #2968 + +When capturing multiple cameras with image planes that have file sequences playing, only the active (first) camera will play through the file sequence. + + +___ + +
    + + +
    +Maya: Fix broken review publishing. #4549 + +Resolves #4547 + + +___ + +
    + + +
    +Maya: Avoid error on right click in Loader if `mtoa` is not loaded #4616 + +Fix an error on right clicking in the Loader when `mtoa` is not a loaded plug-in.Additionally if `mtoa` isn't loaded the loader will now load the plug-in before trying to create the arnold standin. + + +___ + +
    + + +
    +Maya: Fix extract look colorspace detection #4618 + +Fix the logic which guesses the colorspace using `arnold` python library. +- Previously it'd error if `mtoa` was not available on path so it still required `mtoa` to be available. +- The guessing colorspace logic doesn't actually require `mtoa` to be loaded, but just the `arnold` python library to be available. This changes the logic so it doesn't require the `mtoa` plugin to get loaded to guess the colorspace. +- The if/else branch was likely not doing what was intended `cmds.loadPlugin("mtoa", quiet=True)` returns None if the plug-in was already loaded. So this would only ever be true if it ends up loading the `mtoa` plugin the first time. +```python +# Tested in Maya 2022.1 +print(cmds.loadPlugin("mtoa", quiet=True)) +# ['mtoa'] +print(cmds.loadPlugin("mtoa", quiet=True)) +# None +``` + + +___ + +
    + + +
    +Maya: Maya Playblast Options overrides - OP-3847 #4634 + +When publishing a review in Maya, the extractor would fail due to wrong (long) panel name. + + +___ + +
    + + +
    +Bugfix/op 2834 fix extract playblast #4701 + +Paragraphs contain detailed information on the changes made to the product or service, providing an in-depth description of the updates and enhancements. They can be used to explain the reasoning behind the changes, or to highlight the importance of the new features. Paragraphs can often include links to further information or support documentation. + + +___ + +
    + + +
    +Bugfix/op 2834 fix extract playblast #4704 + +Paragraphs contain detailed information on the changes made to the product or service, providing an in-depth description of the updates and enhancements. They can be used to explain the reasoning behind the changes, or to highlight the importance of the new features. Paragraphs can often include links to further information or support documentation. + + +___ + +
    + + +
    +Maya: bug fix for passing zoom settings if review is attached to subset #4716 + +Fix for attaching review to subset with pan/zoom option. + + +___ + +
    + + +
    +Maya: tile assembly fail in draft - OP-4820 #4416 + +Tile assembly in Deadline was broken. + +Initial bug report revealed other areas of the tile assembly that needed fixing. + + +___ + +
    + + +
    +Maya: Yeti Validate Rig Input - OP-3454 #4554 + +Fix Yeti Validate Rig Input + +Existing workflow was broken due to this #3297. + + +___ + +
    + + +
    +Scene inventory: Fix code errors when "not found" entries are found #4594 + +Whenever a "NOT FOUND" entry is present a lot of errors happened in the Scene Inventory: +- It started spamming a lot of errors for the VersionDelegate since it had no numeric version (no version at all).Error reported on Discord: +```python +Traceback (most recent call last): + File "C:\Users\videopro\Documents\github\OpenPype\openpype\tools\utils\delegates.py", line 65, in paint + text = self.displayText( + File "C:\Users\videopro\Documents\github\OpenPype\openpype\tools\utils\delegates.py", line 33, in displayText + assert isinstance(value, numbers.Integral), ( +AssertionError: Version is not integer. "None" +``` +- Right click menu would error on NOT FOUND entries, and thus not show. With this PR it will now _disregard_ not found items for "Set version" and "Remove" but still allow actions.This PR resolves those. + + +___ + +
    + + +
    +Kitsu: Sync OP with zou, make sure value-data is int or float #4596 + +Currently the data zou pulls is a string and not a value causing some bugs in the pipe where a value is expected (like `Set frame range` in Fusion). + + + +This PR makes sure each value is set with int() or float() so these bugs can't happen later on. + + + +_(A request to cgwire has also bin sent to allow force values only for some metadata columns, but currently the user can enter what ever they want in there)_ + + +___ + +
    + + +
    +Max: fix the bug of removing an instance #4617 + +fix the bug of removing an instance in 3dsMax + + +___ + +
    + + +
    +Global | Nuke: fixing farm publishing workflow #4623 + +After Nuke had adopted new publisher with new creators new issues were introduced. Those issues were addressed with this PR. Those are for example broken reviewable video files publishing if published via farm. Also fixed local publishing. + + +___ + +
    + + +
    +Ftrack: Ftrack additional families filtering #4633 + +Ftrack family collector makes sure the subset family is also in instance families for additional families filtering. + + +___ + +
    + + +
    +Ftrack: Hierarchical <> Non-Hierarchical attributes sync fix #4635 + +Sync between hierarchical and non-hierarchical attributes should be fixed and work as expected. Action should sync the values as expected and event handler should do it too and only on newly created entities. + + +___ + +
    + + +
    +bugfix for 3dsmax publishing error #4637 + +fix the bug of failing publishing job in 3dsMax + + +___ + +
    + + +
    +General: Use right validation for ffmpeg executable #4640 + +Use ffmpeg exec validation for ffmpeg executables instead of oiio exec validation. The validation is used as last possible source of ffmpeg from `PATH` environment variables, which is an edge case but can cause issues. + + +___ + +
    + + +
    +3dsmax: opening last workfile #4644 + +Supports opening last saved workfile in 3dsmax host. + + +___ + +
    + + +
    +Fixed a bug where a QThread in the splash screen could be destroyed before finishing execution #4647 + +This should fix the occasional behavior of the QThread being destroyed before even its worker returns from the `run()` function.After quiting, it should wait for the QThread object to properly close itself. + + +___ + +
    + + +
    +General: Use right plugin class for Collect Comment #4653 + +Collect Comment plugin is instance plugin so should inherit from `InstancePlugin` instead of `ContextPlugin`. + + +___ + +
    + + +
    +Global: add tags field to thumbnail representation #4660 + +Thumbnail representation might be missing tags field. + + +___ + +
    + + +
    +Integrator: Enforce unique destination transfers, disallow overwrites in queued transfers #4662 + +Fix #4656 by enforcing unique destination transfers in the Integrator. It's now disallowed to a destination in the file transaction queue with a new source path during the publish. + + +___ + +
    + + +
    +Hiero: Creator with correct workfile numeric padding input #4666 + +Creator was showing 99 in workfile input for long time, even if users set default value to 1001 in studio settings. This has been fixed now. + + +___ + +
    + + +
    +Nuke: Nukenodes family instance without frame range #4669 + +No need to add frame range data into `nukenodes` (backdrop) family publishes - since those are timeless. + + +___ + +
    + + +
    +TVPaint: Optional Validation plugins can be de/activated by user #4674 + +Added `OptionalPyblishPluginMixin` to TVpaint plugins that can be optional. + + +___ + +
    + + +
    +Kitsu: Slightly less strict with instance data #4678 + +- Allow to take task name from context if asset doesn't have any. Fixes an issue with Photoshop's review instance not having `task` in data. +- Allow to match "review" against both `instance.data["family"]` and `instance.data["families"]` because some instances don't have the primary family in families, e.g. in Photoshop and TVPaint. +- Do not error on Integrate Kitsu Review whenever for whatever reason Integrate Kitsu Note did not created a comment but just log the message that it was unable to connect a review. + + +___ + +
    + + +
    +Publisher: Fix reset shortcut sequence #4694 + +Fix bug created in https://github.com/ynput/OpenPype/pull/4676 where key sequence is checked using unsupported method. The check was changed to convert event into `QKeySequence` object which can be compared to prepared sequence. + + +___ + +
    + + +
    +Refactor _capture #4702 + +Paragraphs contain detailed information on the changes made to the product or service, providing an in-depth description of the updates and enhancements. They can be used to explain the reasoning behind the changes, or to highlight the importance of the new features. Paragraphs can often include links to further information or support documentation. + + +___ + +
    + + +
    +Hiero: correct container colors if UpToDate #4708 + +Colors on loaded containers are now correctly identifying real state of version. `Red` for out of date and `green` for up to date. + + +___ + +
    + +### **🔀 Refactored code** + + +
    +Look Assigner: Move Look Assigner tool since it's Maya only #4604 + +Fix #4357: Move Look Assigner tool to maya since it's Maya only + + +___ + +
    + + +
    +Maya: Remove unused functions from Extract Look #4671 + +Remove unused functions from Maya Extract Look plug-in + + +___ + +
    + + +
    +Extract Review code refactor #3930 + +Trying to reduce complexity of Extract Review plug-in +- Re-use profile filtering from lib +- Remove "combination families" additional filtering which supposedly was from OP v2 +- Simplify 'formatting' for filling gaps +- Use `legacy_io.Session` over `os.environ` + + +___ + +
    + + +
    +Maya: Replace last usages of Qt module #4610 + +Replace last usage of `Qt` module with `qtpy`. This change is needed for `PySide6` support. All changes happened in Maya loader plugins. + + +___ + +
    + + +
    +Update tests and documentation for `ColormanagedPyblishPluginMixin` #4612 + +Refactor `ExtractorColormanaged` to `ColormanagedPyblishPluginMixin` in tests and documentation. + + +___ + +
    + + +
    +Improve logging of used app + tool envs on application launch (minor tweak) #4686 + +Use `app.full_name` for change done in #4682 + + +___ + +
    + +### **📃 Documentation** + + +
    +Docs/add architecture document #4344 + +Add `ARCHITECTURE.md` document. + +his document attemps to give a quick overview of the project to help onboarding, it's not an extensive documentation but more of a elevator pitch one-line descriptions of files/directories and what the attempt to do. + + +___ + +
    + + +
    +Documentation: Tweak grammar and fix some typos #4613 + +This resolves some grammar and typos in the documentation.Also fixes the extension of some images in after effects docs which used uppercase extension even though files were lowercase extension. + + +___ + +
    + + +
    +Docs: Fix some minor grammar/typos #4680 + +Typo/grammar fixes in documentation. + + +___ + +
    + +### **Merged pull requests** + + +
    +Maya: Implement image file node loader #4313 + +Implements a loader for loading texture image into a `file` node in Maya. + +Similar to Maya's hypershade creation of textures on load you have the option to choose for three modes of creating: +- Texture +- Projection +- StencilThese should match what Maya generates if you create those in Maya. +- [x] Load and manage file nodes +- [x] Apply color spaces after #4195 +- [x] Support for _either_ UDIM or image sequence - currently it seems to always load sequences as UDIM automatically. +- [ ] Add support for animation sequences of UDIM textures using the `..exr` path format? + + +___ + +
    + + +
    +Maya Look Assigner: Don't rely on containers for get all assets #4600 + +This resolves #4044 by not actually relying on containers in the scene but instead just rely on finding nodes with `cbId` attributes. As such, imported nodes would also be found and a shader can be assigned (similar to when using get from selection).**Please take into consideration the potential downsides below**Potential downsides would be: +- IF an already loaded look has any dagNodes, say a 3D Projection node - then that will also show up as a loaded asset where previously nodes from loaded looks were ignored. +- If any dag nodes were created locally - they would have gotten `cbId` attributes on scene save and thus the current asset would almost always show? + + +___ + +
    + + +
    +Maya: Unify menu labels for "Set Frame Range" and "Set Resolution" #4605 + +Fix #4109: Unify menu labels for "Set Frame Range" and "Set Resolution"This also tweaks it in Houdini from Reset Frame Range to Set Frame Range. + + +___ + +
    + + +
    +Resolve missing OPENPYPE_MONGO in deadline global job preload #4484 + +In the GlobalJobPreLoad plugin, we propose to replace the SpawnProcess by a sub-process and to pass the environment variables in the parameters, since the SpawnProcess under Centos Linux does not pass the environment variables. + +In the GlobalJobPreLoad plugin, the Deadline SpawnProcess is used to start the OpenPype process. The problem is that the SpawnProcess does not pass environment variables, including OPENPYPE_MONGO, to the process when it is under Centos7 linux, and the process gets stuck. We propose to replace it by a subprocess and to pass the variable in the parameters. + + +___ + +
    + + +
    +Tests: Added setup_only to tests #4591 + +Allows to download test zip, unzip and restore DB in preparation for new test. + + +___ + +
    + + +
    +Maya: Arnold don't reset maya timeline frame range on render creation (or setting render settings) #4603 + +Fix #4429: Do not reset fps or playback timeline on applying or creating render settings + + +___ + +
    + + +
    +Bump @sideway/formula from 3.0.0 to 3.0.1 in /website #4609 + +Bumps [@sideway/formula](https://github.com/sideway/formula) from 3.0.0 to 3.0.1. +
    +Commits + +
    +
    +Maintainer changes +

    This version was pushed to npm by marsup, a new releaser for @​sideway/formula since your current version.

    +
    +
    + + +[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@sideway/formula&package-manager=npm_and_yarn&previous-version=3.0.0&new-version=3.0.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) + +Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. + +[//]: # (dependabot-automerge-start) +[//]: # (dependabot-automerge-end) + +--- + +
    +Dependabot commands and options +
    + +You can trigger Dependabot actions by commenting on this PR: +- `@dependabot rebase` will rebase this PR +- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it +- `@dependabot merge` will merge this PR after your CI passes on it +- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it +- `@dependabot cancel merge` will cancel a previously requested merge and block automerging +- `@dependabot reopen` will reopen this PR if it is closed +- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually +- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) +- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) +- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) +- `@dependabot use these labels` will set the current labels as the default for future PRs for this repo and language +- `@dependabot use these reviewers` will set the current reviewers as the default for future PRs for this repo and language +- `@dependabot use these assignees` will set the current assignees as the default for future PRs for this repo and language +- `@dependabot use this milestone` will set the current milestone as the default for future PRs for this repo and language + +You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/ynput/OpenPype/network/alerts). + +
    +___ + +
    + + +
    +Update artist_hosts_maya_arnold.md #4626 + +Correct Arnold docs. +___ + +
    + + +
    +Maya: Add "Include Parent Hierarchy" option in animation creator plugin #4645 + +Add an option in Project Settings > Maya > Creator Plugins > Create Animation to include (or not) parent hierarchy. This is to avoid artists to check manually the option for all create animation. + + +___ + +
    + + +
    +General: Filter available applications #4667 + +Added option to filter applications that don't have valid executable available in settings in launcher and ftrack actions. This option can be disabled in new settings category `Applications`. The filtering is by default disabled. + + +___ + +
    + + +
    +3dsmax: make sure that startup script executes #4695 + +Fixing reliability of OpenPype startup in 3dsmax. + + +___ + +
    + + +
    +Project Manager: Change minimum frame start/end to '0' #4719 + +Project manager can have frame start/end set to `0`. + + +___ + +
    + + + +## [3.15.2](https://github.com/ynput/OpenPype/tree/3.15.2) [Full Changelog](https://github.com/ynput/OpenPype/compare/3.15.1...3.15.2) diff --git a/openpype/client/entities.py b/openpype/client/entities.py index c415be8816f..7054658c645 100644 --- a/openpype/client/entities.py +++ b/openpype/client/entities.py @@ -3,7 +3,7 @@ Goal is that most of functions here are called on (or with) an object that has project name as a context (e.g. on 'ProjectEntity'?). -+ We will need more specific functions doing wery specific queires really fast. ++ We will need more specific functions doing very specific queries really fast. """ import re @@ -193,7 +193,7 @@ def _get_assets( be found. asset_names (Iterable[str]): Name assets that should be found. parent_ids (Iterable[Union[str, ObjectId]]): Parent asset ids. - standard (bool): Query standart assets (type 'asset'). + standard (bool): Query standard assets (type 'asset'). archived (bool): Query archived assets (type 'archived_asset'). fields (Iterable[str]): Fields that should be returned. All fields are returned if 'None' is passed. @@ -1185,7 +1185,7 @@ def get_representations( standard=True, fields=None ): - """Representaion entities data from one project filtered by filters. + """Representation entities data from one project filtered by filters. Filters are additive (all conditions must pass to return subset). @@ -1231,7 +1231,7 @@ def get_archived_representations( names_by_version_ids=None, fields=None ): - """Archived representaion entities data from project with applied filters. + """Archived representation entities data from project with applied filters. Filters are additive (all conditions must pass to return subset). diff --git a/openpype/client/notes.md b/openpype/client/notes.md index a261b86eca9..59743892eb6 100644 --- a/openpype/client/notes.md +++ b/openpype/client/notes.md @@ -2,7 +2,7 @@ ## Reason Preparation for OpenPype v4 server. Goal is to remove direct mongo calls in code to prepare a little bit for different source of data for code before. To start think about database calls less as mongo calls but more universally. To do so was implemented simple wrapper around database calls to not use pymongo specific code. -Current goal is not to make universal database model which can be easily replaced with any different source of data but to make it close as possible. Current implementation of OpenPype is too tighly connected to pymongo and it's abilities so we're trying to get closer with long term changes that can be used even in current state. +Current goal is not to make universal database model which can be easily replaced with any different source of data but to make it close as possible. Current implementation of OpenPype is too tightly connected to pymongo and it's abilities so we're trying to get closer with long term changes that can be used even in current state. ## Queries Query functions don't use full potential of mongo queries like very specific queries based on subdictionaries or unknown structures. We try to avoid these calls as much as possible because they'll probably won't be available in future. If it's really necessary a new function can be added but only if it's reasonable for overall logic. All query functions were moved to `~/client/entities.py`. Each function has arguments with available filters and possible reduce of returned keys for each entity. @@ -14,7 +14,7 @@ Changes are a little bit complicated. Mongo has many options how update can happ Create operations expect already prepared document data, for that are prepared functions creating skeletal structures of documents (do not fill all required data), except `_id` all data should be right. Existence of entity is not validated so if the same creation operation is send n times it will create the entity n times which can cause issues. ### Update -Update operation require entity id and keys that should be changed, update dictionary must have {"key": value}. If value should be set in nested dictionary the key must have also all subkeys joined with dot `.` (e.g. `{"data": {"fps": 25}}` -> `{"data.fps": 25}`). To simplify update dictionaries were prepared functions which does that for you, their name has template `prepare__update_data` - they work on comparison of previous document and new document. If there is missing function for requested entity type it is because we didn't need it yet and require implementaion. +Update operation require entity id and keys that should be changed, update dictionary must have {"key": value}. If value should be set in nested dictionary the key must have also all subkeys joined with dot `.` (e.g. `{"data": {"fps": 25}}` -> `{"data.fps": 25}`). To simplify update dictionaries were prepared functions which does that for you, their name has template `prepare__update_data` - they work on comparison of previous document and new document. If there is missing function for requested entity type it is because we didn't need it yet and require implementation. ### Delete Delete operation need entity id. Entity will be deleted from mongo. diff --git a/openpype/client/operations.py b/openpype/client/operations.py index fd639c34a7c..ef48f2a1c49 100644 --- a/openpype/client/operations.py +++ b/openpype/client/operations.py @@ -368,7 +368,7 @@ def prepare_workfile_info_update_data(old_doc, new_doc, replace=True): class AbstractOperation(object): """Base operation class. - Opration represent a call into database. The call can create, change or + Operation represent a call into database. The call can create, change or remove data. Args: @@ -409,7 +409,7 @@ def to_mongo_operation(self): pass def to_data(self): - """Convert opration to data that can be converted to json or others. + """Convert operation to data that can be converted to json or others. Warning: Current state returns ObjectId objects which cannot be parsed by @@ -428,7 +428,7 @@ def to_data(self): class CreateOperation(AbstractOperation): - """Opeartion to create an entity. + """Operation to create an entity. Args: project_name (str): On which project operation will happen. @@ -485,7 +485,7 @@ def to_data(self): class UpdateOperation(AbstractOperation): - """Opeartion to update an entity. + """Operation to update an entity. Args: project_name (str): On which project operation will happen. @@ -552,7 +552,7 @@ def to_data(self): class DeleteOperation(AbstractOperation): - """Opeartion to delete an entity. + """Operation to delete an entity. Args: project_name (str): On which project operation will happen. diff --git a/openpype/hooks/pre_create_extra_workdir_folders.py b/openpype/hooks/pre_create_extra_workdir_folders.py index c5af620c877..8856281120f 100644 --- a/openpype/hooks/pre_create_extra_workdir_folders.py +++ b/openpype/hooks/pre_create_extra_workdir_folders.py @@ -3,10 +3,13 @@ from openpype.pipeline.workfile import create_workdir_extra_folders -class AddLastWorkfileToLaunchArgs(PreLaunchHook): - """Add last workfile path to launch arguments. +class CreateWorkdirExtraFolders(PreLaunchHook): + """Create extra folders for the work directory. + + Based on setting `project_settings/global/tools/Workfiles/extra_folders` + profile filtering will decide whether extra folders need to be created in + the work directory. - This is not possible to do for all applications the same way. """ # Execute after workfile template copy diff --git a/openpype/hooks/pre_foundry_apps.py b/openpype/hooks/pre_foundry_apps.py index 2092d5025dc..21ec8e78814 100644 --- a/openpype/hooks/pre_foundry_apps.py +++ b/openpype/hooks/pre_foundry_apps.py @@ -7,7 +7,7 @@ class LaunchFoundryAppsWindows(PreLaunchHook): Nuke is executed "like" python process so it is required to pass `CREATE_NEW_CONSOLE` flag on windows to trigger creation of new console. - At the same time the newly created console won't create it's own stdout + At the same time the newly created console won't create its own stdout and stderr handlers so they should not be redirected to DEVNULL. """ @@ -18,7 +18,7 @@ class LaunchFoundryAppsWindows(PreLaunchHook): def execute(self): # Change `creationflags` to CREATE_NEW_CONSOLE - # - on Windows will nuke create new window using it's console + # - on Windows nuke will create new window using its console # Set `stdout` and `stderr` to None so new created console does not # have redirected output to DEVNULL in build self.launch_context.kwargs.update({ diff --git a/openpype/host/dirmap.py b/openpype/host/dirmap.py index 1d084cccad5..42bf80ececc 100644 --- a/openpype/host/dirmap.py +++ b/openpype/host/dirmap.py @@ -2,7 +2,7 @@ Idea for current dirmap implementation was used from Maya where is possible to enter source and destination roots and maya will try each found source -in referenced file replace with each destionation paths. First path which +in referenced file replace with each destination paths. First path which exists is used. """ @@ -183,7 +183,7 @@ def _get_local_sync_dirmap(self): project_name, remote_site ) # dirmap has sense only with regular disk provider, in the workfile - # wont be root on cloud or sftp provider + # won't be root on cloud or sftp provider if remote_provider != "local_drive": remote_site = "studio" for root_name, active_site_dir in active_overrides.items(): diff --git a/openpype/host/host.py b/openpype/host/host.py index d2335c00621..630fb873a81 100644 --- a/openpype/host/host.py +++ b/openpype/host/host.py @@ -18,7 +18,7 @@ class HostBase(object): Compared to 'avalon' concept: What was before considered as functions in host implementation folder. The host implementation should primarily care about adding ability of creation - (mark subsets to be published) and optionaly about referencing published + (mark subsets to be published) and optionally about referencing published representations as containers. Host may need extend some functionality like working with workfiles @@ -129,9 +129,9 @@ def get_current_context(self): """Get current context information. This method should be used to get current context of host. Usage of - this method can be crutial for host implementations in DCCs where + this method can be crucial for host implementations in DCCs where can be opened multiple workfiles at one moment and change of context - can't be catched properly. + can't be caught properly. Default implementation returns values from 'legacy_io.Session'. diff --git a/openpype/host/interfaces.py b/openpype/host/interfaces.py index 999aefd2547..7c6057acf06 100644 --- a/openpype/host/interfaces.py +++ b/openpype/host/interfaces.py @@ -81,7 +81,7 @@ def validate_load_methods(host): @abstractmethod def get_containers(self): - """Retreive referenced containers from scene. + """Retrieve referenced containers from scene. This can be implemented in hosts where referencing can be used. @@ -191,7 +191,7 @@ def open_workfile(self, filepath): @abstractmethod def get_current_workfile(self): - """Retreive path to current opened file. + """Retrieve path to current opened file. Returns: str: Path to file which is currently opened. @@ -220,8 +220,8 @@ def work_root(self, session): Default implementation keeps workdir untouched. Warnings: - We must handle this modification with more sofisticated way because - this can't be called out of DCC so opening of last workfile + We must handle this modification with more sophisticated way + because this can't be called out of DCC so opening of last workfile (calculated before DCC is launched) is complicated. Also breaking defined work template is not a good idea. Only place where it's really used and can make sense is Maya. There @@ -302,7 +302,7 @@ def get_missing_publish_methods(host): required methods. Returns: - list[str]: Missing method implementations for new publsher + list[str]: Missing method implementations for new publisher workflow. """ diff --git a/openpype/hosts/aftereffects/api/extension/jsx/hostscript.jsx b/openpype/hosts/aftereffects/api/extension/jsx/hostscript.jsx index 9b211207de9..5c1d1634398 100644 --- a/openpype/hosts/aftereffects/api/extension/jsx/hostscript.jsx +++ b/openpype/hosts/aftereffects/api/extension/jsx/hostscript.jsx @@ -504,7 +504,7 @@ function addItemAsLayerToComp(comp_id, item_id, found_comp){ * Args: * comp_id (int): id of target composition * item_id (int): FootageItem.id - * found_comp (CompItem, optional): to limit quering if + * found_comp (CompItem, optional): to limit querying if * comp already found previously */ var comp = found_comp || app.project.itemByID(comp_id); diff --git a/openpype/hosts/aftereffects/api/ws_stub.py b/openpype/hosts/aftereffects/api/ws_stub.py index e5d6d9ed893..f094c7fa2a6 100644 --- a/openpype/hosts/aftereffects/api/ws_stub.py +++ b/openpype/hosts/aftereffects/api/ws_stub.py @@ -80,7 +80,7 @@ def get_metadata(self): Get complete stored JSON with metadata from AE.Metadata.Label field. - It contains containers loaded by any Loader OR instances creted + It contains containers loaded by any Loader OR instances created by Creator. Returns: diff --git a/openpype/hosts/blender/api/ops.py b/openpype/hosts/blender/api/ops.py index b1fa13acb9d..91cbfe524f9 100644 --- a/openpype/hosts/blender/api/ops.py +++ b/openpype/hosts/blender/api/ops.py @@ -24,7 +24,7 @@ PREVIEW_COLLECTIONS: Dict = dict() # This seems like a good value to keep the Qt app responsive and doesn't slow -# down Blender. At least on macOS I the interace of Blender gets very laggy if +# down Blender. At least on macOS I the interface of Blender gets very laggy if # you make it smaller. TIMER_INTERVAL: float = 0.01 if platform.system() == "Windows" else 0.1 @@ -84,11 +84,11 @@ def __init__(self, callback, *args, **kwargs): self.kwargs = kwargs def execute(self): - """Execute callback and store it's result. + """Execute callback and store its result. Method must be called from main thread. Item is marked as `done` when callback execution finished. Store output of callback of exception - information when callback raise one. + information when callback raises one. """ print("Executing process in main thread") if self.done: diff --git a/openpype/hosts/blender/plugins/publish/extract_playblast.py b/openpype/hosts/blender/plugins/publish/extract_playblast.py index 8dc2f66c22a..196e75b8ccb 100644 --- a/openpype/hosts/blender/plugins/publish/extract_playblast.py +++ b/openpype/hosts/blender/plugins/publish/extract_playblast.py @@ -50,7 +50,7 @@ def process(self, instance): # get isolate objects list isolate = instance.data("isolate", None) - # get ouput path + # get output path stagingdir = self.staging_dir(instance) filename = instance.name path = os.path.join(stagingdir, filename) @@ -116,7 +116,6 @@ def process(self, instance): "frameStart": start, "frameEnd": end, "fps": fps, - "preview": True, "tags": tags, "camera_name": camera } diff --git a/openpype/hosts/celaction/hooks/pre_celaction_setup.py b/openpype/hosts/celaction/hooks/pre_celaction_setup.py index 62cebf99ed2..96e784875c2 100644 --- a/openpype/hosts/celaction/hooks/pre_celaction_setup.py +++ b/openpype/hosts/celaction/hooks/pre_celaction_setup.py @@ -38,8 +38,9 @@ def execute(self): ) path_to_cli = os.path.join(CELACTION_SCRIPTS_DIR, "publish_cli.py") - subproces_args = get_openpype_execute_args("run", path_to_cli) - openpype_executable = subproces_args.pop(0) + subprocess_args = get_openpype_execute_args("run", path_to_cli) + openpype_executable = subprocess_args.pop(0) + workfile_settings = self.get_workfile_settings() winreg.SetValueEx( hKey, @@ -49,20 +50,34 @@ def execute(self): openpype_executable ) - parameters = subproces_args + [ - "--currentFile", "*SCENE*", - "--chunk", "*CHUNK*", - "--frameStart", "*START*", - "--frameEnd", "*END*", - "--resolutionWidth", "*X*", - "--resolutionHeight", "*Y*" + # add required arguments for workfile path + parameters = subprocess_args + [ + "--currentFile", "*SCENE*" ] + # Add custom parameters from workfile settings + if "render_chunk" in workfile_settings["submission_overrides"]: + parameters += [ + "--chunk", "*CHUNK*" + ] + if "resolution" in workfile_settings["submission_overrides"]: + parameters += [ + "--resolutionWidth", "*X*", + "--resolutionHeight", "*Y*" + ] + if "frame_range" in workfile_settings["submission_overrides"]: + parameters += [ + "--frameStart", "*START*", + "--frameEnd", "*END*" + ] + winreg.SetValueEx( hKey, "SubmitParametersTitle", 0, winreg.REG_SZ, subprocess.list2cmdline(parameters) ) + self.log.debug(f"__ parameters: \"{parameters}\"") + # setting resolution parameters path_submit = "\\".join([ path_user_settings, "Dialogs", "SubmitOutput" @@ -135,3 +150,6 @@ def workfile_path(self): self.log.info(f"Workfile to open: \"{workfile_path}\"") return workfile_path + + def get_workfile_settings(self): + return self.data["project_settings"]["celaction"]["workfile"] diff --git a/openpype/hosts/celaction/plugins/publish/collect_celaction_cli_kwargs.py b/openpype/hosts/celaction/plugins/publish/collect_celaction_cli_kwargs.py index 43b81b83e7e..54dea15dffc 100644 --- a/openpype/hosts/celaction/plugins/publish/collect_celaction_cli_kwargs.py +++ b/openpype/hosts/celaction/plugins/publish/collect_celaction_cli_kwargs.py @@ -39,7 +39,7 @@ def process(self, context): passing_kwargs[key] = value if missing_kwargs: - raise RuntimeError("Missing arguments {}".format( + self.log.debug("Missing arguments {}".format( ", ".join( [f'"{key}"' for key in missing_kwargs] ) diff --git a/openpype/hosts/flame/api/lib.py b/openpype/hosts/flame/api/lib.py index 6aca5c5ce61..ab713aed841 100644 --- a/openpype/hosts/flame/api/lib.py +++ b/openpype/hosts/flame/api/lib.py @@ -773,7 +773,7 @@ def __init__(self, path, logger=None): if logger: self.log = logger - # test if `dl_get_media_info` paht exists + # test if `dl_get_media_info` path exists self._validate_media_script_path() # derivate other feed variables @@ -993,7 +993,7 @@ def file_pattern(self, fpattern): def _validate_media_script_path(self): if not os.path.isfile(self.MEDIA_SCRIPT_PATH): - raise IOError("Media Scirpt does not exist: `{}`".format( + raise IOError("Media Script does not exist: `{}`".format( self.MEDIA_SCRIPT_PATH)) def _generate_media_info_file(self, fpath, feed_ext, feed_dir): diff --git a/openpype/hosts/flame/api/pipeline.py b/openpype/hosts/flame/api/pipeline.py index 3a233899619..d6fbf750ba0 100644 --- a/openpype/hosts/flame/api/pipeline.py +++ b/openpype/hosts/flame/api/pipeline.py @@ -38,7 +38,7 @@ def install(): pyblish.register_plugin_path(PUBLISH_PATH) register_loader_plugin_path(LOAD_PATH) register_creator_plugin_path(CREATE_PATH) - log.info("OpenPype Flame plug-ins registred ...") + log.info("OpenPype Flame plug-ins registered ...") # register callback for switching publishable pyblish.register_callback("instanceToggled", on_pyblish_instance_toggled) diff --git a/openpype/hosts/flame/api/plugin.py b/openpype/hosts/flame/api/plugin.py index 983d7486b39..df8c1ac8872 100644 --- a/openpype/hosts/flame/api/plugin.py +++ b/openpype/hosts/flame/api/plugin.py @@ -157,7 +157,7 @@ def create_row(self, layout, type_name, text, **kwargs): # convert label text to normal capitalized text with spaces label_text = self.camel_case_split(text) - # assign the new text to lable widget + # assign the new text to label widget label = QtWidgets.QLabel(label_text) label.setObjectName("LineLabel") @@ -345,8 +345,8 @@ class PublishableClip: "track": "sequence", } - # parents search patern - parents_search_patern = r"\{([a-z]*?)\}" + # parents search pattern + parents_search_pattern = r"\{([a-z]*?)\}" # default templates for non-ui use rename_default = False @@ -445,7 +445,7 @@ def convert(self): return self.current_segment def _populate_segment_default_data(self): - """ Populate default formating data from segment. """ + """ Populate default formatting data from segment. """ self.current_segment_default_data = { "_folder_": "shots", @@ -538,7 +538,7 @@ def _convert_to_marker_data(self): if not self.index_from_segment: self.count_steps *= self.rename_index - hierarchy_formating_data = {} + hierarchy_formatting_data = {} hierarchy_data = deepcopy(self.hierarchy_data) _data = self.current_segment_default_data.copy() if self.ui_inputs: @@ -552,7 +552,7 @@ def _convert_to_marker_data(self): # mark review layer if self.review_track and ( self.review_track not in self.review_track_default): - # if review layer is defined and not the same as defalut + # if review layer is defined and not the same as default self.review_layer = self.review_track # shot num calculate @@ -578,13 +578,13 @@ def _convert_to_marker_data(self): # fill up pythonic expresisons in hierarchy data for k, _v in hierarchy_data.items(): - hierarchy_formating_data[k] = _v["value"].format(**_data) + hierarchy_formatting_data[k] = _v["value"].format(**_data) else: # if no gui mode then just pass default data - hierarchy_formating_data = hierarchy_data + hierarchy_formatting_data = hierarchy_data tag_hierarchy_data = self._solve_tag_hierarchy_data( - hierarchy_formating_data + hierarchy_formatting_data ) tag_hierarchy_data.update({"heroTrack": True}) @@ -615,27 +615,27 @@ def _convert_to_marker_data(self): # in case track name and subset name is the same then add if self.subset_name == self.track_name: _hero_data["subset"] = self.subset - # assing data to return hierarchy data to tag + # assign data to return hierarchy data to tag tag_hierarchy_data = _hero_data break # add data to return data dict self.marker_data.update(tag_hierarchy_data) - def _solve_tag_hierarchy_data(self, hierarchy_formating_data): + def _solve_tag_hierarchy_data(self, hierarchy_formatting_data): """ Solve marker data from hierarchy data and templates. """ # fill up clip name and hierarchy keys - hierarchy_filled = self.hierarchy.format(**hierarchy_formating_data) - clip_name_filled = self.clip_name.format(**hierarchy_formating_data) + hierarchy_filled = self.hierarchy.format(**hierarchy_formatting_data) + clip_name_filled = self.clip_name.format(**hierarchy_formatting_data) # remove shot from hierarchy data: is not needed anymore - hierarchy_formating_data.pop("shot") + hierarchy_formatting_data.pop("shot") return { "newClipName": clip_name_filled, "hierarchy": hierarchy_filled, "parents": self.parents, - "hierarchyData": hierarchy_formating_data, + "hierarchyData": hierarchy_formatting_data, "subset": self.subset, "family": self.subset_family, "families": [self.family] @@ -650,17 +650,17 @@ def _convert_to_entity(self, type, template): type ) - # first collect formating data to use for formating template - formating_data = {} + # first collect formatting data to use for formatting template + formatting_data = {} for _k, _v in self.hierarchy_data.items(): value = _v["value"].format( **self.current_segment_default_data) - formating_data[_k] = value + formatting_data[_k] = value return { "entity_type": entity_type, "entity_name": template.format( - **formating_data + **formatting_data ) } @@ -668,9 +668,9 @@ def _create_parents(self): """ Create parents and return it in list. """ self.parents = [] - patern = re.compile(self.parents_search_patern) + pattern = re.compile(self.parents_search_pattern) - par_split = [(patern.findall(t).pop(), t) + par_split = [(pattern.findall(t).pop(), t) for t in self.hierarchy.split("/")] for type, template in par_split: @@ -902,22 +902,22 @@ def _rename_track_name(self, xml_track_data): ): return - formating_data = self._update_formating_data( + formatting_data = self._update_formatting_data( layerName=layer_name, layerUID=layer_uid ) name_obj.text = StringTemplate( self.layer_rename_template - ).format(formating_data) + ).format(formatting_data) - def _update_formating_data(self, **kwargs): - """ Updating formating data for layer rename + def _update_formatting_data(self, **kwargs): + """ Updating formatting data for layer rename Attributes: - key=value (optional): will be included to formating data + key=value (optional): will be included to formatting data as {key: value} Returns: - dict: anatomy context data for formating + dict: anatomy context data for formatting """ self.log.debug(">> self.clip_data: {}".format(self.clip_data)) clip_name_obj = self.clip_data.find("name") diff --git a/openpype/hosts/flame/api/scripts/wiretap_com.py b/openpype/hosts/flame/api/scripts/wiretap_com.py index 4825ff43865..a74172c4056 100644 --- a/openpype/hosts/flame/api/scripts/wiretap_com.py +++ b/openpype/hosts/flame/api/scripts/wiretap_com.py @@ -203,7 +203,7 @@ def _get_all_volumes(self): list: all available volumes in server Rises: - AttributeError: unable to get any volumes childs from server + AttributeError: unable to get any volumes children from server """ root = WireTapNodeHandle(self._server, "/volumes") children_num = WireTapInt(0) diff --git a/openpype/hosts/flame/api/utils.py b/openpype/hosts/flame/api/utils.py index fb8bdee42df..80a5c47e892 100644 --- a/openpype/hosts/flame/api/utils.py +++ b/openpype/hosts/flame/api/utils.py @@ -108,7 +108,7 @@ def _sync_utility_scripts(env=None): shutil.copy2(src, dst) except (PermissionError, FileExistsError) as msg: log.warning( - "Not able to coppy to: `{}`, Problem with: `{}`".format( + "Not able to copy to: `{}`, Problem with: `{}`".format( dst, msg ) diff --git a/openpype/hosts/flame/hooks/pre_flame_setup.py b/openpype/hosts/flame/hooks/pre_flame_setup.py index 713daf10317..8034885c478 100644 --- a/openpype/hosts/flame/hooks/pre_flame_setup.py +++ b/openpype/hosts/flame/hooks/pre_flame_setup.py @@ -153,7 +153,7 @@ def _get_flame_fps(self, fps_num): def _add_pythonpath(self): pythonpath = self.launch_context.env.get("PYTHONPATH") - # separate it explicity by `;` that is what we use in settings + # separate it explicitly by `;` that is what we use in settings new_pythonpath = self.flame_pythonpath.split(os.pathsep) new_pythonpath += pythonpath.split(os.pathsep) diff --git a/openpype/hosts/flame/plugins/create/create_shot_clip.py b/openpype/hosts/flame/plugins/create/create_shot_clip.py index 4fb041a4b26..b01354c3137 100644 --- a/openpype/hosts/flame/plugins/create/create_shot_clip.py +++ b/openpype/hosts/flame/plugins/create/create_shot_clip.py @@ -209,7 +209,7 @@ def get_gui_inputs(self): "type": "QComboBox", "label": "Subset Name", "target": "ui", - "toolTip": "chose subset name patern, if [ track name ] is selected, name of track layer will be used", # noqa + "toolTip": "chose subset name pattern, if [ track name ] is selected, name of track layer will be used", # noqa "order": 0}, "subsetFamily": { "value": ["plate", "take"], diff --git a/openpype/hosts/flame/plugins/load/load_clip.py b/openpype/hosts/flame/plugins/load/load_clip.py index 25b31c94a32..dfb2d2b6f00 100644 --- a/openpype/hosts/flame/plugins/load/load_clip.py +++ b/openpype/hosts/flame/plugins/load/load_clip.py @@ -61,9 +61,9 @@ def load(self, context, name, namespace, options): self.layer_rename_template = self.layer_rename_template.replace( "output", "representation") - formating_data = deepcopy(context["representation"]["context"]) + formatting_data = deepcopy(context["representation"]["context"]) clip_name = StringTemplate(self.clip_name_template).format( - formating_data) + formatting_data) # convert colorspace with ocio to flame mapping # in imageio flame section @@ -88,7 +88,7 @@ def load(self, context, name, namespace, options): "version": "v{:0>3}".format(version_name), "layer_rename_template": self.layer_rename_template, "layer_rename_patterns": self.layer_rename_patterns, - "context_data": formating_data + "context_data": formatting_data } self.log.debug(pformat( loading_context diff --git a/openpype/hosts/flame/plugins/load/load_clip_batch.py b/openpype/hosts/flame/plugins/load/load_clip_batch.py index 86bc0f8f1e8..5c5a77f0d09 100644 --- a/openpype/hosts/flame/plugins/load/load_clip_batch.py +++ b/openpype/hosts/flame/plugins/load/load_clip_batch.py @@ -58,11 +58,11 @@ def load(self, context, name, namespace, options): self.layer_rename_template = self.layer_rename_template.replace( "output", "representation") - formating_data = deepcopy(context["representation"]["context"]) - formating_data["batch"] = self.batch.name.get_value() + formatting_data = deepcopy(context["representation"]["context"]) + formatting_data["batch"] = self.batch.name.get_value() clip_name = StringTemplate(self.clip_name_template).format( - formating_data) + formatting_data) # convert colorspace with ocio to flame mapping # in imageio flame section @@ -88,7 +88,7 @@ def load(self, context, name, namespace, options): "version": "v{:0>3}".format(version_name), "layer_rename_template": self.layer_rename_template, "layer_rename_patterns": self.layer_rename_patterns, - "context_data": formating_data + "context_data": formatting_data } self.log.debug(pformat( loading_context diff --git a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py index 76d48dded24..23fdf5e7851 100644 --- a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py +++ b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py @@ -203,7 +203,7 @@ def _get_comment_attributes(self, segment): self._get_xml_preset_attrs( attributes, split) - # add xml overides resolution to instance data + # add xml overrides resolution to instance data xml_overrides = attributes["xml_overrides"] if xml_overrides.get("width"): attributes.update({ @@ -284,7 +284,7 @@ def _get_head_tail(self, clip_data, otio_clip, handle_start, handle_end): self.log.debug("__ head: `{}`".format(head)) self.log.debug("__ tail: `{}`".format(tail)) - # HACK: it is here to serve for versions bellow 2021.1 + # HACK: it is here to serve for versions below 2021.1 if not any([head, tail]): retimed_attributes = get_media_range_with_retimes( otio_clip, handle_start, handle_end) diff --git a/openpype/hosts/flame/plugins/publish/extract_subset_resources.py b/openpype/hosts/flame/plugins/publish/extract_subset_resources.py index 5082217db06..a7979ab4d53 100644 --- a/openpype/hosts/flame/plugins/publish/extract_subset_resources.py +++ b/openpype/hosts/flame/plugins/publish/extract_subset_resources.py @@ -227,7 +227,7 @@ def process(self, instance): self.hide_others( exporting_clip, segment_name, s_track_name) - # change name patern + # change name pattern name_patern_xml = ( "__{}.").format( unique_name) @@ -358,7 +358,7 @@ def process(self, instance): representation_data["stagingDir"] = n_stage_dir files = n_files - # add files to represetation but add + # add files to representation but add # imagesequence as list if ( # first check if path in files is not mov extension diff --git a/openpype/hosts/flame/plugins/publish/integrate_batch_group.py b/openpype/hosts/flame/plugins/publish/integrate_batch_group.py index 4d45f67ded2..4f3945bb0fd 100644 --- a/openpype/hosts/flame/plugins/publish/integrate_batch_group.py +++ b/openpype/hosts/flame/plugins/publish/integrate_batch_group.py @@ -50,7 +50,7 @@ def process(self, instance): self._load_clip_to_context(instance, bgroup) def _add_nodes_to_batch_with_links(self, instance, task_data, batch_group): - # get write file node properties > OrederDict because order does mater + # get write file node properties > OrederDict because order does matter write_pref_data = self._get_write_prefs(instance, task_data) batch_nodes = [ diff --git a/openpype/hosts/fusion/api/action.py b/openpype/hosts/fusion/api/action.py index 17509209504..ff5dd14caa3 100644 --- a/openpype/hosts/fusion/api/action.py +++ b/openpype/hosts/fusion/api/action.py @@ -6,12 +6,13 @@ class SelectInvalidAction(pyblish.api.Action): - """Select invalid nodes in Maya when plug-in failed. + """Select invalid nodes in Fusion when plug-in failed. To retrieve the invalid nodes this assumes a static `get_invalid()` method is available on the plugin. """ + label = "Select invalid" on = "failed" # This action is only available on a failed plug-in icon = "search" # Icon from Awesome Icon @@ -31,8 +32,10 @@ def process(self, context, plugin): if isinstance(invalid_nodes, (list, tuple)): invalid.extend(invalid_nodes) else: - self.log.warning("Plug-in returned to be invalid, " - "but has no selectable nodes.") + self.log.warning( + "Plug-in returned to be invalid, " + "but has no selectable nodes." + ) if not invalid: # Assume relevant comp is current comp and clear selection @@ -51,4 +54,6 @@ def process(self, context, plugin): for tool in invalid: flow.Select(tool, True) names.add(tool.Name) - self.log.info("Selecting invalid tools: %s" % ", ".join(sorted(names))) + self.log.info( + "Selecting invalid tools: %s" % ", ".join(sorted(names)) + ) diff --git a/openpype/hosts/fusion/api/menu.py b/openpype/hosts/fusion/api/menu.py index 343f5f803ad..92f38a64c2a 100644 --- a/openpype/hosts/fusion/api/menu.py +++ b/openpype/hosts/fusion/api/menu.py @@ -6,7 +6,6 @@ from openpype.style import load_stylesheet from openpype.lib import register_event_callback from openpype.hosts.fusion.scripts import ( - set_rendermode, duplicate_with_inputs, ) from openpype.hosts.fusion.api.lib import ( @@ -60,7 +59,6 @@ def __init__(self, *args, **kwargs): publish_btn = QtWidgets.QPushButton("Publish...", self) manager_btn = QtWidgets.QPushButton("Manage...", self) libload_btn = QtWidgets.QPushButton("Library...", self) - rendermode_btn = QtWidgets.QPushButton("Set render mode...", self) set_framerange_btn = QtWidgets.QPushButton("Set Frame Range", self) set_resolution_btn = QtWidgets.QPushButton("Set Resolution", self) duplicate_with_inputs_btn = QtWidgets.QPushButton( @@ -91,7 +89,6 @@ def __init__(self, *args, **kwargs): layout.addWidget(set_framerange_btn) layout.addWidget(set_resolution_btn) - layout.addWidget(rendermode_btn) layout.addSpacing(20) @@ -108,7 +105,6 @@ def __init__(self, *args, **kwargs): load_btn.clicked.connect(self.on_load_clicked) manager_btn.clicked.connect(self.on_manager_clicked) libload_btn.clicked.connect(self.on_libload_clicked) - rendermode_btn.clicked.connect(self.on_rendermode_clicked) duplicate_with_inputs_btn.clicked.connect( self.on_duplicate_with_inputs_clicked ) @@ -162,15 +158,6 @@ def on_manager_clicked(self): def on_libload_clicked(self): host_tools.show_library_loader() - def on_rendermode_clicked(self): - if self.render_mode_widget is None: - window = set_rendermode.SetRenderMode() - window.setStyleSheet(load_stylesheet()) - window.show() - self.render_mode_widget = window - else: - self.render_mode_widget.show() - def on_duplicate_with_inputs_clicked(self): duplicate_with_inputs.duplicate_with_input_connections() diff --git a/openpype/hosts/fusion/plugins/create/create_saver.py b/openpype/hosts/fusion/plugins/create/create_saver.py index e581bac20ff..56085b0a06b 100644 --- a/openpype/hosts/fusion/plugins/create/create_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_saver.py @@ -4,29 +4,34 @@ from openpype.hosts.fusion.api import ( get_current_comp, - comp_lock_and_undo_chunk + comp_lock_and_undo_chunk, ) -from openpype.lib import BoolDef +from openpype.lib import ( + BoolDef, + EnumDef, +) from openpype.pipeline import ( legacy_io, Creator, - CreatedInstance + CreatedInstance, +) +from openpype.client import ( + get_asset_by_name, ) -from openpype.client import get_asset_by_name class CreateSaver(Creator): identifier = "io.openpype.creators.fusion.saver" - name = "saver" - label = "Saver" + label = "Render (saver)" + name = "render" family = "render" - default_variants = ["Main"] - + default_variants = ["Main", "Mask"] description = "Fusion Saver to generate image sequence" - def create(self, subset_name, instance_data, pre_create_data): + instance_attributes = ["reviewable"] + def create(self, subset_name, instance_data, pre_create_data): # TODO: Add pre_create attributes to choose file format? file_format = "OpenEXRFormat" @@ -58,7 +63,8 @@ def create(self, subset_name, instance_data, pre_create_data): family=self.family, subset_name=subset_name, data=instance_data, - creator=self) + creator=self, + ) # Insert the transient data instance.transient_data["tool"] = saver @@ -68,11 +74,9 @@ def create(self, subset_name, instance_data, pre_create_data): return instance def collect_instances(self): - comp = get_current_comp() tools = comp.GetToolList(False, "Saver").values() for tool in tools: - data = self.get_managed_tool_data(tool) if not data: data = self._collect_unmanaged_saver(tool) @@ -90,7 +94,6 @@ def get_icon(self): def update_instances(self, update_list): for created_inst, _changes in update_list: - new_data = created_inst.data_to_store() tool = created_inst.transient_data["tool"] self._update_tool_with_data(tool, new_data) @@ -139,7 +142,6 @@ def _update_tool_with_data(self, tool, data): tool.SetAttrs({"TOOLS_Name": subset}) def _collect_unmanaged_saver(self, tool): - # TODO: this should not be done this way - this should actually # get the data as stored on the tool explicitly (however) # that would disallow any 'regular saver' to be collected @@ -153,8 +155,7 @@ def _collect_unmanaged_saver(self, tool): asset = legacy_io.Session["AVALON_ASSET"] task = legacy_io.Session["AVALON_TASK"] - asset_doc = get_asset_by_name(project_name=project, - asset_name=asset) + asset_doc = get_asset_by_name(project_name=project, asset_name=asset) path = tool["Clip"][comp.TIME_UNDEFINED] fname = os.path.basename(path) @@ -178,21 +179,20 @@ def _collect_unmanaged_saver(self, tool): "variant": variant, "active": not passthrough, "family": self.family, - # Unique identifier for instance and this creator "id": "pyblish.avalon.instance", - "creator_identifier": self.identifier + "creator_identifier": self.identifier, } def get_managed_tool_data(self, tool): """Return data of the tool if it matches creator identifier""" - data = tool.GetData('openpype') + data = tool.GetData("openpype") if not isinstance(data, dict): return required = { "id": "pyblish.avalon.instance", - "creator_identifier": self.identifier + "creator_identifier": self.identifier, } for key, value in required.items(): if key not in data or data[key] != value: @@ -205,11 +205,40 @@ def get_managed_tool_data(self, tool): return data + def get_pre_create_attr_defs(self): + """Settings for create page""" + attr_defs = [ + self._get_render_target_enum(), + self._get_reviewable_bool(), + ] + return attr_defs + def get_instance_attr_defs(self): - return [ - BoolDef( - "review", - default=True, - label="Review" - ) + """Settings for publish page""" + attr_defs = [ + self._get_render_target_enum(), + self._get_reviewable_bool(), ] + return attr_defs + + # These functions below should be moved to another file + # so it can be used by other plugins. plugin.py ? + + def _get_render_target_enum(self): + rendering_targets = { + "local": "Local machine rendering", + "frames": "Use existing frames", + } + if "farm_rendering" in self.instance_attributes: + rendering_targets["farm"] = "Farm rendering" + + return EnumDef( + "render_target", items=rendering_targets, label="Render target" + ) + + def _get_reviewable_bool(self): + return BoolDef( + "review", + default=("reviewable" in self.instance_attributes), + label="Review", + ) diff --git a/openpype/hosts/fusion/plugins/load/actions.py b/openpype/hosts/fusion/plugins/load/actions.py index 3b14f022e51..f83ab433ee5 100644 --- a/openpype/hosts/fusion/plugins/load/actions.py +++ b/openpype/hosts/fusion/plugins/load/actions.py @@ -72,8 +72,7 @@ def load(self, context, name, namespace, data): return # Include handles - handles = version_data.get("handles", 0) - start -= handles - end += handles + start -= version_data.get("handleStart", 0) + end += version_data.get("handleEnd", 0) lib.update_frame_range(start, end) diff --git a/openpype/hosts/fusion/plugins/publish/collect_expected_frames.py b/openpype/hosts/fusion/plugins/publish/collect_expected_frames.py new file mode 100644 index 00000000000..0ba777629fa --- /dev/null +++ b/openpype/hosts/fusion/plugins/publish/collect_expected_frames.py @@ -0,0 +1,50 @@ +import pyblish.api +from openpype.pipeline import publish +import os + + +class CollectFusionExpectedFrames( + pyblish.api.InstancePlugin, publish.ColormanagedPyblishPluginMixin +): + """Collect all frames needed to publish expected frames""" + + order = pyblish.api.CollectorOrder + 0.5 + label = "Collect Expected Frames" + hosts = ["fusion"] + families = ["render"] + + def process(self, instance): + context = instance.context + + frame_start = context.data["frameStartHandle"] + frame_end = context.data["frameEndHandle"] + path = instance.data["path"] + output_dir = instance.data["outputDir"] + + basename = os.path.basename(path) + head, ext = os.path.splitext(basename) + files = [ + f"{head}{str(frame).zfill(4)}{ext}" + for frame in range(frame_start, frame_end + 1) + ] + repre = { + "name": ext[1:], + "ext": ext[1:], + "frameStart": f"%0{len(str(frame_end))}d" % frame_start, + "files": files, + "stagingDir": output_dir, + } + + self.set_representation_colorspace( + representation=repre, + context=context, + ) + + # review representation + if instance.data.get("review", False): + repre["tags"] = ["review"] + + # add the repre to the instance + if "representations" not in instance.data: + instance.data["representations"] = [] + instance.data["representations"].append(repre) diff --git a/openpype/hosts/fusion/plugins/publish/collect_render_target.py b/openpype/hosts/fusion/plugins/publish/collect_render_target.py deleted file mode 100644 index 39017f32e02..00000000000 --- a/openpype/hosts/fusion/plugins/publish/collect_render_target.py +++ /dev/null @@ -1,44 +0,0 @@ -import pyblish.api - - -class CollectFusionRenderMode(pyblish.api.InstancePlugin): - """Collect current comp's render Mode - - Options: - local - farm - - Note that this value is set for each comp separately. When you save the - comp this information will be stored in that file. If for some reason the - available tool does not visualize which render mode is set for the - current comp, please run the following line in the console (Py2) - - comp.GetData("openpype.rendermode") - - This will return the name of the current render mode as seen above under - Options. - - """ - - order = pyblish.api.CollectorOrder + 0.4 - label = "Collect Render Mode" - hosts = ["fusion"] - families = ["render"] - - def process(self, instance): - """Collect all image sequence tools""" - options = ["local", "farm"] - - comp = instance.context.data.get("currentComp") - if not comp: - raise RuntimeError("No comp previously collected, unable to " - "retrieve Fusion version.") - - rendermode = comp.GetData("openpype.rendermode") or "local" - assert rendermode in options, "Must be supported render mode" - - self.log.info("Render mode: {0}".format(rendermode)) - - # Append family - family = "render.{0}".format(rendermode) - instance.data["families"].append(family) diff --git a/openpype/hosts/fusion/plugins/publish/collect_renders.py b/openpype/hosts/fusion/plugins/publish/collect_renders.py new file mode 100644 index 00000000000..7f38e68447d --- /dev/null +++ b/openpype/hosts/fusion/plugins/publish/collect_renders.py @@ -0,0 +1,25 @@ +import pyblish.api + + +class CollectFusionRenders(pyblish.api.InstancePlugin): + """Collect current saver node's render Mode + + Options: + local (Render locally) + frames (Use existing frames) + + """ + + order = pyblish.api.CollectorOrder + 0.4 + label = "Collect Renders" + hosts = ["fusion"] + families = ["render"] + + def process(self, instance): + render_target = instance.data["render_target"] + family = instance.data["family"] + + # add targeted family to families + instance.data["families"].append( + "{}.{}".format(family, render_target) + ) diff --git a/openpype/hosts/fusion/plugins/publish/extract_render_local.py b/openpype/hosts/fusion/plugins/publish/extract_render_local.py new file mode 100644 index 00000000000..5a0140c5258 --- /dev/null +++ b/openpype/hosts/fusion/plugins/publish/extract_render_local.py @@ -0,0 +1,109 @@ +import logging +import contextlib +import pyblish.api +from openpype.hosts.fusion.api import comp_lock_and_undo_chunk + + +log = logging.getLogger(__name__) + + +@contextlib.contextmanager +def enabled_savers(comp, savers): + """Enable only the `savers` in Comp during the context. + + Any Saver tool in the passed composition that is not in the savers list + will be set to passthrough during the context. + + Args: + comp (object): Fusion composition object. + savers (list): List of Saver tool objects. + + """ + passthrough_key = "TOOLB_PassThrough" + original_states = {} + enabled_save_names = {saver.Name for saver in savers} + try: + all_savers = comp.GetToolList(False, "Saver").values() + for saver in all_savers: + original_state = saver.GetAttrs()[passthrough_key] + original_states[saver] = original_state + + # The passthrough state we want to set (passthrough != enabled) + state = saver.Name not in enabled_save_names + if state != original_state: + saver.SetAttrs({passthrough_key: state}) + yield + finally: + for saver, original_state in original_states.items(): + saver.SetAttrs({"TOOLB_PassThrough": original_state}) + + +class FusionRenderLocal(pyblish.api.InstancePlugin): + """Render the current Fusion composition locally.""" + + order = pyblish.api.ExtractorOrder - 0.2 + label = "Render Local" + hosts = ["fusion"] + families = ["render.local"] + + def process(self, instance): + context = instance.context + + # Start render + self.render_once(context) + + # Log render status + self.log.info( + "Rendered '{nm}' for asset '{ast}' under the task '{tsk}'".format( + nm=instance.data["name"], + ast=instance.data["asset"], + tsk=instance.data["task"], + ) + ) + + def render_once(self, context): + """Render context comp only once, even with more render instances""" + + # This plug-in assumes all render nodes get rendered at the same time + # to speed up the rendering. The check below makes sure that we only + # execute the rendering once and not for each instance. + key = f"__hasRun{self.__class__.__name__}" + + savers_to_render = [ + # Get the saver tool from the instance + instance[0] for instance in context if + # Only active instances + instance.data.get("publish", True) and + # Only render.local instances + "render.local" in instance.data["families"] + ] + + if key not in context.data: + # We initialize as false to indicate it wasn't successful yet + # so we can keep track of whether Fusion succeeded + context.data[key] = False + + current_comp = context.data["currentComp"] + frame_start = context.data["frameStartHandle"] + frame_end = context.data["frameEndHandle"] + + self.log.info("Starting Fusion render") + self.log.info(f"Start frame: {frame_start}") + self.log.info(f"End frame: {frame_end}") + saver_names = ", ".join(saver.Name for saver in savers_to_render) + self.log.info(f"Rendering tools: {saver_names}") + + with comp_lock_and_undo_chunk(current_comp): + with enabled_savers(current_comp, savers_to_render): + result = current_comp.Render( + { + "Start": frame_start, + "End": frame_end, + "Wait": True, + } + ) + + context.data[key] = bool(result) + + if context.data[key] is False: + raise RuntimeError("Comp render failed") diff --git a/openpype/hosts/fusion/plugins/publish/render_local.py b/openpype/hosts/fusion/plugins/publish/render_local.py deleted file mode 100644 index 7d5f1a40c72..00000000000 --- a/openpype/hosts/fusion/plugins/publish/render_local.py +++ /dev/null @@ -1,100 +0,0 @@ -import os -import pyblish.api -from openpype.pipeline import publish -from openpype.hosts.fusion.api import comp_lock_and_undo_chunk - - -class Fusionlocal(pyblish.api.InstancePlugin, - publish.ColormanagedPyblishPluginMixin): - """Render the current Fusion composition locally. - - Extract the result of savers by starting a comp render - This will run the local render of Fusion. - - """ - - order = pyblish.api.ExtractorOrder - 0.1 - label = "Render Local" - hosts = ["fusion"] - families = ["render.local"] - - def process(self, instance): - context = instance.context - - # Start render - self.render_once(context) - - # Log render status - self.log.info( - "Rendered '{nm}' for asset '{ast}' under the task '{tsk}'".format( - nm=instance.data["name"], - ast=instance.data["asset"], - tsk=instance.data["task"], - ) - ) - - frame_start = context.data["frameStartHandle"] - frame_end = context.data["frameEndHandle"] - path = instance.data["path"] - output_dir = instance.data["outputDir"] - - basename = os.path.basename(path) - head, ext = os.path.splitext(basename) - files = [ - f"{head}{str(frame).zfill(4)}{ext}" - for frame in range(frame_start, frame_end + 1) - ] - repre = { - "name": ext[1:], - "ext": ext[1:], - "frameStart": f"%0{len(str(frame_end))}d" % frame_start, - "files": files, - "stagingDir": output_dir, - } - - self.set_representation_colorspace( - representation=repre, - context=context, - ) - - if "representations" not in instance.data: - instance.data["representations"] = [] - instance.data["representations"].append(repre) - - # review representation - if instance.data.get("review", False): - repre["tags"] = ["review", "ftrackreview"] - - def render_once(self, context): - """Render context comp only once, even with more render instances""" - - # This plug-in assumes all render nodes get rendered at the same time - # to speed up the rendering. The check below makes sure that we only - # execute the rendering once and not for each instance. - key = f"__hasRun{self.__class__.__name__}" - if key not in context.data: - # We initialize as false to indicate it wasn't successful yet - # so we can keep track of whether Fusion succeeded - context.data[key] = False - - current_comp = context.data["currentComp"] - frame_start = context.data["frameStartHandle"] - frame_end = context.data["frameEndHandle"] - - self.log.info("Starting Fusion render") - self.log.info(f"Start frame: {frame_start}") - self.log.info(f"End frame: {frame_end}") - - with comp_lock_and_undo_chunk(current_comp): - result = current_comp.Render( - { - "Start": frame_start, - "End": frame_end, - "Wait": True, - } - ) - - context.data[key] = bool(result) - - if context.data[key] is False: - raise RuntimeError("Comp render failed") diff --git a/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py b/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py index ba943abacb0..8a91f23578c 100644 --- a/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py +++ b/openpype/hosts/fusion/plugins/publish/validate_create_folder_checked.py @@ -14,22 +14,19 @@ class ValidateCreateFolderChecked(pyblish.api.InstancePlugin): """ order = pyblish.api.ValidatorOrder - actions = [RepairAction] label = "Validate Create Folder Checked" families = ["render"] hosts = ["fusion"] - actions = [SelectInvalidAction] + actions = [RepairAction, SelectInvalidAction] @classmethod def get_invalid(cls, instance): - active = instance.data.get("active", instance.data.get("publish")) - if not active: - return [] - tool = instance[0] create_dir = tool.GetInput("CreateDir") if create_dir == 0.0: - cls.log.error("%s has Create Folder turned off" % instance[0].Name) + cls.log.error( + "%s has Create Folder turned off" % instance[0].Name + ) return [tool] def process(self, instance): @@ -37,7 +34,8 @@ def process(self, instance): if invalid: raise PublishValidationError( "Found Saver with Create Folder During Render checked off", - title=self.label) + title=self.label, + ) @classmethod def repair(cls, instance): diff --git a/openpype/hosts/fusion/plugins/publish/validate_expected_frames_existence.py b/openpype/hosts/fusion/plugins/publish/validate_expected_frames_existence.py new file mode 100644 index 00000000000..c208b8ef159 --- /dev/null +++ b/openpype/hosts/fusion/plugins/publish/validate_expected_frames_existence.py @@ -0,0 +1,78 @@ +import os +import pyblish.api + +from openpype.pipeline.publish import RepairAction +from openpype.pipeline import PublishValidationError + +from openpype.hosts.fusion.api.action import SelectInvalidAction + + +class ValidateLocalFramesExistence(pyblish.api.InstancePlugin): + """Checks if files for savers that's set + to publish expected frames exists + """ + + order = pyblish.api.ValidatorOrder + label = "Validate Expected Frames Exists" + families = ["render"] + hosts = ["fusion"] + actions = [RepairAction, SelectInvalidAction] + + @classmethod + def get_invalid(cls, instance, non_existing_frames=None): + if non_existing_frames is None: + non_existing_frames = [] + + if instance.data.get("render_target") == "frames": + tool = instance[0] + + frame_start = instance.data["frameStart"] + frame_end = instance.data["frameEnd"] + path = instance.data["path"] + output_dir = instance.data["outputDir"] + + basename = os.path.basename(path) + head, ext = os.path.splitext(basename) + files = [ + f"{head}{str(frame).zfill(4)}{ext}" + for frame in range(frame_start, frame_end + 1) + ] + + for file in files: + if not os.path.exists(os.path.join(output_dir, file)): + cls.log.error( + f"Missing file: {os.path.join(output_dir, file)}" + ) + non_existing_frames.append(file) + + if len(non_existing_frames) > 0: + cls.log.error(f"Some of {tool.Name}'s files does not exist") + return [tool] + + def process(self, instance): + non_existing_frames = [] + invalid = self.get_invalid(instance, non_existing_frames) + if invalid: + raise PublishValidationError( + "{} is set to publish existing frames but " + "some frames are missing. " + "The missing file(s) are:\n\n{}".format( + invalid[0].Name, + "\n\n".join(non_existing_frames), + ), + title=self.label, + ) + + @classmethod + def repair(cls, instance): + invalid = cls.get_invalid(instance) + if invalid: + tool = invalid[0] + + # Change render target to local to render locally + tool.SetData("openpype.creator_attributes.render_target", "local") + + cls.log.info( + f"Reload the publisher and {tool.Name} " + "will be set to render locally" + ) diff --git a/openpype/hosts/fusion/scripts/set_rendermode.py b/openpype/hosts/fusion/scripts/set_rendermode.py deleted file mode 100644 index 9d2bfef3107..00000000000 --- a/openpype/hosts/fusion/scripts/set_rendermode.py +++ /dev/null @@ -1,112 +0,0 @@ -from qtpy import QtWidgets -import qtawesome -from openpype.hosts.fusion.api import get_current_comp - - -_help = {"local": "Render the comp on your own machine and publish " - "it from that the destination folder", - "farm": "Submit a Fusion render job to a Render farm to use all other" - " computers and add a publish job"} - - -class SetRenderMode(QtWidgets.QWidget): - - def __init__(self, parent=None): - QtWidgets.QWidget.__init__(self, parent) - - self._comp = get_current_comp() - self._comp_name = self._get_comp_name() - - self.setWindowTitle("Set Render Mode") - self.setFixedSize(300, 175) - - layout = QtWidgets.QVBoxLayout() - - # region comp info - comp_info_layout = QtWidgets.QHBoxLayout() - - update_btn = QtWidgets.QPushButton(qtawesome.icon("fa.refresh", - color="white"), "") - update_btn.setFixedWidth(25) - update_btn.setFixedHeight(25) - - comp_information = QtWidgets.QLineEdit() - comp_information.setEnabled(False) - - comp_info_layout.addWidget(comp_information) - comp_info_layout.addWidget(update_btn) - # endregion comp info - - # region modes - mode_options = QtWidgets.QComboBox() - mode_options.addItems(_help.keys()) - - mode_information = QtWidgets.QTextEdit() - mode_information.setReadOnly(True) - # endregion modes - - accept_btn = QtWidgets.QPushButton("Accept") - - layout.addLayout(comp_info_layout) - layout.addWidget(mode_options) - layout.addWidget(mode_information) - layout.addWidget(accept_btn) - - self.setLayout(layout) - - self.comp_information = comp_information - self.update_btn = update_btn - - self.mode_options = mode_options - self.mode_information = mode_information - - self.accept_btn = accept_btn - - self.connections() - self.update() - - # Force updated render mode help text - self._update_rendermode_info() - - def connections(self): - """Build connections between code and buttons""" - - self.update_btn.clicked.connect(self.update) - self.accept_btn.clicked.connect(self._set_comp_rendermode) - self.mode_options.currentIndexChanged.connect( - self._update_rendermode_info) - - def update(self): - """Update all information in the UI""" - - self._comp = get_current_comp() - self._comp_name = self._get_comp_name() - self.comp_information.setText(self._comp_name) - - # Update current comp settings - mode = self._get_comp_rendermode() - index = self.mode_options.findText(mode) - self.mode_options.setCurrentIndex(index) - - def _update_rendermode_info(self): - rendermode = self.mode_options.currentText() - self.mode_information.setText(_help[rendermode]) - - def _get_comp_name(self): - return self._comp.GetAttrs("COMPS_Name") - - def _get_comp_rendermode(self): - return self._comp.GetData("openpype.rendermode") or "local" - - def _set_comp_rendermode(self): - rendermode = self.mode_options.currentText() - self._comp.SetData("openpype.rendermode", rendermode) - - self._comp.Print("Updated render mode to '%s'\n" % rendermode) - self.hide() - - def _validation(self): - ui_mode = self.mode_options.currentText() - comp_mode = self._get_comp_rendermode() - - return comp_mode == ui_mode diff --git a/openpype/hosts/harmony/api/README.md b/openpype/hosts/harmony/api/README.md index b39f900886a..12f21f551a2 100644 --- a/openpype/hosts/harmony/api/README.md +++ b/openpype/hosts/harmony/api/README.md @@ -432,11 +432,11 @@ copy_files = """function copyFile(srcFilename, dstFilename) import_files = """function %s_import_files() { - var PNGTransparencyMode = 0; // Premultiplied wih Black - var TGATransparencyMode = 0; // Premultiplied wih Black - var SGITransparencyMode = 0; // Premultiplied wih Black + var PNGTransparencyMode = 0; // Premultiplied with Black + var TGATransparencyMode = 0; // Premultiplied with Black + var SGITransparencyMode = 0; // Premultiplied with Black var LayeredPSDTransparencyMode = 1; // Straight - var FlatPSDTransparencyMode = 2; // Premultiplied wih White + var FlatPSDTransparencyMode = 2; // Premultiplied with White function getUniqueColumnName( column_prefix ) { diff --git a/openpype/hosts/harmony/api/TB_sceneOpened.js b/openpype/hosts/harmony/api/TB_sceneOpened.js index e7cd555332e..a284a6ec5cf 100644 --- a/openpype/hosts/harmony/api/TB_sceneOpened.js +++ b/openpype/hosts/harmony/api/TB_sceneOpened.js @@ -142,10 +142,10 @@ function Client() { }; /** - * Process recieved request. This will eval recieved function and produce + * Process received request. This will eval received function and produce * results. * @function - * @param {object} request - recieved request JSON + * @param {object} request - received request JSON * @return {object} result of evaled function. */ self.processRequest = function(request) { @@ -245,7 +245,7 @@ function Client() { var request = JSON.parse(to_parse); var mid = request.message_id; // self.logDebug('[' + mid + '] - Request: ' + '\n' + JSON.stringify(request)); - self.logDebug('[' + mid + '] Recieved.'); + self.logDebug('[' + mid + '] Received.'); request.result = self.processRequest(request); self.logDebug('[' + mid + '] Processing done.'); @@ -286,8 +286,8 @@ function Client() { /** Harmony 21.1 doesn't have QDataStream anymore. This means we aren't able to write bytes into QByteArray so we had - modify how content lenght is sent do the server. - Content lenght is sent as string of 8 char convertible into integer + modify how content length is sent do the server. + Content length is sent as string of 8 char convertible into integer (instead of 0x00000001[4 bytes] > "000000001"[8 bytes]) */ var codec_name = new QByteArray().append("UTF-8"); @@ -476,6 +476,25 @@ function start() { action.triggered.connect(self.onSubsetManage); } + /** + * Set scene settings from DB to the scene + */ + self.onSetSceneSettings = function() { + app.avalonClient.send( + { + "module": "openpype.hosts.harmony.api", + "method": "ensure_scene_settings", + "args": [] + }, + false + ); + }; + // add Set Scene Settings + if (app.avalonMenu == null) { + action = menu.addAction('Set Scene Settings...'); + action.triggered.connect(self.onSetSceneSettings); + } + /** * Show Experimental dialog */ diff --git a/openpype/hosts/harmony/api/lib.py b/openpype/hosts/harmony/api/lib.py index e1e77bfbee0..b009dabb447 100644 --- a/openpype/hosts/harmony/api/lib.py +++ b/openpype/hosts/harmony/api/lib.py @@ -242,9 +242,15 @@ def launch_zip_file(filepath): print(f"Localizing {filepath}") temp_path = get_local_harmony_path(filepath) + scene_name = os.path.basename(temp_path) + if os.path.exists(os.path.join(temp_path, scene_name)): + # unzipped with duplicated scene_name + temp_path = os.path.join(temp_path, scene_name) + scene_path = os.path.join( - temp_path, os.path.basename(temp_path) + ".xstage" + temp_path, scene_name + ".xstage" ) + unzip = False if os.path.exists(scene_path): # Check remote scene is newer than local. @@ -262,6 +268,10 @@ def launch_zip_file(filepath): with _ZipFile(filepath, "r") as zip_ref: zip_ref.extractall(temp_path) + if os.path.exists(os.path.join(temp_path, scene_name)): + # unzipped with duplicated scene_name + temp_path = os.path.join(temp_path, scene_name) + # Close existing scene. if ProcessContext.pid: os.kill(ProcessContext.pid, signal.SIGTERM) @@ -309,7 +319,7 @@ def launch_zip_file(filepath): ) if not os.path.exists(scene_path): - print("error: cannot determine scene file") + print("error: cannot determine scene file {}".format(scene_path)) ProcessContext.server.stop() return @@ -394,7 +404,7 @@ def get_scene_data(): "function": "AvalonHarmony.getSceneData" })["result"] except json.decoder.JSONDecodeError: - # Means no sceen metadata has been made before. + # Means no scene metadata has been made before. return {} except KeyError: # Means no existing scene metadata has been made. @@ -465,7 +475,7 @@ def imprint(node_id, data, remove=False): Example: >>> from openpype.hosts.harmony.api import lib >>> node = "Top/Display" - >>> data = {"str": "someting", "int": 1, "float": 0.32, "bool": True} + >>> data = {"str": "something", "int": 1, "float": 0.32, "bool": True} >>> lib.imprint(layer, data) """ scene_data = get_scene_data() @@ -550,7 +560,7 @@ def save_scene(): method prevents this double request and safely saves the scene. """ - # Need to turn off the backgound watcher else the communication with + # Need to turn off the background watcher else the communication with # the server gets spammed with two requests at the same time. scene_path = send( {"function": "AvalonHarmony.saveScene"})["result"] diff --git a/openpype/hosts/harmony/api/pipeline.py b/openpype/hosts/harmony/api/pipeline.py index 686770b64ef..285ee806a1f 100644 --- a/openpype/hosts/harmony/api/pipeline.py +++ b/openpype/hosts/harmony/api/pipeline.py @@ -142,7 +142,7 @@ def application_launch(event): harmony.send({"script": script}) inject_avalon_js() - ensure_scene_settings() + # ensure_scene_settings() check_inventory() diff --git a/openpype/hosts/harmony/api/server.py b/openpype/hosts/harmony/api/server.py index ecf339d91bd..04048e5c84d 100644 --- a/openpype/hosts/harmony/api/server.py +++ b/openpype/hosts/harmony/api/server.py @@ -61,7 +61,7 @@ def process_request(self, request): "module": (str), # Module of method. "method" (str), # Name of method in module. "args" (list), # Arguments to pass to method. - "kwargs" (dict), # Keywork arguments to pass to method. + "kwargs" (dict), # Keyword arguments to pass to method. "reply" (bool), # Optional wait for method completion. } """ diff --git a/openpype/hosts/harmony/plugins/publish/extract_render.py b/openpype/hosts/harmony/plugins/publish/extract_render.py index c29864bb286..38b09902c15 100644 --- a/openpype/hosts/harmony/plugins/publish/extract_render.py +++ b/openpype/hosts/harmony/plugins/publish/extract_render.py @@ -25,8 +25,9 @@ def process(self, instance): application_path = instance.context.data.get("applicationPath") scene_path = instance.context.data.get("scenePath") frame_rate = instance.context.data.get("frameRate") - frame_start = instance.context.data.get("frameStart") - frame_end = instance.context.data.get("frameEnd") + # real value from timeline + frame_start = instance.context.data.get("frameStartHandle") + frame_end = instance.context.data.get("frameEndHandle") audio_path = instance.context.data.get("audioPath") if audio_path and os.path.exists(audio_path): @@ -55,9 +56,13 @@ def process(self, instance): # Execute rendering. Ignoring error cause Harmony returns error code # always. - self.log.info(f"running [ {application_path} -batch {scene_path}") + + args = [application_path, "-batch", + "-frames", str(frame_start), str(frame_end), + "-scene", scene_path] + self.log.info(f"running [ {application_path} {' '.join(args)}") proc = subprocess.Popen( - [application_path, "-batch", scene_path], + args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE diff --git a/openpype/hosts/harmony/plugins/publish/validate_scene_settings.py b/openpype/hosts/harmony/plugins/publish/validate_scene_settings.py index 936533abd6b..6e4c6955e49 100644 --- a/openpype/hosts/harmony/plugins/publish/validate_scene_settings.py +++ b/openpype/hosts/harmony/plugins/publish/validate_scene_settings.py @@ -60,7 +60,8 @@ def process(self, instance): # which is available on 'context.data["assetEntity"]' # - the same approach can be used in 'ValidateSceneSettingsRepair' expected_settings = harmony.get_asset_settings() - self.log.info("scene settings from DB:".format(expected_settings)) + self.log.info("scene settings from DB:{}".format(expected_settings)) + expected_settings.pop("entityType") # not useful for the validation expected_settings = _update_frames(dict.copy(expected_settings)) expected_settings["frameEndHandle"] = expected_settings["frameEnd"] +\ @@ -68,21 +69,32 @@ def process(self, instance): if (any(re.search(pattern, os.getenv('AVALON_TASK')) for pattern in self.skip_resolution_check)): + self.log.info("Skipping resolution check because of " + "task name and pattern {}".format( + self.skip_resolution_check)) expected_settings.pop("resolutionWidth") expected_settings.pop("resolutionHeight") - entity_type = expected_settings.get("entityType") - if (any(re.search(pattern, entity_type) + if (any(re.search(pattern, os.getenv('AVALON_TASK')) for pattern in self.skip_timelines_check)): + self.log.info("Skipping frames check because of " + "task name and pattern {}".format( + self.skip_timelines_check)) expected_settings.pop('frameStart', None) expected_settings.pop('frameEnd', None) - - expected_settings.pop("entityType") # not useful after the check + expected_settings.pop('frameStartHandle', None) + expected_settings.pop('frameEndHandle', None) asset_name = instance.context.data['anatomyData']['asset'] if any(re.search(pattern, asset_name) for pattern in self.frame_check_filter): - expected_settings.pop("frameEnd") + self.log.info("Skipping frames check because of " + "task name and pattern {}".format( + self.frame_check_filter)) + expected_settings.pop('frameStart', None) + expected_settings.pop('frameEnd', None) + expected_settings.pop('frameStartHandle', None) + expected_settings.pop('frameEndHandle', None) # handle case where ftrack uses only two decimal places # 23.976023976023978 vs. 23.98 @@ -99,6 +111,7 @@ def process(self, instance): "frameEnd": instance.context.data["frameEnd"], "handleStart": instance.context.data.get("handleStart"), "handleEnd": instance.context.data.get("handleEnd"), + "frameStartHandle": instance.context.data.get("frameStartHandle"), "frameEndHandle": instance.context.data.get("frameEndHandle"), "resolutionWidth": instance.context.data.get("resolutionWidth"), "resolutionHeight": instance.context.data.get("resolutionHeight"), diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/README.md b/openpype/hosts/harmony/vendor/OpenHarmony/README.md index 7c77fbfcfa8..064afca86ca 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/README.md +++ b/openpype/hosts/harmony/vendor/OpenHarmony/README.md @@ -6,7 +6,7 @@ Ever tried to make a simple script for toonboom Harmony, then got stumped by the Toonboom Harmony is a very powerful software, with hundreds of functions and tools, and it unlocks a great amount of possibilities for animation studios around the globe. And... being the produce of the hard work of a small team forced to prioritise, it can also be a bit rustic at times! -We are users at heart, animators and riggers, who just want to interact with the software as simply as possible. Simplicity is at the heart of the design of openHarmony. But we also are developpers, and we made the library for people like us who can't resist tweaking the software and bend it in all possible ways, and are looking for powerful functions to help them do it. +We are users at heart, animators and riggers, who just want to interact with the software as simply as possible. Simplicity is at the heart of the design of openHarmony. But we also are developers, and we made the library for people like us who can't resist tweaking the software and bend it in all possible ways, and are looking for powerful functions to help them do it. This library's aim is to create a more direct way to interact with Toonboom through scripts, by providing a more intuitive way to access its elements, and help with the cumbersome and repetitive tasks as well as help unlock untapped potential in its many available systems. So we can go from having to do things like this: @@ -78,7 +78,7 @@ All you have to do is call : ```javascript include("openHarmony.js"); ``` -at the beggining of your script. +at the beginning of your script. You can ask your users to download their copy of the library and store it alongside, or bundle it as you wish as long as you include the license file provided on this repository. @@ -129,7 +129,7 @@ Check that the environment variable `LIB_OPENHARMONY_PATH` is set correctly to t ## How to add openHarmony to vscode intellisense for autocompletion Although not fully supported, you can get most of the autocompletion features to work by adding the following lines to a `jsconfig.json` file placed at the root of your working folder. -The paths need to be relative which means the openHarmony source code must be placed directly in your developping environnement. +The paths need to be relative which means the openHarmony source code must be placed directly in your developping environment. For example, if your working folder contains the openHarmony source in a folder called `OpenHarmony` and your working scripts in a folder called `myScripts`, place the `jsconfig.json` file at the root of the folder and add these lines to the file: diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony.js index 530c0902c52..ae65d32a2b4 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -78,7 +78,7 @@ * $.log("hello"); // prints out a message to the MessageLog. * var myPoint = new $.oPoint(0,0,0); // create a new class instance from an openHarmony class. * - * // function members of the $ objects get published to the global scope, which means $ can be ommited + * // function members of the $ objects get published to the global scope, which means $ can be omitted * * log("hello"); * var myPoint = new oPoint(0,0,0); // This is all valid @@ -118,7 +118,7 @@ Object.defineProperty( $, "directory", { /** - * Wether Harmony is run with the interface or simply from command line + * Whether Harmony is run with the interface or simply from command line */ Object.defineProperty( $, "batchMode", { get: function(){ diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_actions.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_actions.js index ad1efc91beb..a54f74e1477 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_actions.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_actions.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -67,7 +67,7 @@ * @hideconstructor * @namespace * @example - * // To check wether an action is available, call the synthax: + * // To check whether an action is available, call the synthax: * Action.validate (, ); * * // To launch an action, call the synthax: diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_application.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_application.js index 9e9acb766c5..5809cee6942 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_application.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_application.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -409,7 +409,7 @@ $.oApp.prototype.getToolByName = function(toolName){ /** - * returns the list of stencils useable by the specified tool + * returns the list of stencils usable by the specified tool * @param {$.oTool} tool the tool object we want valid stencils for * @return {$.oStencil[]} the list of stencils compatible with the specified tool */ diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_attribute.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_attribute.js index d4d2d791ae2..fa044d5b742 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_attribute.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_attribute.js @@ -4,7 +4,7 @@ // openHarmony Library v0.01 // // -// Developped by Mathieu Chaptel, Chris Fourney... +// Developed by Mathieu Chaptel, Chris Fourney... // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -338,7 +338,7 @@ Object.defineProperty($.oAttribute.prototype, "useSeparate", { * Returns the default value of the attribute for most keywords * @name $.oAttribute#defaultValue * @type {bool} - * @todo switch the implentation to types? + * @todo switch the implementation to types? * @example * // to reset an attribute to its default value: * // (mostly used for position/angle/skew parameters of pegs and drawing nodes) @@ -449,7 +449,7 @@ $.oAttribute.prototype.getLinkedColumns = function(){ /** * Recursively sets an attribute to the same value as another. Both must have the same keyword. - * @param {bool} [duplicateColumns=false] In the case that the attribute has a column, wether to duplicate the column before linking + * @param {bool} [duplicateColumns=false] In the case that the attribute has a column, whether to duplicate the column before linking * @private */ $.oAttribute.prototype.setToAttributeValue = function(attributeToCopy, duplicateColumns){ diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_backdrop.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_backdrop.js index c98e1945394..1d359f93c4f 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_backdrop.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_backdrop.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_color.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_color.js index 7726be6cd6d..ff06688e66d 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_color.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_color.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -158,7 +158,7 @@ $.oColorValue.prototype.fromColorString = function (hexString){ /** - * Uses a color integer (used in backdrops) and parses the INT; applies the RGBA components of the INT to thos oColorValue + * Uses a color integer (used in backdrops) and parses the INT; applies the RGBA components of the INT to the oColorValue * @param { int } colorInt 24 bit-shifted integer containing RGBA values */ $.oColorValue.prototype.parseColorFromInt = function(colorInt){ diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_column.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_column.js index 1b73c7943e9..f73309049ea 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_column.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_column.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_database.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_database.js index 73964c5c38a..5440b92875b 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_database.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_database.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_dialog.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_dialog.js index a6e16ecb782..3ab78b87d6c 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_dialog.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_dialog.js @@ -5,7 +5,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -17,7 +17,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -250,7 +250,7 @@ $.oDialog.prototype.prompt = function( labelText, title, prefilledText){ /** * Prompts with a file selector window * @param {string} [text="Select a file:"] The title of the confirmation dialog. - * @param {string} [filter="*"] The filter for the file type and/or file name that can be selected. Accepts wildcard charater "*". + * @param {string} [filter="*"] The filter for the file type and/or file name that can be selected. Accepts wildcard character "*". * @param {string} [getExisting=true] Whether to select an existing file or a save location * @param {string} [acceptMultiple=false] Whether or not selecting more than one file is ok. Is ignored if getExisting is falses. * @param {string} [startDirectory] The directory showed at the opening of the dialog. @@ -327,14 +327,14 @@ $.oDialog.prototype.browseForFolder = function(text, startDirectory){ * @constructor * @classdesc An simple progress dialog to display the progress of a task. * To react to the user clicking the cancel button, connect a function to $.oProgressDialog.canceled() signal. - * When $.batchmode is true, the progress will be outputed as a "Progress : value/range" string to the Harmony stdout. + * When $.batchmode is true, the progress will be outputted as a "Progress : value/range" string to the Harmony stdout. * @param {string} [labelText] The text displayed above the progress bar. * @param {string} [range=100] The maximum value that represents a full progress bar. * @param {string} [title] The title of the dialog * @param {bool} [show=false] Whether to immediately show the dialog. * * @property {bool} wasCanceled Whether the progress bar was cancelled. - * @property {$.oSignal} canceled A Signal emited when the dialog is canceled. Can be connected to a callback. + * @property {$.oSignal} canceled A Signal emitted when the dialog is canceled. Can be connected to a callback. */ $.oProgressDialog = function( labelText, range, title, show ){ if (typeof title === 'undefined') var title = "Progress"; @@ -608,7 +608,7 @@ $.oPieMenu = function( name, widgets, show, minAngle, maxAngle, radius, position this.maxAngle = maxAngle; this.globalCenter = position; - // how wide outisde the icons is the slice drawn + // how wide outside the icons is the slice drawn this._circleMargin = 30; // set these values before calling show() to customize the menu appearance @@ -974,7 +974,7 @@ $.oPieMenu.prototype.getMenuRadius = function(){ var _minRadius = UiLoader.dpiScale(30); var _speed = 10; // the higher the value, the slower the progression - // hyperbolic tangent function to determin the radius + // hyperbolic tangent function to determine the radius var exp = Math.exp(2*itemsNumber/_speed); var _radius = ((exp-1)/(exp+1))*_maxRadius+_minRadius; @@ -1383,7 +1383,7 @@ $.oActionButton.prototype.activate = function(){ * This class is a subclass of QPushButton and all the methods from that class are available to modify this button. * @param {string} paletteName The name of the palette that contains the color * @param {string} colorName The name of the color (if more than one is present, will pick the first match) - * @param {bool} showName Wether to display the name of the color on the button + * @param {bool} showName Whether to display the name of the color on the button * @param {QWidget} parent The parent QWidget for the button. Automatically set during initialisation of the menu. * */ @@ -1437,7 +1437,7 @@ $.oColorButton.prototype.activate = function(){ * @name $.oScriptButton * @constructor * @classdescription This subclass of QPushButton provides an easy way to create a button for a widget that will launch a function from another script file.
    - * The buttons created this way automatically load the icon named after the script if it finds one named like the funtion in a script-icons folder next to the script file.
    + * The buttons created this way automatically load the icon named after the script if it finds one named like the function in a script-icons folder next to the script file.
    * It will also automatically set the callback to lanch the function from the script.
    * This class is a subclass of QPushButton and all the methods from that class are available to modify this button. * @param {string} scriptFile The path to the script file that will be launched diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_drawing.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_drawing.js index bad735f2370..6f2bc19c0c2 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_drawing.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_drawing.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -426,7 +426,7 @@ Object.defineProperty($.oDrawing.prototype, 'drawingData', { /** * Import a given file into an existing drawing. * @param {$.oFile} file The path to the file - * @param {bool} [convertToTvg=false] Wether to convert the bitmap to the tvg format (this doesn't vectorise the drawing) + * @param {bool} [convertToTvg=false] Whether to convert the bitmap to the tvg format (this doesn't vectorise the drawing) * * @return { $.oFile } the oFile object pointing to the drawing file after being it has been imported into the element folder. */ @@ -878,8 +878,8 @@ $.oArtLayer.prototype.drawCircle = function(center, radius, lineStyle, fillStyle * @param {$.oVertex[]} path an array of $.oVertex objects that describe a path. * @param {$.oLineStyle} [lineStyle] the line style to draw with. (By default, will use the current stencil selection) * @param {$.oFillStyle} [fillStyle] the fill information for the path. (By default, will use the current palette selection) - * @param {bool} [polygon] Wether bezier handles should be created for the points in the path (ignores "onCurve" properties of oVertex from path) - * @param {bool} [createUnderneath] Wether the new shape will appear on top or underneath the contents of the layer. (not working yet) + * @param {bool} [polygon] Whether bezier handles should be created for the points in the path (ignores "onCurve" properties of oVertex from path) + * @param {bool} [createUnderneath] Whether the new shape will appear on top or underneath the contents of the layer. (not working yet) */ $.oArtLayer.prototype.drawShape = function(path, lineStyle, fillStyle, polygon, createUnderneath){ if (typeof fillStyle === 'undefined') var fillStyle = new this.$.oFillStyle(); @@ -959,7 +959,7 @@ $.oArtLayer.prototype.drawContour = function(path, fillStyle){ * @param {float} width the width of the rectangle. * @param {float} height the height of the rectangle. * @param {$.oLineStyle} lineStyle a line style to use for the rectangle stroke. - * @param {$.oFillStyle} fillStyle a fill style to use for the rectange fill. + * @param {$.oFillStyle} fillStyle a fill style to use for the rectangle fill. * @returns {$.oShape} the shape containing the added stroke. */ $.oArtLayer.prototype.drawRectangle = function(x, y, width, height, lineStyle, fillStyle){ @@ -1514,7 +1514,7 @@ Object.defineProperty($.oStroke.prototype, "path", { /** - * The oVertex that are on the stroke (Bezier handles exluded.) + * The oVertex that are on the stroke (Bezier handles excluded.) * The first is repeated at the last position when the stroke is closed. * @name $.oStroke#points * @type {$.oVertex[]} @@ -1583,7 +1583,7 @@ Object.defineProperty($.oStroke.prototype, "style", { /** - * wether the stroke is a closed shape. + * whether the stroke is a closed shape. * @name $.oStroke#closed * @type {bool} */ @@ -1919,7 +1919,7 @@ $.oContour.prototype.toString = function(){ * @constructor * @classdesc * The $.oVertex class represents a single control point on a stroke. This class is used to get the index of the point in the stroke path sequence, as well as its position as a float along the stroke's length. - * The onCurve property describes wether this control point is a bezier handle or a point on the curve. + * The onCurve property describes whether this control point is a bezier handle or a point on the curve. * * @param {$.oStroke} stroke the stroke that this vertex belongs to * @param {float} x the x coordinate of the vertex, in drawing space diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_element.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_element.js index ed50d6e50b4..b64c8169ecc 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_element.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_element.js @@ -4,7 +4,7 @@ // openHarmony Library v0.01 // // -// Developped by Mathieu Chaptel, Chris Fourney... +// Developed by Mathieu Chaptel, Chris Fourney... // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_file.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_file.js index 14dafa3b638..50e4b0d4758 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_file.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_file.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -509,7 +509,7 @@ Object.defineProperty($.oFile.prototype, 'fullName', { /** - * The name of the file without extenstion. + * The name of the file without extension. * @name $.oFile#name * @type {string} */ diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_frame.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_frame.js index 37bdede02a9..e1d1dd7fad3 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_frame.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_frame.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -263,7 +263,7 @@ Object.defineProperty($.oFrame.prototype, 'duration', { return _sceneLength; } - // walk up the frames of the scene to the next keyFrame to determin duration + // walk up the frames of the scene to the next keyFrame to determine duration var _frames = this.column.frames for (var i=this.frameNumber+1; i<_sceneLength; i++){ if (_frames[i].isKeyframe) return _frames[i].frameNumber - _startFrame; @@ -426,7 +426,7 @@ Object.defineProperty($.oFrame.prototype, 'velocity', { * easeIn : a $.oPoint object representing the left handle for bezier columns, or a {point, ease} object for ease columns. * easeOut : a $.oPoint object representing the left handle for bezier columns, or a {point, ease} object for ease columns. * continuity : the type of bezier used by the point. - * constant : wether the frame is interpolated or a held value. + * constant : whether the frame is interpolated or a held value. * @name $.oFrame#ease * @type {oPoint/object} */ @@ -520,7 +520,7 @@ Object.defineProperty($.oFrame.prototype, 'easeOut', { /** - * Determines the frame's continuity setting. Can take the values "CORNER", (two independant bezier handles on each side), "SMOOTH"(handles are aligned) or "STRAIGHT" (no handles and in straight lines). + * Determines the frame's continuity setting. Can take the values "CORNER", (two independent bezier handles on each side), "SMOOTH"(handles are aligned) or "STRAIGHT" (no handles and in straight lines). * @name $.oFrame#continuity * @type {string} */ diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_list.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_list.js index 9d02b1c2aa6..63a5c0eeb82 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_list.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_list.js @@ -4,7 +4,7 @@ // openHarmony Library v0.01 // // -// Developped by Mathieu Chaptel, Chris Fourney... +// Developed by Mathieu Chaptel, Chris Fourney... // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -516,5 +516,5 @@ Object.defineProperty($.oList.prototype, 'toString', { -//Needs all filtering, limiting. mapping, pop, concat, join, ect +//Needs all filtering, limiting. mapping, pop, concat, join, etc //Speed up by finessing the way it extends and tracks the enumerable properties. \ No newline at end of file diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_math.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_math.js index c0d4ca99a74..06bfb51f306 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_math.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_math.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -193,7 +193,7 @@ $.oPoint.prototype.pointSubtract = function( sub_pt ){ /** * Subtracts the point to the coordinates of the current oPoint and returns a new oPoint with the result. * @param {$.oPoint} point The point to subtract to this point. - * @returns {$.oPoint} a new independant oPoint. + * @returns {$.oPoint} a new independent oPoint. */ $.oPoint.prototype.subtractPoint = function( point ){ var x = this.x - point.x; @@ -298,9 +298,9 @@ $.oPoint.prototype.convertToWorldspace = function(){ /** - * Linearily Interpolate between this (0.0) and the provided point (1.0) + * Linearly Interpolate between this (0.0) and the provided point (1.0) * @param {$.oPoint} point The target point at 100% - * @param {double} perc 0-1.0 value to linearily interp + * @param {double} perc 0-1.0 value to linearly interp * * @return: { $.oPoint } The interpolated value. */ @@ -410,9 +410,9 @@ $.oBox.prototype.include = function(box){ /** - * Checks wether the box contains another $.oBox. + * Checks whether the box contains another $.oBox. * @param {$.oBox} box The $.oBox to check for. - * @param {bool} [partial=false] wether to accept partially contained boxes. + * @param {bool} [partial=false] whether to accept partially contained boxes. */ $.oBox.prototype.contains = function(box, partial){ if (typeof partial === 'undefined') var partial = false; @@ -537,7 +537,7 @@ $.oMatrix.prototype.toString = function(){ * @classdesc The $.oVector is a replacement for the Vector3d objects of Harmony. * @param {float} x a x coordinate for this vector. * @param {float} y a y coordinate for this vector. - * @param {float} [z=0] a z coordinate for this vector. If ommited, will be set to 0 and vector will be 2D. + * @param {float} [z=0] a z coordinate for this vector. If omitted, will be set to 0 and vector will be 2D. */ $.oVector = function(x, y, z){ if (typeof z === "undefined" || isNaN(z)) var z = 0; diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_metadata.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_metadata.js index c19e6d12f41..29afeb522cf 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_metadata.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_metadata.js @@ -4,7 +4,7 @@ // openHarmony Library v0.01 // // -// Developped by Mathieu Chaptel, Chris Fourney... +// Developed by Mathieu Chaptel, Chris Fourney... // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_misc.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_misc.js index fec5d328164..6ef75f55604 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_misc.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_misc.js @@ -4,7 +4,7 @@ // openHarmony Library v0.01 // // -// Developped by Mathieu Chaptel, Chris Fourney... +// Developed by Mathieu Chaptel, Chris Fourney... // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -54,7 +54,7 @@ /** - * The $.oUtils helper class -- providing generic utilities. Doesn't need instanciation. + * The $.oUtils helper class -- providing generic utilities. Doesn't need instantiation. * @classdesc $.oUtils utility Class */ $.oUtils = function(){ diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_network.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_network.js index a4476d75914..2a6aa3519ac 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_network.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_network.js @@ -4,7 +4,7 @@ // openHarmony Library v0.01 // // -// Developped by Mathieu Chaptel, Chris Fourney... +// Developed by Mathieu Chaptel, Chris Fourney... // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -87,7 +87,7 @@ $.oNetwork = function( ){ * @param {function} callback_func Providing a callback function prevents blocking, and will respond on this function. The callback function is in form func( results ){} * @param {bool} use_json In the event of a JSON api, this will return an object converted from the returned JSON. * - * @return: {string/object} The resulting object/string from the query -- otherwise a bool as false when an error occured.. + * @return: {string/object} The resulting object/string from the query -- otherwise a bool as false when an error occurred.. */ $.oNetwork.prototype.webQuery = function ( address, callback_func, use_json ){ if (typeof callback_func === 'undefined') var callback_func = false; @@ -272,7 +272,7 @@ $.oNetwork.prototype.webQuery = function ( address, callback_func, use_json ){ * @param {function} path The local file path to save the download. * @param {bool} replace Replace the file if it exists. * - * @return: {string/object} The resulting object/string from the query -- otherwise a bool as false when an error occured.. + * @return: {string/object} The resulting object/string from the query -- otherwise a bool as false when an error occurred.. */ $.oNetwork.prototype.downloadSingle = function ( address, path, replace ){ if (typeof replace === 'undefined') var replace = false; diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_node.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_node.js index 5590d7b7e94..deb18543578 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_node.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_node.js @@ -4,7 +4,7 @@ // openHarmony Library // // -// Developped by Mathieu Chaptel, Chris Fourney +// Developed by Mathieu Chaptel, Chris Fourney // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -562,7 +562,7 @@ Object.defineProperty($.oNode.prototype, 'height', { /** - * The list of oNodeLinks objects descibing the connections to the inport of this node, in order of inport. + * The list of oNodeLinks objects describing the connections to the inport of this node, in order of inport. * @name $.oNode#inLinks * @readonly * @deprecated returns $.oNodeLink instances but $.oLink is preferred. Use oNode.getInLinks() instead. @@ -658,7 +658,7 @@ Object.defineProperty($.oNode.prototype, 'outPorts', { /** - * The list of oNodeLinks objects descibing the connections to the outports of this node, in order of outport. + * The list of oNodeLinks objects describing the connections to the outports of this node, in order of outport. * @name $.oNode#outLinks * @readonly * @type {$.oNodeLink[]} @@ -1666,7 +1666,7 @@ $.oNode.prototype.refreshAttributes = function( ){ * It represents peg nodes in the scene. * @constructor * @augments $.oNode - * @classdesc Peg Moudle Class + * @classdesc Peg Module Class * @param {string} path Path to the node in the network. * @param {oScene} oSceneObject Access to the oScene object of the DOM. */ @@ -1886,7 +1886,7 @@ $.oDrawingNode.prototype.getDrawingAtFrame = function(frameNumber){ /** - * Gets the list of palettes containing colors used by a drawing node. This only gets palettes with the first occurence of the colors. + * Gets the list of palettes containing colors used by a drawing node. This only gets palettes with the first occurrence of the colors. * @return {$.oPalette[]} The palettes that contain the color IDs used by the drawings of the node. */ $.oDrawingNode.prototype.getUsedPalettes = function(){ @@ -1968,7 +1968,7 @@ $.oDrawingNode.prototype.unlinkPalette = function(oPaletteObject){ * Duplicates a node by creating an independent copy. * @param {string} [newName] The new name for the duplicated node. * @param {oPoint} [newPosition] The new position for the duplicated node. - * @param {bool} [duplicateElement] Wether to also duplicate the element. + * @param {bool} [duplicateElement] Whether to also duplicate the element. */ $.oDrawingNode.prototype.duplicate = function(newName, newPosition, duplicateElement){ if (typeof newPosition === 'undefined') var newPosition = this.nodePosition; @@ -2464,7 +2464,7 @@ $.oGroupNode.prototype.getNodeByName = function(name){ * Returns all the nodes of a certain type in the group. * Pass a value to recurse to look into the groups as well. * @param {string} typeName The type of the nodes. - * @param {bool} recurse Wether to look inside the groups. + * @param {bool} recurse Whether to look inside the groups. * * @return {$.oNode[]} The nodes found. */ @@ -2626,7 +2626,7 @@ $.oGroupNode.prototype.orderNodeView = function(recurse){ * * peg.linkOutNode(drawingNode); * - * //through all this we didn't specify nodePosition parameters so we'll sort evertything at once + * //through all this we didn't specify nodePosition parameters so we'll sort everything at once * * sceneRoot.orderNodeView(); * @@ -3333,7 +3333,7 @@ $.oGroupNode.prototype.importImageAsTVG = function(path, alignment, nodePosition * imports an image sequence as a node into the current group. * @param {$.oFile[]} imagePaths a list of paths to the images to import (can pass a list of strings or $.oFile) * @param {number} [exposureLength=1] the number of frames each drawing should be exposed at. If set to 0/false, each drawing will use the numbering suffix of the file to set its frame. - * @param {boolean} [convertToTvg=false] wether to convert the files to tvg during import + * @param {boolean} [convertToTvg=false] whether to convert the files to tvg during import * @param {string} [alignment="ASIS"] the alignment to apply to the node * @param {$.oPoint} [nodePosition] the position of the node in the nodeview * @@ -3346,7 +3346,7 @@ $.oGroupNode.prototype.importImageSequence = function(imagePaths, exposureLength if (typeof extendScene === 'undefined') var extendScene = false; - // match anything but capture trailing numbers and separates punctuation preceeding it + // match anything but capture trailing numbers and separates punctuation preceding it var numberingRe = /(.*?)([\W_]+)?(\d*)$/i; // sanitize imagePaths diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_nodeLink.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_nodeLink.js index 279a8716911..07a4d147da3 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_nodeLink.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony/openHarmony_nodeLink.js @@ -4,7 +4,7 @@ // openHarmony Library v0.01 // // -// Developped by Mathieu Chaptel, Chris Fourney... +// Developed by Mathieu Chaptel, Chris Fourney... // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -174,7 +174,7 @@ Object.defineProperty($.oNodeLink.prototype, 'outNode', { return; } - this.apply(); // do we really want to apply everytime we set? + this.apply(); // do we really want to apply every time we set? } }); @@ -198,7 +198,7 @@ Object.defineProperty($.oNodeLink.prototype, 'inNode', { return; } - this.apply(); // do we really want to apply everytime we set? + this.apply(); // do we really want to apply every time we set? } }); @@ -222,7 +222,7 @@ Object.defineProperty($.oNodeLink.prototype, 'outPort', { return; } - this.apply(); // do we really want to apply everytime we set? + this.apply(); // do we really want to apply every time we set? } }); @@ -256,7 +256,7 @@ Object.defineProperty($.oNodeLink.prototype, 'inPort', { return; } - this.apply(); // do we really want to apply everytime we set? + this.apply(); // do we really want to apply every time we set? } }); @@ -983,7 +983,7 @@ $.oNodeLink.prototype.validate = function ( ) { * @return {bool} Whether the connection is a valid connection that exists currently in the node system. */ $.oNodeLink.prototype.validateUpwards = function( inport, outportProvided ) { - //IN THE EVENT OUTNODE WASNT PROVIDED. + //IN THE EVENT OUTNODE WASN'T PROVIDED. this.path = this.findInputPath( this._inNode, inport, [] ); if( !this.path || this.path.length == 0 ){ return false; @@ -1173,7 +1173,7 @@ Object.defineProperty($.oLink.prototype, 'outPort', { /** - * The index of the link comming out of the out-port. + * The index of the link coming out of the out-port. *
    In the event this value wasn't known by the link object but the link is actually connected, the correct value will be found. * @name $.oLink#outLink * @readonly @@ -1323,7 +1323,7 @@ $.oLink.prototype.getValidLink = function(createOutPorts, createInPorts){ /** - * Attemps to connect a link. Will guess the ports if not provided. + * Attempts to connect a link. Will guess the ports if not provided. * @return {bool} */ $.oLink.prototype.connect = function(){ @@ -1623,11 +1623,11 @@ $.oLinkPath.prototype.findExistingPath = function(){ /** - * Gets a link object from two nodes that can be succesfully connected. Provide port numbers if there are specific requirements to match. If a link already exists, it will be returned. + * Gets a link object from two nodes that can be successfully connected. Provide port numbers if there are specific requirements to match. If a link already exists, it will be returned. * @param {$.oNode} start The node from which the link originates. * @param {$.oNode} end The node at which the link ends. - * @param {int} [outPort] A prefered out-port for the link to use. - * @param {int} [inPort] A prefered in-port for the link to use. + * @param {int} [outPort] A preferred out-port for the link to use. + * @param {int} [inPort] A preferred in-port for the link to use. * * @return {$.oLink} the valid $.oLink object. Returns null if no such link could be created (for example if the node's in-port is already linked) */ diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony_tools.js b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony_tools.js index 57d4a63e961..9014929fc48 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony_tools.js +++ b/openpype/hosts/harmony/vendor/OpenHarmony/openHarmony_tools.js @@ -4,7 +4,7 @@ // openHarmony Library v0.01 // // -// Developped by Mathieu Chaptel, ... +// Developed by Mathieu Chaptel, ... // // // This library is an open source implementation of a Document Object Model @@ -16,7 +16,7 @@ // and by hiding the heavy lifting required by the official API. // // This library is provided as is and is a work in progress. As such, not every -// function has been implemented or is garanteed to work. Feel free to contribute +// function has been implemented or is guaranteed to work. Feel free to contribute // improvements to its official github. If you do make sure you follow the provided // template and naming conventions and document your new methods properly. // @@ -212,7 +212,7 @@ function openHarmony_toolInstaller(){ //---------------------------------------------- - //-- GET THE FILE CONTENTS IN A DIRCTORY ON GIT + //-- GET THE FILE CONTENTS IN A DIRECTORY ON GIT this.recurse_files = function( contents, arr_files ){ with( context.$.global ){ try{ @@ -501,7 +501,7 @@ function openHarmony_toolInstaller(){ var download_item = item["download_url"]; var query = $.network.webQuery( download_item, false, false ); if( query ){ - //INSTALL TYPES ARE script, package, ect. + //INSTALL TYPES ARE script, package, etc. if( install_types[ m.install_cache[ item["url"] ] ] ){ m.installLabel.text = install_types[ m.install_cache[ item["url"] ] ]; diff --git a/openpype/hosts/harmony/vendor/OpenHarmony/package.json b/openpype/hosts/harmony/vendor/OpenHarmony/package.json index c62ecbc9d80..7a535cdcf6f 100644 --- a/openpype/hosts/harmony/vendor/OpenHarmony/package.json +++ b/openpype/hosts/harmony/vendor/OpenHarmony/package.json @@ -1,7 +1,7 @@ { "name": "openharmony", "version": "0.0.1", - "description": "An Open Source Imlementation of a Document Object Model for the Toonboom Harmony scripting interface", + "description": "An Open Source Implementation of a Document Object Model for the Toonboom Harmony scripting interface", "main": "openHarmony.js", "scripts": { "test": "$", diff --git a/openpype/hosts/hiero/api/__init__.py b/openpype/hosts/hiero/api/__init__.py index 1fa40c9f745..b95c0fe1d73 100644 --- a/openpype/hosts/hiero/api/__init__.py +++ b/openpype/hosts/hiero/api/__init__.py @@ -108,7 +108,7 @@ "apply_colorspace_project", "apply_colorspace_clips", "get_sequence_pattern_and_padding", - # depricated + # deprecated "get_track_item_pype_tag", "set_track_item_pype_tag", "get_track_item_pype_data", diff --git a/openpype/hosts/hiero/api/lib.py b/openpype/hosts/hiero/api/lib.py index bbd1edc14a3..0d4368529f5 100644 --- a/openpype/hosts/hiero/api/lib.py +++ b/openpype/hosts/hiero/api/lib.py @@ -1221,7 +1221,7 @@ def set_track_color(track_item, color): def check_inventory_versions(track_items=None): """ - Actual version color idetifier of Loaded containers + Actual version color identifier of Loaded containers Check all track items and filter only Loader nodes for its version. It will get all versions from database @@ -1249,10 +1249,10 @@ def check_inventory_versions(track_items=None): project_name = legacy_io.active_project() filter_result = filter_containers(containers, project_name) for container in filter_result.latest: - set_track_color(container["_item"], clip_color) + set_track_color(container["_item"], clip_color_last) for container in filter_result.outdated: - set_track_color(container["_item"], clip_color_last) + set_track_color(container["_item"], clip_color) def selection_changed_timeline(event): diff --git a/openpype/hosts/hiero/api/pipeline.py b/openpype/hosts/hiero/api/pipeline.py index 4ab73e7d194..d88aeac8100 100644 --- a/openpype/hosts/hiero/api/pipeline.py +++ b/openpype/hosts/hiero/api/pipeline.py @@ -193,8 +193,8 @@ def data_to_container(item, data): return # convert the data to list and validate them for _, obj_data in _data.items(): - cotnainer = data_to_container(item, obj_data) - return_list.append(cotnainer) + container = data_to_container(item, obj_data) + return_list.append(container) return return_list else: _data = lib.get_trackitem_openpype_data(item) diff --git a/openpype/hosts/hiero/api/plugin.py b/openpype/hosts/hiero/api/plugin.py index 07457db1a40..a3f8a6c5243 100644 --- a/openpype/hosts/hiero/api/plugin.py +++ b/openpype/hosts/hiero/api/plugin.py @@ -146,6 +146,8 @@ def camel_case_split(self, text): return " ".join([str(m.group(0)).capitalize() for m in matches]) def create_row(self, layout, type, text, **kwargs): + value_keys = ["setText", "setCheckState", "setValue", "setChecked"] + # get type attribute from qwidgets attr = getattr(QtWidgets, type) @@ -167,14 +169,27 @@ def create_row(self, layout, type, text, **kwargs): # assign the created attribute to variable item = getattr(self, attr_name) + + # set attributes to item which are not values for func, val in kwargs.items(): + if func in value_keys: + continue + if getattr(item, func): + log.debug("Setting {} to {}".format(func, val)) func_attr = getattr(item, func) if isinstance(val, tuple): func_attr(*val) else: func_attr(val) + # set values to item + for value_item in value_keys: + if value_item not in kwargs: + continue + if getattr(item, value_item): + getattr(item, value_item)(kwargs[value_item]) + # add to layout layout.addRow(label, item) @@ -276,8 +291,11 @@ def populate_widgets(self, data, content_layout=None): elif v["type"] == "QSpinBox": data[k]["value"] = self.create_row( content_layout, "QSpinBox", v["label"], - setValue=v["value"], setMinimum=0, + setValue=v["value"], + setDisplayIntegerBase=10000, + setRange=(0, 99999), setMinimum=0, setMaximum=100000, setToolTip=tool_tip) + return data @@ -393,7 +411,7 @@ def __init__(self, cls, context, **options): self.with_handles = options.get("handles") or bool( options.get("handles") is True) # try to get value from options or evaluate key value for `load_how` - self.sequencial_load = options.get("sequencially") or bool( + self.sequencial_load = options.get("sequentially") or bool( "Sequentially in order" in options.get("load_how", "")) # try to get value from options or evaluate key value for `load_to` self.new_sequence = options.get("newSequence") or bool( @@ -818,7 +836,7 @@ def _convert_to_tag_data(self): # increasing steps by index of rename iteration self.count_steps *= self.rename_index - hierarchy_formating_data = {} + hierarchy_formatting_data = {} hierarchy_data = deepcopy(self.hierarchy_data) _data = self.track_item_default_data.copy() if self.ui_inputs: @@ -853,13 +871,13 @@ def _convert_to_tag_data(self): # fill up pythonic expresisons in hierarchy data for k, _v in hierarchy_data.items(): - hierarchy_formating_data[k] = _v["value"].format(**_data) + hierarchy_formatting_data[k] = _v["value"].format(**_data) else: # if no gui mode then just pass default data - hierarchy_formating_data = hierarchy_data + hierarchy_formatting_data = hierarchy_data tag_hierarchy_data = self._solve_tag_hierarchy_data( - hierarchy_formating_data + hierarchy_formatting_data ) tag_hierarchy_data.update({"heroTrack": True}) @@ -887,20 +905,20 @@ def _convert_to_tag_data(self): # add data to return data dict self.tag_data.update(tag_hierarchy_data) - def _solve_tag_hierarchy_data(self, hierarchy_formating_data): + def _solve_tag_hierarchy_data(self, hierarchy_formatting_data): """ Solve tag data from hierarchy data and templates. """ # fill up clip name and hierarchy keys - hierarchy_filled = self.hierarchy.format(**hierarchy_formating_data) - clip_name_filled = self.clip_name.format(**hierarchy_formating_data) + hierarchy_filled = self.hierarchy.format(**hierarchy_formatting_data) + clip_name_filled = self.clip_name.format(**hierarchy_formatting_data) # remove shot from hierarchy data: is not needed anymore - hierarchy_formating_data.pop("shot") + hierarchy_formatting_data.pop("shot") return { "newClipName": clip_name_filled, "hierarchy": hierarchy_filled, "parents": self.parents, - "hierarchyData": hierarchy_formating_data, + "hierarchyData": hierarchy_formatting_data, "subset": self.subset, "family": self.subset_family, "families": [self.data["family"]] @@ -916,16 +934,16 @@ def _convert_to_entity(self, type, template): ) # first collect formatting data to use for formatting template - formating_data = {} + formatting_data = {} for _k, _v in self.hierarchy_data.items(): value = _v["value"].format( **self.track_item_default_data) - formating_data[_k] = value + formatting_data[_k] = value return { "entity_type": entity_type, "entity_name": template.format( - **formating_data + **formatting_data ) } diff --git a/openpype/hosts/houdini/api/lib.py b/openpype/hosts/houdini/api/lib.py index 13f5a62ec33..f19dc649925 100644 --- a/openpype/hosts/houdini/api/lib.py +++ b/openpype/hosts/houdini/api/lib.py @@ -479,23 +479,13 @@ def reset_framerange(): frame_start = asset_data.get("frameStart") frame_end = asset_data.get("frameEnd") - # Backwards compatibility - if frame_start is None or frame_end is None: - frame_start = asset_data.get("edit_in") - frame_end = asset_data.get("edit_out") if frame_start is None or frame_end is None: log.warning("No edit information found for %s" % asset_name) return - handles = asset_data.get("handles") or 0 - handle_start = asset_data.get("handleStart") - if handle_start is None: - handle_start = handles - - handle_end = asset_data.get("handleEnd") - if handle_end is None: - handle_end = handles + handle_start = asset_data.get("handleStart", 0) + handle_end = asset_data.get("handleEnd", 0) frame_start -= int(handle_start) frame_end += int(handle_end) diff --git a/openpype/hosts/houdini/api/pipeline.py b/openpype/hosts/houdini/api/pipeline.py index 9793679b45d..45e2f8f87fb 100644 --- a/openpype/hosts/houdini/api/pipeline.py +++ b/openpype/hosts/houdini/api/pipeline.py @@ -144,13 +144,10 @@ def create_context_node(): """ obj_network = hou.node("/obj") - op_ctx = obj_network.createNode("null", node_name="OpenPypeContext") - - # A null in houdini by default comes with content inside to visualize - # the null. However since we explicitly want to hide the node lets - # remove the content and disable the display flag of the node - for node in op_ctx.children(): - node.destroy() + op_ctx = obj_network.createNode("subnet", + node_name="OpenPypeContext", + run_init_scripts=False, + load_contents=False) op_ctx.moveToGoodPosition() op_ctx.setBuiltExplicitly(False) diff --git a/openpype/hosts/houdini/api/plugin.py b/openpype/hosts/houdini/api/plugin.py index f0985973a61..340a7f07704 100644 --- a/openpype/hosts/houdini/api/plugin.py +++ b/openpype/hosts/houdini/api/plugin.py @@ -60,7 +60,7 @@ def process(self): def process(self): instance = super(CreateEpicNode, self, process() - # Set paramaters for Alembic node + # Set parameters for Alembic node instance.setParms( {"sop_path": "$HIP/%s.abc" % self.nodes[0]} ) diff --git a/openpype/hosts/houdini/api/shelves.py b/openpype/hosts/houdini/api/shelves.py index ebd668e9e48..6e0f367f624 100644 --- a/openpype/hosts/houdini/api/shelves.py +++ b/openpype/hosts/houdini/api/shelves.py @@ -69,7 +69,7 @@ def generate_shelves(): mandatory_attributes = {'label', 'script'} for tool_definition in shelf_definition.get('tools_list'): - # We verify that the name and script attibutes of the tool + # We verify that the name and script attributes of the tool # are set if not all( tool_definition[key] for key in mandatory_attributes diff --git a/openpype/hosts/houdini/plugins/create/convert_legacy.py b/openpype/hosts/houdini/plugins/create/convert_legacy.py index 4b8041b4f55..e549c9dc26b 100644 --- a/openpype/hosts/houdini/plugins/create/convert_legacy.py +++ b/openpype/hosts/houdini/plugins/create/convert_legacy.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -"""Convertor for legacy Houdini subsets.""" +"""Converter for legacy Houdini subsets.""" from openpype.pipeline.create.creator_plugins import SubsetConvertorPlugin from openpype.hosts.houdini.api.lib import imprint @@ -7,7 +7,7 @@ class HoudiniLegacyConvertor(SubsetConvertorPlugin): """Find and convert any legacy subsets in the scene. - This Convertor will find all legacy subsets in the scene and will + This Converter will find all legacy subsets in the scene and will transform them to the current system. Since the old subsets doesn't retain any information about their original creators, the only mapping we can do is based on their families. diff --git a/openpype/hosts/houdini/plugins/publish/collect_current_file.py b/openpype/hosts/houdini/plugins/publish/collect_current_file.py index 9cca07fdc7c..caf679f98be 100644 --- a/openpype/hosts/houdini/plugins/publish/collect_current_file.py +++ b/openpype/hosts/houdini/plugins/publish/collect_current_file.py @@ -1,7 +1,6 @@ import os import hou -from openpype.pipeline import legacy_io import pyblish.api @@ -11,7 +10,7 @@ class CollectHoudiniCurrentFile(pyblish.api.InstancePlugin): order = pyblish.api.CollectorOrder - 0.01 label = "Houdini Current File" hosts = ["houdini"] - family = ["workfile"] + families = ["workfile"] def process(self, instance): """Inject the current working file""" @@ -21,7 +20,7 @@ def process(self, instance): # By default, Houdini will even point a new scene to a path. # However if the file is not saved at all and does not exist, # we assume the user never set it. - filepath = "" + current_file = "" elif os.path.basename(current_file) == "untitled.hip": # Due to even a new file being called 'untitled.hip' we are unable diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index 4fb750d91bd..ad9a450cad3 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -6,6 +6,11 @@ from typing import Union import contextlib +from openpype.pipeline.context_tools import ( + get_current_project_asset, + get_current_project +) + JSON_PREFIX = "JSON::" @@ -157,6 +162,105 @@ def get_multipass_setting(project_setting=None): ["multipass"]) +def set_scene_resolution(width: int, height: int): + """Set the render resolution + + Args: + width(int): value of the width + height(int): value of the height + + Returns: + None + + """ + rt.renderWidth = width + rt.renderHeight = height + + +def reset_scene_resolution(): + """Apply the scene resolution from the project definition + + scene resolution can be overwritten by an asset if the asset.data contains + any information regarding scene resolution . + Returns: + None + """ + data = ["data.resolutionWidth", "data.resolutionHeight"] + project_resolution = get_current_project(fields=data) + project_resolution_data = project_resolution["data"] + asset_resolution = get_current_project_asset(fields=data) + asset_resolution_data = asset_resolution["data"] + # Set project resolution + project_width = int(project_resolution_data.get("resolutionWidth", 1920)) + project_height = int(project_resolution_data.get("resolutionHeight", 1080)) + width = int(asset_resolution_data.get("resolutionWidth", project_width)) + height = int(asset_resolution_data.get("resolutionHeight", project_height)) + + set_scene_resolution(width, height) + + +def get_frame_range() -> dict: + """Get the current assets frame range and handles. + + Returns: + dict: with frame start, frame end, handle start, handle end. + """ + # Set frame start/end + asset = get_current_project_asset() + frame_start = asset["data"].get("frameStart") + frame_end = asset["data"].get("frameEnd") + + if frame_start is None or frame_end is None: + return + + handle_start = asset["data"].get("handleStart", 0) + handle_end = asset["data"].get("handleEnd", 0) + return { + "frameStart": frame_start, + "frameEnd": frame_end, + "handleStart": handle_start, + "handleEnd": handle_end + } + + +def reset_frame_range(fps: bool = True): + """Set frame range to current asset. + This is part of 3dsmax documentation: + + animationRange: A System Global variable which lets you get and + set an Interval value that defines the start and end frames + of the Active Time Segment. + frameRate: A System Global variable which lets you get + and set an Integer value that defines the current + scene frame rate in frames-per-second. + """ + if fps: + data_fps = get_current_project(fields=["data.fps"]) + fps_number = float(data_fps["data"]["fps"]) + rt.frameRate = fps_number + frame_range = get_frame_range() + frame_start = frame_range["frameStart"] - int(frame_range["handleStart"]) + frame_end = frame_range["frameEnd"] + int(frame_range["handleEnd"]) + frange_cmd = f"animationRange = interval {frame_start} {frame_end}" + rt.execute(frange_cmd) + + +def set_context_setting(): + """Apply the project settings from the project definition + + Settings can be overwritten by an asset if the asset.data contains + any information regarding those settings. + + Examples of settings: + frame range + resolution + + Returns: + None + """ + reset_scene_resolution() + + def get_max_version(): """ Args: diff --git a/openpype/hosts/max/api/menu.py b/openpype/hosts/max/api/menu.py index 5c273b49b4c..066cc900394 100644 --- a/openpype/hosts/max/api/menu.py +++ b/openpype/hosts/max/api/menu.py @@ -4,6 +4,7 @@ from pymxs import runtime as rt from openpype.tools.utils import host_tools +from openpype.hosts.max.api import lib class OpenPypeMenu(object): @@ -107,6 +108,17 @@ def build_openpype_menu(self) -> QtWidgets.QAction: workfiles_action = QtWidgets.QAction("Work Files...", openpype_menu) workfiles_action.triggered.connect(self.workfiles_callback) openpype_menu.addAction(workfiles_action) + + openpype_menu.addSeparator() + + res_action = QtWidgets.QAction("Set Resolution", openpype_menu) + res_action.triggered.connect(self.resolution_callback) + openpype_menu.addAction(res_action) + + frame_action = QtWidgets.QAction("Set Frame Range", openpype_menu) + frame_action.triggered.connect(self.frame_range_callback) + openpype_menu.addAction(frame_action) + return openpype_menu def load_callback(self): @@ -128,3 +140,11 @@ def library_callback(self): def workfiles_callback(self): """Callback to show Workfiles tool.""" host_tools.show_workfiles(parent=self.main_widget) + + def resolution_callback(self): + """Callback to reset scene resolution""" + return lib.reset_scene_resolution() + + def frame_range_callback(self): + """Callback to reset frame range""" + return lib.reset_frame_range() diff --git a/openpype/hosts/max/api/pipeline.py b/openpype/hosts/max/api/pipeline.py index f8a7b8ea5c1..dacc402318d 100644 --- a/openpype/hosts/max/api/pipeline.py +++ b/openpype/hosts/max/api/pipeline.py @@ -50,6 +50,11 @@ def install(self): self._has_been_setup = True + def context_setting(): + return lib.set_context_setting() + rt.callbacks.addScript(rt.Name('systemPostNew'), + context_setting) + def has_unsaved_changes(self): # TODO: how to get it from 3dsmax? return True diff --git a/openpype/hosts/max/plugins/publish/collect_render.py b/openpype/hosts/max/plugins/publish/collect_render.py index 7c9e311c2fb..63e4108c849 100644 --- a/openpype/hosts/max/plugins/publish/collect_render.py +++ b/openpype/hosts/max/plugins/publish/collect_render.py @@ -61,7 +61,7 @@ def process(self, instance): "plugin": "3dsmax", "frameStart": context.data['frameStart'], "frameEnd": context.data['frameEnd'], - "version": version_int + "version": version_int, } self.log.info("data: {0}".format(data)) instance.data.update(data) diff --git a/openpype/hosts/max/plugins/publish/increment_workfile_version.py b/openpype/hosts/max/plugins/publish/increment_workfile_version.py new file mode 100644 index 00000000000..3dec214f777 --- /dev/null +++ b/openpype/hosts/max/plugins/publish/increment_workfile_version.py @@ -0,0 +1,19 @@ +import pyblish.api +from openpype.lib import version_up +from pymxs import runtime as rt + + +class IncrementWorkfileVersion(pyblish.api.ContextPlugin): + """Increment current workfile version.""" + + order = pyblish.api.IntegratorOrder + 0.9 + label = "Increment Workfile Version" + hosts = ["max"] + families = ["workfile"] + + def process(self, context): + path = context.data["currentFile"] + filepath = version_up(path) + + rt.saveMaxFile(filepath) + self.log.info("Incrementing file version") diff --git a/openpype/hosts/maya/api/commands.py b/openpype/hosts/maya/api/commands.py index 018340d86c7..3e31875fd8c 100644 --- a/openpype/hosts/maya/api/commands.py +++ b/openpype/hosts/maya/api/commands.py @@ -69,7 +69,7 @@ def _resolution_from_document(doc): resolution_width = doc["data"].get("resolution_width") resolution_height = doc["data"].get("resolution_height") - # Make sure both width and heigh are set + # Make sure both width and height are set if resolution_width is None or resolution_height is None: cmds.warning( "No resolution information found for \"{}\"".format(doc["name"]) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index aa1e501578c..22803a2e3a9 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -1367,6 +1367,71 @@ def set_id(node, unique_id, overwrite=False): cmds.setAttr(attr, unique_id, type="string") +def get_attribute(plug, + asString=False, + expandEnvironmentVariables=False, + **kwargs): + """Maya getAttr with some fixes based on `pymel.core.general.getAttr()`. + + Like Pymel getAttr this applies some changes to `maya.cmds.getAttr` + - maya pointlessly returned vector results as a tuple wrapped in a list + (ex. '[(1,2,3)]'). This command unpacks the vector for you. + - when getting a multi-attr, maya would raise an error, but this will + return a list of values for the multi-attr + - added support for getting message attributes by returning the + connections instead + + Note that the asString + expandEnvironmentVariables argument naming + convention matches the `maya.cmds.getAttr` arguments so that it can + act as a direct replacement for it. + + Args: + plug (str): Node's attribute plug as `node.attribute` + asString (bool): Return string value for enum attributes instead + of the index. Note that the return value can be dependent on the + UI language Maya is running in. + expandEnvironmentVariables (bool): Expand any environment variable and + (tilde characters on UNIX) found in string attributes which are + returned. + + Kwargs: + Supports the keyword arguments of `maya.cmds.getAttr` + + Returns: + object: The value of the maya attribute. + + """ + attr_type = cmds.getAttr(plug, type=True) + if asString: + kwargs["asString"] = True + if expandEnvironmentVariables: + kwargs["expandEnvironmentVariables"] = True + try: + res = cmds.getAttr(plug, **kwargs) + except RuntimeError: + if attr_type == "message": + return cmds.listConnections(plug) + + node, attr = plug.split(".", 1) + children = cmds.attributeQuery(attr, node=node, listChildren=True) + if children: + return [ + get_attribute("{}.{}".format(node, child)) + for child in children + ] + + raise + + # Convert vector result wrapped in tuple + if isinstance(res, list) and len(res): + if isinstance(res[0], tuple) and len(res): + if attr_type in {'pointArray', 'vectorArray'}: + return res + return res[0] + + return res + + def set_attribute(attribute, value, node): """Adjust attributes based on the value from the attribute data @@ -1881,6 +1946,12 @@ def remove_other_uv_sets(mesh): cmds.removeMultiInstance(attr, b=True) +def get_node_parent(node): + """Return full path name for parent of node""" + parents = cmds.listRelatives(node, parent=True, fullPath=True) + return parents[0] if parents else None + + def get_id_from_sibling(node, history_only=True): """Return first node id in the history chain that matches this node. @@ -1904,10 +1975,6 @@ def get_id_from_sibling(node, history_only=True): """ - def _get_parent(node): - """Return full path name for parent of node""" - return cmds.listRelatives(node, parent=True, fullPath=True) - node = cmds.ls(node, long=True)[0] # Find all similar nodes in history @@ -1919,8 +1986,8 @@ def _get_parent(node): similar_nodes = [x for x in similar_nodes if x != node] # The node *must be* under the same parent - parent = _get_parent(node) - similar_nodes = [i for i in similar_nodes if _get_parent(i) == parent] + parent = get_node_parent(node) + similar_nodes = [i for i in similar_nodes if get_node_parent(i) == parent] # Check all of the remaining similar nodes and take the first one # with an id and assume it's the original. @@ -2073,23 +2140,13 @@ def get_frame_range(): frame_start = asset["data"].get("frameStart") frame_end = asset["data"].get("frameEnd") - # Backwards compatibility - if frame_start is None or frame_end is None: - frame_start = asset["data"].get("edit_in") - frame_end = asset["data"].get("edit_out") if frame_start is None or frame_end is None: cmds.warning("No edit information found for %s" % asset_name) return - handles = asset["data"].get("handles") or 0 - handle_start = asset["data"].get("handleStart") - if handle_start is None: - handle_start = handles - - handle_end = asset["data"].get("handleEnd") - if handle_end is None: - handle_end = handles + handle_start = asset["data"].get("handleStart") or 0 + handle_end = asset["data"].get("handleEnd") or 0 return { "frameStart": frame_start, @@ -2478,8 +2535,8 @@ def load_capture_preset(data=None): float(value[2]) / 255 ] disp_options[key] = value - else: - disp_options['displayGradient'] = True + elif key == "displayGradient": + disp_options[key] = value options['display_options'] = disp_options @@ -3176,38 +3233,78 @@ def _colormanage(**kwargs): def parent_nodes(nodes, parent=None): # type: (list, str) -> list """Context manager to un-parent provided nodes and return them back.""" - import pymel.core as pm # noqa - parent_node = None - delete_parent = False + def _as_mdagpath(node): + """Return MDagPath for node path.""" + if not node: + return + sel = OpenMaya.MSelectionList() + sel.add(node) + return sel.getDagPath(0) + # We can only parent dag nodes so we ensure input contains only dag nodes + nodes = cmds.ls(nodes, type="dagNode", long=True) + if not nodes: + # opt-out early + yield + return + + parent_node_path = None + delete_parent = False if parent: if not cmds.objExists(parent): - parent_node = pm.createNode("transform", n=parent, ss=False) + parent_node = cmds.createNode("transform", + name=parent, + skipSelect=False) delete_parent = True else: - parent_node = pm.PyNode(parent) + parent_node = parent + parent_node_path = cmds.ls(parent_node, long=True)[0] + + # Store original parents node_parents = [] for node in nodes: - n = pm.PyNode(node) - try: - root = pm.listRelatives(n, parent=1)[0] - except IndexError: - root = None - node_parents.append((n, root)) + node_parent = get_node_parent(node) + node_parents.append((_as_mdagpath(node), _as_mdagpath(node_parent))) + try: - for node in node_parents: - if not parent: - node[0].setParent(world=True) + for node, node_parent in node_parents: + node_parent_path = node_parent.fullPathName() if node_parent else None # noqa + if node_parent_path == parent_node_path: + # Already a child + continue + + if parent_node_path: + cmds.parent(node.fullPathName(), parent_node_path) else: - node[0].setParent(parent_node) + cmds.parent(node.fullPathName(), world=True) + yield finally: - for node in node_parents: - if node[1]: - node[0].setParent(node[1]) + # Reparent to original parents + for node, original_parent in node_parents: + node_path = node.fullPathName() + if not node_path: + # Node must have been deleted + continue + + node_parent_path = get_node_parent(node_path) + + original_parent_path = None + if original_parent: + original_parent_path = original_parent.fullPathName() + if not original_parent_path: + # Original parent node must have been deleted + continue + + if node_parent_path != original_parent_path: + if not original_parent_path: + cmds.parent(node_path, world=True) + else: + cmds.parent(node_path, original_parent_path) + if delete_parent: - pm.delete(parent_node) + cmds.delete(parent_node_path) @contextlib.contextmanager @@ -3675,3 +3772,43 @@ def len_flattened(components): else: n += 1 return n + + +def get_all_children(nodes): + """Return all children of `nodes` including each instanced child. + Using maya.cmds.listRelatives(allDescendents=True) includes only the first + instance. As such, this function acts as an optimal replacement with a + focus on a fast query. + + """ + + sel = OpenMaya.MSelectionList() + traversed = set() + iterator = OpenMaya.MItDag(OpenMaya.MItDag.kDepthFirst) + for node in nodes: + + if node in traversed: + # Ignore if already processed as a child + # before + continue + + sel.clear() + sel.add(node) + dag = sel.getDagPath(0) + + iterator.reset(dag) + # ignore self + iterator.next() # noqa: B305 + while not iterator.isDone(): + + path = iterator.fullPathName() + + if path in traversed: + iterator.prune() + iterator.next() # noqa: B305 + continue + + traversed.add(path) + iterator.next() # noqa: B305 + + return list(traversed) diff --git a/openpype/hosts/maya/api/lib_renderproducts.py b/openpype/hosts/maya/api/lib_renderproducts.py index a54256c59a1..a6bcd003a54 100644 --- a/openpype/hosts/maya/api/lib_renderproducts.py +++ b/openpype/hosts/maya/api/lib_renderproducts.py @@ -339,7 +339,7 @@ def extract_separator(file_prefix): aov_tokens = ["", ""] def match_last(tokens, text): - """regex match the last occurence from a list of tokens""" + """regex match the last occurrence from a list of tokens""" pattern = "(?:.*)({})".format("|".join(tokens)) return re.search(pattern, text, re.IGNORECASE) @@ -857,6 +857,7 @@ def get_render_products(self): if default_ext in {"exr (multichannel)", "exr (deep)"}: default_ext = "exr" + colorspace = lib.get_color_management_output_transform() products = [] # add beauty as default when not disabled @@ -868,7 +869,7 @@ def get_render_products(self): productName="", ext=default_ext, camera=camera, - colorspace=lib.get_color_management_output_transform(), + colorspace=colorspace, multipart=self.multipart ) ) @@ -882,6 +883,7 @@ def get_render_products(self): productName="Alpha", ext=default_ext, camera=camera, + colorspace=colorspace, multipart=self.multipart ) ) @@ -917,7 +919,8 @@ def get_render_products(self): product = RenderProduct(productName=name, ext=default_ext, aov=aov, - camera=camera) + camera=camera, + colorspace=colorspace) products.append(product) # Continue as we've processed this special case AOV continue @@ -929,7 +932,7 @@ def get_render_products(self): ext=default_ext, aov=aov, camera=camera, - colorspace=lib.get_color_management_output_transform() + colorspace=colorspace ) products.append(product) @@ -1051,7 +1054,7 @@ class RenderProductsRedshift(ARenderProducts): def get_files(self, product): # When outputting AOVs we need to replace Redshift specific AOV tokens # with Maya render tokens for generating file sequences. We validate to - # a specific AOV fileprefix so we only need to accout for one + # a specific AOV fileprefix so we only need to account for one # replacement. if not product.multipart and product.driver: file_prefix = self._get_attr(product.driver + ".filePrefix") @@ -1130,6 +1133,7 @@ def get_render_products(self): products = [] light_groups_enabled = False has_beauty_aov = False + colorspace = lib.get_color_management_output_transform() for aov in aovs: enabled = self._get_attr(aov, "enabled") if not enabled: @@ -1173,7 +1177,8 @@ def get_render_products(self): ext=ext, multipart=False, camera=camera, - driver=aov) + driver=aov, + colorspace=colorspace) products.append(product) if light_groups: @@ -1188,7 +1193,8 @@ def get_render_products(self): ext=ext, multipart=False, camera=camera, - driver=aov) + driver=aov, + colorspace=colorspace) products.append(product) # When a Beauty AOV is added manually, it will be rendered as @@ -1204,7 +1210,8 @@ def get_render_products(self): RenderProduct(productName=beauty_name, ext=ext, multipart=self.multipart, - camera=camera)) + camera=camera, + colorspace=colorspace)) return products @@ -1236,6 +1243,8 @@ def get_render_products(self): """ from rfm2.api.displays import get_displays # noqa + colorspace = lib.get_color_management_output_transform() + cameras = [ self.sanitize_camera_name(c) for c in self.get_renderable_cameras() @@ -1302,7 +1311,8 @@ def get_render_products(self): productName=aov_name, ext=extensions, camera=camera, - multipart=True + multipart=True, + colorspace=colorspace ) if has_cryptomatte and matte_enabled: @@ -1311,7 +1321,8 @@ def get_render_products(self): aov=cryptomatte_aov, ext=extensions, camera=camera, - multipart=True + multipart=True, + colorspace=colorspace ) else: # this code should handle the case where no multipart diff --git a/openpype/hosts/maya/api/lib_rendersetup.py b/openpype/hosts/maya/api/lib_rendersetup.py index e616f26e1b4..440ee21a524 100644 --- a/openpype/hosts/maya/api/lib_rendersetup.py +++ b/openpype/hosts/maya/api/lib_rendersetup.py @@ -19,6 +19,8 @@ UniqueOverride ) +from openpype.hosts.maya.api.lib import get_attribute + EXACT_MATCH = 0 PARENT_MATCH = 1 CLIENT_MATCH = 2 @@ -96,9 +98,6 @@ def get_attr_in_layer(node_attr, layer): """ - # Delay pymel import to here because it's slow to load - import pymel.core as pm - def _layer_needs_update(layer): """Return whether layer needs updating.""" # Use `getattr` as e.g. DEFAULT_RENDER_LAYER does not have @@ -125,7 +124,7 @@ def get_default_layer_value(node_attr_): node = history_overrides[-1] if history_overrides else override node_attr_ = node + ".original" - return pm.getAttr(node_attr_, asString=True) + return get_attribute(node_attr_, asString=True) layer = get_rendersetup_layer(layer) rs = renderSetup.instance() @@ -145,7 +144,7 @@ def get_default_layer_value(node_attr_): # we will let it error out. rs.switchToLayer(current_layer) - return pm.getAttr(node_attr, asString=True) + return get_attribute(node_attr, asString=True) overrides = get_attr_overrides(node_attr, layer) default_layer_value = get_default_layer_value(node_attr) @@ -156,7 +155,7 @@ def get_default_layer_value(node_attr_): for match, layer_override, index in overrides: if isinstance(layer_override, AbsOverride): # Absolute override - value = pm.getAttr(layer_override.name() + ".attrValue") + value = get_attribute(layer_override.name() + ".attrValue") if match == EXACT_MATCH: # value = value pass @@ -168,8 +167,8 @@ def get_default_layer_value(node_attr_): elif isinstance(layer_override, RelOverride): # Relative override # Value = Original * Multiply + Offset - multiply = pm.getAttr(layer_override.name() + ".multiply") - offset = pm.getAttr(layer_override.name() + ".offset") + multiply = get_attribute(layer_override.name() + ".multiply") + offset = get_attribute(layer_override.name() + ".offset") if match == EXACT_MATCH: value = value * multiply + offset diff --git a/openpype/hosts/maya/api/workfile_template_builder.py b/openpype/hosts/maya/api/workfile_template_builder.py index 90ab6e21e04..4bee0664ef7 100644 --- a/openpype/hosts/maya/api/workfile_template_builder.py +++ b/openpype/hosts/maya/api/workfile_template_builder.py @@ -33,7 +33,7 @@ def import_template(self, path): get_template_preset implementation) Returns: - bool: Wether the template was succesfully imported or not + bool: Whether the template was successfully imported or not """ if cmds.objExists(PLACEHOLDER_SET): @@ -116,7 +116,7 @@ def _create_placeholder_name(self, placeholder_data): placeholder_name_parts = placeholder_data["builder_type"].split("_") pos = 1 - # add famlily in any + # add family in any placeholder_family = placeholder_data["family"] if placeholder_family: placeholder_name_parts.insert(pos, placeholder_family) diff --git a/openpype/hosts/maya/plugins/create/create_look.py b/openpype/hosts/maya/plugins/create/create_look.py index 44e439fe1f9..51b0b8819a0 100644 --- a/openpype/hosts/maya/plugins/create/create_look.py +++ b/openpype/hosts/maya/plugins/create/create_look.py @@ -12,6 +12,7 @@ class CreateLook(plugin.Creator): family = "look" icon = "paint-brush" make_tx = True + rs_tex = False def __init__(self, *args, **kwargs): super(CreateLook, self).__init__(*args, **kwargs) @@ -20,7 +21,8 @@ def __init__(self, *args, **kwargs): # Whether to automatically convert the textures to .tx upon publish. self.data["maketx"] = self.make_tx - + # Whether to automatically convert the textures to .rstex upon publish. + self.data["rstex"] = self.rs_tex # Enable users to force a copy. # - on Windows is "forceCopy" always changed to `True` because of # windows implementation of hardlinks diff --git a/openpype/hosts/maya/plugins/create/create_review.py b/openpype/hosts/maya/plugins/create/create_review.py index f1b626c06b9..e709239ae78 100644 --- a/openpype/hosts/maya/plugins/create/create_review.py +++ b/openpype/hosts/maya/plugins/create/create_review.py @@ -26,6 +26,7 @@ class CreateReview(plugin.Creator): "alpha cut" ] useMayaTimeline = True + panZoom = False def __init__(self, *args, **kwargs): super(CreateReview, self).__init__(*args, **kwargs) @@ -45,5 +46,6 @@ def __init__(self, *args, **kwargs): data["keepImages"] = self.keepImages data["imagePlane"] = self.imagePlane data["transparency"] = self.transparency + data["panZoom"] = self.panZoom self.data = data diff --git a/openpype/hosts/maya/plugins/load/actions.py b/openpype/hosts/maya/plugins/load/actions.py index 2574624dbb8..ba69debc405 100644 --- a/openpype/hosts/maya/plugins/load/actions.py +++ b/openpype/hosts/maya/plugins/load/actions.py @@ -118,7 +118,7 @@ class ImportMayaLoader(load.LoaderPlugin): "clean_import", label="Clean import", default=False, - help="Should all occurences of cbId be purged?" + help="Should all occurrences of cbId be purged?" ) ] diff --git a/openpype/hosts/maya/plugins/load/load_arnold_standin.py b/openpype/hosts/maya/plugins/load/load_arnold_standin.py index 11a2bd19669..7c3a7323891 100644 --- a/openpype/hosts/maya/plugins/load/load_arnold_standin.py +++ b/openpype/hosts/maya/plugins/load/load_arnold_standin.py @@ -84,7 +84,7 @@ def load(self, context, name, namespace, options): sequence = is_sequence(os.listdir(os.path.dirname(self.fname))) cmds.setAttr(standin_shape + ".useFrameExtension", sequence) - nodes = [root, standin] + nodes = [root, standin, standin_shape] if operator is not None: nodes.append(operator) self[:] = nodes @@ -180,10 +180,10 @@ def update(self, container, representation): proxy_basename, proxy_path = self._get_proxy_path(path) # Whether there is proxy or so, we still update the string operator. - # If no proxy exists, the string operator wont replace anything. + # If no proxy exists, the string operator won't replace anything. cmds.setAttr( string_replace_operator + ".match", - "resources/" + proxy_basename, + proxy_basename, type="string" ) cmds.setAttr( diff --git a/openpype/hosts/maya/plugins/load/load_audio.py b/openpype/hosts/maya/plugins/load/load_audio.py index 6f60cb57265..9e7fd96bdb7 100644 --- a/openpype/hosts/maya/plugins/load/load_audio.py +++ b/openpype/hosts/maya/plugins/load/load_audio.py @@ -11,7 +11,7 @@ get_representation_path, ) from openpype.hosts.maya.api.pipeline import containerise -from openpype.hosts.maya.api.lib import unique_namespace +from openpype.hosts.maya.api.lib import unique_namespace, get_container_members class AudioLoader(load.LoaderPlugin): @@ -52,17 +52,15 @@ def load(self, context, name, namespace, data): ) def update(self, container, representation): - import pymel.core as pm - audio_node = None - for node in pm.PyNode(container["objectName"]).members(): - if node.nodeType() == "audio": - audio_node = node + members = get_container_members(container) + audio_nodes = cmds.ls(members, type="audio") - assert audio_node is not None, "Audio node not found." + assert audio_nodes is not None, "Audio node not found." + audio_node = audio_nodes[0] path = get_representation_path(representation) - audio_node.filename.set(path) + cmds.setAttr("{}.filename".format(audio_node), path, type="string") cmds.setAttr( container["objectName"] + ".representation", str(representation["_id"]), @@ -80,8 +78,12 @@ def update(self, container, representation): asset = get_asset_by_id( project_name, subset["parent"], fields=["parent"] ) - audio_node.sourceStart.set(1 - asset["data"]["frameStart"]) - audio_node.sourceEnd.set(asset["data"]["frameEnd"]) + + source_start = 1 - asset["data"]["frameStart"] + source_end = asset["data"]["frameEnd"] + + cmds.setAttr("{}.sourceStart".format(audio_node), source_start) + cmds.setAttr("{}.sourceEnd".format(audio_node), source_end) def switch(self, container, representation): self.update(container, representation) diff --git a/openpype/hosts/maya/plugins/load/load_gpucache.py b/openpype/hosts/maya/plugins/load/load_gpucache.py index 07e5734f43d..794b21eb5d5 100644 --- a/openpype/hosts/maya/plugins/load/load_gpucache.py +++ b/openpype/hosts/maya/plugins/load/load_gpucache.py @@ -1,5 +1,9 @@ import os +import maya.cmds as cmds + +from openpype.hosts.maya.api.pipeline import containerise +from openpype.hosts.maya.api.lib import unique_namespace from openpype.pipeline import ( load, get_representation_path @@ -11,19 +15,15 @@ class GpuCacheLoader(load.LoaderPlugin): """Load Alembic as gpuCache""" families = ["model", "animation", "proxyAbc", "pointcache"] - representations = ["abc"] + representations = ["abc", "gpu_cache"] - label = "Import Gpu Cache" + label = "Load Gpu Cache" order = -5 icon = "code-fork" color = "orange" def load(self, context, name, namespace, data): - import maya.cmds as cmds - from openpype.hosts.maya.api.pipeline import containerise - from openpype.hosts.maya.api.lib import unique_namespace - asset = context['asset']['name'] namespace = namespace or unique_namespace( asset + "_", @@ -42,10 +42,9 @@ def load(self, context, name, namespace, data): c = colors.get('model') if c is not None: cmds.setAttr(root + ".useOutlinerColor", 1) - cmds.setAttr(root + ".outlinerColor", - (float(c[0])/255), - (float(c[1])/255), - (float(c[2])/255) + cmds.setAttr( + root + ".outlinerColor", + (float(c[0]) / 255), (float(c[1]) / 255), (float(c[2]) / 255) ) # Create transform with shape @@ -74,9 +73,6 @@ def load(self, context, name, namespace, data): loader=self.__class__.__name__) def update(self, container, representation): - - import maya.cmds as cmds - path = get_representation_path(representation) # Update the cache @@ -96,7 +92,6 @@ def switch(self, container, representation): self.update(container, representation) def remove(self, container): - import maya.cmds as cmds members = cmds.sets(container['objectName'], query=True) cmds.lockNode(members, lock=False) cmds.delete([container['objectName']] + members) diff --git a/openpype/hosts/maya/plugins/load/load_image_plane.py b/openpype/hosts/maya/plugins/load/load_image_plane.py index 6421f3ffe2c..bf13708e9b6 100644 --- a/openpype/hosts/maya/plugins/load/load_image_plane.py +++ b/openpype/hosts/maya/plugins/load/load_image_plane.py @@ -11,11 +11,26 @@ get_representation_path ) from openpype.hosts.maya.api.pipeline import containerise -from openpype.hosts.maya.api.lib import unique_namespace +from openpype.hosts.maya.api.lib import ( + unique_namespace, + namespaced, + pairwise, + get_container_members +) from maya import cmds +def disconnect_inputs(plug): + overrides = cmds.listConnections(plug, + source=True, + destination=False, + plugs=True, + connections=True) or [] + for dest, src in pairwise(overrides): + cmds.disconnectAttr(src, dest) + + class CameraWindow(QtWidgets.QDialog): def __init__(self, cameras): @@ -74,6 +89,7 @@ def on_cancel_pressed(self): self.camera = None self.close() + class ImagePlaneLoader(load.LoaderPlugin): """Specific loader of plate for image planes on selected camera.""" @@ -84,9 +100,7 @@ class ImagePlaneLoader(load.LoaderPlugin): color = "orange" def load(self, context, name, namespace, data, options=None): - import pymel.core as pm - new_nodes = [] image_plane_depth = 1000 asset = context['asset']['name'] namespace = namespace or unique_namespace( @@ -96,16 +110,20 @@ def load(self, context, name, namespace, data, options=None): ) # Get camera from user selection. - camera = None # is_static_image_plane = None # is_in_all_views = None - if data: - camera = pm.PyNode(data.get("camera")) + camera = data.get("camera") if data else None if not camera: - cameras = pm.ls(type="camera") - camera_names = {x.getParent().name(): x for x in cameras} - camera_names["Create new camera."] = "create_camera" + cameras = cmds.ls(type="camera") + + # Cameras by names + camera_names = {} + for camera in cameras: + parent = cmds.listRelatives(camera, parent=True, path=True)[0] + camera_names[parent] = camera + + camera_names["Create new camera."] = "create-camera" window = CameraWindow(camera_names.keys()) window.exec_() # Skip if no camera was selected (Dialog was closed) @@ -113,43 +131,48 @@ def load(self, context, name, namespace, data, options=None): return camera = camera_names[window.camera] - if camera == "create_camera": - camera = pm.createNode("camera") + if camera == "create-camera": + camera = cmds.createNode("camera") if camera is None: return try: - camera.displayResolution.set(1) - camera.farClipPlane.set(image_plane_depth * 10) + cmds.setAttr("{}.displayResolution".format(camera), True) + cmds.setAttr("{}.farClipPlane".format(camera), + image_plane_depth * 10) except RuntimeError: pass # Create image plane - image_plane_transform, image_plane_shape = pm.imagePlane( - fileName=context["representation"]["data"]["path"], - camera=camera) - image_plane_shape.depth.set(image_plane_depth) - - - start_frame = pm.playbackOptions(q=True, min=True) - end_frame = pm.playbackOptions(q=True, max=True) - - image_plane_shape.frameOffset.set(0) - image_plane_shape.frameIn.set(start_frame) - image_plane_shape.frameOut.set(end_frame) - image_plane_shape.frameCache.set(end_frame) - image_plane_shape.useFrameExtension.set(1) + with namespaced(namespace): + # Create inside the namespace + image_plane_transform, image_plane_shape = cmds.imagePlane( + fileName=context["representation"]["data"]["path"], + camera=camera + ) + start_frame = cmds.playbackOptions(query=True, min=True) + end_frame = cmds.playbackOptions(query=True, max=True) + + for attr, value in { + "depth": image_plane_depth, + "frameOffset": 0, + "frameIn": start_frame, + "frameOut": end_frame, + "frameCache": end_frame, + "useFrameExtension": True + }.items(): + plug = "{}.{}".format(image_plane_shape, attr) + cmds.setAttr(plug, value) movie_representations = ["mov", "preview"] if context["representation"]["name"] in movie_representations: - # Need to get "type" by string, because its a method as well. - pm.Attribute(image_plane_shape + ".type").set(2) + cmds.setAttr(image_plane_shape + ".type", 2) # Ask user whether to use sequence or still image. if context["representation"]["name"] == "exr": # Ensure OpenEXRLoader plugin is loaded. - pm.loadPlugin("OpenEXRLoader.mll", quiet=True) + cmds.loadPlugin("OpenEXRLoader", quiet=True) message = ( "Hold image sequence on first frame?" @@ -161,32 +184,18 @@ def load(self, context, name, namespace, data, options=None): None, "Frame Hold.", message, - QtWidgets.QMessageBox.Ok, - QtWidgets.QMessageBox.Cancel + QtWidgets.QMessageBox.Yes, + QtWidgets.QMessageBox.No ) - if reply == QtWidgets.QMessageBox.Ok: - # find the input and output of frame extension - expressions = image_plane_shape.frameExtension.inputs() - frame_ext_output = image_plane_shape.frameExtension.outputs() - if expressions: - # the "time1" node is non-deletable attr - # in Maya, use disconnectAttr instead - pm.disconnectAttr(expressions, frame_ext_output) - - if not image_plane_shape.frameExtension.isFreeToChange(): - raise RuntimeError("Can't set frame extension for {}".format(image_plane_shape)) # noqa - # get the node of time instead and set the time for it. - image_plane_shape.frameExtension.set(start_frame) - - new_nodes.extend( - [ - image_plane_transform.longName().split("|")[-1], - image_plane_shape.longName().split("|")[-1] - ] - ) + if reply == QtWidgets.QMessageBox.Yes: + frame_extension_plug = "{}.frameExtension".format(image_plane_shape) # noqa - for node in new_nodes: - pm.rename(node, "{}:{}".format(namespace, node)) + # Remove current frame expression + disconnect_inputs(frame_extension_plug) + + cmds.setAttr(frame_extension_plug, start_frame) + + new_nodes = [image_plane_transform, image_plane_shape] return containerise( name=name, @@ -197,21 +206,19 @@ def load(self, context, name, namespace, data, options=None): ) def update(self, container, representation): - import pymel.core as pm - image_plane_shape = None - for node in pm.PyNode(container["objectName"]).members(): - if node.nodeType() == "imagePlane": - image_plane_shape = node - assert image_plane_shape is not None, "Image plane not found." + members = get_container_members(container) + image_planes = cmds.ls(members, type="imagePlane") + assert image_planes, "Image plane not found." + image_plane_shape = image_planes[0] path = get_representation_path(representation) - image_plane_shape.imageName.set(path) - cmds.setAttr( - container["objectName"] + ".representation", - str(representation["_id"]), - type="string" - ) + cmds.setAttr("{}.imageName".format(image_plane_shape), + path, + type="string") + cmds.setAttr("{}.representation".format(container["objectName"]), + str(representation["_id"]), + type="string") # Set frame range. project_name = legacy_io.active_project() @@ -227,10 +234,14 @@ def update(self, container, representation): start_frame = asset["data"]["frameStart"] end_frame = asset["data"]["frameEnd"] - image_plane_shape.frameOffset.set(0) - image_plane_shape.frameIn.set(start_frame) - image_plane_shape.frameOut.set(end_frame) - image_plane_shape.frameCache.set(end_frame) + for attr, value in { + "frameOffset": 0, + "frameIn": start_frame, + "frameOut": end_frame, + "frameCache": end_frame + }: + plug = "{}.{}".format(image_plane_shape, attr) + cmds.setAttr(plug, value) def switch(self, container, representation): self.update(container, representation) diff --git a/openpype/hosts/maya/plugins/load/load_reference.py b/openpype/hosts/maya/plugins/load/load_reference.py index d93702a16d6..461f4258aad 100644 --- a/openpype/hosts/maya/plugins/load/load_reference.py +++ b/openpype/hosts/maya/plugins/load/load_reference.py @@ -1,4 +1,6 @@ import os +import difflib +import contextlib from maya import cmds from openpype.settings import get_project_settings @@ -8,7 +10,83 @@ get_legacy_creator_by_name, ) import openpype.hosts.maya.api.plugin -from openpype.hosts.maya.api.lib import maintained_selection +from openpype.hosts.maya.api.lib import ( + maintained_selection, + get_container_members, + parent_nodes +) + + +@contextlib.contextmanager +def preserve_modelpanel_cameras(container, log=None): + """Preserve camera members of container in the modelPanels. + + This is used to ensure a camera remains in the modelPanels after updating + to a new version. + + """ + + # Get the modelPanels that used the old camera + members = get_container_members(container) + old_cameras = set(cmds.ls(members, type="camera", long=True)) + if not old_cameras: + # No need to manage anything + yield + return + + panel_cameras = {} + for panel in cmds.getPanel(type="modelPanel"): + cam = cmds.ls(cmds.modelPanel(panel, query=True, camera=True), + long=True) + + # Often but not always maya returns the transform from the + # modelPanel as opposed to the camera shape, so we convert it + # to explicitly be the camera shape + if cmds.nodeType(cam) != "camera": + cam = cmds.listRelatives(cam, + children=True, + fullPath=True, + type="camera")[0] + if cam in old_cameras: + panel_cameras[panel] = cam + + if not panel_cameras: + # No need to manage anything + yield + return + + try: + yield + finally: + new_members = get_container_members(container) + new_cameras = set(cmds.ls(new_members, type="camera", long=True)) + if not new_cameras: + return + + for panel, cam_name in panel_cameras.items(): + new_camera = None + if cam_name in new_cameras: + new_camera = cam_name + elif len(new_cameras) == 1: + new_camera = next(iter(new_cameras)) + else: + # Multiple cameras in the updated container but not an exact + # match detected by name. Find the closest match + matches = difflib.get_close_matches(word=cam_name, + possibilities=new_cameras, + n=1) + if matches: + new_camera = matches[0] # best match + if log: + log.info("Camera in '{}' restored with " + "closest match camera: {} (before: {})" + .format(panel, new_camera, cam_name)) + + if not new_camera: + # Unable to find the camera to re-apply in the modelpanel + continue + + cmds.modelPanel(panel, edit=True, camera=new_camera) class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): @@ -41,7 +119,6 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): def process_reference(self, context, name, namespace, options): import maya.cmds as cmds - import pymel.core as pm try: family = context["representation"]["context"]["family"] @@ -68,7 +145,10 @@ def process_reference(self, context, name, namespace, options): new_nodes = (list(set(nodes) - set(shapes))) - current_namespace = pm.namespaceInfo(currentNamespace=True) + # if there are cameras, try to lock their transforms + self._lock_camera_transforms(new_nodes) + + current_namespace = cmds.namespaceInfo(currentNamespace=True) if current_namespace != ":": group_name = current_namespace + ":" + group_name @@ -78,37 +158,29 @@ def process_reference(self, context, name, namespace, options): self[:] = new_nodes if attach_to_root: - group_node = pm.PyNode(group_name) - roots = set() - - for node in new_nodes: - try: - roots.add(pm.PyNode(node).getAllParents()[-2]) - except: # noqa: E722 - pass - - if family not in ["layout", "setdress", - "mayaAscii", "mayaScene"]: - for root in roots: - root.setParent(world=True) + roots = cmds.listRelatives(group_name, + children=True, + fullPath=True) or [] - group_node.zeroTransformPivots() - for root in roots: - root.setParent(group_node) + if family not in {"layout", "setdress", + "mayaAscii", "mayaScene"}: + # QUESTION Why do we need to exclude these families? + with parent_nodes(roots, parent=None): + cmds.xform(group_name, zeroTransformPivots=True) - cmds.setAttr(group_name + ".displayHandle", 1) + cmds.setAttr("{}.displayHandle".format(group_name), 1) settings = get_project_settings(os.environ['AVALON_PROJECT']) colors = settings['maya']['load']['colors'] c = colors.get(family) if c is not None: - group_node.useOutlinerColor.set(1) - group_node.outlinerColor.set( - (float(c[0]) / 255), - (float(c[1]) / 255), - (float(c[2]) / 255)) + cmds.setAttr("{}.useOutlinerColor".format(group_name), 1) + cmds.setAttr("{}.outlinerColor".format(group_name), + (float(c[0]) / 255), + (float(c[1]) / 255), + (float(c[2]) / 255)) - cmds.setAttr(group_name + ".displayHandle", 1) + cmds.setAttr("{}.displayHandle".format(group_name), 1) # get bounding box bbox = cmds.exactWorldBoundingBox(group_name) # get pivot position on world space @@ -122,20 +194,30 @@ def process_reference(self, context, name, namespace, options): cy = cy + pivot[1] cz = cz + pivot[2] # set selection handle offset to center of bounding box - cmds.setAttr(group_name + ".selectHandleX", cx) - cmds.setAttr(group_name + ".selectHandleY", cy) - cmds.setAttr(group_name + ".selectHandleZ", cz) + cmds.setAttr("{}.selectHandleX".format(group_name), cx) + cmds.setAttr("{}.selectHandleY".format(group_name), cy) + cmds.setAttr("{}.selectHandleZ".format(group_name), cz) if family == "rig": self._post_process_rig(name, namespace, context, options) else: if "translate" in options: - cmds.setAttr(group_name + ".t", *options["translate"]) + cmds.setAttr("{}.translate".format(group_name), + *options["translate"]) return new_nodes def switch(self, container, representation): self.update(container, representation) + def update(self, container, representation): + with preserve_modelpanel_cameras(container, log=self.log): + super(ReferenceLoader, self).update(container, representation) + + # We also want to lock camera transforms on any new cameras in the + # reference or for a camera which might have changed names. + members = get_container_members(container) + self._lock_camera_transforms(members) + def _post_process_rig(self, name, namespace, context, options): output = next((node for node in self if @@ -168,3 +250,18 @@ def _post_process_rig(self, name, namespace, context, options): options={"useSelection": True}, data={"dependencies": dependency} ) + + def _lock_camera_transforms(self, nodes): + cameras = cmds.ls(nodes, type="camera") + if not cameras: + return + + # Check the Maya version, lockTransform has been introduced since + # Maya 2016.5 Ext 2 + version = int(cmds.about(version=True)) + if version >= 2016: + for camera in cameras: + cmds.camera(camera, edit=True, lockTransform=True) + else: + self.log.warning("This version of Maya does not support locking of" + " transforms of cameras.") diff --git a/openpype/hosts/maya/plugins/publish/collect_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/collect_arnold_scene_source.py index 0415808b7ae..0845f653b13 100644 --- a/openpype/hosts/maya/plugins/publish/collect_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/collect_arnold_scene_source.py @@ -1,6 +1,7 @@ from maya import cmds import pyblish.api +from openpype.hosts.maya.api.lib import get_all_children class CollectArnoldSceneSource(pyblish.api.InstancePlugin): @@ -21,18 +22,21 @@ def process(self, instance): self.log.warning("Skipped empty instance: \"%s\" " % objset) continue if objset.endswith("content_SET"): - instance.data["setMembers"] = cmds.ls(members, long=True) - self.log.debug("content members: {}".format(members)) + members = cmds.ls(members, long=True) + children = get_all_children(members) + instance.data["contentMembers"] = children + self.log.debug("content members: {}".format(children)) elif objset.endswith("proxy_SET"): - instance.data["proxy"] = cmds.ls(members, long=True) - self.log.debug("proxy members: {}".format(members)) + set_members = get_all_children(cmds.ls(members, long=True)) + instance.data["proxy"] = set_members + self.log.debug("proxy members: {}".format(set_members)) # Use camera in object set if present else default to render globals # camera. cameras = cmds.ls(type="camera", long=True) renderable = [c for c in cameras if cmds.getAttr("%s.renderable" % c)] camera = renderable[0] - for node in instance.data["setMembers"]: + for node in instance.data["contentMembers"]: camera_shapes = cmds.listRelatives( node, shapes=True, type="camera" ) diff --git a/openpype/hosts/maya/plugins/publish/collect_instances.py b/openpype/hosts/maya/plugins/publish/collect_instances.py index c5946265698..87a4de162d3 100644 --- a/openpype/hosts/maya/plugins/publish/collect_instances.py +++ b/openpype/hosts/maya/plugins/publish/collect_instances.py @@ -1,48 +1,8 @@ from maya import cmds -import maya.api.OpenMaya as om import pyblish.api import json - - -def get_all_children(nodes): - """Return all children of `nodes` including each instanced child. - Using maya.cmds.listRelatives(allDescendents=True) includes only the first - instance. As such, this function acts as an optimal replacement with a - focus on a fast query. - - """ - - sel = om.MSelectionList() - traversed = set() - iterator = om.MItDag(om.MItDag.kDepthFirst) - for node in nodes: - - if node in traversed: - # Ignore if already processed as a child - # before - continue - - sel.clear() - sel.add(node) - dag = sel.getDagPath(0) - - iterator.reset(dag) - # ignore self - iterator.next() # noqa: B305 - while not iterator.isDone(): - - path = iterator.fullPathName() - - if path in traversed: - iterator.prune() - iterator.next() # noqa: B305 - continue - - traversed.add(path) - iterator.next() # noqa: B305 - - return list(traversed) +from openpype.hosts.maya.api.lib import get_all_children class CollectInstances(pyblish.api.ContextPlugin): @@ -149,13 +109,6 @@ def process(self, context): # Append start frame and end frame to label if present if "frameStart" and "frameEnd" in data: - - # Backwards compatibility for 'handles' data - if "handles" in data: - data["handleStart"] = data["handles"] - data["handleEnd"] = data["handles"] - data.pop('handles') - # Take handles from context if not set locally on the instance for key in ["handleStart", "handleEnd"]: if key not in data: diff --git a/openpype/hosts/maya/plugins/publish/collect_look.py b/openpype/hosts/maya/plugins/publish/collect_look.py index b01160a1c05..287ddc228bb 100644 --- a/openpype/hosts/maya/plugins/publish/collect_look.py +++ b/openpype/hosts/maya/plugins/publish/collect_look.py @@ -556,7 +556,7 @@ def collect_attributes_changed(self, instance): continue if cmds.getAttr(attribute, type=True) == "message": continue - node_attributes[attr] = cmds.getAttr(attribute) + node_attributes[attr] = cmds.getAttr(attribute, asString=True) # Only include if there are any properties we care about if not node_attributes: continue diff --git a/openpype/hosts/maya/plugins/publish/collect_multiverse_look.py b/openpype/hosts/maya/plugins/publish/collect_multiverse_look.py index a7cb14855b2..33fc7a025f8 100644 --- a/openpype/hosts/maya/plugins/publish/collect_multiverse_look.py +++ b/openpype/hosts/maya/plugins/publish/collect_multiverse_look.py @@ -255,7 +255,7 @@ class CollectMultiverseLookData(pyblish.api.InstancePlugin): Searches through the overrides finding all material overrides. From there it extracts the shading group and then finds all texture files in the shading group network. It also checks for mipmap versions of texture files - and adds them to the resouces to get published. + and adds them to the resources to get published. """ diff --git a/openpype/hosts/maya/plugins/publish/collect_review.py b/openpype/hosts/maya/plugins/publish/collect_review.py index 548b1c996aa..0b039880023 100644 --- a/openpype/hosts/maya/plugins/publish/collect_review.py +++ b/openpype/hosts/maya/plugins/publish/collect_review.py @@ -1,10 +1,10 @@ from maya import cmds, mel -import pymel.core as pm import pyblish.api from openpype.client import get_subset_by_name -from openpype.pipeline import legacy_io +from openpype.pipeline import legacy_io, KnownPublishError +from openpype.hosts.maya.api.lib import get_attribute_input class CollectReview(pyblish.api.InstancePlugin): @@ -15,7 +15,6 @@ class CollectReview(pyblish.api.InstancePlugin): order = pyblish.api.CollectorOrder + 0.3 label = 'Collect Review Data' families = ["review"] - legacy = True def process(self, instance): @@ -35,55 +34,67 @@ def process(self, instance): self.log.debug('members: {}'.format(members)) # validate required settings - assert len(cameras) == 1, "Not a single camera found in extraction" + if len(cameras) == 0: + raise KnownPublishError("No camera found in review " + "instance: {}".format(instance)) + elif len(cameras) > 2: + raise KnownPublishError( + "Only a single camera is allowed for a review instance but " + "more than one camera found in review instance: {}. " + "Cameras found: {}".format(instance, ", ".join(cameras))) + camera = cameras[0] self.log.debug('camera: {}'.format(camera)) - objectset = instance.context.data['objectsets'] - - reviewable_subset = None - reviewable_subset = list(set(members) & set(objectset)) - if reviewable_subset: - assert len(reviewable_subset) <= 1, "Multiple subsets for review" - self.log.debug('subset for review: {}'.format(reviewable_subset)) - - i = 0 - for inst in instance.context: - - self.log.debug('filtering {}'.format(inst)) - data = instance.context[i].data - - if inst.name != reviewable_subset[0]: - self.log.debug('subset name does not match {}'.format( - reviewable_subset[0])) - i += 1 - continue - - if data.get('families'): - data['families'].append('review') - else: - data['families'] = ['review'] - self.log.debug('adding review family to {}'.format( - reviewable_subset)) - data['review_camera'] = camera - # data["publish"] = False - data['frameStartFtrack'] = instance.data["frameStartHandle"] - data['frameEndFtrack'] = instance.data["frameEndHandle"] - data['frameStartHandle'] = instance.data["frameStartHandle"] - data['frameEndHandle'] = instance.data["frameEndHandle"] - data["frameStart"] = instance.data["frameStart"] - data["frameEnd"] = instance.data["frameEnd"] - data['handles'] = instance.data.get('handles', None) - data['step'] = instance.data['step'] - data['fps'] = instance.data['fps'] - data['review_width'] = instance.data['review_width'] - data['review_height'] = instance.data['review_height'] - data["isolate"] = instance.data["isolate"] - cmds.setAttr(str(instance) + '.active', 1) - self.log.debug('data {}'.format(instance.context[i].data)) - instance.context[i].data.update(data) - instance.data['remove'] = True - self.log.debug('isntance data {}'.format(instance.data)) + context = instance.context + objectset = context.data['objectsets'] + + reviewable_subsets = list(set(members) & set(objectset)) + if reviewable_subsets: + if len(reviewable_subsets) > 1: + raise KnownPublishError( + "Multiple attached subsets for review are not supported. " + "Attached: {}".format(", ".join(reviewable_subsets)) + ) + + reviewable_subset = reviewable_subsets[0] + self.log.debug( + "Subset attached to review: {}".format(reviewable_subset) + ) + + # Find the relevant publishing instance in the current context + reviewable_inst = next(inst for inst in context + if inst.name == reviewable_subset) + data = reviewable_inst.data + + self.log.debug( + 'Adding review family to {}'.format(reviewable_subset) + ) + if data.get('families'): + data['families'].append('review') + else: + data['families'] = ['review'] + + data['review_camera'] = camera + data['frameStartFtrack'] = instance.data["frameStartHandle"] + data['frameEndFtrack'] = instance.data["frameEndHandle"] + data['frameStartHandle'] = instance.data["frameStartHandle"] + data['frameEndHandle'] = instance.data["frameEndHandle"] + data["frameStart"] = instance.data["frameStart"] + data["frameEnd"] = instance.data["frameEnd"] + data['step'] = instance.data['step'] + data['fps'] = instance.data['fps'] + data['review_width'] = instance.data['review_width'] + data['review_height'] = instance.data['review_height'] + data["isolate"] = instance.data["isolate"] + data["panZoom"] = instance.data.get("panZoom", False) + data["panel"] = instance.data["panel"] + + # The review instance must be active + cmds.setAttr(str(instance) + '.active', 1) + + instance.data['remove'] = True + else: legacy_subset_name = task + 'Review' asset_doc = instance.context.data['assetEntity'] @@ -105,42 +116,59 @@ def process(self, instance): instance.data["frameEndHandle"] # make ftrack publishable - instance.data["families"] = ['ftrack'] + instance.data.setdefault("families", []).append('ftrack') cmds.setAttr(str(instance) + '.active', 1) # Collect audio playback_slider = mel.eval('$tmpVar=$gPlayBackSlider') - audio_name = cmds.timeControl(playback_slider, q=True, s=True) + audio_name = cmds.timeControl(playback_slider, + query=True, + sound=True) display_sounds = cmds.timeControl( - playback_slider, q=True, displaySound=True + playback_slider, query=True, displaySound=True ) - audio_nodes = [] + def get_audio_node_data(node): + return { + "offset": cmds.getAttr("{}.offset".format(node)), + "filename": cmds.getAttr("{}.filename".format(node)) + } + + audio_data = [] if audio_name: - audio_nodes.append(pm.PyNode(audio_name)) + audio_data.append(get_audio_node_data(audio_name)) - if not audio_name and display_sounds: - start_frame = int(pm.playbackOptions(q=True, min=True)) - end_frame = float(pm.playbackOptions(q=True, max=True)) - frame_range = range(int(start_frame), int(end_frame)) + elif display_sounds: + start_frame = int(cmds.playbackOptions(query=True, min=True)) + end_frame = int(cmds.playbackOptions(query=True, max=True)) - for node in pm.ls(type="audio"): + for node in cmds.ls(type="audio"): # Check if frame range and audio range intersections, # for whether to include this audio node or not. - start_audio = node.offset.get() - end_audio = node.offset.get() + node.duration.get() - audio_range = range(int(start_audio), int(end_audio)) - - if bool(set(frame_range).intersection(audio_range)): - audio_nodes.append(node) - - instance.data["audio"] = [] - for node in audio_nodes: - instance.data["audio"].append( - { - "offset": node.offset.get(), - "filename": node.filename.get() - } - ) + duration = cmds.getAttr("{}.duration".format(node)) + start_audio = cmds.getAttr("{}.offset".format(node)) + end_audio = start_audio + duration + + if start_audio <= end_frame and end_audio > start_frame: + audio_data.append(get_audio_node_data(node)) + + instance.data["audio"] = audio_data + + # Collect focal length. + attr = camera + ".focalLength" + if get_attribute_input(attr): + start = instance.data["frameStart"] + end = instance.data["frameEnd"] + 1 + focal_length = [ + cmds.getAttr(attr, time=t) for t in range(int(start), int(end)) + ] + else: + focal_length = cmds.getAttr(attr) + + key = "focalLength" + try: + instance.data["burninDataMembers"][key] = focal_length + except KeyError: + instance.data["burninDataMembers"] = {key: focal_length} diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index 924ac58c403..14bcc71da6c 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -1,12 +1,12 @@ import os +from collections import defaultdict +import json from maya import cmds import arnold from openpype.pipeline import publish -from openpype.hosts.maya.api.lib import ( - maintained_selection, attribute_values, delete_after -) +from openpype.hosts.maya.api import lib class ExtractArnoldSceneSource(publish.Extractor): @@ -19,8 +19,7 @@ class ExtractArnoldSceneSource(publish.Extractor): def process(self, instance): staging_dir = self.staging_dir(instance) - filename = "{}.ass".format(instance.name) - file_path = os.path.join(staging_dir, filename) + file_path = os.path.join(staging_dir, "{}.ass".format(instance.name)) # Mask mask = arnold.AI_NODE_ALL @@ -71,8 +70,8 @@ def process(self, instance): "mask": mask } - filenames = self._extract( - instance.data["setMembers"], attribute_data, kwargs + filenames, nodes_by_id = self._extract( + instance.data["contentMembers"], attribute_data, kwargs ) if "representations" not in instance.data: @@ -88,6 +87,19 @@ def process(self, instance): instance.data["representations"].append(representation) + json_path = os.path.join(staging_dir, "{}.json".format(instance.name)) + with open(json_path, "w") as f: + json.dump(nodes_by_id, f) + + representation = { + "name": "json", + "ext": "json", + "files": os.path.basename(json_path), + "stagingDir": staging_dir + } + + instance.data["representations"].append(representation) + self.log.info( "Extracted instance {} to: {}".format(instance.name, staging_dir) ) @@ -97,7 +109,7 @@ def process(self, instance): return kwargs["filename"] = file_path.replace(".ass", "_proxy.ass") - filenames = self._extract( + filenames, _ = self._extract( instance.data["proxy"], attribute_data, kwargs ) @@ -113,34 +125,60 @@ def process(self, instance): instance.data["representations"].append(representation) def _extract(self, nodes, attribute_data, kwargs): - self.log.info("Writing: " + kwargs["filename"]) + self.log.info( + "Writing {} with:\n{}".format(kwargs["filename"], kwargs) + ) filenames = [] + nodes_by_id = defaultdict(list) # Duplicating nodes so they are direct children of the world. This # makes the hierarchy of any exported ass file the same. - with delete_after() as delete_bin: + with lib.delete_after() as delete_bin: duplicate_nodes = [] for node in nodes: + # Only interested in transforms: + if cmds.nodeType(node) != "transform": + continue + + # Only interested in transforms with shapes. + shapes = cmds.listRelatives( + node, shapes=True, noIntermediate=True + ) + if not shapes: + continue + duplicate_transform = cmds.duplicate(node)[0] - # Discard the children. - shapes = cmds.listRelatives(duplicate_transform, shapes=True) + if cmds.listRelatives(duplicate_transform, parent=True): + duplicate_transform = cmds.parent( + duplicate_transform, world=True + )[0] + + basename = node.rsplit("|", 1)[-1].rsplit(":", 1)[-1] + duplicate_transform = cmds.rename( + duplicate_transform, basename + ) + + # Discard children nodes that are not shapes + shapes = cmds.listRelatives( + duplicate_transform, shapes=True, fullPath=True + ) children = cmds.listRelatives( - duplicate_transform, children=True + duplicate_transform, children=True, fullPath=True ) cmds.delete(set(children) - set(shapes)) - duplicate_transform = cmds.parent( - duplicate_transform, world=True - )[0] - - cmds.rename(duplicate_transform, node.split("|")[-1]) - duplicate_transform = "|" + node.split("|")[-1] - duplicate_nodes.append(duplicate_transform) + duplicate_nodes.extend(shapes) delete_bin.append(duplicate_transform) - with attribute_values(attribute_data): - with maintained_selection(): + # Copy cbId to mtoa_constant. + for node in duplicate_nodes: + # Converting Maya hierarchy separator "|" to Arnold + # separator "/". + nodes_by_id[lib.get_id(node)].append(node.replace("|", "/")) + + with lib.attribute_values(attribute_data): + with lib.maintained_selection(): self.log.info( "Writing: {}".format(duplicate_nodes) ) @@ -157,4 +195,4 @@ def _extract(self, nodes, attribute_data, kwargs): self.log.info("Exported: {}".format(filenames)) - return filenames + return filenames, nodes_by_id diff --git a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py new file mode 100644 index 00000000000..422f5ad019b --- /dev/null +++ b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py @@ -0,0 +1,65 @@ +import json + +from maya import cmds + +from openpype.pipeline import publish + + +class ExtractGPUCache(publish.Extractor): + """Extract the content of the instance to a GPU cache file.""" + + label = "GPU Cache" + hosts = ["maya"] + families = ["model", "animation", "pointcache"] + step = 1.0 + stepSave = 1 + optimize = True + optimizationThreshold = 40000 + optimizeAnimationsForMotionBlur = True + writeMaterials = True + useBaseTessellation = True + + def process(self, instance): + cmds.loadPlugin("gpuCache", quiet=True) + + staging_dir = self.staging_dir(instance) + filename = "{}_gpu_cache".format(instance.name) + + # Write out GPU cache file. + kwargs = { + "directory": staging_dir, + "fileName": filename, + "saveMultipleFiles": False, + "simulationRate": self.step, + "sampleMultiplier": self.stepSave, + "optimize": self.optimize, + "optimizationThreshold": self.optimizationThreshold, + "optimizeAnimationsForMotionBlur": ( + self.optimizeAnimationsForMotionBlur + ), + "writeMaterials": self.writeMaterials, + "useBaseTessellation": self.useBaseTessellation + } + self.log.debug( + "Extract {} with:\n{}".format( + instance[:], json.dumps(kwargs, indent=4, sort_keys=True) + ) + ) + cmds.gpuCache(instance[:], **kwargs) + + if "representations" not in instance.data: + instance.data["representations"] = [] + + representation = { + "name": "gpu_cache", + "ext": "abc", + "files": filename + ".abc", + "stagingDir": staging_dir, + "outputName": "gpu_cache" + } + + instance.data["representations"].append(representation) + + self.log.info( + "Extracted instance {} to: {}".format(instance.name, staging_dir) + ) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index bc506b7feb1..93054e5fbb7 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -1,63 +1,42 @@ # -*- coding: utf-8 -*- """Maya look extractor.""" -import os +from abc import ABCMeta, abstractmethod +from collections import OrderedDict +import contextlib import json -import tempfile +import logging +import os import platform -import contextlib -from collections import OrderedDict - -from maya import cmds # noqa +import tempfile +import six +import attr import pyblish.api -from openpype.lib import source_hash, run_subprocess -from openpype.pipeline import legacy_io, publish +from maya import cmds # noqa + +from openpype.lib.vendor_bin_utils import find_executable +from openpype.lib import source_hash, run_subprocess, get_oiio_tools_path +from openpype.pipeline import legacy_io, publish, KnownPublishError from openpype.hosts.maya.api import lib -from openpype.hosts.maya.api.lib import image_info, guess_colorspace # Modes for transfer COPY = 1 HARDLINK = 2 -def _has_arnold(): - """Return whether the arnold package is available and can be imported.""" - try: - import arnold # noqa: F401 - return True - except (ImportError, ModuleNotFoundError): - return False - - -def escape_space(path): - """Ensure path is enclosed by quotes to allow paths with spaces""" - return '"{}"'.format(path) if " " in path else path - - -def get_ocio_config_path(profile_folder): - """Path to OpenPype vendorized OCIO. - - Vendorized OCIO config file path is grabbed from the specific path - hierarchy specified below. - - "{OPENPYPE_ROOT}/vendor/OpenColorIO-Configs/{profile_folder}/config.ocio" - Args: - profile_folder (str): Name of folder to grab config file from. - - Returns: - str: Path to vendorized config file. - """ - - return os.path.join( - os.environ["OPENPYPE_ROOT"], - "vendor", - "bin", - "ocioconfig", - "OpenColorIOConfigs", - profile_folder, - "config.ocio" - ) +@attr.s +class TextureResult: + """The resulting texture of a processed file for a resource""" + # Path to the file + path = attr.ib() + # Colorspace of the resulting texture. This might not be the input + # colorspace of the texture if a TextureProcessor has processed the file. + colorspace = attr.ib() + # Hash generated for the texture using openpype.lib.source_hash + file_hash = attr.ib() + # The transfer mode, e.g. COPY or HARDLINK + transfer_mode = attr.ib() def find_paths_by_hash(texture_hash): @@ -76,61 +55,6 @@ def find_paths_by_hash(texture_hash): return legacy_io.distinct(key, {"type": "version"}) -def maketx(source, destination, args, logger): - """Make `.tx` using `maketx` with some default settings. - - The settings are based on default as used in Arnold's - txManager in the scene. - This function requires the `maketx` executable to be - on the `PATH`. - - Args: - source (str): Path to source file. - destination (str): Writing destination path. - args (list): Additional arguments for `maketx`. - logger (logging.Logger): Logger to log messages to. - - Returns: - str: Output of `maketx` command. - - """ - from openpype.lib import get_oiio_tools_path - - maketx_path = get_oiio_tools_path("maketx") - - if not maketx_path: - print( - "OIIO tool not found in {}".format(maketx_path)) - raise AssertionError("OIIO tool not found") - - subprocess_args = [ - maketx_path, - "-v", # verbose - "-u", # update mode - # unpremultiply before conversion (recommended when alpha present) - "--unpremult", - "--checknan", - # use oiio-optimized settings for tile-size, planarconfig, metadata - "--oiio", - "--filter", "lanczos3", - source - ] - - subprocess_args.extend(args) - subprocess_args.extend(["-o", destination]) - - cmd = " ".join(subprocess_args) - logger.debug(cmd) - - try: - out = run_subprocess(subprocess_args) - except Exception: - logger.error("Maketx converion failed", exc_info=True) - raise - - return out - - @contextlib.contextmanager def no_workspace_dir(): """Force maya to a fake temporary workspace directory. @@ -163,6 +87,303 @@ def no_workspace_dir(): os.rmdir(fake_workspace_dir) +@six.add_metaclass(ABCMeta) +class TextureProcessor: + + extension = None + + def __init__(self, log=None): + if log is None: + log = logging.getLogger(self.__class__.__name__) + self.log = log + + def apply_settings(self, system_settings, project_settings): + """Apply OpenPype system/project settings to the TextureProcessor + + Args: + system_settings (dict): OpenPype system settings + project_settings (dict): OpenPype project settings + + Returns: + None + + """ + pass + + @abstractmethod + def process(self, + source, + colorspace, + color_management, + staging_dir): + """Process the `source` texture. + + Must be implemented on inherited class. + + This must always return a TextureResult even when it does not generate + a texture. If it doesn't generate a texture then it should return a + TextureResult using the input path and colorspace. + + Args: + source (str): Path to source file. + colorspace (str): Colorspace of the source file. + color_management (dict): Maya Color management data from + `lib.get_color_management_preferences` + staging_dir (str): Output directory to write to. + + Returns: + TextureResult: The resulting texture information. + + """ + pass + + def __repr__(self): + # Log instance as class name + return self.__class__.__name__ + + +class MakeRSTexBin(TextureProcessor): + """Make `.rstexbin` using `redshiftTextureProcessor`""" + + extension = ".rstexbin" + + def process(self, + source, + colorspace, + color_management, + staging_dir): + + texture_processor_path = self.get_redshift_tool( + "redshiftTextureProcessor" + ) + if not texture_processor_path: + raise KnownPublishError("Must have Redshift available.") + + subprocess_args = [ + texture_processor_path, + source + ] + + hash_args = ["rstex"] + texture_hash = source_hash(source, *hash_args) + + # Redshift stores the output texture next to the input but with + # the extension replaced to `.rstexbin` + basename, ext = os.path.splitext(source) + destination = "{}{}".format(basename, self.extension) + + self.log.debug(" ".join(subprocess_args)) + try: + run_subprocess(subprocess_args) + except Exception: + self.log.error("Texture .rstexbin conversion failed", + exc_info=True) + raise + + return TextureResult( + path=destination, + file_hash=texture_hash, + colorspace=colorspace, + transfer_mode=COPY + ) + + @staticmethod + def get_redshift_tool(tool_name): + """Path to redshift texture processor. + + On Windows it adds .exe extension if missing from tool argument. + + Args: + tool_name (string): Tool name. + + Returns: + str: Full path to redshift texture processor executable. + """ + if "REDSHIFT_COREDATAPATH" not in os.environ: + raise RuntimeError("Must have Redshift available.") + + redshift_tool_path = os.path.join( + os.environ["REDSHIFT_COREDATAPATH"], + "bin", + tool_name + ) + + return find_executable(redshift_tool_path) + + +class MakeTX(TextureProcessor): + """Make `.tx` using `maketx` with some default settings. + + Some hardcoded arguments passed to `maketx` are based on the defaults used + in Arnold's txManager tool. + + """ + + extension = ".tx" + + def __init__(self, log=None): + super(MakeTX, self).__init__(log=log) + self.extra_args = [] + + def apply_settings(self, system_settings, project_settings): + # Allow extra maketx arguments from project settings + args_settings = ( + project_settings["maya"]["publish"] + .get("ExtractLook", {}).get("maketx_arguments", []) + ) + extra_args = [] + for arg_data in args_settings: + argument = arg_data["argument"] + parameters = arg_data["parameters"] + if not argument: + self.log.debug("Ignoring empty parameter from " + "`maketx_arguments` setting..") + continue + + extra_args.append(argument) + extra_args.extend(parameters) + + self.extra_args = extra_args + + def process(self, + source, + colorspace, + color_management, + staging_dir): + """Process the texture. + + This function requires the `maketx` executable to be available in an + OpenImageIO toolset detectable by OpenPype. + + Args: + source (str): Path to source file. + colorspace (str): Colorspace of the source file. + color_management (dict): Maya Color management data from + `lib.get_color_management_preferences` + staging_dir (str): Output directory to write to. + + Returns: + TextureResult: The resulting texture information. + + """ + + maketx_path = get_oiio_tools_path("maketx") + + if not maketx_path: + raise AssertionError( + "OIIO 'maketx' tool not found. Result: {}".format(maketx_path) + ) + + # Define .tx filepath in staging if source file is not .tx + fname, ext = os.path.splitext(os.path.basename(source)) + if ext == ".tx": + # Do nothing if the source file is already a .tx file. + return TextureResult( + path=source, + file_hash=None, # todo: unknown texture hash? + colorspace=colorspace, + transfer_mode=COPY + ) + + # Hardcoded default arguments for maketx conversion based on Arnold's + # txManager in Maya + args = [ + # unpremultiply before conversion (recommended when alpha present) + "--unpremult", + # use oiio-optimized settings for tile-size, planarconfig, metadata + "--oiio", + "--filter", "lanczos3", + ] + if color_management["enabled"]: + config_path = color_management["config"] + if not os.path.exists(config_path): + raise RuntimeError("OCIO config not found at: " + "{}".format(config_path)) + + render_colorspace = color_management["rendering_space"] + + self.log.info("tx: converting colorspace {0} " + "-> {1}".format(colorspace, + render_colorspace)) + args.extend(["--colorconvert", colorspace, render_colorspace]) + args.extend(["--colorconfig", config_path]) + + else: + # Maya Color management is disabled. We cannot rely on an OCIO + self.log.debug("tx: Maya color management is disabled. No color " + "conversion will be applied to .tx conversion for: " + "{}".format(source)) + # Assume linear + render_colorspace = "linear" + + # Note: The texture hash is only reliable if we include any potential + # conversion arguments provide to e.g. `maketx` + hash_args = ["maketx"] + args + self.extra_args + texture_hash = source_hash(source, *hash_args) + + # Ensure folder exists + resources_dir = os.path.join(staging_dir, "resources") + if not os.path.exists(resources_dir): + os.makedirs(resources_dir) + + self.log.info("Generating .tx file for %s .." % source) + + subprocess_args = [ + maketx_path, + "-v", # verbose + "-u", # update mode + # --checknan doesn't influence the output file but aborts the + # conversion if it finds any. So we can avoid it for the file hash + "--checknan", + source + ] + + subprocess_args.extend(args) + if self.extra_args: + subprocess_args.extend(self.extra_args) + + # Add source hash attribute after other arguments for log readability + # Note: argument is excluded from the hash since it is the hash itself + subprocess_args.extend([ + "--sattrib", + "sourceHash", + texture_hash + ]) + + destination = os.path.join(resources_dir, fname + ".tx") + subprocess_args.extend(["-o", destination]) + + # We want to make sure we are explicit about what OCIO config gets + # used. So when we supply no --colorconfig flag that no fallback to + # an OCIO env var occurs. + env = os.environ.copy() + env.pop("OCIO", None) + + self.log.debug(" ".join(subprocess_args)) + try: + run_subprocess(subprocess_args, env=env) + except Exception: + self.log.error("Texture maketx conversion failed", + exc_info=True) + raise + + return TextureResult( + path=destination, + file_hash=texture_hash, + colorspace=render_colorspace, + transfer_mode=COPY + ) + + @staticmethod + def _has_arnold(): + """Return whether the arnold package is available and importable.""" + try: + import arnold # noqa: F401 + return True + except (ImportError, ModuleNotFoundError): + return False + + class ExtractLook(publish.Extractor): """Extract Look (Maya Scene + JSON) @@ -179,22 +400,6 @@ class ExtractLook(publish.Extractor): scene_type = "ma" look_data_type = "json" - @staticmethod - def get_renderer_name(): - """Get renderer name from Maya. - - Returns: - str: Renderer name. - - """ - renderer = cmds.getAttr( - "defaultRenderGlobals.currentRenderer" - ).lower() - # handle various renderman names - if renderer.startswith("renderman"): - renderer = "renderman" - return renderer - def get_maya_scene_type(self, instance): """Get Maya scene type from settings. @@ -234,16 +439,12 @@ def process(self, instance): dir_path = self.staging_dir(instance) maya_fname = "{0}.{1}".format(instance.name, self.scene_type) json_fname = "{0}.{1}".format(instance.name, self.look_data_type) - - # Make texture dump folder maya_path = os.path.join(dir_path, maya_fname) json_path = os.path.join(dir_path, json_fname) - self.log.info("Performing extraction..") - # Remove all members of the sets so they are not included in the # exported file by accident - self.log.info("Extract sets (%s) ..." % _scene_type) + self.log.info("Processing sets..") lookdata = instance.data["lookData"] relationships = lookdata["relationships"] sets = list(relationships.keys()) @@ -251,13 +452,36 @@ def process(self, instance): self.log.info("No sets found") return - results = self.process_resources(instance, staging_dir=dir_path) + # Specify texture processing executables to activate + # TODO: Load these more dynamically once we support more processors + processors = [] + context = instance.context + for key, Processor in { + # Instance data key to texture processor mapping + "maketx": MakeTX, + "rstex": MakeRSTexBin + }.items(): + if instance.data.get(key, False): + processor = Processor() + processor.apply_settings(context.data["system_settings"], + context.data["project_settings"]) + processors.append(processor) + + if processors: + self.log.debug("Collected texture processors: " + "{}".format(processors)) + + self.log.debug("Processing resources..") + results = self.process_resources(instance, + staging_dir=dir_path, + processors=processors) transfers = results["fileTransfers"] hardlinks = results["fileHardlinks"] hashes = results["fileHashes"] remap = results["attrRemap"] # Extract in correct render layer + self.log.info("Extracting look maya scene file: {}".format(maya_path)) layer = instance.data.get("renderlayer", "defaultRenderLayer") with lib.renderlayer(layer): # TODO: Ensure membership edits don't become renderlayer overrides @@ -265,7 +489,7 @@ def process(self, instance): # To avoid Maya trying to automatically remap the file # textures relative to the `workspace -directory` we force # it to a fake temporary workspace. This fixes textures - # getting incorrectly remapped. (LKD-17, PLN-101) + # getting incorrectly remapped. with no_workspace_dir(): with lib.attribute_values(remap): with lib.maintained_selection(): @@ -329,40 +553,38 @@ def process(self, instance): # Source hash for the textures instance.data["sourceHashes"] = hashes - """ - self.log.info("Returning colorspaces to their original values ...") - for attr, value in remap.items(): - self.log.info(" - {}: {}".format(attr, value)) - cmds.setAttr(attr, value, type="string") - """ self.log.info("Extracted instance '%s' to: %s" % (instance.name, maya_path)) - def process_resources(self, instance, staging_dir): + def _set_resource_result_colorspace(self, resource, colorspace): + """Update resource resulting colorspace after texture processing""" + if "result_color_space" in resource: + if resource["result_color_space"] == colorspace: + return - # Extract the textures to transfer, possibly convert with maketx and - # remap the node paths to the destination path. Note that a source - # might be included more than once amongst the resources as they could - # be the input file to multiple nodes. - resources = instance.data["resources"] - do_maketx = instance.data.get("maketx", False) + self.log.warning( + "Resource already has a resulting colorspace but is now " + "being overridden to a new one: {} -> {}".format( + resource["result_color_space"], colorspace + ) + ) + resource["result_color_space"] = colorspace - # Collect all unique files used in the resources - files_metadata = {} - for resource in resources: - # Preserve color space values (force value after filepath change) - # This will also trigger in the same order at end of context to - # ensure after context it's still the original value. - color_space = resource.get("color_space") + def process_resources(self, instance, staging_dir, processors): + """Process all resources in the instance. - for f in resource["files"]: - files_metadata[os.path.normpath(f)] = { - "color_space": color_space} + It is assumed that all resources are nodes using file textures. + + Extract the textures to transfer, possibly convert with maketx and + remap the node paths to the destination path. Note that a source + might be included more than once amongst the resources as they could + be the input file to multiple nodes. + + """ + + resources = instance.data["resources"] + color_management = lib.get_color_management_preferences() - # Process the resource files - transfers = [] - hardlinks = [] - hashes = {} # Temporary fix to NOT create hardlinks on windows machines if platform.system().lower() == "windows": self.log.info( @@ -372,95 +594,114 @@ def process_resources(self, instance, staging_dir): else: force_copy = instance.data.get("forceCopy", False) - for filepath in files_metadata: - - linearize = False - # if OCIO color management enabled - # it won't take the condition of the files_metadata + destinations_cache = {} - ocio_maya = cmds.colorManagementPrefs(q=True, - cmConfigFileEnabled=True, - cmEnabled=True) + def get_resource_destination_cached(path): + """Get resource destination with cached result per filepath""" + if path not in destinations_cache: + destination = self.get_resource_destination( + path, instance.data["resourcesDir"], processors) + destinations_cache[path] = destination + return destinations_cache[path] - if do_maketx and not ocio_maya: - if files_metadata[filepath]["color_space"].lower() == "srgb": # noqa: E501 - linearize = True - # set its file node to 'raw' as tx will be linearized - files_metadata[filepath]["color_space"] = "Raw" + # Process all resource's individual files + processed_files = {} + transfers = [] + hardlinks = [] + hashes = {} + remap = OrderedDict() + for resource in resources: + colorspace = resource["color_space"] + + for filepath in resource["files"]: + filepath = os.path.normpath(filepath) + + if filepath in processed_files: + # The file was already processed, likely due to usage by + # another resource in the scene. We confirm here it + # didn't do color spaces different than the current + # resource. + processed_file = processed_files[filepath] + self.log.debug( + "File was already processed. Likely used by another " + "resource too: {}".format(filepath) + ) + + if colorspace != processed_file["color_space"]: + self.log.warning( + "File '{}' was already processed using colorspace " + "'{}' instead of the current resource's " + "colorspace '{}'. The already processed texture " + "result's colorspace '{}' will be used." + "".format(filepath, + colorspace, + processed_file["color_space"], + processed_file["result_color_space"])) + + self._set_resource_result_colorspace( + resource, + colorspace=processed_file["result_color_space"] + ) + continue + + texture_result = self._process_texture( + filepath, + processors=processors, + staging_dir=staging_dir, + force_copy=force_copy, + color_management=color_management, + colorspace=colorspace + ) - # if do_maketx: - # color_space = "Raw" + # Set the resulting color space on the resource + self._set_resource_result_colorspace( + resource, colorspace=texture_result.colorspace + ) - source, mode, texture_hash = self._process_texture( - filepath, - resource, - do_maketx, - staging=staging_dir, - linearize=linearize, - force=force_copy + processed_files[filepath] = { + "color_space": colorspace, + "result_color_space": texture_result.colorspace, + } + + source = texture_result.path + destination = get_resource_destination_cached(source) + if force_copy or texture_result.transfer_mode == COPY: + transfers.append((source, destination)) + self.log.info('file will be copied {} -> {}'.format( + source, destination)) + elif texture_result.transfer_mode == HARDLINK: + hardlinks.append((source, destination)) + self.log.info('file will be hardlinked {} -> {}'.format( + source, destination)) + + # Store the hashes from hash to destination to include in the + # database + hashes[texture_result.file_hash] = destination + + # Set up remapping attributes for the node during the publish + # The order of these can be important if one attribute directly + # affects another, e.g. we set colorspace after filepath because + # maya sometimes tries to guess the colorspace when changing + # filepaths (which is avoidable, but we don't want to have those + # attributes changed in the resulting publish) + # Remap filepath to publish destination + # TODO It would be much better if we could use the destination path + # from the actual processed texture results, but since the + # attribute will need to preserve tokens like , etc for + # now we will define the output path from the attribute value + # including the tokens to persist them. + filepath_attr = resource["attribute"] + remap[filepath_attr] = get_resource_destination_cached( + resource["source"] ) - destination = self.resource_destination(instance, - source, - do_maketx) - - # Force copy is specified. - if force_copy: - mode = COPY - - if mode == COPY: - transfers.append((source, destination)) - self.log.info('file will be copied {} -> {}'.format( - source, destination)) - elif mode == HARDLINK: - hardlinks.append((source, destination)) - self.log.info('file will be hardlinked {} -> {}'.format( - source, destination)) - - # Store the hashes from hash to destination to include in the - # database - hashes[texture_hash] = destination - - # Remap the resources to the destination path (change node attributes) - destinations = {} - remap = OrderedDict() # needs to be ordered, see color space values - for resource in resources: - source = os.path.normpath(resource["source"]) - if source not in destinations: - # Cache destination as source resource might be included - # multiple times - destinations[source] = self.resource_destination( - instance, source, do_maketx - ) # Preserve color space values (force value after filepath change) # This will also trigger in the same order at end of context to # ensure after context it's still the original value. - color_space_attr = resource["node"] + ".colorSpace" - try: - color_space = cmds.getAttr(color_space_attr) - except ValueError: - # node doesn't have color space attribute - color_space = "Raw" - else: - # get the resolved files - metadata = files_metadata.get(source) - # if the files are unresolved from `source` - # assume color space from the first file of - # the resource - if not metadata: - first_file = next(iter(resource.get( - "files", [])), None) - if not first_file: - continue - first_filepath = os.path.normpath(first_file) - metadata = files_metadata[first_filepath] - if metadata["color_space"] == "Raw": - # set color space to raw if we linearized it - color_space = "Raw" - # Remap file node filename to destination - remap[color_space_attr] = color_space - attr = resource["attribute"] - remap[attr] = destinations[source] + node = resource["node"] + if cmds.attributeQuery("colorSpace", node=node, exists=True): + color_space_attr = "{}.colorSpace".format(node) + remap[color_space_attr] = resource["result_color_space"] self.log.info("Finished remapping destinations ...") @@ -471,134 +712,131 @@ def process_resources(self, instance, staging_dir): "attrRemap": remap, } - def resource_destination(self, instance, filepath, do_maketx): + def get_resource_destination(self, filepath, resources_dir, processors): """Get resource destination path. This is utility function to change path if resource file name is changed by some external tool like `maketx`. Args: - instance: Current Instance. - filepath (str): Resource path - do_maketx (bool): Flag if resource is processed by `maketx`. + filepath (str): Resource source path + resources_dir (str): Destination dir for resources in publish. + processors (list): Texture processors converting resource. Returns: str: Path to resource file """ - resources_dir = instance.data["resourcesDir"] - # Compute destination location basename, ext = os.path.splitext(os.path.basename(filepath)) - # If `maketx` then the texture will always end with .tx - if do_maketx: - ext = ".tx" + # Get extension from the last processor + for processor in reversed(processors): + processor_ext = processor.extension + if processor_ext and ext != processor_ext: + self.log.debug("Processor {} overrides extension to '{}' " + "for path: {}".format(processor, + processor_ext, + filepath)) + ext = processor_ext + break return os.path.join( resources_dir, basename + ext ) - def _process_texture(self, filepath, resource, - do_maketx, staging, linearize, force): - """Process a single texture file on disk for publishing. - This will: - 1. Check whether it's already published, if so it will do hardlink - 2. If not published and maketx is enabled, generate a new .tx file. - 3. Compute the destination path for the source file. - Args: - filepath (str): The source file path to process. - do_maketx (bool): Whether to produce a .tx file - Returns: - """ - - fname, ext = os.path.splitext(os.path.basename(filepath)) - - args = [] - if do_maketx: - args.append("maketx") - texture_hash = source_hash(filepath, *args) + def _get_existing_hashed_texture(self, texture_hash): + """Return the first found filepath from a texture hash""" # If source has been published before with the same settings, # then don't reprocess but hardlink from the original existing = find_paths_by_hash(texture_hash) - if existing and not force: - self.log.info("Found hash in database, preparing hardlink..") + if existing: source = next((p for p in existing if os.path.exists(p)), None) if source: - return source, HARDLINK, texture_hash + return source else: self.log.warning( - ("Paths not found on disk, " - "skipping hardlink: %s") % (existing,) + "Paths not found on disk, " + "skipping hardlink: {}".format(existing) ) - if do_maketx and ext != ".tx": - # Produce .tx file in staging if source file is not .tx - converted = os.path.join(staging, "resources", fname + ".tx") - additional_args = [ - "--sattrib", - "sourceHash", - texture_hash - ] - if linearize: - if cmds.colorManagementPrefs(query=True, cmEnabled=True): - render_colorspace = cmds.colorManagementPrefs(query=True, - renderingSpaceName=True) # noqa - config_path = cmds.colorManagementPrefs(query=True, - configFilePath=True) # noqa - if not os.path.exists(config_path): - raise RuntimeError("No OCIO config path found!") - - color_space_attr = resource["node"] + ".colorSpace" - try: - color_space = cmds.getAttr(color_space_attr) - except ValueError: - # node doesn't have color space attribute - if _has_arnold(): - img_info = image_info(filepath) - color_space = guess_colorspace(img_info) - else: - color_space = "Raw" - self.log.info("tx: converting {0} -> {1}".format(color_space, render_colorspace)) # noqa - - additional_args.extend(["--colorconvert", - color_space, - render_colorspace]) - else: - - if _has_arnold(): - img_info = image_info(filepath) - color_space = guess_colorspace(img_info) - if color_space == "sRGB": - self.log.info("tx: converting sRGB -> linear") - additional_args.extend(["--colorconvert", - "sRGB", - "Raw"]) - else: - self.log.info("tx: texture's colorspace " - "is already linear") - else: - self.log.warning("cannot guess the colorspace" - "color conversion won't be available!") # noqa - - - additional_args.extend(["--colorconfig", config_path]) - # Ensure folder exists - if not os.path.exists(os.path.dirname(converted)): - os.makedirs(os.path.dirname(converted)) - - self.log.info("Generating .tx file for %s .." % filepath) - maketx( - filepath, - converted, - additional_args, - self.log + def _process_texture(self, + filepath, + processors, + staging_dir, + force_copy, + color_management, + colorspace): + """Process a single texture file on disk for publishing. + + This will: + 1. Check whether it's already published, if so it will do hardlink + (if the texture hash is found and force copy is not enabled) + 2. It will process the texture using the supplied texture + processors like MakeTX and MakeRSTexBin if enabled. + 3. Compute the destination path for the source file. + + Args: + filepath (str): The source file path to process. + processors (list): List of TextureProcessor processing the texture + staging_dir (str): The staging directory to write to. + force_copy (bool): Whether to force a copy even if a file hash + might have existed already in the project, otherwise + hardlinking the existing file is allowed. + color_management (dict): Maya's Color Management settings from + `lib.get_color_management_preferences` + colorspace (str): The source colorspace of the resources this + texture belongs to. + + Returns: + TextureResult: The texture result information. + """ + + if len(processors) > 1: + raise KnownPublishError( + "More than one texture processor not supported. " + "Current processors enabled: {}".format(processors) ) - return converted, COPY, texture_hash + for processor in processors: + self.log.debug("Processing texture {} with processor {}".format( + filepath, processor + )) + + processed_result = processor.process(filepath, + colorspace, + color_management, + staging_dir) + if not processed_result: + raise RuntimeError("Texture Processor {} returned " + "no result.".format(processor)) + self.log.info("Generated processed " + "texture: {}".format(processed_result.path)) + + # TODO: Currently all processors force copy instead of allowing + # hardlinks using source hashes. This should be refactored + return processed_result + + # No texture processing for this file + texture_hash = source_hash(filepath) + if not force_copy: + existing = self._get_existing_hashed_texture(filepath) + if existing: + self.log.info("Found hash in database, preparing hardlink..") + return TextureResult( + path=filepath, + file_hash=texture_hash, + colorspace=colorspace, + transfer_mode=HARDLINK + ) - return filepath, COPY, texture_hash + return TextureResult( + path=filepath, + file_hash=texture_hash, + colorspace=colorspace, + transfer_mode=COPY + ) class ExtractModelRenderSets(ExtractLook): diff --git a/openpype/hosts/maya/plugins/publish/extract_multiverse_usd_over.py b/openpype/hosts/maya/plugins/publish/extract_multiverse_usd_over.py index 0628623e887..cf610ac6b42 100644 --- a/openpype/hosts/maya/plugins/publish/extract_multiverse_usd_over.py +++ b/openpype/hosts/maya/plugins/publish/extract_multiverse_usd_over.py @@ -102,7 +102,7 @@ def process(self, instance): long=True) self.log.info("Collected object {}".format(members)) - # TODO: Deal with asset, composition, overide with options. + # TODO: Deal with asset, composition, override with options. import multiverse time_opts = None diff --git a/openpype/hosts/maya/plugins/publish/extract_playblast.py b/openpype/hosts/maya/plugins/publish/extract_playblast.py index 94571ff7312..0f3425a1deb 100644 --- a/openpype/hosts/maya/plugins/publish/extract_playblast.py +++ b/openpype/hosts/maya/plugins/publish/extract_playblast.py @@ -1,5 +1,6 @@ import os import json +import contextlib import clique import capture @@ -8,7 +9,16 @@ from openpype.hosts.maya.api import lib from maya import cmds -import pymel.core as pm + + +@contextlib.contextmanager +def panel_camera(panel, camera): + original_camera = cmds.modelPanel(panel, query=True, camera=True) + try: + cmds.modelPanel(panel, edit=True, camera=camera) + yield + finally: + cmds.modelPanel(panel, edit=True, camera=original_camera) class ExtractPlayblast(publish.Extractor): @@ -25,6 +35,16 @@ class ExtractPlayblast(publish.Extractor): optional = True capture_preset = {} + def _capture(self, preset): + self.log.info( + "Using preset:\n{}".format( + json.dumps(preset, sort_keys=True, indent=4) + ) + ) + + path = capture.capture(log=self.log, **preset) + self.log.debug("playblast path {}".format(path)) + def process(self, instance): self.log.info("Extracting capture..") @@ -43,7 +63,7 @@ def process(self, instance): self.log.info("start: {}, end: {}".format(start, end)) # get cameras - camera = instance.data['review_camera'] + camera = instance.data["review_camera"] preset = lib.load_capture_preset(data=self.capture_preset) # Grab capture presets from the project settings @@ -57,23 +77,23 @@ def process(self, instance): asset_height = asset_data.get("resolutionHeight") review_instance_width = instance.data.get("review_width") review_instance_height = instance.data.get("review_height") - preset['camera'] = camera + preset["camera"] = camera # Tests if project resolution is set, # if it is a value other than zero, that value is # used, if not then the asset resolution is # used if review_instance_width and review_instance_height: - preset['width'] = review_instance_width - preset['height'] = review_instance_height + preset["width"] = review_instance_width + preset["height"] = review_instance_height elif width_preset and height_preset: - preset['width'] = width_preset - preset['height'] = height_preset + preset["width"] = width_preset + preset["height"] = height_preset elif asset_width and asset_height: - preset['width'] = asset_width - preset['height'] = asset_height - preset['start_frame'] = start - preset['end_frame'] = end + preset["width"] = asset_width + preset["height"] = asset_height + preset["start_frame"] = start + preset["end_frame"] = end # Enforce persisting camera depth of field camera_options = preset.setdefault("camera_options", {}) @@ -86,14 +106,14 @@ def process(self, instance): self.log.info("Outputting images to %s" % path) - preset['filename'] = path - preset['overwrite'] = True + preset["filename"] = path + preset["overwrite"] = True - pm.refresh(f=True) + cmds.refresh(force=True) - refreshFrameInt = int(pm.playbackOptions(q=True, minTime=True)) - pm.currentTime(refreshFrameInt - 1, edit=True) - pm.currentTime(refreshFrameInt, edit=True) + refreshFrameInt = int(cmds.playbackOptions(q=True, minTime=True)) + cmds.currentTime(refreshFrameInt - 1, edit=True) + cmds.currentTime(refreshFrameInt, edit=True) # Override transparency if requested. transparency = instance.data.get("transparency", 0) @@ -114,7 +134,8 @@ def process(self, instance): # Disable Pan/Zoom. pan_zoom = cmds.getAttr("{}.panZoomEnabled".format(preset["camera"])) - cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), False) + preset.pop("pan_zoom", None) + preset["camera_options"]["panZoomEnabled"] = instance.data["panZoom"] # Need to explicitly enable some viewport changes so the viewport is # refreshed ahead of playblasting. @@ -136,30 +157,39 @@ def process(self, instance): ) override_viewport_options = ( - capture_presets['Viewport Options']['override_viewport_options'] + capture_presets["Viewport Options"]["override_viewport_options"] ) - with lib.maintained_time(): - filename = preset.get("filename", "%TEMP%") - - # Force viewer to False in call to capture because we have our own - # viewer opening call to allow a signal to trigger between - # playblast and viewer - preset['viewer'] = False - - # Update preset with current panel setting - # if override_viewport_options is turned off - if not override_viewport_options: - panel_preset = capture.parse_view(instance.data["panel"]) - panel_preset.pop("camera") - preset.update(panel_preset) - - self.log.info( - "Using preset:\n{}".format( - json.dumps(preset, sort_keys=True, indent=4) + + # Force viewer to False in call to capture because we have our own + # viewer opening call to allow a signal to trigger between + # playblast and viewer + preset["viewer"] = False + + # Update preset with current panel setting + # if override_viewport_options is turned off + if not override_viewport_options: + panel_preset = capture.parse_view(instance.data["panel"]) + panel_preset.pop("camera") + preset.update(panel_preset) + + # Need to ensure Python 2 compatibility. + # TODO: Remove once dropping Python 2. + if getattr(contextlib, "nested", None): + # Python 3 compatibility. + with contextlib.nested( + lib.maintained_time(), + panel_camera(instance.data["panel"], preset["camera"]) + ): + self._capture(preset) + else: + # Python 2 compatibility. + with contextlib.ExitStack() as stack: + stack.enter_context(lib.maintained_time()) + stack.enter_context( + panel_camera(instance.data["panel"], preset["camera"]) ) - ) - path = capture.capture(log=self.log, **preset) + self._capture(preset) # Restoring viewport options. if viewport_defaults: @@ -169,18 +199,17 @@ def process(self, instance): cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), pan_zoom) - self.log.debug("playblast path {}".format(path)) - collected_files = os.listdir(stagingdir) patterns = [clique.PATTERNS["frames"]] collections, remainder = clique.assemble(collected_files, minimum_items=1, patterns=patterns) + filename = preset.get("filename", "%TEMP%") self.log.debug("filename {}".format(filename)) frame_collection = None for collection in collections: - filebase = collection.format('{head}').rstrip(".") + filebase = collection.format("{head}").rstrip(".") self.log.debug("collection head {}".format(filebase)) if filebase in filename: frame_collection = collection @@ -196,7 +225,7 @@ def process(self, instance): tags.append("delete") # Add camera node name to representation data - camera_node_name = pm.ls(camera)[0].getTransform().name() + camera_node_name = cmds.listRelatives(camera, parent=True)[0] collected_files = list(frame_collection) # single frame file shouldn't be in list, only as a string @@ -204,15 +233,14 @@ def process(self, instance): collected_files = collected_files[0] representation = { - 'name': 'png', - 'ext': 'png', - 'files': collected_files, + "name": self.capture_preset["Codec"]["compression"], + "ext": self.capture_preset["Codec"]["compression"], + "files": collected_files, "stagingDir": stagingdir, "frameStart": start, "frameEnd": end, - 'fps': fps, - 'preview': True, - 'tags': tags, - 'camera_name': camera_node_name + "fps": fps, + "tags": tags, + "camera_name": camera_node_name } instance.data["representations"].append(representation) diff --git a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py index 1d94bd58c56..b4ed8dce4c1 100644 --- a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py +++ b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py @@ -8,7 +8,6 @@ from openpype.hosts.maya.api import lib from maya import cmds -import pymel.core as pm class ExtractThumbnail(publish.Extractor): @@ -26,28 +25,28 @@ class ExtractThumbnail(publish.Extractor): def process(self, instance): self.log.info("Extracting capture..") - camera = instance.data['review_camera'] + camera = instance.data["review_camera"] - capture_preset = ( - instance.context.data["project_settings"]['maya']['publish']['ExtractPlayblast']['capture_preset'] - ) + maya_setting = instance.context.data["project_settings"]["maya"] + plugin_setting = maya_setting["publish"]["ExtractPlayblast"] + capture_preset = plugin_setting["capture_preset"] override_viewport_options = ( - capture_preset['Viewport Options']['override_viewport_options'] + capture_preset["Viewport Options"]["override_viewport_options"] ) try: preset = lib.load_capture_preset(data=capture_preset) except KeyError as ke: - self.log.error('Error loading capture presets: {}'.format(str(ke))) + self.log.error("Error loading capture presets: {}".format(str(ke))) preset = {} - self.log.info('Using viewport preset: {}'.format(preset)) + self.log.info("Using viewport preset: {}".format(preset)) # preset["off_screen"] = False - preset['camera'] = camera - preset['start_frame'] = instance.data["frameStart"] - preset['end_frame'] = instance.data["frameStart"] - preset['camera_options'] = { + preset["camera"] = camera + preset["start_frame"] = instance.data["frameStart"] + preset["end_frame"] = instance.data["frameStart"] + preset["camera_options"] = { "displayGateMask": False, "displayResolution": False, "displayFilmGate": False, @@ -74,14 +73,14 @@ def process(self, instance): # used, if not then the asset resolution is # used if review_instance_width and review_instance_height: - preset['width'] = review_instance_width - preset['height'] = review_instance_height + preset["width"] = review_instance_width + preset["height"] = review_instance_height elif width_preset and height_preset: - preset['width'] = width_preset - preset['height'] = height_preset + preset["width"] = width_preset + preset["height"] = height_preset elif asset_width and asset_height: - preset['width'] = asset_width - preset['height'] = asset_height + preset["width"] = asset_width + preset["height"] = asset_height # Create temp directory for thumbnail # - this is to avoid "override" of source file @@ -96,14 +95,14 @@ def process(self, instance): self.log.info("Outputting images to %s" % path) - preset['filename'] = path - preset['overwrite'] = True + preset["filename"] = path + preset["overwrite"] = True - pm.refresh(f=True) + cmds.refresh(force=True) - refreshFrameInt = int(pm.playbackOptions(q=True, minTime=True)) - pm.currentTime(refreshFrameInt - 1, edit=True) - pm.currentTime(refreshFrameInt, edit=True) + refreshFrameInt = int(cmds.playbackOptions(q=True, minTime=True)) + cmds.currentTime(refreshFrameInt - 1, edit=True) + cmds.currentTime(refreshFrameInt, edit=True) # Override transparency if requested. transparency = instance.data.get("transparency", 0) @@ -123,14 +122,14 @@ def process(self, instance): preset["viewport_options"] = {"imagePlane": image_plane} # Disable Pan/Zoom. - pan_zoom = cmds.getAttr("{}.panZoomEnabled".format(preset["camera"])) - cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), False) + preset.pop("pan_zoom", None) + preset["camera_options"]["panZoomEnabled"] = instance.data["panZoom"] with lib.maintained_time(): # Force viewer to False in call to capture because we have our own # viewer opening call to allow a signal to trigger between # playblast and viewer - preset['viewer'] = False + preset["viewer"] = False # Update preset with current panel setting # if override_viewport_options is turned off @@ -145,17 +144,15 @@ def process(self, instance): _, thumbnail = os.path.split(playblast) - cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), pan_zoom) - self.log.info("file list {}".format(thumbnail)) if "representations" not in instance.data: instance.data["representations"] = [] representation = { - 'name': 'thumbnail', - 'ext': 'jpg', - 'files': thumbnail, + "name": "thumbnail", + "ext": "jpg", + "files": thumbnail, "stagingDir": dst_staging, "thumbnail": True } diff --git a/openpype/hosts/maya/plugins/publish/extract_vrayproxy.py b/openpype/hosts/maya/plugins/publish/extract_vrayproxy.py index 9b10d2737de..df16c6c3572 100644 --- a/openpype/hosts/maya/plugins/publish/extract_vrayproxy.py +++ b/openpype/hosts/maya/plugins/publish/extract_vrayproxy.py @@ -30,9 +30,7 @@ def process(self, instance): # non-animated subsets keys = ["frameStart", "frameEnd", "handleStart", "handleEnd", - "frameStartHandle", "frameEndHandle", - # Backwards compatibility - "handles"] + "frameStartHandle", "frameEndHandle"] for key in keys: instance.data.pop(key, None) diff --git a/openpype/hosts/maya/plugins/publish/reset_xgen_attributes.py b/openpype/hosts/maya/plugins/publish/reset_xgen_attributes.py index b90885663c3..d8e8554b686 100644 --- a/openpype/hosts/maya/plugins/publish/reset_xgen_attributes.py +++ b/openpype/hosts/maya/plugins/publish/reset_xgen_attributes.py @@ -30,7 +30,7 @@ def process(self, instance): cmds.setAttr(palette + ".xgExportAsDelta", True) # Need to save the scene, cause the attribute changes above does not - # mark the scene as modified so user can exit without commiting the + # mark the scene as modified so user can exit without committing the # changes. self.log.info("Saving changes.") cmds.file(save=True) diff --git a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py index 3b0ffd52d79..7055dc145ea 100644 --- a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source.py @@ -1,5 +1,3 @@ -import maya.cmds as cmds - import pyblish.api from openpype.pipeline.publish import ( ValidateContentsOrder, PublishValidationError @@ -22,10 +20,11 @@ class ValidateArnoldSceneSource(pyblish.api.InstancePlugin): families = ["ass"] label = "Validate Arnold Scene Source" - def _get_nodes_data(self, nodes): + def _get_nodes_by_name(self, nodes): ungrouped_nodes = [] nodes_by_name = {} parents = [] + same_named_nodes = {} for node in nodes: node_split = node.split("|") if len(node_split) == 2: @@ -35,21 +34,38 @@ def _get_nodes_data(self, nodes): if parent: parents.append(parent) - nodes_by_name[node_split[-1]] = node - for shape in cmds.listRelatives(node, shapes=True): - nodes_by_name[shape.split("|")[-1]] = shape + node_name = node.rsplit("|", 1)[-1].rsplit(":", 1)[-1] + + # Check for same same nodes, which can happen in different + # hierarchies. + if node_name in nodes_by_name: + try: + same_named_nodes[node_name].append(node) + except KeyError: + same_named_nodes[node_name] = [ + nodes_by_name[node_name], node + ] + + nodes_by_name[node_name] = node + + if same_named_nodes: + message = "Found nodes with the same name:" + for name, nodes in same_named_nodes.items(): + message += "\n\n\"{}\":\n{}".format(name, "\n".join(nodes)) + + raise PublishValidationError(message) return ungrouped_nodes, nodes_by_name, parents def process(self, instance): ungrouped_nodes = [] - nodes, content_nodes_by_name, content_parents = self._get_nodes_data( - instance.data["setMembers"] + nodes, content_nodes_by_name, content_parents = ( + self._get_nodes_by_name(instance.data["contentMembers"]) ) ungrouped_nodes.extend(nodes) - nodes, proxy_nodes_by_name, proxy_parents = self._get_nodes_data( + nodes, proxy_nodes_by_name, proxy_parents = self._get_nodes_by_name( instance.data.get("proxy", []) ) ungrouped_nodes.extend(nodes) @@ -66,11 +82,11 @@ def process(self, instance): return # Validate for content and proxy nodes amount being the same. - if len(instance.data["setMembers"]) != len(instance.data["proxy"]): + if len(instance.data["contentMembers"]) != len(instance.data["proxy"]): raise PublishValidationError( "Amount of content nodes ({}) and proxy nodes ({}) needs to " "be the same.".format( - len(instance.data["setMembers"]), + len(instance.data["contentMembers"]), len(instance.data["proxy"]) ) ) diff --git a/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py new file mode 100644 index 00000000000..e27723e1045 --- /dev/null +++ b/openpype/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py @@ -0,0 +1,74 @@ +import pyblish.api +from openpype.hosts.maya.api import lib +from openpype.pipeline.publish import ( + ValidateContentsOrder, PublishValidationError, RepairAction +) + + +class ValidateArnoldSceneSourceCbid(pyblish.api.InstancePlugin): + """Validate Arnold Scene Source Cbid. + + It is required for the proxy and content nodes to share the same cbid. + """ + + order = ValidateContentsOrder + hosts = ["maya"] + families = ["ass"] + label = "Validate Arnold Scene Source CBID" + actions = [RepairAction] + + @staticmethod + def _get_nodes_by_name(nodes): + nodes_by_name = {} + for node in nodes: + node_name = node.rsplit("|", 1)[-1].rsplit(":", 1)[-1] + nodes_by_name[node_name] = node + + return nodes_by_name + + @classmethod + def get_invalid_couples(cls, instance): + content_nodes_by_name = cls._get_nodes_by_name( + instance.data["contentMembers"] + ) + proxy_nodes_by_name = cls._get_nodes_by_name( + instance.data.get("proxy", []) + ) + + invalid_couples = [] + for content_name, content_node in content_nodes_by_name.items(): + proxy_node = proxy_nodes_by_name.get(content_name, None) + + if not proxy_node: + cls.log.debug( + "Content node '{}' has no matching proxy node.".format( + content_node + ) + ) + continue + + content_id = lib.get_id(content_node) + proxy_id = lib.get_id(proxy_node) + if content_id != proxy_id: + invalid_couples.append((content_node, proxy_node)) + + return invalid_couples + + def process(self, instance): + # Proxy validation. + if not instance.data.get("proxy", []): + return + + # Validate for proxy nodes sharing the same cbId as content nodes. + invalid_couples = self.get_invalid_couples(instance) + if invalid_couples: + raise PublishValidationError( + "Found proxy nodes with mismatching cbid:\n{}".format( + invalid_couples + ) + ) + + @classmethod + def repair(cls, instance): + for content_node, proxy_node in cls.get_invalid_couples(cls, instance): + lib.set_id(proxy_node, lib.get_id(content_node), overwrite=False) diff --git a/openpype/hosts/maya/plugins/publish/validate_attributes.py b/openpype/hosts/maya/plugins/publish/validate_attributes.py index 7a1f0cf086a..6ca9afb9a4e 100644 --- a/openpype/hosts/maya/plugins/publish/validate_attributes.py +++ b/openpype/hosts/maya/plugins/publish/validate_attributes.py @@ -1,13 +1,17 @@ -import pymel.core as pm +from collections import defaultdict + +from maya import cmds import pyblish.api + +from openpype.hosts.maya.api.lib import set_attribute from openpype.pipeline.publish import ( RepairContextAction, ValidateContentsOrder, ) -class ValidateAttributes(pyblish.api.ContextPlugin): +class ValidateAttributes(pyblish.api.InstancePlugin): """Ensure attributes are consistent. Attributes to validate and their values comes from the @@ -27,86 +31,80 @@ class ValidateAttributes(pyblish.api.ContextPlugin): attributes = None - def process(self, context): + def process(self, instance): # Check for preset existence. - if not self.attributes: return - invalid = self.get_invalid(context, compute=True) + invalid = self.get_invalid(instance, compute=True) if invalid: raise RuntimeError( "Found attributes with invalid values: {}".format(invalid) ) @classmethod - def get_invalid(cls, context, compute=False): - invalid = context.data.get("invalid_attributes", []) + def get_invalid(cls, instance, compute=False): if compute: - invalid = cls.get_invalid_attributes(context) - - return invalid + return cls.get_invalid_attributes(instance) + else: + return instance.data.get("invalid_attributes", []) @classmethod - def get_invalid_attributes(cls, context): + def get_invalid_attributes(cls, instance): invalid_attributes = [] - for instance in context: - # Filter publisable instances. - if not instance.data["publish"]: + + # Filter families. + families = [instance.data["family"]] + families += instance.data.get("families", []) + families = set(families) & set(cls.attributes.keys()) + if not families: + return [] + + # Get all attributes to validate. + attributes = defaultdict(dict) + for family in families: + if family not in cls.attributes: + # No attributes to validate for family continue - # Filter families. - families = [instance.data["family"]] - families += instance.data.get("families", []) - families = list(set(families) & set(cls.attributes.keys())) - if not families: + for preset_attr, preset_value in cls.attributes[family].items(): + node_name, attribute_name = preset_attr.split(".", 1) + attributes[node_name][attribute_name] = preset_value + + if not attributes: + return [] + + # Get invalid attributes. + nodes = cmds.ls(long=True) + for node in nodes: + node_name = node.rsplit("|", 1)[-1].rsplit(":", 1)[-1] + if node_name not in attributes: continue - # Get all attributes to validate. - attributes = {} - for family in families: - for preset in cls.attributes[family]: - [node_name, attribute_name] = preset.split(".") - try: - attributes[node_name].update( - {attribute_name: cls.attributes[family][preset]} - ) - except KeyError: - attributes.update({ - node_name: { - attribute_name: cls.attributes[family][preset] - } - }) - - # Get invalid attributes. - nodes = pm.ls() - for node in nodes: - name = node.name(stripNamespace=True) - if name not in attributes.keys(): + for attr_name, expected in attributes.items(): + + # Skip if attribute does not exist + if not cmds.attributeQuery(attr_name, node=node, exists=True): continue - presets_to_validate = attributes[name] - for attribute in node.listAttr(): - names = [attribute.shortName(), attribute.longName()] - attribute_name = list( - set(names) & set(presets_to_validate.keys()) + plug = "{}.{}".format(node, attr_name) + value = cmds.getAttr(plug) + if value != expected: + invalid_attributes.append( + { + "attribute": plug, + "expected": expected, + "current": value + } ) - if attribute_name: - expected = presets_to_validate[attribute_name[0]] - if attribute.get() != expected: - invalid_attributes.append( - { - "attribute": attribute, - "expected": expected, - "current": attribute.get() - } - ) - - context.data["invalid_attributes"] = invalid_attributes + + instance.data["invalid_attributes"] = invalid_attributes return invalid_attributes @classmethod def repair(cls, instance): invalid = cls.get_invalid(instance) for data in invalid: - data["attribute"].set(data["expected"]) + node, attr = data["attribute"].split(".", 1) + value = data["expected"] + set_attribute(node=node, attribute=attr, value=value) diff --git a/openpype/hosts/maya/plugins/publish/validate_camera_attributes.py b/openpype/hosts/maya/plugins/publish/validate_camera_attributes.py index bd1529e2527..13ea53a357e 100644 --- a/openpype/hosts/maya/plugins/publish/validate_camera_attributes.py +++ b/openpype/hosts/maya/plugins/publish/validate_camera_attributes.py @@ -8,7 +8,7 @@ class ValidateCameraAttributes(pyblish.api.InstancePlugin): """Validates Camera has no invalid attribute keys or values. - The Alembic file format does not a specifc subset of attributes as such + The Alembic file format does not a specific subset of attributes as such we validate that no values are set there as the output will not match the current scene. For example the preScale, film offsets and film roll. diff --git a/openpype/hosts/maya/plugins/publish/validate_frame_range.py b/openpype/hosts/maya/plugins/publish/validate_frame_range.py index 59b06874b3f..ccb351c880b 100644 --- a/openpype/hosts/maya/plugins/publish/validate_frame_range.py +++ b/openpype/hosts/maya/plugins/publish/validate_frame_range.py @@ -4,6 +4,7 @@ from openpype.pipeline.publish import ( RepairAction, ValidateContentsOrder, + PublishValidationError ) from openpype.hosts.maya.api.lib_rendersetup import ( get_attr_overrides, @@ -49,7 +50,6 @@ def process(self, instance): frame_start_handle = int(context.data.get("frameStartHandle")) frame_end_handle = int(context.data.get("frameEndHandle")) - handles = int(context.data.get("handles")) handle_start = int(context.data.get("handleStart")) handle_end = int(context.data.get("handleEnd")) frame_start = int(context.data.get("frameStart")) @@ -66,8 +66,6 @@ def process(self, instance): assert frame_start_handle <= frame_end_handle, ( "start frame is lower then end frame") - assert handles >= 0, ("handles cannot have negative values") - # compare with data on instance errors = [] if [ef for ef in self.exclude_families diff --git a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py b/openpype/hosts/maya/plugins/publish/validate_look_color_space.py deleted file mode 100644 index b1bdeb7541b..00000000000 --- a/openpype/hosts/maya/plugins/publish/validate_look_color_space.py +++ /dev/null @@ -1,26 +0,0 @@ -from maya import cmds - -import pyblish.api -from openpype.pipeline.publish import ValidateContentsOrder -from openpype.pipeline import PublishValidationError - - -class ValidateMayaColorSpace(pyblish.api.InstancePlugin): - """ - Check if the OCIO Color Management and maketx options - enabled at the same time - """ - - order = ValidateContentsOrder - families = ['look'] - hosts = ['maya'] - label = 'Color Management with maketx' - - def process(self, instance): - ocio_maya = cmds.colorManagementPrefs(q=True, - cmConfigFileEnabled=True, - cmEnabled=True) - maketx = instance.data["maketx"] - - if ocio_maya and maketx: - raise PublishValidationError("Maya is color managed and maketx option is on. OpenPype doesn't support this combination yet.") # noqa diff --git a/openpype/hosts/maya/plugins/publish/validate_look_contents.py b/openpype/hosts/maya/plugins/publish/validate_look_contents.py index 53501d11e52..2d38099f0f0 100644 --- a/openpype/hosts/maya/plugins/publish/validate_look_contents.py +++ b/openpype/hosts/maya/plugins/publish/validate_look_contents.py @@ -1,6 +1,7 @@ import pyblish.api import openpype.hosts.maya.api.action from openpype.pipeline.publish import ValidateContentsOrder +from maya import cmds # noqa class ValidateLookContents(pyblish.api.InstancePlugin): @@ -85,6 +86,7 @@ def validate_lookdata_attributes(cls, instance): invalid.add(instance.name) return list(invalid) + @classmethod def validate_looks(cls, instance): @@ -112,3 +114,23 @@ def validate_files(cls, instance): invalid.append(node) return invalid + + @classmethod + def validate_renderer(cls, instance): + # TODO: Rewrite this to be more specific and configurable + renderer = cmds.getAttr( + 'defaultRenderGlobals.currentRenderer').lower() + do_maketx = instance.data.get("maketx", False) + do_rstex = instance.data.get("rstex", False) + processors = [] + + if do_maketx: + processors.append('arnold') + if do_rstex: + processors.append('redshift') + + for processor in processors: + if processor == renderer: + continue + else: + cls.log.error("Converted texture does not match current renderer.") # noqa diff --git a/openpype/hosts/maya/plugins/publish/validate_maya_units.py b/openpype/hosts/maya/plugins/publish/validate_maya_units.py index 357dde692c3..011df0846c7 100644 --- a/openpype/hosts/maya/plugins/publish/validate_maya_units.py +++ b/openpype/hosts/maya/plugins/publish/validate_maya_units.py @@ -34,7 +34,7 @@ def process(self, context): fps = context.data.get('fps') - # TODO repace query with using 'context.data["assetEntity"]' + # TODO replace query with using 'context.data["assetEntity"]' asset_doc = get_current_project_asset() asset_fps = mayalib.convert_to_maya_fps(asset_doc["data"]["fps"]) @@ -86,7 +86,7 @@ def repair(cls, context): cls.log.debug(current_linear) cls.log.info("Setting time unit to match project") - # TODO repace query with using 'context.data["assetEntity"]' + # TODO replace query with using 'context.data["assetEntity"]' asset_doc = get_current_project_asset() asset_fps = asset_doc["data"]["fps"] mayalib.set_scene_fps(asset_fps) diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py b/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py index fa4c66952c8..a580a1c7874 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py @@ -1,8 +1,14 @@ -import pymel.core as pc from maya import cmds import pyblish.api + import openpype.hosts.maya.api.action -from openpype.hosts.maya.api.lib import maintained_selection +from openpype.hosts.maya.api.lib import ( + maintained_selection, + delete_after, + undo_chunk, + get_attribute, + set_attribute +) from openpype.pipeline.publish import ( RepairAction, ValidateMeshOrder, @@ -31,60 +37,68 @@ class ValidateMeshArnoldAttributes(pyblish.api.InstancePlugin): else: active = False + @classmethod + def get_default_attributes(cls): + # Get default arnold attribute values for mesh type. + defaults = {} + with delete_after() as tmp: + transform = cmds.createNode("transform") + tmp.append(transform) + + mesh = cmds.createNode("mesh", parent=transform) + for attr in cmds.listAttr(mesh, string="ai*"): + plug = "{}.{}".format(mesh, attr) + try: + defaults[attr] = get_attribute(plug) + except RuntimeError: + cls.log.debug("Ignoring arnold attribute: {}".format(attr)) + + return defaults + @classmethod def get_invalid_attributes(cls, instance, compute=False): invalid = [] if compute: - # Get default arnold attributes. - temp_transform = pc.polyCube()[0] - - for shape in pc.ls(instance, type="mesh"): - for attr in temp_transform.getShape().listAttr(): - if not attr.attrName().startswith("ai"): - continue - target_attr = pc.PyNode( - "{}.{}".format(shape.name(), attr.attrName()) - ) - if attr.get() != target_attr.get(): - invalid.append(target_attr) + meshes = cmds.ls(instance, type="mesh", long=True) + if not meshes: + return [] - pc.delete(temp_transform) + # Compare the values against the defaults + defaults = cls.get_default_attributes() + for mesh in meshes: + for attr_name, default_value in defaults.items(): + plug = "{}.{}".format(mesh, attr_name) + if get_attribute(plug) != default_value: + invalid.append(plug) instance.data["nondefault_arnold_attributes"] = invalid - else: - invalid.extend(instance.data["nondefault_arnold_attributes"]) - return invalid + return instance.data.get("nondefault_arnold_attributes", []) @classmethod def get_invalid(cls, instance): - invalid = [] - - for attr in cls.get_invalid_attributes(instance, compute=False): - invalid.append(attr.node().name()) - - return invalid + invalid_attrs = cls.get_invalid_attributes(instance, compute=False) + invalid_nodes = set(attr.split(".", 1)[0] for attr in invalid_attrs) + return sorted(invalid_nodes) @classmethod def repair(cls, instance): with maintained_selection(): - with pc.UndoChunk(): - temp_transform = pc.polyCube()[0] - + with undo_chunk(): + defaults = cls.get_default_attributes() attributes = cls.get_invalid_attributes( instance, compute=False ) for attr in attributes: - source = pc.PyNode( - "{}.{}".format( - temp_transform.getShape(), attr.attrName() - ) + node, attr_name = attr.split(".", 1) + value = defaults[attr_name] + set_attribute( + node=node, + attribute=attr_name, + value=value ) - attr.set(source.get()) - - pc.delete(temp_transform) def process(self, instance): diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_overlapping_uvs.py b/openpype/hosts/maya/plugins/publish/validate_mesh_overlapping_uvs.py index be23f61ec50..74269cc5068 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_overlapping_uvs.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_overlapping_uvs.py @@ -1,10 +1,11 @@ -import pyblish.api -import openpype.hosts.maya.api.action import math +from six.moves import xrange + +from maya import cmds import maya.api.OpenMaya as om -import pymel.core as pm +import pyblish.api -from six.moves import xrange +import openpype.hosts.maya.api.action from openpype.pipeline.publish import ValidateMeshOrder @@ -185,8 +186,7 @@ def _getOverlapUVFaces(self, meshName): center, radius = self._createBoundingCircle(meshfn) for i in xrange(meshfn.numPolygons): # noqa: F821 - rayb1, face1Orig, face1Vec = self._createRayGivenFace( - meshfn, i) + rayb1, face1Orig, face1Vec = self._createRayGivenFace(meshfn, i) if not rayb1: continue cui = center[2*i] @@ -206,8 +206,8 @@ def _getOverlapUVFaces(self, meshName): if (dsqr >= (ri + rj) * (ri + rj)): continue - rayb2, face2Orig, face2Vec = self._createRayGivenFace( - meshfn, j) + rayb2, face2Orig, face2Vec = self._createRayGivenFace(meshfn, + j) if not rayb2: continue # Exclude the degenerate face @@ -240,37 +240,45 @@ class ValidateMeshHasOverlappingUVs(pyblish.api.InstancePlugin): optional = True @classmethod - def _get_overlapping_uvs(cls, node): - """ Check if mesh has overlapping UVs. + def _get_overlapping_uvs(cls, mesh): + """Return overlapping UVs of mesh. + + Args: + mesh (str): Mesh node name + + Returns: + list: Overlapping uvs for the input mesh in all uv sets. - :param node: node to check - :type node: str - :returns: True is has overlapping UVs, False otherwise - :rtype: bool """ ovl = GetOverlappingUVs() + # Store original uv set + original_current_uv_set = cmds.polyUVSet(mesh, + query=True, + currentUVSet=True) + overlapping_faces = [] - for i, uv in enumerate(pm.polyUVSet(node, q=1, auv=1)): - pm.polyUVSet(node, cuv=1, uvSet=uv) - overlapping_faces.extend(ovl._getOverlapUVFaces(str(node))) + for uv_set in cmds.polyUVSet(mesh, query=True, allUVSets=True): + cmds.polyUVSet(mesh, currentUVSet=True, uvSet=uv_set) + overlapping_faces.extend(ovl._getOverlapUVFaces(mesh)) + + # Restore original uv set + cmds.polyUVSet(mesh, currentUVSet=True, uvSet=original_current_uv_set) return overlapping_faces @classmethod def get_invalid(cls, instance, compute=False): - invalid = [] + if compute: - instance.data["overlapping_faces"] = [] - for node in pm.ls(instance, type="mesh"): + invalid = [] + for node in cmds.ls(instance, type="mesh"): faces = cls._get_overlapping_uvs(node) invalid.extend(faces) - # Store values for later. - instance.data["overlapping_faces"].extend(faces) - else: - invalid.extend(instance.data["overlapping_faces"]) - return invalid + instance.data["overlapping_faces"] = invalid + + return instance.data.get("overlapping_faces", []) def process(self, instance): diff --git a/openpype/hosts/maya/plugins/publish/validate_mvlook_contents.py b/openpype/hosts/maya/plugins/publish/validate_mvlook_contents.py index e583c1edbab..04db5a061b1 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mvlook_contents.py +++ b/openpype/hosts/maya/plugins/publish/validate_mvlook_contents.py @@ -42,7 +42,8 @@ def process(self, instance): resources = instance.data.get("resources", []) for resource in resources: files = resource["files"] - self.log.debug("Resouce '{}', files: [{}]".format(resource, files)) + self.log.debug( + "Resource '{}', files: [{}]".format(resource, files)) node = resource["node"] if len(files) == 0: self.log.error("File node '{}' uses no or non-existing " diff --git a/openpype/hosts/maya/plugins/publish/validate_no_namespace.py b/openpype/hosts/maya/plugins/publish/validate_no_namespace.py index e91b99359dd..0ff03f91650 100644 --- a/openpype/hosts/maya/plugins/publish/validate_no_namespace.py +++ b/openpype/hosts/maya/plugins/publish/validate_no_namespace.py @@ -1,4 +1,3 @@ -import pymel.core as pm import maya.cmds as cmds import pyblish.api @@ -12,7 +11,7 @@ def get_namespace(node_name): # ensure only node's name (not parent path) - node_name = node_name.rsplit("|")[-1] + node_name = node_name.rsplit("|", 1)[-1] # ensure only namespace return node_name.rpartition(":")[0] @@ -45,13 +44,11 @@ def repair(cls, instance): invalid = cls.get_invalid(instance) - # Get nodes with pymel since we'll be renaming them - # Since we don't want to keep checking the hierarchy - # or full paths - nodes = pm.ls(invalid) + # Iterate over the nodes by long to short names to iterate the lowest + # in hierarchy nodes first. This way we avoid having renamed parents + # before renaming children nodes + for node in sorted(invalid, key=len, reverse=True): - for node in nodes: - namespace = node.namespace() - if namespace: - name = node.nodeName() - node.rename(name[len(namespace):]) + node_name = node.rsplit("|", 1)[-1] + node_name_without_namespace = node_name.rsplit(":")[-1] + cmds.rename(node, node_name_without_namespace) diff --git a/openpype/hosts/maya/plugins/publish/validate_renderlayer_aovs.py b/openpype/hosts/maya/plugins/publish/validate_renderlayer_aovs.py index 6b6fb03eec7..7919a6eaa10 100644 --- a/openpype/hosts/maya/plugins/publish/validate_renderlayer_aovs.py +++ b/openpype/hosts/maya/plugins/publish/validate_renderlayer_aovs.py @@ -37,8 +37,8 @@ def get_invalid(self, instance): project_name = legacy_io.active_project() asset_doc = instance.data["assetEntity"] - render_passses = instance.data.get("renderPasses", []) - for render_pass in render_passses: + render_passes = instance.data.get("renderPasses", []) + for render_pass in render_passes: is_valid = self.validate_subset_registered( project_name, asset_doc, render_pass ) diff --git a/openpype/hosts/maya/plugins/publish/validate_rendersettings.py b/openpype/hosts/maya/plugins/publish/validate_rendersettings.py index 53f340cd2c0..ebf7b3138d1 100644 --- a/openpype/hosts/maya/plugins/publish/validate_rendersettings.py +++ b/openpype/hosts/maya/plugins/publish/validate_rendersettings.py @@ -275,15 +275,6 @@ def get_invalid(cls, instance): # go through definitions and test if such node.attribute exists. # if so, compare its value from the one required. for attribute, data in cls.get_nodes(instance, renderer).items(): - # Validate the settings has values. - if not data["values"]: - cls.log.error( - "Settings for {}.{} is missing values.".format( - node, attribute - ) - ) - continue - for node in data["nodes"]: try: render_value = cmds.getAttr( @@ -316,6 +307,15 @@ def get_nodes(cls, instance, renderer): ) result = {} for attr, values in OrderedDict(validation_settings).items(): + values = [convert_to_int_or_float(v) for v in values if v] + + # Validate the settings has values. + if not values: + cls.log.error( + "Settings for {} is missing values.".format(attr) + ) + continue + cls.log.debug("{}: {}".format(attr, values)) if "." not in attr: cls.log.warning( @@ -324,8 +324,6 @@ def get_nodes(cls, instance, renderer): ) continue - values = [convert_to_int_or_float(v) for v in values] - node_type, attribute_name = attr.split(".", 1) # first get node of that type diff --git a/openpype/hosts/maya/plugins/publish/validate_rig_output_ids.py b/openpype/hosts/maya/plugins/publish/validate_rig_output_ids.py index f3ed1a36efb..499bfd4e375 100644 --- a/openpype/hosts/maya/plugins/publish/validate_rig_output_ids.py +++ b/openpype/hosts/maya/plugins/publish/validate_rig_output_ids.py @@ -1,14 +1,22 @@ -import pymel.core as pc +from collections import defaultdict + +from maya import cmds import pyblish.api import openpype.hosts.maya.api.action +from openpype.hosts.maya.api.lib import get_id, set_id from openpype.pipeline.publish import ( RepairAction, ValidateContentsOrder, ) +def get_basename(node): + """Return node short name without namespace""" + return node.rsplit("|", 1)[-1].rsplit(":", 1)[-1] + + class ValidateRigOutputIds(pyblish.api.InstancePlugin): """Validate rig output ids. @@ -30,43 +38,48 @@ def process(self, instance): @classmethod def get_invalid(cls, instance, compute=False): - invalid = cls.get_invalid_matches(instance, compute=compute) - return [x["node"].longName() for x in invalid] + invalid_matches = cls.get_invalid_matches(instance, compute=compute) + return list(invalid_matches.keys()) @classmethod def get_invalid_matches(cls, instance, compute=False): - invalid = [] + invalid = {} if compute: out_set = next(x for x in instance if x.endswith("out_SET")) - instance_nodes = pc.sets(out_set, query=True) - instance_nodes.extend( - [x.getShape() for x in instance_nodes if x.getShape()]) - scene_nodes = pc.ls(type="transform") + pc.ls(type="mesh") + instance_nodes = cmds.sets(out_set, query=True, nodesOnly=True) + instance_nodes = cmds.ls(instance_nodes, long=True) + for node in instance_nodes: + shapes = cmds.listRelatives(node, shapes=True, fullPath=True) + if shapes: + instance_nodes.extend(shapes) + + scene_nodes = cmds.ls(type="transform") + cmds.ls(type="mesh") scene_nodes = set(scene_nodes) - set(instance_nodes) + scene_nodes_by_basename = defaultdict(list) + for node in scene_nodes: + basename = get_basename(node) + scene_nodes_by_basename[basename].append(node) + for instance_node in instance_nodes: - matches = [] - basename = instance_node.name(stripNamespace=True) - for scene_node in scene_nodes: - if scene_node.name(stripNamespace=True) == basename: - matches.append(scene_node) - - if matches: - ids = [instance_node.cbId.get()] - ids.extend([x.cbId.get() for x in matches]) - ids = set(ids) - - if len(ids) > 1: - cls.log.error( - "\"{}\" id mismatch to: {}".format( - instance_node.longName(), matches - ) - ) - invalid.append( - {"node": instance_node, "matches": matches} + basename = get_basename(instance_node) + if basename not in scene_nodes_by_basename: + continue + + matches = scene_nodes_by_basename[basename] + + ids = set(get_id(node) for node in matches) + ids.add(get_id(instance_node)) + + if len(ids) > 1: + cls.log.error( + "\"{}\" id mismatch to: {}".format( + instance_node.longName(), matches ) + ) + invalid[instance_node] = matches instance.data["mismatched_output_ids"] = invalid else: @@ -76,19 +89,21 @@ def get_invalid_matches(cls, instance, compute=False): @classmethod def repair(cls, instance): - invalid = cls.get_invalid_matches(instance) + invalid_matches = cls.get_invalid_matches(instance) multiple_ids_match = [] - for data in invalid: - ids = [x.cbId.get() for x in data["matches"]] + for instance_node, matches in invalid_matches.items(): + ids = set(get_id(node) for node in matches) # If there are multiple scene ids matched, and error needs to be # raised for manual correction. if len(ids) > 1: - multiple_ids_match.append(data) + multiple_ids_match.append({"node": instance_node, + "matches": matches}) continue - data["node"].cbId.set(ids[0]) + id_to_set = next(iter(ids)) + set_id(instance_node, id_to_set, overwrite=True) if multiple_ids_match: raise RuntimeError( diff --git a/openpype/hosts/maya/plugins/publish/validate_transform_naming_suffix.py b/openpype/hosts/maya/plugins/publish/validate_transform_naming_suffix.py index 0147aa8a52a..b2a83a80fb0 100644 --- a/openpype/hosts/maya/plugins/publish/validate_transform_naming_suffix.py +++ b/openpype/hosts/maya/plugins/publish/validate_transform_naming_suffix.py @@ -21,7 +21,7 @@ class ValidateTransformNamingSuffix(pyblish.api.InstancePlugin): - nurbsSurface: _NRB - locator: _LOC - null/group: _GRP - Suffices can also be overriden by project settings. + Suffices can also be overridden by project settings. .. warning:: This grabs the first child shape as a reference and doesn't use the diff --git a/openpype/hosts/maya/tools/mayalookassigner/app.py b/openpype/hosts/maya/tools/mayalookassigner/app.py index f9508657e50..2a8775fff6f 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/app.py +++ b/openpype/hosts/maya/tools/mayalookassigner/app.py @@ -24,6 +24,7 @@ remove_unused_looks ) from .vray_proxies import vrayproxy_assign_look +from . import arnold_standin module = sys.modules[__name__] module.window = None @@ -43,7 +44,7 @@ def __init__(self, parent=None): filename = get_workfile() self.setObjectName("lookManager") - self.setWindowTitle("Look Manager 1.3.0 - [{}]".format(filename)) + self.setWindowTitle("Look Manager 1.4.0 - [{}]".format(filename)) self.setWindowFlags(QtCore.Qt.Window) self.setParent(parent) @@ -240,18 +241,37 @@ def on_process_selected(self): )) nodes = item["nodes"] + # Assign Vray Proxy look. if cmds.pluginInfo('vrayformaya', query=True, loaded=True): self.echo("Getting vray proxy nodes ...") vray_proxies = set(cmds.ls(type="VRayProxy", long=True)) - if vray_proxies: - for vp in vray_proxies: - if vp in nodes: - vrayproxy_assign_look(vp, subset_name) + for vp in vray_proxies: + if vp in nodes: + vrayproxy_assign_look(vp, subset_name) - nodes = list(set(item["nodes"]).difference(vray_proxies)) + nodes = list(set(item["nodes"]).difference(vray_proxies)) + else: + self.echo( + "Could not assign to VRayProxy because vrayformaya plugin " + "is not loaded." + ) + + # Assign Arnold Standin look. + if cmds.pluginInfo("mtoa", query=True, loaded=True): + arnold_standins = set(cmds.ls(type="aiStandIn", long=True)) + for standin in arnold_standins: + if standin in nodes: + arnold_standin.assign_look(standin, subset_name) + else: + self.echo( + "Could not assign to aiStandIn because mtoa plugin is not " + "loaded." + ) + + nodes = list(set(item["nodes"]).difference(arnold_standins)) - # Assign look + # Assign look if nodes: assign_look_by_version(nodes, version_id=version["_id"]) diff --git a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py new file mode 100644 index 00000000000..7eeeb725530 --- /dev/null +++ b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py @@ -0,0 +1,247 @@ +import os +import json +from collections import defaultdict +import logging + +from maya import cmds + +from openpype.pipeline import legacy_io +from openpype.client import get_last_version_by_subset_name +from openpype.hosts.maya import api +from . import lib + + +log = logging.getLogger(__name__) + + +ATTRIBUTE_MAPPING = { + "primaryVisibility": "visibility", # Camera + "castsShadows": "visibility", # Shadow + "receiveShadows": "receive_shadows", + "aiSelfShadows": "self_shadows", + "aiOpaque": "opaque", + "aiMatte": "matte", + "aiVisibleInDiffuseTransmission": "visibility", + "aiVisibleInSpecularTransmission": "visibility", + "aiVisibleInVolume": "visibility", + "aiVisibleInDiffuseReflection": "visibility", + "aiVisibleInSpecularReflection": "visibility", + "aiSubdivUvSmoothing": "subdiv_uv_smoothing", + "aiDispHeight": "disp_height", + "aiDispPadding": "disp_padding", + "aiDispZeroValue": "disp_zero_value", + "aiStepSize": "step_size", + "aiVolumePadding": "volume_padding", + "aiSubdivType": "subdiv_type", + "aiSubdivIterations": "subdiv_iterations" +} + + +def calculate_visibility_mask(attributes): + # https://arnoldsupport.com/2018/11/21/backdoor-setting-visibility/ + mapping = { + "primaryVisibility": 1, # Camera + "castsShadows": 2, # Shadow + "aiVisibleInDiffuseTransmission": 4, + "aiVisibleInSpecularTransmission": 8, + "aiVisibleInVolume": 16, + "aiVisibleInDiffuseReflection": 32, + "aiVisibleInSpecularReflection": 64 + } + mask = 255 + for attr, value in mapping.items(): + if attributes.get(attr, True): + continue + + mask -= value + + return mask + + +def get_nodes_by_id(standin): + """Get node id from aiStandIn via json sidecar. + + Args: + standin (string): aiStandIn node. + + Returns: + (dict): Dictionary with node full name/path and id. + """ + path = cmds.getAttr(standin + ".dso") + json_path = None + for f in os.listdir(os.path.dirname(path)): + if f.endswith(".json"): + json_path = os.path.join(os.path.dirname(path), f) + break + + if not json_path: + log.warning("Could not find json file for {}.".format(standin)) + return {} + + with open(json_path, "r") as f: + return json.load(f) + + +def shading_engine_assignments(shading_engine, attribute, nodes, assignments): + """Full assignments with shader or disp_map. + + Args: + shading_engine (string): Shading engine for material. + attribute (string): "surfaceShader" or "displacementShader" + nodes: (list): Nodes paths relative to aiStandIn. + assignments (dict): Assignments by nodes. + """ + shader_inputs = cmds.listConnections( + shading_engine + "." + attribute, source=True + ) + if not shader_inputs: + log.info( + "Shading engine \"{}\" missing input \"{}\"".format( + shading_engine, attribute + ) + ) + return + + # Strip off component assignments + for i, node in enumerate(nodes): + if "." in node: + log.warning( + "Converting face assignment to full object assignment. This " + "conversion can be lossy: {}".format(node) + ) + nodes[i] = node.split(".")[0] + + shader_type = "shader" if attribute == "surfaceShader" else "disp_map" + assignment = "{}='{}'".format(shader_type, shader_inputs[0]) + for node in nodes: + assignments[node].append(assignment) + + +def assign_look(standin, subset): + log.info("Assigning {} to {}.".format(subset, standin)) + + nodes_by_id = get_nodes_by_id(standin) + + # Group by asset id so we run over the look per asset + node_ids_by_asset_id = defaultdict(set) + for node_id in nodes_by_id: + asset_id = node_id.split(":", 1)[0] + node_ids_by_asset_id[asset_id].add(node_id) + + project_name = legacy_io.active_project() + for asset_id, node_ids in node_ids_by_asset_id.items(): + + # Get latest look version + version = get_last_version_by_subset_name( + project_name, + subset_name=subset, + asset_id=asset_id, + fields=["_id"] + ) + if not version: + log.info("Didn't find last version for subset name {}".format( + subset + )) + continue + + relationships = lib.get_look_relationships(version["_id"]) + shader_nodes, container_node = lib.load_look(version["_id"]) + namespace = shader_nodes[0].split(":")[0] + + # Get only the node ids and paths related to this asset + # And get the shader edits the look supplies + asset_nodes_by_id = { + node_id: nodes_by_id[node_id] for node_id in node_ids + } + edits = list( + api.lib.iter_shader_edits( + relationships, shader_nodes, asset_nodes_by_id + ) + ) + + # Create assignments + node_assignments = {} + for edit in edits: + for node in edit["nodes"]: + if node not in node_assignments: + node_assignments[node] = [] + + if edit["action"] == "assign": + if not cmds.ls(edit["shader"], type="shadingEngine"): + log.info("Skipping non-shader: %s" % edit["shader"]) + continue + + shading_engine_assignments( + shading_engine=edit["shader"], + attribute="surfaceShader", + nodes=edit["nodes"], + assignments=node_assignments + ) + shading_engine_assignments( + shading_engine=edit["shader"], + attribute="displacementShader", + nodes=edit["nodes"], + assignments=node_assignments + ) + + if edit["action"] == "setattr": + visibility = False + for attr, value in edit["attributes"].items(): + if attr not in ATTRIBUTE_MAPPING: + log.warning( + "Skipping setting attribute {} on {} because it is" + " not recognized.".format(attr, edit["nodes"]) + ) + continue + + if isinstance(value, str): + value = "'{}'".format(value) + + if ATTRIBUTE_MAPPING[attr] == "visibility": + visibility = True + continue + + assignment = "{}={}".format(ATTRIBUTE_MAPPING[attr], value) + + for node in edit["nodes"]: + node_assignments[node].append(assignment) + + if visibility: + mask = calculate_visibility_mask(edit["attributes"]) + assignment = "visibility={}".format(mask) + + for node in edit["nodes"]: + node_assignments[node].append(assignment) + + # Assign shader + # Clear all current shader assignments + plug = standin + ".operators" + num = cmds.getAttr(plug, size=True) + for i in reversed(range(num)): + cmds.removeMultiInstance("{}[{}]".format(plug, i), b=True) + + # Create new assignment overrides + index = 0 + for node, assignments in node_assignments.items(): + if not assignments: + continue + + with api.lib.maintained_selection(): + operator = cmds.createNode("aiSetParameter") + operator = cmds.rename(operator, namespace + ":" + operator) + + cmds.setAttr(operator + ".selection", node, type="string") + for i, assignment in enumerate(assignments): + cmds.setAttr( + "{}.assignment[{}]".format(operator, i), + assignment, + type="string" + ) + + cmds.connectAttr( + operator + ".out", "{}[{}]".format(plug, index) + ) + + index += 1 + + cmds.sets(operator, edit=True, addElement=container_node) diff --git a/openpype/hosts/maya/tools/mayalookassigner/commands.py b/openpype/hosts/maya/tools/mayalookassigner/commands.py index 2e7a51efded..c5e6c973cfd 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/commands.py +++ b/openpype/hosts/maya/tools/mayalookassigner/commands.py @@ -13,6 +13,7 @@ from openpype.hosts.maya.api import lib from .vray_proxies import get_alembic_ids_cache +from . import arnold_standin log = logging.getLogger(__name__) @@ -44,33 +45,11 @@ def get_namespace_from_node(node): return parts[0] if len(parts) > 1 else u":" -def list_descendents(nodes): - """Include full descendant hierarchy of given nodes. - - This is a workaround to cmds.listRelatives(allDescendents=True) because - this way correctly keeps children instance paths (see Maya documentation) - - This fixes LKD-26: assignments not working as expected on instanced shapes. - - Return: - list: List of children descendents of nodes - - """ - result = [] - while True: - nodes = cmds.listRelatives(nodes, - fullPath=True) - if nodes: - result.extend(nodes) - else: - return result - - def get_selected_nodes(): """Get information from current selection""" selection = cmds.ls(selection=True, long=True) - hierarchy = list_descendents(selection) + hierarchy = lib.get_all_children(selection) return list(set(selection + hierarchy)) @@ -80,21 +59,7 @@ def get_all_asset_nodes(): Returns: list: list of dictionaries """ - - host = registered_host() - - nodes = [] - for container in host.ls(): - # We are not interested in looks but assets! - if container["loader"] == "LookLoader": - continue - - # Gather all information - container_name = container["objectName"] - nodes += lib.get_container_members(container_name) - - nodes = list(set(nodes)) - return nodes + return cmds.ls(dag=True, noIntermediate=True, long=True) def create_asset_id_hash(nodes): @@ -119,10 +84,12 @@ def create_asset_id_hash(nodes): path = cmds.getAttr("{}.fileName".format(node)) ids = get_alembic_ids_cache(path) for k, _ in ids.items(): - pid = k.split(":")[0] - if node not in node_id_hash[pid]: - node_id_hash[pid].append(node) - + id = k.split(":")[0] + node_id_hash[id].append(node) + elif cmds.nodeType(node) == "aiStandIn": + for id, _ in arnold_standin.get_nodes_by_id(node).items(): + id = id.split(":")[0] + node_id_hash[id].append(node) else: value = lib.get_id(node) if value is None: diff --git a/openpype/hosts/maya/tools/mayalookassigner/lib.py b/openpype/hosts/maya/tools/mayalookassigner/lib.py new file mode 100644 index 00000000000..fddaf6112dd --- /dev/null +++ b/openpype/hosts/maya/tools/mayalookassigner/lib.py @@ -0,0 +1,87 @@ +import json +import logging + +from openpype.pipeline import ( + legacy_io, + get_representation_path, + registered_host, + discover_loader_plugins, + loaders_from_representation, + load_container +) +from openpype.client import get_representation_by_name +from openpype.hosts.maya.api import lib + + +log = logging.getLogger(__name__) + + +def get_look_relationships(version_id): + # type: (str) -> dict + """Get relations for the look. + + Args: + version_id (str): Parent version Id. + + Returns: + dict: Dictionary of relations. + """ + + project_name = legacy_io.active_project() + json_representation = get_representation_by_name( + project_name, representation_name="json", version_id=version_id + ) + + # Load relationships + shader_relation = get_representation_path(json_representation) + with open(shader_relation, "r") as f: + relationships = json.load(f) + + return relationships + + +def load_look(version_id): + # type: (str) -> list + """Load look from version. + + Get look from version and invoke Loader for it. + + Args: + version_id (str): Version ID + + Returns: + list of shader nodes. + + """ + + project_name = legacy_io.active_project() + # Get representations of shader file and relationships + look_representation = get_representation_by_name( + project_name, representation_name="ma", version_id=version_id + ) + + # See if representation is already loaded, if so reuse it. + host = registered_host() + representation_id = str(look_representation['_id']) + for container in host.ls(): + if (container['loader'] == "LookLoader" and + container['representation'] == representation_id): + log.info("Reusing loaded look ...") + container_node = container['objectName'] + break + else: + log.info("Using look for the first time ...") + + # Load file + all_loaders = discover_loader_plugins() + loaders = loaders_from_representation(all_loaders, representation_id) + loader = next( + (i for i in loaders if i.__name__ == "LookLoader"), None) + if loader is None: + raise RuntimeError("Could not find LookLoader, this is a bug") + + # Reference the look file + with lib.maintained_selection(): + container_node = load_container(loader, look_representation)[0] + + return lib.get_container_members(container_node), container_node diff --git a/openpype/hosts/maya/tools/mayalookassigner/vray_proxies.py b/openpype/hosts/maya/tools/mayalookassigner/vray_proxies.py index 889396e555d..1d2ec5fd87e 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/vray_proxies.py +++ b/openpype/hosts/maya/tools/mayalookassigner/vray_proxies.py @@ -3,26 +3,16 @@ import os from collections import defaultdict import logging -import json import six import alembic.Abc from maya import cmds -from openpype.client import ( - get_representation_by_name, - get_last_version_by_subset_name, -) -from openpype.pipeline import ( - legacy_io, - load_container, - loaders_from_representation, - discover_loader_plugins, - get_representation_path, - registered_host, -) -from openpype.hosts.maya.api import lib +from openpype.client import get_last_version_by_subset_name +from openpype.pipeline import legacy_io +import openpype.hosts.maya.lib as maya_lib +from . import lib log = logging.getLogger(__name__) @@ -149,79 +139,6 @@ def assign_vrayproxy_shaders(vrayproxy, assignments): index += 1 -def get_look_relationships(version_id): - # type: (str) -> dict - """Get relations for the look. - - Args: - version_id (str): Parent version Id. - - Returns: - dict: Dictionary of relations. - """ - - project_name = legacy_io.active_project() - json_representation = get_representation_by_name( - project_name, representation_name="json", version_id=version_id - ) - - # Load relationships - shader_relation = get_representation_path(json_representation) - with open(shader_relation, "r") as f: - relationships = json.load(f) - - return relationships - - -def load_look(version_id): - # type: (str) -> list - """Load look from version. - - Get look from version and invoke Loader for it. - - Args: - version_id (str): Version ID - - Returns: - list of shader nodes. - - """ - - project_name = legacy_io.active_project() - # Get representations of shader file and relationships - look_representation = get_representation_by_name( - project_name, representation_name="ma", version_id=version_id - ) - - # See if representation is already loaded, if so reuse it. - host = registered_host() - representation_id = str(look_representation['_id']) - for container in host.ls(): - if (container['loader'] == "LookLoader" and - container['representation'] == representation_id): - log.info("Reusing loaded look ...") - container_node = container['objectName'] - break - else: - log.info("Using look for the first time ...") - - # Load file - all_loaders = discover_loader_plugins() - loaders = loaders_from_representation(all_loaders, representation_id) - loader = next( - (i for i in loaders if i.__name__ == "LookLoader"), None) - if loader is None: - raise RuntimeError("Could not find LookLoader, this is a bug") - - # Reference the look file - with lib.maintained_selection(): - container_node = load_container(loader, look_representation) - - # Get container members - shader_nodes = lib.get_container_members(container_node) - return shader_nodes - - def vrayproxy_assign_look(vrayproxy, subset="lookDefault"): # type: (str, str) -> None """Assign look to vray proxy. @@ -263,8 +180,8 @@ def vrayproxy_assign_look(vrayproxy, subset="lookDefault"): )) continue - relationships = get_look_relationships(version["_id"]) - shadernodes = load_look(version["_id"]) + relationships = lib.get_look_relationships(version["_id"]) + shadernodes, _ = lib.load_look(version["_id"]) # Get only the node ids and paths related to this asset # And get the shader edits the look supplies @@ -272,8 +189,10 @@ def vrayproxy_assign_look(vrayproxy, subset="lookDefault"): node_id: nodes_by_id[node_id] for node_id in node_ids } edits = list( - lib.iter_shader_edits( - relationships, shadernodes, asset_nodes_by_id)) + maya_lib.iter_shader_edits( + relationships, shadernodes, asset_nodes_by_id + ) + ) # Create assignments assignments = {} diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index 2a14096f0eb..fe3a2d2bd1e 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -23,6 +23,9 @@ from openpype.host import HostDirmap from openpype.tools.utils import host_tools +from openpype.pipeline.workfile.workfile_template_builder import ( + TemplateProfileNotFound +) from openpype.lib import ( env_value_to_bool, Logger, @@ -148,7 +151,7 @@ def get_main_window(): def set_node_data(node, knobname, data): """Write data to node invisible knob - Will create new in case it doesnt exists + Will create new in case it doesn't exists or update the one already created. Args: @@ -506,7 +509,7 @@ def get_avalon_knob_data(node, prefix="avalon:", create=True): try: # check if data available on the node test = node[AVALON_DATA_GROUP].value() - log.debug("Only testing if data avalable: `{}`".format(test)) + log.debug("Only testing if data available: `{}`".format(test)) except NameError as e: # if it doesn't then create it log.debug("Creating avalon knob: `{}`".format(e)) @@ -908,11 +911,11 @@ def get_view_process_node(): continue if not ipn_node: - # in case a Viewer node is transfered from + # in case a Viewer node is transferred from # different workfile with old values raise NameError(( "Input process node name '{}' set in " - "Viewer '{}' is does't exists in nodes" + "Viewer '{}' is doesn't exists in nodes" ).format(ipn, v_.name())) ipn_node.setSelected(True) @@ -1662,7 +1665,7 @@ def create_write_node_legacy( tile_color = _data.get("tile_color", "0xff0000ff") GN["tile_color"].setValue(tile_color) - # overrie knob values from settings + # override knob values from settings for knob in knob_overrides: knob_type = knob["type"] knob_name = knob["name"] @@ -2117,7 +2120,7 @@ def set_writes_colorspace(self): write_node[knob["name"]].setValue(value) except TypeError: log.warning( - "Legacy workflow didnt work, switching to current") + "Legacy workflow didn't work, switching to current") set_node_knobs_from_settings( write_node, nuke_imageio_writes["knobs"]) @@ -2543,7 +2546,7 @@ def reset_selection(): def select_nodes(nodes): - """Selects all inputed nodes + """Selects all inputted nodes Arguments: nodes (list): nuke nodes to be selected @@ -2560,7 +2563,7 @@ def launch_workfiles_app(): Trigger to show workfiles tool on application launch. Can be executed only once all other calls are ignored. - Workfiles tool show is deffered after application initialization using + Workfiles tool show is deferred after application initialization using QTimer. """ @@ -2581,7 +2584,7 @@ def launch_workfiles_app(): # Show workfiles tool using timer # - this will be probably triggered during initialization in that case # the application is not be able to show uis so it must be - # deffered using timer + # deferred using timer # - timer should be processed when initialization ends # When applications starts to process events. timer = QtCore.QTimer() @@ -2684,7 +2687,10 @@ def start_workfile_template_builder(): # to avoid looping of the callback, remove it! log.info("Starting workfile template builder...") - build_workfile_template(workfile_creation_enabled=True) + try: + build_workfile_template(workfile_creation_enabled=True) + except TemplateProfileNotFound: + log.warning("Template profile not found. Skipping...") # remove callback since it would be duplicating the workfile nuke.removeOnCreate(start_workfile_template_builder, nodeClass="Root") diff --git a/openpype/hosts/nuke/api/plugin.py b/openpype/hosts/nuke/api/plugin.py index aec87be5ab6..3566cb64c17 100644 --- a/openpype/hosts/nuke/api/plugin.py +++ b/openpype/hosts/nuke/api/plugin.py @@ -208,6 +208,12 @@ def create(self, subset_name, instance_data, pre_create_data): def collect_instances(self): cached_instances = _collect_and_cache_nodes(self) + attr_def_keys = { + attr_def.key + for attr_def in self.get_instance_attr_defs() + } + attr_def_keys.discard(None) + for (node, data) in cached_instances[self.identifier]: created_instance = CreatedInstance.from_existing( data, self @@ -215,6 +221,12 @@ def collect_instances(self): created_instance.transient_data["node"] = node self._add_instance_to_context(created_instance) + for key in ( + set(created_instance["creator_attributes"].keys()) + - attr_def_keys + ): + created_instance["creator_attributes"].pop(key) + def update_instances(self, update_list): for created_inst, _changes in update_list: instance_node = created_inst.transient_data["node"] @@ -301,8 +313,11 @@ def get_pre_create_attr_defs(self): def get_instance_attr_defs(self): attr_defs = [ self._get_render_target_enum(), - self._get_reviewable_bool() ] + # add reviewable attribute + if "reviewable" in self.instance_attributes: + attr_defs.append(self._get_reviewable_bool()) + return attr_defs def _get_render_target_enum(self): @@ -322,7 +337,7 @@ def _get_render_target_enum(self): def _get_reviewable_bool(self): return BoolDef( "review", - default=("reviewable" in self.instance_attributes), + default=True, label="Review" ) @@ -594,7 +609,7 @@ def get_representation_data( Defaults to None. range (bool, optional): flag for adding ranges. Defaults to False. - custom_tags (list[str], optional): user inputed custom tags. + custom_tags (list[str], optional): user inputted custom tags. Defaults to None. """ add_tags = tags or [] @@ -1110,7 +1125,7 @@ def process(self): def is_legacy(self): """Check if it needs to run legacy code - In case where `type` key is missing in singe + In case where `type` key is missing in single knob it is legacy project anatomy. Returns: diff --git a/openpype/hosts/nuke/api/utils.py b/openpype/hosts/nuke/api/utils.py index 6bcb752dd1d..2b3c35c23ad 100644 --- a/openpype/hosts/nuke/api/utils.py +++ b/openpype/hosts/nuke/api/utils.py @@ -87,7 +87,7 @@ def bake_gizmos_recursively(in_group=None): def colorspace_exists_on_node(node, colorspace_name): """ Check if colorspace exists on node - Look through all options in the colorpsace knob, and see if we have an + Look through all options in the colorspace knob, and see if we have an exact match to one of the items. Args: diff --git a/openpype/hosts/nuke/api/workfile_template_builder.py b/openpype/hosts/nuke/api/workfile_template_builder.py index fb0afb3d553..72d4ffb4762 100644 --- a/openpype/hosts/nuke/api/workfile_template_builder.py +++ b/openpype/hosts/nuke/api/workfile_template_builder.py @@ -42,7 +42,7 @@ def import_template(self, path): get_template_preset implementation) Returns: - bool: Wether the template was successfully imported or not + bool: Whether the template was successfully imported or not """ # TODO check if the template is already imported @@ -219,19 +219,22 @@ def cleanup_placeholder(self, placeholder, failed): # fix the problem of z_order for backdrops self._fix_z_order(placeholder) - self._imprint_siblings(placeholder) + + if placeholder.data.get("keep_placeholder"): + self._imprint_siblings(placeholder) if placeholder.data["nb_children"] == 0: - # save initial nodes postions and dimensions, update them + # save initial nodes positions and dimensions, update them # and set inputs and outputs of loaded nodes + if placeholder.data.get("keep_placeholder"): + self._imprint_inits() + self._update_nodes(placeholder, nuke.allNodes(), nodes_loaded) - self._imprint_inits() - self._update_nodes(placeholder, nuke.allNodes(), nodes_loaded) self._set_loaded_connections(placeholder) elif placeholder.data["siblings"]: # create copies of placeholder siblings for the new loaded nodes, - # set their inputs and outpus and update all nodes positions and + # set their inputs and outputs and update all nodes positions and # dimensions and siblings names siblings = get_nodes_by_names(placeholder.data["siblings"]) @@ -629,19 +632,23 @@ def cleanup_placeholder(self, placeholder, failed): # fix the problem of z_order for backdrops self._fix_z_order(placeholder) - self._imprint_siblings(placeholder) + + if placeholder.data.get("keep_placeholder"): + self._imprint_siblings(placeholder) if placeholder.data["nb_children"] == 0: - # save initial nodes postions and dimensions, update them + # save initial nodes positions and dimensions, update them # and set inputs and outputs of created nodes - self._imprint_inits() - self._update_nodes(placeholder, nuke.allNodes(), nodes_created) + if placeholder.data.get("keep_placeholder"): + self._imprint_inits() + self._update_nodes(placeholder, nuke.allNodes(), nodes_created) + self._set_created_connections(placeholder) elif placeholder.data["siblings"]: # create copies of placeholder siblings for the new created nodes, - # set their inputs and outpus and update all nodes positions and + # set their inputs and outputs and update all nodes positions and # dimensions and siblings names siblings = get_nodes_by_names(placeholder.data["siblings"]) diff --git a/openpype/hosts/nuke/plugins/create/convert_legacy.py b/openpype/hosts/nuke/plugins/create/convert_legacy.py index d7341c625f4..c143e4cb278 100644 --- a/openpype/hosts/nuke/plugins/create/convert_legacy.py +++ b/openpype/hosts/nuke/plugins/create/convert_legacy.py @@ -39,7 +39,7 @@ def find_instances(self): break if legacy_found: - # if not item do not add legacy instance convertor + # if not item do not add legacy instance converter self.add_convertor_item("Convert legacy instances") def convert(self): diff --git a/openpype/hosts/nuke/plugins/create/create_source.py b/openpype/hosts/nuke/plugins/create/create_source.py index 06cf4e6cbf5..57504b5d53f 100644 --- a/openpype/hosts/nuke/plugins/create/create_source.py +++ b/openpype/hosts/nuke/plugins/create/create_source.py @@ -85,4 +85,4 @@ def set_selected_nodes(self, pre_create_data): raise NukeCreatorError("Creator error: No active selection") else: NukeCreatorError( - "Creator error: only supprted with active selection") + "Creator error: only supported with active selection") diff --git a/openpype/hosts/nuke/plugins/create/create_write_image.py b/openpype/hosts/nuke/plugins/create/create_write_image.py index d38253ab2f3..b74cea5dae6 100644 --- a/openpype/hosts/nuke/plugins/create/create_write_image.py +++ b/openpype/hosts/nuke/plugins/create/create_write_image.py @@ -63,13 +63,6 @@ def _get_frame_source_number(self): default=nuke.frame() ) - def get_instance_attr_defs(self): - attr_defs = [ - self._get_render_target_enum(), - self._get_reviewable_bool() - ] - return attr_defs - def create_instance_node(self, subset_name, instance_data): linked_knobs_ = [] if "use_range_limit" in self.instance_attributes: diff --git a/openpype/hosts/nuke/plugins/create/create_write_prerender.py b/openpype/hosts/nuke/plugins/create/create_write_prerender.py index 8103cb7c4d5..387768b1dd6 100644 --- a/openpype/hosts/nuke/plugins/create/create_write_prerender.py +++ b/openpype/hosts/nuke/plugins/create/create_write_prerender.py @@ -41,13 +41,6 @@ def get_pre_create_attr_defs(self): ] return attr_defs - def get_instance_attr_defs(self): - attr_defs = [ - self._get_render_target_enum(), - self._get_reviewable_bool() - ] - return attr_defs - def create_instance_node(self, subset_name, instance_data): linked_knobs_ = [] if "use_range_limit" in self.instance_attributes: diff --git a/openpype/hosts/nuke/plugins/create/create_write_render.py b/openpype/hosts/nuke/plugins/create/create_write_render.py index 23efa62e368..09257f662e6 100644 --- a/openpype/hosts/nuke/plugins/create/create_write_render.py +++ b/openpype/hosts/nuke/plugins/create/create_write_render.py @@ -38,13 +38,6 @@ def get_pre_create_attr_defs(self): ] return attr_defs - def get_instance_attr_defs(self): - attr_defs = [ - self._get_render_target_enum(), - self._get_reviewable_bool() - ] - return attr_defs - def create_instance_node(self, subset_name, instance_data): # add fpath_template write_data = { diff --git a/openpype/hosts/nuke/plugins/load/actions.py b/openpype/hosts/nuke/plugins/load/actions.py index e562c74c58c..3227a7ed987 100644 --- a/openpype/hosts/nuke/plugins/load/actions.py +++ b/openpype/hosts/nuke/plugins/load/actions.py @@ -74,8 +74,7 @@ def load(self, context, name, namespace, data): return # Include handles - handles = version_data.get("handles", 0) - start -= handles - end += handles + start -= version_data.get("handleStart", 0) + end += version_data.get("handleEnd", 0) lib.update_frame_range(start, end) diff --git a/openpype/hosts/nuke/plugins/load/load_backdrop.py b/openpype/hosts/nuke/plugins/load/load_backdrop.py index f227aa161ab..67c7877e609 100644 --- a/openpype/hosts/nuke/plugins/load/load_backdrop.py +++ b/openpype/hosts/nuke/plugins/load/load_backdrop.py @@ -54,22 +54,19 @@ def load(self, context, name, namespace, data): version = context['version'] version_data = version.get("data", {}) vname = version.get("name", None) - first = version_data.get("frameStart", None) - last = version_data.get("frameEnd", None) namespace = namespace or context['asset']['name'] colorspace = version_data.get("colorspace", None) object_name = "{}_{}".format(name, namespace) # prepare data for imprinting # add additional metadata from the version to imprint to Avalon knob - add_keys = ["frameStart", "frameEnd", "handleStart", "handleEnd", - "source", "author", "fps"] + add_keys = ["source", "author", "fps"] - data_imprint = {"frameStart": first, - "frameEnd": last, - "version": vname, - "colorspaceInput": colorspace, - "objectName": object_name} + data_imprint = { + "version": vname, + "colorspaceInput": colorspace, + "objectName": object_name + } for k in add_keys: data_imprint.update({k: version_data[k]}) @@ -204,18 +201,13 @@ def update(self, container, representation): name = container['name'] version_data = version_doc.get("data", {}) vname = version_doc.get("name", None) - first = version_data.get("frameStart", None) - last = version_data.get("frameEnd", None) namespace = container['namespace'] colorspace = version_data.get("colorspace", None) object_name = "{}_{}".format(name, namespace) - add_keys = ["frameStart", "frameEnd", "handleStart", "handleEnd", - "source", "author", "fps"] + add_keys = ["source", "author", "fps"] data_imprint = {"representation": str(representation["_id"]), - "frameStart": first, - "frameEnd": last, "version": vname, "colorspaceInput": colorspace, "objectName": object_name} diff --git a/openpype/hosts/nuke/plugins/load/load_script_precomp.py b/openpype/hosts/nuke/plugins/load/load_script_precomp.py index 90581c2f228..53e9a760031 100644 --- a/openpype/hosts/nuke/plugins/load/load_script_precomp.py +++ b/openpype/hosts/nuke/plugins/load/load_script_precomp.py @@ -138,7 +138,6 @@ def update(self, container, representation): "version": version_doc.get("name"), "colorspace": version_data.get("colorspace"), "source": version_data.get("source"), - "handles": version_data.get("handles"), "fps": version_data.get("fps"), "author": version_data.get("author") }) diff --git a/openpype/hosts/nuke/plugins/publish/collect_backdrop.py b/openpype/hosts/nuke/plugins/publish/collect_backdrop.py index 8eaefa68541..7d51af7e9e4 100644 --- a/openpype/hosts/nuke/plugins/publish/collect_backdrop.py +++ b/openpype/hosts/nuke/plugins/publish/collect_backdrop.py @@ -51,38 +51,10 @@ def process(self, instance): instance.data["label"] = "{0} ({1} nodes)".format( bckn.name(), len(instance.data["transientData"]["childNodes"])) - instance.data["families"].append(instance.data["family"]) - - # Get frame range - handle_start = instance.context.data["handleStart"] - handle_end = instance.context.data["handleEnd"] - first_frame = int(nuke.root()["first_frame"].getValue()) - last_frame = int(nuke.root()["last_frame"].getValue()) - # get version version = instance.context.data.get('version') - if not version: - raise RuntimeError("Script name has no version in the name.") - - instance.data['version'] = version - - # Add version data to instance - version_data = { - "handles": handle_start, - "handleStart": handle_start, - "handleEnd": handle_end, - "frameStart": first_frame + handle_start, - "frameEnd": last_frame - handle_end, - "version": int(version), - "families": [instance.data["family"]] + instance.data["families"], - "subset": instance.data["subset"], - "fps": instance.context.data["fps"] - } + if version: + instance.data['version'] = version - instance.data.update({ - "versionData": version_data, - "frameStart": first_frame, - "frameEnd": last_frame - }) self.log.info("Backdrop instance collected: `{}`".format(instance)) diff --git a/openpype/hosts/nuke/plugins/publish/collect_context_data.py b/openpype/hosts/nuke/plugins/publish/collect_context_data.py index b487c946f05..f1b49652057 100644 --- a/openpype/hosts/nuke/plugins/publish/collect_context_data.py +++ b/openpype/hosts/nuke/plugins/publish/collect_context_data.py @@ -49,8 +49,6 @@ def process(self, context): # sourcery skip: avoid-builtin-shadow "resolutionHeight": resolution_height, "pixelAspect": pixel_aspect, - # backward compatibility handles - "handles": handle_start, "handleStart": handle_start, "handleEnd": handle_end, "step": 1, diff --git a/openpype/hosts/nuke/plugins/publish/collect_gizmo.py b/openpype/hosts/nuke/plugins/publish/collect_gizmo.py index 3a877fc194a..e3c40a7a907 100644 --- a/openpype/hosts/nuke/plugins/publish/collect_gizmo.py +++ b/openpype/hosts/nuke/plugins/publish/collect_gizmo.py @@ -28,7 +28,6 @@ def process(self, instance): # Add version data to instance version_data = { - "handles": handle_start, "handleStart": handle_start, "handleEnd": handle_end, "frameStart": first_frame + handle_start, diff --git a/openpype/hosts/nuke/plugins/publish/collect_model.py b/openpype/hosts/nuke/plugins/publish/collect_model.py index 9da056052be..3fdf376d0c7 100644 --- a/openpype/hosts/nuke/plugins/publish/collect_model.py +++ b/openpype/hosts/nuke/plugins/publish/collect_model.py @@ -28,7 +28,6 @@ def process(self, instance): # Add version data to instance version_data = { - "handles": handle_start, "handleStart": handle_start, "handleEnd": handle_end, "frameStart": first_frame + handle_start, diff --git a/openpype/hosts/nuke/plugins/publish/collect_reads.py b/openpype/hosts/nuke/plugins/publish/collect_reads.py index a1144fbcc31..831ae29a27b 100644 --- a/openpype/hosts/nuke/plugins/publish/collect_reads.py +++ b/openpype/hosts/nuke/plugins/publish/collect_reads.py @@ -103,7 +103,6 @@ def process(self, instance): # Add version data to instance version_data = { - "handles": handle_start, "handleStart": handle_start, "handleEnd": handle_end, "frameStart": first_frame + handle_start, @@ -123,7 +122,8 @@ def process(self, instance): "frameStart": first_frame, "frameEnd": last_frame, "colorspace": colorspace, - "handles": int(asset_doc["data"].get("handles", 0)), + "handleStart": handle_start, + "handleEnd": handle_end, "step": 1, "fps": int(nuke.root()['fps'].value()) }) diff --git a/openpype/hosts/nuke/plugins/publish/collect_writes.py b/openpype/hosts/nuke/plugins/publish/collect_writes.py index 0008a756bc4..536a0698f3b 100644 --- a/openpype/hosts/nuke/plugins/publish/collect_writes.py +++ b/openpype/hosts/nuke/plugins/publish/collect_writes.py @@ -189,7 +189,7 @@ def process(self, instance): }) # make sure rendered sequence on farm will - # be used for exctract review + # be used for extract review if not instance.data["review"]: instance.data["useSequenceForReview"] = False diff --git a/openpype/hosts/nuke/plugins/publish/extract_review_data.py b/openpype/hosts/nuke/plugins/publish/extract_review_data.py index dee82482957..c221af40fba 100644 --- a/openpype/hosts/nuke/plugins/publish/extract_review_data.py +++ b/openpype/hosts/nuke/plugins/publish/extract_review_data.py @@ -25,7 +25,7 @@ def process(self, instance): # review can be removed since `ProcessSubmittedJobOnFarm` will create # reviewable representation if needed if ( - "render.farm" in instance.data["families"] + instance.data.get("farm") and "review" in instance.data["families"] ): instance.data["families"].remove("review") diff --git a/openpype/hosts/nuke/plugins/publish/extract_review_data_lut.py b/openpype/hosts/nuke/plugins/publish/extract_review_data_lut.py index 67779e9599e..e4b7b155cd1 100644 --- a/openpype/hosts/nuke/plugins/publish/extract_review_data_lut.py +++ b/openpype/hosts/nuke/plugins/publish/extract_review_data_lut.py @@ -49,7 +49,12 @@ def process(self, instance): exporter.stagingDir, exporter.file).replace("\\", "/") instance.data["representations"] += data["representations"] - if "render.farm" in families: + # review can be removed since `ProcessSubmittedJobOnFarm` will create + # reviewable representation if needed + if ( + instance.data.get("farm") + and "review" in instance.data["families"] + ): instance.data["families"].remove("review") self.log.debug( diff --git a/openpype/hosts/nuke/plugins/publish/extract_review_data_mov.py b/openpype/hosts/nuke/plugins/publish/extract_review_data_mov.py index 3fcfc2a4b51..956d1a54a34 100644 --- a/openpype/hosts/nuke/plugins/publish/extract_review_data_mov.py +++ b/openpype/hosts/nuke/plugins/publish/extract_review_data_mov.py @@ -105,10 +105,7 @@ def process(self, instance): self, instance, o_name, o_data["extension"], multiple_presets) - if ( - "render.farm" in families or - "prerender.farm" in families - ): + if instance.data.get("farm"): if "review" in instance.data["families"]: instance.data["families"].remove("review") diff --git a/openpype/hosts/nuke/plugins/publish/extract_thumbnail.py b/openpype/hosts/nuke/plugins/publish/extract_thumbnail.py index a1a0e241c07..f391ca1e7c2 100644 --- a/openpype/hosts/nuke/plugins/publish/extract_thumbnail.py +++ b/openpype/hosts/nuke/plugins/publish/extract_thumbnail.py @@ -31,7 +31,7 @@ class ExtractThumbnail(publish.Extractor): def process(self, instance): - if "render.farm" in instance.data["families"]: + if instance.data.get("farm"): return with napi.maintained_selection(): diff --git a/openpype/hosts/nuke/plugins/publish/validate_backdrop.py b/openpype/hosts/nuke/plugins/publish/validate_backdrop.py index 208d4a24985..5f4a5c3ab0c 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_backdrop.py +++ b/openpype/hosts/nuke/plugins/publish/validate_backdrop.py @@ -48,7 +48,7 @@ def process(self, context, plugin): class ValidateBackdrop(pyblish.api.InstancePlugin): """ Validate amount of nodes on backdrop node in case user - forgoten to add nodes above the publishing backdrop node. + forgotten to add nodes above the publishing backdrop node. """ order = pyblish.api.ValidatorOrder diff --git a/openpype/hosts/photoshop/api/extension/host/index.jsx b/openpype/hosts/photoshop/api/extension/host/index.jsx index 2acec1ebc13..e2711fb960e 100644 --- a/openpype/hosts/photoshop/api/extension/host/index.jsx +++ b/openpype/hosts/photoshop/api/extension/host/index.jsx @@ -199,7 +199,7 @@ function getActiveDocumentName(){ function getActiveDocumentFullName(){ /** * Returns file name of active document with file path. - * activeDocument.fullName returns path in URI (eg /c/.. insted of c:/) + * activeDocument.fullName returns path in URI (eg /c/.. instead of c:/) * */ if (documents.length == 0){ return null; @@ -225,7 +225,7 @@ function getSelectedLayers(doc) { * Returns json representation of currently selected layers. * Works in three steps - 1) creates new group with selected layers * 2) traverses this group - * 3) deletes newly created group, not neede + * 3) deletes newly created group, not needed * Bit weird, but Adobe.. **/ if (doc == null){ @@ -284,7 +284,7 @@ function selectLayers(selectedLayers){ existing_ids.push(existing_layers[y]["id"]); } for (var i = 0; i < selectedLayers.length; i++) { - // a check to see if the id stil exists + // a check to see if the id still exists var id = selectedLayers[i]; if(existing_ids.toString().indexOf(id)>=0){ layers[i] = charIDToTypeID( "Lyr " ); diff --git a/openpype/hosts/photoshop/api/launch_logic.py b/openpype/hosts/photoshop/api/launch_logic.py index 89ba6ad4e6c..25732446b51 100644 --- a/openpype/hosts/photoshop/api/launch_logic.py +++ b/openpype/hosts/photoshop/api/launch_logic.py @@ -66,11 +66,11 @@ def result(self): return self._result def execute(self): - """Execute callback and store it's result. + """Execute callback and store its result. Method must be called from main thread. Item is marked as `done` when callback execution finished. Store output of callback of exception - information when callback raise one. + information when callback raises one. """ log.debug("Executing process in main thread") if self.done: diff --git a/openpype/hosts/photoshop/plugins/publish/extract_review.py b/openpype/hosts/photoshop/plugins/publish/extract_review.py index 01022ce0b29..9d7eff02113 100644 --- a/openpype/hosts/photoshop/plugins/publish/extract_review.py +++ b/openpype/hosts/photoshop/plugins/publish/extract_review.py @@ -129,7 +129,6 @@ def _generate_mov(self, ffmpeg_path, instance, fps, no_of_frames, "frameStart": 1, "frameEnd": no_of_frames, "fps": fps, - "preview": True, "tags": self.mov_options['tags'] }) diff --git a/openpype/hosts/resolve/api/lib.py b/openpype/hosts/resolve/api/lib.py index f41eb36cafe..b3ad20df399 100644 --- a/openpype/hosts/resolve/api/lib.py +++ b/openpype/hosts/resolve/api/lib.py @@ -250,7 +250,7 @@ def create_timeline_item(media_pool_item: object, media_pool_item, timeline) assert output_timeline_item, AssertionError( - "Track Item with name `{}` doesnt exist on the timeline: `{}`".format( + "Track Item with name `{}` doesn't exist on the timeline: `{}`".format( clip_name, timeline.GetName() )) return output_timeline_item @@ -571,7 +571,7 @@ def create_compound_clip(clip_data, name, folder): # Set current folder to input media_pool_folder: mp.SetCurrentFolder(folder) - # check if clip doesnt exist already: + # check if clip doesn't exist already: clips = folder.GetClipList() cct = next((c for c in clips if c.GetName() in name), None) @@ -582,7 +582,7 @@ def create_compound_clip(clip_data, name, folder): # Create empty timeline in current folder and give name: cct = mp.CreateEmptyTimeline(name) - # check if clip doesnt exist already: + # check if clip doesn't exist already: clips = folder.GetClipList() cct = next((c for c in clips if c.GetName() in name), None) diff --git a/openpype/hosts/resolve/api/menu_style.qss b/openpype/hosts/resolve/api/menu_style.qss index d2d3d1ed37a..3d51c7139fa 100644 --- a/openpype/hosts/resolve/api/menu_style.qss +++ b/openpype/hosts/resolve/api/menu_style.qss @@ -61,7 +61,7 @@ QVBoxLayout { background-color: #282828; } -#Devider { +#Divider { border: 1px solid #090909; background-color: #585858; } diff --git a/openpype/hosts/resolve/api/plugin.py b/openpype/hosts/resolve/api/plugin.py index 77e30149fd6..609cff60f7a 100644 --- a/openpype/hosts/resolve/api/plugin.py +++ b/openpype/hosts/resolve/api/plugin.py @@ -715,7 +715,7 @@ def _convert_to_tag_data(self): # increasing steps by index of rename iteration self.count_steps *= self.rename_index - hierarchy_formating_data = dict() + hierarchy_formatting_data = dict() _data = self.timeline_item_default_data.copy() if self.ui_inputs: # adding tag metadata from ui @@ -749,13 +749,13 @@ def _convert_to_tag_data(self): # fill up pythonic expresisons in hierarchy data for k, _v in self.hierarchy_data.items(): - hierarchy_formating_data[k] = _v["value"].format(**_data) + hierarchy_formatting_data[k] = _v["value"].format(**_data) else: # if no gui mode then just pass default data - hierarchy_formating_data = self.hierarchy_data + hierarchy_formatting_data = self.hierarchy_data tag_hierarchy_data = self._solve_tag_hierarchy_data( - hierarchy_formating_data + hierarchy_formatting_data ) tag_hierarchy_data.update({"heroTrack": True}) @@ -792,18 +792,17 @@ def _convert_to_tag_data(self): else: self.tag_data.update({"reviewTrack": None}) - - def _solve_tag_hierarchy_data(self, hierarchy_formating_data): + def _solve_tag_hierarchy_data(self, hierarchy_formatting_data): """ Solve tag data from hierarchy data and templates. """ # fill up clip name and hierarchy keys - hierarchy_filled = self.hierarchy.format(**hierarchy_formating_data) - clip_name_filled = self.clip_name.format(**hierarchy_formating_data) + hierarchy_filled = self.hierarchy.format(**hierarchy_formatting_data) + clip_name_filled = self.clip_name.format(**hierarchy_formatting_data) return { "newClipName": clip_name_filled, "hierarchy": hierarchy_filled, "parents": self.parents, - "hierarchyData": hierarchy_formating_data, + "hierarchyData": hierarchy_formatting_data, "subset": self.subset, "family": self.subset_family, "families": ["clip"] diff --git a/openpype/hosts/standalonepublisher/plugins/publish/collect_bulk_mov_instances.py b/openpype/hosts/standalonepublisher/plugins/publish/collect_bulk_mov_instances.py index 7925b0ecf3a..6c3b0c3efdb 100644 --- a/openpype/hosts/standalonepublisher/plugins/publish/collect_bulk_mov_instances.py +++ b/openpype/hosts/standalonepublisher/plugins/publish/collect_bulk_mov_instances.py @@ -83,9 +83,9 @@ def process(self, instance): self.log.info(f"Created new instance: {instance_name}") - def convertor(value): + def converter(value): return str(value) self.log.debug("Instance data: {}".format( - json.dumps(new_instance.data, indent=4, default=convertor) + json.dumps(new_instance.data, indent=4, default=converter) )) diff --git a/openpype/hosts/standalonepublisher/plugins/publish/collect_context.py b/openpype/hosts/standalonepublisher/plugins/publish/collect_context.py index 2bf3917e2f2..96aaae23dc2 100644 --- a/openpype/hosts/standalonepublisher/plugins/publish/collect_context.py +++ b/openpype/hosts/standalonepublisher/plugins/publish/collect_context.py @@ -104,7 +104,7 @@ def multiple_instances(self, context, in_data): if repr.get(k): repr.pop(k) - # convert files to list if it isnt + # convert files to list if it isn't if not isinstance(files, (tuple, list)): files = [files] @@ -174,7 +174,7 @@ def prepare_mov_batch_instances(self, in_data): continue files = repre["files"] - # Convert files to list if it isnt + # Convert files to list if it isn't if not isinstance(files, (tuple, list)): files = [files] @@ -255,7 +255,9 @@ def create_instance(self, context, in_data): if ext.startswith("."): component["ext"] = ext[1:] - if component["preview"]: + # Remove 'preview' key from representation data + preview = component.pop("preview") + if preview: instance.data["families"].append("review") component["tags"] = ["review"] self.log.debug("Adding review family") diff --git a/openpype/hosts/standalonepublisher/plugins/publish/collect_editorial.py b/openpype/hosts/standalonepublisher/plugins/publish/collect_editorial.py index 8633d4bf9dd..391cace7617 100644 --- a/openpype/hosts/standalonepublisher/plugins/publish/collect_editorial.py +++ b/openpype/hosts/standalonepublisher/plugins/publish/collect_editorial.py @@ -116,7 +116,7 @@ def process(self, instance): kwargs = {} if extension == ".edl": # EDL has no frame rate embedded so needs explicit - # frame rate else 24 is asssumed. + # frame rate else 24 is assumed. kwargs["rate"] = get_current_project_asset()["data"]["fps"] instance.data["otio_timeline"] = otio.adapters.read_from_file( diff --git a/openpype/hosts/standalonepublisher/plugins/publish/validate_frame_ranges.py b/openpype/hosts/standalonepublisher/plugins/publish/validate_frame_ranges.py index 074c62ea0e9..e46fbe60988 100644 --- a/openpype/hosts/standalonepublisher/plugins/publish/validate_frame_ranges.py +++ b/openpype/hosts/standalonepublisher/plugins/publish/validate_frame_ranges.py @@ -29,7 +29,7 @@ def process(self, instance): for pattern in self.skip_timelines_check): self.log.info("Skipping for {} task".format(instance.data["task"])) - # TODO repace query with using 'instance.data["assetEntity"]' + # TODO replace query with using 'instance.data["assetEntity"]' asset_data = get_current_project_asset(instance.data["asset"])["data"] frame_start = asset_data["frameStart"] frame_end = asset_data["frameEnd"] diff --git a/openpype/hosts/traypublisher/api/editorial.py b/openpype/hosts/traypublisher/api/editorial.py index 293db542a98..e8f76bd3141 100644 --- a/openpype/hosts/traypublisher/api/editorial.py +++ b/openpype/hosts/traypublisher/api/editorial.py @@ -8,10 +8,10 @@ class ShotMetadataSolver: """ Solving hierarchical metadata - Used during editorial publishing. Works with imput + Used during editorial publishing. Works with input clip name and settings defining python formatable template. Settings also define searching patterns - and its token keys used for formating in templates. + and its token keys used for formatting in templates. """ NO_DECOR_PATERN = re.compile(r"\{([a-z]*?)\}") @@ -40,13 +40,13 @@ def _rename_template(self, data): """Shot renaming function Args: - data (dict): formating data + data (dict): formatting data Raises: CreatorError: If missing keys Returns: - str: formated new name + str: formatted new name """ shot_rename_template = self.shot_rename[ "shot_rename_template"] @@ -58,7 +58,7 @@ def _rename_template(self, data): "Make sure all keys in settings are correct:: \n\n" f"From template string {shot_rename_template} > " f"`{_E}` has no equivalent in \n" - f"{list(data.keys())} input formating keys!" + f"{list(data.keys())} input formatting keys!" )) def _generate_tokens(self, clip_name, source_data): @@ -68,7 +68,7 @@ def _generate_tokens(self, clip_name, source_data): Args: clip_name (str): name of clip in editorial - source_data (dict): data for formating + source_data (dict): data for formatting Raises: CreatorError: if missing key @@ -106,14 +106,14 @@ def _generate_tokens(self, clip_name, source_data): return output_data def _create_parents_from_settings(self, parents, data): - """Formating parent components. + """formatting parent components. Args: parents (list): list of dict parent components - data (dict): formating data + data (dict): formatting data Raises: - CreatorError: missing formating key + CreatorError: missing formatting key CreatorError: missing token key KeyError: missing parent token @@ -126,7 +126,7 @@ def _create_parents_from_settings(self, parents, data): # fill parent keys data template from anatomy data try: - _parent_tokens_formating_data = { + _parent_tokens_formatting_data = { parent_token["name"]: parent_token["value"].format(**data) for parent_token in hierarchy_parents } @@ -143,17 +143,17 @@ def _create_parents_from_settings(self, parents, data): for _index, _parent in enumerate( shot_hierarchy["parents_path"].split("/") ): - # format parent token with value which is formated + # format parent token with value which is formatted try: parent_name = _parent.format( - **_parent_tokens_formating_data) + **_parent_tokens_formatting_data) except KeyError as _E: raise CreatorError(( "Make sure all keys in settings are correct : \n\n" f"`{_E}` from template string " f"{shot_hierarchy['parents_path']}, " f" has no equivalent in \n" - f"{list(_parent_tokens_formating_data.keys())} parents" + f"{list(_parent_tokens_formatting_data.keys())} parents" )) parent_token_name = ( @@ -225,7 +225,7 @@ def _get_parents_from_selected_asset( visual_hierarchy = [asset_doc] current_doc = asset_doc - # looping trought all available visual parents + # looping through all available visual parents # if they are not available anymore than it breaks while True: visual_parent_id = current_doc["data"]["visualParent"] @@ -288,7 +288,7 @@ def generate_data(self, clip_name, source_data): Args: clip_name (str): clip name - source_data (dict): formating data + source_data (dict): formatting data Returns: (str, dict): shot name and hierarchy data @@ -301,19 +301,19 @@ def generate_data(self, clip_name, source_data): # match clip to shot name at start shot_name = clip_name - # parse all tokens and generate formating data - formating_data = self._generate_tokens(shot_name, source_data) + # parse all tokens and generate formatting data + formatting_data = self._generate_tokens(shot_name, source_data) # generate parents from selected asset parents = self._get_parents_from_selected_asset(asset_doc, project_doc) if self.shot_rename["enabled"]: - shot_name = self._rename_template(formating_data) + shot_name = self._rename_template(formatting_data) self.log.info(f"Renamed shot name: {shot_name}") if self.shot_hierarchy["enabled"]: parents = self._create_parents_from_settings( - parents, formating_data) + parents, formatting_data) if self.shot_add_tasks: tasks = self._generate_tasks_from_settings( diff --git a/openpype/hosts/traypublisher/plugins/create/create_editorial.py b/openpype/hosts/traypublisher/plugins/create/create_editorial.py index 73be43444e8..0630dfb3da1 100644 --- a/openpype/hosts/traypublisher/plugins/create/create_editorial.py +++ b/openpype/hosts/traypublisher/plugins/create/create_editorial.py @@ -260,7 +260,7 @@ def create(self, subset_name, instance_data, pre_create_data): ) if not first_otio_timeline: - # assing otio timeline for multi file to layer + # assign otio timeline for multi file to layer first_otio_timeline = otio_timeline # create otio editorial instance @@ -283,7 +283,7 @@ def _create_otio_instance( Args: subset_name (str): name of subset - data (dict): instnance data + data (dict): instance data sequence_path (str): path to sequence file media_path (str): path to media file otio_timeline (otio.Timeline): otio timeline object @@ -315,7 +315,7 @@ def _create_otio_timeline(self, sequence_path, fps): kwargs = {} if extension == ".edl": # EDL has no frame rate embedded so needs explicit - # frame rate else 24 is asssumed. + # frame rate else 24 is assumed. kwargs["rate"] = fps kwargs["ignore_timecode_mismatch"] = True @@ -358,7 +358,7 @@ def _get_clip_instances( sequence_file_name, first_otio_timeline=None ): - """Helping function fro creating clip instance + """Helping function for creating clip instance Args: otio_timeline (otio.Timeline): otio timeline object @@ -527,7 +527,7 @@ def _make_subset_instance( Args: otio_clip (otio.Clip): otio clip object - preset (dict): sigle family preset + preset (dict): single family preset instance_data (dict): instance data parenting_data (dict): shot instance parent data @@ -767,7 +767,7 @@ def _get_allowed_family_presets(self, pre_create_data): ] def _validate_clip_for_processing(self, otio_clip): - """Validate otio clip attribues + """Validate otio clip attributes Args: otio_clip (otio.Clip): otio clip object @@ -843,7 +843,7 @@ def get_pre_create_attr_defs(self): single_item=False, label="Media files", ), - # TODO: perhpas better would be timecode and fps input + # TODO: perhaps better would be timecode and fps input NumberDef( "timeline_offset", default=0, diff --git a/openpype/hosts/traypublisher/plugins/publish/collect_simple_instances.py b/openpype/hosts/traypublisher/plugins/publish/collect_simple_instances.py index 183195a5155..c081216481c 100644 --- a/openpype/hosts/traypublisher/plugins/publish/collect_simple_instances.py +++ b/openpype/hosts/traypublisher/plugins/publish/collect_simple_instances.py @@ -14,7 +14,7 @@ class CollectSettingsSimpleInstances(pyblish.api.InstancePlugin): There is also possibility to have reviewable representation which can be stored under 'reviewable' attribute stored on instance data. If there was - already created representation with the same files as 'revieable' containes + already created representation with the same files as 'reviewable' contains Representations can be marked for review and in that case is also added 'review' family to instance families. For review can be marked only one diff --git a/openpype/hosts/tvpaint/api/communication_server.py b/openpype/hosts/tvpaint/api/communication_server.py index e94e64e04a6..6f76c25e0ce 100644 --- a/openpype/hosts/tvpaint/api/communication_server.py +++ b/openpype/hosts/tvpaint/api/communication_server.py @@ -389,11 +389,11 @@ def __init__(self, callback, *args, **kwargs): self.kwargs = kwargs def execute(self): - """Execute callback and store it's result. + """Execute callback and store its result. Method must be called from main thread. Item is marked as `done` when callback execution finished. Store output of callback of exception - information when callback raise one. + information when callback raises one. """ log.debug("Executing process in main thread") if self.done: diff --git a/openpype/hosts/tvpaint/api/pipeline.py b/openpype/hosts/tvpaint/api/pipeline.py index 575e6aa7553..58fbd095452 100644 --- a/openpype/hosts/tvpaint/api/pipeline.py +++ b/openpype/hosts/tvpaint/api/pipeline.py @@ -504,14 +504,9 @@ def set_context_settings(project_name, asset_doc): print("Frame range was not found!") return - handles = asset_doc["data"].get("handles") or 0 handle_start = asset_doc["data"].get("handleStart") handle_end = asset_doc["data"].get("handleEnd") - if handle_start is None or handle_end is None: - handle_start = handles - handle_end = handles - # Always start from 0 Mark In and set only Mark Out mark_in = 0 mark_out = mark_in + (frame_end - frame_start) + handle_start + handle_end diff --git a/openpype/hosts/tvpaint/plugins/create/convert_legacy.py b/openpype/hosts/tvpaint/plugins/create/convert_legacy.py index 538c6e4c5e8..5cfa1faa506 100644 --- a/openpype/hosts/tvpaint/plugins/create/convert_legacy.py +++ b/openpype/hosts/tvpaint/plugins/create/convert_legacy.py @@ -55,7 +55,7 @@ def convert(self): self._convert_render_layers( to_convert["renderLayer"], current_instances) self._convert_render_passes( - to_convert["renderpass"], current_instances) + to_convert["renderPass"], current_instances) self._convert_render_scenes( to_convert["renderScene"], current_instances) self._convert_workfiles( @@ -116,7 +116,7 @@ def _convert_render_passes(self, render_passes, current_instances): render_layers_by_group_id = {} for instance in current_instances: if instance.get("creator_identifier") == "render.layer": - group_id = instance["creator_identifier"]["group_id"] + group_id = instance["creator_attributes"]["group_id"] render_layers_by_group_id[group_id] = instance for render_pass in render_passes: diff --git a/openpype/hosts/tvpaint/plugins/create/create_render.py b/openpype/hosts/tvpaint/plugins/create/create_render.py index 9711024c79c..2369c7329f6 100644 --- a/openpype/hosts/tvpaint/plugins/create/create_render.py +++ b/openpype/hosts/tvpaint/plugins/create/create_render.py @@ -415,11 +415,11 @@ def collect_instances(self): .get("creator_attributes", {}) .get("render_layer_instance_id") ) - render_layer_info = render_layers.get(render_layer_instance_id) + render_layer_info = render_layers.get(render_layer_instance_id, {}) self.update_instance_labels( instance_data, - render_layer_info["variant"], - render_layer_info["template_data"] + render_layer_info.get("variant"), + render_layer_info.get("template_data") ) instance = CreatedInstance.from_existing(instance_data, self) self._add_instance_to_context(instance) @@ -607,11 +607,11 @@ def get_pre_create_attr_defs(self): current_instances = self.host.list_instances() render_layers = [ { - "value": instance["instance_id"], - "label": instance["subset"] + "value": inst["instance_id"], + "label": inst["subset"] } - for instance in current_instances - if instance["creator_identifier"] == CreateRenderlayer.identifier + for inst in current_instances + if inst.get("creator_identifier") == CreateRenderlayer.identifier ] if not render_layers: render_layers.append({"value": None, "label": "N/A"}) @@ -697,6 +697,7 @@ def apply_settings(self, project_settings, system_settings): ["create"] ["auto_detect_render"] ) + self.enabled = plugin_settings.get("enabled", False) self.allow_group_rename = plugin_settings["allow_group_rename"] self.group_name_template = plugin_settings["group_name_template"] self.group_idx_offset = plugin_settings["group_idx_offset"] diff --git a/openpype/hosts/tvpaint/plugins/publish/collect_instance_frames.py b/openpype/hosts/tvpaint/plugins/publish/collect_instance_frames.py index 5eb702a1da4..63f04cf3ce6 100644 --- a/openpype/hosts/tvpaint/plugins/publish/collect_instance_frames.py +++ b/openpype/hosts/tvpaint/plugins/publish/collect_instance_frames.py @@ -22,9 +22,11 @@ def process(self, instance): context = instance.context frame_start = asset_doc["data"]["frameStart"] + fps = asset_doc["data"]["fps"] frame_end = frame_start + ( context.data["sceneMarkOut"] - context.data["sceneMarkIn"] ) + instance.data["fps"] = fps instance.data["frameStart"] = frame_start instance.data["frameEnd"] = frame_end self.log.info( diff --git a/openpype/hosts/tvpaint/plugins/publish/help/validate_layers_visibility.xml b/openpype/hosts/tvpaint/plugins/publish/help/validate_layers_visibility.xml index e7be7358881..5832c743500 100644 --- a/openpype/hosts/tvpaint/plugins/publish/help/validate_layers_visibility.xml +++ b/openpype/hosts/tvpaint/plugins/publish/help/validate_layers_visibility.xml @@ -1,7 +1,7 @@ -Layers visiblity +Layers visibility ## All layers are not visible Layers visibility was changed during publishing which caused that all layers for subset "{instance_name}" are hidden. diff --git a/openpype/hosts/tvpaint/plugins/publish/help/validate_workfile_metadata.xml b/openpype/hosts/tvpaint/plugins/publish/help/validate_workfile_metadata.xml index 7397f6ef0b1..0fc03c2948b 100644 --- a/openpype/hosts/tvpaint/plugins/publish/help/validate_workfile_metadata.xml +++ b/openpype/hosts/tvpaint/plugins/publish/help/validate_workfile_metadata.xml @@ -11,7 +11,7 @@ Your scene does not contain metadata about {missing_metadata}. Resave the scene using Workfiles tool or hit the "Repair" button on the right. -### How this could happend? +### How this could happen? You're using scene file that was not created using Workfiles tool. diff --git a/openpype/hosts/tvpaint/plugins/publish/help/validate_workfile_project_name.xml b/openpype/hosts/tvpaint/plugins/publish/help/validate_workfile_project_name.xml index c4ffafc8b5f..bb57e93bf25 100644 --- a/openpype/hosts/tvpaint/plugins/publish/help/validate_workfile_project_name.xml +++ b/openpype/hosts/tvpaint/plugins/publish/help/validate_workfile_project_name.xml @@ -13,7 +13,7 @@ If the workfile belongs to project "{env_project_name}" then use Workfiles tool Otherwise close TVPaint and launch it again from project you want to publish in. -### How this could happend? +### How this could happen? You've opened workfile from different project. You've opened TVPaint on a task from "{env_project_name}" then you've opened TVPaint again on task from "{workfile_project_name}" without closing the TVPaint. Because TVPaint can run only once the project didn't change. diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_asset_name.py b/openpype/hosts/tvpaint/plugins/publish/validate_asset_name.py index 7e35726030d..9347960d3f4 100644 --- a/openpype/hosts/tvpaint/plugins/publish/validate_asset_name.py +++ b/openpype/hosts/tvpaint/plugins/publish/validate_asset_name.py @@ -1,5 +1,8 @@ import pyblish.api -from openpype.pipeline import PublishXmlValidationError +from openpype.pipeline import ( + PublishXmlValidationError, + OptionalPyblishPluginMixin, +) from openpype.hosts.tvpaint.api.pipeline import ( list_instances, write_instances, @@ -31,8 +34,11 @@ def process(self, context, plugin): write_instances(new_instance_items) -class ValidateAssetNames(pyblish.api.ContextPlugin): - """Validate assset name present on instance. +class ValidateAssetName( + OptionalPyblishPluginMixin, + pyblish.api.ContextPlugin +): + """Validate asset name present on instance. Asset name on instance should be the same as context's. """ @@ -43,6 +49,8 @@ class ValidateAssetNames(pyblish.api.ContextPlugin): actions = [FixAssetNames] def process(self, context): + if not self.is_active(context.data): + return context_asset_name = context.data["asset"] for instance in context: asset_name = instance.data.get("asset") diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_layers_visibility.py b/openpype/hosts/tvpaint/plugins/publish/validate_layers_visibility.py index 6a496a2e496..8e52a636f4f 100644 --- a/openpype/hosts/tvpaint/plugins/publish/validate_layers_visibility.py +++ b/openpype/hosts/tvpaint/plugins/publish/validate_layers_visibility.py @@ -11,7 +11,7 @@ class ValidateLayersVisiblity(pyblish.api.InstancePlugin): families = ["review", "render"] def process(self, instance): - layers = instance.data["layers"] + layers = instance.data.get("layers") # Instance have empty layers # - it is not job of this validator to check that if not layers: diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_marks.py b/openpype/hosts/tvpaint/plugins/publish/validate_marks.py index 0030b0fd1ce..7b2cc62bb5a 100644 --- a/openpype/hosts/tvpaint/plugins/publish/validate_marks.py +++ b/openpype/hosts/tvpaint/plugins/publish/validate_marks.py @@ -1,7 +1,10 @@ import json import pyblish.api -from openpype.pipeline import PublishXmlValidationError +from openpype.pipeline import ( + PublishXmlValidationError, + OptionalPyblishPluginMixin, +) from openpype.hosts.tvpaint.api.lib import execute_george @@ -23,7 +26,10 @@ def process(self, context, plugin): ) -class ValidateMarks(pyblish.api.ContextPlugin): +class ValidateMarks( + OptionalPyblishPluginMixin, + pyblish.api.ContextPlugin +): """Validate mark in and out are enabled and it's duration. Mark In/Out does not have to match frameStart and frameEnd but duration is @@ -59,6 +65,9 @@ def get_expected_data(context): } def process(self, context): + if not self.is_active(context.data): + return + current_data = { "markIn": context.data["sceneMarkIn"], "markInState": context.data["sceneMarkInState"], diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_scene_settings.py b/openpype/hosts/tvpaint/plugins/publish/validate_scene_settings.py index 4473e4b1b79..0ab8e811f58 100644 --- a/openpype/hosts/tvpaint/plugins/publish/validate_scene_settings.py +++ b/openpype/hosts/tvpaint/plugins/publish/validate_scene_settings.py @@ -1,11 +1,17 @@ import json import pyblish.api -from openpype.pipeline import PublishXmlValidationError +from openpype.pipeline import ( + PublishXmlValidationError, + OptionalPyblishPluginMixin, +) # TODO @iLliCiTiT add fix action for fps -class ValidateProjectSettings(pyblish.api.ContextPlugin): +class ValidateProjectSettings( + OptionalPyblishPluginMixin, + pyblish.api.ContextPlugin +): """Validate scene settings against database.""" label = "Validate Scene Settings" @@ -13,6 +19,9 @@ class ValidateProjectSettings(pyblish.api.ContextPlugin): optional = True def process(self, context): + if not self.is_active(context.data): + return + expected_data = context.data["assetEntity"]["data"] scene_data = { "fps": context.data.get("sceneFps"), diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_start_frame.py b/openpype/hosts/tvpaint/plugins/publish/validate_start_frame.py index 066e54c6707..229ccfcd18f 100644 --- a/openpype/hosts/tvpaint/plugins/publish/validate_start_frame.py +++ b/openpype/hosts/tvpaint/plugins/publish/validate_start_frame.py @@ -1,5 +1,8 @@ import pyblish.api -from openpype.pipeline import PublishXmlValidationError +from openpype.pipeline import ( + PublishXmlValidationError, + OptionalPyblishPluginMixin, +) from openpype.hosts.tvpaint.api.lib import execute_george @@ -14,7 +17,10 @@ def process(self, context, plugin): execute_george("tv_startframe 0") -class ValidateStartFrame(pyblish.api.ContextPlugin): +class ValidateStartFrame( + OptionalPyblishPluginMixin, + pyblish.api.ContextPlugin +): """Validate start frame being at frame 0.""" label = "Validate Start Frame" @@ -24,6 +30,9 @@ class ValidateStartFrame(pyblish.api.ContextPlugin): optional = True def process(self, context): + if not self.is_active(context.data): + return + start_frame = execute_george("tv_startframe") if start_frame == 0: return diff --git a/openpype/hosts/unreal/api/pipeline.py b/openpype/hosts/unreal/api/pipeline.py index 8a5a4591949..1a7c6269842 100644 --- a/openpype/hosts/unreal/api/pipeline.py +++ b/openpype/hosts/unreal/api/pipeline.py @@ -306,7 +306,7 @@ def imprint(node, data): def show_tools_popup(): """Show popup with tools. - Popup will disappear on click or loosing focus. + Popup will disappear on click or losing focus. """ from openpype.hosts.unreal.api import tools_ui diff --git a/openpype/hosts/unreal/integration/UE_4.7/OpenPype/Source/OpenPype/Private/OpenPypeLib.cpp b/openpype/hosts/unreal/integration/UE_4.7/OpenPype/Source/OpenPype/Private/OpenPypeLib.cpp index 008025e8166..34faba1f499 100644 --- a/openpype/hosts/unreal/integration/UE_4.7/OpenPype/Source/OpenPype/Private/OpenPypeLib.cpp +++ b/openpype/hosts/unreal/integration/UE_4.7/OpenPype/Source/OpenPype/Private/OpenPypeLib.cpp @@ -31,7 +31,7 @@ bool UOpenPypeLib::SetFolderColor(const FString& FolderPath, const FLinearColor& } /** - * Returns all poperties on given object + * Returns all properties on given object * @param cls - class * @return TArray of properties */ diff --git a/openpype/hosts/unreal/integration/UE_4.7/OpenPype/Source/OpenPype/Public/Commandlets/OPActionResult.h b/openpype/hosts/unreal/integration/UE_4.7/OpenPype/Source/OpenPype/Public/Commandlets/OPActionResult.h index c960bbf190d..322a23a3e81 100644 --- a/openpype/hosts/unreal/integration/UE_4.7/OpenPype/Source/OpenPype/Public/Commandlets/OPActionResult.h +++ b/openpype/hosts/unreal/integration/UE_4.7/OpenPype/Source/OpenPype/Public/Commandlets/OPActionResult.h @@ -16,7 +16,7 @@ /** * @brief This enum values are humanly readable mapping of error codes. * Here should be all error codes to be possible find what went wrong. -* TODO: In the future should exists an web document where is mapped error code & what problem occured & how to repair it... +* TODO: In the future a web document should exists with the mapped error code & what problem occurred & how to repair it... */ UENUM() namespace EOP_ActionResult @@ -27,11 +27,11 @@ namespace EOP_ActionResult ProjectNotCreated, ProjectNotLoaded, ProjectNotSaved, - //....Here insert another values + //....Here insert another values //Do not remove! //Usable for looping through enum values - __Last UMETA(Hidden) + __Last UMETA(Hidden) }; } @@ -63,10 +63,10 @@ struct FOP_ActionResult private: /** @brief Action status */ - EOP_ActionResult::Type Status; + EOP_ActionResult::Type Status; /** @brief Optional reason of fail */ - FText Reason; + FText Reason; public: /** @@ -77,7 +77,7 @@ struct FOP_ActionResult EOP_ActionResult::Type& GetStatus(); FText& GetReason(); -private: +private: void TryLog() const; }; diff --git a/openpype/hosts/unreal/integration/UE_5.0/OpenPype/Source/OpenPype/Private/OpenPypeLib.cpp b/openpype/hosts/unreal/integration/UE_5.0/OpenPype/Source/OpenPype/Private/OpenPypeLib.cpp index 008025e8166..34faba1f499 100644 --- a/openpype/hosts/unreal/integration/UE_5.0/OpenPype/Source/OpenPype/Private/OpenPypeLib.cpp +++ b/openpype/hosts/unreal/integration/UE_5.0/OpenPype/Source/OpenPype/Private/OpenPypeLib.cpp @@ -31,7 +31,7 @@ bool UOpenPypeLib::SetFolderColor(const FString& FolderPath, const FLinearColor& } /** - * Returns all poperties on given object + * Returns all properties on given object * @param cls - class * @return TArray of properties */ diff --git a/openpype/hosts/unreal/integration/UE_5.0/OpenPype/Source/OpenPype/Public/Commandlets/OPActionResult.h b/openpype/hosts/unreal/integration/UE_5.0/OpenPype/Source/OpenPype/Public/Commandlets/OPActionResult.h index c960bbf190d..322a23a3e81 100644 --- a/openpype/hosts/unreal/integration/UE_5.0/OpenPype/Source/OpenPype/Public/Commandlets/OPActionResult.h +++ b/openpype/hosts/unreal/integration/UE_5.0/OpenPype/Source/OpenPype/Public/Commandlets/OPActionResult.h @@ -16,7 +16,7 @@ /** * @brief This enum values are humanly readable mapping of error codes. * Here should be all error codes to be possible find what went wrong. -* TODO: In the future should exists an web document where is mapped error code & what problem occured & how to repair it... +* TODO: In the future a web document should exists with the mapped error code & what problem occurred & how to repair it... */ UENUM() namespace EOP_ActionResult @@ -27,11 +27,11 @@ namespace EOP_ActionResult ProjectNotCreated, ProjectNotLoaded, ProjectNotSaved, - //....Here insert another values + //....Here insert another values //Do not remove! //Usable for looping through enum values - __Last UMETA(Hidden) + __Last UMETA(Hidden) }; } @@ -63,10 +63,10 @@ struct FOP_ActionResult private: /** @brief Action status */ - EOP_ActionResult::Type Status; + EOP_ActionResult::Type Status; /** @brief Optional reason of fail */ - FText Reason; + FText Reason; public: /** @@ -77,7 +77,7 @@ struct FOP_ActionResult EOP_ActionResult::Type& GetStatus(); FText& GetReason(); -private: +private: void TryLog() const; }; diff --git a/openpype/hosts/unreal/plugins/load/load_camera.py b/openpype/hosts/unreal/plugins/load/load_camera.py index ca6b0ce7368..2496440e5f0 100644 --- a/openpype/hosts/unreal/plugins/load/load_camera.py +++ b/openpype/hosts/unreal/plugins/load/load_camera.py @@ -171,7 +171,7 @@ def load(self, context, name, namespace, data): project_name = legacy_io.active_project() # TODO refactor - # - Creationg of hierarchy should be a function in unreal integration + # - Creating of hierarchy should be a function in unreal integration # - it's used in multiple loaders but must not be loader's logic # - hard to say what is purpose of the loop # - variables does not match their meaning diff --git a/openpype/hosts/unreal/ue_workers.py b/openpype/hosts/unreal/ue_workers.py index 00f83a7d7a4..d1740124a87 100644 --- a/openpype/hosts/unreal/ue_workers.py +++ b/openpype/hosts/unreal/ue_workers.py @@ -5,29 +5,38 @@ import subprocess from distutils import dir_util from pathlib import Path -from typing import List +from typing import List, Union import openpype.hosts.unreal.lib as ue_lib from qtpy import QtCore -def parse_comp_progress(line: str, progress_signal: QtCore.Signal(int)) -> int: - match = re.search('\[[1-9]+/[0-9]+\]', line) +def parse_comp_progress(line: str, progress_signal: QtCore.Signal(int)): + match = re.search(r"\[[1-9]+/[0-9]+]", line) if match is not None: - split: list[str] = match.group().split('/') + split: list[str] = match.group().split("/") curr: float = float(split[0][1:]) total: float = float(split[1][:-1]) progress_signal.emit(int((curr / total) * 100.0)) -def parse_prj_progress(line: str, progress_signal: QtCore.Signal(int)) -> int: - match = re.search('@progress', line) +def parse_prj_progress(line: str, progress_signal: QtCore.Signal(int)): + match = re.search("@progress", line) if match is not None: - percent_match = re.search('\d{1,3}', line) + percent_match = re.search(r"\d{1,3}", line) progress_signal.emit(int(percent_match.group())) +def retrieve_exit_code(line: str): + match = re.search(r"ExitCode=\d+", line) + if match is not None: + split: list[str] = match.group().split("=") + return int(split[1]) + + return None + + class UEProjectGenerationWorker(QtCore.QObject): finished = QtCore.Signal(str) failed = QtCore.Signal(str) @@ -77,16 +86,19 @@ def run(self): if self.dev_mode: stage_count = 4 - self.stage_begin.emit(f'Generating a new UE project ... 1 out of ' - f'{stage_count}') + self.stage_begin.emit( + ("Generating a new UE project ... 1 out of " + f"{stage_count}")) - commandlet_cmd = [f'{ue_editor_exe.as_posix()}', - f'{cmdlet_project.as_posix()}', - f'-run=OPGenerateProject', - f'{project_file.resolve().as_posix()}'] + commandlet_cmd = [ + f"{ue_editor_exe.as_posix()}", + f"{cmdlet_project.as_posix()}", + "-run=OPGenerateProject", + f"{project_file.resolve().as_posix()}", + ] if self.dev_mode: - commandlet_cmd.append('-GenerateCode') + commandlet_cmd.append("-GenerateCode") gen_process = subprocess.Popen(commandlet_cmd, stdout=subprocess.PIPE, @@ -94,24 +106,27 @@ def run(self): for line in gen_process.stdout: decoded_line = line.decode(errors="replace") - print(decoded_line, end='') + print(decoded_line, end="") self.log.emit(decoded_line) gen_process.stdout.close() return_code = gen_process.wait() if return_code and return_code != 0: - msg = 'Failed to generate ' + self.project_name \ - + f' project! Exited with return code {return_code}' + msg = ( + f"Failed to generate {self.project_name} " + f"project! Exited with return code {return_code}" + ) self.failed.emit(msg, return_code) raise RuntimeError(msg) print("--- Project has been generated successfully.") - self.stage_begin.emit(f'Writing the Engine ID of the build UE ... 1' - f' out of {stage_count}') + self.stage_begin.emit( + (f"Writing the Engine ID of the build UE ... 1" + f" out of {stage_count}")) if not project_file.is_file(): - msg = "Failed to write the Engine ID into .uproject file! Can " \ - "not read!" + msg = ("Failed to write the Engine ID into .uproject file! Can " + "not read!") self.failed.emit(msg) raise RuntimeError(msg) @@ -125,13 +140,14 @@ def run(self): pf.seek(0) json.dump(pf_json, pf, indent=4) pf.truncate() - print(f'--- Engine ID has been written into the project file') + print("--- Engine ID has been written into the project file") self.progress.emit(90) if self.dev_mode: # 2nd stage - self.stage_begin.emit(f'Generating project files ... 2 out of ' - f'{stage_count}') + self.stage_begin.emit( + (f"Generating project files ... 2 out of " + f"{stage_count}")) self.progress.emit(0) ubt_path = ue_lib.get_path_to_ubt(self.engine_path, @@ -154,8 +170,8 @@ def run(self): stdout=subprocess.PIPE, stderr=subprocess.PIPE) for line in gen_proc.stdout: - decoded_line: str = line.decode(errors='replace') - print(decoded_line, end='') + decoded_line: str = line.decode(errors="replace") + print(decoded_line, end="") self.log.emit(decoded_line) parse_prj_progress(decoded_line, self.progress) @@ -163,13 +179,13 @@ def run(self): return_code = gen_proc.wait() if return_code and return_code != 0: - msg = 'Failed to generate project files! ' \ - f'Exited with return code {return_code}' + msg = ("Failed to generate project files! " + f"Exited with return code {return_code}") self.failed.emit(msg, return_code) raise RuntimeError(msg) - self.stage_begin.emit(f'Building the project ... 3 out of ' - f'{stage_count}') + self.stage_begin.emit( + f"Building the project ... 3 out of {stage_count}") self.progress.emit(0) # 3rd stage build_prj_cmd = [ubt_path.as_posix(), @@ -177,16 +193,16 @@ def run(self): arch, "Development", "-TargetType=Editor", - f'-Project={project_file}', - f'{project_file}', + f"-Project={project_file}", + f"{project_file}", "-IgnoreJunk"] build_prj_proc = subprocess.Popen(build_prj_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) for line in build_prj_proc.stdout: - decoded_line: str = line.decode(errors='replace') - print(decoded_line, end='') + decoded_line: str = line.decode(errors="replace") + print(decoded_line, end="") self.log.emit(decoded_line) parse_comp_progress(decoded_line, self.progress) @@ -194,16 +210,17 @@ def run(self): return_code = build_prj_proc.wait() if return_code and return_code != 0: - msg = 'Failed to build project! ' \ - f'Exited with return code {return_code}' + msg = ("Failed to build project! " + f"Exited with return code {return_code}") self.failed.emit(msg, return_code) raise RuntimeError(msg) # ensure we have PySide2 installed in engine self.progress.emit(0) - self.stage_begin.emit(f'Checking PySide2 installation... {stage_count}' - f' out of {stage_count}') + self.stage_begin.emit( + (f"Checking PySide2 installation... {stage_count} " + f" out of {stage_count}")) python_path = None if platform.system().lower() == "windows": python_path = self.engine_path / ("Engine/Binaries/ThirdParty/" @@ -225,9 +242,30 @@ def run(self): msg = f"Unreal Python not found at {python_path}" self.failed.emit(msg, 1) raise RuntimeError(msg) - subprocess.check_call( - [python_path.as_posix(), "-m", "pip", "install", "pyside2"] - ) + pyside_cmd = [python_path.as_posix(), + "-m", + "pip", + "install", + "pyside2"] + + pyside_install = subprocess.Popen(pyside_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + + for line in pyside_install.stdout: + decoded_line: str = line.decode(errors="replace") + print(decoded_line, end="") + self.log.emit(decoded_line) + + pyside_install.stdout.close() + return_code = pyside_install.wait() + + if return_code and return_code != 0: + msg = ("Failed to create the project! " + "The installation of PySide2 has failed!") + self.failed.emit(msg, return_code) + raise RuntimeError(msg) + self.progress.emit(100) self.finished.emit("Project successfully built!") @@ -266,26 +304,30 @@ def _build_and_move_plugin(self, plugin_build_path: Path): # in order to successfully build the plugin, # It must be built outside the Engine directory and then moved - build_plugin_cmd: List[str] = [f'{uat_path.as_posix()}', - 'BuildPlugin', - f'-Plugin={uplugin_path.as_posix()}', - f'-Package={temp_dir.as_posix()}'] + build_plugin_cmd: List[str] = [f"{uat_path.as_posix()}", + "BuildPlugin", + f"-Plugin={uplugin_path.as_posix()}", + f"-Package={temp_dir.as_posix()}"] build_proc = subprocess.Popen(build_plugin_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return_code: Union[None, int] = None for line in build_proc.stdout: - decoded_line: str = line.decode(errors='replace') - print(decoded_line, end='') + decoded_line: str = line.decode(errors="replace") + print(decoded_line, end="") self.log.emit(decoded_line) + if return_code is None: + return_code = retrieve_exit_code(decoded_line) parse_comp_progress(decoded_line, self.progress) build_proc.stdout.close() - return_code = build_proc.wait() + build_proc.wait() if return_code and return_code != 0: - msg = 'Failed to build plugin' \ - f' project! Exited with return code {return_code}' + msg = ("Failed to build plugin" + f" project! Exited with return code {return_code}") + dir_util.remove_tree(temp_dir.as_posix()) self.failed.emit(msg, return_code) raise RuntimeError(msg) diff --git a/openpype/hosts/webpublisher/lib.py b/openpype/hosts/webpublisher/lib.py index 4bc3f1db80d..b207f85b46e 100644 --- a/openpype/hosts/webpublisher/lib.py +++ b/openpype/hosts/webpublisher/lib.py @@ -30,7 +30,7 @@ def parse_json(path): Returns: (dict) or None if unparsable Raises: - AsssertionError if 'path' doesn't exist + AssertionError if 'path' doesn't exist """ path = path.strip('\"') assert os.path.isfile(path), ( diff --git a/openpype/lib/applications.py b/openpype/lib/applications.py index 7cc296f47bc..8adae348276 100644 --- a/openpype/lib/applications.py +++ b/openpype/lib/applications.py @@ -889,7 +889,8 @@ def __init__(self, application, executable, env_group=None, **data): self.modules_manager = ModulesManager() # Logger - logger_name = "{}-{}".format(self.__class__.__name__, self.app_name) + logger_name = "{}-{}".format(self.__class__.__name__, + self.application.full_name) self.log = Logger.get_logger(logger_name) self.executable = executable @@ -968,7 +969,7 @@ def _collect_addons_launch_hook_paths(self): """Helper to collect application launch hooks from addons. Module have to have implemented 'get_launch_hook_paths' method which - can expect appliction as argument or nothing. + can expect application as argument or nothing. Returns: List[str]: Paths to launch hook directories. @@ -1246,7 +1247,7 @@ def launch(self): args_len_str = " ({})".format(len(args)) self.log.info( "Launching \"{}\" with args{}: {}".format( - self.app_name, args_len_str, args + self.application.full_name, args_len_str, args ) ) self.launch_args = args @@ -1271,7 +1272,9 @@ def launch(self): exc_info=True ) - self.log.debug("Launch of {} finished.".format(self.app_name)) + self.log.debug("Launch of {} finished.".format( + self.application.full_name + )) return self.process @@ -1508,8 +1511,8 @@ def prepare_app_environments( if key in source_env: source_env[key] = value - # `added_env_keys` has debug purpose - added_env_keys = {app.group.name, app.name} + # `app_and_tool_labels` has debug purpose + app_and_tool_labels = [app.full_name] # Environments for application environments = [ app.group.environment, @@ -1532,15 +1535,14 @@ def prepare_app_environments( for group_name in sorted(groups_by_name.keys()): group = groups_by_name[group_name] environments.append(group.environment) - added_env_keys.add(group_name) for tool_name in sorted(tool_by_group_name[group_name].keys()): tool = tool_by_group_name[group_name][tool_name] environments.append(tool.environment) - added_env_keys.add(tool.name) + app_and_tool_labels.append(tool.full_name) log.debug( "Will add environments for apps and tools: {}".format( - ", ".join(added_env_keys) + ", ".join(app_and_tool_labels) ) ) diff --git a/openpype/lib/attribute_definitions.py b/openpype/lib/attribute_definitions.py index b5cd15f41af..6054d2a92ae 100644 --- a/openpype/lib/attribute_definitions.py +++ b/openpype/lib/attribute_definitions.py @@ -9,7 +9,7 @@ import six import clique -# Global variable which store attribude definitions by type +# Global variable which store attribute definitions by type # - default types are registered on import _attr_defs_by_type = {} @@ -93,7 +93,7 @@ def __call__(self, *args, **kwargs): @six.add_metaclass(AbstractAttrDefMeta) class AbstractAttrDef(object): - """Abstraction of attribute definiton. + """Abstraction of attribute definition. Each attribute definition must have implemented validation and conversion method. @@ -427,7 +427,7 @@ class EnumDef(AbstractAttrDef): """Enumeration of single item from items. Args: - items: Items definition that can be coverted using + items: Items definition that can be converted using 'prepare_enum_items'. default: Default value. Must be one key(value) from passed items. """ diff --git a/openpype/lib/events.py b/openpype/lib/events.py index 096201312fb..bed00fe6591 100644 --- a/openpype/lib/events.py +++ b/openpype/lib/events.py @@ -156,7 +156,7 @@ def set_enabled(self, enabled): self._enabled = enabled def deregister(self): - """Calling this funcion will cause that callback will be removed.""" + """Calling this function will cause that callback will be removed.""" # Fake reference self._ref_valid = False diff --git a/openpype/lib/execute.py b/openpype/lib/execute.py index 759a4db0cb7..ef456395e78 100644 --- a/openpype/lib/execute.py +++ b/openpype/lib/execute.py @@ -8,6 +8,8 @@ from .log import Logger from .vendor_bin_utils import find_executable +from .openpype_version import is_running_from_build + # MSDN process creation flag (Windows only) CREATE_NO_WINDOW = 0x08000000 @@ -102,6 +104,10 @@ def run_subprocess(*args, **kwargs): if ( platform.system().lower() == "windows" and "creationflags" not in kwargs + # shell=True already tries to hide the console window + # and passing these creationflags then shows the window again + # so we avoid it for shell=True cases + and kwargs.get("shell") is not True ): kwargs["creationflags"] = ( subprocess.CREATE_NEW_PROCESS_GROUP @@ -157,18 +163,20 @@ def run_subprocess(*args, **kwargs): def clean_envs_for_openpype_process(env=None): - """Modify environemnts that may affect OpenPype process. + """Modify environments that may affect OpenPype process. Main reason to implement this function is to pop PYTHONPATH which may be affected by in-host environments. """ if env is None: env = os.environ - return { - key: value - for key, value in env.items() - if key not in ("PYTHONPATH",) - } + + # Exclude some environment variables from a copy of the environment + env = env.copy() + for key in ["PYTHONPATH", "PYTHONHOME"]: + env.pop(key, None) + + return env def run_openpype_process(*args, **kwargs): @@ -196,6 +204,11 @@ def run_openpype_process(*args, **kwargs): # Skip envs that can affect OpenPype process # - fill more if you find more env = clean_envs_for_openpype_process(os.environ) + + # Only keep OpenPype version if we are running from build. + if not is_running_from_build(): + env.pop("OPENPYPE_VERSION", None) + return run_subprocess(args, env=env, **kwargs) diff --git a/openpype/lib/file_transaction.py b/openpype/lib/file_transaction.py index fe70b37cb19..80f4e81f2c3 100644 --- a/openpype/lib/file_transaction.py +++ b/openpype/lib/file_transaction.py @@ -13,6 +13,16 @@ from shutil import copyfile +class DuplicateDestinationError(ValueError): + """Error raised when transfer destination already exists in queue. + + The error is only raised if `allow_queue_replacements` is False on the + FileTransaction instance and the added file to transfer is of a different + src file than the one already detected in the queue. + + """ + + class FileTransaction(object): """File transaction with rollback options. @@ -44,7 +54,7 @@ class FileTransaction(object): MODE_COPY = 0 MODE_HARDLINK = 1 - def __init__(self, log=None): + def __init__(self, log=None, allow_queue_replacements=False): if log is None: log = logging.getLogger("FileTransaction") @@ -60,6 +70,8 @@ def __init__(self, log=None): # Backup file location mapping to original locations self._backup_to_original = {} + self._allow_queue_replacements = allow_queue_replacements + def add(self, src, dst, mode=MODE_COPY): """Add a new file to transfer queue. @@ -82,6 +94,14 @@ def add(self, src, dst, mode=MODE_COPY): src, dst)) return else: + if not self._allow_queue_replacements: + raise DuplicateDestinationError( + "Transfer to destination is already in queue: " + "{} -> {}. It's not allowed to be replaced by " + "a new transfer from {}".format( + queued_src, dst, src + )) + self.log.warning("File transfer in queue replaced..") self.log.debug( "Removed from queue: {} -> {} replaced by {} -> {}".format( @@ -110,7 +130,7 @@ def process(self): path_same = self._same_paths(src, dst) if path_same: self.log.debug( - "Source and destionation are same files {} -> {}".format( + "Source and destination are same files {} -> {}".format( src, dst)) continue diff --git a/openpype/lib/path_templates.py b/openpype/lib/path_templates.py index 0f99efb430a..9be1736abf0 100644 --- a/openpype/lib/path_templates.py +++ b/openpype/lib/path_templates.py @@ -256,17 +256,18 @@ def set_templates(self, templates): elif isinstance(templates, dict): self._raw_templates = copy.deepcopy(templates) self._templates = templates - self._objected_templates = self.create_ojected_templates(templates) + self._objected_templates = self.create_objected_templates( + templates) else: raise TypeError("<{}> argument must be a dict, not {}.".format( self.__class__.__name__, str(type(templates)) )) def __getitem__(self, key): - return self.templates[key] + return self.objected_templates[key] def get(self, key, *args, **kwargs): - return self.templates.get(key, *args, **kwargs) + return self.objected_templates.get(key, *args, **kwargs) @property def raw_templates(self): @@ -280,8 +281,21 @@ def templates(self): def objected_templates(self): return self._objected_templates - @classmethod - def create_ojected_templates(cls, templates): + def _create_template_object(self, template): + """Create template object from a template string. + + Separated into method to give option change class of templates. + + Args: + template (str): Template string. + + Returns: + StringTemplate: Object of template. + """ + + return StringTemplate(template) + + def create_objected_templates(self, templates): if not isinstance(templates, dict): raise TypeError("Expected dict object, got {}".format( str(type(templates)) @@ -297,7 +311,7 @@ def create_ojected_templates(cls, templates): for key in tuple(item.keys()): value = item[key] if isinstance(value, six.string_types): - item[key] = StringTemplate(value) + item[key] = self._create_template_object(value) elif isinstance(value, dict): inner_queue.append(value) return objected_templates diff --git a/openpype/lib/transcoding.py b/openpype/lib/transcoding.py index 799693554fa..57968b37002 100644 --- a/openpype/lib/transcoding.py +++ b/openpype/lib/transcoding.py @@ -540,7 +540,7 @@ def convert_for_ffmpeg( continue # Remove attributes that have string value longer than allowed length - # for ffmpeg or when containt unallowed symbols + # for ffmpeg or when contain unallowed symbols erase_reason = "Missing reason" erase_attribute = False if len(attr_value) > MAX_FFMPEG_STRING_LEN: @@ -680,7 +680,7 @@ def convert_input_paths_for_ffmpeg( continue # Remove attributes that have string value longer than allowed - # length for ffmpeg or when containt unallowed symbols + # length for ffmpeg or when containing unallowed symbols erase_reason = "Missing reason" erase_attribute = False if len(attr_value) > MAX_FFMPEG_STRING_LEN: @@ -968,7 +968,7 @@ def _ffmpeg_dnxhd_codec_args(stream_data, source_ffmpeg_cmd): if source_ffmpeg_cmd: # Define bitrate arguments bit_rate_args = ("-b:v", "-vb",) - # Seprate the two variables in case something else should be copied + # Separate the two variables in case something else should be copied # from source command copy_args = [] copy_args.extend(bit_rate_args) diff --git a/openpype/lib/vendor_bin_utils.py b/openpype/lib/vendor_bin_utils.py index 00dd1955fee..f27c78d486c 100644 --- a/openpype/lib/vendor_bin_utils.py +++ b/openpype/lib/vendor_bin_utils.py @@ -224,18 +224,26 @@ def find_tool_in_custom_paths(paths, tool, validation_func=None): def _check_args_returncode(args): try: - # Python 2 compatibility where DEVNULL is not available + kwargs = {} + if platform.system().lower() == "windows": + kwargs["creationflags"] = ( + subprocess.CREATE_NEW_PROCESS_GROUP + | getattr(subprocess, "DETACHED_PROCESS", 0) + | getattr(subprocess, "CREATE_NO_WINDOW", 0) + ) + if hasattr(subprocess, "DEVNULL"): proc = subprocess.Popen( args, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, + **kwargs ) proc.wait() else: with open(os.devnull, "w") as devnull: proc = subprocess.Popen( - args, stdout=devnull, stderr=devnull, + args, stdout=devnull, stderr=devnull, **kwargs ) proc.wait() @@ -252,7 +260,7 @@ def _oiio_executable_validation(filepath): that it can be executed. For that is used '--help' argument which is fast and does not need any other inputs. - Any possible crash of missing libraries or invalid build should be catched. + Any possible crash of missing libraries or invalid build should be caught. Main reason is to validate if executable can be executed on OS just running which can be issue ob linux machines. @@ -321,7 +329,7 @@ def _ffmpeg_executable_validation(filepath): that it can be executed. For that is used '-version' argument which is fast and does not need any other inputs. - Any possible crash of missing libraries or invalid build should be catched. + Any possible crash of missing libraries or invalid build should be caught. Main reason is to validate if executable can be executed on OS just running which can be issue ob linux machines. diff --git a/openpype/modules/base.py b/openpype/modules/base.py index 0fd21492e82..ed1eeb04cd5 100644 --- a/openpype/modules/base.py +++ b/openpype/modules/base.py @@ -472,7 +472,7 @@ def modify_application_launch_arguments(self, application, env): Args: application (Application): Application that is launched. - env (dict): Current environemnt variables. + env (dict): Current environment variables. """ pass @@ -622,7 +622,7 @@ def initialize_modules(self): # Check if class is abstract (Developing purpose) if inspect.isabstract(modules_item): - # Find missing implementations by convetion on `abc` module + # Find abstract attributes by convention on `abc` module not_implemented = [] for attr_name in dir(modules_item): attr = getattr(modules_item, attr_name, None) @@ -708,13 +708,13 @@ def get_enabled_modules(self): ] def collect_global_environments(self): - """Helper to collect global enviornment variabled from modules. + """Helper to collect global environment variabled from modules. Returns: dict: Global environment variables from enabled modules. Raises: - AssertionError: Gobal environment variables must be unique for + AssertionError: Global environment variables must be unique for all modules. """ module_envs = {} @@ -1174,7 +1174,7 @@ def on_exit(self): def get_module_settings_defs(): - """Check loaded addons/modules for existence of thei settings definition. + """Check loaded addons/modules for existence of their settings definition. Check if OpenPype addon/module as python module has class that inherit from `ModuleSettingsDef` in python module variables (imported @@ -1204,7 +1204,7 @@ def get_module_settings_defs(): continue if inspect.isabstract(attr): - # Find missing implementations by convetion on `abc` module + # Find missing implementations by convention on `abc` module not_implemented = [] for attr_name in dir(attr): attr = getattr(attr, attr_name, None) @@ -1293,7 +1293,7 @@ def save_defaults(self, top_key, data): class ModuleSettingsDef(BaseModuleSettingsDef): - """Settings definiton with separated system and procect settings parts. + """Settings definition with separated system and procect settings parts. Reduce conditions that must be checked and adds predefined methods for each case. diff --git a/openpype/modules/clockify/clockify_api.py b/openpype/modules/clockify/clockify_api.py index 80979c83ab2..47af002f7ab 100644 --- a/openpype/modules/clockify/clockify_api.py +++ b/openpype/modules/clockify/clockify_api.py @@ -247,7 +247,7 @@ def start_time_entry( current_timer = self.get_in_progress() # Check if is currently run another times and has same values - # DO not restart the timer, if it is already running for curent task + # DO not restart the timer, if it is already running for current task if current_timer: current_timer_hierarchy = current_timer.get("description") current_project_id = current_timer.get("projectId") diff --git a/openpype/modules/clockify/clockify_module.py b/openpype/modules/clockify/clockify_module.py index 200a268ad7c..b6efec79074 100644 --- a/openpype/modules/clockify/clockify_module.py +++ b/openpype/modules/clockify/clockify_module.py @@ -76,7 +76,7 @@ def tray_exit(self, *_a, **_kw): return def get_plugin_paths(self): - """Implementaton of IPluginPaths to get plugin paths.""" + """Implementation of IPluginPaths to get plugin paths.""" actions_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "launcher_actions" ) diff --git a/openpype/modules/clockify/widgets.py b/openpype/modules/clockify/widgets.py index 8c28f38b6ef..86e67569f2b 100644 --- a/openpype/modules/clockify/widgets.py +++ b/openpype/modules/clockify/widgets.py @@ -34,7 +34,7 @@ def __init__(self, messages, title): def _ui_layout(self, messages): if not messages: - messages = ["*Misssing messages (This is a bug)*", ] + messages = ["*Missing messages (This is a bug)*", ] elif not isinstance(messages, (tuple, list)): messages = [messages, ] diff --git a/openpype/modules/deadline/plugins/publish/collect_pools.py b/openpype/modules/deadline/plugins/publish/collect_pools.py index 48130848d51..e221eb00ea6 100644 --- a/openpype/modules/deadline/plugins/publish/collect_pools.py +++ b/openpype/modules/deadline/plugins/publish/collect_pools.py @@ -3,21 +3,60 @@ """ import pyblish.api +from openpype.lib import TextDef +from openpype.pipeline.publish import OpenPypePyblishPluginMixin -class CollectDeadlinePools(pyblish.api.InstancePlugin): +class CollectDeadlinePools(pyblish.api.InstancePlugin, + OpenPypePyblishPluginMixin): """Collect pools from instance if present, from Setting otherwise.""" order = pyblish.api.CollectorOrder + 0.420 label = "Collect Deadline Pools" - families = ["rendering", "render.farm", "renderFarm", "renderlayer"] + families = ["rendering", + "render.farm", + "renderFarm", + "renderlayer", + "maxrender"] primary_pool = None secondary_pool = None + @classmethod + def apply_settings(cls, project_settings, system_settings): + # deadline.publish.CollectDeadlinePools + settings = project_settings["deadline"]["publish"]["CollectDeadlinePools"] # noqa + cls.primary_pool = settings.get("primary_pool", None) + cls.secondary_pool = settings.get("secondary_pool", None) + def process(self, instance): + + attr_values = self.get_attr_values_from_data(instance.data) if not instance.data.get("primaryPool"): - instance.data["primaryPool"] = self.primary_pool or "none" + instance.data["primaryPool"] = ( + attr_values.get("primaryPool") or self.primary_pool or "none" + ) if not instance.data.get("secondaryPool"): - instance.data["secondaryPool"] = self.secondary_pool or "none" + instance.data["secondaryPool"] = ( + attr_values.get("secondaryPool") or self.secondary_pool or "none" # noqa + ) + + @classmethod + def get_attribute_defs(cls): + # TODO: Preferably this would be an enum for the user + # but the Deadline server URL can be dynamic and + # can be set per render instance. Since get_attribute_defs + # can't be dynamic unfortunately EnumDef isn't possible (yet?) + # pool_names = self.deadline_module.get_deadline_pools(deadline_url, + # self.log) + # secondary_pool_names = ["-"] + pool_names + + return [ + TextDef("primaryPool", + label="Primary Pool", + default=cls.primary_pool), + TextDef("secondaryPool", + label="Secondary Pool", + default=cls.secondary_pool) + ] diff --git a/openpype/modules/deadline/plugins/publish/submit_celaction_deadline.py b/openpype/modules/deadline/plugins/publish/submit_celaction_deadline.py index 038ee4fc034..bcf08507687 100644 --- a/openpype/modules/deadline/plugins/publish/submit_celaction_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_celaction_deadline.py @@ -106,7 +106,7 @@ def payload_submit(self, # define chunk and priority chunk_size = instance.context.data.get("chunk") - if chunk_size == 0: + if not chunk_size: chunk_size = self.deadline_chunk_size # search for %02d pattern in name, and padding number diff --git a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py index aff34c7e4a8..5c598df94b0 100644 --- a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py @@ -32,7 +32,7 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin, label = "Submit Nuke to Deadline" order = pyblish.api.IntegratorOrder + 0.1 hosts = ["nuke"] - families = ["render", "prerender.farm"] + families = ["render", "prerender"] optional = True targets = ["local"] @@ -66,7 +66,7 @@ def get_attribute_defs(cls): ), NumberDef( "concurrency", - label="Concurency", + label="Concurrency", default=cls.concurrent_tasks, decimals=0, minimum=1, @@ -76,13 +76,26 @@ def get_attribute_defs(cls): "use_gpu", default=cls.use_gpu, label="Use GPU" + ), + BoolDef( + "suspend_publish", + default=False, + label="Suspend publish" ) ] def process(self, instance): + if not instance.data.get("farm"): + self.log.info("Skipping local instance.") + return + instance.data["attributeValues"] = self.get_attr_values_from_data( instance.data) + # add suspend_publish attributeValue to instance data + instance.data["suspend_publish"] = instance.data["attributeValues"][ + "suspend_publish"] + instance.data["toBeRenderedOn"] = "deadline" families = instance.data["families"] @@ -168,10 +181,10 @@ def process(self, instance): resp.json()["_id"]) # redefinition of families - if "render.farm" in families: + if "render" in instance.data["family"]: instance.data['family'] = 'write' families.insert(0, "render2d") - elif "prerender.farm" in families: + elif "prerender" in instance.data["family"]: instance.data['family'] = 'write' families.insert(0, "prerender") instance.data["families"] = families diff --git a/openpype/modules/deadline/plugins/publish/submit_publish_job.py b/openpype/modules/deadline/plugins/publish/submit_publish_job.py index 53c09ad22f9..4765772bcff 100644 --- a/openpype/modules/deadline/plugins/publish/submit_publish_job.py +++ b/openpype/modules/deadline/plugins/publish/submit_publish_job.py @@ -85,10 +85,10 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): These jobs are dependent on a deadline or muster job submission prior to this plug-in. - - In case of Deadline, it creates dependend job on farm publishing + - In case of Deadline, it creates dependent job on farm publishing rendered image sequence. - - In case of Muster, there is no need for such thing as dependend job, + - In case of Muster, there is no need for such thing as dependent job, post action will be executed and rendered sequence will be published. Options in instance.data: @@ -108,7 +108,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): - publishJobState (str, Optional): "Active" or "Suspended" This defaults to "Suspended" - - expectedFiles (list or dict): explained bellow + - expectedFiles (list or dict): explained below """ @@ -158,8 +158,8 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): # regex for finding frame number in string R_FRAME_NUMBER = re.compile(r'.+\.(?P[0-9]+)\..+') - # mapping of instance properties to be transfered to new instance for every - # specified family + # mapping of instance properties to be transferred to new instance + # for every specified family instance_transfer = { "slate": ["slateFrames", "slate"], "review": ["lutPath"], @@ -398,7 +398,7 @@ def _copy_extend_frames(self, instance, representation): continue r_col.indexes.remove(frame) - # now we need to translate published names from represenation + # now we need to translate published names from representation # back. This is tricky, right now we'll just use same naming # and only switch frame numbers resource_files = [] @@ -535,7 +535,7 @@ def _create_instances_for_aov( if preview: new_instance["review"] = True - # create represenation + # create representation if isinstance(col, (list, tuple)): files = [os.path.basename(f) for f in col] else: @@ -748,7 +748,7 @@ def process(self, instance): # type: (pyblish.api.Instance) -> None """Process plugin. - Detect type of renderfarm submission and create and post dependend job + Detect type of renderfarm submission and create and post dependent job in case of Deadline. It creates json file with metadata needed for publishing in directory of render. @@ -756,6 +756,10 @@ def process(self, instance): instance (pyblish.api.Instance): Instance data. """ + if not instance.data.get("farm"): + self.log.info("Skipping local instance.") + return + data = instance.data.copy() context = instance.context self.context = context @@ -940,17 +944,28 @@ def process(self, instance): # we cannot attach AOVs to other subsets as we consider every # AOV subset of its own. - config = instance.data["colorspaceConfig"] additional_data = { "renderProducts": instance.data["renderProducts"], "colorspaceConfig": instance.data["colorspaceConfig"], "display": instance.data["colorspaceDisplay"], - "view": instance.data["colorspaceView"], - "colorspaceTemplate": config.replace( - str(context.data["anatomy"].roots["work"]), "{root[work]}" - ) + "view": instance.data["colorspaceView"] } + # Get templated path from absolute config path. + anatomy = instance.context.data["anatomy"] + colorspaceTemplate = instance.data["colorspaceConfig"] + success, rootless_staging_dir = ( + anatomy.find_root_template_from_path(colorspaceTemplate) + ) + if success: + colorspaceTemplate = rootless_staging_dir + else: + self.log.warning(( + "Could not find root path for remapping \"{}\"." + " This may cause issues on farm." + ).format(colorspaceTemplate)) + additional_data["colorspaceTemplate"] = colorspaceTemplate + if len(data.get("attachTo")) > 0: assert len(data.get("expectedFiles")[0].keys()) == 1, ( "attaching multiple AOVs or renderable cameras to " @@ -982,7 +997,7 @@ def process(self, instance): instances = [instance_skeleton_data] # if we are attaching to other subsets, create copy of existing - # instances, change data to match thats subset and replace + # instances, change data to match its subset and replace # existing instances with modified data if instance.data.get("attachTo"): self.log.info("Attaching render to subset:") diff --git a/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py b/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py index 78eed17c986..7c8ab62d4d8 100644 --- a/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py +++ b/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py @@ -17,10 +17,18 @@ class ValidateDeadlinePools(OptionalPyblishPluginMixin, label = "Validate Deadline Pools" order = pyblish.api.ValidatorOrder - families = ["rendering", "render.farm", "renderFarm", "renderlayer"] + families = ["rendering", + "render.farm", + "renderFarm", + "renderlayer", + "maxrender"] optional = True def process(self, instance): + if not instance.data.get("farm"): + self.log.info("Skipping local instance.") + return + # get default deadline webservice url from deadline module deadline_url = instance.context.data["defaultDeadline"] self.log.info("deadline_url::{}".format(deadline_url)) diff --git a/openpype/modules/example_addons/example_addon/addon.py b/openpype/modules/example_addons/example_addon/addon.py index ead647b41d0..be1d3ff9205 100644 --- a/openpype/modules/example_addons/example_addon/addon.py +++ b/openpype/modules/example_addons/example_addon/addon.py @@ -44,7 +44,7 @@ def get_settings_root_path(self): class ExampleAddon(OpenPypeAddOn, IPluginPaths, ITrayAction): - """This Addon has defined it's settings and interface. + """This Addon has defined its settings and interface. This example has system settings with an enabled option. And use few other interfaces: diff --git a/openpype/modules/ftrack/event_handlers_server/action_clone_review_session.py b/openpype/modules/ftrack/event_handlers_server/action_clone_review_session.py index 1ad7a17785e..333228c6999 100644 --- a/openpype/modules/ftrack/event_handlers_server/action_clone_review_session.py +++ b/openpype/modules/ftrack/event_handlers_server/action_clone_review_session.py @@ -44,7 +44,7 @@ def clone_review_session(session, entity): class CloneReviewSession(ServerAction): '''Generate Client Review action - `label` a descriptive string identifing your action. + `label` a descriptive string identifying your action. `varaint` To group actions together, give them the same label and specify a unique variant per action. `identifier` a unique identifier for your action. diff --git a/openpype/modules/ftrack/event_handlers_server/action_create_review_session.py b/openpype/modules/ftrack/event_handlers_server/action_create_review_session.py index 21382007a0f..42a279e3333 100644 --- a/openpype/modules/ftrack/event_handlers_server/action_create_review_session.py +++ b/openpype/modules/ftrack/event_handlers_server/action_create_review_session.py @@ -230,7 +230,7 @@ def _process_review_session( if not today_session_name: continue - # Find matchin review session + # Find matching review session project_review_sessions = review_sessions_by_project_id[project_id] todays_session = None yesterdays_session = None diff --git a/openpype/modules/ftrack/event_handlers_server/action_prepare_project.py b/openpype/modules/ftrack/event_handlers_server/action_prepare_project.py index 332648cd028..02231cbe3ce 100644 --- a/openpype/modules/ftrack/event_handlers_server/action_prepare_project.py +++ b/openpype/modules/ftrack/event_handlers_server/action_prepare_project.py @@ -124,7 +124,7 @@ def prepare_root_items(self, project_anatom_settings): root_items.append({ "type": "label", "value": ( - "

    NOTE: Roots are crutial for path filling" + "

    NOTE: Roots are crucial for path filling" " (and creating folder structure).

    " ) }) diff --git a/openpype/modules/ftrack/event_handlers_server/action_push_frame_values_to_task.py b/openpype/modules/ftrack/event_handlers_server/action_push_frame_values_to_task.py index 1209375f821..a698195c59d 100644 --- a/openpype/modules/ftrack/event_handlers_server/action_push_frame_values_to_task.py +++ b/openpype/modules/ftrack/event_handlers_server/action_push_frame_values_to_task.py @@ -9,7 +9,7 @@ class PushHierValuesToNonHier(ServerAction): - """Action push hierarchical custom attribute values to non hierarchical. + """Action push hierarchical custom attribute values to non-hierarchical. Hierarchical value is also pushed to their task entities. @@ -119,17 +119,109 @@ def attrs_configurations(self, session, object_ids, interest_attributes): self.join_query_keys(object_ids) )).all() - output = {} + attrs_by_obj_id = collections.defaultdict(list) hiearchical = [] for attr in attrs: if attr["is_hierarchical"]: hiearchical.append(attr) continue obj_id = attr["object_type_id"] - if obj_id not in output: - output[obj_id] = [] - output[obj_id].append(attr) - return output, hiearchical + attrs_by_obj_id[obj_id].append(attr) + return attrs_by_obj_id, hiearchical + + def query_attr_value( + self, + session, + hier_attrs, + attrs_by_obj_id, + dst_object_type_ids, + task_entity_ids, + non_task_entity_ids, + parent_id_by_entity_id + ): + all_non_task_ids_with_parents = set() + for entity_id in non_task_entity_ids: + all_non_task_ids_with_parents.add(entity_id) + _entity_id = entity_id + while True: + parent_id = parent_id_by_entity_id.get(_entity_id) + if ( + parent_id is None + or parent_id in all_non_task_ids_with_parents + ): + break + all_non_task_ids_with_parents.add(parent_id) + _entity_id = parent_id + + all_entity_ids = ( + set(all_non_task_ids_with_parents) + | set(task_entity_ids) + ) + attr_ids = {attr["id"] for attr in hier_attrs} + for obj_id in dst_object_type_ids: + attrs = attrs_by_obj_id.get(obj_id) + if attrs is not None: + for attr in attrs: + attr_ids.add(attr["id"]) + + real_values_by_entity_id = { + entity_id: {} + for entity_id in all_entity_ids + } + + attr_values = query_custom_attributes( + session, attr_ids, all_entity_ids, True + ) + for item in attr_values: + entity_id = item["entity_id"] + attr_id = item["configuration_id"] + real_values_by_entity_id[entity_id][attr_id] = item["value"] + + # Fill hierarchical values + hier_attrs_key_by_id = { + hier_attr["id"]: hier_attr + for hier_attr in hier_attrs + } + hier_values_per_entity_id = {} + for entity_id in all_non_task_ids_with_parents: + real_values = real_values_by_entity_id[entity_id] + hier_values_per_entity_id[entity_id] = {} + for attr_id, attr in hier_attrs_key_by_id.items(): + key = attr["key"] + hier_values_per_entity_id[entity_id][key] = ( + real_values.get(attr_id) + ) + + output = {} + for entity_id in non_task_entity_ids: + output[entity_id] = {} + for attr in hier_attrs_key_by_id.values(): + key = attr["key"] + value = hier_values_per_entity_id[entity_id][key] + tried_ids = set() + if value is None: + tried_ids.add(entity_id) + _entity_id = entity_id + while value is None: + parent_id = parent_id_by_entity_id.get(_entity_id) + if not parent_id: + break + value = hier_values_per_entity_id[parent_id][key] + if value is not None: + break + _entity_id = parent_id + tried_ids.add(parent_id) + + if value is None: + value = attr["default"] + + if value is not None: + for ent_id in tried_ids: + hier_values_per_entity_id[ent_id][key] = value + + output[entity_id][key] = value + + return real_values_by_entity_id, output def propagate_values(self, session, event, selected_entities): ftrack_settings = self.get_ftrack_settings( @@ -156,29 +248,24 @@ def propagate_values(self, session, event, selected_entities): } task_object_type = object_types_by_low_name["task"] - destination_object_types = [task_object_type] + dst_object_type_ids = {task_object_type["id"]} for ent_type in interest_entity_types: obj_type = object_types_by_low_name.get(ent_type) - if obj_type and obj_type not in destination_object_types: - destination_object_types.append(obj_type) - - destination_object_type_ids = set( - obj_type["id"] - for obj_type in destination_object_types - ) + if obj_type: + dst_object_type_ids.add(obj_type["id"]) interest_attributes = action_settings["interest_attributes"] # Find custom attributes definitions attrs_by_obj_id, hier_attrs = self.attrs_configurations( - session, destination_object_type_ids, interest_attributes + session, dst_object_type_ids, interest_attributes ) # Filter destination object types if they have any object specific # custom attribute - for obj_id in tuple(destination_object_type_ids): + for obj_id in tuple(dst_object_type_ids): if obj_id not in attrs_by_obj_id: - destination_object_type_ids.remove(obj_id) + dst_object_type_ids.remove(obj_id) - if not destination_object_type_ids: + if not dst_object_type_ids: # TODO report that there are not matching custom attributes return { "success": True, @@ -192,14 +279,14 @@ def propagate_values(self, session, event, selected_entities): session, selected_ids, project_entity, - destination_object_type_ids + dst_object_type_ids ) self.log.debug("Preparing whole project hierarchy by ids.") entities_by_obj_id = { obj_id: [] - for obj_id in destination_object_type_ids + for obj_id in dst_object_type_ids } self.log.debug("Filtering Task entities.") @@ -223,10 +310,16 @@ def propagate_values(self, session, event, selected_entities): "message": "Nothing to do in your selection." } - self.log.debug("Getting Hierarchical custom attribute values parents.") - hier_values_by_entity_id = self.get_hier_values( + self.log.debug("Getting Custom attribute values.") + ( + real_values_by_entity_id, + hier_values_by_entity_id + ) = self.query_attr_value( session, hier_attrs, + attrs_by_obj_id, + dst_object_type_ids, + task_entity_ids, non_task_entity_ids, parent_id_by_entity_id ) @@ -237,7 +330,8 @@ def propagate_values(self, session, event, selected_entities): hier_attrs, task_entity_ids, hier_values_by_entity_id, - parent_id_by_entity_id + parent_id_by_entity_id, + real_values_by_entity_id ) self.log.debug("Setting values to entities themselves.") @@ -245,7 +339,8 @@ def propagate_values(self, session, event, selected_entities): session, entities_by_obj_id, attrs_by_obj_id, - hier_values_by_entity_id + hier_values_by_entity_id, + real_values_by_entity_id ) return True @@ -322,112 +417,64 @@ def all_hierarchy_entities( return parent_id_by_entity_id, filtered_entities - def get_hier_values( - self, - session, - hier_attrs, - focus_entity_ids, - parent_id_by_entity_id - ): - all_ids_with_parents = set() - for entity_id in focus_entity_ids: - all_ids_with_parents.add(entity_id) - _entity_id = entity_id - while True: - parent_id = parent_id_by_entity_id.get(_entity_id) - if ( - not parent_id - or parent_id in all_ids_with_parents - ): - break - all_ids_with_parents.add(parent_id) - _entity_id = parent_id - - hier_attr_ids = tuple(hier_attr["id"] for hier_attr in hier_attrs) - hier_attrs_key_by_id = { - hier_attr["id"]: hier_attr["key"] - for hier_attr in hier_attrs - } - - values_per_entity_id = {} - for entity_id in all_ids_with_parents: - values_per_entity_id[entity_id] = {} - for key in hier_attrs_key_by_id.values(): - values_per_entity_id[entity_id][key] = None - - values = query_custom_attributes( - session, hier_attr_ids, all_ids_with_parents, True - ) - for item in values: - entity_id = item["entity_id"] - key = hier_attrs_key_by_id[item["configuration_id"]] - - values_per_entity_id[entity_id][key] = item["value"] - - output = {} - for entity_id in focus_entity_ids: - output[entity_id] = {} - for key in hier_attrs_key_by_id.values(): - value = values_per_entity_id[entity_id][key] - tried_ids = set() - if value is None: - tried_ids.add(entity_id) - _entity_id = entity_id - while value is None: - parent_id = parent_id_by_entity_id.get(_entity_id) - if not parent_id: - break - value = values_per_entity_id[parent_id][key] - if value is not None: - break - _entity_id = parent_id - tried_ids.add(parent_id) - - if value is not None: - for ent_id in tried_ids: - values_per_entity_id[ent_id][key] = value - - output[entity_id][key] = value - return output - def set_task_attr_values( self, session, hier_attrs, task_entity_ids, hier_values_by_entity_id, - parent_id_by_entity_id + parent_id_by_entity_id, + real_values_by_entity_id ): hier_attr_id_by_key = { attr["key"]: attr["id"] for attr in hier_attrs } + filtered_task_ids = set() for task_id in task_entity_ids: - parent_id = parent_id_by_entity_id.get(task_id) or {} + parent_id = parent_id_by_entity_id.get(task_id) parent_values = hier_values_by_entity_id.get(parent_id) - if not parent_values: - continue + if parent_values: + filtered_task_ids.add(task_id) + + if not filtered_task_ids: + return + for task_id in filtered_task_ids: + parent_id = parent_id_by_entity_id[task_id] + parent_values = hier_values_by_entity_id[parent_id] hier_values_by_entity_id[task_id] = {} + real_task_attr_values = real_values_by_entity_id[task_id] for key, value in parent_values.items(): hier_values_by_entity_id[task_id][key] = value + if value is None: + continue + configuration_id = hier_attr_id_by_key[key] _entity_key = collections.OrderedDict([ ("configuration_id", configuration_id), ("entity_id", task_id) ]) - - session.recorded_operations.push( - ftrack_api.operation.UpdateEntityOperation( - "ContextCustomAttributeValue", + op = None + if configuration_id not in real_task_attr_values: + op = ftrack_api.operation.CreateEntityOperation( + "CustomAttributeValue", + _entity_key, + {"value": value} + ) + elif real_task_attr_values[configuration_id] != value: + op = ftrack_api.operation.UpdateEntityOperation( + "CustomAttributeValue", _entity_key, "value", - ftrack_api.symbol.NOT_SET, + real_task_attr_values[configuration_id], value ) - ) - if len(session.recorded_operations) > 100: - session.commit() + + if op is not None: + session.recorded_operations.push(op) + if len(session.recorded_operations) > 100: + session.commit() session.commit() @@ -436,39 +483,68 @@ def push_values_to_entities( session, entities_by_obj_id, attrs_by_obj_id, - hier_values_by_entity_id + hier_values_by_entity_id, + real_values_by_entity_id ): + """Push values from hierarchical custom attributes to non-hierarchical. + + Args: + session (ftrack_api.Sessison): Session which queried entities, + values and which is used for change propagation. + entities_by_obj_id (dict[str, list[str]]): TypedContext + ftrack entity ids where the attributes are propagated by their + object ids. + attrs_by_obj_id (dict[str, ftrack_api.Entity]): Objects of + 'CustomAttributeConfiguration' by their ids. + hier_values_by_entity_id (doc[str, dict[str, Any]]): Attribute + values by entity id and by their keys. + real_values_by_entity_id (doc[str, dict[str, Any]]): Real attribute + values of entities. + """ + for object_id, entity_ids in entities_by_obj_id.items(): attrs = attrs_by_obj_id.get(object_id) if not attrs or not entity_ids: continue - for attr in attrs: - for entity_id in entity_ids: - value = ( - hier_values_by_entity_id - .get(entity_id, {}) - .get(attr["key"]) - ) + for entity_id in entity_ids: + real_values = real_values_by_entity_id.get(entity_id) + hier_values = hier_values_by_entity_id.get(entity_id) + if hier_values is None: + continue + + for attr in attrs: + attr_id = attr["id"] + attr_key = attr["key"] + value = hier_values.get(attr_key) if value is None: continue _entity_key = collections.OrderedDict([ - ("configuration_id", attr["id"]), + ("configuration_id", attr_id), ("entity_id", entity_id) ]) - session.recorded_operations.push( - ftrack_api.operation.UpdateEntityOperation( - "ContextCustomAttributeValue", + op = None + if attr_id not in real_values: + op = ftrack_api.operation.CreateEntityOperation( + "CustomAttributeValue", + _entity_key, + {"value": value} + ) + elif real_values[attr_id] != value: + op = ftrack_api.operation.UpdateEntityOperation( + "CustomAttributeValue", _entity_key, "value", - ftrack_api.symbol.NOT_SET, + real_values[attr_id], value ) - ) - if len(session.recorded_operations) > 100: - session.commit() + + if op is not None: + session.recorded_operations.push(op) + if len(session.recorded_operations) > 100: + session.commit() session.commit() diff --git a/openpype/modules/ftrack/event_handlers_server/action_tranfer_hierarchical_values.py b/openpype/modules/ftrack/event_handlers_server/action_tranfer_hierarchical_values.py index d160b7200db..f6899843a39 100644 --- a/openpype/modules/ftrack/event_handlers_server/action_tranfer_hierarchical_values.py +++ b/openpype/modules/ftrack/event_handlers_server/action_tranfer_hierarchical_values.py @@ -12,7 +12,7 @@ class TransferHierarchicalValues(ServerAction): - """Transfer values across hierarhcical attributes. + """Transfer values across hierarchical attributes. Aalso gives ability to convert types meanwhile. That is limited to conversions between numbers and strings @@ -67,7 +67,7 @@ def _selection_interface(self, session, event_values=None): "type": "label", "value": ( "Didn't found custom attributes" - " that can be transfered." + " that can be transferred." ) }] } diff --git a/openpype/modules/ftrack/event_handlers_server/event_next_task_update.py b/openpype/modules/ftrack/event_handlers_server/event_next_task_update.py index a65ae46545c..a100c34f679 100644 --- a/openpype/modules/ftrack/event_handlers_server/event_next_task_update.py +++ b/openpype/modules/ftrack/event_handlers_server/event_next_task_update.py @@ -279,7 +279,7 @@ def set_next_task_statuses( except Exception: session.rollback() self.log.warning( - "\"{}\" status couldnt be set to \"{}\"".format( + "\"{}\" status couldn't be set to \"{}\"".format( ent_path, new_status["name"] ), exc_info=True diff --git a/openpype/modules/ftrack/event_handlers_server/event_push_frame_values_to_task.py b/openpype/modules/ftrack/event_handlers_server/event_push_frame_values_to_task.py index dc76920a57c..ed630ad59d9 100644 --- a/openpype/modules/ftrack/event_handlers_server/event_push_frame_values_to_task.py +++ b/openpype/modules/ftrack/event_handlers_server/event_push_frame_values_to_task.py @@ -1,6 +1,6 @@ import collections -import datetime import copy +from typing import Any import ftrack_api from openpype_modules.ftrack.lib import ( @@ -9,13 +9,30 @@ ) -class PushFrameValuesToTaskEvent(BaseEvent): +class PushHierValuesToNonHierEvent(BaseEvent): + """Push value changes between hierarchical and non-hierarchical attributes. + + Changes of non-hierarchical attributes are pushed to hierarchical and back. + The attributes must have same definition of custom attribute. + + Handler does not handle changes of hierarchical parents. So if entity does + not have explicitly set value of hierarchical attribute and any parent + would change it the change would not be propagated. + + The handler also push the value to task entity on task creation + and movement. To push values between hierarchical & non-hierarchical + add 'Task' to entity types in settings. + + Todos: + Task attribute values push on create/move should be possible to + enabled by settings. + """ + # Ignore event handler by default cust_attrs_query = ( "select id, key, object_type_id, is_hierarchical, default" " from CustomAttributeConfiguration" - " where key in ({}) and" - " (object_type_id in ({}) or is_hierarchical is true)" + " where key in ({})" ) _cached_task_object_id = None @@ -26,35 +43,35 @@ class PushFrameValuesToTaskEvent(BaseEvent): settings_key = "sync_hier_entity_attributes" - def session_user_id(self, session): - if self._cached_user_id is None: - user = session.query( - "User where username is \"{}\"".format(session.api_user) - ).one() - self._cached_user_id = user["id"] - return self._cached_user_id + def filter_entities_info( + self, event: ftrack_api.event.base.Event + ) -> dict[str, list[dict[str, Any]]]: + """Basic entities filter info we care about. - def launch(self, session, event): - filtered_entities_info = self.filter_entities_info(event) - if not filtered_entities_info: - return + This filtering is first of many filters. This does not query anything + from ftrack nor use settings. - for project_id, entities_info in filtered_entities_info.items(): - self.process_by_project(session, event, project_id, entities_info) + Args: + event (ftrack_api.event.base.Event): Ftrack event with update + information. + + Returns: + dict[str, list[dict[str, Any]]]: Filtered entity changes by + project id. + """ - def filter_entities_info(self, event): # Filter if event contain relevant data entities_info = event["data"].get("entities") if not entities_info: return - entities_info_by_project_id = {} + entities_info_by_project_id = collections.defaultdict(list) for entity_info in entities_info: - # Care only about tasks - if entity_info.get("entityType") != "task": + # Ignore removed entities + if entity_info.get("action") == "remove": continue - # Care only about changes of status + # Care only about information with changes of entities changes = entity_info.get("changes") if not changes: continue @@ -69,367 +86,287 @@ def filter_entities_info(self, event): if project_id is None: continue - # Skip `Task` entity type if parent didn't change - if entity_info["entity_type"].lower() == "task": - if ( - "parent_id" not in changes - or changes["parent_id"]["new"] is None - ): - continue - - if project_id not in entities_info_by_project_id: - entities_info_by_project_id[project_id] = [] entities_info_by_project_id[project_id].append(entity_info) return entities_info_by_project_id - def process_by_project(self, session, event, project_id, entities_info): - project_name = self.get_project_name_from_event( + def _get_attrs_configurations(self, session, interest_attributes): + """Get custom attribute configurations by name. + + Args: + session (ftrack_api.Session): Ftrack sesson. + interest_attributes (list[str]): Names of custom attributes + that should be synchronized. + + Returns: + tuple[dict[str, list], list]: Attributes by object id and + hierarchical attributes. + """ + + attrs = session.query(self.cust_attrs_query.format( + self.join_query_keys(interest_attributes) + )).all() + + attrs_by_obj_id = collections.defaultdict(list) + hier_attrs = [] + for attr in attrs: + if attr["is_hierarchical"]: + hier_attrs.append(attr) + continue + obj_id = attr["object_type_id"] + attrs_by_obj_id[obj_id].append(attr) + return attrs_by_obj_id, hier_attrs + + def _get_handler_project_settings( + self, + session: ftrack_api.Session, + event: ftrack_api.event.base.Event, + project_id: str + ) -> tuple[set[str], set[str]]: + """Get handler settings based on the project. + + Args: + session (ftrack_api.Session): Ftrack session. + event (ftrack_api.event.base.Event): Ftrack event which triggered + the changes. + project_id (str): Project id where the current changes are handled. + + Returns: + tuple[set[str], set[str]]: Attribute names we care about and + entity types we care about. + """ + + project_name: str = self.get_project_name_from_event( session, event, project_id ) # Load settings - project_settings = self.get_project_settings_from_event( - event, project_name + project_settings: dict[str, Any] = ( + self.get_project_settings_from_event(event, project_name) ) # Load status mapping from presets - event_settings = ( + event_settings: dict[str, Any] = ( project_settings ["ftrack"] ["events"] - ["sync_hier_entity_attributes"] + [self.settings_key] ) # Skip if event is not enabled if not event_settings["enabled"]: self.log.debug("Project \"{}\" has disabled {}".format( project_name, self.__class__.__name__ )) - return + return set(), set() - interest_attributes = event_settings["interest_attributes"] + interest_attributes: list[str] = event_settings["interest_attributes"] if not interest_attributes: self.log.info(( "Project \"{}\" does not have filled 'interest_attributes'," " skipping." )) - return - interest_entity_types = event_settings["interest_entity_types"] + + interest_entity_types: list[str] = ( + event_settings["interest_entity_types"]) if not interest_entity_types: self.log.info(( "Project \"{}\" does not have filled 'interest_entity_types'," " skipping." )) - return - - interest_attributes = set(interest_attributes) - interest_entity_types = set(interest_entity_types) - # Separate value changes and task parent changes - _entities_info = [] - added_entities = [] - added_entity_ids = set() - task_parent_changes = [] - for entity_info in entities_info: - if entity_info["entity_type"].lower() == "task": - task_parent_changes.append(entity_info) - elif entity_info.get("action") == "add": - added_entities.append(entity_info) - added_entity_ids.add(entity_info["entityId"]) - else: - _entities_info.append(entity_info) - entities_info = _entities_info - - # Filter entities info with changes - interesting_data, changed_keys_by_object_id = self.filter_changes( - session, event, entities_info, interest_attributes - ) - self.interesting_data_for_added( - session, - added_entities, - interest_attributes, - interesting_data, - changed_keys_by_object_id - ) - if not interesting_data and not task_parent_changes: - return - - # Prepare object types - object_types = session.query("select id, name from ObjectType").all() - object_types_by_name = {} - for object_type in object_types: - name_low = object_type["name"].lower() - object_types_by_name[name_low] = object_type - - # NOTE it would be nice to check if `interesting_data` do not contain - # value changs of tasks that were created or moved - # - it is a complex way how to find out - if interesting_data: - self.process_attribute_changes( - session, - object_types_by_name, - interesting_data, - changed_keys_by_object_id, - interest_entity_types, - interest_attributes, - added_entity_ids - ) - - if task_parent_changes: - self.process_task_parent_change( - session, object_types_by_name, task_parent_changes, - interest_entity_types, interest_attributes - ) + # Unify possible issues from settings ('Asset Build' -> 'assetbuild') + interest_entity_types: set[str] = { + entity_type.replace(" ", "").lower() + for entity_type in interest_entity_types + } + return set(interest_attributes), interest_entity_types - def process_task_parent_change( + def _entities_filter_by_settings( self, - session, - object_types_by_name, - task_parent_changes, - interest_entity_types, - interest_attributes + entities_info: list[dict[str, Any]], + interest_attributes: set[str], + interest_entity_types: set[str] ): - """Push custom attribute values if task parent has changed. - - Parent is changed if task is created or if is moved under different - entity. We don't care about all task changes only about those that - have it's parent in interest types (from settings). + new_entities_info = [] + for entity_info in entities_info: + entity_type_low = entity_info["entity_type"].lower() - Tasks hierarchical value should be unset or set based on parents - real hierarchical value and non hierarchical custom attribute value - should be set to hierarchical value. - """ + changes = entity_info["changes"] + # SPECIAL CASE: Capture changes of task created/moved under + # interested entity type + if ( + entity_type_low == "task" + and "parent_id" in changes + ): + # Direct parent is always second item in 'parents' and 'Task' + # must have at least one parent + parent_info = entity_info["parents"][1] + parent_entity_type = ( + parent_info["entity_type"] + .replace(" ", "") + .lower() + ) + if parent_entity_type in interest_entity_types: + new_entities_info.append(entity_info) + continue - # Store task ids which were created or moved under parent with entity - # type defined in settings (interest_entity_types). - task_ids = set() - # Store parent ids of matching task ids - matching_parent_ids = set() - # Store all entity ids of all entities to be able query hierarchical - # values. - whole_hierarchy_ids = set() - # Store parent id of each entity id - parent_id_by_entity_id = {} - for entity_info in task_parent_changes: - # Ignore entities with less parents than 2 - # NOTE entity itself is also part of "parents" value - parents = entity_info.get("parents") or [] - if len(parents) < 2: + # Skip if entity type is not enabled for attr value sync + if entity_type_low not in interest_entity_types: continue - parent_info = parents[1] - # Check if parent has entity type we care about. - if parent_info["entity_type"] not in interest_entity_types: - continue + valid_attr_change = entity_info.get("action") == "add" + for attr_key in interest_attributes: + if valid_attr_change: + break - task_ids.add(entity_info["entityId"]) - matching_parent_ids.add(parent_info["entityId"]) + if attr_key not in changes: + continue - # Store whole hierarchi of task entity - prev_id = None - for item in parents: - item_id = item["entityId"] - whole_hierarchy_ids.add(item_id) + if changes[attr_key]["new"] is not None: + valid_attr_change = True - if prev_id is None: - prev_id = item_id - continue + if not valid_attr_change: + continue - parent_id_by_entity_id[prev_id] = item_id - if item["entityType"] == "show": - break - prev_id = item_id + new_entities_info.append(entity_info) - # Just skip if nothing is interesting for our settings - if not matching_parent_ids: - return + return new_entities_info - # Query object type ids of parent ids for custom attribute - # definitions query - entities = session.query( - "select object_type_id from TypedContext where id in ({})".format( - self.join_query_keys(matching_parent_ids) - ) - ) + def propagate_attribute_changes( + self, + session, + interest_attributes, + entities_info, + attrs_by_obj_id, + hier_attrs, + real_values_by_entity_id, + hier_values_by_entity_id, + ): + hier_attr_ids_by_key = { + attr["key"]: attr["id"] + for attr in hier_attrs + } + filtered_interest_attributes = { + attr_name + for attr_name in interest_attributes + if attr_name in hier_attr_ids_by_key + } + attrs_keys_by_obj_id = {} + for obj_id, attrs in attrs_by_obj_id.items(): + attrs_keys_by_obj_id[obj_id] = { + attr["key"]: attr["id"] + for attr in attrs + } - # Prepare task object id - task_object_id = object_types_by_name["task"]["id"] + op_changes = [] + for entity_info in entities_info: + entity_id = entity_info["entityId"] + obj_id = entity_info["objectTypeId"] + # Skip attributes sync if does not have object specific custom + # attribute + if obj_id not in attrs_keys_by_obj_id: + continue + attr_keys = attrs_keys_by_obj_id[obj_id] + real_values = real_values_by_entity_id[entity_id] + hier_values = hier_values_by_entity_id[entity_id] + + changes = copy.deepcopy(entity_info["changes"]) + obj_id_attr_keys = { + attr_key + for attr_key in filtered_interest_attributes + if attr_key in attr_keys + } + if not obj_id_attr_keys: + continue - # All object ids for which we're querying custom attribute definitions - object_type_ids = set() - object_type_ids.add(task_object_id) - for entity in entities: - object_type_ids.add(entity["object_type_id"]) + value_by_key = {} + is_new_entity = entity_info.get("action") == "add" + for attr_key in obj_id_attr_keys: + if ( + attr_key in changes + and changes[attr_key]["new"] is not None + ): + value_by_key[attr_key] = changes[attr_key]["new"] - attrs_by_obj_id, hier_attrs = self.attrs_configurations( - session, object_type_ids, interest_attributes - ) + if not is_new_entity: + continue - # Skip if all task attributes are not available - task_attrs = attrs_by_obj_id.get(task_object_id) - if not task_attrs: - return + hier_attr_id = hier_attr_ids_by_key[attr_key] + attr_id = attr_keys[attr_key] + if hier_attr_id in real_values or attr_id in real_values: + continue - # Skip attributes that is not in both hierarchical and nonhierarchical - # TODO be able to push values if hierarchical is available - for key in interest_attributes: - if key not in hier_attrs: - task_attrs.pop(key, None) + value_by_key[attr_key] = hier_values[hier_attr_id] - elif key not in task_attrs: - hier_attrs.pop(key) + for key, new_value in value_by_key.items(): + if new_value is None: + continue - # Skip if nothing remained - if not task_attrs: - return + hier_id = hier_attr_ids_by_key[key] + std_id = attr_keys[key] + real_hier_value = real_values.get(hier_id) + real_std_value = real_values.get(std_id) + hier_value = hier_values[hier_id] + # Get right type of value for conversion + # - values in event are strings + type_value = real_hier_value + if type_value is None: + type_value = real_std_value + if type_value is None: + type_value = hier_value + # Skip if current values are not set + if type_value is None: + continue - # Do some preparations for custom attribute values query - attr_key_by_id = {} - nonhier_id_by_key = {} - hier_attr_ids = [] - for key, attr_id in hier_attrs.items(): - attr_key_by_id[attr_id] = key - hier_attr_ids.append(attr_id) - - conf_ids = list(hier_attr_ids) - task_conf_ids = [] - for key, attr_id in task_attrs.items(): - attr_key_by_id[attr_id] = key - nonhier_id_by_key[key] = attr_id - conf_ids.append(attr_id) - task_conf_ids.append(attr_id) - - # Query custom attribute values - # - result does not contain values for all entities only result of - # query callback to ftrack server - result = query_custom_attributes( - session, list(hier_attr_ids), whole_hierarchy_ids, True - ) - result.extend( - query_custom_attributes( - session, task_conf_ids, whole_hierarchy_ids, False - ) - ) + try: + new_value = type(type_value)(new_value) + except Exception: + self.log.warning(( + "Couldn't convert from {} to {}." + " Skipping update values." + ).format(type(new_value), type(type_value))) + continue - # Prepare variables where result will be stored - # - hierachical values should not contain attribute with value by - # default - hier_values_by_entity_id = { - entity_id: {} - for entity_id in whole_hierarchy_ids - } - # - real values of custom attributes - values_by_entity_id = { - entity_id: { - attr_id: None - for attr_id in conf_ids - } - for entity_id in whole_hierarchy_ids - } - for item in result: - attr_id = item["configuration_id"] - entity_id = item["entity_id"] - value = item["value"] - - values_by_entity_id[entity_id][attr_id] = value - - if attr_id in hier_attr_ids and value is not None: - hier_values_by_entity_id[entity_id][attr_id] = value - - # Prepare values for all task entities - # - going through all parents and storing first value value - # - store None to those that are already known that do not have set - # value at all - for task_id in tuple(task_ids): - for attr_id in hier_attr_ids: - entity_ids = [] - value = None - entity_id = task_id - while value is None: - entity_value = hier_values_by_entity_id[entity_id] - if attr_id in entity_value: - value = entity_value[attr_id] - if value is None: - break - - if value is None: - entity_ids.append(entity_id) - - entity_id = parent_id_by_entity_id.get(entity_id) - if entity_id is None: - break - - for entity_id in entity_ids: - hier_values_by_entity_id[entity_id][attr_id] = value - - # Prepare changes to commit - changes = [] - for task_id in tuple(task_ids): - parent_id = parent_id_by_entity_id[task_id] - for attr_id in hier_attr_ids: - attr_key = attr_key_by_id[attr_id] - nonhier_id = nonhier_id_by_key[attr_key] - - # Real value of hierarchical attribute on parent - # - If is none then should be unset - real_parent_value = values_by_entity_id[parent_id][attr_id] - # Current hierarchical value of a task - # - Will be compared to real parent value - hier_value = hier_values_by_entity_id[task_id][attr_id] - - # Parent value that can be inherited from it's parent entity - parent_value = hier_values_by_entity_id[parent_id][attr_id] - # Task value of nonhierarchical custom attribute - nonhier_value = values_by_entity_id[task_id][nonhier_id] - - if real_parent_value != hier_value: - changes.append({ - "new_value": real_parent_value, - "attr_id": attr_id, - "entity_id": task_id, - "attr_key": attr_key - }) - - if parent_value != nonhier_value: - changes.append({ - "new_value": parent_value, - "attr_id": nonhier_id, - "entity_id": task_id, - "attr_key": attr_key - }) - - self._commit_changes(session, changes) - - def _commit_changes(self, session, changes): - uncommited_changes = False - for idx, item in enumerate(changes): - new_value = item["new_value"] - old_value = item["old_value"] - attr_id = item["attr_id"] - entity_id = item["entity_id"] - attr_key = item["attr_key"] + real_std_value_is_same = new_value == real_std_value + real_hier_value_is_same = new_value == real_hier_value + # New value does not match anything in current entity values + if ( + not is_new_entity + and not real_std_value_is_same + and not real_hier_value_is_same + ): + continue - entity_key = collections.OrderedDict(( + if not real_std_value_is_same: + op_changes.append(( + std_id, + entity_id, + new_value, + real_values.get(std_id), + std_id in real_values + )) + + if not real_hier_value_is_same: + op_changes.append(( + hier_id, + entity_id, + new_value, + real_values.get(hier_id), + hier_id in real_values + )) + + for change in op_changes: + ( + attr_id, + entity_id, + new_value, + old_value, + do_update + ) = change + + entity_key = collections.OrderedDict([ ("configuration_id", attr_id), ("entity_id", entity_id) - )) - self._cached_changes.append({ - "attr_key": attr_key, - "entity_id": entity_id, - "value": new_value, - "time": datetime.datetime.now() - }) - old_value_is_set = ( - old_value is not ftrack_api.symbol.NOT_SET - and old_value is not None - ) - if new_value is None: - if not old_value_is_set: - continue - op = ftrack_api.operation.DeleteEntityOperation( - "CustomAttributeValue", - entity_key - ) - - elif old_value_is_set: + ]) + if do_update: op = ftrack_api.operation.UpdateEntityOperation( "CustomAttributeValue", entity_key, @@ -446,449 +383,116 @@ def _commit_changes(self, session, changes): ) session.recorded_operations.push(op) - self.log.info(( - "Changing Custom Attribute \"{}\" to value" - " \"{}\" on entity: {}" - ).format(attr_key, new_value, entity_id)) - - if (idx + 1) % 20 == 0: - uncommited_changes = False - try: - session.commit() - except Exception: - session.rollback() - self.log.warning( - "Changing of values failed.", exc_info=True - ) - else: - uncommited_changes = True - if uncommited_changes: - try: + if len(session.recorded_operations) > 100: session.commit() - except Exception: - session.rollback() - self.log.warning("Changing of values failed.", exc_info=True) + session.commit() - def process_attribute_changes( + def process_by_project( self, - session, - object_types_by_name, - interesting_data, - changed_keys_by_object_id, - interest_entity_types, - interest_attributes, - added_entity_ids + session: ftrack_api.Session, + event: ftrack_api.event.base.Event, + project_id: str, + entities_info: list[dict[str, Any]] ): - # Prepare task object id - task_object_id = object_types_by_name["task"]["id"] - - # Collect object type ids based on settings - interest_object_ids = [] - for entity_type in interest_entity_types: - _entity_type = entity_type.lower() - object_type = object_types_by_name.get(_entity_type) - if not object_type: - self.log.warning("Couldn't find object type \"{}\"".format( - entity_type - )) - - interest_object_ids.append(object_type["id"]) - - # Query entities by filtered data and object ids - entities = self.get_entities( - session, interesting_data, interest_object_ids - ) - if not entities: - return - - # Pop not found entities from interesting data - entity_ids = set( - entity["id"] - for entity in entities - ) - for entity_id in tuple(interesting_data.keys()): - if entity_id not in entity_ids: - interesting_data.pop(entity_id) - - # Add task object type to list - attr_obj_ids = list(interest_object_ids) - attr_obj_ids.append(task_object_id) - - attrs_by_obj_id, hier_attrs = self.attrs_configurations( - session, attr_obj_ids, interest_attributes - ) - - task_attrs = attrs_by_obj_id.get(task_object_id) - - changed_keys = set() - # Skip keys that are not both in hierachical and type specific - for object_id, keys in changed_keys_by_object_id.items(): - changed_keys |= set(keys) - object_id_attrs = attrs_by_obj_id.get(object_id) - for key in keys: - if key not in hier_attrs: - attrs_by_obj_id[object_id].pop(key) - continue + """Process changes in single project. + + Args: + session (ftrack_api.Session): Ftrack session. + event (ftrack_api.event.base.Event): Event which has all changes + information. + project_id (str): Project id related to changes. + entities_info (list[dict[str, Any]]): Changes of entities. + """ - if ( - (not object_id_attrs or key not in object_id_attrs) - and (not task_attrs or key not in task_attrs) - ): - hier_attrs.pop(key) - - # Clean up empty values - for key, value in tuple(attrs_by_obj_id.items()): - if not value: - attrs_by_obj_id.pop(key) - - if not attrs_by_obj_id: - self.log.warning(( - "There is not created Custom Attributes {} " - " for entity types: {}" - ).format( - self.join_query_keys(interest_attributes), - self.join_query_keys(interest_entity_types) - )) + ( + interest_attributes, + interest_entity_types + ) = self._get_handler_project_settings(session, event, project_id) + if not interest_attributes or not interest_entity_types: return - # Prepare task entities - task_entities = [] - # If task entity does not contain changed attribute then skip - if task_attrs: - task_entities = self.get_task_entities(session, interesting_data) - - task_entity_ids = set() - parent_id_by_task_id = {} - for task_entity in task_entities: - task_id = task_entity["id"] - task_entity_ids.add(task_id) - parent_id_by_task_id[task_id] = task_entity["parent_id"] - - self.finalize_attribute_changes( - session, - interesting_data, - changed_keys, - attrs_by_obj_id, - hier_attrs, - task_entity_ids, - parent_id_by_task_id, - added_entity_ids - ) - - def finalize_attribute_changes( - self, - session, - interesting_data, - changed_keys, - attrs_by_obj_id, - hier_attrs, - task_entity_ids, - parent_id_by_task_id, - added_entity_ids - ): - attr_id_to_key = {} - for attr_confs in attrs_by_obj_id.values(): - for key in changed_keys: - custom_attr_id = attr_confs.get(key) - if custom_attr_id: - attr_id_to_key[custom_attr_id] = key - - for key in changed_keys: - custom_attr_id = hier_attrs.get(key) - if custom_attr_id: - attr_id_to_key[custom_attr_id] = key - - entity_ids = ( - set(interesting_data.keys()) | task_entity_ids - ) - attr_ids = set(attr_id_to_key.keys()) - - current_values_by_id = self.get_current_values( - session, - attr_ids, - entity_ids, - task_entity_ids, - hier_attrs + entities_info: list[dict[str, Any]] = ( + self._entities_filter_by_settings( + entities_info, + interest_attributes, + interest_entity_types + ) ) - - changes = [] - for entity_id, current_values in current_values_by_id.items(): - parent_id = parent_id_by_task_id.get(entity_id) - if not parent_id: - parent_id = entity_id - values = interesting_data[parent_id] - - added_entity = entity_id in added_entity_ids - for attr_id, old_value in current_values.items(): - if added_entity and attr_id in hier_attrs: - continue - - attr_key = attr_id_to_key.get(attr_id) - if not attr_key: - continue - - # Convert new value from string - new_value = values.get(attr_key) - new_value_is_valid = ( - old_value is not ftrack_api.symbol.NOT_SET - and new_value is not None - ) - if added_entity and not new_value_is_valid: - continue - - if new_value is not None and new_value_is_valid: - try: - new_value = type(old_value)(new_value) - except Exception: - self.log.warning(( - "Couldn't convert from {} to {}." - " Skipping update values." - ).format(type(new_value), type(old_value))) - if new_value == old_value: - continue - - changes.append({ - "new_value": new_value, - "attr_id": attr_id, - "old_value": old_value, - "entity_id": entity_id, - "attr_key": attr_key - }) - self._commit_changes(session, changes) - - def filter_changes( - self, session, event, entities_info, interest_attributes - ): - session_user_id = self.session_user_id(session) - user_data = event["data"].get("user") - changed_by_session = False - if user_data and user_data.get("userid") == session_user_id: - changed_by_session = True - - current_time = datetime.datetime.now() - - interesting_data = {} - changed_keys_by_object_id = {} - - for entity_info in entities_info: - # Care only about changes if specific keys - entity_changes = {} - changes = entity_info["changes"] - for key in interest_attributes: - if key in changes: - entity_changes[key] = changes[key]["new"] - - entity_id = entity_info["entityId"] - if changed_by_session: - for key, new_value in tuple(entity_changes.items()): - for cached in tuple(self._cached_changes): - if ( - cached["entity_id"] != entity_id - or cached["attr_key"] != key - ): - continue - - cached_value = cached["value"] - try: - new_value = type(cached_value)(new_value) - except Exception: - pass - - if cached_value == new_value: - self._cached_changes.remove(cached) - entity_changes.pop(key) - break - - delta = (current_time - cached["time"]).seconds - if delta > self._max_delta: - self._cached_changes.remove(cached) - - if not entity_changes: - continue - - entity_id = entity_info["entityId"] - object_id = entity_info["objectTypeId"] - interesting_data[entity_id] = entity_changes - if object_id not in changed_keys_by_object_id: - changed_keys_by_object_id[object_id] = set() - changed_keys_by_object_id[object_id] |= set(entity_changes.keys()) - - return interesting_data, changed_keys_by_object_id - - def interesting_data_for_added( - self, - session, - added_entities, - interest_attributes, - interesting_data, - changed_keys_by_object_id - ): - if not added_entities or not interest_attributes: + if not entities_info: return - object_type_ids = set() - entity_ids = set() - all_entity_ids = set() - object_id_by_entity_id = {} - project_id = None - entity_ids_by_parent_id = collections.defaultdict(set) - for entity_info in added_entities: - object_id = entity_info["objectTypeId"] - entity_id = entity_info["entityId"] - object_type_ids.add(object_id) - entity_ids.add(entity_id) - object_id_by_entity_id[entity_id] = object_id - - for item in entity_info["parents"]: - entity_id = item["entityId"] - all_entity_ids.add(entity_id) - parent_id = item["parentId"] - if not parent_id: - project_id = entity_id - else: - entity_ids_by_parent_id[parent_id].add(entity_id) - - hier_attrs = self.get_hierarchical_configurations( + attrs_by_obj_id, hier_attrs = self._get_attrs_configurations( session, interest_attributes ) - if not hier_attrs: + # Skip if attributes are not available + # - there is nothing to sync + if not attrs_by_obj_id or not hier_attrs: return - hier_attrs_key_by_id = { - attr_conf["id"]: attr_conf["key"] - for attr_conf in hier_attrs - } - default_values_by_key = { - attr_conf["key"]: attr_conf["default"] - for attr_conf in hier_attrs - } - - values = query_custom_attributes( - session, list(hier_attrs_key_by_id.keys()), all_entity_ids, True + entity_ids_by_parent_id = collections.defaultdict(set) + all_entity_ids = set() + for entity_info in entities_info: + entity_id = None + for item in entity_info["parents"]: + item_id = item["entityId"] + all_entity_ids.add(item_id) + if entity_id is not None: + entity_ids_by_parent_id[item_id].add(entity_id) + entity_id = item_id + + attr_ids = {attr["id"] for attr in hier_attrs} + for attrs in attrs_by_obj_id.values(): + attr_ids |= {attr["id"] for attr in attrs} + + # Query real custom attribute values + # - we have to know what are the real values, if are set and to what + # value + value_items = query_custom_attributes( + session, attr_ids, all_entity_ids, True ) - values_per_entity_id = {} - for entity_id in all_entity_ids: - values_per_entity_id[entity_id] = {} - for attr_name in interest_attributes: - values_per_entity_id[entity_id][attr_name] = None - - for item in values: + real_values_by_entity_id = collections.defaultdict(dict) + for item in value_items: entity_id = item["entity_id"] - key = hier_attrs_key_by_id[item["configuration_id"]] - values_per_entity_id[entity_id][key] = item["value"] - - fill_queue = collections.deque() - fill_queue.append((project_id, default_values_by_key)) - while fill_queue: - item = fill_queue.popleft() - entity_id, values_by_key = item - entity_values = values_per_entity_id[entity_id] - new_values_by_key = copy.deepcopy(values_by_key) - for key, value in values_by_key.items(): - current_value = entity_values[key] - if current_value is None: - entity_values[key] = value - else: - new_values_by_key[key] = current_value - - for child_id in entity_ids_by_parent_id[entity_id]: - fill_queue.append((child_id, new_values_by_key)) - - for entity_id in entity_ids: - entity_changes = {} - for key, value in values_per_entity_id[entity_id].items(): - if value is not None: - entity_changes[key] = value - - if not entity_changes: - continue - - interesting_data[entity_id] = entity_changes - object_id = object_id_by_entity_id[entity_id] - if object_id not in changed_keys_by_object_id: - changed_keys_by_object_id[object_id] = set() - changed_keys_by_object_id[object_id] |= set(entity_changes.keys()) + attr_id = item["configuration_id"] + real_values_by_entity_id[entity_id][attr_id] = item["value"] - def get_current_values( - self, - session, - attr_ids, - entity_ids, - task_entity_ids, - hier_attrs - ): - current_values_by_id = {} - if not attr_ids or not entity_ids: - return current_values_by_id - - for entity_id in entity_ids: - current_values_by_id[entity_id] = {} - for attr_id in attr_ids: - current_values_by_id[entity_id][attr_id] = ( - ftrack_api.symbol.NOT_SET + hier_values_by_entity_id = {} + default_values = { + attr["id"]: attr["default"] + for attr in hier_attrs + } + hier_queue = collections.deque() + hier_queue.append((default_values, [project_id])) + while hier_queue: + parent_values, entity_ids = hier_queue.popleft() + for entity_id in entity_ids: + entity_values = copy.deepcopy(parent_values) + real_values = real_values_by_entity_id[entity_id] + for attr_id, value in real_values.items(): + entity_values[attr_id] = value + hier_values_by_entity_id[entity_id] = entity_values + hier_queue.append( + (entity_values, entity_ids_by_parent_id[entity_id]) ) - values = query_custom_attributes( - session, attr_ids, entity_ids, True + self.propagate_attribute_changes( + session, + interest_attributes, + entities_info, + attrs_by_obj_id, + hier_attrs, + real_values_by_entity_id, + hier_values_by_entity_id, ) - for item in values: - entity_id = item["entity_id"] - attr_id = item["configuration_id"] - if entity_id in task_entity_ids and attr_id in hier_attrs: - continue - - if entity_id not in current_values_by_id: - current_values_by_id[entity_id] = {} - current_values_by_id[entity_id][attr_id] = item["value"] - return current_values_by_id - - def get_entities(self, session, interesting_data, interest_object_ids): - return session.query(( - "select id from TypedContext" - " where id in ({}) and object_type_id in ({})" - ).format( - self.join_query_keys(interesting_data.keys()), - self.join_query_keys(interest_object_ids) - )).all() - - def get_task_entities(self, session, interesting_data): - return session.query( - "select id, parent_id from Task where parent_id in ({})".format( - self.join_query_keys(interesting_data.keys()) - ) - ).all() - - def attrs_configurations(self, session, object_ids, interest_attributes): - attrs = session.query(self.cust_attrs_query.format( - self.join_query_keys(interest_attributes), - self.join_query_keys(object_ids) - )).all() + def launch(self, session, event): + filtered_entities_info = self.filter_entities_info(event) + if not filtered_entities_info: + return - output = {} - hiearchical = {} - for attr in attrs: - if attr["is_hierarchical"]: - hiearchical[attr["key"]] = attr["id"] - continue - obj_id = attr["object_type_id"] - if obj_id not in output: - output[obj_id] = {} - output[obj_id][attr["key"]] = attr["id"] - return output, hiearchical - - def get_hierarchical_configurations(self, session, interest_attributes): - hier_attr_query = ( - "select id, key, object_type_id, is_hierarchical, default" - " from CustomAttributeConfiguration" - " where key in ({}) and is_hierarchical is true" - ) - if not interest_attributes: - return [] - return list(session.query(hier_attr_query.format( - self.join_query_keys(interest_attributes), - )).all()) + for project_id, entities_info in filtered_entities_info.items(): + self.process_by_project(session, event, project_id, entities_info) def register(session): - PushFrameValuesToTaskEvent(session).register() + PushHierValuesToNonHierEvent(session).register() diff --git a/openpype/modules/ftrack/event_handlers_server/event_radio_buttons.py b/openpype/modules/ftrack/event_handlers_server/event_radio_buttons.py index 99ad3aec374..358a8d2310d 100644 --- a/openpype/modules/ftrack/event_handlers_server/event_radio_buttons.py +++ b/openpype/modules/ftrack/event_handlers_server/event_radio_buttons.py @@ -7,7 +7,7 @@ class RadioButtons(BaseEvent): ignore_me = True def launch(self, session, event): - '''Provides a readio button behaviour to any bolean attribute in + '''Provides a radio button behaviour to any boolean attribute in radio_button group.''' # start of event procedure ---------------------------------- diff --git a/openpype/modules/ftrack/event_handlers_server/event_sync_to_avalon.py b/openpype/modules/ftrack/event_handlers_server/event_sync_to_avalon.py index 0058a428e33..0aa0b9f9f54 100644 --- a/openpype/modules/ftrack/event_handlers_server/event_sync_to_avalon.py +++ b/openpype/modules/ftrack/event_handlers_server/event_sync_to_avalon.py @@ -787,7 +787,7 @@ def launch(self, session, event): # Filter updates where name is changing for ftrack_id, ent_info in updated.items(): ent_keys = ent_info["keys"] - # Seprate update info from rename + # Separate update info from rename if "name" not in ent_keys: continue @@ -827,7 +827,7 @@ def launch(self, session, event): # 5.) Process updated self.process_updated() time_6 = time.time() - # 6.) Process changes in hierarchy or hier custom attribues + # 6.) Process changes in hierarchy or hier custom attributes self.process_hier_cleanup() time_7 = time.time() self.process_task_updates() @@ -1094,7 +1094,7 @@ def process_removed(self): def check_names_synchronizable(self, names): """Check if entities with specific names are importable. - This check should happend after removing entity or renaming entity. + This check should happen after removing entity or renaming entity. When entity was removed or renamed then it's name is possible to sync. """ joined_passed_names = ", ".join( @@ -1743,7 +1743,7 @@ def process_added(self): def process_moved(self): """ - Handles moved entities to different place in hiearchy. + Handles moved entities to different place in hierarchy. (Not tasks - handled separately.) """ if not self.ftrack_moved: @@ -1792,7 +1792,7 @@ def process_moved(self): self.log.warning("{} <{}>".format(error_msg, ent_path)) continue - # THIS MUST HAPPEND AFTER CREATING NEW ENTITIES !!!! + # THIS MUST HAPPEN AFTER CREATING NEW ENTITIES !!!! # - because may be moved to new created entity if "data" not in self.updates[mongo_id]: self.updates[mongo_id]["data"] = {} @@ -2323,7 +2323,7 @@ def process_hier_cleanup(self): items.append("{} - \"{}\"".format(ent_path, value)) self.report_items["error"][fps_msg] = items - # Get dictionary with not None hierarchical values to pull to childs + # Get dictionary with not None hierarchical values to pull to children project_values = {} for key, value in ( entities_dict[ftrack_project_id]["hier_attrs"].items() @@ -2460,7 +2460,7 @@ def process_task_updates(self): def update_entities(self): """ Update Avalon entities by mongo bulk changes. - Expects self.updates which are transfered to $set part of update + Expects self.updates which are transferred to $set part of update command. Resets self.updates afterwards. """ diff --git a/openpype/modules/ftrack/event_handlers_server/event_task_to_parent_status.py b/openpype/modules/ftrack/event_handlers_server/event_task_to_parent_status.py index a0e039926e0..25fa3b0535b 100644 --- a/openpype/modules/ftrack/event_handlers_server/event_task_to_parent_status.py +++ b/openpype/modules/ftrack/event_handlers_server/event_task_to_parent_status.py @@ -291,7 +291,7 @@ def process_by_project(self, session, event, project_id, entities_info): except Exception: session.rollback() self.log.warning( - "\"{}\" status couldnt be set to \"{}\"".format( + "\"{}\" status couldn't be set to \"{}\"".format( ent_path, new_status["name"] ), exc_info=True @@ -399,7 +399,7 @@ def new_status_by_remainders( # For cases there are multiple tasks in changes # - task status which match any new status item by order in the - # list `single_match` is preffered + # list `single_match` is preferred best_order = len(single_match) best_order_status = None for task_entity in task_entities: diff --git a/openpype/modules/ftrack/event_handlers_server/event_user_assigment.py b/openpype/modules/ftrack/event_handlers_server/event_user_assigment.py index c4e48b92f0d..9539a34f5e1 100644 --- a/openpype/modules/ftrack/event_handlers_server/event_user_assigment.py +++ b/openpype/modules/ftrack/event_handlers_server/event_user_assigment.py @@ -10,11 +10,11 @@ class UserAssigmentEvent(BaseEvent): """ - This script will intercept user assigment / de-assigment event and + This script will intercept user assignment / de-assignment event and run shell script, providing as much context as possible. It expects configuration file ``presets/ftrack/user_assigment_event.json``. - In it, you define paths to scripts to be run for user assigment event and + In it, you define paths to scripts to be run for user assignment event and for user-deassigment:: { "add": [ diff --git a/openpype/modules/ftrack/event_handlers_server/event_version_to_task_statuses.py b/openpype/modules/ftrack/event_handlers_server/event_version_to_task_statuses.py index e36c3eecd98..fb40fd6417f 100644 --- a/openpype/modules/ftrack/event_handlers_server/event_version_to_task_statuses.py +++ b/openpype/modules/ftrack/event_handlers_server/event_version_to_task_statuses.py @@ -102,7 +102,7 @@ def process_by_project(self, session, event, project_id, entities_info): asset_version_entities.append(asset_version) task_ids.add(asset_version["task_id"]) - # Skipt if `task_ids` are empty + # Skip if `task_ids` are empty if not task_ids: return diff --git a/openpype/modules/ftrack/event_handlers_user/action_applications.py b/openpype/modules/ftrack/event_handlers_user/action_applications.py index 102f04c9566..30399b463dd 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_applications.py +++ b/openpype/modules/ftrack/event_handlers_user/action_applications.py @@ -124,6 +124,11 @@ def discover(self, session, entities, event): if not avalon_project_apps: return False + settings = self.get_project_settings_from_event( + event, avalon_project_doc["name"]) + + only_available = settings["applications"]["only_available"] + items = [] for app_name in avalon_project_apps: app = self.application_manager.applications.get(app_name) @@ -133,6 +138,10 @@ def discover(self, session, entities, event): if app.group.name in CUSTOM_LAUNCH_APP_GROUPS: continue + # Skip applications without valid executables + if only_available and not app.find_executable(): + continue + app_icon = app.icon if app_icon and self.icon_url: try: diff --git a/openpype/modules/ftrack/event_handlers_user/action_batch_task_creation.py b/openpype/modules/ftrack/event_handlers_user/action_batch_task_creation.py index c7fb1af98b9..06d572601dc 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_batch_task_creation.py +++ b/openpype/modules/ftrack/event_handlers_user/action_batch_task_creation.py @@ -7,7 +7,7 @@ class BatchTasksAction(BaseAction): '''Batch Tasks action - `label` a descriptive string identifing your action. + `label` a descriptive string identifying your action. `varaint` To group actions together, give them the same label and specify a unique variant per action. `identifier` a unique identifier for your action. diff --git a/openpype/modules/ftrack/event_handlers_user/action_create_cust_attrs.py b/openpype/modules/ftrack/event_handlers_user/action_create_cust_attrs.py index c19cfd1502f..471a8c41824 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_create_cust_attrs.py +++ b/openpype/modules/ftrack/event_handlers_user/action_create_cust_attrs.py @@ -82,9 +82,9 @@ write_security_roles/read_security_roles (array of strings) - default: ["ALL"] - strings should be role names (e.g.: ["API", "Administrator"]) - - if set to ["ALL"] - all roles will be availabled + - if set to ["ALL"] - all roles will be available - if first is 'except' - roles will be set to all except roles in array - - Warning: Be carefull with except - roles can be different by company + - Warning: Be careful with except - roles can be different by company - example: write_security_roles = ["except", "User"] read_security_roles = ["ALL"] # (User is can only read) @@ -500,7 +500,7 @@ def process_attr_data(self, cust_attr_data, event): data = {} # Get key, label, type data.update(self.get_required(cust_attr_data)) - # Get hierachical/ entity_type/ object_id + # Get hierarchical/ entity_type/ object_id data.update(self.get_entity_type(cust_attr_data)) # Get group, default, security roles data.update(self.get_optional(cust_attr_data)) diff --git a/openpype/modules/ftrack/event_handlers_user/action_create_folders.py b/openpype/modules/ftrack/event_handlers_user/action_create_folders.py index 9806f83773d..cbeff5343fb 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_create_folders.py +++ b/openpype/modules/ftrack/event_handlers_user/action_create_folders.py @@ -51,7 +51,7 @@ def interface(self, session, entities, event): }, { "type": "label", - "value": "With all chilren entities" + "value": "With all children entities" }, { "name": "children_included", diff --git a/openpype/modules/ftrack/event_handlers_user/action_delete_asset.py b/openpype/modules/ftrack/event_handlers_user/action_delete_asset.py index 03d029b0c18..72a5efbcfee 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_delete_asset.py +++ b/openpype/modules/ftrack/event_handlers_user/action_delete_asset.py @@ -18,7 +18,7 @@ class DeleteAssetSubset(BaseAction): # Action label. label = "Delete Asset/Subsets" # Action description. - description = "Removes from Avalon with all childs and asset from Ftrack" + description = "Removes from Avalon with all children and asset from Ftrack" icon = statics_icon("ftrack", "action_icons", "DeleteAsset.svg") settings_key = "delete_asset_subset" diff --git a/openpype/modules/ftrack/event_handlers_user/action_delete_old_versions.py b/openpype/modules/ftrack/event_handlers_user/action_delete_old_versions.py index c543dc8834f..ec14c6918bf 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_delete_old_versions.py +++ b/openpype/modules/ftrack/event_handlers_user/action_delete_old_versions.py @@ -27,7 +27,7 @@ class DeleteOldVersions(BaseAction): variant = "- Delete old versions" description = ( "Delete files from older publishes so project can be" - " archived with only lates versions." + " archived with only latest versions." ) icon = statics_icon("ftrack", "action_icons", "OpenPypeAdmin.svg") @@ -307,7 +307,7 @@ def sort_func(ent): file_path, seq_path = self.path_from_represenation(repre, anatomy) if file_path is None: self.log.warning(( - "Could not format path for represenation \"{}\"" + "Could not format path for representation \"{}\"" ).format(str(repre))) continue diff --git a/openpype/modules/ftrack/event_handlers_user/action_delivery.py b/openpype/modules/ftrack/event_handlers_user/action_delivery.py index a400c8f5f03..559de3a24d7 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_delivery.py +++ b/openpype/modules/ftrack/event_handlers_user/action_delivery.py @@ -601,7 +601,7 @@ def real_launch(self, session, entities, event): return self.report(report_items) def report(self, report_items): - """Returns dict with final status of delivery (succes, fail etc.).""" + """Returns dict with final status of delivery (success, fail etc.).""" items = [] for msg, _items in report_items.items(): diff --git a/openpype/modules/ftrack/event_handlers_user/action_fill_workfile_attr.py b/openpype/modules/ftrack/event_handlers_user/action_fill_workfile_attr.py index fb1cdf340e2..36d29db96b6 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_fill_workfile_attr.py +++ b/openpype/modules/ftrack/event_handlers_user/action_fill_workfile_attr.py @@ -246,7 +246,7 @@ def in_job_process( project_name = project_entity["full_name"] - # Find matchin asset documents and map them by ftrack task entities + # Find matching asset documents and map them by ftrack task entities # - result stored to 'asset_docs_with_task_entities' is list with # tuple `(asset document, [task entitis, ...])` # Quety all asset documents diff --git a/openpype/modules/ftrack/event_handlers_user/action_job_killer.py b/openpype/modules/ftrack/event_handlers_user/action_job_killer.py index f489c0c54c3..dd68c75f846 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_job_killer.py +++ b/openpype/modules/ftrack/event_handlers_user/action_job_killer.py @@ -54,14 +54,14 @@ def interface(self, session, entities, event): for job in jobs: try: data = json.loads(job["data"]) - desctiption = data["description"] + description = data["description"] except Exception: - desctiption = "*No description*" + description = "*No description*" user_id = job["user_id"] username = usernames_by_id.get(user_id) or "Unknown user" created = job["created_at"].strftime('%d.%m.%Y %H:%M:%S') label = "{} - {} - {}".format( - username, desctiption, created + username, description, created ) item_label = { "type": "label", diff --git a/openpype/modules/ftrack/event_handlers_user/action_prepare_project.py b/openpype/modules/ftrack/event_handlers_user/action_prepare_project.py index e8251981803..19d5701e084 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_prepare_project.py +++ b/openpype/modules/ftrack/event_handlers_user/action_prepare_project.py @@ -24,7 +24,7 @@ class PrepareProjectLocal(BaseAction): settings_key = "prepare_project" - # Key to store info about trigerring create folder structure + # Key to store info about triggering create folder structure create_project_structure_key = "create_folder_structure" create_project_structure_identifier = "create.project.structure" item_splitter = {"type": "label", "value": "---"} @@ -146,7 +146,7 @@ def prepare_root_items(self, project_anatom_settings): root_items.append({ "type": "label", "value": ( - "

    NOTE: Roots are crutial for path filling" + "

    NOTE: Roots are crucial for path filling" " (and creating folder structure).

    " ) }) diff --git a/openpype/modules/ftrack/event_handlers_user/action_rv.py b/openpype/modules/ftrack/event_handlers_user/action_rv.py index d05f0c47f6d..39cf33d6056 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_rv.py +++ b/openpype/modules/ftrack/event_handlers_user/action_rv.py @@ -66,7 +66,7 @@ def preregister(self): def get_components_from_entity(self, session, entity, components): """Get components from various entity types. - The components dictionary is modifid in place, so nothing is returned. + The components dictionary is modified in place, so nothing is returned. Args: entity (Ftrack entity) diff --git a/openpype/modules/ftrack/event_handlers_user/action_seed.py b/openpype/modules/ftrack/event_handlers_user/action_seed.py index 4021d70c0ac..657cd07a9fd 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_seed.py +++ b/openpype/modules/ftrack/event_handlers_user/action_seed.py @@ -325,8 +325,8 @@ def create_assets(self, project, asset_count): ): index = 0 - self.log.debug("*** Commiting Assets") - self.log.debug("Commiting entities. {}/{}".format( + self.log.debug("*** Committing Assets") + self.log.debug("Committing entities. {}/{}".format( created_entities, to_create_length )) self.session.commit() @@ -414,8 +414,8 @@ def create_shots(self, project, seq_count, shots_count): ): index = 0 - self.log.debug("*** Commiting Shots") - self.log.debug("Commiting entities. {}/{}".format( + self.log.debug("*** Committing Shots") + self.log.debug("Committing entities. {}/{}".format( created_entities, to_create_length )) self.session.commit() @@ -423,7 +423,7 @@ def create_shots(self, project, seq_count, shots_count): def temp_commit(self, index, created_entities, to_create_length): if index < self.max_entities_created_at_one_commit: return False - self.log.debug("Commiting {} entities. {}/{}".format( + self.log.debug("Committing {} entities. {}/{}".format( index, created_entities, to_create_length )) self.session.commit() diff --git a/openpype/modules/ftrack/event_handlers_user/action_store_thumbnails_to_avalon.py b/openpype/modules/ftrack/event_handlers_user/action_store_thumbnails_to_avalon.py index 8748f426bdc..c9e0901623b 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_store_thumbnails_to_avalon.py +++ b/openpype/modules/ftrack/event_handlers_user/action_store_thumbnails_to_avalon.py @@ -184,7 +184,7 @@ def launch(self, session, entities, event): self.db_con.install() for entity in entities: - # Skip if entity is not AssetVersion (never should happend, but..) + # Skip if entity is not AssetVersion (should never happen, but..) if entity.entity_type.lower() != "assetversion": continue diff --git a/openpype/modules/ftrack/ftrack_server/event_server_cli.py b/openpype/modules/ftrack/ftrack_server/event_server_cli.py index ad7ffd8e25f..77f479ee207 100644 --- a/openpype/modules/ftrack/ftrack_server/event_server_cli.py +++ b/openpype/modules/ftrack/ftrack_server/event_server_cli.py @@ -33,7 +33,7 @@ class MongoPermissionsError(Exception): """Is used when is created multiple objects of same RestApi class.""" def __init__(self, message=None): if not message: - message = "Exiting because have issue with acces to MongoDB" + message = "Exiting because have issue with access to MongoDB" super().__init__(message) @@ -340,7 +340,7 @@ def on_exit(processor_thread, storer_thread, statuser_thread): return 1 # ====== STORER ======= - # Run backup thread which does not requeire mongo to work + # Run backup thread which does not require mongo to work if storer_thread is None: if storer_failed_count < max_fail_count: storer_thread = socket_thread.SocketThread( @@ -399,7 +399,7 @@ def on_exit(processor_thread, storer_thread, statuser_thread): elif not processor_thread.is_alive(): if processor_thread.mongo_error: raise Exception( - "Exiting because have issue with acces to MongoDB" + "Exiting because have issue with access to MongoDB" ) processor_thread.join() processor_thread = None diff --git a/openpype/modules/ftrack/lib/avalon_sync.py b/openpype/modules/ftrack/lib/avalon_sync.py index 0341c257178..8b4c4619a19 100644 --- a/openpype/modules/ftrack/lib/avalon_sync.py +++ b/openpype/modules/ftrack/lib/avalon_sync.py @@ -891,7 +891,7 @@ def filter_by_ignore_sync(self): parent_dict = self.entities_dict.get(parent_id, {}) for child_id in parent_dict.get("children", []): - # keep original `remove` value for all childs + # keep original `remove` value for all children _remove = (remove is True) if not _remove: if self.entities_dict[child_id]["avalon_attrs"].get( @@ -1191,8 +1191,8 @@ def set_hierarchical_attribute( avalon_hier = [] for item in items: value = item["value"] - # WARNING It is not possible to propage enumerate hierachical - # attributes with multiselection 100% right. Unseting all values + # WARNING It is not possible to propagate enumerate hierarchical + # attributes with multiselection 100% right. Unsetting all values # will cause inheritance from parent. if ( value is None @@ -1231,7 +1231,7 @@ def set_hierarchical_attribute( items.append("{} - \"{}\"".format(ent_path, value)) self.report_items["error"][fps_msg] = items - # Get dictionary with not None hierarchical values to pull to childs + # Get dictionary with not None hierarchical values to pull to children top_id = self.ft_project_id project_values = {} for key, value in self.entities_dict[top_id]["hier_attrs"].items(): @@ -1749,7 +1749,7 @@ def prepare_changes(self): # TODO logging ent_path = self.get_ent_path(ftrack_id) msg = ( - " It is not possible" + " It is not possible" " to change the hierarchy of an entity or it's parents," " if it already contained published data." ) @@ -2584,8 +2584,8 @@ def delete_entities(self): # # ent_dict = self.entities_dict[found_by_name_id] - # TODO report - CRITICAL entity with same name alread exists in - # different hierarchy - can't recreate entity + # TODO report - CRITICAL entity with same name already exists + # in different hierarchy - can't recreate entity continue _vis_parent = deleted_entity["data"]["visualParent"] diff --git a/openpype/modules/ftrack/lib/custom_attributes.py b/openpype/modules/ftrack/lib/custom_attributes.py index 2f538153680..3e40bb02f21 100644 --- a/openpype/modules/ftrack/lib/custom_attributes.py +++ b/openpype/modules/ftrack/lib/custom_attributes.py @@ -65,7 +65,7 @@ def get_openpype_attr(session, split_hierarchical=True, query_keys=None): cust_attrs_query = ( "select {}" " from CustomAttributeConfiguration" - # Kept `pype` for Backwards Compatiblity + # Kept `pype` for Backwards Compatibility " where group.name in (\"pype\", \"{}\")" ).format(", ".join(query_keys), CUST_ATTR_GROUP) all_avalon_attr = session.query(cust_attrs_query).all() diff --git a/openpype/modules/ftrack/lib/ftrack_action_handler.py b/openpype/modules/ftrack/lib/ftrack_action_handler.py index b24fe5f12ae..07b3a780a2b 100644 --- a/openpype/modules/ftrack/lib/ftrack_action_handler.py +++ b/openpype/modules/ftrack/lib/ftrack_action_handler.py @@ -12,7 +12,7 @@ def statics_icon(*icon_statics_file_parts): class BaseAction(BaseHandler): '''Custom Action base class - `label` a descriptive string identifing your action. + `label` a descriptive string identifying your action. `varaint` To group actions together, give them the same label and specify a unique variant per action. diff --git a/openpype/modules/ftrack/lib/ftrack_base_handler.py b/openpype/modules/ftrack/lib/ftrack_base_handler.py index c0b03f8a417..55400c22aba 100644 --- a/openpype/modules/ftrack/lib/ftrack_base_handler.py +++ b/openpype/modules/ftrack/lib/ftrack_base_handler.py @@ -30,7 +30,7 @@ def __init__(self, message=None): class BaseHandler(object): '''Custom Action base class -
    +Blender: Extract Review #3616 + +Added Review to Blender. + +This implementation is based on #3508 but made compatible for the current implementation of OpenPype for Blender. + + +___ + +

    _?B@ssfQYlBAHF=3EyzE&_=Z2gg)O{M_nh8~ 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�lF z3v}%-a*KhmUwz_Wgu1>Q(BJ-w9?PAou;fxSU`r9$p#_)iA<@r11Tvsk)OhOOfdI0Z z#t8BoE41vKMk^dL(+B61@;Ps0K^LtwC%Qnxh*D{7FuMRXaWNnAMsmyxutmZlJ?DF{ zPu7pMq^VgMYZBGW(;p9{az9d}pm4*0Aq7Byh9l)m%gVkQ-987;Wdh;0fYE2WaMJp` z(f4nxvwf2s7oY~pTS?W!Z&BwY>uPF2QF{6~AN;tE*>QPVuub`$JlNd>^$z$@zm9KP zFRIywgDN(ypGGW{g-M3x=aFB_ORy&BY`V`RLJt<>OL+T*Y5r6cPv8^^ezTTIf^+=m zyQ>CkvfZu%Xr6(!?UgF(uW~_`dK%vLbl;I_2_Bfayd1Ms>kv>xDTz4xk7CF4R`k}vS<3$p9{;7_0sHH(bpB4e|G%Rc fw&7b=Cmv8OJ)uU~wvf`no{Qp&`t?g-pX>iGR($zU literal 0 HcmV?d00001 diff --git a/website/docs/assets/maya-admin_extract_playblast_settings_camera_options.png b/website/docs/assets/maya-admin_extract_playblast_settings_camera_options.png new file mode 100644 index 0000000000000000000000000000000000000000..1a5561328e056fe03278f78c56ea6b837a384e56 GIT binary patch literal 16732 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 literal 0 HcmV?d00001 diff --git a/website/docs/assets/maya-admin_extract_playblast_settings_viewport_options.png b/website/docs/assets/maya-admin_extract_playblast_settings_viewport_options.png new file mode 100644 index 0000000000000000000000000000000000000000..5b801775d32338ea9dcb051d2b01a008697c7bd8 GIT binary patch literal 1064191 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%0AJpOqGmRpk29oF=8t0UWz?Ldih)A1?YQ79f+ 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