From 452fd0dae055d83bff46db6f2c5496cd8f7c14b8 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 7 May 2024 20:46:46 +0100 Subject: [PATCH 01/91] Working version --- .../plugins/publish/collect_clip_effects.py | 19 +++++++++++++++++++ .../hosts/nuke/plugins/load/load_effects.py | 1 - server_addon/hiero/package.py | 2 +- .../hiero/server/settings/publish_plugins.py | 13 ++++++++++++- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/hosts/hiero/plugins/publish/collect_clip_effects.py b/client/ayon_core/hosts/hiero/plugins/publish/collect_clip_effects.py index bfc63f2551..85fd3ba048 100644 --- a/client/ayon_core/hosts/hiero/plugins/publish/collect_clip_effects.py +++ b/client/ayon_core/hosts/hiero/plugins/publish/collect_clip_effects.py @@ -1,4 +1,5 @@ import re +from collections import defaultdict import pyblish.api @@ -11,6 +12,7 @@ class CollectClipEffects(pyblish.api.InstancePlugin): families = ["clip"] effect_categories = [] + effect_tracks = [] def process(self, instance): product_type = "effect" @@ -73,6 +75,7 @@ class CollectClipEffects(pyblish.api.InstancePlugin): product_name_split.insert(0, "effect") + # Categorize effects by class. effect_categories = { x["name"]: x["effect_classes"] for x in self.effect_categories } @@ -96,6 +99,22 @@ class CollectClipEffects(pyblish.api.InstancePlugin): effects_categorized[category_by_effect[found_cls]][key] = value + # Categorize effects by track name. + effects_by_track = defaultdict(dict) + for key, value in effects.items(): + if key == "assignTo": + continue + + effects_by_track[value["track"]][key] = value + + for data in self.effect_tracks: + for track_name, track_effects in effects_by_track.items(): + if re.match(data["track_regex"], track_name) is None: + continue + + effects_categorized[data["name"]] = track_effects + + # Ensure required `assignTo` data member exists. categories = list(effects_categorized.keys()) for category in categories: if not effects_categorized[category]: diff --git a/client/ayon_core/hosts/nuke/plugins/load/load_effects.py b/client/ayon_core/hosts/nuke/plugins/load/load_effects.py index a87c81295a..6c0c6a1b0f 100644 --- a/client/ayon_core/hosts/nuke/plugins/load/load_effects.py +++ b/client/ayon_core/hosts/nuke/plugins/load/load_effects.py @@ -69,7 +69,6 @@ class LoadEffects(load.LoaderPlugin): "handleStart", "handleEnd", "source", - "author", "fps" ]: data_imprint[k] = version_attributes[k] diff --git a/server_addon/hiero/package.py b/server_addon/hiero/package.py index 54c2f74fa7..26ceb65448 100644 --- a/server_addon/hiero/package.py +++ b/server_addon/hiero/package.py @@ -1,3 +1,3 @@ name = "hiero" title = "Hiero" -version = "0.1.3" +version = "0.1.4" diff --git a/server_addon/hiero/server/settings/publish_plugins.py b/server_addon/hiero/server/settings/publish_plugins.py index 0e43d4ce3a..9902b68a25 100644 --- a/server_addon/hiero/server/settings/publish_plugins.py +++ b/server_addon/hiero/server/settings/publish_plugins.py @@ -27,11 +27,21 @@ class CollectClipEffectsDefModel(BaseSettingsModel): return normalize_name(value) +class CollectClipEffectsTracksModel(BaseSettingsModel): + _layout = "expanded" + name: str = SettingsField("", title="Name") + track_regex: str = SettingsField("", title="Track Regex") + + class CollectClipEffectsModel(BaseSettingsModel): effect_categories: list[CollectClipEffectsDefModel] = SettingsField( default_factory=list, title="Effect Categories" ) + effect_tracks: list[CollectClipEffectsTracksModel] = SettingsField( + default_factory=list, title="Effect Tracks" + ) + @validator("effect_categories") def validate_unique_outputs(cls, value): ensure_unique_names(value) @@ -79,6 +89,7 @@ DEFAULT_PUBLISH_PLUGIN_SETTINGS = { ] }, "CollectClipEffectsModel": { - "effect_categories": [] + "effect_categories": [], + "effect_tracks": [] } } From 8be42b056f7a05d6542e72cab2c55a692e5bee9b Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 10 May 2024 16:20:21 +0100 Subject: [PATCH 02/91] Explicit track names. --- .../plugins/publish/collect_clip_effects.py | 24 ++++++++++--------- .../hiero/server/settings/publish_plugins.py | 2 +- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/client/ayon_core/hosts/hiero/plugins/publish/collect_clip_effects.py b/client/ayon_core/hosts/hiero/plugins/publish/collect_clip_effects.py index 85fd3ba048..1ff2f25edc 100644 --- a/client/ayon_core/hosts/hiero/plugins/publish/collect_clip_effects.py +++ b/client/ayon_core/hosts/hiero/plugins/publish/collect_clip_effects.py @@ -100,19 +100,21 @@ class CollectClipEffects(pyblish.api.InstancePlugin): effects_categorized[category_by_effect[found_cls]][key] = value # Categorize effects by track name. - effects_by_track = defaultdict(dict) - for key, value in effects.items(): - if key == "assignTo": - continue - - effects_by_track[value["track"]][key] = value - - for data in self.effect_tracks: - for track_name, track_effects in effects_by_track.items(): - if re.match(data["track_regex"], track_name) is None: + track_names_by_category = { + x["name"]: x["track_names"] for x in self.effect_tracks + } + for category, track_names in track_names_by_category.items(): + for key, value in effects.items(): + if key == "assignTo": continue - effects_categorized[data["name"]] = track_effects + if value["track"] not in track_names: + continue + + if category in effects_categorized: + effects_categorized[category][key] = value + else: + effects_categorized[category] = {key: value} # Ensure required `assignTo` data member exists. categories = list(effects_categorized.keys()) diff --git a/server_addon/hiero/server/settings/publish_plugins.py b/server_addon/hiero/server/settings/publish_plugins.py index 9902b68a25..b9e07639df 100644 --- a/server_addon/hiero/server/settings/publish_plugins.py +++ b/server_addon/hiero/server/settings/publish_plugins.py @@ -30,7 +30,7 @@ class CollectClipEffectsDefModel(BaseSettingsModel): class CollectClipEffectsTracksModel(BaseSettingsModel): _layout = "expanded" name: str = SettingsField("", title="Name") - track_regex: str = SettingsField("", title="Track Regex") + track_names: list[str] = SettingsField("", title="Track Names") class CollectClipEffectsModel(BaseSettingsModel): From 835c87a3c0246e1893d384b358091f6f5046c384 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 23 May 2024 22:58:03 +0100 Subject: [PATCH 03/91] Account for no categories --- .../hosts/hiero/plugins/publish/collect_clip_effects.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/hiero/plugins/publish/collect_clip_effects.py b/client/ayon_core/hosts/hiero/plugins/publish/collect_clip_effects.py index 1ff2f25edc..8d9dbb2c92 100644 --- a/client/ayon_core/hosts/hiero/plugins/publish/collect_clip_effects.py +++ b/client/ayon_core/hosts/hiero/plugins/publish/collect_clip_effects.py @@ -86,7 +86,6 @@ class CollectClipEffects(pyblish.api.InstancePlugin): category_by_effect[cls] = key effects_categorized = {k: {} for k in effect_categories.keys()} - effects_categorized[""] = {} for key, value in effects.items(): if key == "assignTo": continue @@ -97,6 +96,9 @@ class CollectClipEffects(pyblish.api.InstancePlugin): if cls in value["class"]: found_cls = cls + if not found_cls: + continue + effects_categorized[category_by_effect[found_cls]][key] = value # Categorize effects by track name. @@ -125,6 +127,10 @@ class CollectClipEffects(pyblish.api.InstancePlugin): effects_categorized[category]["assignTo"] = effects["assignTo"] + # If no effects have been categorized, publish all effects together. + if not effects_categorized: + effects_categorized[""] = effects + for category, effects in effects_categorized.items(): product_name = "".join(product_name_split) product_name += category.capitalize() From e946dd529a3bb0c3778729956e0fd2d324de0119 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 24 May 2024 14:11:25 +0200 Subject: [PATCH 04/91] Fix run deadline collectors on preprender Prerender instances (in Nuke) would be skipped and submit to DL would fail --- .../plugins/publish/collect_deadline_server_from_instance.py | 1 + .../ayon_core/modules/deadline/plugins/publish/collect_pools.py | 1 + .../modules/deadline/plugins/publish/collect_user_credentials.py | 1 + 3 files changed, 3 insertions(+) diff --git a/client/ayon_core/modules/deadline/plugins/publish/collect_deadline_server_from_instance.py b/client/ayon_core/modules/deadline/plugins/publish/collect_deadline_server_from_instance.py index 22022831a0..7fe3ceab9d 100644 --- a/client/ayon_core/modules/deadline/plugins/publish/collect_deadline_server_from_instance.py +++ b/client/ayon_core/modules/deadline/plugins/publish/collect_deadline_server_from_instance.py @@ -17,6 +17,7 @@ class CollectDeadlineServerFromInstance(pyblish.api.InstancePlugin): label = "Deadline Webservice from the Instance" targets = ["local"] families = ["render", + "prerender", "rendering", "render.farm", "renderFarm", diff --git a/client/ayon_core/modules/deadline/plugins/publish/collect_pools.py b/client/ayon_core/modules/deadline/plugins/publish/collect_pools.py index 6923c2b16b..fe5c8be49c 100644 --- a/client/ayon_core/modules/deadline/plugins/publish/collect_pools.py +++ b/client/ayon_core/modules/deadline/plugins/publish/collect_pools.py @@ -35,6 +35,7 @@ class CollectDeadlinePools(pyblish.api.InstancePlugin, "houdini"] families = ["render", + "prerender", "rendering", "render.farm", "renderFarm", diff --git a/client/ayon_core/modules/deadline/plugins/publish/collect_user_credentials.py b/client/ayon_core/modules/deadline/plugins/publish/collect_user_credentials.py index 99d75ecb9e..da5d00f24c 100644 --- a/client/ayon_core/modules/deadline/plugins/publish/collect_user_credentials.py +++ b/client/ayon_core/modules/deadline/plugins/publish/collect_user_credentials.py @@ -34,6 +34,7 @@ class CollectDeadlineUserCredentials(pyblish.api.InstancePlugin): "houdini"] families = ["render", + "prerender", "rendering", "render.farm", "renderFarm", From ddd998f417c1f90266319c9152bfe6f639c9e877 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 28 May 2024 16:46:41 +0200 Subject: [PATCH 05/91] AY-5539 - new Settings for filtering of creators --- server/settings/tools.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/server/settings/tools.py b/server/settings/tools.py index fb8430a71c..6d0c133511 100644 --- a/server/settings/tools.py +++ b/server/settings/tools.py @@ -35,6 +35,22 @@ class ProductNameProfile(BaseSettingsModel): template: str = SettingsField("", title="Template") +class FilterCreatorProfile(BaseSettingsModel): + """Provide list of allowed Creator identifiers for context""" + + _layout = "expanded" + hosts: list[str] = SettingsField(default_factory=list, title="Hosts") + task_types: list[str] = SettingsField( + default_factory=list, + title="Task types", + enum_resolver=task_types_enum + ) + task_names: list[str] = SettingsField(default_factory=list, + title="Task names") + creator_identifiers: list[str] = SettingsField( + "", title="Allowed Creator Identifiers") + + class CreatorToolModel(BaseSettingsModel): # TODO this was dynamic dictionary '{name: task_names}' product_types_smart_select: list[ProductTypeSmartSelectModel] = ( @@ -48,6 +64,11 @@ class CreatorToolModel(BaseSettingsModel): title="Product name profiles" ) + filter_creator_profiles: list[FilterCreatorProfile] = SettingsField( + default_factory=list, + title="Filter creator profiles" + ) + @validator("product_types_smart_select") def validate_unique_name(cls, value): ensure_unique_names(value) @@ -404,7 +425,8 @@ DEFAULT_TOOLS_VALUES = { "tasks": [], "template": "SK_{folder[name]}{variant}" } - ] + ], + "filter_creator_profiles": [] }, "Workfiles": { "workfile_template_profiles": [ From cd11db27aa316c669f0963ac0cec1b2a612362e8 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 28 May 2024 16:47:42 +0200 Subject: [PATCH 06/91] AY-5539 - use configured profiles to filter creators --- client/ayon_core/tools/publisher/control.py | 37 +++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index ede772b917..9ffa33ce5c 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -39,6 +39,9 @@ from ayon_core.pipeline.create.context import ( ) from ayon_core.pipeline.publish import get_publish_instance_label from ayon_core.tools.common_models import HierarchyModel +from ayon_core.settings import get_project_settings +from ayon_core.lib.profiles_filtering import filter_profiles +from ayon_core.pipeline.context_tools import get_current_task_entity # Define constant for plugin orders offset PLUGIN_ORDER_OFFSET = 0.5 @@ -1827,8 +1830,13 @@ class PublisherController(BasePublisherController): def _collect_creator_items(self): # TODO add crashed initialization of create plugins to report output = {} + allowed_creator_identifiers = self._get_allowed_creator_identifiers() for identifier, creator in self._create_context.creators.items(): try: + if (allowed_creator_identifiers and + identifier not in allowed_creator_identifiers): + self.log.debug(f"{identifier} not allowed for context") + continue output[identifier] = CreatorItem.from_creator(creator) except Exception: self.log.error( @@ -1839,6 +1847,35 @@ class PublisherController(BasePublisherController): return output + def _get_allowed_creator_identifiers(self): + """Provide configured creator identifier in this context + + If no profile provided for current context, it shows all creators + """ + proj_settings = get_project_settings(self.project_name) + filter_creator_profiles = ( + proj_settings + ["core"] + ["tools"] + ["creator"] + ["filter_creator_profiles"] + ) + task_type = get_current_task_entity()["taskType"] + filtering_criteria = { + "task_names": self.current_task_name, + "task_types": task_type, + "hosts": self._create_context.host_name + } + profile = filter_profiles( + filter_creator_profiles, + filtering_criteria, + logger=self.log + ) + allowed_creator_identifiers = [] + if profile: + allowed_creator_identifiers = profile["creator_identifiers"] + return allowed_creator_identifiers + def _reset_instances(self): """Reset create instances.""" if self._resetting_instances: From 2cf7f36f9b5820b35684d3f66406d4256bf2f919 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 28 May 2024 16:50:32 +0200 Subject: [PATCH 07/91] AY-5539 - do not use profiles for traypublisher --- client/ayon_core/tools/publisher/control.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index 9ffa33ce5c..b116b4138b 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -1852,6 +1852,10 @@ class PublisherController(BasePublisherController): If no profile provided for current context, it shows all creators """ + allowed_creator_identifiers = [] + if self._create_context.host_name == "traypublisher": + # no real context known + return allowed_creator_identifiers proj_settings = get_project_settings(self.project_name) filter_creator_profiles = ( proj_settings @@ -1871,7 +1875,7 @@ class PublisherController(BasePublisherController): filtering_criteria, logger=self.log ) - allowed_creator_identifiers = [] + if profile: allowed_creator_identifiers = profile["creator_identifiers"] return allowed_creator_identifiers From ce13e2ee027c620f04baf7c9207e561dfc30807a Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 28 May 2024 16:58:11 +0200 Subject: [PATCH 08/91] AY-5539 - provide better method signature Should be used for unittests --- client/ayon_core/tools/publisher/control.py | 28 +++++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index b116b4138b..7753804911 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -1830,7 +1830,13 @@ class PublisherController(BasePublisherController): def _collect_creator_items(self): # TODO add crashed initialization of create plugins to report output = {} - allowed_creator_identifiers = self._get_allowed_creator_identifiers() + allowed_creator_identifiers = self._get_allowed_creator_identifiers( + self.project_name, + self._create_context.host_name, + self.current_task_name, + get_current_task_entity()["taskType"], + self.log + ) for identifier, creator in self._create_context.creators.items(): try: if (allowed_creator_identifiers and @@ -1847,16 +1853,23 @@ class PublisherController(BasePublisherController): return output - def _get_allowed_creator_identifiers(self): + def _get_allowed_creator_identifiers( + self, + project_name, + host_name, + task_name, + task_type, + log=None + ): """Provide configured creator identifier in this context If no profile provided for current context, it shows all creators """ allowed_creator_identifiers = [] - if self._create_context.host_name == "traypublisher": + if host_name == "traypublisher": # no real context known return allowed_creator_identifiers - proj_settings = get_project_settings(self.project_name) + proj_settings = get_project_settings(project_name) filter_creator_profiles = ( proj_settings ["core"] @@ -1864,16 +1877,15 @@ class PublisherController(BasePublisherController): ["creator"] ["filter_creator_profiles"] ) - task_type = get_current_task_entity()["taskType"] filtering_criteria = { - "task_names": self.current_task_name, + "task_names": task_name, "task_types": task_type, - "hosts": self._create_context.host_name + "hosts": host_name } profile = filter_profiles( filter_creator_profiles, filtering_criteria, - logger=self.log + logger=log ) if profile: From 170b1ab9dce32804c737b4b3e5d316fb8b7b56e8 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 29 May 2024 12:12:56 +0200 Subject: [PATCH 09/91] Fix default factory Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- server/settings/tools.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/settings/tools.py b/server/settings/tools.py index 6d0c133511..5587e38ed1 100644 --- a/server/settings/tools.py +++ b/server/settings/tools.py @@ -48,7 +48,8 @@ class FilterCreatorProfile(BaseSettingsModel): task_names: list[str] = SettingsField(default_factory=list, title="Task names") creator_identifiers: list[str] = SettingsField( - "", title="Allowed Creator Identifiers") + default_factory=list, + title="Allowed Creator Identifiers") class CreatorToolModel(BaseSettingsModel): From ea626e125769e91ab2afa6b5fe01dcddecf5159c Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 29 May 2024 12:13:10 +0200 Subject: [PATCH 10/91] Fix formatting Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- client/ayon_core/tools/publisher/control.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index 7753804911..9ea1efecba 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -1839,8 +1839,10 @@ class PublisherController(BasePublisherController): ) for identifier, creator in self._create_context.creators.items(): try: - if (allowed_creator_identifiers and - identifier not in allowed_creator_identifiers): + if ( + allowed_creator_identifiers is not None + and identifier not in allowed_creator_identifiers + ): self.log.debug(f"{identifier} not allowed for context") continue output[identifier] = CreatorItem.from_creator(creator) From 34041b3a1d3c3419b024f0b458d5eb1a76bc8d1f Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 29 May 2024 12:13:23 +0200 Subject: [PATCH 11/91] Fix formatting Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- client/ayon_core/tools/publisher/control.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index 9ea1efecba..fa8236e64f 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -1856,12 +1856,12 @@ class PublisherController(BasePublisherController): return output def _get_allowed_creator_identifiers( - self, - project_name, - host_name, - task_name, - task_type, - log=None + self, + project_name, + host_name, + task_name, + task_type, + log=None ): """Provide configured creator identifier in this context From 5e95565d25eb6f5511e4a109c4eb5c527cff9689 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 29 May 2024 12:15:05 +0200 Subject: [PATCH 12/91] Fix formatting Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- server/settings/tools.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server/settings/tools.py b/server/settings/tools.py index 5587e38ed1..37b0ddfd59 100644 --- a/server/settings/tools.py +++ b/server/settings/tools.py @@ -45,8 +45,9 @@ class FilterCreatorProfile(BaseSettingsModel): title="Task types", enum_resolver=task_types_enum ) - task_names: list[str] = SettingsField(default_factory=list, - title="Task names") + task_names: list[str] = SettingsField( + default_factory=list, + title="Task names") creator_identifiers: list[str] = SettingsField( default_factory=list, title="Allowed Creator Identifiers") From 719e5aa56bb3cc84471509631bb6b75aa18b8b17 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 29 May 2024 13:16:05 +0200 Subject: [PATCH 13/91] AY-5539 - remove explicit check for traypublisher Safely return task_type only if task_entity exits. --- client/ayon_core/tools/publisher/control.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index fa8236e64f..76c647d37f 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -1830,11 +1830,15 @@ class PublisherController(BasePublisherController): def _collect_creator_items(self): # TODO add crashed initialization of create plugins to report output = {} + task_type = None + current_task_entity = get_current_task_entity() + if current_task_entity: + task_type = current_task_entity["taskType"] allowed_creator_identifiers = self._get_allowed_creator_identifiers( self.project_name, self._create_context.host_name, self.current_task_name, - get_current_task_entity()["taskType"], + task_type, self.log ) for identifier, creator in self._create_context.creators.items(): @@ -1867,10 +1871,7 @@ class PublisherController(BasePublisherController): If no profile provided for current context, it shows all creators """ - allowed_creator_identifiers = [] - if host_name == "traypublisher": - # no real context known - return allowed_creator_identifiers + allowed_creator_identifiers = None proj_settings = get_project_settings(project_name) filter_creator_profiles = ( proj_settings From 3c287e1d64151f76487a504e40eb4afb21b7f0a0 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 29 May 2024 14:13:49 +0200 Subject: [PATCH 14/91] AY-5539 - added project settings to CreatorContext --- client/ayon_core/pipeline/create/context.py | 18 ++++++++++++++++++ client/ayon_core/tools/publisher/control.py | 18 +++++++++++++----- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/client/ayon_core/pipeline/create/context.py b/client/ayon_core/pipeline/create/context.py index 45846553a4..f29f2a12a0 100644 --- a/client/ayon_core/pipeline/create/context.py +++ b/client/ayon_core/pipeline/create/context.py @@ -1401,6 +1401,7 @@ class CreateContext: self._current_folder_path = None self._current_task_name = None self._current_workfile_path = None + self._current_project_settings = None self._current_project_anatomy = None @@ -1571,6 +1572,17 @@ class CreateContext: return self._current_task_name + def get_current_task_entity(self): + """Task name which was used as current context on context reset. + + Returns: + Union[str, None]: Task name. + """ + task_name = self.get_current_task_name() + if self._current_task_entity is None and task_name: + self._current_task_entity = get_current_task_entity() + return self._current_task_entity + def get_current_workfile_path(self): """Workfile path which was opened on context reset. @@ -1592,6 +1604,12 @@ class CreateContext: self._current_project_name) return self._current_project_anatomy + def get_current_project_settings(self): + if self._current_project_settings is None: + self._current_project_settings = get_project_settings( + self.get_current_project_name()) + return self._current_project_settings + @property def context_has_changed(self): """Host context has changed. diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index 76c647d37f..9b12b3c318 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -39,7 +39,6 @@ from ayon_core.pipeline.create.context import ( ) from ayon_core.pipeline.publish import get_publish_instance_label from ayon_core.tools.common_models import HierarchyModel -from ayon_core.settings import get_project_settings from ayon_core.lib.profiles_filtering import filter_profiles from ayon_core.pipeline.context_tools import get_current_task_entity @@ -1665,6 +1664,16 @@ class PublisherController(BasePublisherController): return self._create_context.get_current_task_name() + @property + def current_project_settings(self): + """Current project settings. + + Returns: + dict + """ + + return self._create_context.get_current_project_settings() + @property def host_context_has_changed(self): return self._create_context.context_has_changed @@ -1835,7 +1844,7 @@ class PublisherController(BasePublisherController): if current_task_entity: task_type = current_task_entity["taskType"] allowed_creator_identifiers = self._get_allowed_creator_identifiers( - self.project_name, + self.current_project_settings, self._create_context.host_name, self.current_task_name, task_type, @@ -1861,7 +1870,7 @@ class PublisherController(BasePublisherController): def _get_allowed_creator_identifiers( self, - project_name, + project_settings, host_name, task_name, task_type, @@ -1872,9 +1881,8 @@ class PublisherController(BasePublisherController): If no profile provided for current context, it shows all creators """ allowed_creator_identifiers = None - proj_settings = get_project_settings(project_name) filter_creator_profiles = ( - proj_settings + project_settings ["core"] ["tools"] ["creator"] From cafb4c9ad099830a81f1018299036f24b49b45f5 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 29 May 2024 16:28:18 +0200 Subject: [PATCH 15/91] Use host_names in Settings Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- server/settings/tools.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/settings/tools.py b/server/settings/tools.py index 37b0ddfd59..f1ee44168f 100644 --- a/server/settings/tools.py +++ b/server/settings/tools.py @@ -39,7 +39,9 @@ class FilterCreatorProfile(BaseSettingsModel): """Provide list of allowed Creator identifiers for context""" _layout = "expanded" - hosts: list[str] = SettingsField(default_factory=list, title="Hosts") + host_names: list[str] = SettingsField( + default_factory=list, title="Host names" + ) task_types: list[str] = SettingsField( default_factory=list, title="Task types", From e899dd05f36173435348f520d6d8229d8f71b937 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 29 May 2024 16:29:14 +0200 Subject: [PATCH 16/91] AY-5539 - changed value from Settings --- client/ayon_core/tools/publisher/control.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index 9b12b3c318..08229ae7f4 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -1891,7 +1891,7 @@ class PublisherController(BasePublisherController): filtering_criteria = { "task_names": task_name, "task_types": task_type, - "hosts": host_name + "host_names": host_name } profile = filter_profiles( filter_creator_profiles, From 63a2e8f81e311eba37eb14a2d1741dcc28f4f3ca Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 30 May 2024 11:36:07 +0200 Subject: [PATCH 17/91] AY-5539 - removed get_current_task_entity Wasn't implemented properly, cannot import from context_tools because of circular import. --- client/ayon_core/pipeline/create/context.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/client/ayon_core/pipeline/create/context.py b/client/ayon_core/pipeline/create/context.py index f29f2a12a0..f9ed61bc5b 100644 --- a/client/ayon_core/pipeline/create/context.py +++ b/client/ayon_core/pipeline/create/context.py @@ -1572,17 +1572,6 @@ class CreateContext: return self._current_task_name - def get_current_task_entity(self): - """Task name which was used as current context on context reset. - - Returns: - Union[str, None]: Task name. - """ - task_name = self.get_current_task_name() - if self._current_task_entity is None and task_name: - self._current_task_entity = get_current_task_entity() - return self._current_task_entity - def get_current_workfile_path(self): """Workfile path which was opened on context reset. From 4d812df9ad13356204368aa0feea5b66371ac393 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 30 May 2024 11:38:07 +0200 Subject: [PATCH 18/91] AY-5539 - reset project_setting when necessary --- client/ayon_core/pipeline/create/context.py | 1 + 1 file changed, 1 insertion(+) diff --git a/client/ayon_core/pipeline/create/context.py b/client/ayon_core/pipeline/create/context.py index f9ed61bc5b..cca40362d6 100644 --- a/client/ayon_core/pipeline/create/context.py +++ b/client/ayon_core/pipeline/create/context.py @@ -1726,6 +1726,7 @@ class CreateContext: self._current_workfile_path = workfile_path self._current_project_anatomy = None + self._current_project_settings = None def reset_plugins(self, discover_publish_plugins=True): """Reload plugins. From 7b6f8d24affd645854a94bcf248e326122bacaa0 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 30 May 2024 11:39:39 +0200 Subject: [PATCH 19/91] AY-5539 - use internal method for settings --- client/ayon_core/pipeline/create/context.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/pipeline/create/context.py b/client/ayon_core/pipeline/create/context.py index cca40362d6..35b78689f5 100644 --- a/client/ayon_core/pipeline/create/context.py +++ b/client/ayon_core/pipeline/create/context.py @@ -1780,7 +1780,7 @@ class CreateContext: def _reset_creator_plugins(self): # Prepare settings - project_settings = get_project_settings(self.project_name) + project_settings = self.get_current_project_settings() # Discover and prepare creators creators = {} From 739d459e74b3e5e7390fe2eb38f7b4fce4bf832d Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 30 May 2024 12:29:56 +0200 Subject: [PATCH 20/91] CreateContext has methods to get folder & task entity and task type --- client/ayon_core/pipeline/create/context.py | 67 +++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/client/ayon_core/pipeline/create/context.py b/client/ayon_core/pipeline/create/context.py index 35b78689f5..0d8722dab1 100644 --- a/client/ayon_core/pipeline/create/context.py +++ b/client/ayon_core/pipeline/create/context.py @@ -37,6 +37,7 @@ from .creator_plugins import ( # Changes of instances and context are send as tuple of 2 information UpdateData = collections.namedtuple("UpdateData", ["instance", "changes"]) +_NOT_SET = object() class UnavailableSharedData(Exception): @@ -1403,6 +1404,10 @@ class CreateContext: self._current_workfile_path = None self._current_project_settings = None + self._current_folder_entity = _NOT_SET + self._current_task_entity = _NOT_SET + self._current_task_type = _NOT_SET + self._current_project_anatomy = None self._host_is_valid = host_is_valid @@ -1572,6 +1577,64 @@ class CreateContext: return self._current_task_name + def get_current_task_type(self): + """Task type which was used as current context on context reset. + + Returns: + Union[str, None]: Task type. + + """ + if self._current_task_type is _NOT_SET: + task_type = None + task_entity = self.get_current_task_entity() + if task_entity: + task_type = task_entity["taskType"] + self._current_task_type = task_type + return self._current_task_type + + def get_current_folder_entity(self): + """Folder entity for current context folder. + + Returns: + Union[dict[str, Any], None]: Folder entity. + + """ + if self._current_folder_entity is not _NOT_SET: + return copy.deepcopy(self._current_folder_entity) + folder_entity = None + folder_path = self.get_current_folder_path() + if folder_path: + project_name = self.get_current_project_name() + folder_entity = ayon_api.get_folder_by_path( + project_name, folder_path + ) + self._current_folder_entity = folder_entity + return copy.deepcopy(self._current_folder_entity) + + def get_current_task_entity(self): + """Task entity for current context task. + + Returns: + Union[dict[str, Any], None]: Task entity. + + """ + if self._current_task_entity is not _NOT_SET: + return copy.deepcopy(self._current_task_entity) + task_entity = None + task_name = self.get_current_task_name() + if task_name: + folder_entity = self.get_current_folder_entity() + if folder_entity: + project_name = self.get_current_project_name() + task_entity = ayon_api.get_task_by_name( + project_name, + folder_id=folder_entity["id"], + task_name=task_name + ) + self._current_task_entity = task_entity + return copy.deepcopy(self._current_task_entity) + + def get_current_workfile_path(self): """Workfile path which was opened on context reset. @@ -1725,6 +1788,10 @@ class CreateContext: self._current_task_name = task_name self._current_workfile_path = workfile_path + self._current_folder_entity = _NOT_SET + self._current_task_entity = _NOT_SET + self._current_task_type = _NOT_SET + self._current_project_anatomy = None self._current_project_settings = None From ec0327f44f1de63f00d539148c2b0849fbb9d7e7 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 30 May 2024 12:30:59 +0200 Subject: [PATCH 21/91] use new method in publish controller --- client/ayon_core/tools/publisher/control.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index 08229ae7f4..acbd7683ad 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -1839,10 +1839,7 @@ class PublisherController(BasePublisherController): def _collect_creator_items(self): # TODO add crashed initialization of create plugins to report output = {} - task_type = None - current_task_entity = get_current_task_entity() - if current_task_entity: - task_type = current_task_entity["taskType"] + task_type = self._create_context.get_current_task_type() allowed_creator_identifiers = self._get_allowed_creator_identifiers( self.current_project_settings, self._create_context.host_name, From 6e2cdf36a0b887840f7f30ffb502c6d45aaa0d33 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 30 May 2024 12:33:46 +0200 Subject: [PATCH 22/91] '_get_allowed_creator_identifiers' does not expect any arguments --- client/ayon_core/tools/publisher/control.py | 47 ++++++++------------- 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index acbd7683ad..61bd74de5a 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -1664,16 +1664,6 @@ class PublisherController(BasePublisherController): return self._create_context.get_current_task_name() - @property - def current_project_settings(self): - """Current project settings. - - Returns: - dict - """ - - return self._create_context.get_current_project_settings() - @property def host_context_has_changed(self): return self._create_context.context_has_changed @@ -1698,6 +1688,15 @@ class PublisherController(BasePublisherController): """Publish plugins.""" return self._create_context.publish_plugins + def _get_current_project_settings(self): + """Current project settings. + + Returns: + dict + """ + + return self._create_context.get_current_project_settings() + # Hierarchy model def get_folder_items(self, project_name, sender=None): return self._hierarchy_model.get_folder_items(project_name, sender) @@ -1839,14 +1838,7 @@ class PublisherController(BasePublisherController): def _collect_creator_items(self): # TODO add crashed initialization of create plugins to report output = {} - task_type = self._create_context.get_current_task_type() - allowed_creator_identifiers = self._get_allowed_creator_identifiers( - self.current_project_settings, - self._create_context.host_name, - self.current_task_name, - task_type, - self.log - ) + allowed_creator_identifiers = self._get_allowed_creator_identifiers() for identifier, creator in self._create_context.creators.items(): try: if ( @@ -1865,18 +1857,15 @@ class PublisherController(BasePublisherController): return output - def _get_allowed_creator_identifiers( - self, - project_settings, - host_name, - task_name, - task_type, - log=None - ): + def _get_allowed_creator_identifiers(self): """Provide configured creator identifier in this context If no profile provided for current context, it shows all creators """ + + task_type = self._create_context.get_current_task_type() + project_settings = self._get_current_project_settings() + allowed_creator_identifiers = None filter_creator_profiles = ( project_settings @@ -1886,14 +1875,14 @@ class PublisherController(BasePublisherController): ["filter_creator_profiles"] ) filtering_criteria = { - "task_names": task_name, + "task_names": self.current_task_name, "task_types": task_type, - "host_names": host_name + "host_names": self._create_context.host_name } profile = filter_profiles( filter_creator_profiles, filtering_criteria, - logger=log + logger=self.log ) if profile: From 31c2d7ef3b0c901f1592d6b5157b082b213570c2 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 30 May 2024 13:02:21 +0200 Subject: [PATCH 23/91] removed unused import --- client/ayon_core/tools/publisher/control.py | 1 - 1 file changed, 1 deletion(-) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index 61bd74de5a..0a933ffbfb 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -40,7 +40,6 @@ from ayon_core.pipeline.create.context import ( from ayon_core.pipeline.publish import get_publish_instance_label from ayon_core.tools.common_models import HierarchyModel from ayon_core.lib.profiles_filtering import filter_profiles -from ayon_core.pipeline.context_tools import get_current_task_entity # Define constant for plugin orders offset PLUGIN_ORDER_OFFSET = 0.5 From 96c11e6a332a5d3d5a2476c8428136fe7259ed19 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 31 May 2024 12:47:00 +0200 Subject: [PATCH 24/91] AY-5539 - used labels instead of identifiers Identifiers are bit hard to get to fill them into Settings, labels are visible in Publisher and can by Copy&Pasted. --- client/ayon_core/tools/publisher/control.py | 20 ++++++++++---------- server/settings/tools.py | 10 +++++++--- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index 61bd74de5a..1ded279aa2 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -1838,14 +1838,14 @@ class PublisherController(BasePublisherController): def _collect_creator_items(self): # TODO add crashed initialization of create plugins to report output = {} - allowed_creator_identifiers = self._get_allowed_creator_identifiers() + allowed_creator_labels = self._get_allowed_creator_labels() for identifier, creator in self._create_context.creators.items(): try: if ( - allowed_creator_identifiers is not None - and identifier not in allowed_creator_identifiers + allowed_creator_labels is not None + and creator.label not in allowed_creator_labels ): - self.log.debug(f"{identifier} not allowed for context") + self.log.debug(f"{creator.label} not allowed for context") continue output[identifier] = CreatorItem.from_creator(creator) except Exception: @@ -1857,16 +1857,16 @@ class PublisherController(BasePublisherController): return output - def _get_allowed_creator_identifiers(self): - """Provide configured creator identifier in this context + def _get_allowed_creator_labels(self): + """Provide configured creator label in this context - If no profile provided for current context, it shows all creators + If no profile matches current context, it shows all creators """ task_type = self._create_context.get_current_task_type() project_settings = self._get_current_project_settings() - allowed_creator_identifiers = None + allowed_creator_labels = None filter_creator_profiles = ( project_settings ["core"] @@ -1886,8 +1886,8 @@ class PublisherController(BasePublisherController): ) if profile: - allowed_creator_identifiers = profile["creator_identifiers"] - return allowed_creator_identifiers + allowed_creator_labels = profile["creator_labels"] + return allowed_creator_labels def _reset_instances(self): """Reset create instances.""" diff --git a/server/settings/tools.py b/server/settings/tools.py index f1ee44168f..ed0c723bac 100644 --- a/server/settings/tools.py +++ b/server/settings/tools.py @@ -50,9 +50,11 @@ class FilterCreatorProfile(BaseSettingsModel): task_names: list[str] = SettingsField( default_factory=list, title="Task names") - creator_identifiers: list[str] = SettingsField( + creator_labels: list[str] = SettingsField( default_factory=list, - title="Allowed Creator Identifiers") + title="Allowed Creator Labels", + description="Copy creator label from Publisher, regex supported." + ) class CreatorToolModel(BaseSettingsModel): @@ -70,7 +72,9 @@ class CreatorToolModel(BaseSettingsModel): filter_creator_profiles: list[FilterCreatorProfile] = SettingsField( default_factory=list, - title="Filter creator profiles" + title="Filter creator profiles", + description="White list of creator labels that will be only shown if " + "profile matches context." ) @validator("product_types_smart_select") From 5a314354b7b23473f97c609c897f423649a5ecb1 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 31 May 2024 13:00:17 +0200 Subject: [PATCH 25/91] AY-5539 - support regex in creator label --- client/ayon_core/tools/publisher/control.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index 1ded279aa2..a15ab09256 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -8,6 +8,7 @@ import tempfile import shutil import inspect from abc import ABCMeta, abstractmethod +import re import six import arrow @@ -1843,7 +1844,8 @@ class PublisherController(BasePublisherController): try: if ( allowed_creator_labels is not None - and creator.label not in allowed_creator_labels + and not self._label_matches_allowed( + creator.label, allowed_creator_labels) ): self.log.debug(f"{creator.label} not allowed for context") continue @@ -1889,6 +1891,13 @@ class PublisherController(BasePublisherController): allowed_creator_labels = profile["creator_labels"] return allowed_creator_labels + def _label_matches_allowed(self, label, allowed_labels): + """Implement regex support for allowed labels.""" + for allowed in allowed_labels: + if re.match(allowed, label): + return True + return False + def _reset_instances(self): """Reset create instances.""" if self._resetting_instances: From 2794190160cfb370c160c65e5158bb5607ab5f3b Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 31 May 2024 13:01:44 +0200 Subject: [PATCH 26/91] AY-5539 - added logging on profile match --- client/ayon_core/tools/publisher/control.py | 1 + 1 file changed, 1 insertion(+) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index a15ab09256..abf116d337 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -1889,6 +1889,7 @@ class PublisherController(BasePublisherController): if profile: allowed_creator_labels = profile["creator_labels"] + self.log.debug(f"Only allowed `{allowed_creator_labels}` creators") return allowed_creator_labels def _label_matches_allowed(self, label, allowed_labels): From d2d05f64f75efd33501b000925c27d90214a17f7 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 31 May 2024 13:31:47 +0200 Subject: [PATCH 27/91] Updated description Co-authored-by: Roy Nieterau --- server/settings/tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/settings/tools.py b/server/settings/tools.py index ed0c723bac..6c02a928bf 100644 --- a/server/settings/tools.py +++ b/server/settings/tools.py @@ -73,7 +73,7 @@ class CreatorToolModel(BaseSettingsModel): filter_creator_profiles: list[FilterCreatorProfile] = SettingsField( default_factory=list, title="Filter creator profiles", - description="White list of creator labels that will be only shown if " + description="Allowed list of creator labels that will be only shown if " "profile matches context." ) From 0fe6526ae9d0b207c43ad85d867b354ea79a2ac1 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 31 May 2024 13:34:41 +0200 Subject: [PATCH 28/91] AY-5539 - possible speedup of resolution --- client/ayon_core/tools/publisher/control.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index b38df857c0..e73c68a295 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -1893,9 +1893,9 @@ class PublisherController(BasePublisherController): def _label_matches_allowed(self, label, allowed_labels): """Implement regex support for allowed labels.""" - for allowed in allowed_labels: - if re.match(allowed, label): - return True + allowed_patterns = re.compile("|".join(allowed_labels)) + if allowed_patterns.match(label): + return True return False def _reset_instances(self): From d737a162cc495c58d7021937cb212c6cdc986d23 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 31 May 2024 20:22:36 +0800 Subject: [PATCH 29/91] application settings for motion builder --- server_addon/applications/package.py | 2 +- .../applications/server/applications.json | 22 +++++++++++++++++++ server_addon/applications/server/settings.py | 2 ++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/server_addon/applications/package.py b/server_addon/applications/package.py index 983749355e..a95acad345 100644 --- a/server_addon/applications/package.py +++ b/server_addon/applications/package.py @@ -1,6 +1,6 @@ name = "applications" title = "Applications" -version = "0.2.2" +version = "0.2.3" ayon_server_version = ">=1.0.7" ayon_launcher_version = ">=1.0.2" diff --git a/server_addon/applications/server/applications.json b/server_addon/applications/server/applications.json index 84b7fa33cf..5944f482f3 100644 --- a/server_addon/applications/server/applications.json +++ b/server_addon/applications/server/applications.json @@ -1293,6 +1293,28 @@ } ] }, + "motionbuilder": { + "enabled": true, + "label": "Motion Builder", + "icon": "{}/app_icons/motionbuilder.png", + "host_name": "motionbuilder", + "environment": "{}", + "variants": [ + { + "name": "2025", + "label": "2025", + "use_python_2": false, + "executables": { + "windows": [ + "C:\\Program Files\\Autodesk\\MotionBuilder 2025\\bin\\x64\\motionbuilder.exe" + ], + "darwin": [], + "linux": [] + }, + "environment": "{}" + } + ] + }, "additional_apps": [] } } diff --git a/server_addon/applications/server/settings.py b/server_addon/applications/server/settings.py index 3f9d90ef5b..23f37828a6 100644 --- a/server_addon/applications/server/settings.py +++ b/server_addon/applications/server/settings.py @@ -192,6 +192,8 @@ class ApplicationsSettings(BaseSettingsModel): default_factory=AppGroupWithPython, title="Zbrush") equalizer: AppGroup = SettingsField( default_factory=AppGroupWithPython, title="3DEqualizer") + motionbuilder: AppGroup = SettingsField( + default_factory=AppGroupWithPython, title="Motion Builder") additional_apps: list[AdditionalAppGroup] = SettingsField( default_factory=list, title="Additional Applications") From 6251063e71e5825798af307d1a6ba3e531417cd8 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 31 May 2024 21:24:07 +0800 Subject: [PATCH 30/91] add motionbuilder image --- .../resources/app_icons/motionbuilder.png | Bin 0 -> 35807 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 client/ayon_core/resources/app_icons/motionbuilder.png diff --git a/client/ayon_core/resources/app_icons/motionbuilder.png b/client/ayon_core/resources/app_icons/motionbuilder.png new file mode 100644 index 0000000000000000000000000000000000000000..68a17f7afbbbe6816b8891d8443c9819c8de6835 GIT binary patch literal 35807 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 z z;LL}VsA!q&?(Qu7_IEA++O?bpzYR76>&D?mij>!Oc2PCn(0KcQF-3gl6`KR6;Kj`I zL&88B5(bTFebT>SMCGBV$%X_=FBpA|7*LsGa!T*Y0hz)&D0?va=4ynsmkvjOj9kVHwo7{Avx8upOKk$KW!)sQd!P0oFVB^YK+jF~ug; zoxy{zv)x)5wBXN`@Ds2%7a6rXIAQE@u2i@Z5?kYA3*Pspt&ZxTer&QJ-*fMn6OvU~qBVHnK+-$mABi617$C z3wU`T>E4pX5*6DYOi=B7^{7JL(k`6yc6!aA9&ebW+o2zE_ai^z9QKJm-FYoBQYb6RZciJXeIDwwx;2cg2D` zx+?qLjKqQ(3ytHBmVL91JP=SLy#le2C`>vh~H->^XJwaLDWJ5!mg*Ls+@ zw(L1!x{r0UUi=JQKw5QQT|JZ`h z5s&Wb^KV}_sV1c*{KtZG%?|~BzkB?l&Ps}JyUm-Dp49CPDg)_JCtJMBJ%v`?c4<>uXSt#RBgrI z#K=m!NuIOrto8c5?2tl$e&$K}H=5c#ep4728sh&0PbS+R6&Y3g64=7qeE-+SulY&) z>)C;4Q`mS;Ij_g;_i~C{nb1++z{3|MCVSdlKk%San1SKL_WG~a>we$4$$h`#OY8Fg zC%f0z{5Jkxp8v35L+{>uxlewkJgi;}TxzM_&9QSvgA4cDV^WvgUjMt3W!Ja7&xWJ+ z^ZNbYxMxRypLhG-&i{AjR_E82*~pc5Xs{ZnE&6DE_P*xaON9Y?o6Z%O0LS|Fy)Uo- z6}s{QsKf2?G%So)o1@5f_bO-`%5yzFmpJH2)N zi-p1rKnE;0v9~gO&H(g=-^(8_K?_qg_qLNv|7Tya&!Rh6=J_NBAn8t literal 0 HcmV?d00001 From e63910024d98e08f2ea18ecec473d5da92a5630c Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 3 Jun 2024 15:52:19 +0800 Subject: [PATCH 31/91] add motionbuilder with collect scene version --- .../plugins/publish/collect_scene_version.py | 3 ++- server_addon/applications/server/applications.json | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/collect_scene_version.py b/client/ayon_core/plugins/publish/collect_scene_version.py index b04900c74e..8b99e2cd98 100644 --- a/client/ayon_core/plugins/publish/collect_scene_version.py +++ b/client/ayon_core/plugins/publish/collect_scene_version.py @@ -27,7 +27,8 @@ class CollectSceneVersion(pyblish.api.ContextPlugin): "nuke", "photoshop", "resolve", - "tvpaint" + "tvpaint", + "motionbuilder" ] # in some cases of headless publishing (for example webpublisher using PS) diff --git a/server_addon/applications/server/applications.json b/server_addon/applications/server/applications.json index 5944f482f3..1c83997dea 100644 --- a/server_addon/applications/server/applications.json +++ b/server_addon/applications/server/applications.json @@ -1312,6 +1312,19 @@ "linux": [] }, "environment": "{}" + }, + { + "name": "2024", + "label": "2024", + "use_python_2": false, + "executables": { + "windows": [ + "C:\\Program Files\\Autodesk\\MotionBuilder 2024\\bin\\x64\\motionbuilder.exe" + ], + "darwin": [], + "linux": [] + }, + "environment": "{}" } ] }, From 0fa90417369919248500d6b83ccbfca4f125e602 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 3 Jun 2024 11:42:29 +0200 Subject: [PATCH 32/91] AY-5539 - update resolution logic --- client/ayon_core/tools/publisher/control.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index e73c68a295..9578b07b15 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -1841,11 +1841,8 @@ class PublisherController(BasePublisherController): allowed_creator_labels = self._get_allowed_creator_labels() for identifier, creator in self._create_context.creators.items(): try: - if ( - allowed_creator_labels is not None - and not self._label_matches_allowed( - creator.label, allowed_creator_labels) - ): + if (not self._label_matches_allowed( + creator.label, allowed_creator_labels)): self.log.debug(f"{creator.label} not allowed for context") continue output[identifier] = CreatorItem.from_creator(creator) @@ -1893,9 +1890,10 @@ class PublisherController(BasePublisherController): def _label_matches_allowed(self, label, allowed_labels): """Implement regex support for allowed labels.""" - allowed_patterns = re.compile("|".join(allowed_labels)) - if allowed_patterns.match(label): - return True + if allowed_labels: + allowed_patterns = re.compile("|".join(allowed_labels)) + if allowed_patterns.match(label): + return True return False def _reset_instances(self): From c7f0e977f79d6b35ba9f782d21a4da58145901ba Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 3 Jun 2024 11:45:13 +0200 Subject: [PATCH 33/91] AY-5539 - refactor variable position --- client/ayon_core/tools/publisher/control.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index 9578b07b15..c9680b1d9e 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -1864,7 +1864,6 @@ class PublisherController(BasePublisherController): task_type = self._create_context.get_current_task_type() project_settings = self._get_current_project_settings() - allowed_creator_labels = None filter_creator_profiles = ( project_settings ["core"] @@ -1883,6 +1882,7 @@ class PublisherController(BasePublisherController): logger=self.log ) + allowed_creator_labels = None if profile: allowed_creator_labels = profile["creator_labels"] self.log.debug(f"Only allowed `{allowed_creator_labels}` creators") From 4e07b756af65cdb08c58271976bf95b7216ad306 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 3 Jun 2024 12:06:29 +0200 Subject: [PATCH 34/91] AY-5539 - fix wrong logic --- client/ayon_core/tools/publisher/control.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index c9680b1d9e..72a89d2a3a 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -1841,7 +1841,7 @@ class PublisherController(BasePublisherController): allowed_creator_labels = self._get_allowed_creator_labels() for identifier, creator in self._create_context.creators.items(): try: - if (not self._label_matches_allowed( + if (not self._is_label_allowed( creator.label, allowed_creator_labels)): self.log.debug(f"{creator.label} not allowed for context") continue @@ -1888,13 +1888,12 @@ class PublisherController(BasePublisherController): self.log.debug(f"Only allowed `{allowed_creator_labels}` creators") return allowed_creator_labels - def _label_matches_allowed(self, label, allowed_labels): + def _is_label_allowed(self, label, allowed_labels): """Implement regex support for allowed labels.""" - if allowed_labels: - allowed_patterns = re.compile("|".join(allowed_labels)) - if allowed_patterns.match(label): - return True - return False + if not allowed_labels: + return True + allowed_patterns = re.compile("|".join(allowed_labels)) + return bool(allowed_patterns.match(label)) def _reset_instances(self): """Reset create instances.""" From 577da3fb7fcbc2a217d487708b093d81f6c5dee9 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 3 Jun 2024 15:57:30 +0200 Subject: [PATCH 35/91] AY-5539 - protect from empty field in Settings --- client/ayon_core/tools/publisher/control.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index 72a89d2a3a..66487343d1 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -1884,7 +1884,11 @@ class PublisherController(BasePublisherController): allowed_creator_labels = None if profile: - allowed_creator_labels = profile["creator_labels"] + allowed_creator_labels = { + label + for label in profile["creator_labels"] + if label + } self.log.debug(f"Only allowed `{allowed_creator_labels}` creators") return allowed_creator_labels From dd02631786628729fec3fcb696696d1761d513bb Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 3 Jun 2024 17:46:01 +0200 Subject: [PATCH 36/91] AY-5539 - do only single re compile re.compile might be expensive, do it outside of loop --- client/ayon_core/tools/publisher/control.py | 24 +++++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index 66487343d1..f2a440d701 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -1856,9 +1856,13 @@ class PublisherController(BasePublisherController): return output def _get_allowed_creator_labels(self): - """Provide configured creator label in this context + """Provide configured creator labels in this context - If no profile matches current context, it shows all creators + If no profile matches current context, it shows all creators. + Support usage of regular expressions for configured values. + Returns: + (str): None or regex compiled patterns into single one + ('Render|Image.*') """ task_type = self._create_context.get_current_task_type() @@ -1890,14 +1894,20 @@ class PublisherController(BasePublisherController): if label } self.log.debug(f"Only allowed `{allowed_creator_labels}` creators") + allowed_creator_labels = ( + re.compile("|".join(allowed_creator_labels))) return allowed_creator_labels - def _is_label_allowed(self, label, allowed_labels): - """Implement regex support for allowed labels.""" - if not allowed_labels: + def _is_label_allowed(self, label, allowed_label_regexes): + """Implement regex support for allowed labels. + + Args: + label (str): Label of creator - shown in Publisher + allowed_label_regexes (str): compiled regular expression + """ + if not allowed_label_regexes: return True - allowed_patterns = re.compile("|".join(allowed_labels)) - return bool(allowed_patterns.match(label)) + return bool(allowed_label_regexes.match(label)) def _reset_instances(self): """Reset create instances.""" From 8f7882ae28d6048ae8da102b392a42e2f63714e1 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Tue, 4 Jun 2024 16:21:11 +0200 Subject: [PATCH 37/91] use 'newHierarchyIntegration' instead of 'newAssetPublishing' --- .../publish/collect_anatomy_instance_data.py | 25 +++++++++++++------ .../plugins/publish/validate_asset_docs.py | 6 ++++- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/client/ayon_core/plugins/publish/collect_anatomy_instance_data.py b/client/ayon_core/plugins/publish/collect_anatomy_instance_data.py index ad5a5d43fc..3086c04000 100644 --- a/client/ayon_core/plugins/publish/collect_anatomy_instance_data.py +++ b/client/ayon_core/plugins/publish/collect_anatomy_instance_data.py @@ -391,7 +391,11 @@ class CollectAnatomyInstanceData(pyblish.api.ContextPlugin): anatomy_data.update(folder_data) return - if instance.data.get("newAssetPublishing"): + if ( + instance.data.get("newHierarchyIntegration") + # Backwards compatible + or instance.data.get("newAssetPublishing") + ): hierarchy = instance.data["hierarchy"] anatomy_data["hierarchy"] = hierarchy @@ -409,7 +413,7 @@ class CollectAnatomyInstanceData(pyblish.api.ContextPlugin): "path": instance.data["folderPath"], # TODO get folder type from hierarchy # Using 'Shot' is current default behavior of editorial - # (or 'newAssetPublishing') publishing. + # (or 'newHierarchyIntegration') publishing. "type": "Shot", }, }) @@ -432,15 +436,22 @@ class CollectAnatomyInstanceData(pyblish.api.ContextPlugin): if task_data: # Fill task data # - if we're in editorial, make sure the task type is filled - if ( - not instance.data.get("newAssetPublishing") - or task_data["type"] - ): + new_hierarchy = ( + instance.data.get("newHierarchyIntegration") + # Backwards compatible + or instance.data.get("newAssetPublishing") + ) + if not new_hierarchy or task_data["type"]: anatomy_data["task"] = task_data return # New hierarchy is not created, so we can only skip rest of the logic - if not instance.data.get("newAssetPublishing"): + new_hierarchy = ( + instance.data.get("newHierarchyIntegration") + # Backwards compatible + or instance.data.get("newAssetPublishing") + ) + if not new_hierarchy: return # Try to find task data based on hierarchy context and folder path diff --git a/client/ayon_core/plugins/publish/validate_asset_docs.py b/client/ayon_core/plugins/publish/validate_asset_docs.py index 95fe4252be..361f288545 100644 --- a/client/ayon_core/plugins/publish/validate_asset_docs.py +++ b/client/ayon_core/plugins/publish/validate_asset_docs.py @@ -24,7 +24,11 @@ class ValidateFolderEntities(pyblish.api.InstancePlugin): if instance.data.get("folderEntity"): self.log.debug("Instance has set fodler entity in its data.") - elif instance.data.get("newAssetPublishing"): + elif ( + instance.data.get("newHierarchyIntegration") + # Backwards compatible + or instance.data.get("newAssetPublishing") + ): # skip if it is editorial self.log.debug("Editorial instance has no need to check...") From cfe6ae1c67db2b22a9c4590926febb0e2497e3b6 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Tue, 4 Jun 2024 16:23:14 +0200 Subject: [PATCH 38/91] use 'newHierarchyIntegration' over 'newAssetPublishing' in hosts --- .../plugins/publish/collect_timeline_instances.py | 4 +++- server_addon/flame/client/ayon_flame/version.py | 2 +- server_addon/flame/package.py | 2 +- .../ayon_hiero/plugins/publish/precollect_instances.py | 4 +++- server_addon/hiero/client/ayon_hiero/version.py | 2 +- server_addon/hiero/package.py | 2 +- .../ayon_resolve/plugins/publish/precollect_instances.py | 2 ++ .../ayon_traypublisher/plugins/create/create_editorial.py | 2 ++ .../plugins/publish/collect_sequence_frame_data.py | 8 ++++++-- .../plugins/publish/validate_frame_ranges.py | 8 ++++++-- server_addon/traypublisher/package.py | 2 +- 11 files changed, 27 insertions(+), 11 deletions(-) diff --git a/server_addon/flame/client/ayon_flame/plugins/publish/collect_timeline_instances.py b/server_addon/flame/client/ayon_flame/plugins/publish/collect_timeline_instances.py index 35591f1a0d..f38a0903a0 100644 --- a/server_addon/flame/client/ayon_flame/plugins/publish/collect_timeline_instances.py +++ b/server_addon/flame/client/ayon_flame/plugins/publish/collect_timeline_instances.py @@ -152,7 +152,9 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): task["name"]: {"type": task["type"]} for task in self.add_tasks}, "representations": [], - "newAssetPublishing": True + "newHierarchyIntegration": True, + # Backwards compatible + "newAssetPublishing": True, }) self.log.debug("__ inst_data: {}".format(pformat(inst_data))) diff --git a/server_addon/flame/client/ayon_flame/version.py b/server_addon/flame/client/ayon_flame/version.py index 0004797e59..68bdb6e6a0 100644 --- a/server_addon/flame/client/ayon_flame/version.py +++ b/server_addon/flame/client/ayon_flame/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring AYON addon 'flame' version.""" -__version__ = "0.2.0" +__version__ = "0.2.1" diff --git a/server_addon/flame/package.py b/server_addon/flame/package.py index f228e61f8e..b25a514a9f 100644 --- a/server_addon/flame/package.py +++ b/server_addon/flame/package.py @@ -1,6 +1,6 @@ name = "flame" title = "Flame" -version = "0.2.0" +version = "0.2.1" client_dir = "ayon_flame" diff --git a/server_addon/hiero/client/ayon_hiero/plugins/publish/precollect_instances.py b/server_addon/hiero/client/ayon_hiero/plugins/publish/precollect_instances.py index fa2c56182e..be5312b325 100644 --- a/server_addon/hiero/client/ayon_hiero/plugins/publish/precollect_instances.py +++ b/server_addon/hiero/client/ayon_hiero/plugins/publish/precollect_instances.py @@ -140,7 +140,9 @@ class PrecollectInstances(pyblish.api.ContextPlugin): # add all additional tags "tags": phiero.get_track_item_tags(track_item), - "newAssetPublishing": True + "newHierarchyIntegration": True, + # Backwards compatible + "newAssetPublishing": True, }) # otio clip data diff --git a/server_addon/hiero/client/ayon_hiero/version.py b/server_addon/hiero/client/ayon_hiero/version.py index 6a2d180afb..fe6d62221c 100644 --- a/server_addon/hiero/client/ayon_hiero/version.py +++ b/server_addon/hiero/client/ayon_hiero/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring AYON addon 'hiero' version.""" -__version__ = "0.2.0" +__version__ = "0.2.1" diff --git a/server_addon/hiero/package.py b/server_addon/hiero/package.py index 1948d50e6d..95714d95da 100644 --- a/server_addon/hiero/package.py +++ b/server_addon/hiero/package.py @@ -1,6 +1,6 @@ name = "hiero" title = "Hiero" -version = "0.2.0" +version = "0.2.1" client_dir = "ayon_hiero" ayon_required_addons = { diff --git a/server_addon/resolve/client/ayon_resolve/plugins/publish/precollect_instances.py b/server_addon/resolve/client/ayon_resolve/plugins/publish/precollect_instances.py index 10e1eba3e3..af9a63d796 100644 --- a/server_addon/resolve/client/ayon_resolve/plugins/publish/precollect_instances.py +++ b/server_addon/resolve/client/ayon_resolve/plugins/publish/precollect_instances.py @@ -101,6 +101,8 @@ class PrecollectInstances(pyblish.api.ContextPlugin): "fps": context.data["fps"], "handleStart": handle_start, "handleEnd": handle_end, + "newHierarchyIntegration": True, + # Backwards compatible "newAssetPublishing": True, "families": ["clip"], "productType": product_type, diff --git a/server_addon/traypublisher/client/ayon_traypublisher/plugins/create/create_editorial.py b/server_addon/traypublisher/client/ayon_traypublisher/plugins/create/create_editorial.py index a2f6f211f5..0e4512d052 100644 --- a/server_addon/traypublisher/client/ayon_traypublisher/plugins/create/create_editorial.py +++ b/server_addon/traypublisher/client/ayon_traypublisher/plugins/create/create_editorial.py @@ -676,6 +676,8 @@ or updating already created. Publishing will create OTIO file. "shotName": shot_name, "variant": variant_name, "task": None, + "newHierarchyIntegration": True, + # Backwards compatible "newAssetPublishing": True, "trackStartFrame": track_start_frame, "timelineOffset": timeline_offset, diff --git a/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/collect_sequence_frame_data.py b/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/collect_sequence_frame_data.py index de18050f41..b76d81e431 100644 --- a/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/collect_sequence_frame_data.py +++ b/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/collect_sequence_frame_data.py @@ -28,8 +28,12 @@ class CollectSequenceFrameData( return # editorial would fail since they might not be in database yet - new_folder_publishing = instance.data.get("newAssetPublishing") - if new_folder_publishing: + new_hierarchy = ( + instance.data.get("newHierarchyIntegration") + # Backwards compatible + or instance.data.get("newAssetPublishing") + ) + if new_hierarchy: self.log.debug("Instance is creating new folders. Skipping.") return diff --git a/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/validate_frame_ranges.py b/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/validate_frame_ranges.py index 13f13b05bb..301b306089 100644 --- a/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/validate_frame_ranges.py +++ b/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/validate_frame_ranges.py @@ -33,8 +33,12 @@ class ValidateFrameRange(OptionalPyblishPluginMixin, return # editorial would fail since they might not be in database yet - new_folder_publishing = instance.data.get("newAssetPublishing") - if new_folder_publishing: + new_hierarchy = ( + instance.data.get("newHierarchyIntegration") + # Backwards compatible + or instance.data.get("newAssetPublishing") + ) + if new_hierarchy: self.log.debug("Instance is creating new folder. Skipping.") return diff --git a/server_addon/traypublisher/package.py b/server_addon/traypublisher/package.py index c9b94c2b72..85611526d0 100644 --- a/server_addon/traypublisher/package.py +++ b/server_addon/traypublisher/package.py @@ -1,6 +1,6 @@ name = "traypublisher" title = "TrayPublisher" -version = "0.2.1" +version = "0.2.2" client_dir = "ayon_traypublisher" From d73ed7a655825ab93b180a71c33257bbb483f533 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 6 Jun 2024 17:19:40 +0800 Subject: [PATCH 39/91] add review attributes to create textures --- .../ayon_substancepainter/plugins/create/create_textures.py | 5 +++++ .../plugins/publish/collect_textureset_images.py | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/server_addon/substancepainter/client/ayon_substancepainter/plugins/create/create_textures.py b/server_addon/substancepainter/client/ayon_substancepainter/plugins/create/create_textures.py index 8869cb5eb0..97d34a6557 100644 --- a/server_addon/substancepainter/client/ayon_substancepainter/plugins/create/create_textures.py +++ b/server_addon/substancepainter/client/ayon_substancepainter/plugins/create/create_textures.py @@ -46,6 +46,7 @@ class CreateTextures(Creator): creator_attributes = instance_data.setdefault( "creator_attributes", dict()) for key in [ + "review", "exportPresetUrl", "exportFileFormat", "exportSize", @@ -143,6 +144,10 @@ class CreateTextures(Creator): } return [ + BoolDef("review", + label="Review", + tooltip="Mark as reviewable", + default=True), EnumDef("exportChannel", items=export_channel_enum, multiselection=True, diff --git a/server_addon/substancepainter/client/ayon_substancepainter/plugins/publish/collect_textureset_images.py b/server_addon/substancepainter/client/ayon_substancepainter/plugins/publish/collect_textureset_images.py index 6d2336cbc0..5bea3e971f 100644 --- a/server_addon/substancepainter/client/ayon_substancepainter/plugins/publish/collect_textureset_images.py +++ b/server_addon/substancepainter/client/ayon_substancepainter/plugins/publish/collect_textureset_images.py @@ -124,7 +124,6 @@ class CollectTextureSet(pyblish.api.InstancePlugin): staging_dir = os.path.dirname(first_filepath) representation["tags"] = ["review"] representation["stagingDir"] = staging_dir - # Clone the instance product_type = "image" image_instance = context.create_instance(image_product_name) @@ -136,6 +135,9 @@ class CollectTextureSet(pyblish.api.InstancePlugin): image_instance.data["productType"] = product_type image_instance.data["family"] = product_type image_instance.data["families"] = [product_type, "textures"] + if instance.data["creator_attributes"].get("review"): + image_instance.data["families"].append("review") + image_instance.data["representations"] = [representation] # Group the textures together in the loader From cbc0516475a06bc930e725cef6a7147bc160dd7d Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 6 Jun 2024 11:44:54 +0200 Subject: [PATCH 40/91] AY-5539 - refactor argument name --- client/ayon_core/tools/publisher/control.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index f2a440d701..510885ddad 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -1898,16 +1898,16 @@ class PublisherController(BasePublisherController): re.compile("|".join(allowed_creator_labels))) return allowed_creator_labels - def _is_label_allowed(self, label, allowed_label_regexes): + def _is_label_allowed(self, label, allowed_labels_regex): """Implement regex support for allowed labels. Args: label (str): Label of creator - shown in Publisher - allowed_label_regexes (str): compiled regular expression + allowed_labels_regex (re.Pattern): compiled regular expression """ - if not allowed_label_regexes: + if not allowed_labels_regex: return True - return bool(allowed_label_regexes.match(label)) + return bool(allowed_labels_regex.match(label)) def _reset_instances(self): """Reset create instances.""" From 909d6e74e782d755d1d0d9685296aa9c0d852d82 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 6 Jun 2024 11:49:04 +0200 Subject: [PATCH 41/91] AY-5539 - refactor name of method --- client/ayon_core/tools/publisher/control.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index 510885ddad..4e2cfd8783 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -1838,11 +1838,11 @@ class PublisherController(BasePublisherController): def _collect_creator_items(self): # TODO add crashed initialization of create plugins to report output = {} - allowed_creator_labels = self._get_allowed_creator_labels() + allowed_creator_pattern = self._get_allowed_creators_pattern() for identifier, creator in self._create_context.creators.items(): try: if (not self._is_label_allowed( - creator.label, allowed_creator_labels)): + creator.label, allowed_creator_pattern)): self.log.debug(f"{creator.label} not allowed for context") continue output[identifier] = CreatorItem.from_creator(creator) @@ -1855,14 +1855,14 @@ class PublisherController(BasePublisherController): return output - def _get_allowed_creator_labels(self): - """Provide configured creator labels in this context + def _get_allowed_creators_pattern(self): + """Provide regex pattern for configured creator labels in this context If no profile matches current context, it shows all creators. Support usage of regular expressions for configured values. Returns: - (str): None or regex compiled patterns into single one - ('Render|Image.*') + (re.Pattern)[optional]: None or regex compiled patterns + into single one ('Render|Image.*') """ task_type = self._create_context.get_current_task_type() @@ -1886,7 +1886,7 @@ class PublisherController(BasePublisherController): logger=self.log ) - allowed_creator_labels = None + allowed_creator_pattern = None if profile: allowed_creator_labels = { label @@ -1894,9 +1894,9 @@ class PublisherController(BasePublisherController): if label } self.log.debug(f"Only allowed `{allowed_creator_labels}` creators") - allowed_creator_labels = ( + allowed_creator_pattern = ( re.compile("|".join(allowed_creator_labels))) - return allowed_creator_labels + return allowed_creator_pattern def _is_label_allowed(self, label, allowed_labels_regex): """Implement regex support for allowed labels. From 73b20d80f1f05310f0de487361f37562c2039ea8 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 6 Jun 2024 20:34:15 +0800 Subject: [PATCH 42/91] make sure directory used during switching asset when users switch from mov to image sequences --- .../client/ayon_aftereffects/plugins/load/load_file.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server_addon/aftereffects/client/ayon_aftereffects/plugins/load/load_file.py b/server_addon/aftereffects/client/ayon_aftereffects/plugins/load/load_file.py index 05749885c9..fcbd0fc0a5 100644 --- a/server_addon/aftereffects/client/ayon_aftereffects/plugins/load/load_file.py +++ b/server_addon/aftereffects/client/ayon_aftereffects/plugins/load/load_file.py @@ -1,5 +1,5 @@ import re - +import os from ayon_core.pipeline import get_representation_path from ayon_aftereffects import api from ayon_aftereffects.api.lib import get_unique_layer_name @@ -91,6 +91,9 @@ class FileLoader(api.AfterEffectsLoader): else: # switching version - keep same name layer_name = container["namespace"] path = get_representation_path(repre_entity) + + if len(repre_entity["files"]) > 1: + path = os.path.dirname(path) # with aftereffects.maintained_selection(): # TODO stub.replace_item(layer.id, path, stub.LOADED_ICON + layer_name) stub.imprint( From e335d0f3c8bb271fe0428971ab35f90a3c2cfd80 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 16:14:18 +0200 Subject: [PATCH 43/91] use direct ayon_weblisher import --- .../client/ayon_photoshop/plugins/publish/collect_batch_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server_addon/photoshop/client/ayon_photoshop/plugins/publish/collect_batch_data.py b/server_addon/photoshop/client/ayon_photoshop/plugins/publish/collect_batch_data.py index c43a957576..527a7d516a 100644 --- a/server_addon/photoshop/client/ayon_photoshop/plugins/publish/collect_batch_data.py +++ b/server_addon/photoshop/client/ayon_photoshop/plugins/publish/collect_batch_data.py @@ -17,7 +17,7 @@ import os import pyblish.api -from openpype_modules.webpublisher.lib import ( +from ayon_webpublisher.lib import ( get_batch_context_info, parse_json ) From 6fad829a0b54e3bcdd93666d2a19499306227715 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 16:14:28 +0200 Subject: [PATCH 44/91] fix apply of settings in royal render --- .../plugins/publish/collect_sequences_from_job.py | 1 + 1 file changed, 1 insertion(+) diff --git a/server_addon/royalrender/client/ayon_royalrender/plugins/publish/collect_sequences_from_job.py b/server_addon/royalrender/client/ayon_royalrender/plugins/publish/collect_sequences_from_job.py index 7f7b89590c..5e0ea0e258 100644 --- a/server_addon/royalrender/client/ayon_royalrender/plugins/publish/collect_sequences_from_job.py +++ b/server_addon/royalrender/client/ayon_royalrender/plugins/publish/collect_sequences_from_job.py @@ -76,6 +76,7 @@ class CollectSequencesFromJob(pyblish.api.ContextPlugin): order = pyblish.api.CollectorOrder targets = ["rr_control"] label = "Collect Rendered Frames" + settings_category = "royalrender" review = True def process(self, context): From 4cbbe322b51530c6c73131ddb7df09013c577ce0 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 17:34:46 +0200 Subject: [PATCH 45/91] mark 'newAssetPublishing' as deprecated since 24/06/06 --- .../plugins/publish/collect_anatomy_instance_data.py | 6 +++--- client/ayon_core/plugins/publish/validate_asset_docs.py | 2 +- .../plugins/publish/collect_timeline_instances.py | 2 +- .../ayon_hiero/plugins/publish/precollect_instances.py | 2 +- .../ayon_resolve/plugins/publish/precollect_instances.py | 2 +- .../ayon_traypublisher/plugins/create/create_editorial.py | 2 +- .../plugins/publish/collect_sequence_frame_data.py | 2 +- .../plugins/publish/validate_frame_ranges.py | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/client/ayon_core/plugins/publish/collect_anatomy_instance_data.py b/client/ayon_core/plugins/publish/collect_anatomy_instance_data.py index 3086c04000..0c15ec0b57 100644 --- a/client/ayon_core/plugins/publish/collect_anatomy_instance_data.py +++ b/client/ayon_core/plugins/publish/collect_anatomy_instance_data.py @@ -393,7 +393,7 @@ class CollectAnatomyInstanceData(pyblish.api.ContextPlugin): if ( instance.data.get("newHierarchyIntegration") - # Backwards compatible + # Backwards compatible (Deprecated since 24/06/06) or instance.data.get("newAssetPublishing") ): hierarchy = instance.data["hierarchy"] @@ -438,7 +438,7 @@ class CollectAnatomyInstanceData(pyblish.api.ContextPlugin): # - if we're in editorial, make sure the task type is filled new_hierarchy = ( instance.data.get("newHierarchyIntegration") - # Backwards compatible + # Backwards compatible (Deprecated since 24/06/06) or instance.data.get("newAssetPublishing") ) if not new_hierarchy or task_data["type"]: @@ -448,7 +448,7 @@ class CollectAnatomyInstanceData(pyblish.api.ContextPlugin): # New hierarchy is not created, so we can only skip rest of the logic new_hierarchy = ( instance.data.get("newHierarchyIntegration") - # Backwards compatible + # Backwards compatible (Deprecated since 24/06/06) or instance.data.get("newAssetPublishing") ) if not new_hierarchy: diff --git a/client/ayon_core/plugins/publish/validate_asset_docs.py b/client/ayon_core/plugins/publish/validate_asset_docs.py index 361f288545..b80b81b366 100644 --- a/client/ayon_core/plugins/publish/validate_asset_docs.py +++ b/client/ayon_core/plugins/publish/validate_asset_docs.py @@ -26,7 +26,7 @@ class ValidateFolderEntities(pyblish.api.InstancePlugin): elif ( instance.data.get("newHierarchyIntegration") - # Backwards compatible + # Backwards compatible (Deprecated since 24/06/06) or instance.data.get("newAssetPublishing") ): # skip if it is editorial diff --git a/server_addon/flame/client/ayon_flame/plugins/publish/collect_timeline_instances.py b/server_addon/flame/client/ayon_flame/plugins/publish/collect_timeline_instances.py index f38a0903a0..7680483db1 100644 --- a/server_addon/flame/client/ayon_flame/plugins/publish/collect_timeline_instances.py +++ b/server_addon/flame/client/ayon_flame/plugins/publish/collect_timeline_instances.py @@ -153,7 +153,7 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): for task in self.add_tasks}, "representations": [], "newHierarchyIntegration": True, - # Backwards compatible + # Backwards compatible (Deprecated since 24/06/06) "newAssetPublishing": True, }) self.log.debug("__ inst_data: {}".format(pformat(inst_data))) diff --git a/server_addon/hiero/client/ayon_hiero/plugins/publish/precollect_instances.py b/server_addon/hiero/client/ayon_hiero/plugins/publish/precollect_instances.py index be5312b325..4bc749d77c 100644 --- a/server_addon/hiero/client/ayon_hiero/plugins/publish/precollect_instances.py +++ b/server_addon/hiero/client/ayon_hiero/plugins/publish/precollect_instances.py @@ -141,7 +141,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin): # add all additional tags "tags": phiero.get_track_item_tags(track_item), "newHierarchyIntegration": True, - # Backwards compatible + # Backwards compatible (Deprecated since 24/06/06) "newAssetPublishing": True, }) diff --git a/server_addon/resolve/client/ayon_resolve/plugins/publish/precollect_instances.py b/server_addon/resolve/client/ayon_resolve/plugins/publish/precollect_instances.py index af9a63d796..e2b6e7ba37 100644 --- a/server_addon/resolve/client/ayon_resolve/plugins/publish/precollect_instances.py +++ b/server_addon/resolve/client/ayon_resolve/plugins/publish/precollect_instances.py @@ -102,7 +102,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin): "handleStart": handle_start, "handleEnd": handle_end, "newHierarchyIntegration": True, - # Backwards compatible + # Backwards compatible (Deprecated since 24/06/06) "newAssetPublishing": True, "families": ["clip"], "productType": product_type, diff --git a/server_addon/traypublisher/client/ayon_traypublisher/plugins/create/create_editorial.py b/server_addon/traypublisher/client/ayon_traypublisher/plugins/create/create_editorial.py index 0e4512d052..b013ed6864 100644 --- a/server_addon/traypublisher/client/ayon_traypublisher/plugins/create/create_editorial.py +++ b/server_addon/traypublisher/client/ayon_traypublisher/plugins/create/create_editorial.py @@ -677,7 +677,7 @@ or updating already created. Publishing will create OTIO file. "variant": variant_name, "task": None, "newHierarchyIntegration": True, - # Backwards compatible + # Backwards compatible (Deprecated since 24/06/06) "newAssetPublishing": True, "trackStartFrame": track_start_frame, "timelineOffset": timeline_offset, diff --git a/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/collect_sequence_frame_data.py b/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/collect_sequence_frame_data.py index b76d81e431..c2894e15ad 100644 --- a/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/collect_sequence_frame_data.py +++ b/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/collect_sequence_frame_data.py @@ -30,7 +30,7 @@ class CollectSequenceFrameData( # editorial would fail since they might not be in database yet new_hierarchy = ( instance.data.get("newHierarchyIntegration") - # Backwards compatible + # Backwards compatible (Deprecated since 24/06/06) or instance.data.get("newAssetPublishing") ) if new_hierarchy: diff --git a/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/validate_frame_ranges.py b/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/validate_frame_ranges.py index 301b306089..42127f4a5f 100644 --- a/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/validate_frame_ranges.py +++ b/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/validate_frame_ranges.py @@ -35,7 +35,7 @@ class ValidateFrameRange(OptionalPyblishPluginMixin, # editorial would fail since they might not be in database yet new_hierarchy = ( instance.data.get("newHierarchyIntegration") - # Backwards compatible + # Backwards compatible (Deprecated since 24/06/06) or instance.data.get("newAssetPublishing") ) if new_hierarchy: From b7686fe046b3c802d890a4b6a2e4487e4031235b Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 17:37:40 +0200 Subject: [PATCH 46/91] moved unreal integration next to server codebase --- .../unreal => server_addon/unreal/client/ayon_unreal}/README.md | 0 .../unreal => server_addon/unreal/client/ayon_unreal}/__init__.py | 0 .../unreal => server_addon/unreal/client/ayon_unreal}/addon.py | 0 .../unreal/client/ayon_unreal}/api/__init__.py | 0 .../unreal/client/ayon_unreal}/api/helpers.py | 0 .../unreal/client/ayon_unreal}/api/pipeline.py | 0 .../unreal/client/ayon_unreal}/api/plugin.py | 0 .../unreal/client/ayon_unreal}/api/rendering.py | 0 .../unreal/client/ayon_unreal}/api/tools_ui.py | 0 .../unreal/client/ayon_unreal}/hooks/pre_workfile_preparation.py | 0 .../unreal => server_addon/unreal/client/ayon_unreal}/lib.py | 0 .../unreal/client/ayon_unreal}/plugins/__init__.py | 0 .../unreal/client/ayon_unreal}/plugins/create/create_camera.py | 0 .../unreal/client/ayon_unreal}/plugins/create/create_layout.py | 0 .../unreal/client/ayon_unreal}/plugins/create/create_look.py | 0 .../unreal/client/ayon_unreal}/plugins/create/create_render.py | 0 .../client/ayon_unreal}/plugins/create/create_staticmeshfbx.py | 0 .../unreal/client/ayon_unreal}/plugins/create/create_uasset.py | 0 .../client/ayon_unreal}/plugins/inventory/delete_unused_assets.py | 0 .../unreal/client/ayon_unreal}/plugins/inventory/update_actors.py | 0 .../client/ayon_unreal}/plugins/load/load_alembic_animation.py | 0 .../unreal/client/ayon_unreal}/plugins/load/load_animation.py | 0 .../unreal/client/ayon_unreal}/plugins/load/load_camera.py | 0 .../client/ayon_unreal}/plugins/load/load_geometrycache_abc.py | 0 .../unreal/client/ayon_unreal}/plugins/load/load_layout.py | 0 .../client/ayon_unreal}/plugins/load/load_layout_existing.py | 0 .../client/ayon_unreal}/plugins/load/load_skeletalmesh_abc.py | 0 .../client/ayon_unreal}/plugins/load/load_skeletalmesh_fbx.py | 0 .../client/ayon_unreal}/plugins/load/load_staticmesh_abc.py | 0 .../client/ayon_unreal}/plugins/load/load_staticmesh_fbx.py | 0 .../unreal/client/ayon_unreal}/plugins/load/load_uasset.py | 0 .../unreal/client/ayon_unreal}/plugins/load/load_yeticache.py | 0 .../client/ayon_unreal}/plugins/publish/collect_current_file.py | 0 .../ayon_unreal}/plugins/publish/collect_instance_members.py | 0 .../client/ayon_unreal}/plugins/publish/collect_remove_marked.py | 0 .../ayon_unreal}/plugins/publish/collect_render_instances.py | 0 .../unreal/client/ayon_unreal}/plugins/publish/extract_camera.py | 0 .../unreal/client/ayon_unreal}/plugins/publish/extract_layout.py | 0 .../unreal/client/ayon_unreal}/plugins/publish/extract_look.py | 0 .../unreal/client/ayon_unreal}/plugins/publish/extract_uasset.py | 0 .../ayon_unreal}/plugins/publish/validate_no_dependencies.py | 0 .../ayon_unreal}/plugins/publish/validate_sequence_frames.py | 0 .../unreal/client/ayon_unreal}/ue_workers.py | 0 .../unreal/client/ayon_unreal}/ui/__init__.py | 0 .../unreal/client/ayon_unreal}/ui/splash_screen.py | 0 45 files changed, 0 insertions(+), 0 deletions(-) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/README.md (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/__init__.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/addon.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/api/__init__.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/api/helpers.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/api/pipeline.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/api/plugin.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/api/rendering.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/api/tools_ui.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/hooks/pre_workfile_preparation.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/lib.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/__init__.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/create/create_camera.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/create/create_layout.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/create/create_look.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/create/create_render.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/create/create_staticmeshfbx.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/create/create_uasset.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/inventory/delete_unused_assets.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/inventory/update_actors.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/load/load_alembic_animation.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/load/load_animation.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/load/load_camera.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/load/load_geometrycache_abc.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/load/load_layout.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/load/load_layout_existing.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/load/load_skeletalmesh_abc.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/load/load_skeletalmesh_fbx.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/load/load_staticmesh_abc.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/load/load_staticmesh_fbx.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/load/load_uasset.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/load/load_yeticache.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/publish/collect_current_file.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/publish/collect_instance_members.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/publish/collect_remove_marked.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/publish/collect_render_instances.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/publish/extract_camera.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/publish/extract_layout.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/publish/extract_look.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/publish/extract_uasset.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/publish/validate_no_dependencies.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/plugins/publish/validate_sequence_frames.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/ue_workers.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/ui/__init__.py (100%) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/ui/splash_screen.py (100%) diff --git a/client/ayon_core/hosts/unreal/README.md b/server_addon/unreal/client/ayon_unreal/README.md similarity index 100% rename from client/ayon_core/hosts/unreal/README.md rename to server_addon/unreal/client/ayon_unreal/README.md diff --git a/client/ayon_core/hosts/unreal/__init__.py b/server_addon/unreal/client/ayon_unreal/__init__.py similarity index 100% rename from client/ayon_core/hosts/unreal/__init__.py rename to server_addon/unreal/client/ayon_unreal/__init__.py diff --git a/client/ayon_core/hosts/unreal/addon.py b/server_addon/unreal/client/ayon_unreal/addon.py similarity index 100% rename from client/ayon_core/hosts/unreal/addon.py rename to server_addon/unreal/client/ayon_unreal/addon.py diff --git a/client/ayon_core/hosts/unreal/api/__init__.py b/server_addon/unreal/client/ayon_unreal/api/__init__.py similarity index 100% rename from client/ayon_core/hosts/unreal/api/__init__.py rename to server_addon/unreal/client/ayon_unreal/api/__init__.py diff --git a/client/ayon_core/hosts/unreal/api/helpers.py b/server_addon/unreal/client/ayon_unreal/api/helpers.py similarity index 100% rename from client/ayon_core/hosts/unreal/api/helpers.py rename to server_addon/unreal/client/ayon_unreal/api/helpers.py diff --git a/client/ayon_core/hosts/unreal/api/pipeline.py b/server_addon/unreal/client/ayon_unreal/api/pipeline.py similarity index 100% rename from client/ayon_core/hosts/unreal/api/pipeline.py rename to server_addon/unreal/client/ayon_unreal/api/pipeline.py diff --git a/client/ayon_core/hosts/unreal/api/plugin.py b/server_addon/unreal/client/ayon_unreal/api/plugin.py similarity index 100% rename from client/ayon_core/hosts/unreal/api/plugin.py rename to server_addon/unreal/client/ayon_unreal/api/plugin.py diff --git a/client/ayon_core/hosts/unreal/api/rendering.py b/server_addon/unreal/client/ayon_unreal/api/rendering.py similarity index 100% rename from client/ayon_core/hosts/unreal/api/rendering.py rename to server_addon/unreal/client/ayon_unreal/api/rendering.py diff --git a/client/ayon_core/hosts/unreal/api/tools_ui.py b/server_addon/unreal/client/ayon_unreal/api/tools_ui.py similarity index 100% rename from client/ayon_core/hosts/unreal/api/tools_ui.py rename to server_addon/unreal/client/ayon_unreal/api/tools_ui.py diff --git a/client/ayon_core/hosts/unreal/hooks/pre_workfile_preparation.py b/server_addon/unreal/client/ayon_unreal/hooks/pre_workfile_preparation.py similarity index 100% rename from client/ayon_core/hosts/unreal/hooks/pre_workfile_preparation.py rename to server_addon/unreal/client/ayon_unreal/hooks/pre_workfile_preparation.py diff --git a/client/ayon_core/hosts/unreal/lib.py b/server_addon/unreal/client/ayon_unreal/lib.py similarity index 100% rename from client/ayon_core/hosts/unreal/lib.py rename to server_addon/unreal/client/ayon_unreal/lib.py diff --git a/client/ayon_core/hosts/unreal/plugins/__init__.py b/server_addon/unreal/client/ayon_unreal/plugins/__init__.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/__init__.py rename to server_addon/unreal/client/ayon_unreal/plugins/__init__.py diff --git a/client/ayon_core/hosts/unreal/plugins/create/create_camera.py b/server_addon/unreal/client/ayon_unreal/plugins/create/create_camera.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/create/create_camera.py rename to server_addon/unreal/client/ayon_unreal/plugins/create/create_camera.py diff --git a/client/ayon_core/hosts/unreal/plugins/create/create_layout.py b/server_addon/unreal/client/ayon_unreal/plugins/create/create_layout.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/create/create_layout.py rename to server_addon/unreal/client/ayon_unreal/plugins/create/create_layout.py diff --git a/client/ayon_core/hosts/unreal/plugins/create/create_look.py b/server_addon/unreal/client/ayon_unreal/plugins/create/create_look.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/create/create_look.py rename to server_addon/unreal/client/ayon_unreal/plugins/create/create_look.py diff --git a/client/ayon_core/hosts/unreal/plugins/create/create_render.py b/server_addon/unreal/client/ayon_unreal/plugins/create/create_render.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/create/create_render.py rename to server_addon/unreal/client/ayon_unreal/plugins/create/create_render.py diff --git a/client/ayon_core/hosts/unreal/plugins/create/create_staticmeshfbx.py b/server_addon/unreal/client/ayon_unreal/plugins/create/create_staticmeshfbx.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/create/create_staticmeshfbx.py rename to server_addon/unreal/client/ayon_unreal/plugins/create/create_staticmeshfbx.py diff --git a/client/ayon_core/hosts/unreal/plugins/create/create_uasset.py b/server_addon/unreal/client/ayon_unreal/plugins/create/create_uasset.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/create/create_uasset.py rename to server_addon/unreal/client/ayon_unreal/plugins/create/create_uasset.py diff --git a/client/ayon_core/hosts/unreal/plugins/inventory/delete_unused_assets.py b/server_addon/unreal/client/ayon_unreal/plugins/inventory/delete_unused_assets.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/inventory/delete_unused_assets.py rename to server_addon/unreal/client/ayon_unreal/plugins/inventory/delete_unused_assets.py diff --git a/client/ayon_core/hosts/unreal/plugins/inventory/update_actors.py b/server_addon/unreal/client/ayon_unreal/plugins/inventory/update_actors.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/inventory/update_actors.py rename to server_addon/unreal/client/ayon_unreal/plugins/inventory/update_actors.py diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_alembic_animation.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_alembic_animation.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/load/load_alembic_animation.py rename to server_addon/unreal/client/ayon_unreal/plugins/load/load_alembic_animation.py diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_animation.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_animation.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/load/load_animation.py rename to server_addon/unreal/client/ayon_unreal/plugins/load/load_animation.py diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_camera.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_camera.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/load/load_camera.py rename to server_addon/unreal/client/ayon_unreal/plugins/load/load_camera.py diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_geometrycache_abc.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_geometrycache_abc.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/load/load_geometrycache_abc.py rename to server_addon/unreal/client/ayon_unreal/plugins/load/load_geometrycache_abc.py diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_layout.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_layout.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/load/load_layout.py rename to server_addon/unreal/client/ayon_unreal/plugins/load/load_layout.py diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_layout_existing.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_layout_existing.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/load/load_layout_existing.py rename to server_addon/unreal/client/ayon_unreal/plugins/load/load_layout_existing.py diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_skeletalmesh_abc.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_skeletalmesh_abc.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/load/load_skeletalmesh_abc.py rename to server_addon/unreal/client/ayon_unreal/plugins/load/load_skeletalmesh_abc.py diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_skeletalmesh_fbx.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_skeletalmesh_fbx.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/load/load_skeletalmesh_fbx.py rename to server_addon/unreal/client/ayon_unreal/plugins/load/load_skeletalmesh_fbx.py diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_staticmesh_abc.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_staticmesh_abc.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/load/load_staticmesh_abc.py rename to server_addon/unreal/client/ayon_unreal/plugins/load/load_staticmesh_abc.py diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_staticmesh_fbx.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_staticmesh_fbx.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/load/load_staticmesh_fbx.py rename to server_addon/unreal/client/ayon_unreal/plugins/load/load_staticmesh_fbx.py diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_uasset.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_uasset.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/load/load_uasset.py rename to server_addon/unreal/client/ayon_unreal/plugins/load/load_uasset.py diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_yeticache.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_yeticache.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/load/load_yeticache.py rename to server_addon/unreal/client/ayon_unreal/plugins/load/load_yeticache.py diff --git a/client/ayon_core/hosts/unreal/plugins/publish/collect_current_file.py b/server_addon/unreal/client/ayon_unreal/plugins/publish/collect_current_file.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/publish/collect_current_file.py rename to server_addon/unreal/client/ayon_unreal/plugins/publish/collect_current_file.py diff --git a/client/ayon_core/hosts/unreal/plugins/publish/collect_instance_members.py b/server_addon/unreal/client/ayon_unreal/plugins/publish/collect_instance_members.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/publish/collect_instance_members.py rename to server_addon/unreal/client/ayon_unreal/plugins/publish/collect_instance_members.py diff --git a/client/ayon_core/hosts/unreal/plugins/publish/collect_remove_marked.py b/server_addon/unreal/client/ayon_unreal/plugins/publish/collect_remove_marked.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/publish/collect_remove_marked.py rename to server_addon/unreal/client/ayon_unreal/plugins/publish/collect_remove_marked.py diff --git a/client/ayon_core/hosts/unreal/plugins/publish/collect_render_instances.py b/server_addon/unreal/client/ayon_unreal/plugins/publish/collect_render_instances.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/publish/collect_render_instances.py rename to server_addon/unreal/client/ayon_unreal/plugins/publish/collect_render_instances.py diff --git a/client/ayon_core/hosts/unreal/plugins/publish/extract_camera.py b/server_addon/unreal/client/ayon_unreal/plugins/publish/extract_camera.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/publish/extract_camera.py rename to server_addon/unreal/client/ayon_unreal/plugins/publish/extract_camera.py diff --git a/client/ayon_core/hosts/unreal/plugins/publish/extract_layout.py b/server_addon/unreal/client/ayon_unreal/plugins/publish/extract_layout.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/publish/extract_layout.py rename to server_addon/unreal/client/ayon_unreal/plugins/publish/extract_layout.py diff --git a/client/ayon_core/hosts/unreal/plugins/publish/extract_look.py b/server_addon/unreal/client/ayon_unreal/plugins/publish/extract_look.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/publish/extract_look.py rename to server_addon/unreal/client/ayon_unreal/plugins/publish/extract_look.py diff --git a/client/ayon_core/hosts/unreal/plugins/publish/extract_uasset.py b/server_addon/unreal/client/ayon_unreal/plugins/publish/extract_uasset.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/publish/extract_uasset.py rename to server_addon/unreal/client/ayon_unreal/plugins/publish/extract_uasset.py diff --git a/client/ayon_core/hosts/unreal/plugins/publish/validate_no_dependencies.py b/server_addon/unreal/client/ayon_unreal/plugins/publish/validate_no_dependencies.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/publish/validate_no_dependencies.py rename to server_addon/unreal/client/ayon_unreal/plugins/publish/validate_no_dependencies.py diff --git a/client/ayon_core/hosts/unreal/plugins/publish/validate_sequence_frames.py b/server_addon/unreal/client/ayon_unreal/plugins/publish/validate_sequence_frames.py similarity index 100% rename from client/ayon_core/hosts/unreal/plugins/publish/validate_sequence_frames.py rename to server_addon/unreal/client/ayon_unreal/plugins/publish/validate_sequence_frames.py diff --git a/client/ayon_core/hosts/unreal/ue_workers.py b/server_addon/unreal/client/ayon_unreal/ue_workers.py similarity index 100% rename from client/ayon_core/hosts/unreal/ue_workers.py rename to server_addon/unreal/client/ayon_unreal/ue_workers.py diff --git a/client/ayon_core/hosts/unreal/ui/__init__.py b/server_addon/unreal/client/ayon_unreal/ui/__init__.py similarity index 100% rename from client/ayon_core/hosts/unreal/ui/__init__.py rename to server_addon/unreal/client/ayon_unreal/ui/__init__.py diff --git a/client/ayon_core/hosts/unreal/ui/splash_screen.py b/server_addon/unreal/client/ayon_unreal/ui/splash_screen.py similarity index 100% rename from client/ayon_core/hosts/unreal/ui/splash_screen.py rename to server_addon/unreal/client/ayon_unreal/ui/splash_screen.py From b92b7f5231eb7f0f92bec84a88f63799e90fc351 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 17:39:25 +0200 Subject: [PATCH 47/91] moved integration to client codebase --- .gitmodules | 2 +- .../unreal/client/ayon_unreal}/integration | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename {client/ayon_core/hosts/unreal => server_addon/unreal/client/ayon_unreal}/integration (100%) diff --git a/.gitmodules b/.gitmodules index 95c8647d45..c70c2097d9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "client/ayon_core/hosts/unreal/integration"] - path = client/ayon_core/hosts/unreal/integration + path = server_addon/unreal/client/ayon_unreal/integration url = https://github.com/ynput/ayon-unreal-plugin.git diff --git a/client/ayon_core/hosts/unreal/integration b/server_addon/unreal/client/ayon_unreal/integration similarity index 100% rename from client/ayon_core/hosts/unreal/integration rename to server_addon/unreal/client/ayon_unreal/integration From 196d307a577d51db5c31ec48c9ed6e8d550d9e09 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 17:43:41 +0200 Subject: [PATCH 48/91] bump version and add version to client addon --- server_addon/unreal/client/ayon_unreal/__init__.py | 3 +++ server_addon/unreal/client/ayon_unreal/addon.py | 3 +++ server_addon/unreal/client/ayon_unreal/version.py | 3 +++ server_addon/unreal/package.py | 9 ++++++++- 4 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 server_addon/unreal/client/ayon_unreal/version.py diff --git a/server_addon/unreal/client/ayon_unreal/__init__.py b/server_addon/unreal/client/ayon_unreal/__init__.py index 42dd8f0ac4..7dd6875154 100644 --- a/server_addon/unreal/client/ayon_unreal/__init__.py +++ b/server_addon/unreal/client/ayon_unreal/__init__.py @@ -1,6 +1,9 @@ +from .version import __version__ from .addon import UnrealAddon __all__ = ( + "__version__", + "UnrealAddon", ) diff --git a/server_addon/unreal/client/ayon_unreal/addon.py b/server_addon/unreal/client/ayon_unreal/addon.py index c65490bd8c..5cfbc3c019 100644 --- a/server_addon/unreal/client/ayon_unreal/addon.py +++ b/server_addon/unreal/client/ayon_unreal/addon.py @@ -2,11 +2,14 @@ import os import re from ayon_core.addon import AYONAddon, IHostAddon +from .version import __version__ + UNREAL_ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) class UnrealAddon(AYONAddon, IHostAddon): name = "unreal" + version = __version__ host_name = "unreal" def get_global_environments(self): diff --git a/server_addon/unreal/client/ayon_unreal/version.py b/server_addon/unreal/client/ayon_unreal/version.py new file mode 100644 index 0000000000..1ddc580946 --- /dev/null +++ b/server_addon/unreal/client/ayon_unreal/version.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +"""Package declaring AYON addon 'unreal' version.""" +__version__ = "0.2.0" diff --git a/server_addon/unreal/package.py b/server_addon/unreal/package.py index cab89ca873..f1c56b15f6 100644 --- a/server_addon/unreal/package.py +++ b/server_addon/unreal/package.py @@ -1,3 +1,10 @@ name = "unreal" title = "Unreal" -version = "0.1.0" +version = "0.2.0" + +client_dir = "ayon_unreal" + +ayon_required_addons = { + "core": ">0.3.2", +} +ayon_compatible_addons = {} From 8ca69f512ba01f286f7285a468e213d900fb2f72 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 17:50:01 +0200 Subject: [PATCH 49/91] define 'UNREAL_ADDON_ROOT' and use it --- server_addon/unreal/client/ayon_unreal/__init__.py | 3 ++- server_addon/unreal/client/ayon_unreal/addon.py | 10 +++++----- server_addon/unreal/client/ayon_unreal/api/pipeline.py | 5 ++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/server_addon/unreal/client/ayon_unreal/__init__.py b/server_addon/unreal/client/ayon_unreal/__init__.py index 7dd6875154..6be5ae13c9 100644 --- a/server_addon/unreal/client/ayon_unreal/__init__.py +++ b/server_addon/unreal/client/ayon_unreal/__init__.py @@ -1,9 +1,10 @@ from .version import __version__ -from .addon import UnrealAddon +from .addon import UNREAL_ADDON_ROOT, UnrealAddon __all__ = ( "__version__", + "UNREAL_ADDON_ROOT", "UnrealAddon", ) diff --git a/server_addon/unreal/client/ayon_unreal/addon.py b/server_addon/unreal/client/ayon_unreal/addon.py index 5cfbc3c019..d9e1bfaca9 100644 --- a/server_addon/unreal/client/ayon_unreal/addon.py +++ b/server_addon/unreal/client/ayon_unreal/addon.py @@ -4,7 +4,7 @@ from ayon_core.addon import AYONAddon, IHostAddon from .version import __version__ -UNREAL_ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) +UNREAL_ADDON_ROOT = os.path.dirname(os.path.abspath(__file__)) class UnrealAddon(AYONAddon, IHostAddon): @@ -14,7 +14,7 @@ class UnrealAddon(AYONAddon, IHostAddon): def get_global_environments(self): return { - "AYON_UNREAL_ROOT": UNREAL_ROOT_DIR, + "AYON_UNREAL_ROOT": UNREAL_ADDON_ROOT, } def add_implementation_envs(self, env, app): @@ -43,11 +43,11 @@ class UnrealAddon(AYONAddon, IHostAddon): ue_version = app.name.replace("-", ".") unreal_plugin_path = os.path.join( - UNREAL_ROOT_DIR, "integration", "UE_{}".format(ue_version), "Ayon" + UNREAL_ADDON_ROOT, "integration", "UE_{}".format(ue_version), "Ayon" ) if not Path(unreal_plugin_path).exists(): compatible_versions = get_compatible_integration( - ue_version, Path(UNREAL_ROOT_DIR) / "integration" + ue_version, Path(UNREAL_ADDON_ROOT) / "integration" ) if compatible_versions: unreal_plugin_path = compatible_versions[-1] / "Ayon" @@ -70,7 +70,7 @@ class UnrealAddon(AYONAddon, IHostAddon): if app.host_name != self.host_name: return [] return [ - os.path.join(UNREAL_ROOT_DIR, "hooks") + os.path.join(UNREAL_ADDON_ROOT, "hooks") ] def get_workfile_extensions(self): diff --git a/server_addon/unreal/client/ayon_unreal/api/pipeline.py b/server_addon/unreal/client/ayon_unreal/api/pipeline.py index a60564d5b0..9f8502669d 100644 --- a/server_addon/unreal/client/ayon_unreal/api/pipeline.py +++ b/server_addon/unreal/client/ayon_unreal/api/pipeline.py @@ -21,8 +21,8 @@ from ayon_core.pipeline import ( get_current_project_name, ) from ayon_core.tools.utils import host_tools -import ayon_core.hosts.unreal from ayon_core.host import HostBase, ILoadHost, IPublishHost +from ayon_unreal import UNREAL_ADDON_ROOT import unreal # noqa @@ -36,8 +36,7 @@ UNREAL_VERSION = semver.VersionInfo( *os.getenv("AYON_UNREAL_VERSION").split(".") ) -HOST_DIR = os.path.dirname(os.path.abspath(ayon_core.hosts.unreal.__file__)) -PLUGINS_DIR = os.path.join(HOST_DIR, "plugins") +PLUGINS_DIR = os.path.join(UNREAL_ADDON_ROOT, "plugins") PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish") LOAD_PATH = os.path.join(PLUGINS_DIR, "load") CREATE_PATH = os.path.join(PLUGINS_DIR, "create") From 54e57facca9206744cf43511fe9ae67ef47b64c5 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 17:50:41 +0200 Subject: [PATCH 50/91] fix imports --- server_addon/unreal/client/ayon_unreal/api/pipeline.py | 4 ++-- server_addon/unreal/client/ayon_unreal/api/rendering.py | 2 +- server_addon/unreal/client/ayon_unreal/api/tools_ui.py | 2 +- .../client/ayon_unreal/hooks/pre_workfile_preparation.py | 6 +++--- .../client/ayon_unreal/plugins/create/create_camera.py | 4 ++-- .../client/ayon_unreal/plugins/create/create_layout.py | 2 +- .../unreal/client/ayon_unreal/plugins/create/create_look.py | 4 ++-- .../client/ayon_unreal/plugins/create/create_render.py | 4 ++-- .../ayon_unreal/plugins/create/create_staticmeshfbx.py | 2 +- .../client/ayon_unreal/plugins/create/create_uasset.py | 2 +- .../ayon_unreal/plugins/inventory/delete_unused_assets.py | 4 ++-- .../client/ayon_unreal/plugins/inventory/update_actors.py | 2 +- .../ayon_unreal/plugins/load/load_alembic_animation.py | 4 ++-- .../client/ayon_unreal/plugins/load/load_animation.py | 4 ++-- .../unreal/client/ayon_unreal/plugins/load/load_camera.py | 4 ++-- .../ayon_unreal/plugins/load/load_geometrycache_abc.py | 4 ++-- .../unreal/client/ayon_unreal/plugins/load/load_layout.py | 4 ++-- .../client/ayon_unreal/plugins/load/load_layout_existing.py | 4 ++-- .../ayon_unreal/plugins/load/load_skeletalmesh_abc.py | 4 ++-- .../ayon_unreal/plugins/load/load_skeletalmesh_fbx.py | 4 ++-- .../client/ayon_unreal/plugins/load/load_staticmesh_abc.py | 4 ++-- .../client/ayon_unreal/plugins/load/load_staticmesh_fbx.py | 4 ++-- .../unreal/client/ayon_unreal/plugins/load/load_uasset.py | 4 ++-- .../client/ayon_unreal/plugins/load/load_yeticache.py | 4 ++-- .../ayon_unreal/plugins/publish/collect_render_instances.py | 2 +- .../client/ayon_unreal/plugins/publish/extract_camera.py | 2 +- server_addon/unreal/client/ayon_unreal/ue_workers.py | 2 +- 27 files changed, 46 insertions(+), 46 deletions(-) diff --git a/server_addon/unreal/client/ayon_unreal/api/pipeline.py b/server_addon/unreal/client/ayon_unreal/api/pipeline.py index 9f8502669d..f04d8e10a4 100644 --- a/server_addon/unreal/client/ayon_unreal/api/pipeline.py +++ b/server_addon/unreal/client/ayon_unreal/api/pipeline.py @@ -323,7 +323,7 @@ def show_tools_popup(): Popup will disappear on click or losing focus. """ - from ayon_core.hosts.unreal.api import tools_ui + from ayon_unreal.api import tools_ui tools_ui.show_tools_popup() @@ -333,7 +333,7 @@ def show_tools_dialog(): Dialog will stay visible. """ - from ayon_core.hosts.unreal.api import tools_ui + from ayon_unreal.api import tools_ui tools_ui.show_tools_dialog() diff --git a/server_addon/unreal/client/ayon_unreal/api/rendering.py b/server_addon/unreal/client/ayon_unreal/api/rendering.py index 395513aefa..6ae9fee26d 100644 --- a/server_addon/unreal/client/ayon_unreal/api/rendering.py +++ b/server_addon/unreal/client/ayon_unreal/api/rendering.py @@ -4,8 +4,8 @@ import unreal from ayon_core.settings import get_project_settings from ayon_core.pipeline import Anatomy -from ayon_core.hosts.unreal.api import pipeline from ayon_core.tools.utils import show_message_dialog +from ayon_unreal.api import pipeline queue = None diff --git a/server_addon/unreal/client/ayon_unreal/api/tools_ui.py b/server_addon/unreal/client/ayon_unreal/api/tools_ui.py index efae5bb702..f464d39b92 100644 --- a/server_addon/unreal/client/ayon_unreal/api/tools_ui.py +++ b/server_addon/unreal/client/ayon_unreal/api/tools_ui.py @@ -7,7 +7,7 @@ from ayon_core import ( ) from ayon_core.tools.utils import host_tools from ayon_core.tools.utils.lib import qt_app_context -from ayon_core.hosts.unreal.api import rendering +from ayon_unreal.api import rendering class ToolsBtnsWidget(QtWidgets.QWidget): diff --git a/server_addon/unreal/client/ayon_unreal/hooks/pre_workfile_preparation.py b/server_addon/unreal/client/ayon_unreal/hooks/pre_workfile_preparation.py index e38591f65d..e70b3131b3 100644 --- a/server_addon/unreal/client/ayon_unreal/hooks/pre_workfile_preparation.py +++ b/server_addon/unreal/client/ayon_unreal/hooks/pre_workfile_preparation.py @@ -15,12 +15,12 @@ from ayon_applications import ( LaunchTypes, ) from ayon_core.pipeline.workfile import get_workfile_template_key -import ayon_core.hosts.unreal.lib as unreal_lib -from ayon_core.hosts.unreal.ue_workers import ( +import ayon_unreal.lib as unreal_lib +from ayon_unreal.ue_workers import ( UEProjectGenerationWorker, UEPluginInstallWorker ) -from ayon_core.hosts.unreal.ui import SplashScreen +from ayon_unreal.ui import SplashScreen class UnrealPrelaunchHook(PreLaunchHook): diff --git a/server_addon/unreal/client/ayon_unreal/plugins/create/create_camera.py b/server_addon/unreal/client/ayon_unreal/plugins/create/create_camera.py index 3ffb9dd70b..d9a66215db 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/create/create_camera.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/create/create_camera.py @@ -2,8 +2,8 @@ import unreal from ayon_core.pipeline import CreatorError -from ayon_core.hosts.unreal.api.pipeline import UNREAL_VERSION -from ayon_core.hosts.unreal.api.plugin import ( +from ayon_unreal.api.pipeline import UNREAL_VERSION +from ayon_unreal.api.plugin import ( UnrealAssetCreator, ) diff --git a/server_addon/unreal/client/ayon_unreal/plugins/create/create_layout.py b/server_addon/unreal/client/ayon_unreal/plugins/create/create_layout.py index 9bcddfe507..fa4fc072ae 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/create/create_layout.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/create/create_layout.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from ayon_core.hosts.unreal.api.plugin import ( +from ayon_unreal.api.plugin import ( UnrealActorCreator, ) diff --git a/server_addon/unreal/client/ayon_unreal/plugins/create/create_look.py b/server_addon/unreal/client/ayon_unreal/plugins/create/create_look.py index edc6d45f2f..9017997864 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/create/create_look.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/create/create_look.py @@ -2,10 +2,10 @@ import unreal from ayon_core.pipeline import CreatorError -from ayon_core.hosts.unreal.api.pipeline import ( +from ayon_unreal.api.pipeline import ( create_folder ) -from ayon_core.hosts.unreal.api.plugin import ( +from ayon_unreal.api.plugin import ( UnrealAssetCreator ) from ayon_core.lib import UILabelDef diff --git a/server_addon/unreal/client/ayon_unreal/plugins/create/create_render.py b/server_addon/unreal/client/ayon_unreal/plugins/create/create_render.py index 5a96d9809c..e1999e5385 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/create/create_render.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/create/create_render.py @@ -3,12 +3,12 @@ from pathlib import Path import unreal -from ayon_core.hosts.unreal.api.pipeline import ( +from ayon_unreal.api.pipeline import ( UNREAL_VERSION, create_folder, get_subsequences, ) -from ayon_core.hosts.unreal.api.plugin import ( +from ayon_unreal.api.plugin import ( UnrealAssetCreator ) from ayon_core.lib import ( diff --git a/server_addon/unreal/client/ayon_unreal/plugins/create/create_staticmeshfbx.py b/server_addon/unreal/client/ayon_unreal/plugins/create/create_staticmeshfbx.py index 603b852873..79cc249083 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/create/create_staticmeshfbx.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/create/create_staticmeshfbx.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from ayon_core.hosts.unreal.api.plugin import ( +from ayon_unreal.api.plugin import ( UnrealAssetCreator, ) diff --git a/server_addon/unreal/client/ayon_unreal/plugins/create/create_uasset.py b/server_addon/unreal/client/ayon_unreal/plugins/create/create_uasset.py index 1cd532c63d..f053503c45 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/create/create_uasset.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/create/create_uasset.py @@ -4,7 +4,7 @@ from pathlib import Path import unreal from ayon_core.pipeline import CreatorError -from ayon_core.hosts.unreal.api.plugin import ( +from ayon_unreal.api.plugin import ( UnrealAssetCreator, ) diff --git a/server_addon/unreal/client/ayon_unreal/plugins/inventory/delete_unused_assets.py b/server_addon/unreal/client/ayon_unreal/plugins/inventory/delete_unused_assets.py index 1f63a1697a..1892f8ab14 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/inventory/delete_unused_assets.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/inventory/delete_unused_assets.py @@ -1,7 +1,7 @@ import unreal -from ayon_core.hosts.unreal.api.tools_ui import qt_app_context -from ayon_core.hosts.unreal.api.pipeline import delete_asset_if_unused +from ayon_unreal.api.tools_ui import qt_app_context +from ayon_unreal.api.pipeline import delete_asset_if_unused from ayon_core.pipeline import InventoryAction diff --git a/server_addon/unreal/client/ayon_unreal/plugins/inventory/update_actors.py b/server_addon/unreal/client/ayon_unreal/plugins/inventory/update_actors.py index 96965d68e6..3ca861f0c7 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/inventory/update_actors.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/inventory/update_actors.py @@ -1,6 +1,6 @@ import unreal -from ayon_core.hosts.unreal.api.pipeline import ( +from ayon_unreal.api.pipeline import ( ls, replace_static_mesh_actors, replace_skeletal_mesh_actors, diff --git a/server_addon/unreal/client/ayon_unreal/plugins/load/load_alembic_animation.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_alembic_animation.py index a12f4f41b4..109daf86c4 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/load/load_alembic_animation.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/load/load_alembic_animation.py @@ -6,8 +6,8 @@ from ayon_core.pipeline import ( get_representation_path, AYON_CONTAINER_ID ) -from ayon_core.hosts.unreal.api import plugin -from ayon_core.hosts.unreal.api import pipeline as unreal_pipeline +from ayon_unreal.api import plugin +from ayon_unreal.api import pipeline as unreal_pipeline import unreal # noqa diff --git a/server_addon/unreal/client/ayon_unreal/plugins/load/load_animation.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_animation.py index f6a612ce53..1cb5c58ea4 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/load/load_animation.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/load/load_animation.py @@ -13,8 +13,8 @@ from ayon_core.pipeline import ( get_representation_path, AYON_CONTAINER_ID ) -from ayon_core.hosts.unreal.api import plugin -from ayon_core.hosts.unreal.api import pipeline as unreal_pipeline +from ayon_unreal.api import plugin +from ayon_unreal.api import pipeline as unreal_pipeline class AnimationFBXLoader(plugin.Loader): diff --git a/server_addon/unreal/client/ayon_unreal/plugins/load/load_camera.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_camera.py index 681c83c6a1..10172094b6 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/load/load_camera.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/load/load_camera.py @@ -16,8 +16,8 @@ from ayon_core.pipeline import ( get_current_project_name, get_representation_path, ) -from ayon_core.hosts.unreal.api import plugin -from ayon_core.hosts.unreal.api.pipeline import ( +from ayon_unreal.api import plugin +from ayon_unreal.api.pipeline import ( generate_sequence, set_sequence_hierarchy, create_container, diff --git a/server_addon/unreal/client/ayon_unreal/plugins/load/load_geometrycache_abc.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_geometrycache_abc.py index ae7d41192a..1262ade9af 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/load/load_geometrycache_abc.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/load/load_geometrycache_abc.py @@ -6,8 +6,8 @@ from ayon_core.pipeline import ( get_representation_path, AYON_CONTAINER_ID ) -from ayon_core.hosts.unreal.api import plugin -from ayon_core.hosts.unreal.api.pipeline import ( +from ayon_unreal.api import plugin +from ayon_unreal.api.pipeline import ( AYON_ASSET_DIR, create_container, imprint, diff --git a/server_addon/unreal/client/ayon_unreal/plugins/load/load_layout.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_layout.py index 49d95c6459..25883a1ffb 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/load/load_layout.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/load/load_layout.py @@ -27,8 +27,8 @@ from ayon_core.pipeline import ( ) from ayon_core.pipeline.context_tools import get_current_folder_entity from ayon_core.settings import get_current_project_settings -from ayon_core.hosts.unreal.api import plugin -from ayon_core.hosts.unreal.api.pipeline import ( +from ayon_unreal.api import plugin +from ayon_unreal.api.pipeline import ( generate_sequence, set_sequence_hierarchy, create_container, diff --git a/server_addon/unreal/client/ayon_unreal/plugins/load/load_layout_existing.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_layout_existing.py index f9d438367b..df5f154d7c 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/load/load_layout_existing.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/load/load_layout_existing.py @@ -12,8 +12,8 @@ from ayon_core.pipeline import ( get_representation_path, AYON_CONTAINER_ID, ) -from ayon_core.hosts.unreal.api import plugin -from ayon_core.hosts.unreal.api import pipeline as upipeline +from ayon_unreal.api import plugin +from ayon_unreal.api import pipeline as upipeline class ExistingLayoutLoader(plugin.Loader): diff --git a/server_addon/unreal/client/ayon_unreal/plugins/load/load_skeletalmesh_abc.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_skeletalmesh_abc.py index dfc5d58708..5db3e364f1 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/load/load_skeletalmesh_abc.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/load/load_skeletalmesh_abc.py @@ -6,8 +6,8 @@ from ayon_core.pipeline import ( get_representation_path, AYON_CONTAINER_ID ) -from ayon_core.hosts.unreal.api import plugin -from ayon_core.hosts.unreal.api.pipeline import ( +from ayon_unreal.api import plugin +from ayon_unreal.api.pipeline import ( AYON_ASSET_DIR, create_container, imprint, diff --git a/server_addon/unreal/client/ayon_unreal/plugins/load/load_skeletalmesh_fbx.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_skeletalmesh_fbx.py index 513404ab98..6f1ebc1d51 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/load/load_skeletalmesh_fbx.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/load/load_skeletalmesh_fbx.py @@ -6,8 +6,8 @@ from ayon_core.pipeline import ( get_representation_path, AYON_CONTAINER_ID ) -from ayon_core.hosts.unreal.api import plugin -from ayon_core.hosts.unreal.api.pipeline import ( +from ayon_unreal.api import plugin +from ayon_unreal.api.pipeline import ( AYON_ASSET_DIR, create_container, imprint, diff --git a/server_addon/unreal/client/ayon_unreal/plugins/load/load_staticmesh_abc.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_staticmesh_abc.py index 0bf6ce9eaa..f60a173cf6 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/load/load_staticmesh_abc.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/load/load_staticmesh_abc.py @@ -6,8 +6,8 @@ from ayon_core.pipeline import ( get_representation_path, AYON_CONTAINER_ID ) -from ayon_core.hosts.unreal.api import plugin -from ayon_core.hosts.unreal.api.pipeline import ( +from ayon_unreal.api import plugin +from ayon_unreal.api.pipeline import ( AYON_ASSET_DIR, create_container, imprint, diff --git a/server_addon/unreal/client/ayon_unreal/plugins/load/load_staticmesh_fbx.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_staticmesh_fbx.py index b7bb57ac23..914f0e23f2 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/load/load_staticmesh_fbx.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/load/load_staticmesh_fbx.py @@ -6,8 +6,8 @@ from ayon_core.pipeline import ( get_representation_path, AYON_CONTAINER_ID ) -from ayon_core.hosts.unreal.api import plugin -from ayon_core.hosts.unreal.api.pipeline import ( +from ayon_unreal.api import plugin +from ayon_unreal.api.pipeline import ( AYON_ASSET_DIR, create_container, imprint, diff --git a/server_addon/unreal/client/ayon_unreal/plugins/load/load_uasset.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_uasset.py index 63f23ecc11..31c13aa9ee 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/load/load_uasset.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/load/load_uasset.py @@ -7,8 +7,8 @@ from ayon_core.pipeline import ( get_representation_path, AYON_CONTAINER_ID ) -from ayon_core.hosts.unreal.api import plugin -from ayon_core.hosts.unreal.api import pipeline as unreal_pipeline +from ayon_unreal.api import plugin +from ayon_unreal.api import pipeline as unreal_pipeline import unreal # noqa diff --git a/server_addon/unreal/client/ayon_unreal/plugins/load/load_yeticache.py b/server_addon/unreal/client/ayon_unreal/plugins/load/load_yeticache.py index 708fc83745..79cf8e21f7 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/load/load_yeticache.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/load/load_yeticache.py @@ -7,8 +7,8 @@ from ayon_core.pipeline import ( get_representation_path, AYON_CONTAINER_ID ) -from ayon_core.hosts.unreal.api import plugin -from ayon_core.hosts.unreal.api import pipeline as unreal_pipeline +from ayon_unreal.api import plugin +from ayon_unreal.api import pipeline as unreal_pipeline import unreal # noqa diff --git a/server_addon/unreal/client/ayon_unreal/plugins/publish/collect_render_instances.py b/server_addon/unreal/client/ayon_unreal/plugins/publish/collect_render_instances.py index ce2a03155b..a93bca70da 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/publish/collect_render_instances.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/publish/collect_render_instances.py @@ -5,7 +5,7 @@ import pyblish.api from ayon_core.pipeline import get_current_project_name from ayon_core.pipeline import Anatomy -from ayon_core.hosts.unreal.api import pipeline +from ayon_unreal.api import pipeline class CollectRenderInstances(pyblish.api.InstancePlugin): diff --git a/server_addon/unreal/client/ayon_unreal/plugins/publish/extract_camera.py b/server_addon/unreal/client/ayon_unreal/plugins/publish/extract_camera.py index ebc5452011..85f9cb0eaa 100644 --- a/server_addon/unreal/client/ayon_unreal/plugins/publish/extract_camera.py +++ b/server_addon/unreal/client/ayon_unreal/plugins/publish/extract_camera.py @@ -5,7 +5,7 @@ import os import unreal from ayon_core.pipeline import publish -from ayon_core.hosts.unreal.api.pipeline import UNREAL_VERSION +from ayon_unreal.api.pipeline import UNREAL_VERSION class ExtractCamera(publish.Extractor): diff --git a/server_addon/unreal/client/ayon_unreal/ue_workers.py b/server_addon/unreal/client/ayon_unreal/ue_workers.py index 256c0557be..1be1287901 100644 --- a/server_addon/unreal/client/ayon_unreal/ue_workers.py +++ b/server_addon/unreal/client/ayon_unreal/ue_workers.py @@ -11,7 +11,7 @@ from typing import List, Union from qtpy import QtCore -import ayon_core.hosts.unreal.lib as ue_lib +import ayon_unreal.lib as ue_lib from ayon_core.settings import get_project_settings From b296492844895996628b2f08edffac9dcfa09bc3 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 17:58:21 +0200 Subject: [PATCH 51/91] add unreal milestone --- client/ayon_core/addon/base.py | 1 + 1 file changed, 1 insertion(+) diff --git a/client/ayon_core/addon/base.py b/client/ayon_core/addon/base.py index c4407424cc..4a24a6c298 100644 --- a/client/ayon_core/addon/base.py +++ b/client/ayon_core/addon/base.py @@ -68,6 +68,7 @@ MOVED_ADDON_MILESTONE_VERSIONS = { "royalrender": VersionInfo(0, 2, 0), "substancepainter": VersionInfo(0, 2, 0), "houdini": VersionInfo(0, 3, 0), + "unreal": VersionInfo(0, 2, 0), } From cee23f3320f0fcbacd9102e0e760963c0b35463d Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 18:36:23 +0200 Subject: [PATCH 52/91] remove moved or removed filenames --- client/ayon_core/addon/base.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/client/ayon_core/addon/base.py b/client/ayon_core/addon/base.py index c4407424cc..afb37b8738 100644 --- a/client/ayon_core/addon/base.py +++ b/client/ayon_core/addon/base.py @@ -37,13 +37,7 @@ IGNORED_DEFAULT_FILENAMES = ( "base.py", "interfaces.py", "click_wrap.py", - "example_addons", - "default_modules", ) -IGNORED_HOSTS_IN_AYON = { - "flame", - "harmony", -} IGNORED_MODULES_IN_AYON = set() # When addon was moved from ayon-core codebase From 430ad8911f84815a6726da9d6b940ced047ecf52 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 18:36:47 +0200 Subject: [PATCH 53/91] removed useless variables --- client/ayon_core/addon/base.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/client/ayon_core/addon/base.py b/client/ayon_core/addon/base.py index afb37b8738..e498b9e5e1 100644 --- a/client/ayon_core/addon/base.py +++ b/client/ayon_core/addon/base.py @@ -38,7 +38,6 @@ IGNORED_DEFAULT_FILENAMES = ( "interfaces.py", "click_wrap.py", ) -IGNORED_MODULES_IN_AYON = set() # When addon was moved from ayon-core codebase # - this is used to log the missing addon @@ -412,12 +411,6 @@ def _load_addons_in_core( hosts_dir = os.path.join(AYON_CORE_ROOT, "hosts") modules_dir = os.path.join(AYON_CORE_ROOT, "modules") - ignored_host_names = set(IGNORED_HOSTS_IN_AYON) - ignored_module_dir_filenames = ( - set(IGNORED_DEFAULT_FILENAMES) - | IGNORED_MODULES_IN_AYON - ) - for dirpath in {hosts_dir, modules_dir}: if not os.path.exists(dirpath): log.warning(( @@ -426,10 +419,9 @@ def _load_addons_in_core( continue is_in_modules_dir = dirpath == modules_dir + ignored_filenames = set() if is_in_modules_dir: - ignored_filenames = ignored_module_dir_filenames - else: - ignored_filenames = ignored_host_names + ignored_filenames = set(IGNORED_DEFAULT_FILENAMES) for filename in os.listdir(dirpath): # Ignore filenames From 784528df58d2845039533e2360347c957962d2ae Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 18:37:07 +0200 Subject: [PATCH 54/91] don't try to make openpype compatibility --- client/ayon_core/addon/base.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/client/ayon_core/addon/base.py b/client/ayon_core/addon/base.py index e498b9e5e1..8fed0475dd 100644 --- a/client/ayon_core/addon/base.py +++ b/client/ayon_core/addon/base.py @@ -487,9 +487,6 @@ def _load_addons_in_core( def _load_addons(): - # Support to use 'openpype' imports - sys.modules["openpype"] = sys.modules["ayon_core"] - # Key under which will be modules imported in `sys.modules` modules_key = "openpype_modules" From 6fd8a18f2742f4c0d3a0b4acff56440ba528e247 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 18:37:15 +0200 Subject: [PATCH 55/91] fix class name in readme --- client/ayon_core/addon/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/addon/README.md b/client/ayon_core/addon/README.md index 88c27db154..e1c04ea0d6 100644 --- a/client/ayon_core/addon/README.md +++ b/client/ayon_core/addon/README.md @@ -35,14 +35,14 @@ AYON addons should contain separated logic of specific kind of implementation, s - addon has more logic when used in a tray - it is possible that addon can be used only in the tray - abstract methods - - `tray_init` - initialization triggered after `initialize` when used in `TrayModulesManager` and before `connect_with_addons` + - `tray_init` - initialization triggered after `initialize` when used in `TrayAddonsManager` and before `connect_with_addons` - `tray_menu` - add actions to tray widget's menu that represent the addon - `tray_start` - start of addon's login in tray - addon is initialized and connected with other addons - `tray_exit` - addon's cleanup like stop and join threads etc. - - order of calling is based on implementation this order is how it works with `TrayModulesManager` + - order of calling is based on implementation this order is how it works with `TrayAddonsManager` - it is recommended to import and use GUI implementation only in these methods -- has attribute `tray_initialized` (bool) which is set to False by default and is set by `TrayModulesManager` to True after `tray_init` +- has attribute `tray_initialized` (bool) which is set to False by default and is set by `TrayAddonsManager` to True after `tray_init` - if addon has logic only in tray or for both then should be checking for `tray_initialized` attribute to decide how should handle situations ### ITrayService From eb0083fc78dfdd860a858af90adc1b6168786f04 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 18:44:50 +0200 Subject: [PATCH 56/91] add version to applications client addon class --- server_addon/applications/client/ayon_applications/__init__.py | 3 +++ server_addon/applications/client/ayon_applications/addon.py | 2 ++ server_addon/applications/client/ayon_applications/version.py | 0 server_addon/applications/package.py | 2 +- 4 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 server_addon/applications/client/ayon_applications/version.py diff --git a/server_addon/applications/client/ayon_applications/__init__.py b/server_addon/applications/client/ayon_applications/__init__.py index c9b72f9914..99d201e49b 100644 --- a/server_addon/applications/client/ayon_applications/__init__.py +++ b/server_addon/applications/client/ayon_applications/__init__.py @@ -1,3 +1,4 @@ +from .version import __version__ from .constants import ( APPLICATIONS_ADDON_ROOT, DEFAULT_ENV_SUBGROUP, @@ -31,6 +32,8 @@ from .addon import ApplicationsAddon __all__ = ( + "__version__", + "APPLICATIONS_ADDON_ROOT", "DEFAULT_ENV_SUBGROUP", "PLATFORM_NAMES", diff --git a/server_addon/applications/client/ayon_applications/addon.py b/server_addon/applications/client/ayon_applications/addon.py index a8eaa46cad..c28d2b475a 100644 --- a/server_addon/applications/client/ayon_applications/addon.py +++ b/server_addon/applications/client/ayon_applications/addon.py @@ -3,6 +3,7 @@ import json from ayon_core.addon import AYONAddon, IPluginPaths, click_wrap +from .version import __version__ from .constants import APPLICATIONS_ADDON_ROOT from .defs import LaunchTypes from .manager import ApplicationManager @@ -10,6 +11,7 @@ from .manager import ApplicationManager class ApplicationsAddon(AYONAddon, IPluginPaths): name = "applications" + version = __version__ def initialize(self, settings): # TODO remove when addon is removed from ayon-core diff --git a/server_addon/applications/client/ayon_applications/version.py b/server_addon/applications/client/ayon_applications/version.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/server_addon/applications/package.py b/server_addon/applications/package.py index 983749355e..a95acad345 100644 --- a/server_addon/applications/package.py +++ b/server_addon/applications/package.py @@ -1,6 +1,6 @@ name = "applications" title = "Applications" -version = "0.2.2" +version = "0.2.3" ayon_server_version = ">=1.0.7" ayon_launcher_version = ">=1.0.2" From f2acf10f1bc5ee810e2adac9755e6099786b2f32 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 18:45:01 +0200 Subject: [PATCH 57/91] add version to clockify client addon class --- server_addon/clockify/client/ayon_clockify/addon.py | 2 ++ server_addon/clockify/client/ayon_clockify/version.py | 2 +- server_addon/clockify/package.py | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/server_addon/clockify/client/ayon_clockify/addon.py b/server_addon/clockify/client/ayon_clockify/addon.py index ce91b2be70..cf35e77ce4 100644 --- a/server_addon/clockify/client/ayon_clockify/addon.py +++ b/server_addon/clockify/client/ayon_clockify/addon.py @@ -4,11 +4,13 @@ import time from ayon_core.addon import AYONAddon, ITrayAddon, IPluginPaths +from .version import __version__ from .constants import CLOCKIFY_FTRACK_USER_PATH, CLOCKIFY_FTRACK_SERVER_PATH class ClockifyAddon(AYONAddon, ITrayAddon, IPluginPaths): name = "clockify" + version = __version__ def initialize(self, studio_settings): enabled = self.name in studio_settings diff --git a/server_addon/clockify/client/ayon_clockify/version.py b/server_addon/clockify/client/ayon_clockify/version.py index 0e6e40cb7d..36bfd79364 100644 --- a/server_addon/clockify/client/ayon_clockify/version.py +++ b/server_addon/clockify/client/ayon_clockify/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring AYON addon 'clockify' version.""" -__version__ = "0.2.0" +__version__ = "0.2.1" diff --git a/server_addon/clockify/package.py b/server_addon/clockify/package.py index 61e0685191..3245e61ca1 100644 --- a/server_addon/clockify/package.py +++ b/server_addon/clockify/package.py @@ -1,6 +1,6 @@ name = "clockify" title = "Clockify" -version = "0.2.0" +version = "0.2.1" client_dir = "ayon_clockify" ayon_required_addons = { From a62478a87b23202f61debf58ea34143ac7684a45 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 18:45:09 +0200 Subject: [PATCH 58/91] add version to maya client addon class --- server_addon/maya/client/ayon_maya/__init__.py | 3 +++ server_addon/maya/client/ayon_maya/addon.py | 3 +++ server_addon/maya/client/ayon_maya/version.py | 0 server_addon/maya/package.py | 2 +- 4 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 server_addon/maya/client/ayon_maya/version.py diff --git a/server_addon/maya/client/ayon_maya/__init__.py b/server_addon/maya/client/ayon_maya/__init__.py index bb940a881b..39d990a3c2 100644 --- a/server_addon/maya/client/ayon_maya/__init__.py +++ b/server_addon/maya/client/ayon_maya/__init__.py @@ -1,3 +1,4 @@ +from .version import __version__ from .addon import ( MayaAddon, MAYA_ROOT_DIR, @@ -5,6 +6,8 @@ from .addon import ( __all__ = ( + "__version__", + "MayaAddon", "MAYA_ROOT_DIR", ) diff --git a/server_addon/maya/client/ayon_maya/addon.py b/server_addon/maya/client/ayon_maya/addon.py index 1ad0fcf4cf..194528bda2 100644 --- a/server_addon/maya/client/ayon_maya/addon.py +++ b/server_addon/maya/client/ayon_maya/addon.py @@ -1,11 +1,14 @@ import os from ayon_core.addon import AYONAddon, IHostAddon +from .version import __version__ + MAYA_ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) class MayaAddon(AYONAddon, IHostAddon): name = "maya" + version = __version__ host_name = "maya" def add_implementation_envs(self, env, _app): diff --git a/server_addon/maya/client/ayon_maya/version.py b/server_addon/maya/client/ayon_maya/version.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/server_addon/maya/package.py b/server_addon/maya/package.py index 0331fb2fb6..701012f0fc 100644 --- a/server_addon/maya/package.py +++ b/server_addon/maya/package.py @@ -1,6 +1,6 @@ name = "maya" title = "Maya" -version = "0.2.1" +version = "0.2.2" ayon_required_addons = { "core": ">0.3.2", From 7d2948b1351687f6d7ff882ab68b4d631594a0aa Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 18:45:16 +0200 Subject: [PATCH 59/91] add version to max client addon class --- server_addon/max/client/ayon_max/__init__.py | 3 +++ server_addon/max/client/ayon_max/addon.py | 3 +++ server_addon/max/client/ayon_max/version.py | 3 +++ server_addon/max/package.py | 2 +- 4 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 server_addon/max/client/ayon_max/version.py diff --git a/server_addon/max/client/ayon_max/__init__.py b/server_addon/max/client/ayon_max/__init__.py index 9a5af8258c..77293f9aa9 100644 --- a/server_addon/max/client/ayon_max/__init__.py +++ b/server_addon/max/client/ayon_max/__init__.py @@ -1,3 +1,4 @@ +from .version import __version__ from .addon import ( MaxAddon, MAX_HOST_DIR, @@ -5,6 +6,8 @@ from .addon import ( __all__ = ( + "__version__", + "MaxAddon", "MAX_HOST_DIR", ) diff --git a/server_addon/max/client/ayon_max/addon.py b/server_addon/max/client/ayon_max/addon.py index 12f5f7eca0..9cc0cda1ee 100644 --- a/server_addon/max/client/ayon_max/addon.py +++ b/server_addon/max/client/ayon_max/addon.py @@ -2,11 +2,14 @@ import os from ayon_core.addon import AYONAddon, IHostAddon +from .version import __version__ + MAX_HOST_DIR = os.path.dirname(os.path.abspath(__file__)) class MaxAddon(AYONAddon, IHostAddon): name = "max" + version = __version__ host_name = "max" def add_implementation_envs(self, env, _app): diff --git a/server_addon/max/client/ayon_max/version.py b/server_addon/max/client/ayon_max/version.py new file mode 100644 index 0000000000..acb68bbdfc --- /dev/null +++ b/server_addon/max/client/ayon_max/version.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +"""Package declaring AYON addon 'max' version.""" +__version__ = "0.2.1" diff --git a/server_addon/max/package.py b/server_addon/max/package.py index ddd4e3b33e..09e86f8d50 100644 --- a/server_addon/max/package.py +++ b/server_addon/max/package.py @@ -1,6 +1,6 @@ name = "max" title = "Max" -version = "0.2.0" +version = "0.2.1" client_dir = "ayon_max" ayon_required_addons = { From 58f62d21aadd5c13f9f7a3526fafdd78dfbb4ac1 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 18:45:23 +0200 Subject: [PATCH 60/91] add version to nuke client addon class --- server_addon/nuke/client/ayon_nuke/__init__.py | 3 +++ server_addon/nuke/client/ayon_nuke/addon.py | 3 +++ server_addon/nuke/client/ayon_nuke/version.py | 3 +++ server_addon/nuke/package.py | 2 +- 4 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 server_addon/nuke/client/ayon_nuke/version.py diff --git a/server_addon/nuke/client/ayon_nuke/__init__.py b/server_addon/nuke/client/ayon_nuke/__init__.py index 8ab565939b..29ea039739 100644 --- a/server_addon/nuke/client/ayon_nuke/__init__.py +++ b/server_addon/nuke/client/ayon_nuke/__init__.py @@ -1,3 +1,4 @@ +from .version import __version__ from .addon import ( NUKE_ROOT_DIR, NukeAddon, @@ -5,6 +6,8 @@ from .addon import ( __all__ = ( + "__version__", + "NUKE_ROOT_DIR", "NukeAddon", ) diff --git a/server_addon/nuke/client/ayon_nuke/addon.py b/server_addon/nuke/client/ayon_nuke/addon.py index 8e640624f0..ccb7379c0f 100644 --- a/server_addon/nuke/client/ayon_nuke/addon.py +++ b/server_addon/nuke/client/ayon_nuke/addon.py @@ -2,11 +2,14 @@ import os import platform from ayon_core.addon import AYONAddon, IHostAddon +from .version import __version__ + NUKE_ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) class NukeAddon(AYONAddon, IHostAddon): name = "nuke" + version = __version__ host_name = "nuke" def add_implementation_envs(self, env, _app): diff --git a/server_addon/nuke/client/ayon_nuke/version.py b/server_addon/nuke/client/ayon_nuke/version.py new file mode 100644 index 0000000000..1130392592 --- /dev/null +++ b/server_addon/nuke/client/ayon_nuke/version.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +"""Package declaring AYON addon 'nuke' version.""" +__version__ = "0.2.2" diff --git a/server_addon/nuke/package.py b/server_addon/nuke/package.py index 9e1f9362cb..9081205c44 100644 --- a/server_addon/nuke/package.py +++ b/server_addon/nuke/package.py @@ -1,6 +1,6 @@ name = "nuke" title = "Nuke" -version = "0.2.1" +version = "0.2.2" client_dir = "ayon_nuke" From 3142521caabc9f92320acece633fc4fd2580bc49 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 18:45:30 +0200 Subject: [PATCH 61/91] add version to houdini client addon class --- server_addon/houdini/client/ayon_houdini/__init__.py | 3 +++ server_addon/houdini/client/ayon_houdini/addon.py | 3 +++ server_addon/houdini/client/ayon_houdini/version.py | 2 +- server_addon/houdini/package.py | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/server_addon/houdini/client/ayon_houdini/__init__.py b/server_addon/houdini/client/ayon_houdini/__init__.py index 38bf1fcc2d..afb51f7315 100644 --- a/server_addon/houdini/client/ayon_houdini/__init__.py +++ b/server_addon/houdini/client/ayon_houdini/__init__.py @@ -1,3 +1,4 @@ +from .version import __version__ from .addon import ( HoudiniAddon, HOUDINI_HOST_DIR, @@ -5,6 +6,8 @@ from .addon import ( __all__ = ( + "__version__", + "HoudiniAddon", "HOUDINI_HOST_DIR", ) diff --git a/server_addon/houdini/client/ayon_houdini/addon.py b/server_addon/houdini/client/ayon_houdini/addon.py index 95d714aea1..4c23553008 100644 --- a/server_addon/houdini/client/ayon_houdini/addon.py +++ b/server_addon/houdini/client/ayon_houdini/addon.py @@ -1,11 +1,14 @@ import os from ayon_core.addon import AYONAddon, IHostAddon +from .version import __version__ + HOUDINI_HOST_DIR = os.path.dirname(os.path.abspath(__file__)) class HoudiniAddon(AYONAddon, IHostAddon): name = "houdini" + version = __version__ host_name = "houdini" def add_implementation_envs(self, env, _app): diff --git a/server_addon/houdini/client/ayon_houdini/version.py b/server_addon/houdini/client/ayon_houdini/version.py index 1b06708904..87d445d563 100644 --- a/server_addon/houdini/client/ayon_houdini/version.py +++ b/server_addon/houdini/client/ayon_houdini/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring AYON addon 'houdini' version.""" -__version__ = "0.3.0" +__version__ = "0.3.1" diff --git a/server_addon/houdini/package.py b/server_addon/houdini/package.py index 275d21c1bf..a8884ff60a 100644 --- a/server_addon/houdini/package.py +++ b/server_addon/houdini/package.py @@ -1,6 +1,6 @@ name = "houdini" title = "Houdini" -version = "0.3.0" +version = "0.3.1" client_dir = "ayon_houdini" From 811bb5de651ef37749ac181683af13a24de88753 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 18:45:39 +0200 Subject: [PATCH 62/91] add version to substance painter client addon class --- .../substancepainter/client/ayon_substancepainter/__init__.py | 3 +++ .../substancepainter/client/ayon_substancepainter/addon.py | 3 +++ .../substancepainter/client/ayon_substancepainter/version.py | 3 +++ server_addon/substancepainter/package.py | 2 +- 4 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 server_addon/substancepainter/client/ayon_substancepainter/version.py diff --git a/server_addon/substancepainter/client/ayon_substancepainter/__init__.py b/server_addon/substancepainter/client/ayon_substancepainter/__init__.py index 4c33b9f507..5627134cbd 100644 --- a/server_addon/substancepainter/client/ayon_substancepainter/__init__.py +++ b/server_addon/substancepainter/client/ayon_substancepainter/__init__.py @@ -1,3 +1,4 @@ +from .version import __version__ from .addon import ( SubstanceAddon, SUBSTANCE_HOST_DIR, @@ -5,6 +6,8 @@ from .addon import ( __all__ = ( + "__version__", + "SubstanceAddon", "SUBSTANCE_HOST_DIR" ) diff --git a/server_addon/substancepainter/client/ayon_substancepainter/addon.py b/server_addon/substancepainter/client/ayon_substancepainter/addon.py index 26829d3153..971b25a1bd 100644 --- a/server_addon/substancepainter/client/ayon_substancepainter/addon.py +++ b/server_addon/substancepainter/client/ayon_substancepainter/addon.py @@ -1,11 +1,14 @@ import os from ayon_core.addon import AYONAddon, IHostAddon +from .version import __version__ + SUBSTANCE_HOST_DIR = os.path.dirname(os.path.abspath(__file__)) class SubstanceAddon(AYONAddon, IHostAddon): name = "substancepainter" + version = __version__ host_name = "substancepainter" def add_implementation_envs(self, env, _app): diff --git a/server_addon/substancepainter/client/ayon_substancepainter/version.py b/server_addon/substancepainter/client/ayon_substancepainter/version.py new file mode 100644 index 0000000000..d8e2b13996 --- /dev/null +++ b/server_addon/substancepainter/client/ayon_substancepainter/version.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +"""Package declaring AYON addon 'substancepainter' version.""" +__version__ = "0.2.1" diff --git a/server_addon/substancepainter/package.py b/server_addon/substancepainter/package.py index 4db5ef634f..8ffad08b27 100644 --- a/server_addon/substancepainter/package.py +++ b/server_addon/substancepainter/package.py @@ -1,6 +1,6 @@ name = "substancepainter" title = "Substance Painter" -version = "0.2.0" +version = "0.2.1" client_dir = "ayon_substancepainter" From cdd3919c09dd48944aad2fff5eda13c196ab5d8a Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 18:45:49 +0200 Subject: [PATCH 63/91] add version to traypublisher client addon class --- .../traypublisher/client/ayon_traypublisher/__init__.py | 3 +++ server_addon/traypublisher/client/ayon_traypublisher/addon.py | 3 +++ .../traypublisher/client/ayon_traypublisher/version.py | 3 +++ server_addon/traypublisher/package.py | 2 +- 4 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 server_addon/traypublisher/client/ayon_traypublisher/version.py diff --git a/server_addon/traypublisher/client/ayon_traypublisher/__init__.py b/server_addon/traypublisher/client/ayon_traypublisher/__init__.py index 77ba908ddd..52a433b5e1 100644 --- a/server_addon/traypublisher/client/ayon_traypublisher/__init__.py +++ b/server_addon/traypublisher/client/ayon_traypublisher/__init__.py @@ -1,6 +1,9 @@ +from .version import __version__ from .addon import TrayPublishAddon __all__ = ( + "__version__", + "TrayPublishAddon", ) diff --git a/server_addon/traypublisher/client/ayon_traypublisher/addon.py b/server_addon/traypublisher/client/ayon_traypublisher/addon.py index 5432cb1a92..dd78a70b59 100644 --- a/server_addon/traypublisher/client/ayon_traypublisher/addon.py +++ b/server_addon/traypublisher/client/ayon_traypublisher/addon.py @@ -10,12 +10,15 @@ from ayon_core.addon import ( IHostAddon, ) +from .version import __version__ + TRAYPUBLISH_ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) class TrayPublishAddon(AYONAddon, IHostAddon, ITrayAction): label = "Publisher" name = "traypublisher" + version = __version__ host_name = "traypublisher" def initialize(self, settings): diff --git a/server_addon/traypublisher/client/ayon_traypublisher/version.py b/server_addon/traypublisher/client/ayon_traypublisher/version.py new file mode 100644 index 0000000000..01f2ad4f1d --- /dev/null +++ b/server_addon/traypublisher/client/ayon_traypublisher/version.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +"""Package declaring AYON addon 'traypublisher' version.""" +__version__ = "0.2.2" diff --git a/server_addon/traypublisher/package.py b/server_addon/traypublisher/package.py index c9b94c2b72..85611526d0 100644 --- a/server_addon/traypublisher/package.py +++ b/server_addon/traypublisher/package.py @@ -1,6 +1,6 @@ name = "traypublisher" title = "TrayPublisher" -version = "0.2.1" +version = "0.2.2" client_dir = "ayon_traypublisher" From 1dd326eb56d9f344f750d6b64ef04050cae929ff Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 6 Jun 2024 18:56:58 +0200 Subject: [PATCH 64/91] remove python 2 vendor --- .../vendor/python/python_2/README.md | 3 - .../vendor/python/python_2/arrow/__init__.py | 18 - .../vendor/python/python_2/arrow/_version.py | 1 - .../vendor/python/python_2/arrow/api.py | 54 - .../vendor/python/python_2/arrow/arrow.py | 1584 ---- .../vendor/python/python_2/arrow/constants.py | 9 - .../vendor/python/python_2/arrow/factory.py | 301 - .../vendor/python/python_2/arrow/formatter.py | 139 - .../vendor/python/python_2/arrow/locales.py | 4267 --------- .../vendor/python/python_2/arrow/parser.py | 596 -- .../vendor/python/python_2/arrow/util.py | 115 - .../vendor/python/python_2/attr/__init__.py | 80 - .../vendor/python/python_2/attr/__init__.pyi | 484 - .../vendor/python/python_2/attr/_cmp.py | 154 - .../vendor/python/python_2/attr/_cmp.pyi | 13 - .../vendor/python/python_2/attr/_compat.py | 261 - .../vendor/python/python_2/attr/_config.py | 33 - .../vendor/python/python_2/attr/_funcs.py | 422 - .../vendor/python/python_2/attr/_make.py | 3173 ------- .../vendor/python/python_2/attr/_next_gen.py | 216 - .../python/python_2/attr/_version_info.py | 87 - .../python/python_2/attr/_version_info.pyi | 9 - .../vendor/python/python_2/attr/converters.py | 155 - .../python/python_2/attr/converters.pyi | 13 - .../vendor/python/python_2/attr/exceptions.py | 94 - .../python/python_2/attr/exceptions.pyi | 17 - .../vendor/python/python_2/attr/filters.py | 54 - .../vendor/python/python_2/attr/filters.pyi | 6 - .../vendor/python/python_2/attr/py.typed | 0 .../vendor/python/python_2/attr/setters.py | 79 - .../vendor/python/python_2/attr/setters.pyi | 19 - .../vendor/python/python_2/attr/validators.py | 561 -- .../python/python_2/attr/validators.pyi | 78 - .../vendor/python/python_2/attrs/__init__.py | 70 - .../vendor/python/python_2/attrs/__init__.pyi | 63 - .../python/python_2/attrs/converters.py | 3 - .../python/python_2/attrs/exceptions.py | 3 - .../vendor/python/python_2/attrs/filters.py | 3 - .../vendor/python/python_2/attrs/py.typed | 0 .../vendor/python/python_2/attrs/setters.py | 3 - .../python/python_2/attrs/validators.py | 3 - .../python/python_2/backports/__init__.py | 1 - .../backports/configparser/__init__.py | 1390 --- .../backports/configparser/helpers.py | 171 - .../python_2/backports/functools_lru_cache.py | 184 - .../python/python_2/builtins/__init__.py | 12 - .../python/python_2/certifi/__init__.py | 3 - .../python/python_2/certifi/__main__.py | 12 - .../vendor/python/python_2/certifi/cacert.pem | 4362 --------- .../vendor/python/python_2/certifi/core.py | 60 - .../python/python_2/chardet/__init__.py | 83 - .../python/python_2/chardet/big5freq.py | 386 - .../python/python_2/chardet/big5prober.py | 47 - .../python_2/chardet/chardistribution.py | 233 - .../python_2/chardet/charsetgroupprober.py | 107 - .../python/python_2/chardet/charsetprober.py | 145 - .../python/python_2/chardet/cli/__init__.py | 1 - .../python/python_2/chardet/cli/chardetect.py | 84 - .../python_2/chardet/codingstatemachine.py | 88 - .../vendor/python/python_2/chardet/compat.py | 36 - .../python/python_2/chardet/cp949prober.py | 49 - .../vendor/python/python_2/chardet/enums.py | 76 - .../python/python_2/chardet/escprober.py | 101 - .../vendor/python/python_2/chardet/escsm.py | 246 - .../python/python_2/chardet/eucjpprober.py | 92 - .../python/python_2/chardet/euckrfreq.py | 195 - .../python/python_2/chardet/euckrprober.py | 47 - .../python/python_2/chardet/euctwfreq.py | 387 - .../python/python_2/chardet/euctwprober.py | 46 - .../python/python_2/chardet/gb2312freq.py | 283 - .../python/python_2/chardet/gb2312prober.py | 46 - .../python/python_2/chardet/hebrewprober.py | 292 - .../vendor/python/python_2/chardet/jisfreq.py | 325 - .../vendor/python/python_2/chardet/jpcntx.py | 233 - .../python_2/chardet/langbulgarianmodel.py | 4650 --------- .../python/python_2/chardet/langgreekmodel.py | 4398 --------- .../python_2/chardet/langhebrewmodel.py | 4383 --------- .../python_2/chardet/langhungarianmodel.py | 4650 --------- .../python_2/chardet/langrussianmodel.py | 5718 ----------- .../python/python_2/chardet/langthaimodel.py | 4383 --------- .../python_2/chardet/langturkishmodel.py | 4383 --------- .../python/python_2/chardet/latin1prober.py | 145 - .../python_2/chardet/mbcharsetprober.py | 91 - .../python_2/chardet/mbcsgroupprober.py | 54 - .../vendor/python/python_2/chardet/mbcssm.py | 572 -- .../python_2/chardet/metadata/__init__.py | 0 .../python_2/chardet/metadata/languages.py | 310 - .../python_2/chardet/sbcharsetprober.py | 145 - .../python_2/chardet/sbcsgroupprober.py | 83 - .../python/python_2/chardet/sjisprober.py | 92 - .../python_2/chardet/universaldetector.py | 286 - .../python/python_2/chardet/utf8prober.py | 82 - .../vendor/python/python_2/chardet/version.py | 9 - .../python/python_2/charset_normalizer.py | 8 - .../vendor/python/python_2/click/__init__.py | 79 - .../python/python_2/click/_bashcomplete.py | 375 - .../vendor/python/python_2/click/_compat.py | 786 -- .../python/python_2/click/_termui_impl.py | 657 -- .../vendor/python/python_2/click/_textwrap.py | 37 - .../python/python_2/click/_unicodefun.py | 131 - .../python/python_2/click/_winconsole.py | 370 - .../vendor/python/python_2/click/core.py | 2030 ---- .../python/python_2/click/decorators.py | 333 - .../python/python_2/click/exceptions.py | 253 - .../python/python_2/click/formatting.py | 283 - .../vendor/python/python_2/click/globals.py | 47 - .../vendor/python/python_2/click/parser.py | 428 - .../vendor/python/python_2/click/termui.py | 681 -- .../vendor/python/python_2/click/testing.py | 382 - .../vendor/python/python_2/click/types.py | 762 -- .../vendor/python/python_2/click/utils.py | 455 - .../vendor/python/python_2/dns/__init__.py | 56 - .../vendor/python/python_2/dns/_compat.py | 59 - .../vendor/python/python_2/dns/dnssec.py | 519 - .../vendor/python/python_2/dns/e164.py | 105 - .../vendor/python/python_2/dns/edns.py | 269 - .../vendor/python/python_2/dns/entropy.py | 148 - .../vendor/python/python_2/dns/exception.py | 128 - .../vendor/python/python_2/dns/flags.py | 130 - .../vendor/python/python_2/dns/grange.py | 69 - .../vendor/python/python_2/dns/hash.py | 37 - .../vendor/python/python_2/dns/inet.py | 124 - .../vendor/python/python_2/dns/ipv4.py | 63 - .../vendor/python/python_2/dns/ipv6.py | 181 - .../vendor/python/python_2/dns/message.py | 1175 --- .../vendor/python/python_2/dns/name.py | 994 -- .../vendor/python/python_2/dns/namedict.py | 108 - .../vendor/python/python_2/dns/node.py | 182 - .../vendor/python/python_2/dns/opcode.py | 119 - .../vendor/python/python_2/dns/py.typed | 0 .../vendor/python/python_2/dns/query.py | 683 -- .../vendor/python/python_2/dns/rcode.py | 144 - .../vendor/python/python_2/dns/rdata.py | 456 - .../vendor/python/python_2/dns/rdataclass.py | 122 - .../vendor/python/python_2/dns/rdataset.py | 347 - .../vendor/python/python_2/dns/rdatatype.py | 287 - .../python/python_2/dns/rdtypes/ANY/AFSDB.py | 55 - .../python/python_2/dns/rdtypes/ANY/AVC.py | 25 - .../python/python_2/dns/rdtypes/ANY/CAA.py | 75 - .../python_2/dns/rdtypes/ANY/CDNSKEY.py | 27 - .../python/python_2/dns/rdtypes/ANY/CDS.py | 23 - .../python/python_2/dns/rdtypes/ANY/CERT.py | 123 - .../python/python_2/dns/rdtypes/ANY/CNAME.py | 27 - .../python/python_2/dns/rdtypes/ANY/CSYNC.py | 126 - .../python/python_2/dns/rdtypes/ANY/DLV.py | 23 - .../python/python_2/dns/rdtypes/ANY/DNAME.py | 26 - .../python/python_2/dns/rdtypes/ANY/DNSKEY.py | 27 - .../python/python_2/dns/rdtypes/ANY/DS.py | 23 - .../python/python_2/dns/rdtypes/ANY/EUI48.py | 29 - .../python/python_2/dns/rdtypes/ANY/EUI64.py | 29 - .../python/python_2/dns/rdtypes/ANY/GPOS.py | 162 - .../python/python_2/dns/rdtypes/ANY/HINFO.py | 86 - .../python/python_2/dns/rdtypes/ANY/HIP.py | 115 - .../python/python_2/dns/rdtypes/ANY/ISDN.py | 99 - .../python/python_2/dns/rdtypes/ANY/LOC.py | 327 - .../python/python_2/dns/rdtypes/ANY/MX.py | 23 - .../python/python_2/dns/rdtypes/ANY/NS.py | 23 - .../python/python_2/dns/rdtypes/ANY/NSEC.py | 128 - .../python/python_2/dns/rdtypes/ANY/NSEC3.py | 196 - .../python_2/dns/rdtypes/ANY/NSEC3PARAM.py | 90 - .../python_2/dns/rdtypes/ANY/OPENPGPKEY.py | 60 - .../python/python_2/dns/rdtypes/ANY/PTR.py | 23 - .../python/python_2/dns/rdtypes/ANY/RP.py | 82 - .../python/python_2/dns/rdtypes/ANY/RRSIG.py | 158 - .../python/python_2/dns/rdtypes/ANY/RT.py | 23 - .../python/python_2/dns/rdtypes/ANY/SOA.py | 116 - .../python/python_2/dns/rdtypes/ANY/SPF.py | 25 - .../python/python_2/dns/rdtypes/ANY/SSHFP.py | 79 - .../python/python_2/dns/rdtypes/ANY/TLSA.py | 84 - .../python/python_2/dns/rdtypes/ANY/TXT.py | 23 - .../python/python_2/dns/rdtypes/ANY/URI.py | 82 - .../python/python_2/dns/rdtypes/ANY/X25.py | 66 - .../python_2/dns/rdtypes/ANY/__init__.py | 57 - .../python/python_2/dns/rdtypes/CH/A.py | 70 - .../python_2/dns/rdtypes/CH/__init__.py | 22 - .../python/python_2/dns/rdtypes/IN/A.py | 54 - .../python/python_2/dns/rdtypes/IN/AAAA.py | 55 - .../python/python_2/dns/rdtypes/IN/APL.py | 165 - .../python/python_2/dns/rdtypes/IN/DHCID.py | 61 - .../python_2/dns/rdtypes/IN/IPSECKEY.py | 150 - .../python/python_2/dns/rdtypes/IN/KX.py | 23 - .../python/python_2/dns/rdtypes/IN/NAPTR.py | 127 - .../python/python_2/dns/rdtypes/IN/NSAP.py | 60 - .../python_2/dns/rdtypes/IN/NSAP_PTR.py | 23 - .../python/python_2/dns/rdtypes/IN/PX.py | 89 - .../python/python_2/dns/rdtypes/IN/SRV.py | 83 - .../python/python_2/dns/rdtypes/IN/WKS.py | 107 - .../python_2/dns/rdtypes/IN/__init__.py | 33 - .../python/python_2/dns/rdtypes/__init__.py | 27 - .../python/python_2/dns/rdtypes/dnskeybase.py | 138 - .../python/python_2/dns/rdtypes/dsbase.py | 85 - .../python/python_2/dns/rdtypes/euibase.py | 71 - .../python/python_2/dns/rdtypes/mxbase.py | 103 - .../python/python_2/dns/rdtypes/nsbase.py | 83 - .../python/python_2/dns/rdtypes/txtbase.py | 97 - .../vendor/python/python_2/dns/renderer.py | 291 - .../vendor/python/python_2/dns/resolver.py | 1383 --- .../vendor/python/python_2/dns/reversename.py | 96 - .../vendor/python/python_2/dns/rrset.py | 189 - .../vendor/python/python_2/dns/set.py | 261 - .../vendor/python/python_2/dns/tokenizer.py | 571 -- .../vendor/python/python_2/dns/tsig.py | 236 - .../vendor/python/python_2/dns/tsigkeyring.py | 50 - .../vendor/python/python_2/dns/ttl.py | 70 - .../vendor/python/python_2/dns/update.py | 279 - .../vendor/python/python_2/dns/version.py | 43 - .../vendor/python/python_2/dns/wiredata.py | 103 - .../vendor/python/python_2/dns/zone.py | 1127 --- .../python/python_2/engineio/__init__.py | 25 - .../python/python_2/engineio/async_aiohttp.py | 129 - .../python/python_2/engineio/async_asgi.py | 223 - .../engineio/async_drivers/__init__.py | 0 .../engineio/async_drivers/aiohttp.py | 128 - .../python_2/engineio/async_drivers/asgi.py | 214 - .../engineio/async_drivers/eventlet.py | 30 - .../python_2/engineio/async_drivers/gevent.py | 63 - .../engineio/async_drivers/gevent_uwsgi.py | 156 - .../python_2/engineio/async_drivers/sanic.py | 144 - .../engineio/async_drivers/threading.py | 17 - .../engineio/async_drivers/tornado.py | 184 - .../python_2/engineio/async_eventlet.py | 30 - .../python/python_2/engineio/async_gevent.py | 63 - .../python_2/engineio/async_gevent_uwsgi.py | 155 - .../python/python_2/engineio/async_sanic.py | 145 - .../python_2/engineio/async_threading.py | 17 - .../python/python_2/engineio/async_tornado.py | 154 - .../python_2/engineio/asyncio_client.py | 556 -- .../python_2/engineio/asyncio_server.py | 444 - .../python_2/engineio/asyncio_socket.py | 235 - .../vendor/python/python_2/engineio/client.py | 641 -- .../python/python_2/engineio/exceptions.py | 22 - .../python/python_2/engineio/middleware.py | 87 - .../vendor/python/python_2/engineio/packet.py | 92 - .../python/python_2/engineio/payload.py | 80 - .../vendor/python/python_2/engineio/server.py | 633 -- .../vendor/python/python_2/engineio/socket.py | 247 - .../python/python_2/engineio/static_files.py | 55 - .../python/python_2/functools32/__init__.py | 1 - .../python_2/functools32/_dummy_thread32.py | 158 - .../python_2/functools32/functools32.py | 423 - .../python/python_2/functools32/reprlib32.py | 157 - .../vendor/python/python_2/idna/__init__.py | 2 - .../vendor/python/python_2/idna/codec.py | 118 - .../vendor/python/python_2/idna/compat.py | 12 - .../vendor/python/python_2/idna/core.py | 400 - .../vendor/python/python_2/idna/idnadata.py | 2050 ---- .../vendor/python/python_2/idna/intranges.py | 53 - .../python/python_2/idna/package_data.py | 2 - .../vendor/python/python_2/idna/uts46data.py | 8357 ----------------- .../python_2/opentimelineio/__init__.py | 51 - .../opentimelineio/adapters/__init__.py | 213 - .../opentimelineio/adapters/adapter.py | 317 - .../builtin_adapters.plugin_manifest.json | 31 - .../opentimelineio/adapters/cmx_3600.py | 1306 --- .../opentimelineio/adapters/fcp_xml.py | 1941 ---- .../opentimelineio/adapters/otio_json.py | 48 - .../opentimelineio/algorithms/__init__.py | 44 - .../opentimelineio/algorithms/filter.py | 275 - .../opentimelineio/algorithms/stack_algo.py | 138 - .../algorithms/timeline_algo.py | 56 - .../opentimelineio/algorithms/track_algo.py | 236 - .../opentimelineio/console/__init__.py | 40 - .../console/autogen_serialized_datamodel.py | 302 - .../opentimelineio/console/console_utils.py | 72 - .../opentimelineio/console/otiocat.py | 138 - .../opentimelineio/console/otioconvert.py | 259 - .../opentimelineio/console/otiostat.py | 193 - .../python_2/opentimelineio/core/__init__.py | 67 - .../opentimelineio/core/composable.py | 141 - .../opentimelineio/core/composition.py | 718 -- .../python_2/opentimelineio/core/item.py | 243 - .../opentimelineio/core/json_serializer.py | 218 - .../opentimelineio/core/media_reference.py | 102 - .../core/serializable_object.py | 219 - .../opentimelineio/core/type_registry.py | 152 - .../opentimelineio/core/unknown_schema.py | 50 - .../python_2/opentimelineio/exceptions.py | 89 - .../python/python_2/opentimelineio/hooks.py | 174 - .../python_2/opentimelineio/media_linker.py | 169 - .../python_2/opentimelineio/opentime.py | 856 -- .../opentimelineio/plugins/__init__.py | 33 - .../opentimelineio/plugins/manifest.py | 282 - .../opentimelineio/plugins/python_plugin.py | 128 - .../opentimelineio/schema/__init__.py | 75 - .../python_2/opentimelineio/schema/clip.py | 130 - .../python_2/opentimelineio/schema/effect.py | 130 - .../schema/external_reference.py | 69 - .../python_2/opentimelineio/schema/gap.py | 82 - .../schema/generator_reference.py | 76 - .../python_2/opentimelineio/schema/marker.py | 128 - .../schema/missing_reference.py | 43 - .../opentimelineio/schema/schemadef.py | 65 - .../schema/serializable_collection.py | 149 - .../python_2/opentimelineio/schema/stack.py | 120 - .../opentimelineio/schema/timeline.py | 133 - .../python_2/opentimelineio/schema/track.py | 242 - .../opentimelineio/schema/transition.py | 159 - .../opentimelineio/schemadef/__init__.py | 5 - .../python_2/opentimelineio/test_utils.py | 54 - .../opentimelineio_contrib/__init__.py | 37 - .../adapters/__init__.py | 0 .../adapters/aaf_adapter/__init__.py | 0 .../adapters/aaf_adapter/aaf_writer.py | 764 -- .../adapters/advanced_authoring_format.py | 979 -- .../opentimelineio_contrib/adapters/ale.py | 318 - .../adapters/burnins.py | 93 - .../contrib_adapters.plugin_manifest.json | 61 - .../adapters/extern_maya_sequencer.py | 261 - .../adapters/extern_rv.py | 327 - .../adapters/fcpx_xml.py | 1182 --- .../adapters/ffmpeg_burnins.py | 424 - .../adapters/hls_playlist.py | 1781 ---- .../adapters/maya_sequencer.py | 132 - .../opentimelineio_contrib/adapters/rv.py | 84 - .../opentimelineio_contrib/adapters/xges.py | 819 -- .../python/python_2/pkg_resources/__init__.py | 3297 ------- .../pkg_resources/_vendor/__init__.py | 0 .../python_2/pkg_resources/_vendor/appdirs.py | 608 -- .../_vendor/packaging/__about__.py | 21 - .../_vendor/packaging/__init__.py | 14 - .../_vendor/packaging/_compat.py | 30 - .../_vendor/packaging/_structures.py | 68 - .../_vendor/packaging/markers.py | 301 - .../_vendor/packaging/requirements.py | 127 - .../_vendor/packaging/specifiers.py | 774 -- .../pkg_resources/_vendor/packaging/utils.py | 14 - .../_vendor/packaging/version.py | 393 - .../pkg_resources/_vendor/pyparsing.py | 5742 ----------- .../python_2/pkg_resources/_vendor/six.py | 868 -- .../python_2/pkg_resources/extern/__init__.py | 73 - .../python/python_2/pkg_resources/py2_warn.py | 19 - .../python_2/pkg_resources/py31compat.py | 23 - .../python/python_2/qtpy/Qt3DAnimation.py | 26 - .../vendor/python/python_2/qtpy/Qt3DCore.py | 26 - .../vendor/python/python_2/qtpy/Qt3DExtras.py | 26 - .../vendor/python/python_2/qtpy/Qt3DInput.py | 26 - .../vendor/python/python_2/qtpy/Qt3DLogic.py | 26 - .../vendor/python/python_2/qtpy/Qt3DRender.py | 26 - .../vendor/python/python_2/qtpy/QtCharts.py | 22 - .../vendor/python/python_2/qtpy/QtCore.py | 111 - .../python_2/qtpy/QtDataVisualization.py | 22 - .../vendor/python/python_2/qtpy/QtDesigner.py | 20 - .../vendor/python/python_2/qtpy/QtGui.py | 161 - .../vendor/python/python_2/qtpy/QtHelp.py | 24 - .../vendor/python/python_2/qtpy/QtLocation.py | 18 - .../python/python_2/qtpy/QtMultimedia.py | 17 - .../python_2/qtpy/QtMultimediaWidgets.py | 18 - .../vendor/python/python_2/qtpy/QtNetwork.py | 25 - .../vendor/python/python_2/qtpy/QtOpenGL.py | 24 - .../python/python_2/qtpy/QtPositioning.py | 18 - .../python/python_2/qtpy/QtPrintSupport.py | 28 - .../vendor/python/python_2/qtpy/QtQml.py | 18 - .../vendor/python/python_2/qtpy/QtQuick.py | 18 - .../python/python_2/qtpy/QtQuickWidgets.py | 18 - .../python/python_2/qtpy/QtSerialPort.py | 17 - .../vendor/python/python_2/qtpy/QtSql.py | 24 - .../vendor/python/python_2/qtpy/QtSvg.py | 24 - .../vendor/python/python_2/qtpy/QtTest.py | 30 - .../python/python_2/qtpy/QtWebChannel.py | 18 - .../python_2/qtpy/QtWebEngineWidgets.py | 49 - .../python/python_2/qtpy/QtWebSockets.py | 18 - .../vendor/python/python_2/qtpy/QtWidgets.py | 135 - .../python/python_2/qtpy/QtWinExtras.py | 16 - .../python/python_2/qtpy/QtXmlPatterns.py | 22 - .../vendor/python/python_2/qtpy/__init__.py | 278 - .../python/python_2/qtpy/_patch/__init__.py | 0 .../python/python_2/qtpy/_patch/qcombobox.py | 101 - .../python_2/qtpy/_patch/qheaderview.py | 96 - .../vendor/python/python_2/qtpy/_version.py | 2 - .../vendor/python/python_2/qtpy/compat.py | 195 - .../vendor/python/python_2/qtpy/py3compat.py | 262 - .../python/python_2/qtpy/tests/__init__.py | 0 .../python/python_2/qtpy/tests/conftest.py | 71 - .../python/python_2/qtpy/tests/runtests.py | 26 - .../python_2/qtpy/tests/test_macos_checks.py | 110 - .../python/python_2/qtpy/tests/test_main.py | 82 - .../qtpy/tests/test_patch_qcombobox.py | 107 - .../qtpy/tests/test_patch_qheaderview.py | 98 - .../qtpy/tests/test_qdesktopservice_split.py | 41 - .../python_2/qtpy/tests/test_qt3danimation.py | 25 - .../python_2/qtpy/tests/test_qt3dcore.py | 44 - .../python_2/qtpy/tests/test_qt3dextras.py | 47 - .../python_2/qtpy/tests/test_qt3dinput.py | 33 - .../python_2/qtpy/tests/test_qt3dlogic.py | 12 - .../python_2/qtpy/tests/test_qt3drender.py | 119 - .../python_2/qtpy/tests/test_qtcharts.py | 11 - .../python/python_2/qtpy/tests/test_qtcore.py | 29 - .../qtpy/tests/test_qtdatavisualization.py | 86 - .../python_2/qtpy/tests/test_qtdesigner.py | 28 - .../python/python_2/qtpy/tests/test_qthelp.py | 22 - .../python_2/qtpy/tests/test_qtlocation.py | 48 - .../python_2/qtpy/tests/test_qtmultimedia.py | 18 - .../qtpy/tests/test_qtmultimediawidgets.py | 18 - .../python_2/qtpy/tests/test_qtnetwork.py | 43 - .../python_2/qtpy/tests/test_qtpositioning.py | 28 - .../qtpy/tests/test_qtprintsupport.py | 18 - .../python/python_2/qtpy/tests/test_qtqml.py | 34 - .../python_2/qtpy/tests/test_qtquick.py | 53 - .../qtpy/tests/test_qtquickwidgets.py | 10 - .../python_2/qtpy/tests/test_qtserialport.py | 12 - .../python/python_2/qtpy/tests/test_qtsql.py | 24 - .../python/python_2/qtpy/tests/test_qtsvg.py | 13 - .../python/python_2/qtpy/tests/test_qttest.py | 9 - .../python_2/qtpy/tests/test_qtwebchannel.py | 13 - .../qtpy/tests/test_qtwebenginewidgets.py | 12 - .../python_2/qtpy/tests/test_qtwebsockets.py | 15 - .../python_2/qtpy/tests/test_qtwinextras.py | 29 - .../python_2/qtpy/tests/test_qtxmlpatterns.py | 25 - .../python/python_2/qtpy/tests/test_uic.py | 116 - .../vendor/python/python_2/qtpy/uic.py | 277 - .../python/python_2/requests/__init__.py | 152 - .../python/python_2/requests/__version__.py | 14 - .../python_2/requests/_internal_utils.py | 42 - .../python/python_2/requests/adapters.py | 538 -- .../vendor/python/python_2/requests/api.py | 159 - .../vendor/python/python_2/requests/auth.py | 305 - .../vendor/python/python_2/requests/certs.py | 18 - .../vendor/python/python_2/requests/compat.py | 81 - .../python/python_2/requests/cookies.py | 549 -- .../python/python_2/requests/exceptions.py | 133 - .../vendor/python/python_2/requests/help.py | 135 - .../vendor/python/python_2/requests/hooks.py | 34 - .../vendor/python/python_2/requests/models.py | 973 -- .../python/python_2/requests/packages.py | 26 - .../python/python_2/requests/sessions.py | 771 -- .../python/python_2/requests/status_codes.py | 123 - .../python/python_2/requests/structures.py | 105 - .../vendor/python/python_2/requests/utils.py | 1060 --- .../vendor/python/python_2/secrets/LICENSE | 21 - .../python/python_2/secrets/__init__.py | 16 - .../vendor/python/python_2/secrets/secrets.py | 132 - .../setuptools-45.0.0.dist-info/INSTALLER | 1 - .../setuptools-45.0.0.dist-info/LICENSE | 19 - .../setuptools-45.0.0.dist-info/METADATA | 84 - .../setuptools-45.0.0.dist-info/RECORD | 197 - .../setuptools-45.0.0.dist-info/REQUESTED | 0 .../setuptools-45.0.0.dist-info/WHEEL | 6 - .../dependency_links.txt | 2 - .../entry_points.txt | 69 - .../setuptools-45.0.0.dist-info/top_level.txt | 3 - .../setuptools-45.0.0.dist-info/zip-safe | 1 - .../python/python_2/setuptools/__init__.py | 228 - .../setuptools/_deprecation_warning.py | 7 - .../vendor/python/python_2/setuptools/_imp.py | 73 - .../python_2/setuptools/_vendor/__init__.py | 0 .../setuptools/_vendor/ordered_set.py | 488 - .../setuptools/_vendor/packaging/__about__.py | 27 - .../setuptools/_vendor/packaging/__init__.py | 26 - .../setuptools/_vendor/packaging/_compat.py | 31 - .../_vendor/packaging/_structures.py | 68 - .../setuptools/_vendor/packaging/markers.py | 296 - .../_vendor/packaging/requirements.py | 138 - .../_vendor/packaging/specifiers.py | 749 -- .../setuptools/_vendor/packaging/tags.py | 404 - .../setuptools/_vendor/packaging/utils.py | 57 - .../setuptools/_vendor/packaging/version.py | 420 - .../python_2/setuptools/_vendor/pyparsing.py | 5742 ----------- .../python/python_2/setuptools/_vendor/six.py | 868 -- .../python_2/setuptools/archive_util.py | 173 - .../python/python_2/setuptools/build_meta.py | 257 - .../python/python_2/setuptools/cli-32.exe | Bin 65536 -> 0 bytes .../python/python_2/setuptools/cli-64.exe | Bin 74752 -> 0 bytes .../vendor/python/python_2/setuptools/cli.exe | Bin 65536 -> 0 bytes .../python_2/setuptools/command/__init__.py | 17 - .../python_2/setuptools/command/alias.py | 80 - .../python_2/setuptools/command/bdist_egg.py | 502 - .../python_2/setuptools/command/bdist_rpm.py | 43 - .../setuptools/command/bdist_wininst.py | 21 - .../python_2/setuptools/command/build_clib.py | 98 - .../python_2/setuptools/command/build_ext.py | 327 - .../python_2/setuptools/command/build_py.py | 270 - .../python_2/setuptools/command/develop.py | 221 - .../python_2/setuptools/command/dist_info.py | 36 - .../setuptools/command/easy_install.py | 2347 ----- .../python_2/setuptools/command/egg_info.py | 717 -- .../python_2/setuptools/command/install.py | 125 - .../setuptools/command/install_egg_info.py | 62 - .../setuptools/command/install_lib.py | 121 - .../setuptools/command/install_scripts.py | 65 - .../setuptools/command/launcher manifest.xml | 15 - .../python_2/setuptools/command/py36compat.py | 136 - .../python_2/setuptools/command/register.py | 18 - .../python_2/setuptools/command/rotate.py | 66 - .../python_2/setuptools/command/saveopts.py | 22 - .../python_2/setuptools/command/sdist.py | 252 - .../python_2/setuptools/command/setopt.py | 149 - .../python_2/setuptools/command/test.py | 279 - .../python_2/setuptools/command/upload.py | 17 - .../setuptools/command/upload_docs.py | 206 - .../python/python_2/setuptools/config.py | 659 -- .../python/python_2/setuptools/dep_util.py | 23 - .../python/python_2/setuptools/depends.py | 176 - .../vendor/python/python_2/setuptools/dist.py | 1274 --- .../python/python_2/setuptools/errors.py | 16 - .../python/python_2/setuptools/extension.py | 57 - .../python_2/setuptools/extern/__init__.py | 73 - .../vendor/python/python_2/setuptools/glob.py | 174 - .../python/python_2/setuptools/gui-32.exe | Bin 65536 -> 0 bytes .../python/python_2/setuptools/gui-64.exe | Bin 75264 -> 0 bytes .../vendor/python/python_2/setuptools/gui.exe | Bin 65536 -> 0 bytes .../python/python_2/setuptools/installer.py | 150 - .../python/python_2/setuptools/launch.py | 35 - .../python/python_2/setuptools/lib2to3_ex.py | 62 - .../python/python_2/setuptools/monkey.py | 179 - .../vendor/python/python_2/setuptools/msvc.py | 1679 ---- .../python/python_2/setuptools/namespaces.py | 107 - .../python_2/setuptools/package_index.py | 1136 --- .../python/python_2/setuptools/py27compat.py | 60 - .../python/python_2/setuptools/py31compat.py | 32 - .../python/python_2/setuptools/py33compat.py | 59 - .../python/python_2/setuptools/py34compat.py | 13 - .../python/python_2/setuptools/sandbox.py | 491 - .../python_2/setuptools/script (dev).tmpl | 6 - .../python/python_2/setuptools/script.tmpl | 3 - .../python/python_2/setuptools/site-patch.py | 74 - .../python/python_2/setuptools/ssl_support.py | 260 - .../python_2/setuptools/unicode_utils.py | 44 - .../python/python_2/setuptools/version.py | 6 - .../python/python_2/setuptools/wheel.py | 220 - .../python_2/setuptools/windows_support.py | 29 - .../python/python_2/socketio/__init__.py | 35 - .../vendor/python/python_2/socketio/asgi.py | 36 - .../python_2/socketio/asyncio_client.py | 445 - .../python_2/socketio/asyncio_manager.py | 58 - .../python_2/socketio/asyncio_namespace.py | 204 - .../socketio/asyncio_pubsub_manager.py | 163 - .../socketio/asyncio_redis_manager.py | 107 - .../python_2/socketio/asyncio_server.py | 515 - .../python/python_2/socketio/base_manager.py | 178 - .../vendor/python/python_2/socketio/client.py | 590 -- .../python/python_2/socketio/exceptions.py | 26 - .../python/python_2/socketio/kombu_manager.py | 105 - .../python/python_2/socketio/middleware.py | 42 - .../python/python_2/socketio/namespace.py | 191 - .../vendor/python/python_2/socketio/packet.py | 179 - .../python_2/socketio/pubsub_manager.py | 154 - .../python/python_2/socketio/redis_manager.py | 111 - .../vendor/python/python_2/socketio/server.py | 719 -- .../python/python_2/socketio/tornado.py | 11 - .../python/python_2/socketio/zmq_manager.py | 111 - .../python/python_2/urllib3/__init__.py | 85 - .../python/python_2/urllib3/_collections.py | 337 - .../python/python_2/urllib3/_version.py | 2 - .../python/python_2/urllib3/connection.py | 567 -- .../python/python_2/urllib3/connectionpool.py | 1108 --- .../python_2/urllib3/contrib/__init__.py | 0 .../urllib3/contrib/_appengine_environ.py | 36 - .../contrib/_securetransport/__init__.py | 0 .../contrib/_securetransport/bindings.py | 519 - .../contrib/_securetransport/low_level.py | 397 - .../python_2/urllib3/contrib/appengine.py | 314 - .../python_2/urllib3/contrib/ntlmpool.py | 130 - .../python_2/urllib3/contrib/pyopenssl.py | 511 - .../urllib3/contrib/securetransport.py | 922 -- .../python/python_2/urllib3/contrib/socks.py | 216 - .../python/python_2/urllib3/exceptions.py | 323 - .../vendor/python/python_2/urllib3/fields.py | 274 - .../python/python_2/urllib3/filepost.py | 98 - .../python_2/urllib3/packages/__init__.py | 0 .../urllib3/packages/backports/__init__.py | 0 .../urllib3/packages/backports/makefile.py | 51 - .../python/python_2/urllib3/packages/six.py | 1077 --- .../python/python_2/urllib3/poolmanager.py | 537 -- .../vendor/python/python_2/urllib3/request.py | 170 - .../python/python_2/urllib3/response.py | 824 -- .../python/python_2/urllib3/util/__init__.py | 49 - .../python_2/urllib3/util/connection.py | 149 - .../python/python_2/urllib3/util/proxy.py | 57 - .../python/python_2/urllib3/util/queue.py | 22 - .../python/python_2/urllib3/util/request.py | 146 - .../python/python_2/urllib3/util/response.py | 107 - .../python/python_2/urllib3/util/retry.py | 620 -- .../python/python_2/urllib3/util/ssl_.py | 495 - .../urllib3/util/ssl_match_hostname.py | 159 - .../python_2/urllib3/util/ssltransport.py | 221 - .../python/python_2/urllib3/util/timeout.py | 268 - .../python/python_2/urllib3/util/url.py | 432 - .../python/python_2/urllib3/util/wait.py | 153 - .../python/python_2/websocket/__init__.py | 28 - .../vendor/python/python_2/websocket/_abnf.py | 458 - .../vendor/python/python_2/websocket/_app.py | 399 - .../python/python_2/websocket/_cookiejar.py | 78 - .../vendor/python/python_2/websocket/_core.py | 595 -- .../python/python_2/websocket/_exceptions.py | 86 - .../python/python_2/websocket/_handshake.py | 212 - .../vendor/python/python_2/websocket/_http.py | 335 - .../python/python_2/websocket/_logging.py | 92 - .../python/python_2/websocket/_socket.py | 176 - .../python/python_2/websocket/_ssl_compat.py | 53 - .../vendor/python/python_2/websocket/_url.py | 178 - .../python/python_2/websocket/_utils.py | 110 - .../python_2/websocket/tests/__init__.py | 0 .../websocket/tests/data/header01.txt | 6 - .../websocket/tests/data/header02.txt | 6 - .../websocket/tests/data/header03.txt | 6 - .../python_2/websocket/tests/test_abnf.py | 77 - .../python_2/websocket/tests/test_app.py | 137 - .../websocket/tests/test_cookiejar.py | 117 - .../python_2/websocket/tests/test_http.py | 109 - .../python_2/websocket/tests/test_url.py | 309 - .../websocket/tests/test_websocket.py | 433 - 601 files changed, 180886 deletions(-) delete mode 100644 client/ayon_core/vendor/python/python_2/README.md delete mode 100644 client/ayon_core/vendor/python/python_2/arrow/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/arrow/_version.py delete mode 100644 client/ayon_core/vendor/python/python_2/arrow/api.py delete mode 100644 client/ayon_core/vendor/python/python_2/arrow/arrow.py delete mode 100644 client/ayon_core/vendor/python/python_2/arrow/constants.py delete mode 100644 client/ayon_core/vendor/python/python_2/arrow/factory.py delete mode 100644 client/ayon_core/vendor/python/python_2/arrow/formatter.py delete mode 100644 client/ayon_core/vendor/python/python_2/arrow/locales.py delete mode 100644 client/ayon_core/vendor/python/python_2/arrow/parser.py delete mode 100644 client/ayon_core/vendor/python/python_2/arrow/util.py delete mode 100644 client/ayon_core/vendor/python/python_2/attr/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/attr/__init__.pyi delete mode 100644 client/ayon_core/vendor/python/python_2/attr/_cmp.py delete mode 100644 client/ayon_core/vendor/python/python_2/attr/_cmp.pyi delete mode 100644 client/ayon_core/vendor/python/python_2/attr/_compat.py delete mode 100644 client/ayon_core/vendor/python/python_2/attr/_config.py delete mode 100644 client/ayon_core/vendor/python/python_2/attr/_funcs.py delete mode 100644 client/ayon_core/vendor/python/python_2/attr/_make.py delete mode 100644 client/ayon_core/vendor/python/python_2/attr/_next_gen.py delete mode 100644 client/ayon_core/vendor/python/python_2/attr/_version_info.py delete mode 100644 client/ayon_core/vendor/python/python_2/attr/_version_info.pyi delete mode 100644 client/ayon_core/vendor/python/python_2/attr/converters.py delete mode 100644 client/ayon_core/vendor/python/python_2/attr/converters.pyi delete mode 100644 client/ayon_core/vendor/python/python_2/attr/exceptions.py delete mode 100644 client/ayon_core/vendor/python/python_2/attr/exceptions.pyi delete mode 100644 client/ayon_core/vendor/python/python_2/attr/filters.py delete mode 100644 client/ayon_core/vendor/python/python_2/attr/filters.pyi delete mode 100644 client/ayon_core/vendor/python/python_2/attr/py.typed delete mode 100644 client/ayon_core/vendor/python/python_2/attr/setters.py delete mode 100644 client/ayon_core/vendor/python/python_2/attr/setters.pyi delete mode 100644 client/ayon_core/vendor/python/python_2/attr/validators.py delete mode 100644 client/ayon_core/vendor/python/python_2/attr/validators.pyi delete mode 100644 client/ayon_core/vendor/python/python_2/attrs/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/attrs/__init__.pyi delete mode 100644 client/ayon_core/vendor/python/python_2/attrs/converters.py delete mode 100644 client/ayon_core/vendor/python/python_2/attrs/exceptions.py delete mode 100644 client/ayon_core/vendor/python/python_2/attrs/filters.py delete mode 100644 client/ayon_core/vendor/python/python_2/attrs/py.typed delete mode 100644 client/ayon_core/vendor/python/python_2/attrs/setters.py delete mode 100644 client/ayon_core/vendor/python/python_2/attrs/validators.py delete mode 100644 client/ayon_core/vendor/python/python_2/backports/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/backports/configparser/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/backports/configparser/helpers.py delete mode 100644 client/ayon_core/vendor/python/python_2/backports/functools_lru_cache.py delete mode 100644 client/ayon_core/vendor/python/python_2/builtins/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/certifi/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/certifi/__main__.py delete mode 100644 client/ayon_core/vendor/python/python_2/certifi/cacert.pem delete mode 100644 client/ayon_core/vendor/python/python_2/certifi/core.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/big5freq.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/big5prober.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/chardistribution.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/charsetgroupprober.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/charsetprober.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/cli/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/cli/chardetect.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/codingstatemachine.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/compat.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/cp949prober.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/enums.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/escprober.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/escsm.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/eucjpprober.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/euckrfreq.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/euckrprober.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/euctwfreq.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/euctwprober.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/gb2312freq.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/gb2312prober.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/hebrewprober.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/jisfreq.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/jpcntx.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/langbulgarianmodel.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/langgreekmodel.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/langhebrewmodel.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/langhungarianmodel.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/langrussianmodel.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/langthaimodel.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/langturkishmodel.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/latin1prober.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/mbcharsetprober.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/mbcsgroupprober.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/mbcssm.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/metadata/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/metadata/languages.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/sbcharsetprober.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/sbcsgroupprober.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/sjisprober.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/universaldetector.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/utf8prober.py delete mode 100644 client/ayon_core/vendor/python/python_2/chardet/version.py delete mode 100644 client/ayon_core/vendor/python/python_2/charset_normalizer.py delete mode 100644 client/ayon_core/vendor/python/python_2/click/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/click/_bashcomplete.py delete mode 100644 client/ayon_core/vendor/python/python_2/click/_compat.py delete mode 100644 client/ayon_core/vendor/python/python_2/click/_termui_impl.py delete mode 100644 client/ayon_core/vendor/python/python_2/click/_textwrap.py delete mode 100644 client/ayon_core/vendor/python/python_2/click/_unicodefun.py delete mode 100644 client/ayon_core/vendor/python/python_2/click/_winconsole.py delete mode 100644 client/ayon_core/vendor/python/python_2/click/core.py delete mode 100644 client/ayon_core/vendor/python/python_2/click/decorators.py delete mode 100644 client/ayon_core/vendor/python/python_2/click/exceptions.py delete mode 100644 client/ayon_core/vendor/python/python_2/click/formatting.py delete mode 100644 client/ayon_core/vendor/python/python_2/click/globals.py delete mode 100644 client/ayon_core/vendor/python/python_2/click/parser.py delete mode 100644 client/ayon_core/vendor/python/python_2/click/termui.py delete mode 100644 client/ayon_core/vendor/python/python_2/click/testing.py delete mode 100644 client/ayon_core/vendor/python/python_2/click/types.py delete mode 100644 client/ayon_core/vendor/python/python_2/click/utils.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/_compat.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/dnssec.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/e164.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/edns.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/entropy.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/exception.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/flags.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/grange.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/hash.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/inet.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/ipv4.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/ipv6.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/message.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/name.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/namedict.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/node.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/opcode.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/py.typed delete mode 100644 client/ayon_core/vendor/python/python_2/dns/query.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rcode.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdata.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdataclass.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdataset.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdatatype.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/AFSDB.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/AVC.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/CAA.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/CDNSKEY.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/CDS.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/CERT.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/CNAME.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/CSYNC.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/DLV.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/DNAME.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/DNSKEY.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/DS.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/EUI48.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/EUI64.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/GPOS.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/HINFO.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/HIP.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/ISDN.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/LOC.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/MX.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/NS.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/NSEC.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/NSEC3.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/NSEC3PARAM.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/OPENPGPKEY.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/PTR.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/RP.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/RRSIG.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/RT.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/SOA.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/SPF.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/SSHFP.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/TLSA.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/TXT.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/URI.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/X25.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/ANY/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/CH/A.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/CH/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/IN/A.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/IN/AAAA.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/IN/APL.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/IN/DHCID.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/IN/IPSECKEY.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/IN/KX.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/IN/NAPTR.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/IN/NSAP.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/IN/NSAP_PTR.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/IN/PX.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/IN/SRV.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/IN/WKS.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/IN/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/dnskeybase.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/dsbase.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/euibase.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/mxbase.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/nsbase.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rdtypes/txtbase.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/renderer.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/resolver.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/reversename.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/rrset.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/set.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/tokenizer.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/tsig.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/tsigkeyring.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/ttl.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/update.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/version.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/wiredata.py delete mode 100644 client/ayon_core/vendor/python/python_2/dns/zone.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/async_aiohttp.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/async_asgi.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/async_drivers/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/async_drivers/aiohttp.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/async_drivers/asgi.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/async_drivers/eventlet.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/async_drivers/gevent.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/async_drivers/gevent_uwsgi.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/async_drivers/sanic.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/async_drivers/threading.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/async_drivers/tornado.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/async_eventlet.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/async_gevent.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/async_gevent_uwsgi.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/async_sanic.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/async_threading.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/async_tornado.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/asyncio_client.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/asyncio_server.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/asyncio_socket.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/client.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/exceptions.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/middleware.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/packet.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/payload.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/server.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/socket.py delete mode 100644 client/ayon_core/vendor/python/python_2/engineio/static_files.py delete mode 100644 client/ayon_core/vendor/python/python_2/functools32/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/functools32/_dummy_thread32.py delete mode 100644 client/ayon_core/vendor/python/python_2/functools32/functools32.py delete mode 100644 client/ayon_core/vendor/python/python_2/functools32/reprlib32.py delete mode 100644 client/ayon_core/vendor/python/python_2/idna/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/idna/codec.py delete mode 100644 client/ayon_core/vendor/python/python_2/idna/compat.py delete mode 100644 client/ayon_core/vendor/python/python_2/idna/core.py delete mode 100644 client/ayon_core/vendor/python/python_2/idna/idnadata.py delete mode 100644 client/ayon_core/vendor/python/python_2/idna/intranges.py delete mode 100644 client/ayon_core/vendor/python/python_2/idna/package_data.py delete mode 100644 client/ayon_core/vendor/python/python_2/idna/uts46data.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/adapters/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/adapters/adapter.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/adapters/builtin_adapters.plugin_manifest.json delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/adapters/cmx_3600.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/adapters/fcp_xml.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/adapters/otio_json.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/algorithms/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/algorithms/filter.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/algorithms/stack_algo.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/algorithms/timeline_algo.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/algorithms/track_algo.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/console/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/console/autogen_serialized_datamodel.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/console/console_utils.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/console/otiocat.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/console/otioconvert.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/console/otiostat.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/core/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/core/composable.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/core/composition.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/core/item.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/core/json_serializer.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/core/media_reference.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/core/serializable_object.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/core/type_registry.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/core/unknown_schema.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/exceptions.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/hooks.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/media_linker.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/opentime.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/plugins/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/plugins/manifest.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/plugins/python_plugin.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/schema/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/schema/clip.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/schema/effect.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/schema/external_reference.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/schema/gap.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/schema/generator_reference.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/schema/marker.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/schema/missing_reference.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/schema/schemadef.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/schema/serializable_collection.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/schema/stack.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/schema/timeline.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/schema/track.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/schema/transition.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/schemadef/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio/test_utils.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio_contrib/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio_contrib/adapters/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio_contrib/adapters/aaf_adapter/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio_contrib/adapters/aaf_adapter/aaf_writer.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio_contrib/adapters/advanced_authoring_format.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio_contrib/adapters/ale.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio_contrib/adapters/burnins.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio_contrib/adapters/contrib_adapters.plugin_manifest.json delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio_contrib/adapters/extern_maya_sequencer.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio_contrib/adapters/extern_rv.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio_contrib/adapters/fcpx_xml.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio_contrib/adapters/ffmpeg_burnins.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio_contrib/adapters/hls_playlist.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio_contrib/adapters/maya_sequencer.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio_contrib/adapters/rv.py delete mode 100644 client/ayon_core/vendor/python/python_2/opentimelineio_contrib/adapters/xges.py delete mode 100644 client/ayon_core/vendor/python/python_2/pkg_resources/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/pkg_resources/_vendor/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/pkg_resources/_vendor/appdirs.py delete mode 100644 client/ayon_core/vendor/python/python_2/pkg_resources/_vendor/packaging/__about__.py delete mode 100644 client/ayon_core/vendor/python/python_2/pkg_resources/_vendor/packaging/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/pkg_resources/_vendor/packaging/_compat.py delete mode 100644 client/ayon_core/vendor/python/python_2/pkg_resources/_vendor/packaging/_structures.py delete mode 100644 client/ayon_core/vendor/python/python_2/pkg_resources/_vendor/packaging/markers.py delete mode 100644 client/ayon_core/vendor/python/python_2/pkg_resources/_vendor/packaging/requirements.py delete mode 100644 client/ayon_core/vendor/python/python_2/pkg_resources/_vendor/packaging/specifiers.py delete mode 100644 client/ayon_core/vendor/python/python_2/pkg_resources/_vendor/packaging/utils.py delete mode 100644 client/ayon_core/vendor/python/python_2/pkg_resources/_vendor/packaging/version.py delete mode 100644 client/ayon_core/vendor/python/python_2/pkg_resources/_vendor/pyparsing.py delete mode 100644 client/ayon_core/vendor/python/python_2/pkg_resources/_vendor/six.py delete mode 100644 client/ayon_core/vendor/python/python_2/pkg_resources/extern/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/pkg_resources/py2_warn.py delete mode 100644 client/ayon_core/vendor/python/python_2/pkg_resources/py31compat.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/Qt3DAnimation.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/Qt3DCore.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/Qt3DExtras.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/Qt3DInput.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/Qt3DLogic.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/Qt3DRender.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtCharts.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtCore.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtDataVisualization.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtDesigner.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtGui.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtHelp.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtLocation.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtMultimedia.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtMultimediaWidgets.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtNetwork.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtOpenGL.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtPositioning.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtPrintSupport.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtQml.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtQuick.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtQuickWidgets.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtSerialPort.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtSql.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtSvg.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtTest.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtWebChannel.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtWebEngineWidgets.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtWebSockets.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtWidgets.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtWinExtras.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/QtXmlPatterns.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/_patch/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/_patch/qcombobox.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/_patch/qheaderview.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/_version.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/compat.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/py3compat.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/conftest.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/runtests.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_macos_checks.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_main.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_patch_qcombobox.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_patch_qheaderview.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qdesktopservice_split.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qt3danimation.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qt3dcore.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qt3dextras.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qt3dinput.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qt3dlogic.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qt3drender.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtcharts.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtcore.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtdatavisualization.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtdesigner.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qthelp.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtlocation.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtmultimedia.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtmultimediawidgets.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtnetwork.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtpositioning.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtprintsupport.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtqml.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtquick.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtquickwidgets.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtserialport.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtsql.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtsvg.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qttest.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtwebchannel.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtwebenginewidgets.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtwebsockets.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtwinextras.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_qtxmlpatterns.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/tests/test_uic.py delete mode 100644 client/ayon_core/vendor/python/python_2/qtpy/uic.py delete mode 100644 client/ayon_core/vendor/python/python_2/requests/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/requests/__version__.py delete mode 100644 client/ayon_core/vendor/python/python_2/requests/_internal_utils.py delete mode 100644 client/ayon_core/vendor/python/python_2/requests/adapters.py delete mode 100644 client/ayon_core/vendor/python/python_2/requests/api.py delete mode 100644 client/ayon_core/vendor/python/python_2/requests/auth.py delete mode 100644 client/ayon_core/vendor/python/python_2/requests/certs.py delete mode 100644 client/ayon_core/vendor/python/python_2/requests/compat.py delete mode 100644 client/ayon_core/vendor/python/python_2/requests/cookies.py delete mode 100644 client/ayon_core/vendor/python/python_2/requests/exceptions.py delete mode 100644 client/ayon_core/vendor/python/python_2/requests/help.py delete mode 100644 client/ayon_core/vendor/python/python_2/requests/hooks.py delete mode 100644 client/ayon_core/vendor/python/python_2/requests/models.py delete mode 100644 client/ayon_core/vendor/python/python_2/requests/packages.py delete mode 100644 client/ayon_core/vendor/python/python_2/requests/sessions.py delete mode 100644 client/ayon_core/vendor/python/python_2/requests/status_codes.py delete mode 100644 client/ayon_core/vendor/python/python_2/requests/structures.py delete mode 100644 client/ayon_core/vendor/python/python_2/requests/utils.py delete mode 100644 client/ayon_core/vendor/python/python_2/secrets/LICENSE delete mode 100644 client/ayon_core/vendor/python/python_2/secrets/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/secrets/secrets.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools-45.0.0.dist-info/INSTALLER delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools-45.0.0.dist-info/LICENSE delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools-45.0.0.dist-info/METADATA delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools-45.0.0.dist-info/RECORD delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools-45.0.0.dist-info/REQUESTED delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools-45.0.0.dist-info/WHEEL delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools-45.0.0.dist-info/dependency_links.txt delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools-45.0.0.dist-info/entry_points.txt delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools-45.0.0.dist-info/top_level.txt delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools-45.0.0.dist-info/zip-safe delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/_deprecation_warning.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/_imp.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/_vendor/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/_vendor/ordered_set.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/_vendor/packaging/__about__.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/_vendor/packaging/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/_vendor/packaging/_compat.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/_vendor/packaging/_structures.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/_vendor/packaging/markers.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/_vendor/packaging/requirements.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/_vendor/packaging/specifiers.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/_vendor/packaging/tags.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/_vendor/packaging/utils.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/_vendor/packaging/version.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/_vendor/pyparsing.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/_vendor/six.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/archive_util.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/build_meta.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/cli-32.exe delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/cli-64.exe delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/cli.exe delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/alias.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/bdist_egg.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/bdist_rpm.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/bdist_wininst.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/build_clib.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/build_ext.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/build_py.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/develop.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/dist_info.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/easy_install.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/egg_info.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/install.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/install_egg_info.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/install_lib.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/install_scripts.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/launcher manifest.xml delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/py36compat.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/register.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/rotate.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/saveopts.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/sdist.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/setopt.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/test.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/upload.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/command/upload_docs.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/config.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/dep_util.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/depends.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/dist.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/errors.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/extension.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/extern/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/glob.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/gui-32.exe delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/gui-64.exe delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/gui.exe delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/installer.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/launch.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/lib2to3_ex.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/monkey.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/msvc.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/namespaces.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/package_index.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/py27compat.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/py31compat.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/py33compat.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/py34compat.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/sandbox.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/script (dev).tmpl delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/script.tmpl delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/site-patch.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/ssl_support.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/unicode_utils.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/version.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/wheel.py delete mode 100644 client/ayon_core/vendor/python/python_2/setuptools/windows_support.py delete mode 100644 client/ayon_core/vendor/python/python_2/socketio/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/socketio/asgi.py delete mode 100644 client/ayon_core/vendor/python/python_2/socketio/asyncio_client.py delete mode 100644 client/ayon_core/vendor/python/python_2/socketio/asyncio_manager.py delete mode 100644 client/ayon_core/vendor/python/python_2/socketio/asyncio_namespace.py delete mode 100644 client/ayon_core/vendor/python/python_2/socketio/asyncio_pubsub_manager.py delete mode 100644 client/ayon_core/vendor/python/python_2/socketio/asyncio_redis_manager.py delete mode 100644 client/ayon_core/vendor/python/python_2/socketio/asyncio_server.py delete mode 100644 client/ayon_core/vendor/python/python_2/socketio/base_manager.py delete mode 100644 client/ayon_core/vendor/python/python_2/socketio/client.py delete mode 100644 client/ayon_core/vendor/python/python_2/socketio/exceptions.py delete mode 100644 client/ayon_core/vendor/python/python_2/socketio/kombu_manager.py delete mode 100644 client/ayon_core/vendor/python/python_2/socketio/middleware.py delete mode 100644 client/ayon_core/vendor/python/python_2/socketio/namespace.py delete mode 100644 client/ayon_core/vendor/python/python_2/socketio/packet.py delete mode 100644 client/ayon_core/vendor/python/python_2/socketio/pubsub_manager.py delete mode 100644 client/ayon_core/vendor/python/python_2/socketio/redis_manager.py delete mode 100644 client/ayon_core/vendor/python/python_2/socketio/server.py delete mode 100644 client/ayon_core/vendor/python/python_2/socketio/tornado.py delete mode 100644 client/ayon_core/vendor/python/python_2/socketio/zmq_manager.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/_collections.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/_version.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/connection.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/connectionpool.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/contrib/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/contrib/_appengine_environ.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/contrib/_securetransport/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/contrib/_securetransport/bindings.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/contrib/_securetransport/low_level.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/contrib/appengine.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/contrib/ntlmpool.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/contrib/pyopenssl.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/contrib/securetransport.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/contrib/socks.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/exceptions.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/fields.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/filepost.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/packages/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/packages/backports/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/packages/backports/makefile.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/packages/six.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/poolmanager.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/request.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/response.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/util/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/util/connection.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/util/proxy.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/util/queue.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/util/request.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/util/response.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/util/retry.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/util/ssl_.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/util/ssl_match_hostname.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/util/ssltransport.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/util/timeout.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/util/url.py delete mode 100644 client/ayon_core/vendor/python/python_2/urllib3/util/wait.py delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/_abnf.py delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/_app.py delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/_cookiejar.py delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/_core.py delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/_exceptions.py delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/_handshake.py delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/_http.py delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/_logging.py delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/_socket.py delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/_ssl_compat.py delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/_url.py delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/_utils.py delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/tests/__init__.py delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/tests/data/header01.txt delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/tests/data/header02.txt delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/tests/data/header03.txt delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/tests/test_abnf.py delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/tests/test_app.py delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/tests/test_cookiejar.py delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/tests/test_http.py delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/tests/test_url.py delete mode 100644 client/ayon_core/vendor/python/python_2/websocket/tests/test_websocket.py diff --git a/client/ayon_core/vendor/python/python_2/README.md b/client/ayon_core/vendor/python/python_2/README.md deleted file mode 100644 index f101ddbf54..0000000000 --- a/client/ayon_core/vendor/python/python_2/README.md +++ /dev/null @@ -1,3 +0,0 @@ -## Info - -Only **Python 2** specific modules are here. \ No newline at end of file diff --git a/client/ayon_core/vendor/python/python_2/arrow/__init__.py b/client/ayon_core/vendor/python/python_2/arrow/__init__.py deleted file mode 100644 index 2883527be8..0000000000 --- a/client/ayon_core/vendor/python/python_2/arrow/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -# -*- coding: utf-8 -*- -from ._version import __version__ -from .api import get, now, utcnow -from .arrow import Arrow -from .factory import ArrowFactory -from .formatter import ( - FORMAT_ATOM, - FORMAT_COOKIE, - FORMAT_RFC822, - FORMAT_RFC850, - FORMAT_RFC1036, - FORMAT_RFC1123, - FORMAT_RFC2822, - FORMAT_RFC3339, - FORMAT_RSS, - FORMAT_W3C, -) -from .parser import ParserError diff --git a/client/ayon_core/vendor/python/python_2/arrow/_version.py b/client/ayon_core/vendor/python/python_2/arrow/_version.py deleted file mode 100644 index fd86b3ee91..0000000000 --- a/client/ayon_core/vendor/python/python_2/arrow/_version.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = "0.17.0" diff --git a/client/ayon_core/vendor/python/python_2/arrow/api.py b/client/ayon_core/vendor/python/python_2/arrow/api.py deleted file mode 100644 index a6b7be3de2..0000000000 --- a/client/ayon_core/vendor/python/python_2/arrow/api.py +++ /dev/null @@ -1,54 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Provides the default implementation of :class:`ArrowFactory ` -methods for use as a module API. - -""" - -from __future__ import absolute_import - -from arrow.factory import ArrowFactory - -# internal default factory. -_factory = ArrowFactory() - - -def get(*args, **kwargs): - """Calls the default :class:`ArrowFactory ` ``get`` method.""" - - return _factory.get(*args, **kwargs) - - -get.__doc__ = _factory.get.__doc__ - - -def utcnow(): - """Calls the default :class:`ArrowFactory ` ``utcnow`` method.""" - - return _factory.utcnow() - - -utcnow.__doc__ = _factory.utcnow.__doc__ - - -def now(tz=None): - """Calls the default :class:`ArrowFactory ` ``now`` method.""" - - return _factory.now(tz) - - -now.__doc__ = _factory.now.__doc__ - - -def factory(type): - """Returns an :class:`.ArrowFactory` for the specified :class:`Arrow ` - or derived type. - - :param type: the type, :class:`Arrow ` or derived. - - """ - - return ArrowFactory(type) - - -__all__ = ["get", "utcnow", "now", "factory"] diff --git a/client/ayon_core/vendor/python/python_2/arrow/arrow.py b/client/ayon_core/vendor/python/python_2/arrow/arrow.py deleted file mode 100644 index 4fe9541789..0000000000 --- a/client/ayon_core/vendor/python/python_2/arrow/arrow.py +++ /dev/null @@ -1,1584 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Provides the :class:`Arrow ` class, an enhanced ``datetime`` -replacement. - -""" - -from __future__ import absolute_import - -import calendar -import sys -import warnings -from datetime import datetime, timedelta -from datetime import tzinfo as dt_tzinfo -from math import trunc - -from dateutil import tz as dateutil_tz -from dateutil.relativedelta import relativedelta - -from arrow import formatter, locales, parser, util - -if sys.version_info[:2] < (3, 6): # pragma: no cover - with warnings.catch_warnings(): - warnings.simplefilter("default", DeprecationWarning) - warnings.warn( - "Arrow will drop support for Python 2.7 and 3.5 in the upcoming v1.0.0 release. Please upgrade to " - "Python 3.6+ to continue receiving updates for Arrow.", - DeprecationWarning, - ) - - -class Arrow(object): - """An :class:`Arrow ` object. - - Implements the ``datetime`` interface, behaving as an aware ``datetime`` while implementing - additional functionality. - - :param year: the calendar year. - :param month: the calendar month. - :param day: the calendar day. - :param hour: (optional) the hour. Defaults to 0. - :param minute: (optional) the minute, Defaults to 0. - :param second: (optional) the second, Defaults to 0. - :param microsecond: (optional) the microsecond. Defaults to 0. - :param tzinfo: (optional) A timezone expression. Defaults to UTC. - :param fold: (optional) 0 or 1, used to disambiguate repeated times. Defaults to 0. - - .. _tz-expr: - - Recognized timezone expressions: - - - A ``tzinfo`` object. - - A ``str`` describing a timezone, similar to 'US/Pacific', or 'Europe/Berlin'. - - A ``str`` in ISO 8601 style, as in '+07:00'. - - A ``str``, one of the following: 'local', 'utc', 'UTC'. - - Usage:: - - >>> import arrow - >>> arrow.Arrow(2013, 5, 5, 12, 30, 45) - - - """ - - resolution = datetime.resolution - - _ATTRS = ["year", "month", "day", "hour", "minute", "second", "microsecond"] - _ATTRS_PLURAL = ["{}s".format(a) for a in _ATTRS] - _MONTHS_PER_QUARTER = 3 - _SECS_PER_MINUTE = float(60) - _SECS_PER_HOUR = float(60 * 60) - _SECS_PER_DAY = float(60 * 60 * 24) - _SECS_PER_WEEK = float(60 * 60 * 24 * 7) - _SECS_PER_MONTH = float(60 * 60 * 24 * 30.5) - _SECS_PER_YEAR = float(60 * 60 * 24 * 365.25) - - def __init__( - self, - year, - month, - day, - hour=0, - minute=0, - second=0, - microsecond=0, - tzinfo=None, - **kwargs - ): - if tzinfo is None: - tzinfo = dateutil_tz.tzutc() - # detect that tzinfo is a pytz object (issue #626) - elif ( - isinstance(tzinfo, dt_tzinfo) - and hasattr(tzinfo, "localize") - and hasattr(tzinfo, "zone") - and tzinfo.zone - ): - tzinfo = parser.TzinfoParser.parse(tzinfo.zone) - elif util.isstr(tzinfo): - tzinfo = parser.TzinfoParser.parse(tzinfo) - - fold = kwargs.get("fold", 0) - - # use enfold here to cover direct arrow.Arrow init on 2.7/3.5 - self._datetime = dateutil_tz.enfold( - datetime(year, month, day, hour, minute, second, microsecond, tzinfo), - fold=fold, - ) - - # factories: single object, both original and from datetime. - - @classmethod - def now(cls, tzinfo=None): - """Constructs an :class:`Arrow ` object, representing "now" in the given - timezone. - - :param tzinfo: (optional) a ``tzinfo`` object. Defaults to local time. - - Usage:: - - >>> arrow.now('Asia/Baku') - - - """ - - if tzinfo is None: - tzinfo = dateutil_tz.tzlocal() - - dt = datetime.now(tzinfo) - - return cls( - dt.year, - dt.month, - dt.day, - dt.hour, - dt.minute, - dt.second, - dt.microsecond, - dt.tzinfo, - fold=getattr(dt, "fold", 0), - ) - - @classmethod - def utcnow(cls): - """Constructs an :class:`Arrow ` object, representing "now" in UTC - time. - - Usage:: - - >>> arrow.utcnow() - - - """ - - dt = datetime.now(dateutil_tz.tzutc()) - - return cls( - dt.year, - dt.month, - dt.day, - dt.hour, - dt.minute, - dt.second, - dt.microsecond, - dt.tzinfo, - fold=getattr(dt, "fold", 0), - ) - - @classmethod - def fromtimestamp(cls, timestamp, tzinfo=None): - """Constructs an :class:`Arrow ` object from a timestamp, converted to - the given timezone. - - :param timestamp: an ``int`` or ``float`` timestamp, or a ``str`` that converts to either. - :param tzinfo: (optional) a ``tzinfo`` object. Defaults to local time. - """ - - if tzinfo is None: - tzinfo = dateutil_tz.tzlocal() - elif util.isstr(tzinfo): - tzinfo = parser.TzinfoParser.parse(tzinfo) - - if not util.is_timestamp(timestamp): - raise ValueError( - "The provided timestamp '{}' is invalid.".format(timestamp) - ) - - timestamp = util.normalize_timestamp(float(timestamp)) - dt = datetime.fromtimestamp(timestamp, tzinfo) - - return cls( - dt.year, - dt.month, - dt.day, - dt.hour, - dt.minute, - dt.second, - dt.microsecond, - dt.tzinfo, - fold=getattr(dt, "fold", 0), - ) - - @classmethod - def utcfromtimestamp(cls, timestamp): - """Constructs an :class:`Arrow ` object from a timestamp, in UTC time. - - :param timestamp: an ``int`` or ``float`` timestamp, or a ``str`` that converts to either. - - """ - - if not util.is_timestamp(timestamp): - raise ValueError( - "The provided timestamp '{}' is invalid.".format(timestamp) - ) - - timestamp = util.normalize_timestamp(float(timestamp)) - dt = datetime.utcfromtimestamp(timestamp) - - return cls( - dt.year, - dt.month, - dt.day, - dt.hour, - dt.minute, - dt.second, - dt.microsecond, - dateutil_tz.tzutc(), - fold=getattr(dt, "fold", 0), - ) - - @classmethod - def fromdatetime(cls, dt, tzinfo=None): - """Constructs an :class:`Arrow ` object from a ``datetime`` and - optional replacement timezone. - - :param dt: the ``datetime`` - :param tzinfo: (optional) A :ref:`timezone expression `. Defaults to ``dt``'s - timezone, or UTC if naive. - - If you only want to replace the timezone of naive datetimes:: - - >>> dt - datetime.datetime(2013, 5, 5, 0, 0, tzinfo=tzutc()) - >>> arrow.Arrow.fromdatetime(dt, dt.tzinfo or 'US/Pacific') - - - """ - - if tzinfo is None: - if dt.tzinfo is None: - tzinfo = dateutil_tz.tzutc() - else: - tzinfo = dt.tzinfo - - return cls( - dt.year, - dt.month, - dt.day, - dt.hour, - dt.minute, - dt.second, - dt.microsecond, - tzinfo, - fold=getattr(dt, "fold", 0), - ) - - @classmethod - def fromdate(cls, date, tzinfo=None): - """Constructs an :class:`Arrow ` object from a ``date`` and optional - replacement timezone. Time values are set to 0. - - :param date: the ``date`` - :param tzinfo: (optional) A :ref:`timezone expression `. Defaults to UTC. - """ - - if tzinfo is None: - tzinfo = dateutil_tz.tzutc() - - return cls(date.year, date.month, date.day, tzinfo=tzinfo) - - @classmethod - def strptime(cls, date_str, fmt, tzinfo=None): - """Constructs an :class:`Arrow ` object from a date string and format, - in the style of ``datetime.strptime``. Optionally replaces the parsed timezone. - - :param date_str: the date string. - :param fmt: the format string. - :param tzinfo: (optional) A :ref:`timezone expression `. Defaults to the parsed - timezone if ``fmt`` contains a timezone directive, otherwise UTC. - - Usage:: - - >>> arrow.Arrow.strptime('20-01-2019 15:49:10', '%d-%m-%Y %H:%M:%S') - - - """ - - dt = datetime.strptime(date_str, fmt) - if tzinfo is None: - tzinfo = dt.tzinfo - - return cls( - dt.year, - dt.month, - dt.day, - dt.hour, - dt.minute, - dt.second, - dt.microsecond, - tzinfo, - fold=getattr(dt, "fold", 0), - ) - - # factories: ranges and spans - - @classmethod - def range(cls, frame, start, end=None, tz=None, limit=None): - """Returns an iterator of :class:`Arrow ` objects, representing - points in time between two inputs. - - :param frame: The timeframe. Can be any ``datetime`` property (day, hour, minute...). - :param start: A datetime expression, the start of the range. - :param end: (optional) A datetime expression, the end of the range. - :param tz: (optional) A :ref:`timezone expression `. Defaults to - ``start``'s timezone, or UTC if ``start`` is naive. - :param limit: (optional) A maximum number of tuples to return. - - **NOTE**: The ``end`` or ``limit`` must be provided. Call with ``end`` alone to - return the entire range. Call with ``limit`` alone to return a maximum # of results from - the start. Call with both to cap a range at a maximum # of results. - - **NOTE**: ``tz`` internally **replaces** the timezones of both ``start`` and ``end`` before - iterating. As such, either call with naive objects and ``tz``, or aware objects from the - same timezone and no ``tz``. - - Supported frame values: year, quarter, month, week, day, hour, minute, second. - - Recognized datetime expressions: - - - An :class:`Arrow ` object. - - A ``datetime`` object. - - Usage:: - - >>> start = datetime(2013, 5, 5, 12, 30) - >>> end = datetime(2013, 5, 5, 17, 15) - >>> for r in arrow.Arrow.range('hour', start, end): - ... print(repr(r)) - ... - - - - - - - **NOTE**: Unlike Python's ``range``, ``end`` *may* be included in the returned iterator:: - - >>> start = datetime(2013, 5, 5, 12, 30) - >>> end = datetime(2013, 5, 5, 13, 30) - >>> for r in arrow.Arrow.range('hour', start, end): - ... print(repr(r)) - ... - - - - """ - - _, frame_relative, relative_steps = cls._get_frames(frame) - - tzinfo = cls._get_tzinfo(start.tzinfo if tz is None else tz) - - start = cls._get_datetime(start).replace(tzinfo=tzinfo) - end, limit = cls._get_iteration_params(end, limit) - end = cls._get_datetime(end).replace(tzinfo=tzinfo) - - current = cls.fromdatetime(start) - original_day = start.day - day_is_clipped = False - i = 0 - - while current <= end and i < limit: - i += 1 - yield current - - values = [getattr(current, f) for f in cls._ATTRS] - current = cls(*values, tzinfo=tzinfo).shift( - **{frame_relative: relative_steps} - ) - - if frame in ["month", "quarter", "year"] and current.day < original_day: - day_is_clipped = True - - if day_is_clipped and not cls._is_last_day_of_month(current): - current = current.replace(day=original_day) - - def span(self, frame, count=1, bounds="[)"): - """Returns two new :class:`Arrow ` objects, representing the timespan - of the :class:`Arrow ` object in a given timeframe. - - :param frame: the timeframe. Can be any ``datetime`` property (day, hour, minute...). - :param count: (optional) the number of frames to span. - :param bounds: (optional) a ``str`` of either '()', '(]', '[)', or '[]' that specifies - whether to include or exclude the start and end values in the span. '(' excludes - the start, '[' includes the start, ')' excludes the end, and ']' includes the end. - If the bounds are not specified, the default bound '[)' is used. - - Supported frame values: year, quarter, month, week, day, hour, minute, second. - - Usage:: - - >>> arrow.utcnow() - - - >>> arrow.utcnow().span('hour') - (, ) - - >>> arrow.utcnow().span('day') - (, ) - - >>> arrow.utcnow().span('day', count=2) - (, ) - - >>> arrow.utcnow().span('day', bounds='[]') - (, ) - - """ - - util.validate_bounds(bounds) - - frame_absolute, frame_relative, relative_steps = self._get_frames(frame) - - if frame_absolute == "week": - attr = "day" - elif frame_absolute == "quarter": - attr = "month" - else: - attr = frame_absolute - - index = self._ATTRS.index(attr) - frames = self._ATTRS[: index + 1] - - values = [getattr(self, f) for f in frames] - - for _ in range(3 - len(values)): - values.append(1) - - floor = self.__class__(*values, tzinfo=self.tzinfo) - - if frame_absolute == "week": - floor = floor.shift(days=-(self.isoweekday() - 1)) - elif frame_absolute == "quarter": - floor = floor.shift(months=-((self.month - 1) % 3)) - - ceil = floor.shift(**{frame_relative: count * relative_steps}) - - if bounds[0] == "(": - floor = floor.shift(microseconds=+1) - - if bounds[1] == ")": - ceil = ceil.shift(microseconds=-1) - - return floor, ceil - - def floor(self, frame): - """Returns a new :class:`Arrow ` object, representing the "floor" - of the timespan of the :class:`Arrow ` object in a given timeframe. - Equivalent to the first element in the 2-tuple returned by - :func:`span `. - - :param frame: the timeframe. Can be any ``datetime`` property (day, hour, minute...). - - Usage:: - - >>> arrow.utcnow().floor('hour') - - """ - - return self.span(frame)[0] - - def ceil(self, frame): - """Returns a new :class:`Arrow ` object, representing the "ceiling" - of the timespan of the :class:`Arrow ` object in a given timeframe. - Equivalent to the second element in the 2-tuple returned by - :func:`span `. - - :param frame: the timeframe. Can be any ``datetime`` property (day, hour, minute...). - - Usage:: - - >>> arrow.utcnow().ceil('hour') - - """ - - return self.span(frame)[1] - - @classmethod - def span_range(cls, frame, start, end, tz=None, limit=None, bounds="[)"): - """Returns an iterator of tuples, each :class:`Arrow ` objects, - representing a series of timespans between two inputs. - - :param frame: The timeframe. Can be any ``datetime`` property (day, hour, minute...). - :param start: A datetime expression, the start of the range. - :param end: (optional) A datetime expression, the end of the range. - :param tz: (optional) A :ref:`timezone expression `. Defaults to - ``start``'s timezone, or UTC if ``start`` is naive. - :param limit: (optional) A maximum number of tuples to return. - :param bounds: (optional) a ``str`` of either '()', '(]', '[)', or '[]' that specifies - whether to include or exclude the start and end values in each span in the range. '(' excludes - the start, '[' includes the start, ')' excludes the end, and ']' includes the end. - If the bounds are not specified, the default bound '[)' is used. - - **NOTE**: The ``end`` or ``limit`` must be provided. Call with ``end`` alone to - return the entire range. Call with ``limit`` alone to return a maximum # of results from - the start. Call with both to cap a range at a maximum # of results. - - **NOTE**: ``tz`` internally **replaces** the timezones of both ``start`` and ``end`` before - iterating. As such, either call with naive objects and ``tz``, or aware objects from the - same timezone and no ``tz``. - - Supported frame values: year, quarter, month, week, day, hour, minute, second. - - Recognized datetime expressions: - - - An :class:`Arrow ` object. - - A ``datetime`` object. - - **NOTE**: Unlike Python's ``range``, ``end`` will *always* be included in the returned - iterator of timespans. - - Usage: - - >>> start = datetime(2013, 5, 5, 12, 30) - >>> end = datetime(2013, 5, 5, 17, 15) - >>> for r in arrow.Arrow.span_range('hour', start, end): - ... print(r) - ... - (, ) - (, ) - (, ) - (, ) - (, ) - (, ) - - """ - - tzinfo = cls._get_tzinfo(start.tzinfo if tz is None else tz) - start = cls.fromdatetime(start, tzinfo).span(frame)[0] - _range = cls.range(frame, start, end, tz, limit) - return (r.span(frame, bounds=bounds) for r in _range) - - @classmethod - def interval(cls, frame, start, end, interval=1, tz=None, bounds="[)"): - """Returns an iterator of tuples, each :class:`Arrow ` objects, - representing a series of intervals between two inputs. - - :param frame: The timeframe. Can be any ``datetime`` property (day, hour, minute...). - :param start: A datetime expression, the start of the range. - :param end: (optional) A datetime expression, the end of the range. - :param interval: (optional) Time interval for the given time frame. - :param tz: (optional) A timezone expression. Defaults to UTC. - :param bounds: (optional) a ``str`` of either '()', '(]', '[)', or '[]' that specifies - whether to include or exclude the start and end values in the intervals. '(' excludes - the start, '[' includes the start, ')' excludes the end, and ']' includes the end. - If the bounds are not specified, the default bound '[)' is used. - - Supported frame values: year, quarter, month, week, day, hour, minute, second - - Recognized datetime expressions: - - - An :class:`Arrow ` object. - - A ``datetime`` object. - - Recognized timezone expressions: - - - A ``tzinfo`` object. - - A ``str`` describing a timezone, similar to 'US/Pacific', or 'Europe/Berlin'. - - A ``str`` in ISO 8601 style, as in '+07:00'. - - A ``str``, one of the following: 'local', 'utc', 'UTC'. - - Usage: - - >>> start = datetime(2013, 5, 5, 12, 30) - >>> end = datetime(2013, 5, 5, 17, 15) - >>> for r in arrow.Arrow.interval('hour', start, end, 2): - ... print r - ... - (, ) - (, ) - (, ) - """ - if interval < 1: - raise ValueError("interval has to be a positive integer") - - spanRange = iter(cls.span_range(frame, start, end, tz, bounds=bounds)) - while True: - try: - intvlStart, intvlEnd = next(spanRange) - for _ in range(interval - 1): - _, intvlEnd = next(spanRange) - yield intvlStart, intvlEnd - except StopIteration: - return - - # representations - - def __repr__(self): - return "<{} [{}]>".format(self.__class__.__name__, self.__str__()) - - def __str__(self): - return self._datetime.isoformat() - - def __format__(self, formatstr): - - if len(formatstr) > 0: - return self.format(formatstr) - - return str(self) - - def __hash__(self): - return self._datetime.__hash__() - - # attributes and properties - - def __getattr__(self, name): - - if name == "week": - return self.isocalendar()[1] - - if name == "quarter": - return int((self.month - 1) / self._MONTHS_PER_QUARTER) + 1 - - if not name.startswith("_"): - value = getattr(self._datetime, name, None) - - if value is not None: - return value - - return object.__getattribute__(self, name) - - @property - def tzinfo(self): - """Gets the ``tzinfo`` of the :class:`Arrow ` object. - - Usage:: - - >>> arw=arrow.utcnow() - >>> arw.tzinfo - tzutc() - - """ - - return self._datetime.tzinfo - - @tzinfo.setter - def tzinfo(self, tzinfo): - """ Sets the ``tzinfo`` of the :class:`Arrow ` object. """ - - self._datetime = self._datetime.replace(tzinfo=tzinfo) - - @property - def datetime(self): - """Returns a datetime representation of the :class:`Arrow ` object. - - Usage:: - - >>> arw=arrow.utcnow() - >>> arw.datetime - datetime.datetime(2019, 1, 24, 16, 35, 27, 276649, tzinfo=tzutc()) - - """ - - return self._datetime - - @property - def naive(self): - """Returns a naive datetime representation of the :class:`Arrow ` - object. - - Usage:: - - >>> nairobi = arrow.now('Africa/Nairobi') - >>> nairobi - - >>> nairobi.naive - datetime.datetime(2019, 1, 23, 19, 27, 12, 297999) - - """ - - return self._datetime.replace(tzinfo=None) - - @property - def timestamp(self): - """Returns a timestamp representation of the :class:`Arrow ` object, in - UTC time. - - Usage:: - - >>> arrow.utcnow().timestamp - 1548260567 - - """ - - warnings.warn( - "For compatibility with the datetime.timestamp() method this property will be replaced with a method in " - "the 1.0.0 release, please switch to the .int_timestamp property for identical behaviour as soon as " - "possible.", - DeprecationWarning, - ) - return calendar.timegm(self._datetime.utctimetuple()) - - @property - def int_timestamp(self): - """Returns a timestamp representation of the :class:`Arrow ` object, in - UTC time. - - Usage:: - - >>> arrow.utcnow().int_timestamp - 1548260567 - - """ - - return calendar.timegm(self._datetime.utctimetuple()) - - @property - def float_timestamp(self): - """Returns a floating-point representation of the :class:`Arrow ` - object, in UTC time. - - Usage:: - - >>> arrow.utcnow().float_timestamp - 1548260516.830896 - - """ - - # IDEA get rid of this in 1.0.0 and wrap datetime.timestamp() - # Or for compatibility retain this but make it call the timestamp method - with warnings.catch_warnings(): - warnings.simplefilter("ignore", DeprecationWarning) - return self.timestamp + float(self.microsecond) / 1000000 - - @property - def fold(self): - """ Returns the ``fold`` value of the :class:`Arrow ` object. """ - - # in python < 3.6 _datetime will be a _DatetimeWithFold if fold=1 and a datetime with no fold attribute - # otherwise, so we need to return zero to cover the latter case - return getattr(self._datetime, "fold", 0) - - @property - def ambiguous(self): - """ Returns a boolean indicating whether the :class:`Arrow ` object is ambiguous.""" - - return dateutil_tz.datetime_ambiguous(self._datetime) - - @property - def imaginary(self): - """Indicates whether the :class: `Arrow ` object exists in the current timezone.""" - - return not dateutil_tz.datetime_exists(self._datetime) - - # mutation and duplication. - - def clone(self): - """Returns a new :class:`Arrow ` object, cloned from the current one. - - Usage: - - >>> arw = arrow.utcnow() - >>> cloned = arw.clone() - - """ - - return self.fromdatetime(self._datetime) - - def replace(self, **kwargs): - """Returns a new :class:`Arrow ` object with attributes updated - according to inputs. - - Use property names to set their value absolutely:: - - >>> import arrow - >>> arw = arrow.utcnow() - >>> arw - - >>> arw.replace(year=2014, month=6) - - - You can also replace the timezone without conversion, using a - :ref:`timezone expression `:: - - >>> arw.replace(tzinfo=tz.tzlocal()) - - - """ - - absolute_kwargs = {} - - for key, value in kwargs.items(): - - if key in self._ATTRS: - absolute_kwargs[key] = value - elif key in ["week", "quarter"]: - raise AttributeError("setting absolute {} is not supported".format(key)) - elif key not in ["tzinfo", "fold"]: - raise AttributeError('unknown attribute: "{}"'.format(key)) - - current = self._datetime.replace(**absolute_kwargs) - - tzinfo = kwargs.get("tzinfo") - - if tzinfo is not None: - tzinfo = self._get_tzinfo(tzinfo) - current = current.replace(tzinfo=tzinfo) - - fold = kwargs.get("fold") - - # TODO revisit this once we drop support for 2.7/3.5 - if fold is not None: - current = dateutil_tz.enfold(current, fold=fold) - - return self.fromdatetime(current) - - def shift(self, **kwargs): - """Returns a new :class:`Arrow ` object with attributes updated - according to inputs. - - Use pluralized property names to relatively shift their current value: - - >>> import arrow - >>> arw = arrow.utcnow() - >>> arw - - >>> arw.shift(years=1, months=-1) - - - Day-of-the-week relative shifting can use either Python's weekday numbers - (Monday = 0, Tuesday = 1 .. Sunday = 6) or using dateutil.relativedelta's - day instances (MO, TU .. SU). When using weekday numbers, the returned - date will always be greater than or equal to the starting date. - - Using the above code (which is a Saturday) and asking it to shift to Saturday: - - >>> arw.shift(weekday=5) - - - While asking for a Monday: - - >>> arw.shift(weekday=0) - - - """ - - relative_kwargs = {} - additional_attrs = ["weeks", "quarters", "weekday"] - - for key, value in kwargs.items(): - - if key in self._ATTRS_PLURAL or key in additional_attrs: - relative_kwargs[key] = value - else: - raise AttributeError( - "Invalid shift time frame. Please select one of the following: {}.".format( - ", ".join(self._ATTRS_PLURAL + additional_attrs) - ) - ) - - # core datetime does not support quarters, translate to months. - relative_kwargs.setdefault("months", 0) - relative_kwargs["months"] += ( - relative_kwargs.pop("quarters", 0) * self._MONTHS_PER_QUARTER - ) - - current = self._datetime + relativedelta(**relative_kwargs) - - if not dateutil_tz.datetime_exists(current): - current = dateutil_tz.resolve_imaginary(current) - - return self.fromdatetime(current) - - def to(self, tz): - """Returns a new :class:`Arrow ` object, converted - to the target timezone. - - :param tz: A :ref:`timezone expression `. - - Usage:: - - >>> utc = arrow.utcnow() - >>> utc - - - >>> utc.to('US/Pacific') - - - >>> utc.to(tz.tzlocal()) - - - >>> utc.to('-07:00') - - - >>> utc.to('local') - - - >>> utc.to('local').to('utc') - - - """ - - if not isinstance(tz, dt_tzinfo): - tz = parser.TzinfoParser.parse(tz) - - dt = self._datetime.astimezone(tz) - - return self.__class__( - dt.year, - dt.month, - dt.day, - dt.hour, - dt.minute, - dt.second, - dt.microsecond, - dt.tzinfo, - fold=getattr(dt, "fold", 0), - ) - - # string output and formatting - - def format(self, fmt="YYYY-MM-DD HH:mm:ssZZ", locale="en_us"): - """Returns a string representation of the :class:`Arrow ` object, - formatted according to a format string. - - :param fmt: the format string. - - Usage:: - - >>> arrow.utcnow().format('YYYY-MM-DD HH:mm:ss ZZ') - '2013-05-09 03:56:47 -00:00' - - >>> arrow.utcnow().format('X') - '1368071882' - - >>> arrow.utcnow().format('MMMM DD, YYYY') - 'May 09, 2013' - - >>> arrow.utcnow().format() - '2013-05-09 03:56:47 -00:00' - - """ - - return formatter.DateTimeFormatter(locale).format(self._datetime, fmt) - - def humanize( - self, other=None, locale="en_us", only_distance=False, granularity="auto" - ): - """Returns a localized, humanized representation of a relative difference in time. - - :param other: (optional) an :class:`Arrow ` or ``datetime`` object. - Defaults to now in the current :class:`Arrow ` object's timezone. - :param locale: (optional) a ``str`` specifying a locale. Defaults to 'en_us'. - :param only_distance: (optional) returns only time difference eg: "11 seconds" without "in" or "ago" part. - :param granularity: (optional) defines the precision of the output. Set it to strings 'second', 'minute', - 'hour', 'day', 'week', 'month' or 'year' or a list of any combination of these strings - - Usage:: - - >>> earlier = arrow.utcnow().shift(hours=-2) - >>> earlier.humanize() - '2 hours ago' - - >>> later = earlier.shift(hours=4) - >>> later.humanize(earlier) - 'in 4 hours' - - """ - - locale_name = locale - locale = locales.get_locale(locale) - - if other is None: - utc = datetime.utcnow().replace(tzinfo=dateutil_tz.tzutc()) - dt = utc.astimezone(self._datetime.tzinfo) - - elif isinstance(other, Arrow): - dt = other._datetime - - elif isinstance(other, datetime): - if other.tzinfo is None: - dt = other.replace(tzinfo=self._datetime.tzinfo) - else: - dt = other.astimezone(self._datetime.tzinfo) - - else: - raise TypeError( - "Invalid 'other' argument of type '{}'. " - "Argument must be of type None, Arrow, or datetime.".format( - type(other).__name__ - ) - ) - - if isinstance(granularity, list) and len(granularity) == 1: - granularity = granularity[0] - - delta = int(round(util.total_seconds(self._datetime - dt))) - sign = -1 if delta < 0 else 1 - diff = abs(delta) - delta = diff - - try: - if granularity == "auto": - if diff < 10: - return locale.describe("now", only_distance=only_distance) - - if diff < 45: - seconds = sign * delta - return locale.describe( - "seconds", seconds, only_distance=only_distance - ) - - elif diff < 90: - return locale.describe("minute", sign, only_distance=only_distance) - elif diff < 2700: - minutes = sign * int(max(delta / 60, 2)) - return locale.describe( - "minutes", minutes, only_distance=only_distance - ) - - elif diff < 5400: - return locale.describe("hour", sign, only_distance=only_distance) - elif diff < 79200: - hours = sign * int(max(delta / 3600, 2)) - return locale.describe("hours", hours, only_distance=only_distance) - - # anything less than 48 hours should be 1 day - elif diff < 172800: - return locale.describe("day", sign, only_distance=only_distance) - elif diff < 554400: - days = sign * int(max(delta / 86400, 2)) - return locale.describe("days", days, only_distance=only_distance) - - elif diff < 907200: - return locale.describe("week", sign, only_distance=only_distance) - elif diff < 2419200: - weeks = sign * int(max(delta / 604800, 2)) - return locale.describe("weeks", weeks, only_distance=only_distance) - - elif diff < 3888000: - return locale.describe("month", sign, only_distance=only_distance) - elif diff < 29808000: - self_months = self._datetime.year * 12 + self._datetime.month - other_months = dt.year * 12 + dt.month - - months = sign * int(max(abs(other_months - self_months), 2)) - - return locale.describe( - "months", months, only_distance=only_distance - ) - - elif diff < 47260800: - return locale.describe("year", sign, only_distance=only_distance) - else: - years = sign * int(max(delta / 31536000, 2)) - return locale.describe("years", years, only_distance=only_distance) - - elif util.isstr(granularity): - if granularity == "second": - delta = sign * delta - if abs(delta) < 2: - return locale.describe("now", only_distance=only_distance) - elif granularity == "minute": - delta = sign * delta / self._SECS_PER_MINUTE - elif granularity == "hour": - delta = sign * delta / self._SECS_PER_HOUR - elif granularity == "day": - delta = sign * delta / self._SECS_PER_DAY - elif granularity == "week": - delta = sign * delta / self._SECS_PER_WEEK - elif granularity == "month": - delta = sign * delta / self._SECS_PER_MONTH - elif granularity == "year": - delta = sign * delta / self._SECS_PER_YEAR - else: - raise AttributeError( - "Invalid level of granularity. Please select between 'second', 'minute', 'hour', 'day', 'week', 'month' or 'year'" - ) - - if trunc(abs(delta)) != 1: - granularity += "s" - return locale.describe(granularity, delta, only_distance=only_distance) - - else: - timeframes = [] - if "year" in granularity: - years = sign * delta / self._SECS_PER_YEAR - delta %= self._SECS_PER_YEAR - timeframes.append(["year", years]) - - if "month" in granularity: - months = sign * delta / self._SECS_PER_MONTH - delta %= self._SECS_PER_MONTH - timeframes.append(["month", months]) - - if "week" in granularity: - weeks = sign * delta / self._SECS_PER_WEEK - delta %= self._SECS_PER_WEEK - timeframes.append(["week", weeks]) - - if "day" in granularity: - days = sign * delta / self._SECS_PER_DAY - delta %= self._SECS_PER_DAY - timeframes.append(["day", days]) - - if "hour" in granularity: - hours = sign * delta / self._SECS_PER_HOUR - delta %= self._SECS_PER_HOUR - timeframes.append(["hour", hours]) - - if "minute" in granularity: - minutes = sign * delta / self._SECS_PER_MINUTE - delta %= self._SECS_PER_MINUTE - timeframes.append(["minute", minutes]) - - if "second" in granularity: - seconds = sign * delta - timeframes.append(["second", seconds]) - - if len(timeframes) < len(granularity): - raise AttributeError( - "Invalid level of granularity. " - "Please select between 'second', 'minute', 'hour', 'day', 'week', 'month' or 'year'." - ) - - for tf in timeframes: - # Make granularity plural if the delta is not equal to 1 - if trunc(abs(tf[1])) != 1: - tf[0] += "s" - return locale.describe_multi(timeframes, only_distance=only_distance) - - except KeyError as e: - raise ValueError( - "Humanization of the {} granularity is not currently translated in the '{}' locale. " - "Please consider making a contribution to this locale.".format( - e, locale_name - ) - ) - - # query functions - - def is_between(self, start, end, bounds="()"): - """Returns a boolean denoting whether the specified date and time is between - the start and end dates and times. - - :param start: an :class:`Arrow ` object. - :param end: an :class:`Arrow ` object. - :param bounds: (optional) a ``str`` of either '()', '(]', '[)', or '[]' that specifies - whether to include or exclude the start and end values in the range. '(' excludes - the start, '[' includes the start, ')' excludes the end, and ']' includes the end. - If the bounds are not specified, the default bound '()' is used. - - Usage:: - - >>> start = arrow.get(datetime(2013, 5, 5, 12, 30, 10)) - >>> end = arrow.get(datetime(2013, 5, 5, 12, 30, 36)) - >>> arrow.get(datetime(2013, 5, 5, 12, 30, 27)).is_between(start, end) - True - - >>> start = arrow.get(datetime(2013, 5, 5)) - >>> end = arrow.get(datetime(2013, 5, 8)) - >>> arrow.get(datetime(2013, 5, 8)).is_between(start, end, '[]') - True - - >>> start = arrow.get(datetime(2013, 5, 5)) - >>> end = arrow.get(datetime(2013, 5, 8)) - >>> arrow.get(datetime(2013, 5, 8)).is_between(start, end, '[)') - False - - """ - - util.validate_bounds(bounds) - - if not isinstance(start, Arrow): - raise TypeError( - "Can't parse start date argument type of '{}'".format(type(start)) - ) - - if not isinstance(end, Arrow): - raise TypeError( - "Can't parse end date argument type of '{}'".format(type(end)) - ) - - include_start = bounds[0] == "[" - include_end = bounds[1] == "]" - - target_timestamp = self.float_timestamp - start_timestamp = start.float_timestamp - end_timestamp = end.float_timestamp - - if include_start and include_end: - return ( - target_timestamp >= start_timestamp - and target_timestamp <= end_timestamp - ) - elif include_start and not include_end: - return ( - target_timestamp >= start_timestamp and target_timestamp < end_timestamp - ) - elif not include_start and include_end: - return ( - target_timestamp > start_timestamp and target_timestamp <= end_timestamp - ) - else: - return ( - target_timestamp > start_timestamp and target_timestamp < end_timestamp - ) - - # datetime methods - - def date(self): - """Returns a ``date`` object with the same year, month and day. - - Usage:: - - >>> arrow.utcnow().date() - datetime.date(2019, 1, 23) - - """ - - return self._datetime.date() - - def time(self): - """Returns a ``time`` object with the same hour, minute, second, microsecond. - - Usage:: - - >>> arrow.utcnow().time() - datetime.time(12, 15, 34, 68352) - - """ - - return self._datetime.time() - - def timetz(self): - """Returns a ``time`` object with the same hour, minute, second, microsecond and - tzinfo. - - Usage:: - - >>> arrow.utcnow().timetz() - datetime.time(12, 5, 18, 298893, tzinfo=tzutc()) - - """ - - return self._datetime.timetz() - - def astimezone(self, tz): - """Returns a ``datetime`` object, converted to the specified timezone. - - :param tz: a ``tzinfo`` object. - - Usage:: - - >>> pacific=arrow.now('US/Pacific') - >>> nyc=arrow.now('America/New_York').tzinfo - >>> pacific.astimezone(nyc) - datetime.datetime(2019, 1, 20, 10, 24, 22, 328172, tzinfo=tzfile('/usr/share/zoneinfo/America/New_York')) - - """ - - return self._datetime.astimezone(tz) - - def utcoffset(self): - """Returns a ``timedelta`` object representing the whole number of minutes difference from - UTC time. - - Usage:: - - >>> arrow.now('US/Pacific').utcoffset() - datetime.timedelta(-1, 57600) - - """ - - return self._datetime.utcoffset() - - def dst(self): - """Returns the daylight savings time adjustment. - - Usage:: - - >>> arrow.utcnow().dst() - datetime.timedelta(0) - - """ - - return self._datetime.dst() - - def timetuple(self): - """Returns a ``time.struct_time``, in the current timezone. - - Usage:: - - >>> arrow.utcnow().timetuple() - time.struct_time(tm_year=2019, tm_mon=1, tm_mday=20, tm_hour=15, tm_min=17, tm_sec=8, tm_wday=6, tm_yday=20, tm_isdst=0) - - """ - - return self._datetime.timetuple() - - def utctimetuple(self): - """Returns a ``time.struct_time``, in UTC time. - - Usage:: - - >>> arrow.utcnow().utctimetuple() - time.struct_time(tm_year=2019, tm_mon=1, tm_mday=19, tm_hour=21, tm_min=41, tm_sec=7, tm_wday=5, tm_yday=19, tm_isdst=0) - - """ - - return self._datetime.utctimetuple() - - def toordinal(self): - """Returns the proleptic Gregorian ordinal of the date. - - Usage:: - - >>> arrow.utcnow().toordinal() - 737078 - - """ - - return self._datetime.toordinal() - - def weekday(self): - """Returns the day of the week as an integer (0-6). - - Usage:: - - >>> arrow.utcnow().weekday() - 5 - - """ - - return self._datetime.weekday() - - def isoweekday(self): - """Returns the ISO day of the week as an integer (1-7). - - Usage:: - - >>> arrow.utcnow().isoweekday() - 6 - - """ - - return self._datetime.isoweekday() - - def isocalendar(self): - """Returns a 3-tuple, (ISO year, ISO week number, ISO weekday). - - Usage:: - - >>> arrow.utcnow().isocalendar() - (2019, 3, 6) - - """ - - return self._datetime.isocalendar() - - def isoformat(self, sep="T"): - """Returns an ISO 8601 formatted representation of the date and time. - - Usage:: - - >>> arrow.utcnow().isoformat() - '2019-01-19T18:30:52.442118+00:00' - - """ - - return self._datetime.isoformat(sep) - - def ctime(self): - """Returns a ctime formatted representation of the date and time. - - Usage:: - - >>> arrow.utcnow().ctime() - 'Sat Jan 19 18:26:50 2019' - - """ - - return self._datetime.ctime() - - def strftime(self, format): - """Formats in the style of ``datetime.strftime``. - - :param format: the format string. - - Usage:: - - >>> arrow.utcnow().strftime('%d-%m-%Y %H:%M:%S') - '23-01-2019 12:28:17' - - """ - - return self._datetime.strftime(format) - - def for_json(self): - """Serializes for the ``for_json`` protocol of simplejson. - - Usage:: - - >>> arrow.utcnow().for_json() - '2019-01-19T18:25:36.760079+00:00' - - """ - - return self.isoformat() - - # math - - def __add__(self, other): - - if isinstance(other, (timedelta, relativedelta)): - return self.fromdatetime(self._datetime + other, self._datetime.tzinfo) - - return NotImplemented - - def __radd__(self, other): - return self.__add__(other) - - def __sub__(self, other): - - if isinstance(other, (timedelta, relativedelta)): - return self.fromdatetime(self._datetime - other, self._datetime.tzinfo) - - elif isinstance(other, datetime): - return self._datetime - other - - elif isinstance(other, Arrow): - return self._datetime - other._datetime - - return NotImplemented - - def __rsub__(self, other): - - if isinstance(other, datetime): - return other - self._datetime - - return NotImplemented - - # comparisons - - def __eq__(self, other): - - if not isinstance(other, (Arrow, datetime)): - return False - - return self._datetime == self._get_datetime(other) - - def __ne__(self, other): - - if not isinstance(other, (Arrow, datetime)): - return True - - return not self.__eq__(other) - - def __gt__(self, other): - - if not isinstance(other, (Arrow, datetime)): - return NotImplemented - - return self._datetime > self._get_datetime(other) - - def __ge__(self, other): - - if not isinstance(other, (Arrow, datetime)): - return NotImplemented - - return self._datetime >= self._get_datetime(other) - - def __lt__(self, other): - - if not isinstance(other, (Arrow, datetime)): - return NotImplemented - - return self._datetime < self._get_datetime(other) - - def __le__(self, other): - - if not isinstance(other, (Arrow, datetime)): - return NotImplemented - - return self._datetime <= self._get_datetime(other) - - def __cmp__(self, other): - if sys.version_info[0] < 3: # pragma: no cover - if not isinstance(other, (Arrow, datetime)): - raise TypeError( - "can't compare '{}' to '{}'".format(type(self), type(other)) - ) - - # internal methods - - @staticmethod - def _get_tzinfo(tz_expr): - - if tz_expr is None: - return dateutil_tz.tzutc() - if isinstance(tz_expr, dt_tzinfo): - return tz_expr - else: - try: - return parser.TzinfoParser.parse(tz_expr) - except parser.ParserError: - raise ValueError("'{}' not recognized as a timezone".format(tz_expr)) - - @classmethod - def _get_datetime(cls, expr): - """Get datetime object for a specified expression.""" - if isinstance(expr, Arrow): - return expr.datetime - elif isinstance(expr, datetime): - return expr - elif util.is_timestamp(expr): - timestamp = float(expr) - return cls.utcfromtimestamp(timestamp).datetime - else: - raise ValueError( - "'{}' not recognized as a datetime or timestamp.".format(expr) - ) - - @classmethod - def _get_frames(cls, name): - - if name in cls._ATTRS: - return name, "{}s".format(name), 1 - elif name[-1] == "s" and name[:-1] in cls._ATTRS: - return name[:-1], name, 1 - elif name in ["week", "weeks"]: - return "week", "weeks", 1 - elif name in ["quarter", "quarters"]: - return "quarter", "months", 3 - - supported = ", ".join( - [ - "year(s)", - "month(s)", - "day(s)", - "hour(s)", - "minute(s)", - "second(s)", - "microsecond(s)", - "week(s)", - "quarter(s)", - ] - ) - raise AttributeError( - "range/span over frame {} not supported. Supported frames: {}".format( - name, supported - ) - ) - - @classmethod - def _get_iteration_params(cls, end, limit): - - if end is None: - - if limit is None: - raise ValueError("one of 'end' or 'limit' is required") - - return cls.max, limit - - else: - if limit is None: - return end, sys.maxsize - return end, limit - - @staticmethod - def _is_last_day_of_month(date): - return date.day == calendar.monthrange(date.year, date.month)[1] - - -Arrow.min = Arrow.fromdatetime(datetime.min) -Arrow.max = Arrow.fromdatetime(datetime.max) diff --git a/client/ayon_core/vendor/python/python_2/arrow/constants.py b/client/ayon_core/vendor/python/python_2/arrow/constants.py deleted file mode 100644 index 81e37b26de..0000000000 --- a/client/ayon_core/vendor/python/python_2/arrow/constants.py +++ /dev/null @@ -1,9 +0,0 @@ -# -*- coding: utf-8 -*- - -# Output of time.mktime(datetime.max.timetuple()) on macOS -# This value must be hardcoded for compatibility with Windows -# Platform-independent max timestamps are hard to form -# https://stackoverflow.com/q/46133223 -MAX_TIMESTAMP = 253402318799.0 -MAX_TIMESTAMP_MS = MAX_TIMESTAMP * 1000 -MAX_TIMESTAMP_US = MAX_TIMESTAMP * 1000000 diff --git a/client/ayon_core/vendor/python/python_2/arrow/factory.py b/client/ayon_core/vendor/python/python_2/arrow/factory.py deleted file mode 100644 index 05933e8151..0000000000 --- a/client/ayon_core/vendor/python/python_2/arrow/factory.py +++ /dev/null @@ -1,301 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Implements the :class:`ArrowFactory ` class, -providing factory methods for common :class:`Arrow ` -construction scenarios. - -""" - -from __future__ import absolute_import - -import calendar -from datetime import date, datetime -from datetime import tzinfo as dt_tzinfo -from time import struct_time - -from dateutil import tz as dateutil_tz - -from arrow import parser -from arrow.arrow import Arrow -from arrow.util import is_timestamp, iso_to_gregorian, isstr - - -class ArrowFactory(object): - """A factory for generating :class:`Arrow ` objects. - - :param type: (optional) the :class:`Arrow `-based class to construct from. - Defaults to :class:`Arrow `. - - """ - - def __init__(self, type=Arrow): - self.type = type - - def get(self, *args, **kwargs): - """Returns an :class:`Arrow ` object based on flexible inputs. - - :param locale: (optional) a ``str`` specifying a locale for the parser. Defaults to 'en_us'. - :param tzinfo: (optional) a :ref:`timezone expression ` or tzinfo object. - Replaces the timezone unless using an input form that is explicitly UTC or specifies - the timezone in a positional argument. Defaults to UTC. - :param normalize_whitespace: (optional) a ``bool`` specifying whether or not to normalize - redundant whitespace (spaces, tabs, and newlines) in a datetime string before parsing. - Defaults to false. - - Usage:: - - >>> import arrow - - **No inputs** to get current UTC time:: - - >>> arrow.get() - - - **None** to also get current UTC time:: - - >>> arrow.get(None) - - - **One** :class:`Arrow ` object, to get a copy. - - >>> arw = arrow.utcnow() - >>> arrow.get(arw) - - - **One** ``float`` or ``int``, convertible to a floating-point timestamp, to get - that timestamp in UTC:: - - >>> arrow.get(1367992474.293378) - - - >>> arrow.get(1367992474) - - - **One** ISO 8601-formatted ``str``, to parse it:: - - >>> arrow.get('2013-09-29T01:26:43.830580') - - - **One** ISO 8601-formatted ``str``, in basic format, to parse it:: - - >>> arrow.get('20160413T133656.456289') - - - **One** ``tzinfo``, to get the current time **converted** to that timezone:: - - >>> arrow.get(tz.tzlocal()) - - - **One** naive ``datetime``, to get that datetime in UTC:: - - >>> arrow.get(datetime(2013, 5, 5)) - - - **One** aware ``datetime``, to get that datetime:: - - >>> arrow.get(datetime(2013, 5, 5, tzinfo=tz.tzlocal())) - - - **One** naive ``date``, to get that date in UTC:: - - >>> arrow.get(date(2013, 5, 5)) - - - **One** time.struct time:: - - >>> arrow.get(gmtime(0)) - - - **One** iso calendar ``tuple``, to get that week date in UTC:: - - >>> arrow.get((2013, 18, 7)) - - - **Two** arguments, a naive or aware ``datetime``, and a replacement - :ref:`timezone expression `:: - - >>> arrow.get(datetime(2013, 5, 5), 'US/Pacific') - - - **Two** arguments, a naive ``date``, and a replacement - :ref:`timezone expression `:: - - >>> arrow.get(date(2013, 5, 5), 'US/Pacific') - - - **Two** arguments, both ``str``, to parse the first according to the format of the second:: - - >>> arrow.get('2013-05-05 12:30:45 America/Chicago', 'YYYY-MM-DD HH:mm:ss ZZZ') - - - **Two** arguments, first a ``str`` to parse and second a ``list`` of formats to try:: - - >>> arrow.get('2013-05-05 12:30:45', ['MM/DD/YYYY', 'YYYY-MM-DD HH:mm:ss']) - - - **Three or more** arguments, as for the constructor of a ``datetime``:: - - >>> arrow.get(2013, 5, 5, 12, 30, 45) - - - """ - - arg_count = len(args) - locale = kwargs.pop("locale", "en_us") - tz = kwargs.get("tzinfo", None) - normalize_whitespace = kwargs.pop("normalize_whitespace", False) - - # if kwargs given, send to constructor unless only tzinfo provided - if len(kwargs) > 1: - arg_count = 3 - - # tzinfo kwarg is not provided - if len(kwargs) == 1 and tz is None: - arg_count = 3 - - # () -> now, @ utc. - if arg_count == 0: - if isstr(tz): - tz = parser.TzinfoParser.parse(tz) - return self.type.now(tz) - - if isinstance(tz, dt_tzinfo): - return self.type.now(tz) - - return self.type.utcnow() - - if arg_count == 1: - arg = args[0] - - # (None) -> now, @ utc. - if arg is None: - return self.type.utcnow() - - # try (int, float) -> from timestamp with tz - elif not isstr(arg) and is_timestamp(arg): - if tz is None: - # set to UTC by default - tz = dateutil_tz.tzutc() - return self.type.fromtimestamp(arg, tzinfo=tz) - - # (Arrow) -> from the object's datetime. - elif isinstance(arg, Arrow): - return self.type.fromdatetime(arg.datetime) - - # (datetime) -> from datetime. - elif isinstance(arg, datetime): - return self.type.fromdatetime(arg) - - # (date) -> from date. - elif isinstance(arg, date): - return self.type.fromdate(arg) - - # (tzinfo) -> now, @ tzinfo. - elif isinstance(arg, dt_tzinfo): - return self.type.now(arg) - - # (str) -> parse. - elif isstr(arg): - dt = parser.DateTimeParser(locale).parse_iso(arg, normalize_whitespace) - return self.type.fromdatetime(dt, tz) - - # (struct_time) -> from struct_time - elif isinstance(arg, struct_time): - return self.type.utcfromtimestamp(calendar.timegm(arg)) - - # (iso calendar) -> convert then from date - elif isinstance(arg, tuple) and len(arg) == 3: - dt = iso_to_gregorian(*arg) - return self.type.fromdate(dt) - - else: - raise TypeError( - "Can't parse single argument of type '{}'".format(type(arg)) - ) - - elif arg_count == 2: - - arg_1, arg_2 = args[0], args[1] - - if isinstance(arg_1, datetime): - - # (datetime, tzinfo/str) -> fromdatetime replace tzinfo. - if isinstance(arg_2, dt_tzinfo) or isstr(arg_2): - return self.type.fromdatetime(arg_1, arg_2) - else: - raise TypeError( - "Can't parse two arguments of types 'datetime', '{}'".format( - type(arg_2) - ) - ) - - elif isinstance(arg_1, date): - - # (date, tzinfo/str) -> fromdate replace tzinfo. - if isinstance(arg_2, dt_tzinfo) or isstr(arg_2): - return self.type.fromdate(arg_1, tzinfo=arg_2) - else: - raise TypeError( - "Can't parse two arguments of types 'date', '{}'".format( - type(arg_2) - ) - ) - - # (str, format) -> parse. - elif isstr(arg_1) and (isstr(arg_2) or isinstance(arg_2, list)): - dt = parser.DateTimeParser(locale).parse( - args[0], args[1], normalize_whitespace - ) - return self.type.fromdatetime(dt, tzinfo=tz) - - else: - raise TypeError( - "Can't parse two arguments of types '{}' and '{}'".format( - type(arg_1), type(arg_2) - ) - ) - - # 3+ args -> datetime-like via constructor. - else: - return self.type(*args, **kwargs) - - def utcnow(self): - """Returns an :class:`Arrow ` object, representing "now" in UTC time. - - Usage:: - - >>> import arrow - >>> arrow.utcnow() - - """ - - return self.type.utcnow() - - def now(self, tz=None): - """Returns an :class:`Arrow ` object, representing "now" in the given - timezone. - - :param tz: (optional) A :ref:`timezone expression `. Defaults to local time. - - Usage:: - - >>> import arrow - >>> arrow.now() - - - >>> arrow.now('US/Pacific') - - - >>> arrow.now('+02:00') - - - >>> arrow.now('local') - - """ - - if tz is None: - tz = dateutil_tz.tzlocal() - elif not isinstance(tz, dt_tzinfo): - tz = parser.TzinfoParser.parse(tz) - - return self.type.now(tz) diff --git a/client/ayon_core/vendor/python/python_2/arrow/formatter.py b/client/ayon_core/vendor/python/python_2/arrow/formatter.py deleted file mode 100644 index 9f9d7a44da..0000000000 --- a/client/ayon_core/vendor/python/python_2/arrow/formatter.py +++ /dev/null @@ -1,139 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, division - -import calendar -import re - -from dateutil import tz as dateutil_tz - -from arrow import locales, util - -FORMAT_ATOM = "YYYY-MM-DD HH:mm:ssZZ" -FORMAT_COOKIE = "dddd, DD-MMM-YYYY HH:mm:ss ZZZ" -FORMAT_RFC822 = "ddd, DD MMM YY HH:mm:ss Z" -FORMAT_RFC850 = "dddd, DD-MMM-YY HH:mm:ss ZZZ" -FORMAT_RFC1036 = "ddd, DD MMM YY HH:mm:ss Z" -FORMAT_RFC1123 = "ddd, DD MMM YYYY HH:mm:ss Z" -FORMAT_RFC2822 = "ddd, DD MMM YYYY HH:mm:ss Z" -FORMAT_RFC3339 = "YYYY-MM-DD HH:mm:ssZZ" -FORMAT_RSS = "ddd, DD MMM YYYY HH:mm:ss Z" -FORMAT_W3C = "YYYY-MM-DD HH:mm:ssZZ" - - -class DateTimeFormatter(object): - - # This pattern matches characters enclosed in square brackets are matched as - # an atomic group. For more info on atomic groups and how to they are - # emulated in Python's re library, see https://stackoverflow.com/a/13577411/2701578 - - _FORMAT_RE = re.compile( - r"(\[(?:(?=(?P[^]]))(?P=literal))*\]|YYY?Y?|MM?M?M?|Do|DD?D?D?|d?dd?d?|HH?|hh?|mm?|ss?|SS?S?S?S?S?|ZZ?Z?|a|A|X|x|W)" - ) - - def __init__(self, locale="en_us"): - - self.locale = locales.get_locale(locale) - - def format(cls, dt, fmt): - - return cls._FORMAT_RE.sub(lambda m: cls._format_token(dt, m.group(0)), fmt) - - def _format_token(self, dt, token): - - if token and token.startswith("[") and token.endswith("]"): - return token[1:-1] - - if token == "YYYY": - return self.locale.year_full(dt.year) - if token == "YY": - return self.locale.year_abbreviation(dt.year) - - if token == "MMMM": - return self.locale.month_name(dt.month) - if token == "MMM": - return self.locale.month_abbreviation(dt.month) - if token == "MM": - return "{:02d}".format(dt.month) - if token == "M": - return str(dt.month) - - if token == "DDDD": - return "{:03d}".format(dt.timetuple().tm_yday) - if token == "DDD": - return str(dt.timetuple().tm_yday) - if token == "DD": - return "{:02d}".format(dt.day) - if token == "D": - return str(dt.day) - - if token == "Do": - return self.locale.ordinal_number(dt.day) - - if token == "dddd": - return self.locale.day_name(dt.isoweekday()) - if token == "ddd": - return self.locale.day_abbreviation(dt.isoweekday()) - if token == "d": - return str(dt.isoweekday()) - - if token == "HH": - return "{:02d}".format(dt.hour) - if token == "H": - return str(dt.hour) - if token == "hh": - return "{:02d}".format(dt.hour if 0 < dt.hour < 13 else abs(dt.hour - 12)) - if token == "h": - return str(dt.hour if 0 < dt.hour < 13 else abs(dt.hour - 12)) - - if token == "mm": - return "{:02d}".format(dt.minute) - if token == "m": - return str(dt.minute) - - if token == "ss": - return "{:02d}".format(dt.second) - if token == "s": - return str(dt.second) - - if token == "SSSSSS": - return str("{:06d}".format(int(dt.microsecond))) - if token == "SSSSS": - return str("{:05d}".format(int(dt.microsecond / 10))) - if token == "SSSS": - return str("{:04d}".format(int(dt.microsecond / 100))) - if token == "SSS": - return str("{:03d}".format(int(dt.microsecond / 1000))) - if token == "SS": - return str("{:02d}".format(int(dt.microsecond / 10000))) - if token == "S": - return str(int(dt.microsecond / 100000)) - - if token == "X": - # TODO: replace with a call to dt.timestamp() when we drop Python 2.7 - return str(calendar.timegm(dt.utctimetuple())) - - if token == "x": - # TODO: replace with a call to dt.timestamp() when we drop Python 2.7 - ts = calendar.timegm(dt.utctimetuple()) + (dt.microsecond / 1000000) - return str(int(ts * 1000000)) - - if token == "ZZZ": - return dt.tzname() - - if token in ["ZZ", "Z"]: - separator = ":" if token == "ZZ" else "" - tz = dateutil_tz.tzutc() if dt.tzinfo is None else dt.tzinfo - total_minutes = int(util.total_seconds(tz.utcoffset(dt)) / 60) - - sign = "+" if total_minutes >= 0 else "-" - total_minutes = abs(total_minutes) - hour, minute = divmod(total_minutes, 60) - - return "{}{:02d}{}{:02d}".format(sign, hour, separator, minute) - - if token in ("a", "A"): - return self.locale.meridian(dt.hour, token) - - if token == "W": - year, week, day = dt.isocalendar() - return "{}-W{:02d}-{}".format(year, week, day) diff --git a/client/ayon_core/vendor/python/python_2/arrow/locales.py b/client/ayon_core/vendor/python/python_2/arrow/locales.py deleted file mode 100644 index 6833da5a78..0000000000 --- a/client/ayon_core/vendor/python/python_2/arrow/locales.py +++ /dev/null @@ -1,4267 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, unicode_literals - -import inspect -import sys -from math import trunc - - -def get_locale(name): - """Returns an appropriate :class:`Locale ` - corresponding to an inpute locale name. - - :param name: the name of the locale. - - """ - - locale_cls = _locales.get(name.lower()) - - if locale_cls is None: - raise ValueError("Unsupported locale '{}'".format(name)) - - return locale_cls() - - -def get_locale_by_class_name(name): - """Returns an appropriate :class:`Locale ` - corresponding to an locale class name. - - :param name: the name of the locale class. - - """ - locale_cls = globals().get(name) - - if locale_cls is None: - raise ValueError("Unsupported locale '{}'".format(name)) - - return locale_cls() - - -# base locale type. - - -class Locale(object): - """ Represents locale-specific data and functionality. """ - - names = [] - - timeframes = { - "now": "", - "second": "", - "seconds": "", - "minute": "", - "minutes": "", - "hour": "", - "hours": "", - "day": "", - "days": "", - "week": "", - "weeks": "", - "month": "", - "months": "", - "year": "", - "years": "", - } - - meridians = {"am": "", "pm": "", "AM": "", "PM": ""} - - past = None - future = None - and_word = None - - month_names = [] - month_abbreviations = [] - - day_names = [] - day_abbreviations = [] - - ordinal_day_re = r"(\d+)" - - def __init__(self): - - self._month_name_to_ordinal = None - - def describe(self, timeframe, delta=0, only_distance=False): - """Describes a delta within a timeframe in plain language. - - :param timeframe: a string representing a timeframe. - :param delta: a quantity representing a delta in a timeframe. - :param only_distance: return only distance eg: "11 seconds" without "in" or "ago" keywords - """ - - humanized = self._format_timeframe(timeframe, delta) - if not only_distance: - humanized = self._format_relative(humanized, timeframe, delta) - - return humanized - - def describe_multi(self, timeframes, only_distance=False): - """Describes a delta within multiple timeframes in plain language. - - :param timeframes: a list of string, quantity pairs each representing a timeframe and delta. - :param only_distance: return only distance eg: "2 hours and 11 seconds" without "in" or "ago" keywords - """ - - humanized = "" - for index, (timeframe, delta) in enumerate(timeframes): - humanized += self._format_timeframe(timeframe, delta) - if index == len(timeframes) - 2 and self.and_word: - humanized += " " + self.and_word + " " - elif index < len(timeframes) - 1: - humanized += " " - - if not only_distance: - humanized = self._format_relative(humanized, timeframe, delta) - - return humanized - - def day_name(self, day): - """Returns the day name for a specified day of the week. - - :param day: the ``int`` day of the week (1-7). - - """ - - return self.day_names[day] - - def day_abbreviation(self, day): - """Returns the day abbreviation for a specified day of the week. - - :param day: the ``int`` day of the week (1-7). - - """ - - return self.day_abbreviations[day] - - def month_name(self, month): - """Returns the month name for a specified month of the year. - - :param month: the ``int`` month of the year (1-12). - - """ - - return self.month_names[month] - - def month_abbreviation(self, month): - """Returns the month abbreviation for a specified month of the year. - - :param month: the ``int`` month of the year (1-12). - - """ - - return self.month_abbreviations[month] - - def month_number(self, name): - """Returns the month number for a month specified by name or abbreviation. - - :param name: the month name or abbreviation. - - """ - - if self._month_name_to_ordinal is None: - self._month_name_to_ordinal = self._name_to_ordinal(self.month_names) - self._month_name_to_ordinal.update( - self._name_to_ordinal(self.month_abbreviations) - ) - - return self._month_name_to_ordinal.get(name) - - def year_full(self, year): - """Returns the year for specific locale if available - - :param name: the ``int`` year (4-digit) - """ - return "{:04d}".format(year) - - def year_abbreviation(self, year): - """Returns the year for specific locale if available - - :param name: the ``int`` year (4-digit) - """ - return "{:04d}".format(year)[2:] - - def meridian(self, hour, token): - """Returns the meridian indicator for a specified hour and format token. - - :param hour: the ``int`` hour of the day. - :param token: the format token. - """ - - if token == "a": - return self.meridians["am"] if hour < 12 else self.meridians["pm"] - if token == "A": - return self.meridians["AM"] if hour < 12 else self.meridians["PM"] - - def ordinal_number(self, n): - """Returns the ordinal format of a given integer - - :param n: an integer - """ - return self._ordinal_number(n) - - def _ordinal_number(self, n): - return "{}".format(n) - - def _name_to_ordinal(self, lst): - return dict(map(lambda i: (i[1].lower(), i[0] + 1), enumerate(lst[1:]))) - - def _format_timeframe(self, timeframe, delta): - return self.timeframes[timeframe].format(trunc(abs(delta))) - - def _format_relative(self, humanized, timeframe, delta): - - if timeframe == "now": - return humanized - - direction = self.past if delta < 0 else self.future - - return direction.format(humanized) - - -# base locale type implementations. - - -class EnglishLocale(Locale): - - names = [ - "en", - "en_us", - "en_gb", - "en_au", - "en_be", - "en_jp", - "en_za", - "en_ca", - "en_ph", - ] - - past = "{0} ago" - future = "in {0}" - and_word = "and" - - timeframes = { - "now": "just now", - "second": "a second", - "seconds": "{0} seconds", - "minute": "a minute", - "minutes": "{0} minutes", - "hour": "an hour", - "hours": "{0} hours", - "day": "a day", - "days": "{0} days", - "week": "a week", - "weeks": "{0} weeks", - "month": "a month", - "months": "{0} months", - "year": "a year", - "years": "{0} years", - } - - meridians = {"am": "am", "pm": "pm", "AM": "AM", "PM": "PM"} - - month_names = [ - "", - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December", - ] - month_abbreviations = [ - "", - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", - ] - - day_names = [ - "", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", - "Sunday", - ] - day_abbreviations = ["", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] - - ordinal_day_re = r"((?P[2-3]?1(?=st)|[2-3]?2(?=nd)|[2-3]?3(?=rd)|[1-3]?[04-9](?=th)|1[1-3](?=th))(st|nd|rd|th))" - - def _ordinal_number(self, n): - if n % 100 not in (11, 12, 13): - remainder = abs(n) % 10 - if remainder == 1: - return "{}st".format(n) - elif remainder == 2: - return "{}nd".format(n) - elif remainder == 3: - return "{}rd".format(n) - return "{}th".format(n) - - def describe(self, timeframe, delta=0, only_distance=False): - """Describes a delta within a timeframe in plain language. - - :param timeframe: a string representing a timeframe. - :param delta: a quantity representing a delta in a timeframe. - :param only_distance: return only distance eg: "11 seconds" without "in" or "ago" keywords - """ - - humanized = super(EnglishLocale, self).describe(timeframe, delta, only_distance) - if only_distance and timeframe == "now": - humanized = "instantly" - - return humanized - - -class ItalianLocale(Locale): - names = ["it", "it_it"] - past = "{0} fa" - future = "tra {0}" - and_word = "e" - - timeframes = { - "now": "adesso", - "second": "un secondo", - "seconds": "{0} qualche secondo", - "minute": "un minuto", - "minutes": "{0} minuti", - "hour": "un'ora", - "hours": "{0} ore", - "day": "un giorno", - "days": "{0} giorni", - "week": "una settimana,", - "weeks": "{0} settimane", - "month": "un mese", - "months": "{0} mesi", - "year": "un anno", - "years": "{0} anni", - } - - month_names = [ - "", - "gennaio", - "febbraio", - "marzo", - "aprile", - "maggio", - "giugno", - "luglio", - "agosto", - "settembre", - "ottobre", - "novembre", - "dicembre", - ] - month_abbreviations = [ - "", - "gen", - "feb", - "mar", - "apr", - "mag", - "giu", - "lug", - "ago", - "set", - "ott", - "nov", - "dic", - ] - - day_names = [ - "", - "lunedì", - "martedì", - "mercoledì", - "giovedì", - "venerdì", - "sabato", - "domenica", - ] - day_abbreviations = ["", "lun", "mar", "mer", "gio", "ven", "sab", "dom"] - - ordinal_day_re = r"((?P[1-3]?[0-9](?=[ºª]))[ºª])" - - def _ordinal_number(self, n): - return "{}º".format(n) - - -class SpanishLocale(Locale): - names = ["es", "es_es"] - past = "hace {0}" - future = "en {0}" - and_word = "y" - - timeframes = { - "now": "ahora", - "second": "un segundo", - "seconds": "{0} segundos", - "minute": "un minuto", - "minutes": "{0} minutos", - "hour": "una hora", - "hours": "{0} horas", - "day": "un día", - "days": "{0} días", - "week": "una semana", - "weeks": "{0} semanas", - "month": "un mes", - "months": "{0} meses", - "year": "un año", - "years": "{0} años", - } - - meridians = {"am": "am", "pm": "pm", "AM": "AM", "PM": "PM"} - - month_names = [ - "", - "enero", - "febrero", - "marzo", - "abril", - "mayo", - "junio", - "julio", - "agosto", - "septiembre", - "octubre", - "noviembre", - "diciembre", - ] - month_abbreviations = [ - "", - "ene", - "feb", - "mar", - "abr", - "may", - "jun", - "jul", - "ago", - "sep", - "oct", - "nov", - "dic", - ] - - day_names = [ - "", - "lunes", - "martes", - "miércoles", - "jueves", - "viernes", - "sábado", - "domingo", - ] - day_abbreviations = ["", "lun", "mar", "mie", "jue", "vie", "sab", "dom"] - - ordinal_day_re = r"((?P[1-3]?[0-9](?=[ºª]))[ºª])" - - def _ordinal_number(self, n): - return "{}º".format(n) - - -class FrenchBaseLocale(Locale): - - past = "il y a {0}" - future = "dans {0}" - and_word = "et" - - timeframes = { - "now": "maintenant", - "second": "une seconde", - "seconds": "{0} quelques secondes", - "minute": "une minute", - "minutes": "{0} minutes", - "hour": "une heure", - "hours": "{0} heures", - "day": "un jour", - "days": "{0} jours", - "week": "une semaine", - "weeks": "{0} semaines", - "month": "un mois", - "months": "{0} mois", - "year": "un an", - "years": "{0} ans", - } - - month_names = [ - "", - "janvier", - "février", - "mars", - "avril", - "mai", - "juin", - "juillet", - "août", - "septembre", - "octobre", - "novembre", - "décembre", - ] - - day_names = [ - "", - "lundi", - "mardi", - "mercredi", - "jeudi", - "vendredi", - "samedi", - "dimanche", - ] - day_abbreviations = ["", "lun", "mar", "mer", "jeu", "ven", "sam", "dim"] - - ordinal_day_re = ( - r"((?P\b1(?=er\b)|[1-3]?[02-9](?=e\b)|[1-3]1(?=e\b))(er|e)\b)" - ) - - def _ordinal_number(self, n): - if abs(n) == 1: - return "{}er".format(n) - return "{}e".format(n) - - -class FrenchLocale(FrenchBaseLocale, Locale): - - names = ["fr", "fr_fr"] - - month_abbreviations = [ - "", - "janv", - "févr", - "mars", - "avr", - "mai", - "juin", - "juil", - "août", - "sept", - "oct", - "nov", - "déc", - ] - - -class FrenchCanadianLocale(FrenchBaseLocale, Locale): - - names = ["fr_ca"] - - month_abbreviations = [ - "", - "janv", - "févr", - "mars", - "avr", - "mai", - "juin", - "juill", - "août", - "sept", - "oct", - "nov", - "déc", - ] - - -class GreekLocale(Locale): - - names = ["el", "el_gr"] - - past = "{0} πριν" - future = "σε {0}" - and_word = "και" - - timeframes = { - "now": "τώρα", - "second": "ένα δεύτερο", - "seconds": "{0} δευτερόλεπτα", - "minute": "ένα λεπτό", - "minutes": "{0} λεπτά", - "hour": "μία ώρα", - "hours": "{0} ώρες", - "day": "μία μέρα", - "days": "{0} μέρες", - "month": "ένα μήνα", - "months": "{0} μήνες", - "year": "ένα χρόνο", - "years": "{0} χρόνια", - } - - month_names = [ - "", - "Ιανουαρίου", - "Φεβρουαρίου", - "Μαρτίου", - "Απριλίου", - "Μαΐου", - "Ιουνίου", - "Ιουλίου", - "Αυγούστου", - "Σεπτεμβρίου", - "Οκτωβρίου", - "Νοεμβρίου", - "Δεκεμβρίου", - ] - month_abbreviations = [ - "", - "Ιαν", - "Φεβ", - "Μαρ", - "Απρ", - "Μαϊ", - "Ιον", - "Ιολ", - "Αυγ", - "Σεπ", - "Οκτ", - "Νοε", - "Δεκ", - ] - - day_names = [ - "", - "Δευτέρα", - "Τρίτη", - "Τετάρτη", - "Πέμπτη", - "Παρασκευή", - "Σάββατο", - "Κυριακή", - ] - day_abbreviations = ["", "Δευ", "Τρι", "Τετ", "Πεμ", "Παρ", "Σαβ", "Κυρ"] - - -class JapaneseLocale(Locale): - - names = ["ja", "ja_jp"] - - past = "{0}前" - future = "{0}後" - - timeframes = { - "now": "現在", - "second": "二番目の", - "seconds": "{0}数秒", - "minute": "1分", - "minutes": "{0}分", - "hour": "1時間", - "hours": "{0}時間", - "day": "1日", - "days": "{0}日", - "week": "1週間", - "weeks": "{0}週間", - "month": "1ヶ月", - "months": "{0}ヶ月", - "year": "1年", - "years": "{0}年", - } - - month_names = [ - "", - "1月", - "2月", - "3月", - "4月", - "5月", - "6月", - "7月", - "8月", - "9月", - "10月", - "11月", - "12月", - ] - month_abbreviations = [ - "", - " 1", - " 2", - " 3", - " 4", - " 5", - " 6", - " 7", - " 8", - " 9", - "10", - "11", - "12", - ] - - day_names = ["", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日", "日曜日"] - day_abbreviations = ["", "月", "火", "水", "木", "金", "土", "日"] - - -class SwedishLocale(Locale): - - names = ["sv", "sv_se"] - - past = "för {0} sen" - future = "om {0}" - and_word = "och" - - timeframes = { - "now": "just nu", - "second": "en sekund", - "seconds": "{0} några sekunder", - "minute": "en minut", - "minutes": "{0} minuter", - "hour": "en timme", - "hours": "{0} timmar", - "day": "en dag", - "days": "{0} dagar", - "week": "en vecka", - "weeks": "{0} veckor", - "month": "en månad", - "months": "{0} månader", - "year": "ett år", - "years": "{0} år", - } - - month_names = [ - "", - "januari", - "februari", - "mars", - "april", - "maj", - "juni", - "juli", - "augusti", - "september", - "oktober", - "november", - "december", - ] - month_abbreviations = [ - "", - "jan", - "feb", - "mar", - "apr", - "maj", - "jun", - "jul", - "aug", - "sep", - "okt", - "nov", - "dec", - ] - - day_names = [ - "", - "måndag", - "tisdag", - "onsdag", - "torsdag", - "fredag", - "lördag", - "söndag", - ] - day_abbreviations = ["", "mån", "tis", "ons", "tor", "fre", "lör", "sön"] - - -class FinnishLocale(Locale): - - names = ["fi", "fi_fi"] - - # The finnish grammar is very complex, and its hard to convert - # 1-to-1 to something like English. - - past = "{0} sitten" - future = "{0} kuluttua" - - timeframes = { - "now": ["juuri nyt", "juuri nyt"], - "second": ["sekunti", "sekunti"], - "seconds": ["{0} muutama sekunti", "{0} muutaman sekunnin"], - "minute": ["minuutti", "minuutin"], - "minutes": ["{0} minuuttia", "{0} minuutin"], - "hour": ["tunti", "tunnin"], - "hours": ["{0} tuntia", "{0} tunnin"], - "day": ["päivä", "päivä"], - "days": ["{0} päivää", "{0} päivän"], - "month": ["kuukausi", "kuukauden"], - "months": ["{0} kuukautta", "{0} kuukauden"], - "year": ["vuosi", "vuoden"], - "years": ["{0} vuotta", "{0} vuoden"], - } - - # Months and days are lowercase in Finnish - month_names = [ - "", - "tammikuu", - "helmikuu", - "maaliskuu", - "huhtikuu", - "toukokuu", - "kesäkuu", - "heinäkuu", - "elokuu", - "syyskuu", - "lokakuu", - "marraskuu", - "joulukuu", - ] - - month_abbreviations = [ - "", - "tammi", - "helmi", - "maalis", - "huhti", - "touko", - "kesä", - "heinä", - "elo", - "syys", - "loka", - "marras", - "joulu", - ] - - day_names = [ - "", - "maanantai", - "tiistai", - "keskiviikko", - "torstai", - "perjantai", - "lauantai", - "sunnuntai", - ] - - day_abbreviations = ["", "ma", "ti", "ke", "to", "pe", "la", "su"] - - def _format_timeframe(self, timeframe, delta): - return ( - self.timeframes[timeframe][0].format(abs(delta)), - self.timeframes[timeframe][1].format(abs(delta)), - ) - - def _format_relative(self, humanized, timeframe, delta): - if timeframe == "now": - return humanized[0] - - direction = self.past if delta < 0 else self.future - which = 0 if delta < 0 else 1 - - return direction.format(humanized[which]) - - def _ordinal_number(self, n): - return "{}.".format(n) - - -class ChineseCNLocale(Locale): - - names = ["zh", "zh_cn"] - - past = "{0}前" - future = "{0}后" - - timeframes = { - "now": "刚才", - "second": "一秒", - "seconds": "{0}秒", - "minute": "1分钟", - "minutes": "{0}分钟", - "hour": "1小时", - "hours": "{0}小时", - "day": "1天", - "days": "{0}天", - "week": "一周", - "weeks": "{0}周", - "month": "1个月", - "months": "{0}个月", - "year": "1年", - "years": "{0}年", - } - - month_names = [ - "", - "一月", - "二月", - "三月", - "四月", - "五月", - "六月", - "七月", - "八月", - "九月", - "十月", - "十一月", - "十二月", - ] - month_abbreviations = [ - "", - " 1", - " 2", - " 3", - " 4", - " 5", - " 6", - " 7", - " 8", - " 9", - "10", - "11", - "12", - ] - - day_names = ["", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"] - day_abbreviations = ["", "一", "二", "三", "四", "五", "六", "日"] - - -class ChineseTWLocale(Locale): - - names = ["zh_tw"] - - past = "{0}前" - future = "{0}後" - and_word = "和" - - timeframes = { - "now": "剛才", - "second": "1秒", - "seconds": "{0}秒", - "minute": "1分鐘", - "minutes": "{0}分鐘", - "hour": "1小時", - "hours": "{0}小時", - "day": "1天", - "days": "{0}天", - "week": "1週", - "weeks": "{0}週", - "month": "1個月", - "months": "{0}個月", - "year": "1年", - "years": "{0}年", - } - - month_names = [ - "", - "1月", - "2月", - "3月", - "4月", - "5月", - "6月", - "7月", - "8月", - "9月", - "10月", - "11月", - "12月", - ] - month_abbreviations = [ - "", - " 1", - " 2", - " 3", - " 4", - " 5", - " 6", - " 7", - " 8", - " 9", - "10", - "11", - "12", - ] - - day_names = ["", "週一", "週二", "週三", "週四", "週五", "週六", "週日"] - day_abbreviations = ["", "一", "二", "三", "四", "五", "六", "日"] - - -class HongKongLocale(Locale): - - names = ["zh_hk"] - - past = "{0}前" - future = "{0}後" - - timeframes = { - "now": "剛才", - "second": "1秒", - "seconds": "{0}秒", - "minute": "1分鐘", - "minutes": "{0}分鐘", - "hour": "1小時", - "hours": "{0}小時", - "day": "1天", - "days": "{0}天", - "week": "1星期", - "weeks": "{0}星期", - "month": "1個月", - "months": "{0}個月", - "year": "1年", - "years": "{0}年", - } - - month_names = [ - "", - "1月", - "2月", - "3月", - "4月", - "5月", - "6月", - "7月", - "8月", - "9月", - "10月", - "11月", - "12月", - ] - month_abbreviations = [ - "", - " 1", - " 2", - " 3", - " 4", - " 5", - " 6", - " 7", - " 8", - " 9", - "10", - "11", - "12", - ] - - day_names = ["", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"] - day_abbreviations = ["", "一", "二", "三", "四", "五", "六", "日"] - - -class KoreanLocale(Locale): - - names = ["ko", "ko_kr"] - - past = "{0} 전" - future = "{0} 후" - - timeframes = { - "now": "지금", - "second": "1초", - "seconds": "{0}초", - "minute": "1분", - "minutes": "{0}분", - "hour": "한시간", - "hours": "{0}시간", - "day": "하루", - "days": "{0}일", - "week": "1주", - "weeks": "{0}주", - "month": "한달", - "months": "{0}개월", - "year": "1년", - "years": "{0}년", - } - - special_dayframes = { - -3: "그끄제", - -2: "그제", - -1: "어제", - 1: "내일", - 2: "모레", - 3: "글피", - 4: "그글피", - } - - special_yearframes = {-2: "제작년", -1: "작년", 1: "내년", 2: "내후년"} - - month_names = [ - "", - "1월", - "2월", - "3월", - "4월", - "5월", - "6월", - "7월", - "8월", - "9월", - "10월", - "11월", - "12월", - ] - month_abbreviations = [ - "", - " 1", - " 2", - " 3", - " 4", - " 5", - " 6", - " 7", - " 8", - " 9", - "10", - "11", - "12", - ] - - day_names = ["", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일", "일요일"] - day_abbreviations = ["", "월", "화", "수", "목", "금", "토", "일"] - - def _ordinal_number(self, n): - ordinals = ["0", "첫", "두", "세", "네", "다섯", "여섯", "일곱", "여덟", "아홉", "열"] - if n < len(ordinals): - return "{}번째".format(ordinals[n]) - return "{}번째".format(n) - - def _format_relative(self, humanized, timeframe, delta): - if timeframe in ("day", "days"): - special = self.special_dayframes.get(delta) - if special: - return special - elif timeframe in ("year", "years"): - special = self.special_yearframes.get(delta) - if special: - return special - - return super(KoreanLocale, self)._format_relative(humanized, timeframe, delta) - - -# derived locale types & implementations. -class DutchLocale(Locale): - - names = ["nl", "nl_nl"] - - past = "{0} geleden" - future = "over {0}" - - timeframes = { - "now": "nu", - "second": "een seconde", - "seconds": "{0} seconden", - "minute": "een minuut", - "minutes": "{0} minuten", - "hour": "een uur", - "hours": "{0} uur", - "day": "een dag", - "days": "{0} dagen", - "week": "een week", - "weeks": "{0} weken", - "month": "een maand", - "months": "{0} maanden", - "year": "een jaar", - "years": "{0} jaar", - } - - # In Dutch names of months and days are not starting with a capital letter - # like in the English language. - month_names = [ - "", - "januari", - "februari", - "maart", - "april", - "mei", - "juni", - "juli", - "augustus", - "september", - "oktober", - "november", - "december", - ] - month_abbreviations = [ - "", - "jan", - "feb", - "mrt", - "apr", - "mei", - "jun", - "jul", - "aug", - "sep", - "okt", - "nov", - "dec", - ] - - day_names = [ - "", - "maandag", - "dinsdag", - "woensdag", - "donderdag", - "vrijdag", - "zaterdag", - "zondag", - ] - day_abbreviations = ["", "ma", "di", "wo", "do", "vr", "za", "zo"] - - -class SlavicBaseLocale(Locale): - def _format_timeframe(self, timeframe, delta): - - form = self.timeframes[timeframe] - delta = abs(delta) - - if isinstance(form, list): - - if delta % 10 == 1 and delta % 100 != 11: - form = form[0] - elif 2 <= delta % 10 <= 4 and (delta % 100 < 10 or delta % 100 >= 20): - form = form[1] - else: - form = form[2] - - return form.format(delta) - - -class BelarusianLocale(SlavicBaseLocale): - - names = ["be", "be_by"] - - past = "{0} таму" - future = "праз {0}" - - timeframes = { - "now": "зараз", - "second": "секунду", - "seconds": "{0} некалькі секунд", - "minute": "хвіліну", - "minutes": ["{0} хвіліну", "{0} хвіліны", "{0} хвілін"], - "hour": "гадзіну", - "hours": ["{0} гадзіну", "{0} гадзіны", "{0} гадзін"], - "day": "дзень", - "days": ["{0} дзень", "{0} дні", "{0} дзён"], - "month": "месяц", - "months": ["{0} месяц", "{0} месяцы", "{0} месяцаў"], - "year": "год", - "years": ["{0} год", "{0} гады", "{0} гадоў"], - } - - month_names = [ - "", - "студзеня", - "лютага", - "сакавіка", - "красавіка", - "траўня", - "чэрвеня", - "ліпеня", - "жніўня", - "верасня", - "кастрычніка", - "лістапада", - "снежня", - ] - month_abbreviations = [ - "", - "студ", - "лют", - "сак", - "крас", - "трав", - "чэрв", - "ліп", - "жнів", - "вер", - "каст", - "ліст", - "снеж", - ] - - day_names = [ - "", - "панядзелак", - "аўторак", - "серада", - "чацвер", - "пятніца", - "субота", - "нядзеля", - ] - day_abbreviations = ["", "пн", "ат", "ср", "чц", "пт", "сб", "нд"] - - -class PolishLocale(SlavicBaseLocale): - - names = ["pl", "pl_pl"] - - past = "{0} temu" - future = "za {0}" - - # The nouns should be in genitive case (Polish: "dopełniacz") - # in order to correctly form `past` & `future` expressions. - timeframes = { - "now": "teraz", - "second": "sekundę", - "seconds": ["{0} sekund", "{0} sekundy", "{0} sekund"], - "minute": "minutę", - "minutes": ["{0} minut", "{0} minuty", "{0} minut"], - "hour": "godzinę", - "hours": ["{0} godzin", "{0} godziny", "{0} godzin"], - "day": "dzień", - "days": "{0} dni", - "week": "tydzień", - "weeks": ["{0} tygodni", "{0} tygodnie", "{0} tygodni"], - "month": "miesiąc", - "months": ["{0} miesięcy", "{0} miesiące", "{0} miesięcy"], - "year": "rok", - "years": ["{0} lat", "{0} lata", "{0} lat"], - } - - month_names = [ - "", - "styczeń", - "luty", - "marzec", - "kwiecień", - "maj", - "czerwiec", - "lipiec", - "sierpień", - "wrzesień", - "październik", - "listopad", - "grudzień", - ] - month_abbreviations = [ - "", - "sty", - "lut", - "mar", - "kwi", - "maj", - "cze", - "lip", - "sie", - "wrz", - "paź", - "lis", - "gru", - ] - - day_names = [ - "", - "poniedziałek", - "wtorek", - "środa", - "czwartek", - "piątek", - "sobota", - "niedziela", - ] - day_abbreviations = ["", "Pn", "Wt", "Śr", "Czw", "Pt", "So", "Nd"] - - -class RussianLocale(SlavicBaseLocale): - - names = ["ru", "ru_ru"] - - past = "{0} назад" - future = "через {0}" - - timeframes = { - "now": "сейчас", - "second": "Второй", - "seconds": "{0} несколько секунд", - "minute": "минуту", - "minutes": ["{0} минуту", "{0} минуты", "{0} минут"], - "hour": "час", - "hours": ["{0} час", "{0} часа", "{0} часов"], - "day": "день", - "days": ["{0} день", "{0} дня", "{0} дней"], - "week": "неделю", - "weeks": ["{0} неделю", "{0} недели", "{0} недель"], - "month": "месяц", - "months": ["{0} месяц", "{0} месяца", "{0} месяцев"], - "year": "год", - "years": ["{0} год", "{0} года", "{0} лет"], - } - - month_names = [ - "", - "января", - "февраля", - "марта", - "апреля", - "мая", - "июня", - "июля", - "августа", - "сентября", - "октября", - "ноября", - "декабря", - ] - month_abbreviations = [ - "", - "янв", - "фев", - "мар", - "апр", - "май", - "июн", - "июл", - "авг", - "сен", - "окт", - "ноя", - "дек", - ] - - day_names = [ - "", - "понедельник", - "вторник", - "среда", - "четверг", - "пятница", - "суббота", - "воскресенье", - ] - day_abbreviations = ["", "пн", "вт", "ср", "чт", "пт", "сб", "вс"] - - -class AfrikaansLocale(Locale): - - names = ["af", "af_nl"] - - past = "{0} gelede" - future = "in {0}" - - timeframes = { - "now": "nou", - "second": "n sekonde", - "seconds": "{0} sekondes", - "minute": "minuut", - "minutes": "{0} minute", - "hour": "uur", - "hours": "{0} ure", - "day": "een dag", - "days": "{0} dae", - "month": "een maand", - "months": "{0} maande", - "year": "een jaar", - "years": "{0} jaar", - } - - month_names = [ - "", - "Januarie", - "Februarie", - "Maart", - "April", - "Mei", - "Junie", - "Julie", - "Augustus", - "September", - "Oktober", - "November", - "Desember", - ] - month_abbreviations = [ - "", - "Jan", - "Feb", - "Mrt", - "Apr", - "Mei", - "Jun", - "Jul", - "Aug", - "Sep", - "Okt", - "Nov", - "Des", - ] - - day_names = [ - "", - "Maandag", - "Dinsdag", - "Woensdag", - "Donderdag", - "Vrydag", - "Saterdag", - "Sondag", - ] - day_abbreviations = ["", "Ma", "Di", "Wo", "Do", "Vr", "Za", "So"] - - -class BulgarianLocale(SlavicBaseLocale): - - names = ["bg", "bg_BG"] - - past = "{0} назад" - future = "напред {0}" - - timeframes = { - "now": "сега", - "second": "секунда", - "seconds": "{0} няколко секунди", - "minute": "минута", - "minutes": ["{0} минута", "{0} минути", "{0} минути"], - "hour": "час", - "hours": ["{0} час", "{0} часа", "{0} часа"], - "day": "ден", - "days": ["{0} ден", "{0} дни", "{0} дни"], - "month": "месец", - "months": ["{0} месец", "{0} месеца", "{0} месеца"], - "year": "година", - "years": ["{0} година", "{0} години", "{0} години"], - } - - month_names = [ - "", - "януари", - "февруари", - "март", - "април", - "май", - "юни", - "юли", - "август", - "септември", - "октомври", - "ноември", - "декември", - ] - month_abbreviations = [ - "", - "ян", - "февр", - "март", - "апр", - "май", - "юни", - "юли", - "авг", - "септ", - "окт", - "ноем", - "дек", - ] - - day_names = [ - "", - "понеделник", - "вторник", - "сряда", - "четвъртък", - "петък", - "събота", - "неделя", - ] - day_abbreviations = ["", "пон", "вт", "ср", "четв", "пет", "съб", "нед"] - - -class UkrainianLocale(SlavicBaseLocale): - - names = ["ua", "uk_ua"] - - past = "{0} тому" - future = "за {0}" - - timeframes = { - "now": "зараз", - "second": "секунда", - "seconds": "{0} кілька секунд", - "minute": "хвилину", - "minutes": ["{0} хвилину", "{0} хвилини", "{0} хвилин"], - "hour": "годину", - "hours": ["{0} годину", "{0} години", "{0} годин"], - "day": "день", - "days": ["{0} день", "{0} дні", "{0} днів"], - "month": "місяць", - "months": ["{0} місяць", "{0} місяці", "{0} місяців"], - "year": "рік", - "years": ["{0} рік", "{0} роки", "{0} років"], - } - - month_names = [ - "", - "січня", - "лютого", - "березня", - "квітня", - "травня", - "червня", - "липня", - "серпня", - "вересня", - "жовтня", - "листопада", - "грудня", - ] - month_abbreviations = [ - "", - "січ", - "лют", - "бер", - "квіт", - "трав", - "черв", - "лип", - "серп", - "вер", - "жовт", - "лист", - "груд", - ] - - day_names = [ - "", - "понеділок", - "вівторок", - "середа", - "четвер", - "п’ятниця", - "субота", - "неділя", - ] - day_abbreviations = ["", "пн", "вт", "ср", "чт", "пт", "сб", "нд"] - - -class MacedonianLocale(SlavicBaseLocale): - names = ["mk", "mk_mk"] - - past = "пред {0}" - future = "за {0}" - - timeframes = { - "now": "сега", - "second": "една секунда", - "seconds": ["{0} секунда", "{0} секунди", "{0} секунди"], - "minute": "една минута", - "minutes": ["{0} минута", "{0} минути", "{0} минути"], - "hour": "еден саат", - "hours": ["{0} саат", "{0} саати", "{0} саати"], - "day": "еден ден", - "days": ["{0} ден", "{0} дена", "{0} дена"], - "week": "една недела", - "weeks": ["{0} недела", "{0} недели", "{0} недели"], - "month": "еден месец", - "months": ["{0} месец", "{0} месеци", "{0} месеци"], - "year": "една година", - "years": ["{0} година", "{0} години", "{0} години"], - } - - meridians = {"am": "дп", "pm": "пп", "AM": "претпладне", "PM": "попладне"} - - month_names = [ - "", - "Јануари", - "Февруари", - "Март", - "Април", - "Мај", - "Јуни", - "Јули", - "Август", - "Септември", - "Октомври", - "Ноември", - "Декември", - ] - month_abbreviations = [ - "", - "Јан", - "Фев", - "Мар", - "Апр", - "Мај", - "Јун", - "Јул", - "Авг", - "Септ", - "Окт", - "Ноем", - "Декем", - ] - - day_names = [ - "", - "Понеделник", - "Вторник", - "Среда", - "Четврток", - "Петок", - "Сабота", - "Недела", - ] - day_abbreviations = [ - "", - "Пон", - "Вт", - "Сре", - "Чет", - "Пет", - "Саб", - "Нед", - ] - - -class GermanBaseLocale(Locale): - - past = "vor {0}" - future = "in {0}" - and_word = "und" - - timeframes = { - "now": "gerade eben", - "second": "eine Sekunde", - "seconds": "{0} Sekunden", - "minute": "einer Minute", - "minutes": "{0} Minuten", - "hour": "einer Stunde", - "hours": "{0} Stunden", - "day": "einem Tag", - "days": "{0} Tagen", - "week": "einer Woche", - "weeks": "{0} Wochen", - "month": "einem Monat", - "months": "{0} Monaten", - "year": "einem Jahr", - "years": "{0} Jahren", - } - - timeframes_only_distance = timeframes.copy() - timeframes_only_distance["minute"] = "eine Minute" - timeframes_only_distance["hour"] = "eine Stunde" - timeframes_only_distance["day"] = "ein Tag" - timeframes_only_distance["week"] = "eine Woche" - timeframes_only_distance["month"] = "ein Monat" - timeframes_only_distance["year"] = "ein Jahr" - - month_names = [ - "", - "Januar", - "Februar", - "März", - "April", - "Mai", - "Juni", - "Juli", - "August", - "September", - "Oktober", - "November", - "Dezember", - ] - - month_abbreviations = [ - "", - "Jan", - "Feb", - "Mär", - "Apr", - "Mai", - "Jun", - "Jul", - "Aug", - "Sep", - "Okt", - "Nov", - "Dez", - ] - - day_names = [ - "", - "Montag", - "Dienstag", - "Mittwoch", - "Donnerstag", - "Freitag", - "Samstag", - "Sonntag", - ] - - day_abbreviations = ["", "Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"] - - def _ordinal_number(self, n): - return "{}.".format(n) - - def describe(self, timeframe, delta=0, only_distance=False): - """Describes a delta within a timeframe in plain language. - - :param timeframe: a string representing a timeframe. - :param delta: a quantity representing a delta in a timeframe. - :param only_distance: return only distance eg: "11 seconds" without "in" or "ago" keywords - """ - - if not only_distance: - return super(GermanBaseLocale, self).describe( - timeframe, delta, only_distance - ) - - # German uses a different case without 'in' or 'ago' - humanized = self.timeframes_only_distance[timeframe].format(trunc(abs(delta))) - - return humanized - - -class GermanLocale(GermanBaseLocale, Locale): - - names = ["de", "de_de"] - - -class SwissLocale(GermanBaseLocale, Locale): - - names = ["de_ch"] - - -class AustrianLocale(GermanBaseLocale, Locale): - - names = ["de_at"] - - month_names = [ - "", - "Jänner", - "Februar", - "März", - "April", - "Mai", - "Juni", - "Juli", - "August", - "September", - "Oktober", - "November", - "Dezember", - ] - - -class NorwegianLocale(Locale): - - names = ["nb", "nb_no"] - - past = "for {0} siden" - future = "om {0}" - - timeframes = { - "now": "nå nettopp", - "second": "et sekund", - "seconds": "{0} noen sekunder", - "minute": "ett minutt", - "minutes": "{0} minutter", - "hour": "en time", - "hours": "{0} timer", - "day": "en dag", - "days": "{0} dager", - "month": "en måned", - "months": "{0} måneder", - "year": "ett år", - "years": "{0} år", - } - - month_names = [ - "", - "januar", - "februar", - "mars", - "april", - "mai", - "juni", - "juli", - "august", - "september", - "oktober", - "november", - "desember", - ] - month_abbreviations = [ - "", - "jan", - "feb", - "mar", - "apr", - "mai", - "jun", - "jul", - "aug", - "sep", - "okt", - "nov", - "des", - ] - - day_names = [ - "", - "mandag", - "tirsdag", - "onsdag", - "torsdag", - "fredag", - "lørdag", - "søndag", - ] - day_abbreviations = ["", "ma", "ti", "on", "to", "fr", "lø", "sø"] - - -class NewNorwegianLocale(Locale): - - names = ["nn", "nn_no"] - - past = "for {0} sidan" - future = "om {0}" - - timeframes = { - "now": "no nettopp", - "second": "et sekund", - "seconds": "{0} nokre sekund", - "minute": "ett minutt", - "minutes": "{0} minutt", - "hour": "ein time", - "hours": "{0} timar", - "day": "ein dag", - "days": "{0} dagar", - "month": "en månad", - "months": "{0} månader", - "year": "eit år", - "years": "{0} år", - } - - month_names = [ - "", - "januar", - "februar", - "mars", - "april", - "mai", - "juni", - "juli", - "august", - "september", - "oktober", - "november", - "desember", - ] - month_abbreviations = [ - "", - "jan", - "feb", - "mar", - "apr", - "mai", - "jun", - "jul", - "aug", - "sep", - "okt", - "nov", - "des", - ] - - day_names = [ - "", - "måndag", - "tysdag", - "onsdag", - "torsdag", - "fredag", - "laurdag", - "sundag", - ] - day_abbreviations = ["", "må", "ty", "on", "to", "fr", "la", "su"] - - -class PortugueseLocale(Locale): - names = ["pt", "pt_pt"] - - past = "há {0}" - future = "em {0}" - and_word = "e" - - timeframes = { - "now": "agora", - "second": "um segundo", - "seconds": "{0} segundos", - "minute": "um minuto", - "minutes": "{0} minutos", - "hour": "uma hora", - "hours": "{0} horas", - "day": "um dia", - "days": "{0} dias", - "week": "uma semana", - "weeks": "{0} semanas", - "month": "um mês", - "months": "{0} meses", - "year": "um ano", - "years": "{0} anos", - } - - month_names = [ - "", - "Janeiro", - "Fevereiro", - "Março", - "Abril", - "Maio", - "Junho", - "Julho", - "Agosto", - "Setembro", - "Outubro", - "Novembro", - "Dezembro", - ] - month_abbreviations = [ - "", - "Jan", - "Fev", - "Mar", - "Abr", - "Mai", - "Jun", - "Jul", - "Ago", - "Set", - "Out", - "Nov", - "Dez", - ] - - day_names = [ - "", - "Segunda-feira", - "Terça-feira", - "Quarta-feira", - "Quinta-feira", - "Sexta-feira", - "Sábado", - "Domingo", - ] - day_abbreviations = ["", "Seg", "Ter", "Qua", "Qui", "Sex", "Sab", "Dom"] - - -class BrazilianPortugueseLocale(PortugueseLocale): - names = ["pt_br"] - - past = "faz {0}" - - -class TagalogLocale(Locale): - - names = ["tl", "tl_ph"] - - past = "nakaraang {0}" - future = "{0} mula ngayon" - - timeframes = { - "now": "ngayon lang", - "second": "isang segundo", - "seconds": "{0} segundo", - "minute": "isang minuto", - "minutes": "{0} minuto", - "hour": "isang oras", - "hours": "{0} oras", - "day": "isang araw", - "days": "{0} araw", - "week": "isang linggo", - "weeks": "{0} linggo", - "month": "isang buwan", - "months": "{0} buwan", - "year": "isang taon", - "years": "{0} taon", - } - - month_names = [ - "", - "Enero", - "Pebrero", - "Marso", - "Abril", - "Mayo", - "Hunyo", - "Hulyo", - "Agosto", - "Setyembre", - "Oktubre", - "Nobyembre", - "Disyembre", - ] - month_abbreviations = [ - "", - "Ene", - "Peb", - "Mar", - "Abr", - "May", - "Hun", - "Hul", - "Ago", - "Set", - "Okt", - "Nob", - "Dis", - ] - - day_names = [ - "", - "Lunes", - "Martes", - "Miyerkules", - "Huwebes", - "Biyernes", - "Sabado", - "Linggo", - ] - day_abbreviations = ["", "Lun", "Mar", "Miy", "Huw", "Biy", "Sab", "Lin"] - - meridians = {"am": "nu", "pm": "nh", "AM": "ng umaga", "PM": "ng hapon"} - - def _ordinal_number(self, n): - return "ika-{}".format(n) - - -class VietnameseLocale(Locale): - - names = ["vi", "vi_vn"] - - past = "{0} trước" - future = "{0} nữa" - - timeframes = { - "now": "hiện tại", - "second": "một giây", - "seconds": "{0} giây", - "minute": "một phút", - "minutes": "{0} phút", - "hour": "một giờ", - "hours": "{0} giờ", - "day": "một ngày", - "days": "{0} ngày", - "week": "một tuần", - "weeks": "{0} tuần", - "month": "một tháng", - "months": "{0} tháng", - "year": "một năm", - "years": "{0} năm", - } - - month_names = [ - "", - "Tháng Một", - "Tháng Hai", - "Tháng Ba", - "Tháng Tư", - "Tháng Năm", - "Tháng Sáu", - "Tháng Bảy", - "Tháng Tám", - "Tháng Chín", - "Tháng Mười", - "Tháng Mười Một", - "Tháng Mười Hai", - ] - month_abbreviations = [ - "", - "Tháng 1", - "Tháng 2", - "Tháng 3", - "Tháng 4", - "Tháng 5", - "Tháng 6", - "Tháng 7", - "Tháng 8", - "Tháng 9", - "Tháng 10", - "Tháng 11", - "Tháng 12", - ] - - day_names = [ - "", - "Thứ Hai", - "Thứ Ba", - "Thứ Tư", - "Thứ Năm", - "Thứ Sáu", - "Thứ Bảy", - "Chủ Nhật", - ] - day_abbreviations = ["", "Thứ 2", "Thứ 3", "Thứ 4", "Thứ 5", "Thứ 6", "Thứ 7", "CN"] - - -class TurkishLocale(Locale): - - names = ["tr", "tr_tr"] - - past = "{0} önce" - future = "{0} sonra" - - timeframes = { - "now": "şimdi", - "second": "bir saniye", - "seconds": "{0} saniye", - "minute": "bir dakika", - "minutes": "{0} dakika", - "hour": "bir saat", - "hours": "{0} saat", - "day": "bir gün", - "days": "{0} gün", - "month": "bir ay", - "months": "{0} ay", - "year": "yıl", - "years": "{0} yıl", - } - - month_names = [ - "", - "Ocak", - "Şubat", - "Mart", - "Nisan", - "Mayıs", - "Haziran", - "Temmuz", - "Ağustos", - "Eylül", - "Ekim", - "Kasım", - "Aralık", - ] - month_abbreviations = [ - "", - "Oca", - "Şub", - "Mar", - "Nis", - "May", - "Haz", - "Tem", - "Ağu", - "Eyl", - "Eki", - "Kas", - "Ara", - ] - - day_names = [ - "", - "Pazartesi", - "Salı", - "Çarşamba", - "Perşembe", - "Cuma", - "Cumartesi", - "Pazar", - ] - day_abbreviations = ["", "Pzt", "Sal", "Çar", "Per", "Cum", "Cmt", "Paz"] - - -class AzerbaijaniLocale(Locale): - - names = ["az", "az_az"] - - past = "{0} əvvəl" - future = "{0} sonra" - - timeframes = { - "now": "indi", - "second": "saniyə", - "seconds": "{0} saniyə", - "minute": "bir dəqiqə", - "minutes": "{0} dəqiqə", - "hour": "bir saat", - "hours": "{0} saat", - "day": "bir gün", - "days": "{0} gün", - "month": "bir ay", - "months": "{0} ay", - "year": "il", - "years": "{0} il", - } - - month_names = [ - "", - "Yanvar", - "Fevral", - "Mart", - "Aprel", - "May", - "İyun", - "İyul", - "Avqust", - "Sentyabr", - "Oktyabr", - "Noyabr", - "Dekabr", - ] - month_abbreviations = [ - "", - "Yan", - "Fev", - "Mar", - "Apr", - "May", - "İyn", - "İyl", - "Avq", - "Sen", - "Okt", - "Noy", - "Dek", - ] - - day_names = [ - "", - "Bazar ertəsi", - "Çərşənbə axşamı", - "Çərşənbə", - "Cümə axşamı", - "Cümə", - "Şənbə", - "Bazar", - ] - day_abbreviations = ["", "Ber", "Çax", "Çər", "Cax", "Cüm", "Şnb", "Bzr"] - - -class ArabicLocale(Locale): - names = [ - "ar", - "ar_ae", - "ar_bh", - "ar_dj", - "ar_eg", - "ar_eh", - "ar_er", - "ar_km", - "ar_kw", - "ar_ly", - "ar_om", - "ar_qa", - "ar_sa", - "ar_sd", - "ar_so", - "ar_ss", - "ar_td", - "ar_ye", - ] - - past = "منذ {0}" - future = "خلال {0}" - - timeframes = { - "now": "الآن", - "second": "ثانية", - "seconds": {"double": "ثانيتين", "ten": "{0} ثوان", "higher": "{0} ثانية"}, - "minute": "دقيقة", - "minutes": {"double": "دقيقتين", "ten": "{0} دقائق", "higher": "{0} دقيقة"}, - "hour": "ساعة", - "hours": {"double": "ساعتين", "ten": "{0} ساعات", "higher": "{0} ساعة"}, - "day": "يوم", - "days": {"double": "يومين", "ten": "{0} أيام", "higher": "{0} يوم"}, - "month": "شهر", - "months": {"double": "شهرين", "ten": "{0} أشهر", "higher": "{0} شهر"}, - "year": "سنة", - "years": {"double": "سنتين", "ten": "{0} سنوات", "higher": "{0} سنة"}, - } - - month_names = [ - "", - "يناير", - "فبراير", - "مارس", - "أبريل", - "مايو", - "يونيو", - "يوليو", - "أغسطس", - "سبتمبر", - "أكتوبر", - "نوفمبر", - "ديسمبر", - ] - month_abbreviations = [ - "", - "يناير", - "فبراير", - "مارس", - "أبريل", - "مايو", - "يونيو", - "يوليو", - "أغسطس", - "سبتمبر", - "أكتوبر", - "نوفمبر", - "ديسمبر", - ] - - day_names = [ - "", - "الإثنين", - "الثلاثاء", - "الأربعاء", - "الخميس", - "الجمعة", - "السبت", - "الأحد", - ] - day_abbreviations = ["", "إثنين", "ثلاثاء", "أربعاء", "خميس", "جمعة", "سبت", "أحد"] - - def _format_timeframe(self, timeframe, delta): - form = self.timeframes[timeframe] - delta = abs(delta) - if isinstance(form, dict): - if delta == 2: - form = form["double"] - elif delta > 2 and delta <= 10: - form = form["ten"] - else: - form = form["higher"] - - return form.format(delta) - - -class LevantArabicLocale(ArabicLocale): - names = ["ar_iq", "ar_jo", "ar_lb", "ar_ps", "ar_sy"] - month_names = [ - "", - "كانون الثاني", - "شباط", - "آذار", - "نيسان", - "أيار", - "حزيران", - "تموز", - "آب", - "أيلول", - "تشرين الأول", - "تشرين الثاني", - "كانون الأول", - ] - month_abbreviations = [ - "", - "كانون الثاني", - "شباط", - "آذار", - "نيسان", - "أيار", - "حزيران", - "تموز", - "آب", - "أيلول", - "تشرين الأول", - "تشرين الثاني", - "كانون الأول", - ] - - -class AlgeriaTunisiaArabicLocale(ArabicLocale): - names = ["ar_tn", "ar_dz"] - month_names = [ - "", - "جانفي", - "فيفري", - "مارس", - "أفريل", - "ماي", - "جوان", - "جويلية", - "أوت", - "سبتمبر", - "أكتوبر", - "نوفمبر", - "ديسمبر", - ] - month_abbreviations = [ - "", - "جانفي", - "فيفري", - "مارس", - "أفريل", - "ماي", - "جوان", - "جويلية", - "أوت", - "سبتمبر", - "أكتوبر", - "نوفمبر", - "ديسمبر", - ] - - -class MauritaniaArabicLocale(ArabicLocale): - names = ["ar_mr"] - month_names = [ - "", - "يناير", - "فبراير", - "مارس", - "إبريل", - "مايو", - "يونيو", - "يوليو", - "أغشت", - "شتمبر", - "أكتوبر", - "نوفمبر", - "دجمبر", - ] - month_abbreviations = [ - "", - "يناير", - "فبراير", - "مارس", - "إبريل", - "مايو", - "يونيو", - "يوليو", - "أغشت", - "شتمبر", - "أكتوبر", - "نوفمبر", - "دجمبر", - ] - - -class MoroccoArabicLocale(ArabicLocale): - names = ["ar_ma"] - month_names = [ - "", - "يناير", - "فبراير", - "مارس", - "أبريل", - "ماي", - "يونيو", - "يوليوز", - "غشت", - "شتنبر", - "أكتوبر", - "نونبر", - "دجنبر", - ] - month_abbreviations = [ - "", - "يناير", - "فبراير", - "مارس", - "أبريل", - "ماي", - "يونيو", - "يوليوز", - "غشت", - "شتنبر", - "أكتوبر", - "نونبر", - "دجنبر", - ] - - -class IcelandicLocale(Locale): - def _format_timeframe(self, timeframe, delta): - - timeframe = self.timeframes[timeframe] - if delta < 0: - timeframe = timeframe[0] - elif delta > 0: - timeframe = timeframe[1] - - return timeframe.format(abs(delta)) - - names = ["is", "is_is"] - - past = "fyrir {0} síðan" - future = "eftir {0}" - - timeframes = { - "now": "rétt í þessu", - "second": ("sekúndu", "sekúndu"), - "seconds": ("{0} nokkrum sekúndum", "nokkrar sekúndur"), - "minute": ("einni mínútu", "eina mínútu"), - "minutes": ("{0} mínútum", "{0} mínútur"), - "hour": ("einum tíma", "einn tíma"), - "hours": ("{0} tímum", "{0} tíma"), - "day": ("einum degi", "einn dag"), - "days": ("{0} dögum", "{0} daga"), - "month": ("einum mánuði", "einn mánuð"), - "months": ("{0} mánuðum", "{0} mánuði"), - "year": ("einu ári", "eitt ár"), - "years": ("{0} árum", "{0} ár"), - } - - meridians = {"am": "f.h.", "pm": "e.h.", "AM": "f.h.", "PM": "e.h."} - - month_names = [ - "", - "janúar", - "febrúar", - "mars", - "apríl", - "maí", - "júní", - "júlí", - "ágúst", - "september", - "október", - "nóvember", - "desember", - ] - month_abbreviations = [ - "", - "jan", - "feb", - "mar", - "apr", - "maí", - "jún", - "júl", - "ágú", - "sep", - "okt", - "nóv", - "des", - ] - - day_names = [ - "", - "mánudagur", - "þriðjudagur", - "miðvikudagur", - "fimmtudagur", - "föstudagur", - "laugardagur", - "sunnudagur", - ] - day_abbreviations = ["", "mán", "þri", "mið", "fim", "fös", "lau", "sun"] - - -class DanishLocale(Locale): - - names = ["da", "da_dk"] - - past = "for {0} siden" - future = "efter {0}" - and_word = "og" - - timeframes = { - "now": "lige nu", - "second": "et sekund", - "seconds": "{0} et par sekunder", - "minute": "et minut", - "minutes": "{0} minutter", - "hour": "en time", - "hours": "{0} timer", - "day": "en dag", - "days": "{0} dage", - "month": "en måned", - "months": "{0} måneder", - "year": "et år", - "years": "{0} år", - } - - month_names = [ - "", - "januar", - "februar", - "marts", - "april", - "maj", - "juni", - "juli", - "august", - "september", - "oktober", - "november", - "december", - ] - month_abbreviations = [ - "", - "jan", - "feb", - "mar", - "apr", - "maj", - "jun", - "jul", - "aug", - "sep", - "okt", - "nov", - "dec", - ] - - day_names = [ - "", - "mandag", - "tirsdag", - "onsdag", - "torsdag", - "fredag", - "lørdag", - "søndag", - ] - day_abbreviations = ["", "man", "tir", "ons", "tor", "fre", "lør", "søn"] - - -class MalayalamLocale(Locale): - - names = ["ml"] - - past = "{0} മുമ്പ്" - future = "{0} ശേഷം" - - timeframes = { - "now": "ഇപ്പോൾ", - "second": "ഒരു നിമിഷം", - "seconds": "{0} സെക്കന്റ്‌", - "minute": "ഒരു മിനിറ്റ്", - "minutes": "{0} മിനിറ്റ്", - "hour": "ഒരു മണിക്കൂർ", - "hours": "{0} മണിക്കൂർ", - "day": "ഒരു ദിവസം ", - "days": "{0} ദിവസം ", - "month": "ഒരു മാസം ", - "months": "{0} മാസം ", - "year": "ഒരു വർഷം ", - "years": "{0} വർഷം ", - } - - meridians = { - "am": "രാവിലെ", - "pm": "ഉച്ചക്ക് ശേഷം", - "AM": "രാവിലെ", - "PM": "ഉച്ചക്ക് ശേഷം", - } - - month_names = [ - "", - "ജനുവരി", - "ഫെബ്രുവരി", - "മാർച്ച്‌", - "ഏപ്രിൽ ", - "മെയ്‌ ", - "ജൂണ്‍", - "ജൂലൈ", - "ഓഗസ്റ്റ്‌", - "സെപ്റ്റംബർ", - "ഒക്ടോബർ", - "നവംബർ", - "ഡിസംബർ", - ] - month_abbreviations = [ - "", - "ജനു", - "ഫെബ് ", - "മാർ", - "ഏപ്രിൽ", - "മേയ്", - "ജൂണ്‍", - "ജൂലൈ", - "ഓഗസ്റ", - "സെപ്റ്റ", - "ഒക്ടോ", - "നവം", - "ഡിസം", - ] - - day_names = ["", "തിങ്കള്‍", "ചൊവ്വ", "ബുധന്‍", "വ്യാഴം", "വെള്ളി", "ശനി", "ഞായര്‍"] - day_abbreviations = [ - "", - "തിങ്കള്‍", - "ചൊവ്വ", - "ബുധന്‍", - "വ്യാഴം", - "വെള്ളി", - "ശനി", - "ഞായര്‍", - ] - - -class HindiLocale(Locale): - - names = ["hi"] - - past = "{0} पहले" - future = "{0} बाद" - - timeframes = { - "now": "अभी", - "second": "एक पल", - "seconds": "{0} सेकंड्", - "minute": "एक मिनट ", - "minutes": "{0} मिनट ", - "hour": "एक घंटा", - "hours": "{0} घंटे", - "day": "एक दिन", - "days": "{0} दिन", - "month": "एक माह ", - "months": "{0} महीने ", - "year": "एक वर्ष ", - "years": "{0} साल ", - } - - meridians = {"am": "सुबह", "pm": "शाम", "AM": "सुबह", "PM": "शाम"} - - month_names = [ - "", - "जनवरी", - "फरवरी", - "मार्च", - "अप्रैल ", - "मई", - "जून", - "जुलाई", - "अगस्त", - "सितंबर", - "अक्टूबर", - "नवंबर", - "दिसंबर", - ] - month_abbreviations = [ - "", - "जन", - "फ़र", - "मार्च", - "अप्रै", - "मई", - "जून", - "जुलाई", - "आग", - "सित", - "अकत", - "नवे", - "दिस", - ] - - day_names = [ - "", - "सोमवार", - "मंगलवार", - "बुधवार", - "गुरुवार", - "शुक्रवार", - "शनिवार", - "रविवार", - ] - day_abbreviations = ["", "सोम", "मंगल", "बुध", "गुरुवार", "शुक्र", "शनि", "रवि"] - - -class CzechLocale(Locale): - names = ["cs", "cs_cz"] - - timeframes = { - "now": "Teď", - "second": {"past": "vteřina", "future": "vteřina", "zero": "vteřina"}, - "seconds": {"past": "{0} sekundami", "future": ["{0} sekundy", "{0} sekund"]}, - "minute": {"past": "minutou", "future": "minutu", "zero": "{0} minut"}, - "minutes": {"past": "{0} minutami", "future": ["{0} minuty", "{0} minut"]}, - "hour": {"past": "hodinou", "future": "hodinu", "zero": "{0} hodin"}, - "hours": {"past": "{0} hodinami", "future": ["{0} hodiny", "{0} hodin"]}, - "day": {"past": "dnem", "future": "den", "zero": "{0} dnů"}, - "days": {"past": "{0} dny", "future": ["{0} dny", "{0} dnů"]}, - "week": {"past": "týdnem", "future": "týden", "zero": "{0} týdnů"}, - "weeks": {"past": "{0} týdny", "future": ["{0} týdny", "{0} týdnů"]}, - "month": {"past": "měsícem", "future": "měsíc", "zero": "{0} měsíců"}, - "months": {"past": "{0} měsíci", "future": ["{0} měsíce", "{0} měsíců"]}, - "year": {"past": "rokem", "future": "rok", "zero": "{0} let"}, - "years": {"past": "{0} lety", "future": ["{0} roky", "{0} let"]}, - } - - past = "Před {0}" - future = "Za {0}" - - month_names = [ - "", - "leden", - "únor", - "březen", - "duben", - "květen", - "červen", - "červenec", - "srpen", - "září", - "říjen", - "listopad", - "prosinec", - ] - month_abbreviations = [ - "", - "led", - "úno", - "bře", - "dub", - "kvě", - "čvn", - "čvc", - "srp", - "zář", - "říj", - "lis", - "pro", - ] - - day_names = [ - "", - "pondělí", - "úterý", - "středa", - "čtvrtek", - "pátek", - "sobota", - "neděle", - ] - day_abbreviations = ["", "po", "út", "st", "čt", "pá", "so", "ne"] - - def _format_timeframe(self, timeframe, delta): - """Czech aware time frame format function, takes into account - the differences between past and future forms.""" - form = self.timeframes[timeframe] - if isinstance(form, dict): - if delta == 0: - form = form["zero"] # And *never* use 0 in the singular! - elif delta > 0: - form = form["future"] - else: - form = form["past"] - delta = abs(delta) - - if isinstance(form, list): - if 2 <= delta % 10 <= 4 and (delta % 100 < 10 or delta % 100 >= 20): - form = form[0] - else: - form = form[1] - - return form.format(delta) - - -class SlovakLocale(Locale): - names = ["sk", "sk_sk"] - - timeframes = { - "now": "Teraz", - "second": {"past": "sekundou", "future": "sekundu", "zero": "{0} sekúnd"}, - "seconds": {"past": "{0} sekundami", "future": ["{0} sekundy", "{0} sekúnd"]}, - "minute": {"past": "minútou", "future": "minútu", "zero": "{0} minút"}, - "minutes": {"past": "{0} minútami", "future": ["{0} minúty", "{0} minút"]}, - "hour": {"past": "hodinou", "future": "hodinu", "zero": "{0} hodín"}, - "hours": {"past": "{0} hodinami", "future": ["{0} hodiny", "{0} hodín"]}, - "day": {"past": "dňom", "future": "deň", "zero": "{0} dní"}, - "days": {"past": "{0} dňami", "future": ["{0} dni", "{0} dní"]}, - "week": {"past": "týždňom", "future": "týždeň", "zero": "{0} týždňov"}, - "weeks": {"past": "{0} týždňami", "future": ["{0} týždne", "{0} týždňov"]}, - "month": {"past": "mesiacom", "future": "mesiac", "zero": "{0} mesiacov"}, - "months": {"past": "{0} mesiacmi", "future": ["{0} mesiace", "{0} mesiacov"]}, - "year": {"past": "rokom", "future": "rok", "zero": "{0} rokov"}, - "years": {"past": "{0} rokmi", "future": ["{0} roky", "{0} rokov"]}, - } - - past = "Pred {0}" - future = "O {0}" - and_word = "a" - - month_names = [ - "", - "január", - "február", - "marec", - "apríl", - "máj", - "jún", - "júl", - "august", - "september", - "október", - "november", - "december", - ] - month_abbreviations = [ - "", - "jan", - "feb", - "mar", - "apr", - "máj", - "jún", - "júl", - "aug", - "sep", - "okt", - "nov", - "dec", - ] - - day_names = [ - "", - "pondelok", - "utorok", - "streda", - "štvrtok", - "piatok", - "sobota", - "nedeľa", - ] - day_abbreviations = ["", "po", "ut", "st", "št", "pi", "so", "ne"] - - def _format_timeframe(self, timeframe, delta): - """Slovak aware time frame format function, takes into account - the differences between past and future forms.""" - form = self.timeframes[timeframe] - if isinstance(form, dict): - if delta == 0: - form = form["zero"] # And *never* use 0 in the singular! - elif delta > 0: - form = form["future"] - else: - form = form["past"] - delta = abs(delta) - - if isinstance(form, list): - if 2 <= delta % 10 <= 4 and (delta % 100 < 10 or delta % 100 >= 20): - form = form[0] - else: - form = form[1] - - return form.format(delta) - - -class FarsiLocale(Locale): - - names = ["fa", "fa_ir"] - - past = "{0} قبل" - future = "در {0}" - - timeframes = { - "now": "اکنون", - "second": "یک لحظه", - "seconds": "{0} ثانیه", - "minute": "یک دقیقه", - "minutes": "{0} دقیقه", - "hour": "یک ساعت", - "hours": "{0} ساعت", - "day": "یک روز", - "days": "{0} روز", - "month": "یک ماه", - "months": "{0} ماه", - "year": "یک سال", - "years": "{0} سال", - } - - meridians = { - "am": "قبل از ظهر", - "pm": "بعد از ظهر", - "AM": "قبل از ظهر", - "PM": "بعد از ظهر", - } - - month_names = [ - "", - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December", - ] - month_abbreviations = [ - "", - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", - ] - - day_names = [ - "", - "دو شنبه", - "سه شنبه", - "چهارشنبه", - "پنجشنبه", - "جمعه", - "شنبه", - "یکشنبه", - ] - day_abbreviations = ["", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] - - -class HebrewLocale(Locale): - - names = ["he", "he_IL"] - - past = "לפני {0}" - future = "בעוד {0}" - and_word = "ו" - - timeframes = { - "now": "הרגע", - "second": "שנייה", - "seconds": "{0} שניות", - "minute": "דקה", - "minutes": "{0} דקות", - "hour": "שעה", - "hours": "{0} שעות", - "2-hours": "שעתיים", - "day": "יום", - "days": "{0} ימים", - "2-days": "יומיים", - "week": "שבוע", - "weeks": "{0} שבועות", - "2-weeks": "שבועיים", - "month": "חודש", - "months": "{0} חודשים", - "2-months": "חודשיים", - "year": "שנה", - "years": "{0} שנים", - "2-years": "שנתיים", - } - - meridians = { - "am": 'לפנ"צ', - "pm": 'אחר"צ', - "AM": "לפני הצהריים", - "PM": "אחרי הצהריים", - } - - month_names = [ - "", - "ינואר", - "פברואר", - "מרץ", - "אפריל", - "מאי", - "יוני", - "יולי", - "אוגוסט", - "ספטמבר", - "אוקטובר", - "נובמבר", - "דצמבר", - ] - month_abbreviations = [ - "", - "ינו׳", - "פבר׳", - "מרץ", - "אפר׳", - "מאי", - "יוני", - "יולי", - "אוג׳", - "ספט׳", - "אוק׳", - "נוב׳", - "דצמ׳", - ] - - day_names = ["", "שני", "שלישי", "רביעי", "חמישי", "שישי", "שבת", "ראשון"] - day_abbreviations = ["", "ב׳", "ג׳", "ד׳", "ה׳", "ו׳", "ש׳", "א׳"] - - def _format_timeframe(self, timeframe, delta): - """Hebrew couple of aware""" - couple = "2-{}".format(timeframe) - single = timeframe.rstrip("s") - if abs(delta) == 2 and couple in self.timeframes: - key = couple - elif abs(delta) == 1 and single in self.timeframes: - key = single - else: - key = timeframe - - return self.timeframes[key].format(trunc(abs(delta))) - - def describe_multi(self, timeframes, only_distance=False): - """Describes a delta within multiple timeframes in plain language. - In Hebrew, the and word behaves a bit differently. - - :param timeframes: a list of string, quantity pairs each representing a timeframe and delta. - :param only_distance: return only distance eg: "2 hours and 11 seconds" without "in" or "ago" keywords - """ - - humanized = "" - for index, (timeframe, delta) in enumerate(timeframes): - last_humanized = self._format_timeframe(timeframe, delta) - if index == 0: - humanized = last_humanized - elif index == len(timeframes) - 1: # Must have at least 2 items - humanized += " " + self.and_word - if last_humanized[0].isdecimal(): - humanized += "־" - humanized += last_humanized - else: # Don't add for the last one - humanized += ", " + last_humanized - - if not only_distance: - humanized = self._format_relative(humanized, timeframe, delta) - - return humanized - - -class MarathiLocale(Locale): - - names = ["mr"] - - past = "{0} आधी" - future = "{0} नंतर" - - timeframes = { - "now": "सद्य", - "second": "एक सेकंद", - "seconds": "{0} सेकंद", - "minute": "एक मिनिट ", - "minutes": "{0} मिनिट ", - "hour": "एक तास", - "hours": "{0} तास", - "day": "एक दिवस", - "days": "{0} दिवस", - "month": "एक महिना ", - "months": "{0} महिने ", - "year": "एक वर्ष ", - "years": "{0} वर्ष ", - } - - meridians = {"am": "सकाळ", "pm": "संध्याकाळ", "AM": "सकाळ", "PM": "संध्याकाळ"} - - month_names = [ - "", - "जानेवारी", - "फेब्रुवारी", - "मार्च", - "एप्रिल", - "मे", - "जून", - "जुलै", - "अॉगस्ट", - "सप्टेंबर", - "अॉक्टोबर", - "नोव्हेंबर", - "डिसेंबर", - ] - month_abbreviations = [ - "", - "जान", - "फेब्रु", - "मार्च", - "एप्रि", - "मे", - "जून", - "जुलै", - "अॉग", - "सप्टें", - "अॉक्टो", - "नोव्हें", - "डिसें", - ] - - day_names = [ - "", - "सोमवार", - "मंगळवार", - "बुधवार", - "गुरुवार", - "शुक्रवार", - "शनिवार", - "रविवार", - ] - day_abbreviations = ["", "सोम", "मंगळ", "बुध", "गुरु", "शुक्र", "शनि", "रवि"] - - -def _map_locales(): - - locales = {} - - for _, cls in inspect.getmembers(sys.modules[__name__], inspect.isclass): - if issubclass(cls, Locale): # pragma: no branch - for name in cls.names: - locales[name.lower()] = cls - - return locales - - -class CatalanLocale(Locale): - names = ["ca", "ca_es", "ca_ad", "ca_fr", "ca_it"] - past = "Fa {0}" - future = "En {0}" - and_word = "i" - - timeframes = { - "now": "Ara mateix", - "second": "un segon", - "seconds": "{0} segons", - "minute": "1 minut", - "minutes": "{0} minuts", - "hour": "una hora", - "hours": "{0} hores", - "day": "un dia", - "days": "{0} dies", - "month": "un mes", - "months": "{0} mesos", - "year": "un any", - "years": "{0} anys", - } - - month_names = [ - "", - "gener", - "febrer", - "març", - "abril", - "maig", - "juny", - "juliol", - "agost", - "setembre", - "octubre", - "novembre", - "desembre", - ] - month_abbreviations = [ - "", - "gen.", - "febr.", - "març", - "abr.", - "maig", - "juny", - "jul.", - "ag.", - "set.", - "oct.", - "nov.", - "des.", - ] - day_names = [ - "", - "dilluns", - "dimarts", - "dimecres", - "dijous", - "divendres", - "dissabte", - "diumenge", - ] - day_abbreviations = [ - "", - "dl.", - "dt.", - "dc.", - "dj.", - "dv.", - "ds.", - "dg.", - ] - - -class BasqueLocale(Locale): - names = ["eu", "eu_eu"] - past = "duela {0}" - future = "{0}" # I don't know what's the right phrase in Basque for the future. - - timeframes = { - "now": "Orain", - "second": "segundo bat", - "seconds": "{0} segundu", - "minute": "minutu bat", - "minutes": "{0} minutu", - "hour": "ordu bat", - "hours": "{0} ordu", - "day": "egun bat", - "days": "{0} egun", - "month": "hilabete bat", - "months": "{0} hilabet", - "year": "urte bat", - "years": "{0} urte", - } - - month_names = [ - "", - "urtarrilak", - "otsailak", - "martxoak", - "apirilak", - "maiatzak", - "ekainak", - "uztailak", - "abuztuak", - "irailak", - "urriak", - "azaroak", - "abenduak", - ] - month_abbreviations = [ - "", - "urt", - "ots", - "mar", - "api", - "mai", - "eka", - "uzt", - "abu", - "ira", - "urr", - "aza", - "abe", - ] - day_names = [ - "", - "astelehena", - "asteartea", - "asteazkena", - "osteguna", - "ostirala", - "larunbata", - "igandea", - ] - day_abbreviations = ["", "al", "ar", "az", "og", "ol", "lr", "ig"] - - -class HungarianLocale(Locale): - - names = ["hu", "hu_hu"] - - past = "{0} ezelőtt" - future = "{0} múlva" - - timeframes = { - "now": "éppen most", - "second": {"past": "egy második", "future": "egy második"}, - "seconds": {"past": "{0} másodpercekkel", "future": "{0} pár másodperc"}, - "minute": {"past": "egy perccel", "future": "egy perc"}, - "minutes": {"past": "{0} perccel", "future": "{0} perc"}, - "hour": {"past": "egy órával", "future": "egy óra"}, - "hours": {"past": "{0} órával", "future": "{0} óra"}, - "day": {"past": "egy nappal", "future": "egy nap"}, - "days": {"past": "{0} nappal", "future": "{0} nap"}, - "month": {"past": "egy hónappal", "future": "egy hónap"}, - "months": {"past": "{0} hónappal", "future": "{0} hónap"}, - "year": {"past": "egy évvel", "future": "egy év"}, - "years": {"past": "{0} évvel", "future": "{0} év"}, - } - - month_names = [ - "", - "január", - "február", - "március", - "április", - "május", - "június", - "július", - "augusztus", - "szeptember", - "október", - "november", - "december", - ] - month_abbreviations = [ - "", - "jan", - "febr", - "márc", - "ápr", - "máj", - "jún", - "júl", - "aug", - "szept", - "okt", - "nov", - "dec", - ] - - day_names = [ - "", - "hétfő", - "kedd", - "szerda", - "csütörtök", - "péntek", - "szombat", - "vasárnap", - ] - day_abbreviations = ["", "hét", "kedd", "szer", "csüt", "pént", "szom", "vas"] - - meridians = {"am": "de", "pm": "du", "AM": "DE", "PM": "DU"} - - def _format_timeframe(self, timeframe, delta): - form = self.timeframes[timeframe] - - if isinstance(form, dict): - if delta > 0: - form = form["future"] - else: - form = form["past"] - - return form.format(abs(delta)) - - -class EsperantoLocale(Locale): - names = ["eo", "eo_xx"] - past = "antaŭ {0}" - future = "post {0}" - - timeframes = { - "now": "nun", - "second": "sekundo", - "seconds": "{0} kelkaj sekundoj", - "minute": "unu minuto", - "minutes": "{0} minutoj", - "hour": "un horo", - "hours": "{0} horoj", - "day": "unu tago", - "days": "{0} tagoj", - "month": "unu monato", - "months": "{0} monatoj", - "year": "unu jaro", - "years": "{0} jaroj", - } - - month_names = [ - "", - "januaro", - "februaro", - "marto", - "aprilo", - "majo", - "junio", - "julio", - "aŭgusto", - "septembro", - "oktobro", - "novembro", - "decembro", - ] - month_abbreviations = [ - "", - "jan", - "feb", - "mar", - "apr", - "maj", - "jun", - "jul", - "aŭg", - "sep", - "okt", - "nov", - "dec", - ] - - day_names = [ - "", - "lundo", - "mardo", - "merkredo", - "ĵaŭdo", - "vendredo", - "sabato", - "dimanĉo", - ] - day_abbreviations = ["", "lun", "mar", "mer", "ĵaŭ", "ven", "sab", "dim"] - - meridians = {"am": "atm", "pm": "ptm", "AM": "ATM", "PM": "PTM"} - - ordinal_day_re = r"((?P[1-3]?[0-9](?=a))a)" - - def _ordinal_number(self, n): - return "{}a".format(n) - - -class ThaiLocale(Locale): - - names = ["th", "th_th"] - - past = "{0}{1}ที่ผ่านมา" - future = "ในอีก{1}{0}" - - timeframes = { - "now": "ขณะนี้", - "second": "วินาที", - "seconds": "{0} ไม่กี่วินาที", - "minute": "1 นาที", - "minutes": "{0} นาที", - "hour": "1 ชั่วโมง", - "hours": "{0} ชั่วโมง", - "day": "1 วัน", - "days": "{0} วัน", - "month": "1 เดือน", - "months": "{0} เดือน", - "year": "1 ปี", - "years": "{0} ปี", - } - - month_names = [ - "", - "มกราคม", - "กุมภาพันธ์", - "มีนาคม", - "เมษายน", - "พฤษภาคม", - "มิถุนายน", - "กรกฎาคม", - "สิงหาคม", - "กันยายน", - "ตุลาคม", - "พฤศจิกายน", - "ธันวาคม", - ] - month_abbreviations = [ - "", - "ม.ค.", - "ก.พ.", - "มี.ค.", - "เม.ย.", - "พ.ค.", - "มิ.ย.", - "ก.ค.", - "ส.ค.", - "ก.ย.", - "ต.ค.", - "พ.ย.", - "ธ.ค.", - ] - - day_names = ["", "จันทร์", "อังคาร", "พุธ", "พฤหัสบดี", "ศุกร์", "เสาร์", "อาทิตย์"] - day_abbreviations = ["", "จ", "อ", "พ", "พฤ", "ศ", "ส", "อา"] - - meridians = {"am": "am", "pm": "pm", "AM": "AM", "PM": "PM"} - - BE_OFFSET = 543 - - def year_full(self, year): - """Thai always use Buddhist Era (BE) which is CE + 543""" - year += self.BE_OFFSET - return "{:04d}".format(year) - - def year_abbreviation(self, year): - """Thai always use Buddhist Era (BE) which is CE + 543""" - year += self.BE_OFFSET - return "{:04d}".format(year)[2:] - - def _format_relative(self, humanized, timeframe, delta): - """Thai normally doesn't have any space between words""" - if timeframe == "now": - return humanized - space = "" if timeframe == "seconds" else " " - direction = self.past if delta < 0 else self.future - - return direction.format(humanized, space) - - -class BengaliLocale(Locale): - - names = ["bn", "bn_bd", "bn_in"] - - past = "{0} আগে" - future = "{0} পরে" - - timeframes = { - "now": "এখন", - "second": "একটি দ্বিতীয়", - "seconds": "{0} সেকেন্ড", - "minute": "এক মিনিট", - "minutes": "{0} মিনিট", - "hour": "এক ঘণ্টা", - "hours": "{0} ঘণ্টা", - "day": "এক দিন", - "days": "{0} দিন", - "month": "এক মাস", - "months": "{0} মাস ", - "year": "এক বছর", - "years": "{0} বছর", - } - - meridians = {"am": "সকাল", "pm": "বিকাল", "AM": "সকাল", "PM": "বিকাল"} - - month_names = [ - "", - "জানুয়ারি", - "ফেব্রুয়ারি", - "মার্চ", - "এপ্রিল", - "মে", - "জুন", - "জুলাই", - "আগস্ট", - "সেপ্টেম্বর", - "অক্টোবর", - "নভেম্বর", - "ডিসেম্বর", - ] - month_abbreviations = [ - "", - "জানু", - "ফেব", - "মার্চ", - "এপ্রি", - "মে", - "জুন", - "জুল", - "অগা", - "সেপ্ট", - "অক্টো", - "নভে", - "ডিসে", - ] - - day_names = [ - "", - "সোমবার", - "মঙ্গলবার", - "বুধবার", - "বৃহস্পতিবার", - "শুক্রবার", - "শনিবার", - "রবিবার", - ] - day_abbreviations = ["", "সোম", "মঙ্গল", "বুধ", "বৃহঃ", "শুক্র", "শনি", "রবি"] - - def _ordinal_number(self, n): - if n > 10 or n == 0: - return "{}তম".format(n) - if n in [1, 5, 7, 8, 9, 10]: - return "{}ম".format(n) - if n in [2, 3]: - return "{}য়".format(n) - if n == 4: - return "{}র্থ".format(n) - if n == 6: - return "{}ষ্ঠ".format(n) - - -class RomanshLocale(Locale): - - names = ["rm", "rm_ch"] - - past = "avant {0}" - future = "en {0}" - - timeframes = { - "now": "en quest mument", - "second": "in secunda", - "seconds": "{0} secundas", - "minute": "ina minuta", - "minutes": "{0} minutas", - "hour": "in'ura", - "hours": "{0} ura", - "day": "in di", - "days": "{0} dis", - "month": "in mais", - "months": "{0} mais", - "year": "in onn", - "years": "{0} onns", - } - - month_names = [ - "", - "schaner", - "favrer", - "mars", - "avrigl", - "matg", - "zercladur", - "fanadur", - "avust", - "settember", - "october", - "november", - "december", - ] - - month_abbreviations = [ - "", - "schan", - "fav", - "mars", - "avr", - "matg", - "zer", - "fan", - "avu", - "set", - "oct", - "nov", - "dec", - ] - - day_names = [ - "", - "glindesdi", - "mardi", - "mesemna", - "gievgia", - "venderdi", - "sonda", - "dumengia", - ] - - day_abbreviations = ["", "gli", "ma", "me", "gie", "ve", "so", "du"] - - -class RomanianLocale(Locale): - names = ["ro", "ro_ro"] - - past = "{0} în urmă" - future = "peste {0}" - and_word = "și" - - timeframes = { - "now": "acum", - "second": "o secunda", - "seconds": "{0} câteva secunde", - "minute": "un minut", - "minutes": "{0} minute", - "hour": "o oră", - "hours": "{0} ore", - "day": "o zi", - "days": "{0} zile", - "month": "o lună", - "months": "{0} luni", - "year": "un an", - "years": "{0} ani", - } - - month_names = [ - "", - "ianuarie", - "februarie", - "martie", - "aprilie", - "mai", - "iunie", - "iulie", - "august", - "septembrie", - "octombrie", - "noiembrie", - "decembrie", - ] - month_abbreviations = [ - "", - "ian", - "febr", - "mart", - "apr", - "mai", - "iun", - "iul", - "aug", - "sept", - "oct", - "nov", - "dec", - ] - - day_names = [ - "", - "luni", - "marți", - "miercuri", - "joi", - "vineri", - "sâmbătă", - "duminică", - ] - day_abbreviations = ["", "Lun", "Mar", "Mie", "Joi", "Vin", "Sâm", "Dum"] - - -class SlovenianLocale(Locale): - names = ["sl", "sl_si"] - - past = "pred {0}" - future = "čez {0}" - and_word = "in" - - timeframes = { - "now": "zdaj", - "second": "sekundo", - "seconds": "{0} sekund", - "minute": "minuta", - "minutes": "{0} minutami", - "hour": "uro", - "hours": "{0} ur", - "day": "dan", - "days": "{0} dni", - "month": "mesec", - "months": "{0} mesecev", - "year": "leto", - "years": "{0} let", - } - - meridians = {"am": "", "pm": "", "AM": "", "PM": ""} - - month_names = [ - "", - "Januar", - "Februar", - "Marec", - "April", - "Maj", - "Junij", - "Julij", - "Avgust", - "September", - "Oktober", - "November", - "December", - ] - - month_abbreviations = [ - "", - "Jan", - "Feb", - "Mar", - "Apr", - "Maj", - "Jun", - "Jul", - "Avg", - "Sep", - "Okt", - "Nov", - "Dec", - ] - - day_names = [ - "", - "Ponedeljek", - "Torek", - "Sreda", - "Četrtek", - "Petek", - "Sobota", - "Nedelja", - ] - - day_abbreviations = ["", "Pon", "Tor", "Sre", "Čet", "Pet", "Sob", "Ned"] - - -class IndonesianLocale(Locale): - - names = ["id", "id_id"] - - past = "{0} yang lalu" - future = "dalam {0}" - and_word = "dan" - - timeframes = { - "now": "baru saja", - "second": "1 sebentar", - "seconds": "{0} detik", - "minute": "1 menit", - "minutes": "{0} menit", - "hour": "1 jam", - "hours": "{0} jam", - "day": "1 hari", - "days": "{0} hari", - "month": "1 bulan", - "months": "{0} bulan", - "year": "1 tahun", - "years": "{0} tahun", - } - - meridians = {"am": "", "pm": "", "AM": "", "PM": ""} - - month_names = [ - "", - "Januari", - "Februari", - "Maret", - "April", - "Mei", - "Juni", - "Juli", - "Agustus", - "September", - "Oktober", - "November", - "Desember", - ] - - month_abbreviations = [ - "", - "Jan", - "Feb", - "Mar", - "Apr", - "Mei", - "Jun", - "Jul", - "Ags", - "Sept", - "Okt", - "Nov", - "Des", - ] - - day_names = ["", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Minggu"] - - day_abbreviations = [ - "", - "Senin", - "Selasa", - "Rabu", - "Kamis", - "Jumat", - "Sabtu", - "Minggu", - ] - - -class NepaliLocale(Locale): - names = ["ne", "ne_np"] - - past = "{0} पहिले" - future = "{0} पछी" - - timeframes = { - "now": "अहिले", - "second": "एक सेकेन्ड", - "seconds": "{0} सेकण्ड", - "minute": "मिनेट", - "minutes": "{0} मिनेट", - "hour": "एक घण्टा", - "hours": "{0} घण्टा", - "day": "एक दिन", - "days": "{0} दिन", - "month": "एक महिना", - "months": "{0} महिना", - "year": "एक बर्ष", - "years": "बर्ष", - } - - meridians = {"am": "पूर्वाह्न", "pm": "अपरान्ह", "AM": "पूर्वाह्न", "PM": "अपरान्ह"} - - month_names = [ - "", - "जनवरी", - "फेब्रुअरी", - "मार्च", - "एप्रील", - "मे", - "जुन", - "जुलाई", - "अगष्ट", - "सेप्टेम्बर", - "अक्टोबर", - "नोवेम्बर", - "डिसेम्बर", - ] - month_abbreviations = [ - "", - "जन", - "फेब", - "मार्च", - "एप्रील", - "मे", - "जुन", - "जुलाई", - "अग", - "सेप", - "अक्ट", - "नोव", - "डिस", - ] - - day_names = [ - "", - "सोमवार", - "मंगलवार", - "बुधवार", - "बिहिवार", - "शुक्रवार", - "शनिवार", - "आइतवार", - ] - - day_abbreviations = ["", "सोम", "मंगल", "बुध", "बिहि", "शुक्र", "शनि", "आइत"] - - -class EstonianLocale(Locale): - names = ["ee", "et"] - - past = "{0} tagasi" - future = "{0} pärast" - and_word = "ja" - - timeframes = { - "now": {"past": "just nüüd", "future": "just nüüd"}, - "second": {"past": "üks sekund", "future": "ühe sekundi"}, - "seconds": {"past": "{0} sekundit", "future": "{0} sekundi"}, - "minute": {"past": "üks minut", "future": "ühe minuti"}, - "minutes": {"past": "{0} minutit", "future": "{0} minuti"}, - "hour": {"past": "tund aega", "future": "tunni aja"}, - "hours": {"past": "{0} tundi", "future": "{0} tunni"}, - "day": {"past": "üks päev", "future": "ühe päeva"}, - "days": {"past": "{0} päeva", "future": "{0} päeva"}, - "month": {"past": "üks kuu", "future": "ühe kuu"}, - "months": {"past": "{0} kuud", "future": "{0} kuu"}, - "year": {"past": "üks aasta", "future": "ühe aasta"}, - "years": {"past": "{0} aastat", "future": "{0} aasta"}, - } - - month_names = [ - "", - "Jaanuar", - "Veebruar", - "Märts", - "Aprill", - "Mai", - "Juuni", - "Juuli", - "August", - "September", - "Oktoober", - "November", - "Detsember", - ] - month_abbreviations = [ - "", - "Jan", - "Veb", - "Mär", - "Apr", - "Mai", - "Jun", - "Jul", - "Aug", - "Sep", - "Okt", - "Nov", - "Dets", - ] - - day_names = [ - "", - "Esmaspäev", - "Teisipäev", - "Kolmapäev", - "Neljapäev", - "Reede", - "Laupäev", - "Pühapäev", - ] - day_abbreviations = ["", "Esm", "Teis", "Kolm", "Nelj", "Re", "Lau", "Püh"] - - def _format_timeframe(self, timeframe, delta): - form = self.timeframes[timeframe] - if delta > 0: - form = form["future"] - else: - form = form["past"] - return form.format(abs(delta)) - - -class SwahiliLocale(Locale): - - names = [ - "sw", - "sw_ke", - "sw_tz", - ] - - past = "{0} iliyopita" - future = "muda wa {0}" - and_word = "na" - - timeframes = { - "now": "sasa hivi", - "second": "sekunde", - "seconds": "sekunde {0}", - "minute": "dakika moja", - "minutes": "dakika {0}", - "hour": "saa moja", - "hours": "saa {0}", - "day": "siku moja", - "days": "siku {0}", - "week": "wiki moja", - "weeks": "wiki {0}", - "month": "mwezi moja", - "months": "miezi {0}", - "year": "mwaka moja", - "years": "miaka {0}", - } - - meridians = {"am": "asu", "pm": "mch", "AM": "ASU", "PM": "MCH"} - - month_names = [ - "", - "Januari", - "Februari", - "Machi", - "Aprili", - "Mei", - "Juni", - "Julai", - "Agosti", - "Septemba", - "Oktoba", - "Novemba", - "Desemba", - ] - month_abbreviations = [ - "", - "Jan", - "Feb", - "Mac", - "Apr", - "Mei", - "Jun", - "Jul", - "Ago", - "Sep", - "Okt", - "Nov", - "Des", - ] - - day_names = [ - "", - "Jumatatu", - "Jumanne", - "Jumatano", - "Alhamisi", - "Ijumaa", - "Jumamosi", - "Jumapili", - ] - day_abbreviations = [ - "", - "Jumatatu", - "Jumanne", - "Jumatano", - "Alhamisi", - "Ijumaa", - "Jumamosi", - "Jumapili", - ] - - -_locales = _map_locales() diff --git a/client/ayon_core/vendor/python/python_2/arrow/parser.py b/client/ayon_core/vendor/python/python_2/arrow/parser.py deleted file mode 100644 index 243fd1721c..0000000000 --- a/client/ayon_core/vendor/python/python_2/arrow/parser.py +++ /dev/null @@ -1,596 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, unicode_literals - -import re -from datetime import datetime, timedelta - -from dateutil import tz - -from arrow import locales -from arrow.util import iso_to_gregorian, next_weekday, normalize_timestamp - -try: - from functools import lru_cache -except ImportError: # pragma: no cover - from backports.functools_lru_cache import lru_cache # pragma: no cover - - -class ParserError(ValueError): - pass - - -# Allows for ParserErrors to be propagated from _build_datetime() -# when day_of_year errors occur. -# Before this, the ParserErrors were caught by the try/except in -# _parse_multiformat() and the appropriate error message was not -# transmitted to the user. -class ParserMatchError(ParserError): - pass - - -class DateTimeParser(object): - - _FORMAT_RE = re.compile( - r"(YYY?Y?|MM?M?M?|Do|DD?D?D?|d?d?d?d|HH?|hh?|mm?|ss?|S+|ZZ?Z?|a|A|x|X|W)" - ) - _ESCAPE_RE = re.compile(r"\[[^\[\]]*\]") - - _ONE_OR_TWO_DIGIT_RE = re.compile(r"\d{1,2}") - _ONE_OR_TWO_OR_THREE_DIGIT_RE = re.compile(r"\d{1,3}") - _ONE_OR_MORE_DIGIT_RE = re.compile(r"\d+") - _TWO_DIGIT_RE = re.compile(r"\d{2}") - _THREE_DIGIT_RE = re.compile(r"\d{3}") - _FOUR_DIGIT_RE = re.compile(r"\d{4}") - _TZ_Z_RE = re.compile(r"([\+\-])(\d{2})(?:(\d{2}))?|Z") - _TZ_ZZ_RE = re.compile(r"([\+\-])(\d{2})(?:\:(\d{2}))?|Z") - _TZ_NAME_RE = re.compile(r"\w[\w+\-/]+") - # NOTE: timestamps cannot be parsed from natural language strings (by removing the ^...$) because it will - # break cases like "15 Jul 2000" and a format list (see issue #447) - _TIMESTAMP_RE = re.compile(r"^\-?\d+\.?\d+$") - _TIMESTAMP_EXPANDED_RE = re.compile(r"^\-?\d+$") - _TIME_RE = re.compile(r"^(\d{2})(?:\:?(\d{2}))?(?:\:?(\d{2}))?(?:([\.\,])(\d+))?$") - _WEEK_DATE_RE = re.compile(r"(?P\d{4})[\-]?W(?P\d{2})[\-]?(?P\d)?") - - _BASE_INPUT_RE_MAP = { - "YYYY": _FOUR_DIGIT_RE, - "YY": _TWO_DIGIT_RE, - "MM": _TWO_DIGIT_RE, - "M": _ONE_OR_TWO_DIGIT_RE, - "DDDD": _THREE_DIGIT_RE, - "DDD": _ONE_OR_TWO_OR_THREE_DIGIT_RE, - "DD": _TWO_DIGIT_RE, - "D": _ONE_OR_TWO_DIGIT_RE, - "HH": _TWO_DIGIT_RE, - "H": _ONE_OR_TWO_DIGIT_RE, - "hh": _TWO_DIGIT_RE, - "h": _ONE_OR_TWO_DIGIT_RE, - "mm": _TWO_DIGIT_RE, - "m": _ONE_OR_TWO_DIGIT_RE, - "ss": _TWO_DIGIT_RE, - "s": _ONE_OR_TWO_DIGIT_RE, - "X": _TIMESTAMP_RE, - "x": _TIMESTAMP_EXPANDED_RE, - "ZZZ": _TZ_NAME_RE, - "ZZ": _TZ_ZZ_RE, - "Z": _TZ_Z_RE, - "S": _ONE_OR_MORE_DIGIT_RE, - "W": _WEEK_DATE_RE, - } - - SEPARATORS = ["-", "/", "."] - - def __init__(self, locale="en_us", cache_size=0): - - self.locale = locales.get_locale(locale) - self._input_re_map = self._BASE_INPUT_RE_MAP.copy() - self._input_re_map.update( - { - "MMMM": self._generate_choice_re( - self.locale.month_names[1:], re.IGNORECASE - ), - "MMM": self._generate_choice_re( - self.locale.month_abbreviations[1:], re.IGNORECASE - ), - "Do": re.compile(self.locale.ordinal_day_re), - "dddd": self._generate_choice_re( - self.locale.day_names[1:], re.IGNORECASE - ), - "ddd": self._generate_choice_re( - self.locale.day_abbreviations[1:], re.IGNORECASE - ), - "d": re.compile(r"[1-7]"), - "a": self._generate_choice_re( - (self.locale.meridians["am"], self.locale.meridians["pm"]) - ), - # note: 'A' token accepts both 'am/pm' and 'AM/PM' formats to - # ensure backwards compatibility of this token - "A": self._generate_choice_re(self.locale.meridians.values()), - } - ) - if cache_size > 0: - self._generate_pattern_re = lru_cache(maxsize=cache_size)( - self._generate_pattern_re - ) - - # TODO: since we support more than ISO 8601, we should rename this function - # IDEA: break into multiple functions - def parse_iso(self, datetime_string, normalize_whitespace=False): - - if normalize_whitespace: - datetime_string = re.sub(r"\s+", " ", datetime_string.strip()) - - has_space_divider = " " in datetime_string - has_t_divider = "T" in datetime_string - - num_spaces = datetime_string.count(" ") - if has_space_divider and num_spaces != 1 or has_t_divider and num_spaces > 0: - raise ParserError( - "Expected an ISO 8601-like string, but was given '{}'. Try passing in a format string to resolve this.".format( - datetime_string - ) - ) - - has_time = has_space_divider or has_t_divider - has_tz = False - - # date formats (ISO 8601 and others) to test against - # NOTE: YYYYMM is omitted to avoid confusion with YYMMDD (no longer part of ISO 8601, but is still often used) - formats = [ - "YYYY-MM-DD", - "YYYY-M-DD", - "YYYY-M-D", - "YYYY/MM/DD", - "YYYY/M/DD", - "YYYY/M/D", - "YYYY.MM.DD", - "YYYY.M.DD", - "YYYY.M.D", - "YYYYMMDD", - "YYYY-DDDD", - "YYYYDDDD", - "YYYY-MM", - "YYYY/MM", - "YYYY.MM", - "YYYY", - "W", - ] - - if has_time: - - if has_space_divider: - date_string, time_string = datetime_string.split(" ", 1) - else: - date_string, time_string = datetime_string.split("T", 1) - - time_parts = re.split(r"[\+\-Z]", time_string, 1, re.IGNORECASE) - - time_components = self._TIME_RE.match(time_parts[0]) - - if time_components is None: - raise ParserError( - "Invalid time component provided. Please specify a format or provide a valid time component in the basic or extended ISO 8601 time format." - ) - - ( - hours, - minutes, - seconds, - subseconds_sep, - subseconds, - ) = time_components.groups() - - has_tz = len(time_parts) == 2 - has_minutes = minutes is not None - has_seconds = seconds is not None - has_subseconds = subseconds is not None - - is_basic_time_format = ":" not in time_parts[0] - tz_format = "Z" - - # use 'ZZ' token instead since tz offset is present in non-basic format - if has_tz and ":" in time_parts[1]: - tz_format = "ZZ" - - time_sep = "" if is_basic_time_format else ":" - - if has_subseconds: - time_string = "HH{time_sep}mm{time_sep}ss{subseconds_sep}S".format( - time_sep=time_sep, subseconds_sep=subseconds_sep - ) - elif has_seconds: - time_string = "HH{time_sep}mm{time_sep}ss".format(time_sep=time_sep) - elif has_minutes: - time_string = "HH{time_sep}mm".format(time_sep=time_sep) - else: - time_string = "HH" - - if has_space_divider: - formats = ["{} {}".format(f, time_string) for f in formats] - else: - formats = ["{}T{}".format(f, time_string) for f in formats] - - if has_time and has_tz: - # Add "Z" or "ZZ" to the format strings to indicate to - # _parse_token() that a timezone needs to be parsed - formats = ["{}{}".format(f, tz_format) for f in formats] - - return self._parse_multiformat(datetime_string, formats) - - def parse(self, datetime_string, fmt, normalize_whitespace=False): - - if normalize_whitespace: - datetime_string = re.sub(r"\s+", " ", datetime_string) - - if isinstance(fmt, list): - return self._parse_multiformat(datetime_string, fmt) - - fmt_tokens, fmt_pattern_re = self._generate_pattern_re(fmt) - - match = fmt_pattern_re.search(datetime_string) - - if match is None: - raise ParserMatchError( - "Failed to match '{}' when parsing '{}'".format(fmt, datetime_string) - ) - - parts = {} - for token in fmt_tokens: - if token == "Do": - value = match.group("value") - elif token == "W": - value = (match.group("year"), match.group("week"), match.group("day")) - else: - value = match.group(token) - self._parse_token(token, value, parts) - - return self._build_datetime(parts) - - def _generate_pattern_re(self, fmt): - - # fmt is a string of tokens like 'YYYY-MM-DD' - # we construct a new string by replacing each - # token by its pattern: - # 'YYYY-MM-DD' -> '(?P\d{4})-(?P\d{2})-(?P
\d{2})' - tokens = [] - offset = 0 - - # Escape all special RegEx chars - escaped_fmt = re.escape(fmt) - - # Extract the bracketed expressions to be reinserted later. - escaped_fmt = re.sub(self._ESCAPE_RE, "#", escaped_fmt) - - # Any number of S is the same as one. - # TODO: allow users to specify the number of digits to parse - escaped_fmt = re.sub(r"S+", "S", escaped_fmt) - - escaped_data = re.findall(self._ESCAPE_RE, fmt) - - fmt_pattern = escaped_fmt - - for m in self._FORMAT_RE.finditer(escaped_fmt): - token = m.group(0) - try: - input_re = self._input_re_map[token] - except KeyError: - raise ParserError("Unrecognized token '{}'".format(token)) - input_pattern = "(?P<{}>{})".format(token, input_re.pattern) - tokens.append(token) - # a pattern doesn't have the same length as the token - # it replaces! We keep the difference in the offset variable. - # This works because the string is scanned left-to-right and matches - # are returned in the order found by finditer. - fmt_pattern = ( - fmt_pattern[: m.start() + offset] - + input_pattern - + fmt_pattern[m.end() + offset :] - ) - offset += len(input_pattern) - (m.end() - m.start()) - - final_fmt_pattern = "" - split_fmt = fmt_pattern.split(r"\#") - - # Due to the way Python splits, 'split_fmt' will always be longer - for i in range(len(split_fmt)): - final_fmt_pattern += split_fmt[i] - if i < len(escaped_data): - final_fmt_pattern += escaped_data[i][1:-1] - - # Wrap final_fmt_pattern in a custom word boundary to strictly - # match the formatting pattern and filter out date and time formats - # that include junk such as: blah1998-09-12 blah, blah 1998-09-12blah, - # blah1998-09-12blah. The custom word boundary matches every character - # that is not a whitespace character to allow for searching for a date - # and time string in a natural language sentence. Therefore, searching - # for a string of the form YYYY-MM-DD in "blah 1998-09-12 blah" will - # work properly. - # Certain punctuation before or after the target pattern such as - # "1998-09-12," is permitted. For the full list of valid punctuation, - # see the documentation. - - starting_word_boundary = ( - r"(?\s])" # This is the list of punctuation that is ok before the pattern (i.e. "It can't not be these characters before the pattern") - r"(\b|^)" # The \b is to block cases like 1201912 but allow 201912 for pattern YYYYMM. The ^ was necessary to allow a negative number through i.e. before epoch numbers - ) - ending_word_boundary = ( - r"(?=[\,\.\;\:\?\!\"\'\`\[\]\{\}\(\)\<\>]?" # Positive lookahead stating that these punctuation marks can appear after the pattern at most 1 time - r"(?!\S))" # Don't allow any non-whitespace character after the punctuation - ) - bounded_fmt_pattern = r"{}{}{}".format( - starting_word_boundary, final_fmt_pattern, ending_word_boundary - ) - - return tokens, re.compile(bounded_fmt_pattern, flags=re.IGNORECASE) - - def _parse_token(self, token, value, parts): - - if token == "YYYY": - parts["year"] = int(value) - - elif token == "YY": - value = int(value) - parts["year"] = 1900 + value if value > 68 else 2000 + value - - elif token in ["MMMM", "MMM"]: - parts["month"] = self.locale.month_number(value.lower()) - - elif token in ["MM", "M"]: - parts["month"] = int(value) - - elif token in ["DDDD", "DDD"]: - parts["day_of_year"] = int(value) - - elif token in ["DD", "D"]: - parts["day"] = int(value) - - elif token == "Do": - parts["day"] = int(value) - - elif token == "dddd": - # locale day names are 1-indexed - day_of_week = [x.lower() for x in self.locale.day_names].index( - value.lower() - ) - parts["day_of_week"] = day_of_week - 1 - - elif token == "ddd": - # locale day abbreviations are 1-indexed - day_of_week = [x.lower() for x in self.locale.day_abbreviations].index( - value.lower() - ) - parts["day_of_week"] = day_of_week - 1 - - elif token.upper() in ["HH", "H"]: - parts["hour"] = int(value) - - elif token in ["mm", "m"]: - parts["minute"] = int(value) - - elif token in ["ss", "s"]: - parts["second"] = int(value) - - elif token == "S": - # We have the *most significant* digits of an arbitrary-precision integer. - # We want the six most significant digits as an integer, rounded. - # IDEA: add nanosecond support somehow? Need datetime support for it first. - value = value.ljust(7, str("0")) - - # floating-point (IEEE-754) defaults to half-to-even rounding - seventh_digit = int(value[6]) - if seventh_digit == 5: - rounding = int(value[5]) % 2 - elif seventh_digit > 5: - rounding = 1 - else: - rounding = 0 - - parts["microsecond"] = int(value[:6]) + rounding - - elif token == "X": - parts["timestamp"] = float(value) - - elif token == "x": - parts["expanded_timestamp"] = int(value) - - elif token in ["ZZZ", "ZZ", "Z"]: - parts["tzinfo"] = TzinfoParser.parse(value) - - elif token in ["a", "A"]: - if value in (self.locale.meridians["am"], self.locale.meridians["AM"]): - parts["am_pm"] = "am" - elif value in (self.locale.meridians["pm"], self.locale.meridians["PM"]): - parts["am_pm"] = "pm" - - elif token == "W": - parts["weekdate"] = value - - @staticmethod - def _build_datetime(parts): - - weekdate = parts.get("weekdate") - - if weekdate is not None: - # we can use strptime (%G, %V, %u) in python 3.6 but these tokens aren't available before that - year, week = int(weekdate[0]), int(weekdate[1]) - - if weekdate[2] is not None: - day = int(weekdate[2]) - else: - # day not given, default to 1 - day = 1 - - dt = iso_to_gregorian(year, week, day) - parts["year"] = dt.year - parts["month"] = dt.month - parts["day"] = dt.day - - timestamp = parts.get("timestamp") - - if timestamp is not None: - return datetime.fromtimestamp(timestamp, tz=tz.tzutc()) - - expanded_timestamp = parts.get("expanded_timestamp") - - if expanded_timestamp is not None: - return datetime.fromtimestamp( - normalize_timestamp(expanded_timestamp), - tz=tz.tzutc(), - ) - - day_of_year = parts.get("day_of_year") - - if day_of_year is not None: - year = parts.get("year") - month = parts.get("month") - if year is None: - raise ParserError( - "Year component is required with the DDD and DDDD tokens." - ) - - if month is not None: - raise ParserError( - "Month component is not allowed with the DDD and DDDD tokens." - ) - - date_string = "{}-{}".format(year, day_of_year) - try: - dt = datetime.strptime(date_string, "%Y-%j") - except ValueError: - raise ParserError( - "The provided day of year '{}' is invalid.".format(day_of_year) - ) - - parts["year"] = dt.year - parts["month"] = dt.month - parts["day"] = dt.day - - day_of_week = parts.get("day_of_week") - day = parts.get("day") - - # If day is passed, ignore day of week - if day_of_week is not None and day is None: - year = parts.get("year", 1970) - month = parts.get("month", 1) - day = 1 - - # dddd => first day of week after epoch - # dddd YYYY => first day of week in specified year - # dddd MM YYYY => first day of week in specified year and month - # dddd MM => first day after epoch in specified month - next_weekday_dt = next_weekday(datetime(year, month, day), day_of_week) - parts["year"] = next_weekday_dt.year - parts["month"] = next_weekday_dt.month - parts["day"] = next_weekday_dt.day - - am_pm = parts.get("am_pm") - hour = parts.get("hour", 0) - - if am_pm == "pm" and hour < 12: - hour += 12 - elif am_pm == "am" and hour == 12: - hour = 0 - - # Support for midnight at the end of day - if hour == 24: - if parts.get("minute", 0) != 0: - raise ParserError("Midnight at the end of day must not contain minutes") - if parts.get("second", 0) != 0: - raise ParserError("Midnight at the end of day must not contain seconds") - if parts.get("microsecond", 0) != 0: - raise ParserError( - "Midnight at the end of day must not contain microseconds" - ) - hour = 0 - day_increment = 1 - else: - day_increment = 0 - - # account for rounding up to 1000000 - microsecond = parts.get("microsecond", 0) - if microsecond == 1000000: - microsecond = 0 - second_increment = 1 - else: - second_increment = 0 - - increment = timedelta(days=day_increment, seconds=second_increment) - - return ( - datetime( - year=parts.get("year", 1), - month=parts.get("month", 1), - day=parts.get("day", 1), - hour=hour, - minute=parts.get("minute", 0), - second=parts.get("second", 0), - microsecond=microsecond, - tzinfo=parts.get("tzinfo"), - ) - + increment - ) - - def _parse_multiformat(self, string, formats): - - _datetime = None - - for fmt in formats: - try: - _datetime = self.parse(string, fmt) - break - except ParserMatchError: - pass - - if _datetime is None: - raise ParserError( - "Could not match input '{}' to any of the following formats: {}".format( - string, ", ".join(formats) - ) - ) - - return _datetime - - # generates a capture group of choices separated by an OR operator - @staticmethod - def _generate_choice_re(choices, flags=0): - return re.compile(r"({})".format("|".join(choices)), flags=flags) - - -class TzinfoParser(object): - _TZINFO_RE = re.compile(r"^([\+\-])?(\d{2})(?:\:?(\d{2}))?$") - - @classmethod - def parse(cls, tzinfo_string): - - tzinfo = None - - if tzinfo_string == "local": - tzinfo = tz.tzlocal() - - elif tzinfo_string in ["utc", "UTC", "Z"]: - tzinfo = tz.tzutc() - - else: - - iso_match = cls._TZINFO_RE.match(tzinfo_string) - - if iso_match: - sign, hours, minutes = iso_match.groups() - if minutes is None: - minutes = 0 - seconds = int(hours) * 3600 + int(minutes) * 60 - - if sign == "-": - seconds *= -1 - - tzinfo = tz.tzoffset(None, seconds) - - else: - tzinfo = tz.gettz(tzinfo_string) - - if tzinfo is None: - raise ParserError( - 'Could not parse timezone expression "{}"'.format(tzinfo_string) - ) - - return tzinfo diff --git a/client/ayon_core/vendor/python/python_2/arrow/util.py b/client/ayon_core/vendor/python/python_2/arrow/util.py deleted file mode 100644 index acce8878df..0000000000 --- a/client/ayon_core/vendor/python/python_2/arrow/util.py +++ /dev/null @@ -1,115 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import - -import datetime -import numbers - -from dateutil.rrule import WEEKLY, rrule - -from arrow.constants import MAX_TIMESTAMP, MAX_TIMESTAMP_MS, MAX_TIMESTAMP_US - - -def next_weekday(start_date, weekday): - """Get next weekday from the specified start date. - - :param start_date: Datetime object representing the start date. - :param weekday: Next weekday to obtain. Can be a value between 0 (Monday) and 6 (Sunday). - :return: Datetime object corresponding to the next weekday after start_date. - - Usage:: - - # Get first Monday after epoch - >>> next_weekday(datetime(1970, 1, 1), 0) - 1970-01-05 00:00:00 - - # Get first Thursday after epoch - >>> next_weekday(datetime(1970, 1, 1), 3) - 1970-01-01 00:00:00 - - # Get first Sunday after epoch - >>> next_weekday(datetime(1970, 1, 1), 6) - 1970-01-04 00:00:00 - """ - if weekday < 0 or weekday > 6: - raise ValueError("Weekday must be between 0 (Monday) and 6 (Sunday).") - return rrule(freq=WEEKLY, dtstart=start_date, byweekday=weekday, count=1)[0] - - -def total_seconds(td): - """Get total seconds for timedelta.""" - return td.total_seconds() - - -def is_timestamp(value): - """Check if value is a valid timestamp.""" - if isinstance(value, bool): - return False - if not ( - isinstance(value, numbers.Integral) - or isinstance(value, float) - or isinstance(value, str) - ): - return False - try: - float(value) - return True - except ValueError: - return False - - -def normalize_timestamp(timestamp): - """Normalize millisecond and microsecond timestamps into normal timestamps.""" - if timestamp > MAX_TIMESTAMP: - if timestamp < MAX_TIMESTAMP_MS: - timestamp /= 1e3 - elif timestamp < MAX_TIMESTAMP_US: - timestamp /= 1e6 - else: - raise ValueError( - "The specified timestamp '{}' is too large.".format(timestamp) - ) - return timestamp - - -# Credit to https://stackoverflow.com/a/1700069 -def iso_to_gregorian(iso_year, iso_week, iso_day): - """Converts an ISO week date tuple into a datetime object.""" - - if not 1 <= iso_week <= 53: - raise ValueError("ISO Calendar week value must be between 1-53.") - - if not 1 <= iso_day <= 7: - raise ValueError("ISO Calendar day value must be between 1-7") - - # The first week of the year always contains 4 Jan. - fourth_jan = datetime.date(iso_year, 1, 4) - delta = datetime.timedelta(fourth_jan.isoweekday() - 1) - year_start = fourth_jan - delta - gregorian = year_start + datetime.timedelta(days=iso_day - 1, weeks=iso_week - 1) - - return gregorian - - -def validate_bounds(bounds): - if bounds != "()" and bounds != "(]" and bounds != "[)" and bounds != "[]": - raise ValueError( - 'Invalid bounds. Please select between "()", "(]", "[)", or "[]".' - ) - - -# Python 2.7 / 3.0+ definitions for isstr function. - -try: # pragma: no cover - basestring - - def isstr(s): - return isinstance(s, basestring) # noqa: F821 - - -except NameError: # pragma: no cover - - def isstr(s): - return isinstance(s, str) - - -__all__ = ["next_weekday", "total_seconds", "is_timestamp", "isstr", "iso_to_gregorian"] diff --git a/client/ayon_core/vendor/python/python_2/attr/__init__.py b/client/ayon_core/vendor/python/python_2/attr/__init__.py deleted file mode 100644 index f95c96dd57..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/__init__.py +++ /dev/null @@ -1,80 +0,0 @@ -# SPDX-License-Identifier: MIT - -from __future__ import absolute_import, division, print_function - -import sys - -from functools import partial - -from . import converters, exceptions, filters, setters, validators -from ._cmp import cmp_using -from ._config import get_run_validators, set_run_validators -from ._funcs import asdict, assoc, astuple, evolve, has, resolve_types -from ._make import ( - NOTHING, - Attribute, - Factory, - attrib, - attrs, - fields, - fields_dict, - make_class, - validate, -) -from ._version_info import VersionInfo - - -__version__ = "21.4.0" -__version_info__ = VersionInfo._from_version_string(__version__) - -__title__ = "attrs" -__description__ = "Classes Without Boilerplate" -__url__ = "https://www.attrs.org/" -__uri__ = __url__ -__doc__ = __description__ + " <" + __uri__ + ">" - -__author__ = "Hynek Schlawack" -__email__ = "hs@ox.cx" - -__license__ = "MIT" -__copyright__ = "Copyright (c) 2015 Hynek Schlawack" - - -s = attributes = attrs -ib = attr = attrib -dataclass = partial(attrs, auto_attribs=True) # happy Easter ;) - -__all__ = [ - "Attribute", - "Factory", - "NOTHING", - "asdict", - "assoc", - "astuple", - "attr", - "attrib", - "attributes", - "attrs", - "cmp_using", - "converters", - "evolve", - "exceptions", - "fields", - "fields_dict", - "filters", - "get_run_validators", - "has", - "ib", - "make_class", - "resolve_types", - "s", - "set_run_validators", - "setters", - "validate", - "validators", -] - -if sys.version_info[:2] >= (3, 6): - from ._next_gen import define, field, frozen, mutable # noqa: F401 - - __all__.extend(("define", "field", "frozen", "mutable")) diff --git a/client/ayon_core/vendor/python/python_2/attr/__init__.pyi b/client/ayon_core/vendor/python/python_2/attr/__init__.pyi deleted file mode 100644 index c0a2126503..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/__init__.pyi +++ /dev/null @@ -1,484 +0,0 @@ -import sys - -from typing import ( - Any, - Callable, - Dict, - Generic, - List, - Mapping, - Optional, - Sequence, - Tuple, - Type, - TypeVar, - Union, - overload, -) - -# `import X as X` is required to make these public -from . import converters as converters -from . import exceptions as exceptions -from . import filters as filters -from . import setters as setters -from . import validators as validators -from ._version_info import VersionInfo - -__version__: str -__version_info__: VersionInfo -__title__: str -__description__: str -__url__: str -__uri__: str -__author__: str -__email__: str -__license__: str -__copyright__: str - -_T = TypeVar("_T") -_C = TypeVar("_C", bound=type) - -_EqOrderType = Union[bool, Callable[[Any], Any]] -_ValidatorType = Callable[[Any, Attribute[_T], _T], Any] -_ConverterType = Callable[[Any], Any] -_FilterType = Callable[[Attribute[_T], _T], bool] -_ReprType = Callable[[Any], str] -_ReprArgType = Union[bool, _ReprType] -_OnSetAttrType = Callable[[Any, Attribute[Any], Any], Any] -_OnSetAttrArgType = Union[ - _OnSetAttrType, List[_OnSetAttrType], setters._NoOpType -] -_FieldTransformer = Callable[ - [type, List[Attribute[Any]]], List[Attribute[Any]] -] -_CompareWithType = Callable[[Any, Any], bool] -# FIXME: in reality, if multiple validators are passed they must be in a list -# or tuple, but those are invariant and so would prevent subtypes of -# _ValidatorType from working when passed in a list or tuple. -_ValidatorArgType = Union[_ValidatorType[_T], Sequence[_ValidatorType[_T]]] - -# _make -- - -NOTHING: object - -# NOTE: Factory lies about its return type to make this possible: -# `x: List[int] # = Factory(list)` -# Work around mypy issue #4554 in the common case by using an overload. -if sys.version_info >= (3, 8): - from typing import Literal - @overload - def Factory(factory: Callable[[], _T]) -> _T: ... - @overload - def Factory( - factory: Callable[[Any], _T], - takes_self: Literal[True], - ) -> _T: ... - @overload - def Factory( - factory: Callable[[], _T], - takes_self: Literal[False], - ) -> _T: ... - -else: - @overload - def Factory(factory: Callable[[], _T]) -> _T: ... - @overload - def Factory( - factory: Union[Callable[[Any], _T], Callable[[], _T]], - takes_self: bool = ..., - ) -> _T: ... - -# Static type inference support via __dataclass_transform__ implemented as per: -# https://github.com/microsoft/pyright/blob/1.1.135/specs/dataclass_transforms.md -# This annotation must be applied to all overloads of "define" and "attrs" -# -# NOTE: This is a typing construct and does not exist at runtime. Extensions -# wrapping attrs decorators should declare a separate __dataclass_transform__ -# signature in the extension module using the specification linked above to -# provide pyright support. -def __dataclass_transform__( - *, - eq_default: bool = True, - order_default: bool = False, - kw_only_default: bool = False, - field_descriptors: Tuple[Union[type, Callable[..., Any]], ...] = (()), -) -> Callable[[_T], _T]: ... - -class Attribute(Generic[_T]): - name: str - default: Optional[_T] - validator: Optional[_ValidatorType[_T]] - repr: _ReprArgType - cmp: _EqOrderType - eq: _EqOrderType - order: _EqOrderType - hash: Optional[bool] - init: bool - converter: Optional[_ConverterType] - metadata: Dict[Any, Any] - type: Optional[Type[_T]] - kw_only: bool - on_setattr: _OnSetAttrType - def evolve(self, **changes: Any) -> "Attribute[Any]": ... - -# NOTE: We had several choices for the annotation to use for type arg: -# 1) Type[_T] -# - Pros: Handles simple cases correctly -# - Cons: Might produce less informative errors in the case of conflicting -# TypeVars e.g. `attr.ib(default='bad', type=int)` -# 2) Callable[..., _T] -# - Pros: Better error messages than #1 for conflicting TypeVars -# - Cons: Terrible error messages for validator checks. -# e.g. attr.ib(type=int, validator=validate_str) -# -> error: Cannot infer function type argument -# 3) type (and do all of the work in the mypy plugin) -# - Pros: Simple here, and we could customize the plugin with our own errors. -# - Cons: Would need to write mypy plugin code to handle all the cases. -# We chose option #1. - -# `attr` lies about its return type to make the following possible: -# attr() -> Any -# attr(8) -> int -# attr(validator=) -> Whatever the callable expects. -# This makes this type of assignments possible: -# x: int = attr(8) -# -# This form catches explicit None or no default but with no other arguments -# returns Any. -@overload -def attrib( - default: None = ..., - validator: None = ..., - repr: _ReprArgType = ..., - cmp: Optional[_EqOrderType] = ..., - hash: Optional[bool] = ..., - init: bool = ..., - metadata: Optional[Mapping[Any, Any]] = ..., - type: None = ..., - converter: None = ..., - factory: None = ..., - kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., -) -> Any: ... - -# This form catches an explicit None or no default and infers the type from the -# other arguments. -@overload -def attrib( - default: None = ..., - validator: Optional[_ValidatorArgType[_T]] = ..., - repr: _ReprArgType = ..., - cmp: Optional[_EqOrderType] = ..., - hash: Optional[bool] = ..., - init: bool = ..., - metadata: Optional[Mapping[Any, Any]] = ..., - type: Optional[Type[_T]] = ..., - converter: Optional[_ConverterType] = ..., - factory: Optional[Callable[[], _T]] = ..., - kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., -) -> _T: ... - -# This form catches an explicit default argument. -@overload -def attrib( - default: _T, - validator: Optional[_ValidatorArgType[_T]] = ..., - repr: _ReprArgType = ..., - cmp: Optional[_EqOrderType] = ..., - hash: Optional[bool] = ..., - init: bool = ..., - metadata: Optional[Mapping[Any, Any]] = ..., - type: Optional[Type[_T]] = ..., - converter: Optional[_ConverterType] = ..., - factory: Optional[Callable[[], _T]] = ..., - kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., -) -> _T: ... - -# This form covers type=non-Type: e.g. forward references (str), Any -@overload -def attrib( - default: Optional[_T] = ..., - validator: Optional[_ValidatorArgType[_T]] = ..., - repr: _ReprArgType = ..., - cmp: Optional[_EqOrderType] = ..., - hash: Optional[bool] = ..., - init: bool = ..., - metadata: Optional[Mapping[Any, Any]] = ..., - type: object = ..., - converter: Optional[_ConverterType] = ..., - factory: Optional[Callable[[], _T]] = ..., - kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., -) -> Any: ... -@overload -def field( - *, - default: None = ..., - validator: None = ..., - repr: _ReprArgType = ..., - hash: Optional[bool] = ..., - init: bool = ..., - metadata: Optional[Mapping[Any, Any]] = ..., - converter: None = ..., - factory: None = ..., - kw_only: bool = ..., - eq: Optional[bool] = ..., - order: Optional[bool] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., -) -> Any: ... - -# This form catches an explicit None or no default and infers the type from the -# other arguments. -@overload -def field( - *, - default: None = ..., - validator: Optional[_ValidatorArgType[_T]] = ..., - repr: _ReprArgType = ..., - hash: Optional[bool] = ..., - init: bool = ..., - metadata: Optional[Mapping[Any, Any]] = ..., - converter: Optional[_ConverterType] = ..., - factory: Optional[Callable[[], _T]] = ..., - kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., -) -> _T: ... - -# This form catches an explicit default argument. -@overload -def field( - *, - default: _T, - validator: Optional[_ValidatorArgType[_T]] = ..., - repr: _ReprArgType = ..., - hash: Optional[bool] = ..., - init: bool = ..., - metadata: Optional[Mapping[Any, Any]] = ..., - converter: Optional[_ConverterType] = ..., - factory: Optional[Callable[[], _T]] = ..., - kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., -) -> _T: ... - -# This form covers type=non-Type: e.g. forward references (str), Any -@overload -def field( - *, - default: Optional[_T] = ..., - validator: Optional[_ValidatorArgType[_T]] = ..., - repr: _ReprArgType = ..., - hash: Optional[bool] = ..., - init: bool = ..., - metadata: Optional[Mapping[Any, Any]] = ..., - converter: Optional[_ConverterType] = ..., - factory: Optional[Callable[[], _T]] = ..., - kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., -) -> Any: ... -@overload -@__dataclass_transform__(order_default=True, field_descriptors=(attrib, field)) -def attrs( - maybe_cls: _C, - these: Optional[Dict[str, Any]] = ..., - repr_ns: Optional[str] = ..., - repr: bool = ..., - cmp: Optional[_EqOrderType] = ..., - hash: Optional[bool] = ..., - init: bool = ..., - slots: bool = ..., - frozen: bool = ..., - weakref_slot: bool = ..., - str: bool = ..., - auto_attribs: bool = ..., - kw_only: bool = ..., - cache_hash: bool = ..., - auto_exc: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., - auto_detect: bool = ..., - collect_by_mro: bool = ..., - getstate_setstate: Optional[bool] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., - field_transformer: Optional[_FieldTransformer] = ..., - match_args: bool = ..., -) -> _C: ... -@overload -@__dataclass_transform__(order_default=True, field_descriptors=(attrib, field)) -def attrs( - maybe_cls: None = ..., - these: Optional[Dict[str, Any]] = ..., - repr_ns: Optional[str] = ..., - repr: bool = ..., - cmp: Optional[_EqOrderType] = ..., - hash: Optional[bool] = ..., - init: bool = ..., - slots: bool = ..., - frozen: bool = ..., - weakref_slot: bool = ..., - str: bool = ..., - auto_attribs: bool = ..., - kw_only: bool = ..., - cache_hash: bool = ..., - auto_exc: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., - auto_detect: bool = ..., - collect_by_mro: bool = ..., - getstate_setstate: Optional[bool] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., - field_transformer: Optional[_FieldTransformer] = ..., - match_args: bool = ..., -) -> Callable[[_C], _C]: ... -@overload -@__dataclass_transform__(field_descriptors=(attrib, field)) -def define( - maybe_cls: _C, - *, - these: Optional[Dict[str, Any]] = ..., - repr: bool = ..., - hash: Optional[bool] = ..., - init: bool = ..., - slots: bool = ..., - frozen: bool = ..., - weakref_slot: bool = ..., - str: bool = ..., - auto_attribs: bool = ..., - kw_only: bool = ..., - cache_hash: bool = ..., - auto_exc: bool = ..., - eq: Optional[bool] = ..., - order: Optional[bool] = ..., - auto_detect: bool = ..., - getstate_setstate: Optional[bool] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., - field_transformer: Optional[_FieldTransformer] = ..., - match_args: bool = ..., -) -> _C: ... -@overload -@__dataclass_transform__(field_descriptors=(attrib, field)) -def define( - maybe_cls: None = ..., - *, - these: Optional[Dict[str, Any]] = ..., - repr: bool = ..., - hash: Optional[bool] = ..., - init: bool = ..., - slots: bool = ..., - frozen: bool = ..., - weakref_slot: bool = ..., - str: bool = ..., - auto_attribs: bool = ..., - kw_only: bool = ..., - cache_hash: bool = ..., - auto_exc: bool = ..., - eq: Optional[bool] = ..., - order: Optional[bool] = ..., - auto_detect: bool = ..., - getstate_setstate: Optional[bool] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., - field_transformer: Optional[_FieldTransformer] = ..., - match_args: bool = ..., -) -> Callable[[_C], _C]: ... - -mutable = define -frozen = define # they differ only in their defaults - -# TODO: add support for returning NamedTuple from the mypy plugin -class _Fields(Tuple[Attribute[Any], ...]): - def __getattr__(self, name: str) -> Attribute[Any]: ... - -def fields(cls: type) -> _Fields: ... -def fields_dict(cls: type) -> Dict[str, Attribute[Any]]: ... -def validate(inst: Any) -> None: ... -def resolve_types( - cls: _C, - globalns: Optional[Dict[str, Any]] = ..., - localns: Optional[Dict[str, Any]] = ..., - attribs: Optional[List[Attribute[Any]]] = ..., -) -> _C: ... - -# TODO: add support for returning a proper attrs class from the mypy plugin -# we use Any instead of _CountingAttr so that e.g. `make_class('Foo', -# [attr.ib()])` is valid -def make_class( - name: str, - attrs: Union[List[str], Tuple[str, ...], Dict[str, Any]], - bases: Tuple[type, ...] = ..., - repr_ns: Optional[str] = ..., - repr: bool = ..., - cmp: Optional[_EqOrderType] = ..., - hash: Optional[bool] = ..., - init: bool = ..., - slots: bool = ..., - frozen: bool = ..., - weakref_slot: bool = ..., - str: bool = ..., - auto_attribs: bool = ..., - kw_only: bool = ..., - cache_hash: bool = ..., - auto_exc: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., - collect_by_mro: bool = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., - field_transformer: Optional[_FieldTransformer] = ..., -) -> type: ... - -# _funcs -- - -# TODO: add support for returning TypedDict from the mypy plugin -# FIXME: asdict/astuple do not honor their factory args. Waiting on one of -# these: -# https://github.com/python/mypy/issues/4236 -# https://github.com/python/typing/issues/253 -# XXX: remember to fix attrs.asdict/astuple too! -def asdict( - inst: Any, - recurse: bool = ..., - filter: Optional[_FilterType[Any]] = ..., - dict_factory: Type[Mapping[Any, Any]] = ..., - retain_collection_types: bool = ..., - value_serializer: Optional[ - Callable[[type, Attribute[Any], Any], Any] - ] = ..., - tuple_keys: Optional[bool] = ..., -) -> Dict[str, Any]: ... - -# TODO: add support for returning NamedTuple from the mypy plugin -def astuple( - inst: Any, - recurse: bool = ..., - filter: Optional[_FilterType[Any]] = ..., - tuple_factory: Type[Sequence[Any]] = ..., - retain_collection_types: bool = ..., -) -> Tuple[Any, ...]: ... -def has(cls: type) -> bool: ... -def assoc(inst: _T, **changes: Any) -> _T: ... -def evolve(inst: _T, **changes: Any) -> _T: ... - -# _config -- - -def set_run_validators(run: bool) -> None: ... -def get_run_validators() -> bool: ... - -# aliases -- - -s = attributes = attrs -ib = attr = attrib -dataclass = attrs # Technically, partial(attrs, auto_attribs=True) ;) diff --git a/client/ayon_core/vendor/python/python_2/attr/_cmp.py b/client/ayon_core/vendor/python/python_2/attr/_cmp.py deleted file mode 100644 index 6cffa4dbab..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/_cmp.py +++ /dev/null @@ -1,154 +0,0 @@ -# SPDX-License-Identifier: MIT - -from __future__ import absolute_import, division, print_function - -import functools - -from ._compat import new_class -from ._make import _make_ne - - -_operation_names = {"eq": "==", "lt": "<", "le": "<=", "gt": ">", "ge": ">="} - - -def cmp_using( - eq=None, - lt=None, - le=None, - gt=None, - ge=None, - require_same_type=True, - class_name="Comparable", -): - """ - Create a class that can be passed into `attr.ib`'s ``eq``, ``order``, and - ``cmp`` arguments to customize field comparison. - - The resulting class will have a full set of ordering methods if - at least one of ``{lt, le, gt, ge}`` and ``eq`` are provided. - - :param Optional[callable] eq: `callable` used to evaluate equality - of two objects. - :param Optional[callable] lt: `callable` used to evaluate whether - one object is less than another object. - :param Optional[callable] le: `callable` used to evaluate whether - one object is less than or equal to another object. - :param Optional[callable] gt: `callable` used to evaluate whether - one object is greater than another object. - :param Optional[callable] ge: `callable` used to evaluate whether - one object is greater than or equal to another object. - - :param bool require_same_type: When `True`, equality and ordering methods - will return `NotImplemented` if objects are not of the same type. - - :param Optional[str] class_name: Name of class. Defaults to 'Comparable'. - - See `comparison` for more details. - - .. versionadded:: 21.1.0 - """ - - body = { - "__slots__": ["value"], - "__init__": _make_init(), - "_requirements": [], - "_is_comparable_to": _is_comparable_to, - } - - # Add operations. - num_order_functions = 0 - has_eq_function = False - - if eq is not None: - has_eq_function = True - body["__eq__"] = _make_operator("eq", eq) - body["__ne__"] = _make_ne() - - if lt is not None: - num_order_functions += 1 - body["__lt__"] = _make_operator("lt", lt) - - if le is not None: - num_order_functions += 1 - body["__le__"] = _make_operator("le", le) - - if gt is not None: - num_order_functions += 1 - body["__gt__"] = _make_operator("gt", gt) - - if ge is not None: - num_order_functions += 1 - body["__ge__"] = _make_operator("ge", ge) - - type_ = new_class(class_name, (object,), {}, lambda ns: ns.update(body)) - - # Add same type requirement. - if require_same_type: - type_._requirements.append(_check_same_type) - - # Add total ordering if at least one operation was defined. - if 0 < num_order_functions < 4: - if not has_eq_function: - # functools.total_ordering requires __eq__ to be defined, - # so raise early error here to keep a nice stack. - raise ValueError( - "eq must be define is order to complete ordering from " - "lt, le, gt, ge." - ) - type_ = functools.total_ordering(type_) - - return type_ - - -def _make_init(): - """ - Create __init__ method. - """ - - def __init__(self, value): - """ - Initialize object with *value*. - """ - self.value = value - - return __init__ - - -def _make_operator(name, func): - """ - Create operator method. - """ - - def method(self, other): - if not self._is_comparable_to(other): - return NotImplemented - - result = func(self.value, other.value) - if result is NotImplemented: - return NotImplemented - - return result - - method.__name__ = "__%s__" % (name,) - method.__doc__ = "Return a %s b. Computed by attrs." % ( - _operation_names[name], - ) - - return method - - -def _is_comparable_to(self, other): - """ - Check whether `other` is comparable to `self`. - """ - for func in self._requirements: - if not func(self, other): - return False - return True - - -def _check_same_type(self, other): - """ - Return True if *self* and *other* are of the same type, False otherwise. - """ - return other.value.__class__ is self.value.__class__ diff --git a/client/ayon_core/vendor/python/python_2/attr/_cmp.pyi b/client/ayon_core/vendor/python/python_2/attr/_cmp.pyi deleted file mode 100644 index e71aaff7a1..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/_cmp.pyi +++ /dev/null @@ -1,13 +0,0 @@ -from typing import Type - -from . import _CompareWithType - -def cmp_using( - eq: Optional[_CompareWithType], - lt: Optional[_CompareWithType], - le: Optional[_CompareWithType], - gt: Optional[_CompareWithType], - ge: Optional[_CompareWithType], - require_same_type: bool, - class_name: str, -) -> Type: ... diff --git a/client/ayon_core/vendor/python/python_2/attr/_compat.py b/client/ayon_core/vendor/python/python_2/attr/_compat.py deleted file mode 100644 index dc0cb02b64..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/_compat.py +++ /dev/null @@ -1,261 +0,0 @@ -# SPDX-License-Identifier: MIT - -from __future__ import absolute_import, division, print_function - -import platform -import sys -import threading -import types -import warnings - - -PY2 = sys.version_info[0] == 2 -PYPY = platform.python_implementation() == "PyPy" -PY36 = sys.version_info[:2] >= (3, 6) -HAS_F_STRINGS = PY36 -PY310 = sys.version_info[:2] >= (3, 10) - - -if PYPY or PY36: - ordered_dict = dict -else: - from collections import OrderedDict - - ordered_dict = OrderedDict - - -if PY2: - from collections import Mapping, Sequence - - from UserDict import IterableUserDict - - # We 'bundle' isclass instead of using inspect as importing inspect is - # fairly expensive (order of 10-15 ms for a modern machine in 2016) - def isclass(klass): - return isinstance(klass, (type, types.ClassType)) - - def new_class(name, bases, kwds, exec_body): - """ - A minimal stub of types.new_class that we need for make_class. - """ - ns = {} - exec_body(ns) - - return type(name, bases, ns) - - # TYPE is used in exceptions, repr(int) is different on Python 2 and 3. - TYPE = "type" - - def iteritems(d): - return d.iteritems() - - # Python 2 is bereft of a read-only dict proxy, so we make one! - class ReadOnlyDict(IterableUserDict): - """ - Best-effort read-only dict wrapper. - """ - - def __setitem__(self, key, val): - # We gently pretend we're a Python 3 mappingproxy. - raise TypeError( - "'mappingproxy' object does not support item assignment" - ) - - def update(self, _): - # We gently pretend we're a Python 3 mappingproxy. - raise AttributeError( - "'mappingproxy' object has no attribute 'update'" - ) - - def __delitem__(self, _): - # We gently pretend we're a Python 3 mappingproxy. - raise TypeError( - "'mappingproxy' object does not support item deletion" - ) - - def clear(self): - # We gently pretend we're a Python 3 mappingproxy. - raise AttributeError( - "'mappingproxy' object has no attribute 'clear'" - ) - - def pop(self, key, default=None): - # We gently pretend we're a Python 3 mappingproxy. - raise AttributeError( - "'mappingproxy' object has no attribute 'pop'" - ) - - def popitem(self): - # We gently pretend we're a Python 3 mappingproxy. - raise AttributeError( - "'mappingproxy' object has no attribute 'popitem'" - ) - - def setdefault(self, key, default=None): - # We gently pretend we're a Python 3 mappingproxy. - raise AttributeError( - "'mappingproxy' object has no attribute 'setdefault'" - ) - - def __repr__(self): - # Override to be identical to the Python 3 version. - return "mappingproxy(" + repr(self.data) + ")" - - def metadata_proxy(d): - res = ReadOnlyDict() - res.data.update(d) # We blocked update, so we have to do it like this. - return res - - def just_warn(*args, **kw): # pragma: no cover - """ - We only warn on Python 3 because we are not aware of any concrete - consequences of not setting the cell on Python 2. - """ - -else: # Python 3 and later. - from collections.abc import Mapping, Sequence # noqa - - def just_warn(*args, **kw): - """ - We only warn on Python 3 because we are not aware of any concrete - consequences of not setting the cell on Python 2. - """ - warnings.warn( - "Running interpreter doesn't sufficiently support code object " - "introspection. Some features like bare super() or accessing " - "__class__ will not work with slotted classes.", - RuntimeWarning, - stacklevel=2, - ) - - def isclass(klass): - return isinstance(klass, type) - - TYPE = "class" - - def iteritems(d): - return d.items() - - new_class = types.new_class - - def metadata_proxy(d): - return types.MappingProxyType(dict(d)) - - -def make_set_closure_cell(): - """Return a function of two arguments (cell, value) which sets - the value stored in the closure cell `cell` to `value`. - """ - # pypy makes this easy. (It also supports the logic below, but - # why not do the easy/fast thing?) - if PYPY: - - def set_closure_cell(cell, value): - cell.__setstate__((value,)) - - return set_closure_cell - - # Otherwise gotta do it the hard way. - - # Create a function that will set its first cellvar to `value`. - def set_first_cellvar_to(value): - x = value - return - - # This function will be eliminated as dead code, but - # not before its reference to `x` forces `x` to be - # represented as a closure cell rather than a local. - def force_x_to_be_a_cell(): # pragma: no cover - return x - - try: - # Extract the code object and make sure our assumptions about - # the closure behavior are correct. - if PY2: - co = set_first_cellvar_to.func_code - else: - co = set_first_cellvar_to.__code__ - if co.co_cellvars != ("x",) or co.co_freevars != (): - raise AssertionError # pragma: no cover - - # Convert this code object to a code object that sets the - # function's first _freevar_ (not cellvar) to the argument. - if sys.version_info >= (3, 8): - # CPython 3.8+ has an incompatible CodeType signature - # (added a posonlyargcount argument) but also added - # CodeType.replace() to do this without counting parameters. - set_first_freevar_code = co.replace( - co_cellvars=co.co_freevars, co_freevars=co.co_cellvars - ) - else: - args = [co.co_argcount] - if not PY2: - args.append(co.co_kwonlyargcount) - args.extend( - [ - co.co_nlocals, - co.co_stacksize, - co.co_flags, - co.co_code, - co.co_consts, - co.co_names, - co.co_varnames, - co.co_filename, - co.co_name, - co.co_firstlineno, - co.co_lnotab, - # These two arguments are reversed: - co.co_cellvars, - co.co_freevars, - ] - ) - set_first_freevar_code = types.CodeType(*args) - - def set_closure_cell(cell, value): - # Create a function using the set_first_freevar_code, - # whose first closure cell is `cell`. Calling it will - # change the value of that cell. - setter = types.FunctionType( - set_first_freevar_code, {}, "setter", (), (cell,) - ) - # And call it to set the cell. - setter(value) - - # Make sure it works on this interpreter: - def make_func_with_cell(): - x = None - - def func(): - return x # pragma: no cover - - return func - - if PY2: - cell = make_func_with_cell().func_closure[0] - else: - cell = make_func_with_cell().__closure__[0] - set_closure_cell(cell, 100) - if cell.cell_contents != 100: - raise AssertionError # pragma: no cover - - except Exception: - return just_warn - else: - return set_closure_cell - - -set_closure_cell = make_set_closure_cell() - -# Thread-local global to track attrs instances which are already being repr'd. -# This is needed because there is no other (thread-safe) way to pass info -# about the instances that are already being repr'd through the call stack -# in order to ensure we don't perform infinite recursion. -# -# For instance, if an instance contains a dict which contains that instance, -# we need to know that we're already repr'ing the outside instance from within -# the dict's repr() call. -# -# This lives here rather than in _make.py so that the functions in _make.py -# don't have a direct reference to the thread-local in their globals dict. -# If they have such a reference, it breaks cloudpickle. -repr_context = threading.local() diff --git a/client/ayon_core/vendor/python/python_2/attr/_config.py b/client/ayon_core/vendor/python/python_2/attr/_config.py deleted file mode 100644 index fc9be29d00..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/_config.py +++ /dev/null @@ -1,33 +0,0 @@ -# SPDX-License-Identifier: MIT - -from __future__ import absolute_import, division, print_function - - -__all__ = ["set_run_validators", "get_run_validators"] - -_run_validators = True - - -def set_run_validators(run): - """ - Set whether or not validators are run. By default, they are run. - - .. deprecated:: 21.3.0 It will not be removed, but it also will not be - moved to new ``attrs`` namespace. Use `attrs.validators.set_disabled()` - instead. - """ - if not isinstance(run, bool): - raise TypeError("'run' must be bool.") - global _run_validators - _run_validators = run - - -def get_run_validators(): - """ - Return whether or not validators are run. - - .. deprecated:: 21.3.0 It will not be removed, but it also will not be - moved to new ``attrs`` namespace. Use `attrs.validators.get_disabled()` - instead. - """ - return _run_validators diff --git a/client/ayon_core/vendor/python/python_2/attr/_funcs.py b/client/ayon_core/vendor/python/python_2/attr/_funcs.py deleted file mode 100644 index 4c90085a40..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/_funcs.py +++ /dev/null @@ -1,422 +0,0 @@ -# SPDX-License-Identifier: MIT - -from __future__ import absolute_import, division, print_function - -import copy - -from ._compat import iteritems -from ._make import NOTHING, _obj_setattr, fields -from .exceptions import AttrsAttributeNotFoundError - - -def asdict( - inst, - recurse=True, - filter=None, - dict_factory=dict, - retain_collection_types=False, - value_serializer=None, -): - """ - Return the ``attrs`` attribute values of *inst* as a dict. - - Optionally recurse into other ``attrs``-decorated classes. - - :param inst: Instance of an ``attrs``-decorated class. - :param bool recurse: Recurse into classes that are also - ``attrs``-decorated. - :param callable filter: A callable whose return code determines whether an - attribute or element is included (``True``) or dropped (``False``). Is - called with the `attrs.Attribute` as the first argument and the - value as the second argument. - :param callable dict_factory: A callable to produce dictionaries from. For - example, to produce ordered dictionaries instead of normal Python - dictionaries, pass in ``collections.OrderedDict``. - :param bool retain_collection_types: Do not convert to ``list`` when - encountering an attribute whose type is ``tuple`` or ``set``. Only - meaningful if ``recurse`` is ``True``. - :param Optional[callable] value_serializer: A hook that is called for every - attribute or dict key/value. It receives the current instance, field - and value and must return the (updated) value. The hook is run *after* - the optional *filter* has been applied. - - :rtype: return type of *dict_factory* - - :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` - class. - - .. versionadded:: 16.0.0 *dict_factory* - .. versionadded:: 16.1.0 *retain_collection_types* - .. versionadded:: 20.3.0 *value_serializer* - .. versionadded:: 21.3.0 If a dict has a collection for a key, it is - serialized as a tuple. - """ - attrs = fields(inst.__class__) - rv = dict_factory() - for a in attrs: - v = getattr(inst, a.name) - if filter is not None and not filter(a, v): - continue - - if value_serializer is not None: - v = value_serializer(inst, a, v) - - if recurse is True: - if has(v.__class__): - rv[a.name] = asdict( - v, - recurse=True, - filter=filter, - dict_factory=dict_factory, - retain_collection_types=retain_collection_types, - value_serializer=value_serializer, - ) - elif isinstance(v, (tuple, list, set, frozenset)): - cf = v.__class__ if retain_collection_types is True else list - rv[a.name] = cf( - [ - _asdict_anything( - i, - is_key=False, - filter=filter, - dict_factory=dict_factory, - retain_collection_types=retain_collection_types, - value_serializer=value_serializer, - ) - for i in v - ] - ) - elif isinstance(v, dict): - df = dict_factory - rv[a.name] = df( - ( - _asdict_anything( - kk, - is_key=True, - filter=filter, - dict_factory=df, - retain_collection_types=retain_collection_types, - value_serializer=value_serializer, - ), - _asdict_anything( - vv, - is_key=False, - filter=filter, - dict_factory=df, - retain_collection_types=retain_collection_types, - value_serializer=value_serializer, - ), - ) - for kk, vv in iteritems(v) - ) - else: - rv[a.name] = v - else: - rv[a.name] = v - return rv - - -def _asdict_anything( - val, - is_key, - filter, - dict_factory, - retain_collection_types, - value_serializer, -): - """ - ``asdict`` only works on attrs instances, this works on anything. - """ - if getattr(val.__class__, "__attrs_attrs__", None) is not None: - # Attrs class. - rv = asdict( - val, - recurse=True, - filter=filter, - dict_factory=dict_factory, - retain_collection_types=retain_collection_types, - value_serializer=value_serializer, - ) - elif isinstance(val, (tuple, list, set, frozenset)): - if retain_collection_types is True: - cf = val.__class__ - elif is_key: - cf = tuple - else: - cf = list - - rv = cf( - [ - _asdict_anything( - i, - is_key=False, - filter=filter, - dict_factory=dict_factory, - retain_collection_types=retain_collection_types, - value_serializer=value_serializer, - ) - for i in val - ] - ) - elif isinstance(val, dict): - df = dict_factory - rv = df( - ( - _asdict_anything( - kk, - is_key=True, - filter=filter, - dict_factory=df, - retain_collection_types=retain_collection_types, - value_serializer=value_serializer, - ), - _asdict_anything( - vv, - is_key=False, - filter=filter, - dict_factory=df, - retain_collection_types=retain_collection_types, - value_serializer=value_serializer, - ), - ) - for kk, vv in iteritems(val) - ) - else: - rv = val - if value_serializer is not None: - rv = value_serializer(None, None, rv) - - return rv - - -def astuple( - inst, - recurse=True, - filter=None, - tuple_factory=tuple, - retain_collection_types=False, -): - """ - Return the ``attrs`` attribute values of *inst* as a tuple. - - Optionally recurse into other ``attrs``-decorated classes. - - :param inst: Instance of an ``attrs``-decorated class. - :param bool recurse: Recurse into classes that are also - ``attrs``-decorated. - :param callable filter: A callable whose return code determines whether an - attribute or element is included (``True``) or dropped (``False``). Is - called with the `attrs.Attribute` as the first argument and the - value as the second argument. - :param callable tuple_factory: A callable to produce tuples from. For - example, to produce lists instead of tuples. - :param bool retain_collection_types: Do not convert to ``list`` - or ``dict`` when encountering an attribute which type is - ``tuple``, ``dict`` or ``set``. Only meaningful if ``recurse`` is - ``True``. - - :rtype: return type of *tuple_factory* - - :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` - class. - - .. versionadded:: 16.2.0 - """ - attrs = fields(inst.__class__) - rv = [] - retain = retain_collection_types # Very long. :/ - for a in attrs: - v = getattr(inst, a.name) - if filter is not None and not filter(a, v): - continue - if recurse is True: - if has(v.__class__): - rv.append( - astuple( - v, - recurse=True, - filter=filter, - tuple_factory=tuple_factory, - retain_collection_types=retain, - ) - ) - elif isinstance(v, (tuple, list, set, frozenset)): - cf = v.__class__ if retain is True else list - rv.append( - cf( - [ - astuple( - j, - recurse=True, - filter=filter, - tuple_factory=tuple_factory, - retain_collection_types=retain, - ) - if has(j.__class__) - else j - for j in v - ] - ) - ) - elif isinstance(v, dict): - df = v.__class__ if retain is True else dict - rv.append( - df( - ( - astuple( - kk, - tuple_factory=tuple_factory, - retain_collection_types=retain, - ) - if has(kk.__class__) - else kk, - astuple( - vv, - tuple_factory=tuple_factory, - retain_collection_types=retain, - ) - if has(vv.__class__) - else vv, - ) - for kk, vv in iteritems(v) - ) - ) - else: - rv.append(v) - else: - rv.append(v) - - return rv if tuple_factory is list else tuple_factory(rv) - - -def has(cls): - """ - Check whether *cls* is a class with ``attrs`` attributes. - - :param type cls: Class to introspect. - :raise TypeError: If *cls* is not a class. - - :rtype: bool - """ - return getattr(cls, "__attrs_attrs__", None) is not None - - -def assoc(inst, **changes): - """ - Copy *inst* and apply *changes*. - - :param inst: Instance of a class with ``attrs`` attributes. - :param changes: Keyword changes in the new copy. - - :return: A copy of inst with *changes* incorporated. - - :raise attr.exceptions.AttrsAttributeNotFoundError: If *attr_name* couldn't - be found on *cls*. - :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` - class. - - .. deprecated:: 17.1.0 - Use `attrs.evolve` instead if you can. - This function will not be removed du to the slightly different approach - compared to `attrs.evolve`. - """ - import warnings - - warnings.warn( - "assoc is deprecated and will be removed after 2018/01.", - DeprecationWarning, - stacklevel=2, - ) - new = copy.copy(inst) - attrs = fields(inst.__class__) - for k, v in iteritems(changes): - a = getattr(attrs, k, NOTHING) - if a is NOTHING: - raise AttrsAttributeNotFoundError( - "{k} is not an attrs attribute on {cl}.".format( - k=k, cl=new.__class__ - ) - ) - _obj_setattr(new, k, v) - return new - - -def evolve(inst, **changes): - """ - Create a new instance, based on *inst* with *changes* applied. - - :param inst: Instance of a class with ``attrs`` attributes. - :param changes: Keyword changes in the new copy. - - :return: A copy of inst with *changes* incorporated. - - :raise TypeError: If *attr_name* couldn't be found in the class - ``__init__``. - :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` - class. - - .. versionadded:: 17.1.0 - """ - cls = inst.__class__ - attrs = fields(cls) - for a in attrs: - if not a.init: - continue - attr_name = a.name # To deal with private attributes. - init_name = attr_name if attr_name[0] != "_" else attr_name[1:] - if init_name not in changes: - changes[init_name] = getattr(inst, attr_name) - - return cls(**changes) - - -def resolve_types(cls, globalns=None, localns=None, attribs=None): - """ - Resolve any strings and forward annotations in type annotations. - - This is only required if you need concrete types in `Attribute`'s *type* - field. In other words, you don't need to resolve your types if you only - use them for static type checking. - - With no arguments, names will be looked up in the module in which the class - was created. If this is not what you want, e.g. if the name only exists - inside a method, you may pass *globalns* or *localns* to specify other - dictionaries in which to look up these names. See the docs of - `typing.get_type_hints` for more details. - - :param type cls: Class to resolve. - :param Optional[dict] globalns: Dictionary containing global variables. - :param Optional[dict] localns: Dictionary containing local variables. - :param Optional[list] attribs: List of attribs for the given class. - This is necessary when calling from inside a ``field_transformer`` - since *cls* is not an ``attrs`` class yet. - - :raise TypeError: If *cls* is not a class. - :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` - class and you didn't pass any attribs. - :raise NameError: If types cannot be resolved because of missing variables. - - :returns: *cls* so you can use this function also as a class decorator. - Please note that you have to apply it **after** `attrs.define`. That - means the decorator has to come in the line **before** `attrs.define`. - - .. versionadded:: 20.1.0 - .. versionadded:: 21.1.0 *attribs* - - """ - # Since calling get_type_hints is expensive we cache whether we've - # done it already. - if getattr(cls, "__attrs_types_resolved__", None) != cls: - import typing - - hints = typing.get_type_hints(cls, globalns=globalns, localns=localns) - for field in fields(cls) if attribs is None else attribs: - if field.name in hints: - # Since fields have been frozen we must work around it. - _obj_setattr(field, "type", hints[field.name]) - # We store the class we resolved so that subclasses know they haven't - # been resolved. - cls.__attrs_types_resolved__ = cls - - # Return the class so you can use it as a decorator too. - return cls diff --git a/client/ayon_core/vendor/python/python_2/attr/_make.py b/client/ayon_core/vendor/python/python_2/attr/_make.py deleted file mode 100644 index d46f8a3e7a..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/_make.py +++ /dev/null @@ -1,3173 +0,0 @@ -# SPDX-License-Identifier: MIT - -from __future__ import absolute_import, division, print_function - -import copy -import inspect -import linecache -import sys -import warnings - -from operator import itemgetter - -# We need to import _compat itself in addition to the _compat members to avoid -# having the thread-local in the globals here. -from . import _compat, _config, setters -from ._compat import ( - HAS_F_STRINGS, - PY2, - PY310, - PYPY, - isclass, - iteritems, - metadata_proxy, - new_class, - ordered_dict, - set_closure_cell, -) -from .exceptions import ( - DefaultAlreadySetError, - FrozenInstanceError, - NotAnAttrsClassError, - PythonTooOldError, - UnannotatedAttributeError, -) - - -if not PY2: - import typing - - -# This is used at least twice, so cache it here. -_obj_setattr = object.__setattr__ -_init_converter_pat = "__attr_converter_%s" -_init_factory_pat = "__attr_factory_{}" -_tuple_property_pat = ( - " {attr_name} = _attrs_property(_attrs_itemgetter({index}))" -) -_classvar_prefixes = ( - "typing.ClassVar", - "t.ClassVar", - "ClassVar", - "typing_extensions.ClassVar", -) -# we don't use a double-underscore prefix because that triggers -# name mangling when trying to create a slot for the field -# (when slots=True) -_hash_cache_field = "_attrs_cached_hash" - -_empty_metadata_singleton = metadata_proxy({}) - -# Unique object for unequivocal getattr() defaults. -_sentinel = object() - -_ng_default_on_setattr = setters.pipe(setters.convert, setters.validate) - - -class _Nothing(object): - """ - Sentinel class to indicate the lack of a value when ``None`` is ambiguous. - - ``_Nothing`` is a singleton. There is only ever one of it. - - .. versionchanged:: 21.1.0 ``bool(NOTHING)`` is now False. - """ - - _singleton = None - - def __new__(cls): - if _Nothing._singleton is None: - _Nothing._singleton = super(_Nothing, cls).__new__(cls) - return _Nothing._singleton - - def __repr__(self): - return "NOTHING" - - def __bool__(self): - return False - - def __len__(self): - return 0 # __bool__ for Python 2 - - -NOTHING = _Nothing() -""" -Sentinel to indicate the lack of a value when ``None`` is ambiguous. -""" - - -class _CacheHashWrapper(int): - """ - An integer subclass that pickles / copies as None - - This is used for non-slots classes with ``cache_hash=True``, to avoid - serializing a potentially (even likely) invalid hash value. Since ``None`` - is the default value for uncalculated hashes, whenever this is copied, - the copy's value for the hash should automatically reset. - - See GH #613 for more details. - """ - - if PY2: - # For some reason `type(None)` isn't callable in Python 2, but we don't - # actually need a constructor for None objects, we just need any - # available function that returns None. - def __reduce__(self, _none_constructor=getattr, _args=(0, "", None)): - return _none_constructor, _args - - else: - - def __reduce__(self, _none_constructor=type(None), _args=()): - return _none_constructor, _args - - -def attrib( - default=NOTHING, - validator=None, - repr=True, - cmp=None, - hash=None, - init=True, - metadata=None, - type=None, - converter=None, - factory=None, - kw_only=False, - eq=None, - order=None, - on_setattr=None, -): - """ - Create a new attribute on a class. - - .. warning:: - - Does *not* do anything unless the class is also decorated with - `attr.s`! - - :param default: A value that is used if an ``attrs``-generated ``__init__`` - is used and no value is passed while instantiating or the attribute is - excluded using ``init=False``. - - If the value is an instance of `attrs.Factory`, its callable will be - used to construct a new value (useful for mutable data types like lists - or dicts). - - If a default is not set (or set manually to `attrs.NOTHING`), a value - *must* be supplied when instantiating; otherwise a `TypeError` - will be raised. - - The default can also be set using decorator notation as shown below. - - :type default: Any value - - :param callable factory: Syntactic sugar for - ``default=attr.Factory(factory)``. - - :param validator: `callable` that is called by ``attrs``-generated - ``__init__`` methods after the instance has been initialized. They - receive the initialized instance, the :func:`~attrs.Attribute`, and the - passed value. - - The return value is *not* inspected so the validator has to throw an - exception itself. - - If a `list` is passed, its items are treated as validators and must - all pass. - - Validators can be globally disabled and re-enabled using - `get_run_validators`. - - The validator can also be set using decorator notation as shown below. - - :type validator: `callable` or a `list` of `callable`\\ s. - - :param repr: Include this attribute in the generated ``__repr__`` - method. If ``True``, include the attribute; if ``False``, omit it. By - default, the built-in ``repr()`` function is used. To override how the - attribute value is formatted, pass a ``callable`` that takes a single - value and returns a string. Note that the resulting string is used - as-is, i.e. it will be used directly *instead* of calling ``repr()`` - (the default). - :type repr: a `bool` or a `callable` to use a custom function. - - :param eq: If ``True`` (default), include this attribute in the - generated ``__eq__`` and ``__ne__`` methods that check two instances - for equality. To override how the attribute value is compared, - pass a ``callable`` that takes a single value and returns the value - to be compared. - :type eq: a `bool` or a `callable`. - - :param order: If ``True`` (default), include this attributes in the - generated ``__lt__``, ``__le__``, ``__gt__`` and ``__ge__`` methods. - To override how the attribute value is ordered, - pass a ``callable`` that takes a single value and returns the value - to be ordered. - :type order: a `bool` or a `callable`. - - :param cmp: Setting *cmp* is equivalent to setting *eq* and *order* to the - same value. Must not be mixed with *eq* or *order*. - :type cmp: a `bool` or a `callable`. - - :param Optional[bool] hash: Include this attribute in the generated - ``__hash__`` method. If ``None`` (default), mirror *eq*'s value. This - is the correct behavior according the Python spec. Setting this value - to anything else than ``None`` is *discouraged*. - :param bool init: Include this attribute in the generated ``__init__`` - method. It is possible to set this to ``False`` and set a default - value. In that case this attributed is unconditionally initialized - with the specified default value or factory. - :param callable converter: `callable` that is called by - ``attrs``-generated ``__init__`` methods to convert attribute's value - to the desired format. It is given the passed-in value, and the - returned value will be used as the new value of the attribute. The - value is converted before being passed to the validator, if any. - :param metadata: An arbitrary mapping, to be used by third-party - components. See `extending_metadata`. - :param type: The type of the attribute. In Python 3.6 or greater, the - preferred method to specify the type is using a variable annotation - (see `PEP 526 `_). - This argument is provided for backward compatibility. - Regardless of the approach used, the type will be stored on - ``Attribute.type``. - - Please note that ``attrs`` doesn't do anything with this metadata by - itself. You can use it as part of your own code or for - `static type checking `. - :param kw_only: Make this attribute keyword-only (Python 3+) - in the generated ``__init__`` (if ``init`` is ``False``, this - parameter is ignored). - :param on_setattr: Allows to overwrite the *on_setattr* setting from - `attr.s`. If left `None`, the *on_setattr* value from `attr.s` is used. - Set to `attrs.setters.NO_OP` to run **no** `setattr` hooks for this - attribute -- regardless of the setting in `attr.s`. - :type on_setattr: `callable`, or a list of callables, or `None`, or - `attrs.setters.NO_OP` - - .. versionadded:: 15.2.0 *convert* - .. versionadded:: 16.3.0 *metadata* - .. versionchanged:: 17.1.0 *validator* can be a ``list`` now. - .. versionchanged:: 17.1.0 - *hash* is ``None`` and therefore mirrors *eq* by default. - .. versionadded:: 17.3.0 *type* - .. deprecated:: 17.4.0 *convert* - .. versionadded:: 17.4.0 *converter* as a replacement for the deprecated - *convert* to achieve consistency with other noun-based arguments. - .. versionadded:: 18.1.0 - ``factory=f`` is syntactic sugar for ``default=attr.Factory(f)``. - .. versionadded:: 18.2.0 *kw_only* - .. versionchanged:: 19.2.0 *convert* keyword argument removed. - .. versionchanged:: 19.2.0 *repr* also accepts a custom callable. - .. deprecated:: 19.2.0 *cmp* Removal on or after 2021-06-01. - .. versionadded:: 19.2.0 *eq* and *order* - .. versionadded:: 20.1.0 *on_setattr* - .. versionchanged:: 20.3.0 *kw_only* backported to Python 2 - .. versionchanged:: 21.1.0 - *eq*, *order*, and *cmp* also accept a custom callable - .. versionchanged:: 21.1.0 *cmp* undeprecated - """ - eq, eq_key, order, order_key = _determine_attrib_eq_order( - cmp, eq, order, True - ) - - if hash is not None and hash is not True and hash is not False: - raise TypeError( - "Invalid value for hash. Must be True, False, or None." - ) - - if factory is not None: - if default is not NOTHING: - raise ValueError( - "The `default` and `factory` arguments are mutually " - "exclusive." - ) - if not callable(factory): - raise ValueError("The `factory` argument must be a callable.") - default = Factory(factory) - - if metadata is None: - metadata = {} - - # Apply syntactic sugar by auto-wrapping. - if isinstance(on_setattr, (list, tuple)): - on_setattr = setters.pipe(*on_setattr) - - if validator and isinstance(validator, (list, tuple)): - validator = and_(*validator) - - if converter and isinstance(converter, (list, tuple)): - converter = pipe(*converter) - - return _CountingAttr( - default=default, - validator=validator, - repr=repr, - cmp=None, - hash=hash, - init=init, - converter=converter, - metadata=metadata, - type=type, - kw_only=kw_only, - eq=eq, - eq_key=eq_key, - order=order, - order_key=order_key, - on_setattr=on_setattr, - ) - - -def _compile_and_eval(script, globs, locs=None, filename=""): - """ - "Exec" the script with the given global (globs) and local (locs) variables. - """ - bytecode = compile(script, filename, "exec") - eval(bytecode, globs, locs) - - -def _make_method(name, script, filename, globs=None): - """ - Create the method with the script given and return the method object. - """ - locs = {} - if globs is None: - globs = {} - - # In order of debuggers like PDB being able to step through the code, - # we add a fake linecache entry. - count = 1 - base_filename = filename - while True: - linecache_tuple = ( - len(script), - None, - script.splitlines(True), - filename, - ) - old_val = linecache.cache.setdefault(filename, linecache_tuple) - if old_val == linecache_tuple: - break - else: - filename = "{}-{}>".format(base_filename[:-1], count) - count += 1 - - _compile_and_eval(script, globs, locs, filename) - - return locs[name] - - -def _make_attr_tuple_class(cls_name, attr_names): - """ - Create a tuple subclass to hold `Attribute`s for an `attrs` class. - - The subclass is a bare tuple with properties for names. - - class MyClassAttributes(tuple): - __slots__ = () - x = property(itemgetter(0)) - """ - attr_class_name = "{}Attributes".format(cls_name) - attr_class_template = [ - "class {}(tuple):".format(attr_class_name), - " __slots__ = ()", - ] - if attr_names: - for i, attr_name in enumerate(attr_names): - attr_class_template.append( - _tuple_property_pat.format(index=i, attr_name=attr_name) - ) - else: - attr_class_template.append(" pass") - globs = {"_attrs_itemgetter": itemgetter, "_attrs_property": property} - _compile_and_eval("\n".join(attr_class_template), globs) - return globs[attr_class_name] - - -# Tuple class for extracted attributes from a class definition. -# `base_attrs` is a subset of `attrs`. -_Attributes = _make_attr_tuple_class( - "_Attributes", - [ - # all attributes to build dunder methods for - "attrs", - # attributes that have been inherited - "base_attrs", - # map inherited attributes to their originating classes - "base_attrs_map", - ], -) - - -def _is_class_var(annot): - """ - Check whether *annot* is a typing.ClassVar. - - The string comparison hack is used to avoid evaluating all string - annotations which would put attrs-based classes at a performance - disadvantage compared to plain old classes. - """ - annot = str(annot) - - # Annotation can be quoted. - if annot.startswith(("'", '"')) and annot.endswith(("'", '"')): - annot = annot[1:-1] - - return annot.startswith(_classvar_prefixes) - - -def _has_own_attribute(cls, attrib_name): - """ - Check whether *cls* defines *attrib_name* (and doesn't just inherit it). - - Requires Python 3. - """ - attr = getattr(cls, attrib_name, _sentinel) - if attr is _sentinel: - return False - - for base_cls in cls.__mro__[1:]: - a = getattr(base_cls, attrib_name, None) - if attr is a: - return False - - return True - - -def _get_annotations(cls): - """ - Get annotations for *cls*. - """ - if _has_own_attribute(cls, "__annotations__"): - return cls.__annotations__ - - return {} - - -def _counter_getter(e): - """ - Key function for sorting to avoid re-creating a lambda for every class. - """ - return e[1].counter - - -def _collect_base_attrs(cls, taken_attr_names): - """ - Collect attr.ibs from base classes of *cls*, except *taken_attr_names*. - """ - base_attrs = [] - base_attr_map = {} # A dictionary of base attrs to their classes. - - # Traverse the MRO and collect attributes. - for base_cls in reversed(cls.__mro__[1:-1]): - for a in getattr(base_cls, "__attrs_attrs__", []): - if a.inherited or a.name in taken_attr_names: - continue - - a = a.evolve(inherited=True) - base_attrs.append(a) - base_attr_map[a.name] = base_cls - - # For each name, only keep the freshest definition i.e. the furthest at the - # back. base_attr_map is fine because it gets overwritten with every new - # instance. - filtered = [] - seen = set() - for a in reversed(base_attrs): - if a.name in seen: - continue - filtered.insert(0, a) - seen.add(a.name) - - return filtered, base_attr_map - - -def _collect_base_attrs_broken(cls, taken_attr_names): - """ - Collect attr.ibs from base classes of *cls*, except *taken_attr_names*. - - N.B. *taken_attr_names* will be mutated. - - Adhere to the old incorrect behavior. - - Notably it collects from the front and considers inherited attributes which - leads to the buggy behavior reported in #428. - """ - base_attrs = [] - base_attr_map = {} # A dictionary of base attrs to their classes. - - # Traverse the MRO and collect attributes. - for base_cls in cls.__mro__[1:-1]: - for a in getattr(base_cls, "__attrs_attrs__", []): - if a.name in taken_attr_names: - continue - - a = a.evolve(inherited=True) - taken_attr_names.add(a.name) - base_attrs.append(a) - base_attr_map[a.name] = base_cls - - return base_attrs, base_attr_map - - -def _transform_attrs( - cls, these, auto_attribs, kw_only, collect_by_mro, field_transformer -): - """ - Transform all `_CountingAttr`s on a class into `Attribute`s. - - If *these* is passed, use that and don't look for them on the class. - - *collect_by_mro* is True, collect them in the correct MRO order, otherwise - use the old -- incorrect -- order. See #428. - - Return an `_Attributes`. - """ - cd = cls.__dict__ - anns = _get_annotations(cls) - - if these is not None: - ca_list = [(name, ca) for name, ca in iteritems(these)] - - if not isinstance(these, ordered_dict): - ca_list.sort(key=_counter_getter) - elif auto_attribs is True: - ca_names = { - name - for name, attr in cd.items() - if isinstance(attr, _CountingAttr) - } - ca_list = [] - annot_names = set() - for attr_name, type in anns.items(): - if _is_class_var(type): - continue - annot_names.add(attr_name) - a = cd.get(attr_name, NOTHING) - - if not isinstance(a, _CountingAttr): - if a is NOTHING: - a = attrib() - else: - a = attrib(default=a) - ca_list.append((attr_name, a)) - - unannotated = ca_names - annot_names - if len(unannotated) > 0: - raise UnannotatedAttributeError( - "The following `attr.ib`s lack a type annotation: " - + ", ".join( - sorted(unannotated, key=lambda n: cd.get(n).counter) - ) - + "." - ) - else: - ca_list = sorted( - ( - (name, attr) - for name, attr in cd.items() - if isinstance(attr, _CountingAttr) - ), - key=lambda e: e[1].counter, - ) - - own_attrs = [ - Attribute.from_counting_attr( - name=attr_name, ca=ca, type=anns.get(attr_name) - ) - for attr_name, ca in ca_list - ] - - if collect_by_mro: - base_attrs, base_attr_map = _collect_base_attrs( - cls, {a.name for a in own_attrs} - ) - else: - base_attrs, base_attr_map = _collect_base_attrs_broken( - cls, {a.name for a in own_attrs} - ) - - if kw_only: - own_attrs = [a.evolve(kw_only=True) for a in own_attrs] - base_attrs = [a.evolve(kw_only=True) for a in base_attrs] - - attrs = base_attrs + own_attrs - - # Mandatory vs non-mandatory attr order only matters when they are part of - # the __init__ signature and when they aren't kw_only (which are moved to - # the end and can be mandatory or non-mandatory in any order, as they will - # be specified as keyword args anyway). Check the order of those attrs: - had_default = False - for a in (a for a in attrs if a.init is not False and a.kw_only is False): - if had_default is True and a.default is NOTHING: - raise ValueError( - "No mandatory attributes allowed after an attribute with a " - "default value or factory. Attribute in question: %r" % (a,) - ) - - if had_default is False and a.default is not NOTHING: - had_default = True - - if field_transformer is not None: - attrs = field_transformer(cls, attrs) - - # Create AttrsClass *after* applying the field_transformer since it may - # add or remove attributes! - attr_names = [a.name for a in attrs] - AttrsClass = _make_attr_tuple_class(cls.__name__, attr_names) - - return _Attributes((AttrsClass(attrs), base_attrs, base_attr_map)) - - -if PYPY: - - def _frozen_setattrs(self, name, value): - """ - Attached to frozen classes as __setattr__. - """ - if isinstance(self, BaseException) and name in ( - "__cause__", - "__context__", - ): - BaseException.__setattr__(self, name, value) - return - - raise FrozenInstanceError() - -else: - - def _frozen_setattrs(self, name, value): - """ - Attached to frozen classes as __setattr__. - """ - raise FrozenInstanceError() - - -def _frozen_delattrs(self, name): - """ - Attached to frozen classes as __delattr__. - """ - raise FrozenInstanceError() - - -class _ClassBuilder(object): - """ - Iteratively build *one* class. - """ - - __slots__ = ( - "_attr_names", - "_attrs", - "_base_attr_map", - "_base_names", - "_cache_hash", - "_cls", - "_cls_dict", - "_delete_attribs", - "_frozen", - "_has_pre_init", - "_has_post_init", - "_is_exc", - "_on_setattr", - "_slots", - "_weakref_slot", - "_wrote_own_setattr", - "_has_custom_setattr", - ) - - def __init__( - self, - cls, - these, - slots, - frozen, - weakref_slot, - getstate_setstate, - auto_attribs, - kw_only, - cache_hash, - is_exc, - collect_by_mro, - on_setattr, - has_custom_setattr, - field_transformer, - ): - attrs, base_attrs, base_map = _transform_attrs( - cls, - these, - auto_attribs, - kw_only, - collect_by_mro, - field_transformer, - ) - - self._cls = cls - self._cls_dict = dict(cls.__dict__) if slots else {} - self._attrs = attrs - self._base_names = set(a.name for a in base_attrs) - self._base_attr_map = base_map - self._attr_names = tuple(a.name for a in attrs) - self._slots = slots - self._frozen = frozen - self._weakref_slot = weakref_slot - self._cache_hash = cache_hash - self._has_pre_init = bool(getattr(cls, "__attrs_pre_init__", False)) - self._has_post_init = bool(getattr(cls, "__attrs_post_init__", False)) - self._delete_attribs = not bool(these) - self._is_exc = is_exc - self._on_setattr = on_setattr - - self._has_custom_setattr = has_custom_setattr - self._wrote_own_setattr = False - - self._cls_dict["__attrs_attrs__"] = self._attrs - - if frozen: - self._cls_dict["__setattr__"] = _frozen_setattrs - self._cls_dict["__delattr__"] = _frozen_delattrs - - self._wrote_own_setattr = True - elif on_setattr in ( - _ng_default_on_setattr, - setters.validate, - setters.convert, - ): - has_validator = has_converter = False - for a in attrs: - if a.validator is not None: - has_validator = True - if a.converter is not None: - has_converter = True - - if has_validator and has_converter: - break - if ( - ( - on_setattr == _ng_default_on_setattr - and not (has_validator or has_converter) - ) - or (on_setattr == setters.validate and not has_validator) - or (on_setattr == setters.convert and not has_converter) - ): - # If class-level on_setattr is set to convert + validate, but - # there's no field to convert or validate, pretend like there's - # no on_setattr. - self._on_setattr = None - - if getstate_setstate: - ( - self._cls_dict["__getstate__"], - self._cls_dict["__setstate__"], - ) = self._make_getstate_setstate() - - def __repr__(self): - return "<_ClassBuilder(cls={cls})>".format(cls=self._cls.__name__) - - def build_class(self): - """ - Finalize class based on the accumulated configuration. - - Builder cannot be used after calling this method. - """ - if self._slots is True: - return self._create_slots_class() - else: - return self._patch_original_class() - - def _patch_original_class(self): - """ - Apply accumulated methods and return the class. - """ - cls = self._cls - base_names = self._base_names - - # Clean class of attribute definitions (`attr.ib()`s). - if self._delete_attribs: - for name in self._attr_names: - if ( - name not in base_names - and getattr(cls, name, _sentinel) is not _sentinel - ): - try: - delattr(cls, name) - except AttributeError: - # This can happen if a base class defines a class - # variable and we want to set an attribute with the - # same name by using only a type annotation. - pass - - # Attach our dunder methods. - for name, value in self._cls_dict.items(): - setattr(cls, name, value) - - # If we've inherited an attrs __setattr__ and don't write our own, - # reset it to object's. - if not self._wrote_own_setattr and getattr( - cls, "__attrs_own_setattr__", False - ): - cls.__attrs_own_setattr__ = False - - if not self._has_custom_setattr: - cls.__setattr__ = object.__setattr__ - - return cls - - def _create_slots_class(self): - """ - Build and return a new class with a `__slots__` attribute. - """ - cd = { - k: v - for k, v in iteritems(self._cls_dict) - if k not in tuple(self._attr_names) + ("__dict__", "__weakref__") - } - - # If our class doesn't have its own implementation of __setattr__ - # (either from the user or by us), check the bases, if one of them has - # an attrs-made __setattr__, that needs to be reset. We don't walk the - # MRO because we only care about our immediate base classes. - # XXX: This can be confused by subclassing a slotted attrs class with - # XXX: a non-attrs class and subclass the resulting class with an attrs - # XXX: class. See `test_slotted_confused` for details. For now that's - # XXX: OK with us. - if not self._wrote_own_setattr: - cd["__attrs_own_setattr__"] = False - - if not self._has_custom_setattr: - for base_cls in self._cls.__bases__: - if base_cls.__dict__.get("__attrs_own_setattr__", False): - cd["__setattr__"] = object.__setattr__ - break - - # Traverse the MRO to collect existing slots - # and check for an existing __weakref__. - existing_slots = dict() - weakref_inherited = False - for base_cls in self._cls.__mro__[1:-1]: - if base_cls.__dict__.get("__weakref__", None) is not None: - weakref_inherited = True - existing_slots.update( - { - name: getattr(base_cls, name) - for name in getattr(base_cls, "__slots__", []) - } - ) - - base_names = set(self._base_names) - - names = self._attr_names - if ( - self._weakref_slot - and "__weakref__" not in getattr(self._cls, "__slots__", ()) - and "__weakref__" not in names - and not weakref_inherited - ): - names += ("__weakref__",) - - # We only add the names of attributes that aren't inherited. - # Setting __slots__ to inherited attributes wastes memory. - slot_names = [name for name in names if name not in base_names] - # There are slots for attributes from current class - # that are defined in parent classes. - # As their descriptors may be overriden by a child class, - # we collect them here and update the class dict - reused_slots = { - slot: slot_descriptor - for slot, slot_descriptor in iteritems(existing_slots) - if slot in slot_names - } - slot_names = [name for name in slot_names if name not in reused_slots] - cd.update(reused_slots) - if self._cache_hash: - slot_names.append(_hash_cache_field) - cd["__slots__"] = tuple(slot_names) - - qualname = getattr(self._cls, "__qualname__", None) - if qualname is not None: - cd["__qualname__"] = qualname - - # Create new class based on old class and our methods. - cls = type(self._cls)(self._cls.__name__, self._cls.__bases__, cd) - - # The following is a fix for - # . On Python 3, - # if a method mentions `__class__` or uses the no-arg super(), the - # compiler will bake a reference to the class in the method itself - # as `method.__closure__`. Since we replace the class with a - # clone, we rewrite these references so it keeps working. - for item in cls.__dict__.values(): - if isinstance(item, (classmethod, staticmethod)): - # Class- and staticmethods hide their functions inside. - # These might need to be rewritten as well. - closure_cells = getattr(item.__func__, "__closure__", None) - elif isinstance(item, property): - # Workaround for property `super()` shortcut (PY3-only). - # There is no universal way for other descriptors. - closure_cells = getattr(item.fget, "__closure__", None) - else: - closure_cells = getattr(item, "__closure__", None) - - if not closure_cells: # Catch None or the empty list. - continue - for cell in closure_cells: - try: - match = cell.cell_contents is self._cls - except ValueError: # ValueError: Cell is empty - pass - else: - if match: - set_closure_cell(cell, cls) - - return cls - - def add_repr(self, ns): - self._cls_dict["__repr__"] = self._add_method_dunders( - _make_repr(self._attrs, ns, self._cls) - ) - return self - - def add_str(self): - repr = self._cls_dict.get("__repr__") - if repr is None: - raise ValueError( - "__str__ can only be generated if a __repr__ exists." - ) - - def __str__(self): - return self.__repr__() - - self._cls_dict["__str__"] = self._add_method_dunders(__str__) - return self - - def _make_getstate_setstate(self): - """ - Create custom __setstate__ and __getstate__ methods. - """ - # __weakref__ is not writable. - state_attr_names = tuple( - an for an in self._attr_names if an != "__weakref__" - ) - - def slots_getstate(self): - """ - Automatically created by attrs. - """ - return tuple(getattr(self, name) for name in state_attr_names) - - hash_caching_enabled = self._cache_hash - - def slots_setstate(self, state): - """ - Automatically created by attrs. - """ - __bound_setattr = _obj_setattr.__get__(self, Attribute) - for name, value in zip(state_attr_names, state): - __bound_setattr(name, value) - - # The hash code cache is not included when the object is - # serialized, but it still needs to be initialized to None to - # indicate that the first call to __hash__ should be a cache - # miss. - if hash_caching_enabled: - __bound_setattr(_hash_cache_field, None) - - return slots_getstate, slots_setstate - - def make_unhashable(self): - self._cls_dict["__hash__"] = None - return self - - def add_hash(self): - self._cls_dict["__hash__"] = self._add_method_dunders( - _make_hash( - self._cls, - self._attrs, - frozen=self._frozen, - cache_hash=self._cache_hash, - ) - ) - - return self - - def add_init(self): - self._cls_dict["__init__"] = self._add_method_dunders( - _make_init( - self._cls, - self._attrs, - self._has_pre_init, - self._has_post_init, - self._frozen, - self._slots, - self._cache_hash, - self._base_attr_map, - self._is_exc, - self._on_setattr, - attrs_init=False, - ) - ) - - return self - - def add_match_args(self): - self._cls_dict["__match_args__"] = tuple( - field.name - for field in self._attrs - if field.init and not field.kw_only - ) - - def add_attrs_init(self): - self._cls_dict["__attrs_init__"] = self._add_method_dunders( - _make_init( - self._cls, - self._attrs, - self._has_pre_init, - self._has_post_init, - self._frozen, - self._slots, - self._cache_hash, - self._base_attr_map, - self._is_exc, - self._on_setattr, - attrs_init=True, - ) - ) - - return self - - def add_eq(self): - cd = self._cls_dict - - cd["__eq__"] = self._add_method_dunders( - _make_eq(self._cls, self._attrs) - ) - cd["__ne__"] = self._add_method_dunders(_make_ne()) - - return self - - def add_order(self): - cd = self._cls_dict - - cd["__lt__"], cd["__le__"], cd["__gt__"], cd["__ge__"] = ( - self._add_method_dunders(meth) - for meth in _make_order(self._cls, self._attrs) - ) - - return self - - def add_setattr(self): - if self._frozen: - return self - - sa_attrs = {} - for a in self._attrs: - on_setattr = a.on_setattr or self._on_setattr - if on_setattr and on_setattr is not setters.NO_OP: - sa_attrs[a.name] = a, on_setattr - - if not sa_attrs: - return self - - if self._has_custom_setattr: - # We need to write a __setattr__ but there already is one! - raise ValueError( - "Can't combine custom __setattr__ with on_setattr hooks." - ) - - # docstring comes from _add_method_dunders - def __setattr__(self, name, val): - try: - a, hook = sa_attrs[name] - except KeyError: - nval = val - else: - nval = hook(self, a, val) - - _obj_setattr(self, name, nval) - - self._cls_dict["__attrs_own_setattr__"] = True - self._cls_dict["__setattr__"] = self._add_method_dunders(__setattr__) - self._wrote_own_setattr = True - - return self - - def _add_method_dunders(self, method): - """ - Add __module__ and __qualname__ to a *method* if possible. - """ - try: - method.__module__ = self._cls.__module__ - except AttributeError: - pass - - try: - method.__qualname__ = ".".join( - (self._cls.__qualname__, method.__name__) - ) - except AttributeError: - pass - - try: - method.__doc__ = "Method generated by attrs for class %s." % ( - self._cls.__qualname__, - ) - except AttributeError: - pass - - return method - - -_CMP_DEPRECATION = ( - "The usage of `cmp` is deprecated and will be removed on or after " - "2021-06-01. Please use `eq` and `order` instead." -) - - -def _determine_attrs_eq_order(cmp, eq, order, default_eq): - """ - Validate the combination of *cmp*, *eq*, and *order*. Derive the effective - values of eq and order. If *eq* is None, set it to *default_eq*. - """ - if cmp is not None and any((eq is not None, order is not None)): - raise ValueError("Don't mix `cmp` with `eq' and `order`.") - - # cmp takes precedence due to bw-compatibility. - if cmp is not None: - return cmp, cmp - - # If left None, equality is set to the specified default and ordering - # mirrors equality. - if eq is None: - eq = default_eq - - if order is None: - order = eq - - if eq is False and order is True: - raise ValueError("`order` can only be True if `eq` is True too.") - - return eq, order - - -def _determine_attrib_eq_order(cmp, eq, order, default_eq): - """ - Validate the combination of *cmp*, *eq*, and *order*. Derive the effective - values of eq and order. If *eq* is None, set it to *default_eq*. - """ - if cmp is not None and any((eq is not None, order is not None)): - raise ValueError("Don't mix `cmp` with `eq' and `order`.") - - def decide_callable_or_boolean(value): - """ - Decide whether a key function is used. - """ - if callable(value): - value, key = True, value - else: - key = None - return value, key - - # cmp takes precedence due to bw-compatibility. - if cmp is not None: - cmp, cmp_key = decide_callable_or_boolean(cmp) - return cmp, cmp_key, cmp, cmp_key - - # If left None, equality is set to the specified default and ordering - # mirrors equality. - if eq is None: - eq, eq_key = default_eq, None - else: - eq, eq_key = decide_callable_or_boolean(eq) - - if order is None: - order, order_key = eq, eq_key - else: - order, order_key = decide_callable_or_boolean(order) - - if eq is False and order is True: - raise ValueError("`order` can only be True if `eq` is True too.") - - return eq, eq_key, order, order_key - - -def _determine_whether_to_implement( - cls, flag, auto_detect, dunders, default=True -): - """ - Check whether we should implement a set of methods for *cls*. - - *flag* is the argument passed into @attr.s like 'init', *auto_detect* the - same as passed into @attr.s and *dunders* is a tuple of attribute names - whose presence signal that the user has implemented it themselves. - - Return *default* if no reason for either for or against is found. - - auto_detect must be False on Python 2. - """ - if flag is True or flag is False: - return flag - - if flag is None and auto_detect is False: - return default - - # Logically, flag is None and auto_detect is True here. - for dunder in dunders: - if _has_own_attribute(cls, dunder): - return False - - return default - - -def attrs( - maybe_cls=None, - these=None, - repr_ns=None, - repr=None, - cmp=None, - hash=None, - init=None, - slots=False, - frozen=False, - weakref_slot=True, - str=False, - auto_attribs=False, - kw_only=False, - cache_hash=False, - auto_exc=False, - eq=None, - order=None, - auto_detect=False, - collect_by_mro=False, - getstate_setstate=None, - on_setattr=None, - field_transformer=None, - match_args=True, -): - r""" - A class decorator that adds `dunder - `_\ -methods according to the - specified attributes using `attr.ib` or the *these* argument. - - :param these: A dictionary of name to `attr.ib` mappings. This is - useful to avoid the definition of your attributes within the class body - because you can't (e.g. if you want to add ``__repr__`` methods to - Django models) or don't want to. - - If *these* is not ``None``, ``attrs`` will *not* search the class body - for attributes and will *not* remove any attributes from it. - - If *these* is an ordered dict (`dict` on Python 3.6+, - `collections.OrderedDict` otherwise), the order is deduced from - the order of the attributes inside *these*. Otherwise the order - of the definition of the attributes is used. - - :type these: `dict` of `str` to `attr.ib` - - :param str repr_ns: When using nested classes, there's no way in Python 2 - to automatically detect that. Therefore it's possible to set the - namespace explicitly for a more meaningful ``repr`` output. - :param bool auto_detect: Instead of setting the *init*, *repr*, *eq*, - *order*, and *hash* arguments explicitly, assume they are set to - ``True`` **unless any** of the involved methods for one of the - arguments is implemented in the *current* class (i.e. it is *not* - inherited from some base class). - - So for example by implementing ``__eq__`` on a class yourself, - ``attrs`` will deduce ``eq=False`` and will create *neither* - ``__eq__`` *nor* ``__ne__`` (but Python classes come with a sensible - ``__ne__`` by default, so it *should* be enough to only implement - ``__eq__`` in most cases). - - .. warning:: - - If you prevent ``attrs`` from creating the ordering methods for you - (``order=False``, e.g. by implementing ``__le__``), it becomes - *your* responsibility to make sure its ordering is sound. The best - way is to use the `functools.total_ordering` decorator. - - - Passing ``True`` or ``False`` to *init*, *repr*, *eq*, *order*, - *cmp*, or *hash* overrides whatever *auto_detect* would determine. - - *auto_detect* requires Python 3. Setting it ``True`` on Python 2 raises - an `attrs.exceptions.PythonTooOldError`. - - :param bool repr: Create a ``__repr__`` method with a human readable - representation of ``attrs`` attributes.. - :param bool str: Create a ``__str__`` method that is identical to - ``__repr__``. This is usually not necessary except for - `Exception`\ s. - :param Optional[bool] eq: If ``True`` or ``None`` (default), add ``__eq__`` - and ``__ne__`` methods that check two instances for equality. - - They compare the instances as if they were tuples of their ``attrs`` - attributes if and only if the types of both classes are *identical*! - :param Optional[bool] order: If ``True``, add ``__lt__``, ``__le__``, - ``__gt__``, and ``__ge__`` methods that behave like *eq* above and - allow instances to be ordered. If ``None`` (default) mirror value of - *eq*. - :param Optional[bool] cmp: Setting *cmp* is equivalent to setting *eq* - and *order* to the same value. Must not be mixed with *eq* or *order*. - :param Optional[bool] hash: If ``None`` (default), the ``__hash__`` method - is generated according how *eq* and *frozen* are set. - - 1. If *both* are True, ``attrs`` will generate a ``__hash__`` for you. - 2. If *eq* is True and *frozen* is False, ``__hash__`` will be set to - None, marking it unhashable (which it is). - 3. If *eq* is False, ``__hash__`` will be left untouched meaning the - ``__hash__`` method of the base class will be used (if base class is - ``object``, this means it will fall back to id-based hashing.). - - Although not recommended, you can decide for yourself and force - ``attrs`` to create one (e.g. if the class is immutable even though you - didn't freeze it programmatically) by passing ``True`` or not. Both of - these cases are rather special and should be used carefully. - - See our documentation on `hashing`, Python's documentation on - `object.__hash__`, and the `GitHub issue that led to the default \ - behavior `_ for more - details. - :param bool init: Create a ``__init__`` method that initializes the - ``attrs`` attributes. Leading underscores are stripped for the argument - name. If a ``__attrs_pre_init__`` method exists on the class, it will - be called before the class is initialized. If a ``__attrs_post_init__`` - method exists on the class, it will be called after the class is fully - initialized. - - If ``init`` is ``False``, an ``__attrs_init__`` method will be - injected instead. This allows you to define a custom ``__init__`` - method that can do pre-init work such as ``super().__init__()``, - and then call ``__attrs_init__()`` and ``__attrs_post_init__()``. - :param bool slots: Create a `slotted class ` that's more - memory-efficient. Slotted classes are generally superior to the default - dict classes, but have some gotchas you should know about, so we - encourage you to read the `glossary entry `. - :param bool frozen: Make instances immutable after initialization. If - someone attempts to modify a frozen instance, - `attr.exceptions.FrozenInstanceError` is raised. - - .. note:: - - 1. This is achieved by installing a custom ``__setattr__`` method - on your class, so you can't implement your own. - - 2. True immutability is impossible in Python. - - 3. This *does* have a minor a runtime performance `impact - ` when initializing new instances. In other words: - ``__init__`` is slightly slower with ``frozen=True``. - - 4. If a class is frozen, you cannot modify ``self`` in - ``__attrs_post_init__`` or a self-written ``__init__``. You can - circumvent that limitation by using - ``object.__setattr__(self, "attribute_name", value)``. - - 5. Subclasses of a frozen class are frozen too. - - :param bool weakref_slot: Make instances weak-referenceable. This has no - effect unless ``slots`` is also enabled. - :param bool auto_attribs: If ``True``, collect `PEP 526`_-annotated - attributes (Python 3.6 and later only) from the class body. - - In this case, you **must** annotate every field. If ``attrs`` - encounters a field that is set to an `attr.ib` but lacks a type - annotation, an `attr.exceptions.UnannotatedAttributeError` is - raised. Use ``field_name: typing.Any = attr.ib(...)`` if you don't - want to set a type. - - If you assign a value to those attributes (e.g. ``x: int = 42``), that - value becomes the default value like if it were passed using - ``attr.ib(default=42)``. Passing an instance of `attrs.Factory` also - works as expected in most cases (see warning below). - - Attributes annotated as `typing.ClassVar`, and attributes that are - neither annotated nor set to an `attr.ib` are **ignored**. - - .. warning:: - For features that use the attribute name to create decorators (e.g. - `validators `), you still *must* assign `attr.ib` to - them. Otherwise Python will either not find the name or try to use - the default value to call e.g. ``validator`` on it. - - These errors can be quite confusing and probably the most common bug - report on our bug tracker. - - .. _`PEP 526`: https://www.python.org/dev/peps/pep-0526/ - :param bool kw_only: Make all attributes keyword-only (Python 3+) - in the generated ``__init__`` (if ``init`` is ``False``, this - parameter is ignored). - :param bool cache_hash: Ensure that the object's hash code is computed - only once and stored on the object. If this is set to ``True``, - hashing must be either explicitly or implicitly enabled for this - class. If the hash code is cached, avoid any reassignments of - fields involved in hash code computation or mutations of the objects - those fields point to after object creation. If such changes occur, - the behavior of the object's hash code is undefined. - :param bool auto_exc: If the class subclasses `BaseException` - (which implicitly includes any subclass of any exception), the - following happens to behave like a well-behaved Python exceptions - class: - - - the values for *eq*, *order*, and *hash* are ignored and the - instances compare and hash by the instance's ids (N.B. ``attrs`` will - *not* remove existing implementations of ``__hash__`` or the equality - methods. It just won't add own ones.), - - all attributes that are either passed into ``__init__`` or have a - default value are additionally available as a tuple in the ``args`` - attribute, - - the value of *str* is ignored leaving ``__str__`` to base classes. - :param bool collect_by_mro: Setting this to `True` fixes the way ``attrs`` - collects attributes from base classes. The default behavior is - incorrect in certain cases of multiple inheritance. It should be on by - default but is kept off for backward-compatibility. - - See issue `#428 `_ for - more details. - - :param Optional[bool] getstate_setstate: - .. note:: - This is usually only interesting for slotted classes and you should - probably just set *auto_detect* to `True`. - - If `True`, ``__getstate__`` and - ``__setstate__`` are generated and attached to the class. This is - necessary for slotted classes to be pickleable. If left `None`, it's - `True` by default for slotted classes and ``False`` for dict classes. - - If *auto_detect* is `True`, and *getstate_setstate* is left `None`, - and **either** ``__getstate__`` or ``__setstate__`` is detected directly - on the class (i.e. not inherited), it is set to `False` (this is usually - what you want). - - :param on_setattr: A callable that is run whenever the user attempts to set - an attribute (either by assignment like ``i.x = 42`` or by using - `setattr` like ``setattr(i, "x", 42)``). It receives the same arguments - as validators: the instance, the attribute that is being modified, and - the new value. - - If no exception is raised, the attribute is set to the return value of - the callable. - - If a list of callables is passed, they're automatically wrapped in an - `attrs.setters.pipe`. - - :param Optional[callable] field_transformer: - A function that is called with the original class object and all - fields right before ``attrs`` finalizes the class. You can use - this, e.g., to automatically add converters or validators to - fields based on their types. See `transform-fields` for more details. - - :param bool match_args: - If `True` (default), set ``__match_args__`` on the class to support - `PEP 634 `_ (Structural - Pattern Matching). It is a tuple of all positional-only ``__init__`` - parameter names on Python 3.10 and later. Ignored on older Python - versions. - - .. versionadded:: 16.0.0 *slots* - .. versionadded:: 16.1.0 *frozen* - .. versionadded:: 16.3.0 *str* - .. versionadded:: 16.3.0 Support for ``__attrs_post_init__``. - .. versionchanged:: 17.1.0 - *hash* supports ``None`` as value which is also the default now. - .. versionadded:: 17.3.0 *auto_attribs* - .. versionchanged:: 18.1.0 - If *these* is passed, no attributes are deleted from the class body. - .. versionchanged:: 18.1.0 If *these* is ordered, the order is retained. - .. versionadded:: 18.2.0 *weakref_slot* - .. deprecated:: 18.2.0 - ``__lt__``, ``__le__``, ``__gt__``, and ``__ge__`` now raise a - `DeprecationWarning` if the classes compared are subclasses of - each other. ``__eq`` and ``__ne__`` never tried to compared subclasses - to each other. - .. versionchanged:: 19.2.0 - ``__lt__``, ``__le__``, ``__gt__``, and ``__ge__`` now do not consider - subclasses comparable anymore. - .. versionadded:: 18.2.0 *kw_only* - .. versionadded:: 18.2.0 *cache_hash* - .. versionadded:: 19.1.0 *auto_exc* - .. deprecated:: 19.2.0 *cmp* Removal on or after 2021-06-01. - .. versionadded:: 19.2.0 *eq* and *order* - .. versionadded:: 20.1.0 *auto_detect* - .. versionadded:: 20.1.0 *collect_by_mro* - .. versionadded:: 20.1.0 *getstate_setstate* - .. versionadded:: 20.1.0 *on_setattr* - .. versionadded:: 20.3.0 *field_transformer* - .. versionchanged:: 21.1.0 - ``init=False`` injects ``__attrs_init__`` - .. versionchanged:: 21.1.0 Support for ``__attrs_pre_init__`` - .. versionchanged:: 21.1.0 *cmp* undeprecated - .. versionadded:: 21.3.0 *match_args* - """ - if auto_detect and PY2: - raise PythonTooOldError( - "auto_detect only works on Python 3 and later." - ) - - eq_, order_ = _determine_attrs_eq_order(cmp, eq, order, None) - hash_ = hash # work around the lack of nonlocal - - if isinstance(on_setattr, (list, tuple)): - on_setattr = setters.pipe(*on_setattr) - - def wrap(cls): - - if getattr(cls, "__class__", None) is None: - raise TypeError("attrs only works with new-style classes.") - - is_frozen = frozen or _has_frozen_base_class(cls) - is_exc = auto_exc is True and issubclass(cls, BaseException) - has_own_setattr = auto_detect and _has_own_attribute( - cls, "__setattr__" - ) - - if has_own_setattr and is_frozen: - raise ValueError("Can't freeze a class with a custom __setattr__.") - - builder = _ClassBuilder( - cls, - these, - slots, - is_frozen, - weakref_slot, - _determine_whether_to_implement( - cls, - getstate_setstate, - auto_detect, - ("__getstate__", "__setstate__"), - default=slots, - ), - auto_attribs, - kw_only, - cache_hash, - is_exc, - collect_by_mro, - on_setattr, - has_own_setattr, - field_transformer, - ) - if _determine_whether_to_implement( - cls, repr, auto_detect, ("__repr__",) - ): - builder.add_repr(repr_ns) - if str is True: - builder.add_str() - - eq = _determine_whether_to_implement( - cls, eq_, auto_detect, ("__eq__", "__ne__") - ) - if not is_exc and eq is True: - builder.add_eq() - if not is_exc and _determine_whether_to_implement( - cls, order_, auto_detect, ("__lt__", "__le__", "__gt__", "__ge__") - ): - builder.add_order() - - builder.add_setattr() - - if ( - hash_ is None - and auto_detect is True - and _has_own_attribute(cls, "__hash__") - ): - hash = False - else: - hash = hash_ - if hash is not True and hash is not False and hash is not None: - # Can't use `hash in` because 1 == True for example. - raise TypeError( - "Invalid value for hash. Must be True, False, or None." - ) - elif hash is False or (hash is None and eq is False) or is_exc: - # Don't do anything. Should fall back to __object__'s __hash__ - # which is by id. - if cache_hash: - raise TypeError( - "Invalid value for cache_hash. To use hash caching," - " hashing must be either explicitly or implicitly " - "enabled." - ) - elif hash is True or ( - hash is None and eq is True and is_frozen is True - ): - # Build a __hash__ if told so, or if it's safe. - builder.add_hash() - else: - # Raise TypeError on attempts to hash. - if cache_hash: - raise TypeError( - "Invalid value for cache_hash. To use hash caching," - " hashing must be either explicitly or implicitly " - "enabled." - ) - builder.make_unhashable() - - if _determine_whether_to_implement( - cls, init, auto_detect, ("__init__",) - ): - builder.add_init() - else: - builder.add_attrs_init() - if cache_hash: - raise TypeError( - "Invalid value for cache_hash. To use hash caching," - " init must be True." - ) - - if ( - PY310 - and match_args - and not _has_own_attribute(cls, "__match_args__") - ): - builder.add_match_args() - - return builder.build_class() - - # maybe_cls's type depends on the usage of the decorator. It's a class - # if it's used as `@attrs` but ``None`` if used as `@attrs()`. - if maybe_cls is None: - return wrap - else: - return wrap(maybe_cls) - - -_attrs = attrs -""" -Internal alias so we can use it in functions that take an argument called -*attrs*. -""" - - -if PY2: - - def _has_frozen_base_class(cls): - """ - Check whether *cls* has a frozen ancestor by looking at its - __setattr__. - """ - return ( - getattr(cls.__setattr__, "__module__", None) - == _frozen_setattrs.__module__ - and cls.__setattr__.__name__ == _frozen_setattrs.__name__ - ) - -else: - - def _has_frozen_base_class(cls): - """ - Check whether *cls* has a frozen ancestor by looking at its - __setattr__. - """ - return cls.__setattr__ == _frozen_setattrs - - -def _generate_unique_filename(cls, func_name): - """ - Create a "filename" suitable for a function being generated. - """ - unique_filename = "".format( - func_name, - cls.__module__, - getattr(cls, "__qualname__", cls.__name__), - ) - return unique_filename - - -def _make_hash(cls, attrs, frozen, cache_hash): - attrs = tuple( - a for a in attrs if a.hash is True or (a.hash is None and a.eq is True) - ) - - tab = " " - - unique_filename = _generate_unique_filename(cls, "hash") - type_hash = hash(unique_filename) - - hash_def = "def __hash__(self" - hash_func = "hash((" - closing_braces = "))" - if not cache_hash: - hash_def += "):" - else: - if not PY2: - hash_def += ", *" - - hash_def += ( - ", _cache_wrapper=" - + "__import__('attr._make')._make._CacheHashWrapper):" - ) - hash_func = "_cache_wrapper(" + hash_func - closing_braces += ")" - - method_lines = [hash_def] - - def append_hash_computation_lines(prefix, indent): - """ - Generate the code for actually computing the hash code. - Below this will either be returned directly or used to compute - a value which is then cached, depending on the value of cache_hash - """ - - method_lines.extend( - [ - indent + prefix + hash_func, - indent + " %d," % (type_hash,), - ] - ) - - for a in attrs: - method_lines.append(indent + " self.%s," % a.name) - - method_lines.append(indent + " " + closing_braces) - - if cache_hash: - method_lines.append(tab + "if self.%s is None:" % _hash_cache_field) - if frozen: - append_hash_computation_lines( - "object.__setattr__(self, '%s', " % _hash_cache_field, tab * 2 - ) - method_lines.append(tab * 2 + ")") # close __setattr__ - else: - append_hash_computation_lines( - "self.%s = " % _hash_cache_field, tab * 2 - ) - method_lines.append(tab + "return self.%s" % _hash_cache_field) - else: - append_hash_computation_lines("return ", tab) - - script = "\n".join(method_lines) - return _make_method("__hash__", script, unique_filename) - - -def _add_hash(cls, attrs): - """ - Add a hash method to *cls*. - """ - cls.__hash__ = _make_hash(cls, attrs, frozen=False, cache_hash=False) - return cls - - -def _make_ne(): - """ - Create __ne__ method. - """ - - def __ne__(self, other): - """ - Check equality and either forward a NotImplemented or - return the result negated. - """ - result = self.__eq__(other) - if result is NotImplemented: - return NotImplemented - - return not result - - return __ne__ - - -def _make_eq(cls, attrs): - """ - Create __eq__ method for *cls* with *attrs*. - """ - attrs = [a for a in attrs if a.eq] - - unique_filename = _generate_unique_filename(cls, "eq") - lines = [ - "def __eq__(self, other):", - " if other.__class__ is not self.__class__:", - " return NotImplemented", - ] - - # We can't just do a big self.x = other.x and... clause due to - # irregularities like nan == nan is false but (nan,) == (nan,) is true. - globs = {} - if attrs: - lines.append(" return (") - others = [" ) == ("] - for a in attrs: - if a.eq_key: - cmp_name = "_%s_key" % (a.name,) - # Add the key function to the global namespace - # of the evaluated function. - globs[cmp_name] = a.eq_key - lines.append( - " %s(self.%s)," - % ( - cmp_name, - a.name, - ) - ) - others.append( - " %s(other.%s)," - % ( - cmp_name, - a.name, - ) - ) - else: - lines.append(" self.%s," % (a.name,)) - others.append(" other.%s," % (a.name,)) - - lines += others + [" )"] - else: - lines.append(" return True") - - script = "\n".join(lines) - - return _make_method("__eq__", script, unique_filename, globs) - - -def _make_order(cls, attrs): - """ - Create ordering methods for *cls* with *attrs*. - """ - attrs = [a for a in attrs if a.order] - - def attrs_to_tuple(obj): - """ - Save us some typing. - """ - return tuple( - key(value) if key else value - for value, key in ( - (getattr(obj, a.name), a.order_key) for a in attrs - ) - ) - - def __lt__(self, other): - """ - Automatically created by attrs. - """ - if other.__class__ is self.__class__: - return attrs_to_tuple(self) < attrs_to_tuple(other) - - return NotImplemented - - def __le__(self, other): - """ - Automatically created by attrs. - """ - if other.__class__ is self.__class__: - return attrs_to_tuple(self) <= attrs_to_tuple(other) - - return NotImplemented - - def __gt__(self, other): - """ - Automatically created by attrs. - """ - if other.__class__ is self.__class__: - return attrs_to_tuple(self) > attrs_to_tuple(other) - - return NotImplemented - - def __ge__(self, other): - """ - Automatically created by attrs. - """ - if other.__class__ is self.__class__: - return attrs_to_tuple(self) >= attrs_to_tuple(other) - - return NotImplemented - - return __lt__, __le__, __gt__, __ge__ - - -def _add_eq(cls, attrs=None): - """ - Add equality methods to *cls* with *attrs*. - """ - if attrs is None: - attrs = cls.__attrs_attrs__ - - cls.__eq__ = _make_eq(cls, attrs) - cls.__ne__ = _make_ne() - - return cls - - -if HAS_F_STRINGS: - - def _make_repr(attrs, ns, cls): - unique_filename = _generate_unique_filename(cls, "repr") - # Figure out which attributes to include, and which function to use to - # format them. The a.repr value can be either bool or a custom - # callable. - attr_names_with_reprs = tuple( - (a.name, (repr if a.repr is True else a.repr), a.init) - for a in attrs - if a.repr is not False - ) - globs = { - name + "_repr": r - for name, r, _ in attr_names_with_reprs - if r != repr - } - globs["_compat"] = _compat - globs["AttributeError"] = AttributeError - globs["NOTHING"] = NOTHING - attribute_fragments = [] - for name, r, i in attr_names_with_reprs: - accessor = ( - "self." + name - if i - else 'getattr(self, "' + name + '", NOTHING)' - ) - fragment = ( - "%s={%s!r}" % (name, accessor) - if r == repr - else "%s={%s_repr(%s)}" % (name, name, accessor) - ) - attribute_fragments.append(fragment) - repr_fragment = ", ".join(attribute_fragments) - - if ns is None: - cls_name_fragment = ( - '{self.__class__.__qualname__.rsplit(">.", 1)[-1]}' - ) - else: - cls_name_fragment = ns + ".{self.__class__.__name__}" - - lines = [ - "def __repr__(self):", - " try:", - " already_repring = _compat.repr_context.already_repring", - " except AttributeError:", - " already_repring = {id(self),}", - " _compat.repr_context.already_repring = already_repring", - " else:", - " if id(self) in already_repring:", - " return '...'", - " else:", - " already_repring.add(id(self))", - " try:", - " return f'%s(%s)'" % (cls_name_fragment, repr_fragment), - " finally:", - " already_repring.remove(id(self))", - ] - - return _make_method( - "__repr__", "\n".join(lines), unique_filename, globs=globs - ) - -else: - - def _make_repr(attrs, ns, _): - """ - Make a repr method that includes relevant *attrs*, adding *ns* to the - full name. - """ - - # Figure out which attributes to include, and which function to use to - # format them. The a.repr value can be either bool or a custom - # callable. - attr_names_with_reprs = tuple( - (a.name, repr if a.repr is True else a.repr) - for a in attrs - if a.repr is not False - ) - - def __repr__(self): - """ - Automatically created by attrs. - """ - try: - already_repring = _compat.repr_context.already_repring - except AttributeError: - already_repring = set() - _compat.repr_context.already_repring = already_repring - - if id(self) in already_repring: - return "..." - real_cls = self.__class__ - if ns is None: - qualname = getattr(real_cls, "__qualname__", None) - if qualname is not None: # pragma: no cover - # This case only happens on Python 3.5 and 3.6. We exclude - # it from coverage, because we don't want to slow down our - # test suite by running them under coverage too for this - # one line. - class_name = qualname.rsplit(">.", 1)[-1] - else: - class_name = real_cls.__name__ - else: - class_name = ns + "." + real_cls.__name__ - - # Since 'self' remains on the stack (i.e.: strongly referenced) - # for the duration of this call, it's safe to depend on id(...) - # stability, and not need to track the instance and therefore - # worry about properties like weakref- or hash-ability. - already_repring.add(id(self)) - try: - result = [class_name, "("] - first = True - for name, attr_repr in attr_names_with_reprs: - if first: - first = False - else: - result.append(", ") - result.extend( - (name, "=", attr_repr(getattr(self, name, NOTHING))) - ) - return "".join(result) + ")" - finally: - already_repring.remove(id(self)) - - return __repr__ - - -def _add_repr(cls, ns=None, attrs=None): - """ - Add a repr method to *cls*. - """ - if attrs is None: - attrs = cls.__attrs_attrs__ - - cls.__repr__ = _make_repr(attrs, ns, cls) - return cls - - -def fields(cls): - """ - Return the tuple of ``attrs`` attributes for a class. - - The tuple also allows accessing the fields by their names (see below for - examples). - - :param type cls: Class to introspect. - - :raise TypeError: If *cls* is not a class. - :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` - class. - - :rtype: tuple (with name accessors) of `attrs.Attribute` - - .. versionchanged:: 16.2.0 Returned tuple allows accessing the fields - by name. - """ - if not isclass(cls): - raise TypeError("Passed object must be a class.") - attrs = getattr(cls, "__attrs_attrs__", None) - if attrs is None: - raise NotAnAttrsClassError( - "{cls!r} is not an attrs-decorated class.".format(cls=cls) - ) - return attrs - - -def fields_dict(cls): - """ - Return an ordered dictionary of ``attrs`` attributes for a class, whose - keys are the attribute names. - - :param type cls: Class to introspect. - - :raise TypeError: If *cls* is not a class. - :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` - class. - - :rtype: an ordered dict where keys are attribute names and values are - `attrs.Attribute`\\ s. This will be a `dict` if it's - naturally ordered like on Python 3.6+ or an - :class:`~collections.OrderedDict` otherwise. - - .. versionadded:: 18.1.0 - """ - if not isclass(cls): - raise TypeError("Passed object must be a class.") - attrs = getattr(cls, "__attrs_attrs__", None) - if attrs is None: - raise NotAnAttrsClassError( - "{cls!r} is not an attrs-decorated class.".format(cls=cls) - ) - return ordered_dict(((a.name, a) for a in attrs)) - - -def validate(inst): - """ - Validate all attributes on *inst* that have a validator. - - Leaves all exceptions through. - - :param inst: Instance of a class with ``attrs`` attributes. - """ - if _config._run_validators is False: - return - - for a in fields(inst.__class__): - v = a.validator - if v is not None: - v(inst, a, getattr(inst, a.name)) - - -def _is_slot_cls(cls): - return "__slots__" in cls.__dict__ - - -def _is_slot_attr(a_name, base_attr_map): - """ - Check if the attribute name comes from a slot class. - """ - return a_name in base_attr_map and _is_slot_cls(base_attr_map[a_name]) - - -def _make_init( - cls, - attrs, - pre_init, - post_init, - frozen, - slots, - cache_hash, - base_attr_map, - is_exc, - cls_on_setattr, - attrs_init, -): - has_cls_on_setattr = ( - cls_on_setattr is not None and cls_on_setattr is not setters.NO_OP - ) - - if frozen and has_cls_on_setattr: - raise ValueError("Frozen classes can't use on_setattr.") - - needs_cached_setattr = cache_hash or frozen - filtered_attrs = [] - attr_dict = {} - for a in attrs: - if not a.init and a.default is NOTHING: - continue - - filtered_attrs.append(a) - attr_dict[a.name] = a - - if a.on_setattr is not None: - if frozen is True: - raise ValueError("Frozen classes can't use on_setattr.") - - needs_cached_setattr = True - elif has_cls_on_setattr and a.on_setattr is not setters.NO_OP: - needs_cached_setattr = True - - unique_filename = _generate_unique_filename(cls, "init") - - script, globs, annotations = _attrs_to_init_script( - filtered_attrs, - frozen, - slots, - pre_init, - post_init, - cache_hash, - base_attr_map, - is_exc, - needs_cached_setattr, - has_cls_on_setattr, - attrs_init, - ) - if cls.__module__ in sys.modules: - # This makes typing.get_type_hints(CLS.__init__) resolve string types. - globs.update(sys.modules[cls.__module__].__dict__) - - globs.update({"NOTHING": NOTHING, "attr_dict": attr_dict}) - - if needs_cached_setattr: - # Save the lookup overhead in __init__ if we need to circumvent - # setattr hooks. - globs["_cached_setattr"] = _obj_setattr - - init = _make_method( - "__attrs_init__" if attrs_init else "__init__", - script, - unique_filename, - globs, - ) - init.__annotations__ = annotations - - return init - - -def _setattr(attr_name, value_var, has_on_setattr): - """ - Use the cached object.setattr to set *attr_name* to *value_var*. - """ - return "_setattr('%s', %s)" % (attr_name, value_var) - - -def _setattr_with_converter(attr_name, value_var, has_on_setattr): - """ - Use the cached object.setattr to set *attr_name* to *value_var*, but run - its converter first. - """ - return "_setattr('%s', %s(%s))" % ( - attr_name, - _init_converter_pat % (attr_name,), - value_var, - ) - - -def _assign(attr_name, value, has_on_setattr): - """ - Unless *attr_name* has an on_setattr hook, use normal assignment. Otherwise - relegate to _setattr. - """ - if has_on_setattr: - return _setattr(attr_name, value, True) - - return "self.%s = %s" % (attr_name, value) - - -def _assign_with_converter(attr_name, value_var, has_on_setattr): - """ - Unless *attr_name* has an on_setattr hook, use normal assignment after - conversion. Otherwise relegate to _setattr_with_converter. - """ - if has_on_setattr: - return _setattr_with_converter(attr_name, value_var, True) - - return "self.%s = %s(%s)" % ( - attr_name, - _init_converter_pat % (attr_name,), - value_var, - ) - - -if PY2: - - def _unpack_kw_only_py2(attr_name, default=None): - """ - Unpack *attr_name* from _kw_only dict. - """ - if default is not None: - arg_default = ", %s" % default - else: - arg_default = "" - return "%s = _kw_only.pop('%s'%s)" % ( - attr_name, - attr_name, - arg_default, - ) - - def _unpack_kw_only_lines_py2(kw_only_args): - """ - Unpack all *kw_only_args* from _kw_only dict and handle errors. - - Given a list of strings "{attr_name}" and "{attr_name}={default}" - generates list of lines of code that pop attrs from _kw_only dict and - raise TypeError similar to builtin if required attr is missing or - extra key is passed. - - >>> print("\n".join(_unpack_kw_only_lines_py2(["a", "b=42"]))) - try: - a = _kw_only.pop('a') - b = _kw_only.pop('b', 42) - except KeyError as _key_error: - raise TypeError( - ... - if _kw_only: - raise TypeError( - ... - """ - lines = ["try:"] - lines.extend( - " " + _unpack_kw_only_py2(*arg.split("=")) - for arg in kw_only_args - ) - lines += """\ -except KeyError as _key_error: - raise TypeError( - '__init__() missing required keyword-only argument: %s' % _key_error - ) -if _kw_only: - raise TypeError( - '__init__() got an unexpected keyword argument %r' - % next(iter(_kw_only)) - ) -""".split( - "\n" - ) - return lines - - -def _attrs_to_init_script( - attrs, - frozen, - slots, - pre_init, - post_init, - cache_hash, - base_attr_map, - is_exc, - needs_cached_setattr, - has_cls_on_setattr, - attrs_init, -): - """ - Return a script of an initializer for *attrs* and a dict of globals. - - The globals are expected by the generated script. - - If *frozen* is True, we cannot set the attributes directly so we use - a cached ``object.__setattr__``. - """ - lines = [] - if pre_init: - lines.append("self.__attrs_pre_init__()") - - if needs_cached_setattr: - lines.append( - # Circumvent the __setattr__ descriptor to save one lookup per - # assignment. - # Note _setattr will be used again below if cache_hash is True - "_setattr = _cached_setattr.__get__(self, self.__class__)" - ) - - if frozen is True: - if slots is True: - fmt_setter = _setattr - fmt_setter_with_converter = _setattr_with_converter - else: - # Dict frozen classes assign directly to __dict__. - # But only if the attribute doesn't come from an ancestor slot - # class. - # Note _inst_dict will be used again below if cache_hash is True - lines.append("_inst_dict = self.__dict__") - - def fmt_setter(attr_name, value_var, has_on_setattr): - if _is_slot_attr(attr_name, base_attr_map): - return _setattr(attr_name, value_var, has_on_setattr) - - return "_inst_dict['%s'] = %s" % (attr_name, value_var) - - def fmt_setter_with_converter( - attr_name, value_var, has_on_setattr - ): - if has_on_setattr or _is_slot_attr(attr_name, base_attr_map): - return _setattr_with_converter( - attr_name, value_var, has_on_setattr - ) - - return "_inst_dict['%s'] = %s(%s)" % ( - attr_name, - _init_converter_pat % (attr_name,), - value_var, - ) - - else: - # Not frozen. - fmt_setter = _assign - fmt_setter_with_converter = _assign_with_converter - - args = [] - kw_only_args = [] - attrs_to_validate = [] - - # This is a dictionary of names to validator and converter callables. - # Injecting this into __init__ globals lets us avoid lookups. - names_for_globals = {} - annotations = {"return": None} - - for a in attrs: - if a.validator: - attrs_to_validate.append(a) - - attr_name = a.name - has_on_setattr = a.on_setattr is not None or ( - a.on_setattr is not setters.NO_OP and has_cls_on_setattr - ) - arg_name = a.name.lstrip("_") - - has_factory = isinstance(a.default, Factory) - if has_factory and a.default.takes_self: - maybe_self = "self" - else: - maybe_self = "" - - if a.init is False: - if has_factory: - init_factory_name = _init_factory_pat.format(a.name) - if a.converter is not None: - lines.append( - fmt_setter_with_converter( - attr_name, - init_factory_name + "(%s)" % (maybe_self,), - has_on_setattr, - ) - ) - conv_name = _init_converter_pat % (a.name,) - names_for_globals[conv_name] = a.converter - else: - lines.append( - fmt_setter( - attr_name, - init_factory_name + "(%s)" % (maybe_self,), - has_on_setattr, - ) - ) - names_for_globals[init_factory_name] = a.default.factory - else: - if a.converter is not None: - lines.append( - fmt_setter_with_converter( - attr_name, - "attr_dict['%s'].default" % (attr_name,), - has_on_setattr, - ) - ) - conv_name = _init_converter_pat % (a.name,) - names_for_globals[conv_name] = a.converter - else: - lines.append( - fmt_setter( - attr_name, - "attr_dict['%s'].default" % (attr_name,), - has_on_setattr, - ) - ) - elif a.default is not NOTHING and not has_factory: - arg = "%s=attr_dict['%s'].default" % (arg_name, attr_name) - if a.kw_only: - kw_only_args.append(arg) - else: - args.append(arg) - - if a.converter is not None: - lines.append( - fmt_setter_with_converter( - attr_name, arg_name, has_on_setattr - ) - ) - names_for_globals[ - _init_converter_pat % (a.name,) - ] = a.converter - else: - lines.append(fmt_setter(attr_name, arg_name, has_on_setattr)) - - elif has_factory: - arg = "%s=NOTHING" % (arg_name,) - if a.kw_only: - kw_only_args.append(arg) - else: - args.append(arg) - lines.append("if %s is not NOTHING:" % (arg_name,)) - - init_factory_name = _init_factory_pat.format(a.name) - if a.converter is not None: - lines.append( - " " - + fmt_setter_with_converter( - attr_name, arg_name, has_on_setattr - ) - ) - lines.append("else:") - lines.append( - " " - + fmt_setter_with_converter( - attr_name, - init_factory_name + "(" + maybe_self + ")", - has_on_setattr, - ) - ) - names_for_globals[ - _init_converter_pat % (a.name,) - ] = a.converter - else: - lines.append( - " " + fmt_setter(attr_name, arg_name, has_on_setattr) - ) - lines.append("else:") - lines.append( - " " - + fmt_setter( - attr_name, - init_factory_name + "(" + maybe_self + ")", - has_on_setattr, - ) - ) - names_for_globals[init_factory_name] = a.default.factory - else: - if a.kw_only: - kw_only_args.append(arg_name) - else: - args.append(arg_name) - - if a.converter is not None: - lines.append( - fmt_setter_with_converter( - attr_name, arg_name, has_on_setattr - ) - ) - names_for_globals[ - _init_converter_pat % (a.name,) - ] = a.converter - else: - lines.append(fmt_setter(attr_name, arg_name, has_on_setattr)) - - if a.init is True: - if a.type is not None and a.converter is None: - annotations[arg_name] = a.type - elif a.converter is not None and not PY2: - # Try to get the type from the converter. - sig = None - try: - sig = inspect.signature(a.converter) - except (ValueError, TypeError): # inspect failed - pass - if sig: - sig_params = list(sig.parameters.values()) - if ( - sig_params - and sig_params[0].annotation - is not inspect.Parameter.empty - ): - annotations[arg_name] = sig_params[0].annotation - - if attrs_to_validate: # we can skip this if there are no validators. - names_for_globals["_config"] = _config - lines.append("if _config._run_validators is True:") - for a in attrs_to_validate: - val_name = "__attr_validator_" + a.name - attr_name = "__attr_" + a.name - lines.append( - " %s(self, %s, self.%s)" % (val_name, attr_name, a.name) - ) - names_for_globals[val_name] = a.validator - names_for_globals[attr_name] = a - - if post_init: - lines.append("self.__attrs_post_init__()") - - # because this is set only after __attrs_post_init is called, a crash - # will result if post-init tries to access the hash code. This seemed - # preferable to setting this beforehand, in which case alteration to - # field values during post-init combined with post-init accessing the - # hash code would result in silent bugs. - if cache_hash: - if frozen: - if slots: - # if frozen and slots, then _setattr defined above - init_hash_cache = "_setattr('%s', %s)" - else: - # if frozen and not slots, then _inst_dict defined above - init_hash_cache = "_inst_dict['%s'] = %s" - else: - init_hash_cache = "self.%s = %s" - lines.append(init_hash_cache % (_hash_cache_field, "None")) - - # For exceptions we rely on BaseException.__init__ for proper - # initialization. - if is_exc: - vals = ",".join("self." + a.name for a in attrs if a.init) - - lines.append("BaseException.__init__(self, %s)" % (vals,)) - - args = ", ".join(args) - if kw_only_args: - if PY2: - lines = _unpack_kw_only_lines_py2(kw_only_args) + lines - - args += "%s**_kw_only" % (", " if args else "",) # leading comma - else: - args += "%s*, %s" % ( - ", " if args else "", # leading comma - ", ".join(kw_only_args), # kw_only args - ) - return ( - """\ -def {init_name}(self, {args}): - {lines} -""".format( - init_name=("__attrs_init__" if attrs_init else "__init__"), - args=args, - lines="\n ".join(lines) if lines else "pass", - ), - names_for_globals, - annotations, - ) - - -class Attribute(object): - """ - *Read-only* representation of an attribute. - - The class has *all* arguments of `attr.ib` (except for ``factory`` - which is only syntactic sugar for ``default=Factory(...)`` plus the - following: - - - ``name`` (`str`): The name of the attribute. - - ``inherited`` (`bool`): Whether or not that attribute has been inherited - from a base class. - - ``eq_key`` and ``order_key`` (`typing.Callable` or `None`): The callables - that are used for comparing and ordering objects by this attribute, - respectively. These are set by passing a callable to `attr.ib`'s ``eq``, - ``order``, or ``cmp`` arguments. See also :ref:`comparison customization - `. - - Instances of this class are frequently used for introspection purposes - like: - - - `fields` returns a tuple of them. - - Validators get them passed as the first argument. - - The :ref:`field transformer ` hook receives a list of - them. - - .. versionadded:: 20.1.0 *inherited* - .. versionadded:: 20.1.0 *on_setattr* - .. versionchanged:: 20.2.0 *inherited* is not taken into account for - equality checks and hashing anymore. - .. versionadded:: 21.1.0 *eq_key* and *order_key* - - For the full version history of the fields, see `attr.ib`. - """ - - __slots__ = ( - "name", - "default", - "validator", - "repr", - "eq", - "eq_key", - "order", - "order_key", - "hash", - "init", - "metadata", - "type", - "converter", - "kw_only", - "inherited", - "on_setattr", - ) - - def __init__( - self, - name, - default, - validator, - repr, - cmp, # XXX: unused, remove along with other cmp code. - hash, - init, - inherited, - metadata=None, - type=None, - converter=None, - kw_only=False, - eq=None, - eq_key=None, - order=None, - order_key=None, - on_setattr=None, - ): - eq, eq_key, order, order_key = _determine_attrib_eq_order( - cmp, eq_key or eq, order_key or order, True - ) - - # Cache this descriptor here to speed things up later. - bound_setattr = _obj_setattr.__get__(self, Attribute) - - # Despite the big red warning, people *do* instantiate `Attribute` - # themselves. - bound_setattr("name", name) - bound_setattr("default", default) - bound_setattr("validator", validator) - bound_setattr("repr", repr) - bound_setattr("eq", eq) - bound_setattr("eq_key", eq_key) - bound_setattr("order", order) - bound_setattr("order_key", order_key) - bound_setattr("hash", hash) - bound_setattr("init", init) - bound_setattr("converter", converter) - bound_setattr( - "metadata", - ( - metadata_proxy(metadata) - if metadata - else _empty_metadata_singleton - ), - ) - bound_setattr("type", type) - bound_setattr("kw_only", kw_only) - bound_setattr("inherited", inherited) - bound_setattr("on_setattr", on_setattr) - - def __setattr__(self, name, value): - raise FrozenInstanceError() - - @classmethod - def from_counting_attr(cls, name, ca, type=None): - # type holds the annotated value. deal with conflicts: - if type is None: - type = ca.type - elif ca.type is not None: - raise ValueError( - "Type annotation and type argument cannot both be present" - ) - inst_dict = { - k: getattr(ca, k) - for k in Attribute.__slots__ - if k - not in ( - "name", - "validator", - "default", - "type", - "inherited", - ) # exclude methods and deprecated alias - } - return cls( - name=name, - validator=ca._validator, - default=ca._default, - type=type, - cmp=None, - inherited=False, - **inst_dict - ) - - @property - def cmp(self): - """ - Simulate the presence of a cmp attribute and warn. - """ - warnings.warn(_CMP_DEPRECATION, DeprecationWarning, stacklevel=2) - - return self.eq and self.order - - # Don't use attr.evolve since fields(Attribute) doesn't work - def evolve(self, **changes): - """ - Copy *self* and apply *changes*. - - This works similarly to `attr.evolve` but that function does not work - with ``Attribute``. - - It is mainly meant to be used for `transform-fields`. - - .. versionadded:: 20.3.0 - """ - new = copy.copy(self) - - new._setattrs(changes.items()) - - return new - - # Don't use _add_pickle since fields(Attribute) doesn't work - def __getstate__(self): - """ - Play nice with pickle. - """ - return tuple( - getattr(self, name) if name != "metadata" else dict(self.metadata) - for name in self.__slots__ - ) - - def __setstate__(self, state): - """ - Play nice with pickle. - """ - self._setattrs(zip(self.__slots__, state)) - - def _setattrs(self, name_values_pairs): - bound_setattr = _obj_setattr.__get__(self, Attribute) - for name, value in name_values_pairs: - if name != "metadata": - bound_setattr(name, value) - else: - bound_setattr( - name, - metadata_proxy(value) - if value - else _empty_metadata_singleton, - ) - - -_a = [ - Attribute( - name=name, - default=NOTHING, - validator=None, - repr=True, - cmp=None, - eq=True, - order=False, - hash=(name != "metadata"), - init=True, - inherited=False, - ) - for name in Attribute.__slots__ -] - -Attribute = _add_hash( - _add_eq( - _add_repr(Attribute, attrs=_a), - attrs=[a for a in _a if a.name != "inherited"], - ), - attrs=[a for a in _a if a.hash and a.name != "inherited"], -) - - -class _CountingAttr(object): - """ - Intermediate representation of attributes that uses a counter to preserve - the order in which the attributes have been defined. - - *Internal* data structure of the attrs library. Running into is most - likely the result of a bug like a forgotten `@attr.s` decorator. - """ - - __slots__ = ( - "counter", - "_default", - "repr", - "eq", - "eq_key", - "order", - "order_key", - "hash", - "init", - "metadata", - "_validator", - "converter", - "type", - "kw_only", - "on_setattr", - ) - __attrs_attrs__ = tuple( - Attribute( - name=name, - default=NOTHING, - validator=None, - repr=True, - cmp=None, - hash=True, - init=True, - kw_only=False, - eq=True, - eq_key=None, - order=False, - order_key=None, - inherited=False, - on_setattr=None, - ) - for name in ( - "counter", - "_default", - "repr", - "eq", - "order", - "hash", - "init", - "on_setattr", - ) - ) + ( - Attribute( - name="metadata", - default=None, - validator=None, - repr=True, - cmp=None, - hash=False, - init=True, - kw_only=False, - eq=True, - eq_key=None, - order=False, - order_key=None, - inherited=False, - on_setattr=None, - ), - ) - cls_counter = 0 - - def __init__( - self, - default, - validator, - repr, - cmp, - hash, - init, - converter, - metadata, - type, - kw_only, - eq, - eq_key, - order, - order_key, - on_setattr, - ): - _CountingAttr.cls_counter += 1 - self.counter = _CountingAttr.cls_counter - self._default = default - self._validator = validator - self.converter = converter - self.repr = repr - self.eq = eq - self.eq_key = eq_key - self.order = order - self.order_key = order_key - self.hash = hash - self.init = init - self.metadata = metadata - self.type = type - self.kw_only = kw_only - self.on_setattr = on_setattr - - def validator(self, meth): - """ - Decorator that adds *meth* to the list of validators. - - Returns *meth* unchanged. - - .. versionadded:: 17.1.0 - """ - if self._validator is None: - self._validator = meth - else: - self._validator = and_(self._validator, meth) - return meth - - def default(self, meth): - """ - Decorator that allows to set the default for an attribute. - - Returns *meth* unchanged. - - :raises DefaultAlreadySetError: If default has been set before. - - .. versionadded:: 17.1.0 - """ - if self._default is not NOTHING: - raise DefaultAlreadySetError() - - self._default = Factory(meth, takes_self=True) - - return meth - - -_CountingAttr = _add_eq(_add_repr(_CountingAttr)) - - -class Factory(object): - """ - Stores a factory callable. - - If passed as the default value to `attrs.field`, the factory is used to - generate a new value. - - :param callable factory: A callable that takes either none or exactly one - mandatory positional argument depending on *takes_self*. - :param bool takes_self: Pass the partially initialized instance that is - being initialized as a positional argument. - - .. versionadded:: 17.1.0 *takes_self* - """ - - __slots__ = ("factory", "takes_self") - - def __init__(self, factory, takes_self=False): - """ - `Factory` is part of the default machinery so if we want a default - value here, we have to implement it ourselves. - """ - self.factory = factory - self.takes_self = takes_self - - def __getstate__(self): - """ - Play nice with pickle. - """ - return tuple(getattr(self, name) for name in self.__slots__) - - def __setstate__(self, state): - """ - Play nice with pickle. - """ - for name, value in zip(self.__slots__, state): - setattr(self, name, value) - - -_f = [ - Attribute( - name=name, - default=NOTHING, - validator=None, - repr=True, - cmp=None, - eq=True, - order=False, - hash=True, - init=True, - inherited=False, - ) - for name in Factory.__slots__ -] - -Factory = _add_hash(_add_eq(_add_repr(Factory, attrs=_f), attrs=_f), attrs=_f) - - -def make_class(name, attrs, bases=(object,), **attributes_arguments): - """ - A quick way to create a new class called *name* with *attrs*. - - :param str name: The name for the new class. - - :param attrs: A list of names or a dictionary of mappings of names to - attributes. - - If *attrs* is a list or an ordered dict (`dict` on Python 3.6+, - `collections.OrderedDict` otherwise), the order is deduced from - the order of the names or attributes inside *attrs*. Otherwise the - order of the definition of the attributes is used. - :type attrs: `list` or `dict` - - :param tuple bases: Classes that the new class will subclass. - - :param attributes_arguments: Passed unmodified to `attr.s`. - - :return: A new class with *attrs*. - :rtype: type - - .. versionadded:: 17.1.0 *bases* - .. versionchanged:: 18.1.0 If *attrs* is ordered, the order is retained. - """ - if isinstance(attrs, dict): - cls_dict = attrs - elif isinstance(attrs, (list, tuple)): - cls_dict = dict((a, attrib()) for a in attrs) - else: - raise TypeError("attrs argument must be a dict or a list.") - - pre_init = cls_dict.pop("__attrs_pre_init__", None) - post_init = cls_dict.pop("__attrs_post_init__", None) - user_init = cls_dict.pop("__init__", None) - - body = {} - if pre_init is not None: - body["__attrs_pre_init__"] = pre_init - if post_init is not None: - body["__attrs_post_init__"] = post_init - if user_init is not None: - body["__init__"] = user_init - - type_ = new_class(name, bases, {}, lambda ns: ns.update(body)) - - # For pickling to work, the __module__ variable needs to be set to the - # frame where the class is created. Bypass this step in environments where - # sys._getframe is not defined (Jython for example) or sys._getframe is not - # defined for arguments greater than 0 (IronPython). - try: - type_.__module__ = sys._getframe(1).f_globals.get( - "__name__", "__main__" - ) - except (AttributeError, ValueError): - pass - - # We do it here for proper warnings with meaningful stacklevel. - cmp = attributes_arguments.pop("cmp", None) - ( - attributes_arguments["eq"], - attributes_arguments["order"], - ) = _determine_attrs_eq_order( - cmp, - attributes_arguments.get("eq"), - attributes_arguments.get("order"), - True, - ) - - return _attrs(these=cls_dict, **attributes_arguments)(type_) - - -# These are required by within this module so we define them here and merely -# import into .validators / .converters. - - -@attrs(slots=True, hash=True) -class _AndValidator(object): - """ - Compose many validators to a single one. - """ - - _validators = attrib() - - def __call__(self, inst, attr, value): - for v in self._validators: - v(inst, attr, value) - - -def and_(*validators): - """ - A validator that composes multiple validators into one. - - When called on a value, it runs all wrapped validators. - - :param callables validators: Arbitrary number of validators. - - .. versionadded:: 17.1.0 - """ - vals = [] - for validator in validators: - vals.extend( - validator._validators - if isinstance(validator, _AndValidator) - else [validator] - ) - - return _AndValidator(tuple(vals)) - - -def pipe(*converters): - """ - A converter that composes multiple converters into one. - - When called on a value, it runs all wrapped converters, returning the - *last* value. - - Type annotations will be inferred from the wrapped converters', if - they have any. - - :param callables converters: Arbitrary number of converters. - - .. versionadded:: 20.1.0 - """ - - def pipe_converter(val): - for converter in converters: - val = converter(val) - - return val - - if not PY2: - if not converters: - # If the converter list is empty, pipe_converter is the identity. - A = typing.TypeVar("A") - pipe_converter.__annotations__ = {"val": A, "return": A} - else: - # Get parameter type. - sig = None - try: - sig = inspect.signature(converters[0]) - except (ValueError, TypeError): # inspect failed - pass - if sig: - params = list(sig.parameters.values()) - if ( - params - and params[0].annotation is not inspect.Parameter.empty - ): - pipe_converter.__annotations__["val"] = params[ - 0 - ].annotation - # Get return type. - sig = None - try: - sig = inspect.signature(converters[-1]) - except (ValueError, TypeError): # inspect failed - pass - if sig and sig.return_annotation is not inspect.Signature().empty: - pipe_converter.__annotations__[ - "return" - ] = sig.return_annotation - - return pipe_converter diff --git a/client/ayon_core/vendor/python/python_2/attr/_next_gen.py b/client/ayon_core/vendor/python/python_2/attr/_next_gen.py deleted file mode 100644 index 068253688c..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/_next_gen.py +++ /dev/null @@ -1,216 +0,0 @@ -# SPDX-License-Identifier: MIT - -""" -These are Python 3.6+-only and keyword-only APIs that call `attr.s` and -`attr.ib` with different default values. -""" - - -from functools import partial - -from . import setters -from ._funcs import asdict as _asdict -from ._funcs import astuple as _astuple -from ._make import ( - NOTHING, - _frozen_setattrs, - _ng_default_on_setattr, - attrib, - attrs, -) -from .exceptions import UnannotatedAttributeError - - -def define( - maybe_cls=None, - *, - these=None, - repr=None, - hash=None, - init=None, - slots=True, - frozen=False, - weakref_slot=True, - str=False, - auto_attribs=None, - kw_only=False, - cache_hash=False, - auto_exc=True, - eq=None, - order=False, - auto_detect=True, - getstate_setstate=None, - on_setattr=None, - field_transformer=None, - match_args=True, -): - r""" - Define an ``attrs`` class. - - Differences to the classic `attr.s` that it uses underneath: - - - Automatically detect whether or not *auto_attribs* should be `True` - (c.f. *auto_attribs* parameter). - - If *frozen* is `False`, run converters and validators when setting an - attribute by default. - - *slots=True* (see :term:`slotted classes` for potentially surprising - behaviors) - - *auto_exc=True* - - *auto_detect=True* - - *order=False* - - *match_args=True* - - Some options that were only relevant on Python 2 or were kept around for - backwards-compatibility have been removed. - - Please note that these are all defaults and you can change them as you - wish. - - :param Optional[bool] auto_attribs: If set to `True` or `False`, it behaves - exactly like `attr.s`. If left `None`, `attr.s` will try to guess: - - 1. If any attributes are annotated and no unannotated `attrs.fields`\ s - are found, it assumes *auto_attribs=True*. - 2. Otherwise it assumes *auto_attribs=False* and tries to collect - `attrs.fields`\ s. - - For now, please refer to `attr.s` for the rest of the parameters. - - .. versionadded:: 20.1.0 - .. versionchanged:: 21.3.0 Converters are also run ``on_setattr``. - """ - - def do_it(cls, auto_attribs): - return attrs( - maybe_cls=cls, - these=these, - repr=repr, - hash=hash, - init=init, - slots=slots, - frozen=frozen, - weakref_slot=weakref_slot, - str=str, - auto_attribs=auto_attribs, - kw_only=kw_only, - cache_hash=cache_hash, - auto_exc=auto_exc, - eq=eq, - order=order, - auto_detect=auto_detect, - collect_by_mro=True, - getstate_setstate=getstate_setstate, - on_setattr=on_setattr, - field_transformer=field_transformer, - match_args=match_args, - ) - - def wrap(cls): - """ - Making this a wrapper ensures this code runs during class creation. - - We also ensure that frozen-ness of classes is inherited. - """ - nonlocal frozen, on_setattr - - had_on_setattr = on_setattr not in (None, setters.NO_OP) - - # By default, mutable classes convert & validate on setattr. - if frozen is False and on_setattr is None: - on_setattr = _ng_default_on_setattr - - # However, if we subclass a frozen class, we inherit the immutability - # and disable on_setattr. - for base_cls in cls.__bases__: - if base_cls.__setattr__ is _frozen_setattrs: - if had_on_setattr: - raise ValueError( - "Frozen classes can't use on_setattr " - "(frozen-ness was inherited)." - ) - - on_setattr = setters.NO_OP - break - - if auto_attribs is not None: - return do_it(cls, auto_attribs) - - try: - return do_it(cls, True) - except UnannotatedAttributeError: - return do_it(cls, False) - - # maybe_cls's type depends on the usage of the decorator. It's a class - # if it's used as `@attrs` but ``None`` if used as `@attrs()`. - if maybe_cls is None: - return wrap - else: - return wrap(maybe_cls) - - -mutable = define -frozen = partial(define, frozen=True, on_setattr=None) - - -def field( - *, - default=NOTHING, - validator=None, - repr=True, - hash=None, - init=True, - metadata=None, - converter=None, - factory=None, - kw_only=False, - eq=None, - order=None, - on_setattr=None, -): - """ - Identical to `attr.ib`, except keyword-only and with some arguments - removed. - - .. versionadded:: 20.1.0 - """ - return attrib( - default=default, - validator=validator, - repr=repr, - hash=hash, - init=init, - metadata=metadata, - converter=converter, - factory=factory, - kw_only=kw_only, - eq=eq, - order=order, - on_setattr=on_setattr, - ) - - -def asdict(inst, *, recurse=True, filter=None, value_serializer=None): - """ - Same as `attr.asdict`, except that collections types are always retained - and dict is always used as *dict_factory*. - - .. versionadded:: 21.3.0 - """ - return _asdict( - inst=inst, - recurse=recurse, - filter=filter, - value_serializer=value_serializer, - retain_collection_types=True, - ) - - -def astuple(inst, *, recurse=True, filter=None): - """ - Same as `attr.astuple`, except that collections types are always retained - and `tuple` is always used as the *tuple_factory*. - - .. versionadded:: 21.3.0 - """ - return _astuple( - inst=inst, recurse=recurse, filter=filter, retain_collection_types=True - ) diff --git a/client/ayon_core/vendor/python/python_2/attr/_version_info.py b/client/ayon_core/vendor/python/python_2/attr/_version_info.py deleted file mode 100644 index cdaeec37a1..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/_version_info.py +++ /dev/null @@ -1,87 +0,0 @@ -# SPDX-License-Identifier: MIT - -from __future__ import absolute_import, division, print_function - -from functools import total_ordering - -from ._funcs import astuple -from ._make import attrib, attrs - - -@total_ordering -@attrs(eq=False, order=False, slots=True, frozen=True) -class VersionInfo(object): - """ - A version object that can be compared to tuple of length 1--4: - - >>> attr.VersionInfo(19, 1, 0, "final") <= (19, 2) - True - >>> attr.VersionInfo(19, 1, 0, "final") < (19, 1, 1) - True - >>> vi = attr.VersionInfo(19, 2, 0, "final") - >>> vi < (19, 1, 1) - False - >>> vi < (19,) - False - >>> vi == (19, 2,) - True - >>> vi == (19, 2, 1) - False - - .. versionadded:: 19.2 - """ - - year = attrib(type=int) - minor = attrib(type=int) - micro = attrib(type=int) - releaselevel = attrib(type=str) - - @classmethod - def _from_version_string(cls, s): - """ - Parse *s* and return a _VersionInfo. - """ - v = s.split(".") - if len(v) == 3: - v.append("final") - - return cls( - year=int(v[0]), minor=int(v[1]), micro=int(v[2]), releaselevel=v[3] - ) - - def _ensure_tuple(self, other): - """ - Ensure *other* is a tuple of a valid length. - - Returns a possibly transformed *other* and ourselves as a tuple of - the same length as *other*. - """ - - if self.__class__ is other.__class__: - other = astuple(other) - - if not isinstance(other, tuple): - raise NotImplementedError - - if not (1 <= len(other) <= 4): - raise NotImplementedError - - return astuple(self)[: len(other)], other - - def __eq__(self, other): - try: - us, them = self._ensure_tuple(other) - except NotImplementedError: - return NotImplemented - - return us == them - - def __lt__(self, other): - try: - us, them = self._ensure_tuple(other) - except NotImplementedError: - return NotImplemented - - # Since alphabetically "dev0" < "final" < "post1" < "post2", we don't - # have to do anything special with releaselevel for now. - return us < them diff --git a/client/ayon_core/vendor/python/python_2/attr/_version_info.pyi b/client/ayon_core/vendor/python/python_2/attr/_version_info.pyi deleted file mode 100644 index 45ced08633..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/_version_info.pyi +++ /dev/null @@ -1,9 +0,0 @@ -class VersionInfo: - @property - def year(self) -> int: ... - @property - def minor(self) -> int: ... - @property - def micro(self) -> int: ... - @property - def releaselevel(self) -> str: ... diff --git a/client/ayon_core/vendor/python/python_2/attr/converters.py b/client/ayon_core/vendor/python/python_2/attr/converters.py deleted file mode 100644 index 1fb6c05d7b..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/converters.py +++ /dev/null @@ -1,155 +0,0 @@ -# SPDX-License-Identifier: MIT - -""" -Commonly useful converters. -""" - -from __future__ import absolute_import, division, print_function - -from ._compat import PY2 -from ._make import NOTHING, Factory, pipe - - -if not PY2: - import inspect - import typing - - -__all__ = [ - "default_if_none", - "optional", - "pipe", - "to_bool", -] - - -def optional(converter): - """ - A converter that allows an attribute to be optional. An optional attribute - is one which can be set to ``None``. - - Type annotations will be inferred from the wrapped converter's, if it - has any. - - :param callable converter: the converter that is used for non-``None`` - values. - - .. versionadded:: 17.1.0 - """ - - def optional_converter(val): - if val is None: - return None - return converter(val) - - if not PY2: - sig = None - try: - sig = inspect.signature(converter) - except (ValueError, TypeError): # inspect failed - pass - if sig: - params = list(sig.parameters.values()) - if params and params[0].annotation is not inspect.Parameter.empty: - optional_converter.__annotations__["val"] = typing.Optional[ - params[0].annotation - ] - if sig.return_annotation is not inspect.Signature.empty: - optional_converter.__annotations__["return"] = typing.Optional[ - sig.return_annotation - ] - - return optional_converter - - -def default_if_none(default=NOTHING, factory=None): - """ - A converter that allows to replace ``None`` values by *default* or the - result of *factory*. - - :param default: Value to be used if ``None`` is passed. Passing an instance - of `attrs.Factory` is supported, however the ``takes_self`` option - is *not*. - :param callable factory: A callable that takes no parameters whose result - is used if ``None`` is passed. - - :raises TypeError: If **neither** *default* or *factory* is passed. - :raises TypeError: If **both** *default* and *factory* are passed. - :raises ValueError: If an instance of `attrs.Factory` is passed with - ``takes_self=True``. - - .. versionadded:: 18.2.0 - """ - if default is NOTHING and factory is None: - raise TypeError("Must pass either `default` or `factory`.") - - if default is not NOTHING and factory is not None: - raise TypeError( - "Must pass either `default` or `factory` but not both." - ) - - if factory is not None: - default = Factory(factory) - - if isinstance(default, Factory): - if default.takes_self: - raise ValueError( - "`takes_self` is not supported by default_if_none." - ) - - def default_if_none_converter(val): - if val is not None: - return val - - return default.factory() - - else: - - def default_if_none_converter(val): - if val is not None: - return val - - return default - - return default_if_none_converter - - -def to_bool(val): - """ - Convert "boolean" strings (e.g., from env. vars.) to real booleans. - - Values mapping to :code:`True`: - - - :code:`True` - - :code:`"true"` / :code:`"t"` - - :code:`"yes"` / :code:`"y"` - - :code:`"on"` - - :code:`"1"` - - :code:`1` - - Values mapping to :code:`False`: - - - :code:`False` - - :code:`"false"` / :code:`"f"` - - :code:`"no"` / :code:`"n"` - - :code:`"off"` - - :code:`"0"` - - :code:`0` - - :raises ValueError: for any other value. - - .. versionadded:: 21.3.0 - """ - if isinstance(val, str): - val = val.lower() - truthy = {True, "true", "t", "yes", "y", "on", "1", 1} - falsy = {False, "false", "f", "no", "n", "off", "0", 0} - try: - if val in truthy: - return True - if val in falsy: - return False - except TypeError: - # Raised when "val" is not hashable (e.g., lists) - pass - raise ValueError("Cannot convert value to bool: {}".format(val)) diff --git a/client/ayon_core/vendor/python/python_2/attr/converters.pyi b/client/ayon_core/vendor/python/python_2/attr/converters.pyi deleted file mode 100644 index 0f58088a37..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/converters.pyi +++ /dev/null @@ -1,13 +0,0 @@ -from typing import Callable, Optional, TypeVar, overload - -from . import _ConverterType - -_T = TypeVar("_T") - -def pipe(*validators: _ConverterType) -> _ConverterType: ... -def optional(converter: _ConverterType) -> _ConverterType: ... -@overload -def default_if_none(default: _T) -> _ConverterType: ... -@overload -def default_if_none(*, factory: Callable[[], _T]) -> _ConverterType: ... -def to_bool(val: str) -> bool: ... diff --git a/client/ayon_core/vendor/python/python_2/attr/exceptions.py b/client/ayon_core/vendor/python/python_2/attr/exceptions.py deleted file mode 100644 index b2f1edc32a..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/exceptions.py +++ /dev/null @@ -1,94 +0,0 @@ -# SPDX-License-Identifier: MIT - -from __future__ import absolute_import, division, print_function - - -class FrozenError(AttributeError): - """ - A frozen/immutable instance or attribute have been attempted to be - modified. - - It mirrors the behavior of ``namedtuples`` by using the same error message - and subclassing `AttributeError`. - - .. versionadded:: 20.1.0 - """ - - msg = "can't set attribute" - args = [msg] - - -class FrozenInstanceError(FrozenError): - """ - A frozen instance has been attempted to be modified. - - .. versionadded:: 16.1.0 - """ - - -class FrozenAttributeError(FrozenError): - """ - A frozen attribute has been attempted to be modified. - - .. versionadded:: 20.1.0 - """ - - -class AttrsAttributeNotFoundError(ValueError): - """ - An ``attrs`` function couldn't find an attribute that the user asked for. - - .. versionadded:: 16.2.0 - """ - - -class NotAnAttrsClassError(ValueError): - """ - A non-``attrs`` class has been passed into an ``attrs`` function. - - .. versionadded:: 16.2.0 - """ - - -class DefaultAlreadySetError(RuntimeError): - """ - A default has been set using ``attr.ib()`` and is attempted to be reset - using the decorator. - - .. versionadded:: 17.1.0 - """ - - -class UnannotatedAttributeError(RuntimeError): - """ - A class with ``auto_attribs=True`` has an ``attr.ib()`` without a type - annotation. - - .. versionadded:: 17.3.0 - """ - - -class PythonTooOldError(RuntimeError): - """ - It was attempted to use an ``attrs`` feature that requires a newer Python - version. - - .. versionadded:: 18.2.0 - """ - - -class NotCallableError(TypeError): - """ - A ``attr.ib()`` requiring a callable has been set with a value - that is not callable. - - .. versionadded:: 19.2.0 - """ - - def __init__(self, msg, value): - super(TypeError, self).__init__(msg, value) - self.msg = msg - self.value = value - - def __str__(self): - return str(self.msg) diff --git a/client/ayon_core/vendor/python/python_2/attr/exceptions.pyi b/client/ayon_core/vendor/python/python_2/attr/exceptions.pyi deleted file mode 100644 index f2680118b4..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/exceptions.pyi +++ /dev/null @@ -1,17 +0,0 @@ -from typing import Any - -class FrozenError(AttributeError): - msg: str = ... - -class FrozenInstanceError(FrozenError): ... -class FrozenAttributeError(FrozenError): ... -class AttrsAttributeNotFoundError(ValueError): ... -class NotAnAttrsClassError(ValueError): ... -class DefaultAlreadySetError(RuntimeError): ... -class UnannotatedAttributeError(RuntimeError): ... -class PythonTooOldError(RuntimeError): ... - -class NotCallableError(TypeError): - msg: str = ... - value: Any = ... - def __init__(self, msg: str, value: Any) -> None: ... diff --git a/client/ayon_core/vendor/python/python_2/attr/filters.py b/client/ayon_core/vendor/python/python_2/attr/filters.py deleted file mode 100644 index a1978a8775..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/filters.py +++ /dev/null @@ -1,54 +0,0 @@ -# SPDX-License-Identifier: MIT - -""" -Commonly useful filters for `attr.asdict`. -""" - -from __future__ import absolute_import, division, print_function - -from ._compat import isclass -from ._make import Attribute - - -def _split_what(what): - """ - Returns a tuple of `frozenset`s of classes and attributes. - """ - return ( - frozenset(cls for cls in what if isclass(cls)), - frozenset(cls for cls in what if isinstance(cls, Attribute)), - ) - - -def include(*what): - """ - Include *what*. - - :param what: What to include. - :type what: `list` of `type` or `attrs.Attribute`\\ s - - :rtype: `callable` - """ - cls, attrs = _split_what(what) - - def include_(attribute, value): - return value.__class__ in cls or attribute in attrs - - return include_ - - -def exclude(*what): - """ - Exclude *what*. - - :param what: What to exclude. - :type what: `list` of classes or `attrs.Attribute`\\ s. - - :rtype: `callable` - """ - cls, attrs = _split_what(what) - - def exclude_(attribute, value): - return value.__class__ not in cls and attribute not in attrs - - return exclude_ diff --git a/client/ayon_core/vendor/python/python_2/attr/filters.pyi b/client/ayon_core/vendor/python/python_2/attr/filters.pyi deleted file mode 100644 index 993866865e..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/filters.pyi +++ /dev/null @@ -1,6 +0,0 @@ -from typing import Any, Union - -from . import Attribute, _FilterType - -def include(*what: Union[type, Attribute[Any]]) -> _FilterType[Any]: ... -def exclude(*what: Union[type, Attribute[Any]]) -> _FilterType[Any]: ... diff --git a/client/ayon_core/vendor/python/python_2/attr/py.typed b/client/ayon_core/vendor/python/python_2/attr/py.typed deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/client/ayon_core/vendor/python/python_2/attr/setters.py b/client/ayon_core/vendor/python/python_2/attr/setters.py deleted file mode 100644 index b1cbb5d83e..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/setters.py +++ /dev/null @@ -1,79 +0,0 @@ -# SPDX-License-Identifier: MIT - -""" -Commonly used hooks for on_setattr. -""" - -from __future__ import absolute_import, division, print_function - -from . import _config -from .exceptions import FrozenAttributeError - - -def pipe(*setters): - """ - Run all *setters* and return the return value of the last one. - - .. versionadded:: 20.1.0 - """ - - def wrapped_pipe(instance, attrib, new_value): - rv = new_value - - for setter in setters: - rv = setter(instance, attrib, rv) - - return rv - - return wrapped_pipe - - -def frozen(_, __, ___): - """ - Prevent an attribute to be modified. - - .. versionadded:: 20.1.0 - """ - raise FrozenAttributeError() - - -def validate(instance, attrib, new_value): - """ - Run *attrib*'s validator on *new_value* if it has one. - - .. versionadded:: 20.1.0 - """ - if _config._run_validators is False: - return new_value - - v = attrib.validator - if not v: - return new_value - - v(instance, attrib, new_value) - - return new_value - - -def convert(instance, attrib, new_value): - """ - Run *attrib*'s converter -- if it has one -- on *new_value* and return the - result. - - .. versionadded:: 20.1.0 - """ - c = attrib.converter - if c: - return c(new_value) - - return new_value - - -NO_OP = object() -""" -Sentinel for disabling class-wide *on_setattr* hooks for certain attributes. - -Does not work in `pipe` or within lists. - -.. versionadded:: 20.1.0 -""" diff --git a/client/ayon_core/vendor/python/python_2/attr/setters.pyi b/client/ayon_core/vendor/python/python_2/attr/setters.pyi deleted file mode 100644 index 3f5603c2b0..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/setters.pyi +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Any, NewType, NoReturn, TypeVar, cast - -from . import Attribute, _OnSetAttrType - -_T = TypeVar("_T") - -def frozen( - instance: Any, attribute: Attribute[Any], new_value: Any -) -> NoReturn: ... -def pipe(*setters: _OnSetAttrType) -> _OnSetAttrType: ... -def validate(instance: Any, attribute: Attribute[_T], new_value: _T) -> _T: ... - -# convert is allowed to return Any, because they can be chained using pipe. -def convert( - instance: Any, attribute: Attribute[Any], new_value: Any -) -> Any: ... - -_NoOpType = NewType("_NoOpType", object) -NO_OP: _NoOpType diff --git a/client/ayon_core/vendor/python/python_2/attr/validators.py b/client/ayon_core/vendor/python/python_2/attr/validators.py deleted file mode 100644 index 0b0c8342f2..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/validators.py +++ /dev/null @@ -1,561 +0,0 @@ -# SPDX-License-Identifier: MIT - -""" -Commonly useful validators. -""" - -from __future__ import absolute_import, division, print_function - -import operator -import re - -from contextlib import contextmanager - -from ._config import get_run_validators, set_run_validators -from ._make import _AndValidator, and_, attrib, attrs -from .exceptions import NotCallableError - - -try: - Pattern = re.Pattern -except AttributeError: # Python <3.7 lacks a Pattern type. - Pattern = type(re.compile("")) - - -__all__ = [ - "and_", - "deep_iterable", - "deep_mapping", - "disabled", - "ge", - "get_disabled", - "gt", - "in_", - "instance_of", - "is_callable", - "le", - "lt", - "matches_re", - "max_len", - "optional", - "provides", - "set_disabled", -] - - -def set_disabled(disabled): - """ - Globally disable or enable running validators. - - By default, they are run. - - :param disabled: If ``True``, disable running all validators. - :type disabled: bool - - .. warning:: - - This function is not thread-safe! - - .. versionadded:: 21.3.0 - """ - set_run_validators(not disabled) - - -def get_disabled(): - """ - Return a bool indicating whether validators are currently disabled or not. - - :return: ``True`` if validators are currently disabled. - :rtype: bool - - .. versionadded:: 21.3.0 - """ - return not get_run_validators() - - -@contextmanager -def disabled(): - """ - Context manager that disables running validators within its context. - - .. warning:: - - This context manager is not thread-safe! - - .. versionadded:: 21.3.0 - """ - set_run_validators(False) - try: - yield - finally: - set_run_validators(True) - - -@attrs(repr=False, slots=True, hash=True) -class _InstanceOfValidator(object): - type = attrib() - - def __call__(self, inst, attr, value): - """ - We use a callable class to be able to change the ``__repr__``. - """ - if not isinstance(value, self.type): - raise TypeError( - "'{name}' must be {type!r} (got {value!r} that is a " - "{actual!r}).".format( - name=attr.name, - type=self.type, - actual=value.__class__, - value=value, - ), - attr, - self.type, - value, - ) - - def __repr__(self): - return "".format( - type=self.type - ) - - -def instance_of(type): - """ - A validator that raises a `TypeError` if the initializer is called - with a wrong type for this particular attribute (checks are performed using - `isinstance` therefore it's also valid to pass a tuple of types). - - :param type: The type to check for. - :type type: type or tuple of types - - :raises TypeError: With a human readable error message, the attribute - (of type `attrs.Attribute`), the expected type, and the value it - got. - """ - return _InstanceOfValidator(type) - - -@attrs(repr=False, frozen=True, slots=True) -class _MatchesReValidator(object): - pattern = attrib() - match_func = attrib() - - def __call__(self, inst, attr, value): - """ - We use a callable class to be able to change the ``__repr__``. - """ - if not self.match_func(value): - raise ValueError( - "'{name}' must match regex {pattern!r}" - " ({value!r} doesn't)".format( - name=attr.name, pattern=self.pattern.pattern, value=value - ), - attr, - self.pattern, - value, - ) - - def __repr__(self): - return "".format( - pattern=self.pattern - ) - - -def matches_re(regex, flags=0, func=None): - r""" - A validator that raises `ValueError` if the initializer is called - with a string that doesn't match *regex*. - - :param regex: a regex string or precompiled pattern to match against - :param int flags: flags that will be passed to the underlying re function - (default 0) - :param callable func: which underlying `re` function to call (options - are `re.fullmatch`, `re.search`, `re.match`, default - is ``None`` which means either `re.fullmatch` or an emulation of - it on Python 2). For performance reasons, they won't be used directly - but on a pre-`re.compile`\ ed pattern. - - .. versionadded:: 19.2.0 - .. versionchanged:: 21.3.0 *regex* can be a pre-compiled pattern. - """ - fullmatch = getattr(re, "fullmatch", None) - valid_funcs = (fullmatch, None, re.search, re.match) - if func not in valid_funcs: - raise ValueError( - "'func' must be one of {}.".format( - ", ".join( - sorted( - e and e.__name__ or "None" for e in set(valid_funcs) - ) - ) - ) - ) - - if isinstance(regex, Pattern): - if flags: - raise TypeError( - "'flags' can only be used with a string pattern; " - "pass flags to re.compile() instead" - ) - pattern = regex - else: - pattern = re.compile(regex, flags) - - if func is re.match: - match_func = pattern.match - elif func is re.search: - match_func = pattern.search - elif fullmatch: - match_func = pattern.fullmatch - else: # Python 2 fullmatch emulation (https://bugs.python.org/issue16203) - pattern = re.compile( - r"(?:{})\Z".format(pattern.pattern), pattern.flags - ) - match_func = pattern.match - - return _MatchesReValidator(pattern, match_func) - - -@attrs(repr=False, slots=True, hash=True) -class _ProvidesValidator(object): - interface = attrib() - - def __call__(self, inst, attr, value): - """ - We use a callable class to be able to change the ``__repr__``. - """ - if not self.interface.providedBy(value): - raise TypeError( - "'{name}' must provide {interface!r} which {value!r} " - "doesn't.".format( - name=attr.name, interface=self.interface, value=value - ), - attr, - self.interface, - value, - ) - - def __repr__(self): - return "".format( - interface=self.interface - ) - - -def provides(interface): - """ - A validator that raises a `TypeError` if the initializer is called - with an object that does not provide the requested *interface* (checks are - performed using ``interface.providedBy(value)`` (see `zope.interface - `_). - - :param interface: The interface to check for. - :type interface: ``zope.interface.Interface`` - - :raises TypeError: With a human readable error message, the attribute - (of type `attrs.Attribute`), the expected interface, and the - value it got. - """ - return _ProvidesValidator(interface) - - -@attrs(repr=False, slots=True, hash=True) -class _OptionalValidator(object): - validator = attrib() - - def __call__(self, inst, attr, value): - if value is None: - return - - self.validator(inst, attr, value) - - def __repr__(self): - return "".format( - what=repr(self.validator) - ) - - -def optional(validator): - """ - A validator that makes an attribute optional. An optional attribute is one - which can be set to ``None`` in addition to satisfying the requirements of - the sub-validator. - - :param validator: A validator (or a list of validators) that is used for - non-``None`` values. - :type validator: callable or `list` of callables. - - .. versionadded:: 15.1.0 - .. versionchanged:: 17.1.0 *validator* can be a list of validators. - """ - if isinstance(validator, list): - return _OptionalValidator(_AndValidator(validator)) - return _OptionalValidator(validator) - - -@attrs(repr=False, slots=True, hash=True) -class _InValidator(object): - options = attrib() - - def __call__(self, inst, attr, value): - try: - in_options = value in self.options - except TypeError: # e.g. `1 in "abc"` - in_options = False - - if not in_options: - raise ValueError( - "'{name}' must be in {options!r} (got {value!r})".format( - name=attr.name, options=self.options, value=value - ) - ) - - def __repr__(self): - return "".format( - options=self.options - ) - - -def in_(options): - """ - A validator that raises a `ValueError` if the initializer is called - with a value that does not belong in the options provided. The check is - performed using ``value in options``. - - :param options: Allowed options. - :type options: list, tuple, `enum.Enum`, ... - - :raises ValueError: With a human readable error message, the attribute (of - type `attrs.Attribute`), the expected options, and the value it - got. - - .. versionadded:: 17.1.0 - """ - return _InValidator(options) - - -@attrs(repr=False, slots=False, hash=True) -class _IsCallableValidator(object): - def __call__(self, inst, attr, value): - """ - We use a callable class to be able to change the ``__repr__``. - """ - if not callable(value): - message = ( - "'{name}' must be callable " - "(got {value!r} that is a {actual!r})." - ) - raise NotCallableError( - msg=message.format( - name=attr.name, value=value, actual=value.__class__ - ), - value=value, - ) - - def __repr__(self): - return "" - - -def is_callable(): - """ - A validator that raises a `attr.exceptions.NotCallableError` if the - initializer is called with a value for this particular attribute - that is not callable. - - .. versionadded:: 19.1.0 - - :raises `attr.exceptions.NotCallableError`: With a human readable error - message containing the attribute (`attrs.Attribute`) name, - and the value it got. - """ - return _IsCallableValidator() - - -@attrs(repr=False, slots=True, hash=True) -class _DeepIterable(object): - member_validator = attrib(validator=is_callable()) - iterable_validator = attrib( - default=None, validator=optional(is_callable()) - ) - - def __call__(self, inst, attr, value): - """ - We use a callable class to be able to change the ``__repr__``. - """ - if self.iterable_validator is not None: - self.iterable_validator(inst, attr, value) - - for member in value: - self.member_validator(inst, attr, member) - - def __repr__(self): - iterable_identifier = ( - "" - if self.iterable_validator is None - else " {iterable!r}".format(iterable=self.iterable_validator) - ) - return ( - "" - ).format( - iterable_identifier=iterable_identifier, - member=self.member_validator, - ) - - -def deep_iterable(member_validator, iterable_validator=None): - """ - A validator that performs deep validation of an iterable. - - :param member_validator: Validator to apply to iterable members - :param iterable_validator: Validator to apply to iterable itself - (optional) - - .. versionadded:: 19.1.0 - - :raises TypeError: if any sub-validators fail - """ - return _DeepIterable(member_validator, iterable_validator) - - -@attrs(repr=False, slots=True, hash=True) -class _DeepMapping(object): - key_validator = attrib(validator=is_callable()) - value_validator = attrib(validator=is_callable()) - mapping_validator = attrib(default=None, validator=optional(is_callable())) - - def __call__(self, inst, attr, value): - """ - We use a callable class to be able to change the ``__repr__``. - """ - if self.mapping_validator is not None: - self.mapping_validator(inst, attr, value) - - for key in value: - self.key_validator(inst, attr, key) - self.value_validator(inst, attr, value[key]) - - def __repr__(self): - return ( - "" - ).format(key=self.key_validator, value=self.value_validator) - - -def deep_mapping(key_validator, value_validator, mapping_validator=None): - """ - A validator that performs deep validation of a dictionary. - - :param key_validator: Validator to apply to dictionary keys - :param value_validator: Validator to apply to dictionary values - :param mapping_validator: Validator to apply to top-level mapping - attribute (optional) - - .. versionadded:: 19.1.0 - - :raises TypeError: if any sub-validators fail - """ - return _DeepMapping(key_validator, value_validator, mapping_validator) - - -@attrs(repr=False, frozen=True, slots=True) -class _NumberValidator(object): - bound = attrib() - compare_op = attrib() - compare_func = attrib() - - def __call__(self, inst, attr, value): - """ - We use a callable class to be able to change the ``__repr__``. - """ - if not self.compare_func(value, self.bound): - raise ValueError( - "'{name}' must be {op} {bound}: {value}".format( - name=attr.name, - op=self.compare_op, - bound=self.bound, - value=value, - ) - ) - - def __repr__(self): - return "".format( - op=self.compare_op, bound=self.bound - ) - - -def lt(val): - """ - A validator that raises `ValueError` if the initializer is called - with a number larger or equal to *val*. - - :param val: Exclusive upper bound for values - - .. versionadded:: 21.3.0 - """ - return _NumberValidator(val, "<", operator.lt) - - -def le(val): - """ - A validator that raises `ValueError` if the initializer is called - with a number greater than *val*. - - :param val: Inclusive upper bound for values - - .. versionadded:: 21.3.0 - """ - return _NumberValidator(val, "<=", operator.le) - - -def ge(val): - """ - A validator that raises `ValueError` if the initializer is called - with a number smaller than *val*. - - :param val: Inclusive lower bound for values - - .. versionadded:: 21.3.0 - """ - return _NumberValidator(val, ">=", operator.ge) - - -def gt(val): - """ - A validator that raises `ValueError` if the initializer is called - with a number smaller or equal to *val*. - - :param val: Exclusive lower bound for values - - .. versionadded:: 21.3.0 - """ - return _NumberValidator(val, ">", operator.gt) - - -@attrs(repr=False, frozen=True, slots=True) -class _MaxLengthValidator(object): - max_length = attrib() - - def __call__(self, inst, attr, value): - """ - We use a callable class to be able to change the ``__repr__``. - """ - if len(value) > self.max_length: - raise ValueError( - "Length of '{name}' must be <= {max}: {len}".format( - name=attr.name, max=self.max_length, len=len(value) - ) - ) - - def __repr__(self): - return "".format(max=self.max_length) - - -def max_len(length): - """ - A validator that raises `ValueError` if the initializer is called - with a string or iterable that is longer than *length*. - - :param int length: Maximum length of the string or iterable - - .. versionadded:: 21.3.0 - """ - return _MaxLengthValidator(length) diff --git a/client/ayon_core/vendor/python/python_2/attr/validators.pyi b/client/ayon_core/vendor/python/python_2/attr/validators.pyi deleted file mode 100644 index 5e00b85433..0000000000 --- a/client/ayon_core/vendor/python/python_2/attr/validators.pyi +++ /dev/null @@ -1,78 +0,0 @@ -from typing import ( - Any, - AnyStr, - Callable, - Container, - ContextManager, - Iterable, - List, - Mapping, - Match, - Optional, - Pattern, - Tuple, - Type, - TypeVar, - Union, - overload, -) - -from . import _ValidatorType - -_T = TypeVar("_T") -_T1 = TypeVar("_T1") -_T2 = TypeVar("_T2") -_T3 = TypeVar("_T3") -_I = TypeVar("_I", bound=Iterable) -_K = TypeVar("_K") -_V = TypeVar("_V") -_M = TypeVar("_M", bound=Mapping) - -def set_disabled(run: bool) -> None: ... -def get_disabled() -> bool: ... -def disabled() -> ContextManager[None]: ... - -# To be more precise on instance_of use some overloads. -# If there are more than 3 items in the tuple then we fall back to Any -@overload -def instance_of(type: Type[_T]) -> _ValidatorType[_T]: ... -@overload -def instance_of(type: Tuple[Type[_T]]) -> _ValidatorType[_T]: ... -@overload -def instance_of( - type: Tuple[Type[_T1], Type[_T2]] -) -> _ValidatorType[Union[_T1, _T2]]: ... -@overload -def instance_of( - type: Tuple[Type[_T1], Type[_T2], Type[_T3]] -) -> _ValidatorType[Union[_T1, _T2, _T3]]: ... -@overload -def instance_of(type: Tuple[type, ...]) -> _ValidatorType[Any]: ... -def provides(interface: Any) -> _ValidatorType[Any]: ... -def optional( - validator: Union[_ValidatorType[_T], List[_ValidatorType[_T]]] -) -> _ValidatorType[Optional[_T]]: ... -def in_(options: Container[_T]) -> _ValidatorType[_T]: ... -def and_(*validators: _ValidatorType[_T]) -> _ValidatorType[_T]: ... -def matches_re( - regex: Union[Pattern[AnyStr], AnyStr], - flags: int = ..., - func: Optional[ - Callable[[AnyStr, AnyStr, int], Optional[Match[AnyStr]]] - ] = ..., -) -> _ValidatorType[AnyStr]: ... -def deep_iterable( - member_validator: _ValidatorType[_T], - iterable_validator: Optional[_ValidatorType[_I]] = ..., -) -> _ValidatorType[_I]: ... -def deep_mapping( - key_validator: _ValidatorType[_K], - value_validator: _ValidatorType[_V], - mapping_validator: Optional[_ValidatorType[_M]] = ..., -) -> _ValidatorType[_M]: ... -def is_callable() -> _ValidatorType[_T]: ... -def lt(val: _T) -> _ValidatorType[_T]: ... -def le(val: _T) -> _ValidatorType[_T]: ... -def ge(val: _T) -> _ValidatorType[_T]: ... -def gt(val: _T) -> _ValidatorType[_T]: ... -def max_len(length: int) -> _ValidatorType[_T]: ... diff --git a/client/ayon_core/vendor/python/python_2/attrs/__init__.py b/client/ayon_core/vendor/python/python_2/attrs/__init__.py deleted file mode 100644 index a704b8b56b..0000000000 --- a/client/ayon_core/vendor/python/python_2/attrs/__init__.py +++ /dev/null @@ -1,70 +0,0 @@ -# SPDX-License-Identifier: MIT - -from attr import ( - NOTHING, - Attribute, - Factory, - __author__, - __copyright__, - __description__, - __doc__, - __email__, - __license__, - __title__, - __url__, - __version__, - __version_info__, - assoc, - cmp_using, - define, - evolve, - field, - fields, - fields_dict, - frozen, - has, - make_class, - mutable, - resolve_types, - validate, -) -from attr._next_gen import asdict, astuple - -from . import converters, exceptions, filters, setters, validators - - -__all__ = [ - "__author__", - "__copyright__", - "__description__", - "__doc__", - "__email__", - "__license__", - "__title__", - "__url__", - "__version__", - "__version_info__", - "asdict", - "assoc", - "astuple", - "Attribute", - "cmp_using", - "converters", - "define", - "evolve", - "exceptions", - "Factory", - "field", - "fields_dict", - "fields", - "filters", - "frozen", - "has", - "make_class", - "mutable", - "NOTHING", - "resolve_types", - "setters", - "validate", - "validators", -] diff --git a/client/ayon_core/vendor/python/python_2/attrs/__init__.pyi b/client/ayon_core/vendor/python/python_2/attrs/__init__.pyi deleted file mode 100644 index 7426fa5ddb..0000000000 --- a/client/ayon_core/vendor/python/python_2/attrs/__init__.pyi +++ /dev/null @@ -1,63 +0,0 @@ -from typing import ( - Any, - Callable, - Dict, - Mapping, - Optional, - Sequence, - Tuple, - Type, -) - -# Because we need to type our own stuff, we have to make everything from -# attr explicitly public too. -from attr import __author__ as __author__ -from attr import __copyright__ as __copyright__ -from attr import __description__ as __description__ -from attr import __email__ as __email__ -from attr import __license__ as __license__ -from attr import __title__ as __title__ -from attr import __url__ as __url__ -from attr import __version__ as __version__ -from attr import __version_info__ as __version_info__ -from attr import _FilterType -from attr import assoc as assoc -from attr import Attribute as Attribute -from attr import define as define -from attr import evolve as evolve -from attr import Factory as Factory -from attr import exceptions as exceptions -from attr import field as field -from attr import fields as fields -from attr import fields_dict as fields_dict -from attr import frozen as frozen -from attr import has as has -from attr import make_class as make_class -from attr import mutable as mutable -from attr import NOTHING as NOTHING -from attr import resolve_types as resolve_types -from attr import setters as setters -from attr import validate as validate -from attr import validators as validators - -# TODO: see definition of attr.asdict/astuple -def asdict( - inst: Any, - recurse: bool = ..., - filter: Optional[_FilterType[Any]] = ..., - dict_factory: Type[Mapping[Any, Any]] = ..., - retain_collection_types: bool = ..., - value_serializer: Optional[ - Callable[[type, Attribute[Any], Any], Any] - ] = ..., - tuple_keys: bool = ..., -) -> Dict[str, Any]: ... - -# TODO: add support for returning NamedTuple from the mypy plugin -def astuple( - inst: Any, - recurse: bool = ..., - filter: Optional[_FilterType[Any]] = ..., - tuple_factory: Type[Sequence[Any]] = ..., - retain_collection_types: bool = ..., -) -> Tuple[Any, ...]: ... diff --git a/client/ayon_core/vendor/python/python_2/attrs/converters.py b/client/ayon_core/vendor/python/python_2/attrs/converters.py deleted file mode 100644 index edfa8d3c16..0000000000 --- a/client/ayon_core/vendor/python/python_2/attrs/converters.py +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: MIT - -from attr.converters import * # noqa diff --git a/client/ayon_core/vendor/python/python_2/attrs/exceptions.py b/client/ayon_core/vendor/python/python_2/attrs/exceptions.py deleted file mode 100644 index bd9efed202..0000000000 --- a/client/ayon_core/vendor/python/python_2/attrs/exceptions.py +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: MIT - -from attr.exceptions import * # noqa diff --git a/client/ayon_core/vendor/python/python_2/attrs/filters.py b/client/ayon_core/vendor/python/python_2/attrs/filters.py deleted file mode 100644 index 52959005b0..0000000000 --- a/client/ayon_core/vendor/python/python_2/attrs/filters.py +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: MIT - -from attr.filters import * # noqa diff --git a/client/ayon_core/vendor/python/python_2/attrs/py.typed b/client/ayon_core/vendor/python/python_2/attrs/py.typed deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/client/ayon_core/vendor/python/python_2/attrs/setters.py b/client/ayon_core/vendor/python/python_2/attrs/setters.py deleted file mode 100644 index 9b50770804..0000000000 --- a/client/ayon_core/vendor/python/python_2/attrs/setters.py +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: MIT - -from attr.setters import * # noqa diff --git a/client/ayon_core/vendor/python/python_2/attrs/validators.py b/client/ayon_core/vendor/python/python_2/attrs/validators.py deleted file mode 100644 index ab2c9b3024..0000000000 --- a/client/ayon_core/vendor/python/python_2/attrs/validators.py +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: MIT - -from attr.validators import * # noqa diff --git a/client/ayon_core/vendor/python/python_2/backports/__init__.py b/client/ayon_core/vendor/python/python_2/backports/__init__.py deleted file mode 100644 index 69e3be50da..0000000000 --- a/client/ayon_core/vendor/python/python_2/backports/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__path__ = __import__('pkgutil').extend_path(__path__, __name__) diff --git a/client/ayon_core/vendor/python/python_2/backports/configparser/__init__.py b/client/ayon_core/vendor/python/python_2/backports/configparser/__init__.py deleted file mode 100644 index 06d7a0855f..0000000000 --- a/client/ayon_core/vendor/python/python_2/backports/configparser/__init__.py +++ /dev/null @@ -1,1390 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -"""Configuration file parser. - -A configuration file consists of sections, lead by a "[section]" header, -and followed by "name: value" entries, with continuations and such in -the style of RFC 822. - -Intrinsic defaults can be specified by passing them into the -ConfigParser constructor as a dictionary. - -class: - -ConfigParser -- responsible for parsing a list of - configuration files, and managing the parsed database. - - methods: - - __init__(defaults=None, dict_type=_default_dict, allow_no_value=False, - delimiters=('=', ':'), comment_prefixes=('#', ';'), - inline_comment_prefixes=None, strict=True, - empty_lines_in_values=True, default_section='DEFAULT', - interpolation=, converters=): - Create the parser. When `defaults' is given, it is initialized into the - dictionary or intrinsic defaults. The keys must be strings, the values - must be appropriate for %()s string interpolation. - - When `dict_type' is given, it will be used to create the dictionary - objects for the list of sections, for the options within a section, and - for the default values. - - When `delimiters' is given, it will be used as the set of substrings - that divide keys from values. - - When `comment_prefixes' is given, it will be used as the set of - substrings that prefix comments in empty lines. Comments can be - indented. - - When `inline_comment_prefixes' is given, it will be used as the set of - substrings that prefix comments in non-empty lines. - - When `strict` is True, the parser won't allow for any section or option - duplicates while reading from a single source (file, string or - dictionary). Default is True. - - When `empty_lines_in_values' is False (default: True), each empty line - marks the end of an option. Otherwise, internal empty lines of - a multiline option are kept as part of the value. - - When `allow_no_value' is True (default: False), options without - values are accepted; the value presented for these is None. - - sections() - Return all the configuration section names, sans DEFAULT. - - has_section(section) - Return whether the given section exists. - - has_option(section, option) - Return whether the given option exists in the given section. - - options(section) - Return list of configuration options for the named section. - - read(filenames, encoding=None) - Read and parse the list of named configuration files, given by - name. A single filename is also allowed. Non-existing files - are ignored. Return list of successfully read files. - - read_file(f, filename=None) - Read and parse one configuration file, given as a file object. - The filename defaults to f.name; it is only used in error - messages (if f has no `name' attribute, the string `' is used). - - read_string(string) - Read configuration from a given string. - - read_dict(dictionary) - Read configuration from a dictionary. Keys are section names, - values are dictionaries with keys and values that should be present - in the section. If the used dictionary type preserves order, sections - and their keys will be added in order. Values are automatically - converted to strings. - - get(section, option, raw=False, vars=None, fallback=_UNSET) - Return a string value for the named option. All % interpolations are - expanded in the return values, based on the defaults passed into the - constructor and the DEFAULT section. Additional substitutions may be - provided using the `vars' argument, which must be a dictionary whose - contents override any pre-existing defaults. If `option' is a key in - `vars', the value from `vars' is used. - - getint(section, options, raw=False, vars=None, fallback=_UNSET) - Like get(), but convert value to an integer. - - getfloat(section, options, raw=False, vars=None, fallback=_UNSET) - Like get(), but convert value to a float. - - getboolean(section, options, raw=False, vars=None, fallback=_UNSET) - Like get(), but convert value to a boolean (currently case - insensitively defined as 0, false, no, off for False, and 1, true, - yes, on for True). Returns False or True. - - items(section=_UNSET, raw=False, vars=None) - If section is given, return a list of tuples with (name, value) for - each option in the section. Otherwise, return a list of tuples with - (section_name, section_proxy) for each section, including DEFAULTSECT. - - remove_section(section) - Remove the given file section and all its options. - - remove_option(section, option) - Remove the given option from the given section. - - set(section, option, value) - Set the given option. - - write(fp, space_around_delimiters=True) - Write the configuration state in .ini format. If - `space_around_delimiters' is True (the default), delimiters - between keys and values are surrounded by spaces. -""" - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals - -from collections import MutableMapping -import functools -import io -import itertools -import re -import sys -import warnings - -from backports.configparser.helpers import OrderedDict as _default_dict -from backports.configparser.helpers import ChainMap as _ChainMap -from backports.configparser.helpers import from_none, open, str, PY2 - -__all__ = ["NoSectionError", "DuplicateOptionError", "DuplicateSectionError", - "NoOptionError", "InterpolationError", "InterpolationDepthError", - "InterpolationMissingOptionError", "InterpolationSyntaxError", - "ParsingError", "MissingSectionHeaderError", - "ConfigParser", "SafeConfigParser", "RawConfigParser", - "Interpolation", "BasicInterpolation", "ExtendedInterpolation", - "LegacyInterpolation", "SectionProxy", "ConverterMapping", - "DEFAULTSECT", "MAX_INTERPOLATION_DEPTH"] - -DEFAULTSECT = "DEFAULT" - -MAX_INTERPOLATION_DEPTH = 10 - - -# exception classes -class Error(Exception): - """Base class for ConfigParser exceptions.""" - - def __init__(self, msg=''): - self.message = msg - Exception.__init__(self, msg) - - def __repr__(self): - return self.message - - __str__ = __repr__ - - -class NoSectionError(Error): - """Raised when no section matches a requested option.""" - - def __init__(self, section): - Error.__init__(self, 'No section: %r' % (section,)) - self.section = section - self.args = (section, ) - - -class DuplicateSectionError(Error): - """Raised when a section is repeated in an input source. - - Possible repetitions that raise this exception are: multiple creation - using the API or in strict parsers when a section is found more than once - in a single input file, string or dictionary. - """ - - def __init__(self, section, source=None, lineno=None): - msg = [repr(section), " already exists"] - if source is not None: - message = ["While reading from ", repr(source)] - if lineno is not None: - message.append(" [line {0:2d}]".format(lineno)) - message.append(": section ") - message.extend(msg) - msg = message - else: - msg.insert(0, "Section ") - Error.__init__(self, "".join(msg)) - self.section = section - self.source = source - self.lineno = lineno - self.args = (section, source, lineno) - - -class DuplicateOptionError(Error): - """Raised by strict parsers when an option is repeated in an input source. - - Current implementation raises this exception only when an option is found - more than once in a single file, string or dictionary. - """ - - def __init__(self, section, option, source=None, lineno=None): - msg = [repr(option), " in section ", repr(section), - " already exists"] - if source is not None: - message = ["While reading from ", repr(source)] - if lineno is not None: - message.append(" [line {0:2d}]".format(lineno)) - message.append(": option ") - message.extend(msg) - msg = message - else: - msg.insert(0, "Option ") - Error.__init__(self, "".join(msg)) - self.section = section - self.option = option - self.source = source - self.lineno = lineno - self.args = (section, option, source, lineno) - - -class NoOptionError(Error): - """A requested option was not found.""" - - def __init__(self, option, section): - Error.__init__(self, "No option %r in section: %r" % - (option, section)) - self.option = option - self.section = section - self.args = (option, section) - - -class InterpolationError(Error): - """Base class for interpolation-related exceptions.""" - - def __init__(self, option, section, msg): - Error.__init__(self, msg) - self.option = option - self.section = section - self.args = (option, section, msg) - - -class InterpolationMissingOptionError(InterpolationError): - """A string substitution required a setting which was not available.""" - - def __init__(self, option, section, rawval, reference): - msg = ("Bad value substitution: option {0!r} in section {1!r} contains " - "an interpolation key {2!r} which is not a valid option name. " - "Raw value: {3!r}".format(option, section, reference, rawval)) - InterpolationError.__init__(self, option, section, msg) - self.reference = reference - self.args = (option, section, rawval, reference) - - -class InterpolationSyntaxError(InterpolationError): - """Raised when the source text contains invalid syntax. - - Current implementation raises this exception when the source text into - which substitutions are made does not conform to the required syntax. - """ - - -class InterpolationDepthError(InterpolationError): - """Raised when substitutions are nested too deeply.""" - - def __init__(self, option, section, rawval): - msg = ("Recursion limit exceeded in value substitution: option {0!r} " - "in section {1!r} contains an interpolation key which " - "cannot be substituted in {2} steps. Raw value: {3!r}" - "".format(option, section, MAX_INTERPOLATION_DEPTH, - rawval)) - InterpolationError.__init__(self, option, section, msg) - self.args = (option, section, rawval) - - -class ParsingError(Error): - """Raised when a configuration file does not follow legal syntax.""" - - def __init__(self, source=None, filename=None): - # Exactly one of `source'/`filename' arguments has to be given. - # `filename' kept for compatibility. - if filename and source: - raise ValueError("Cannot specify both `filename' and `source'. " - "Use `source'.") - elif not filename and not source: - raise ValueError("Required argument `source' not given.") - elif filename: - source = filename - Error.__init__(self, 'Source contains parsing errors: %r' % source) - self.source = source - self.errors = [] - self.args = (source, ) - - @property - def filename(self): - """Deprecated, use `source'.""" - warnings.warn( - "The 'filename' attribute will be removed in future versions. " - "Use 'source' instead.", - DeprecationWarning, stacklevel=2 - ) - return self.source - - @filename.setter - def filename(self, value): - """Deprecated, user `source'.""" - warnings.warn( - "The 'filename' attribute will be removed in future versions. " - "Use 'source' instead.", - DeprecationWarning, stacklevel=2 - ) - self.source = value - - def append(self, lineno, line): - self.errors.append((lineno, line)) - self.message += '\n\t[line %2d]: %s' % (lineno, line) - - -class MissingSectionHeaderError(ParsingError): - """Raised when a key-value pair is found before any section header.""" - - def __init__(self, filename, lineno, line): - Error.__init__( - self, - 'File contains no section headers.\nfile: %r, line: %d\n%r' % - (filename, lineno, line)) - self.source = filename - self.lineno = lineno - self.line = line - self.args = (filename, lineno, line) - - -# Used in parser getters to indicate the default behaviour when a specific -# option is not found it to raise an exception. Created to enable `None' as -# a valid fallback value. -_UNSET = object() - - -class Interpolation(object): - """Dummy interpolation that passes the value through with no changes.""" - - def before_get(self, parser, section, option, value, defaults): - return value - - def before_set(self, parser, section, option, value): - return value - - def before_read(self, parser, section, option, value): - return value - - def before_write(self, parser, section, option, value): - return value - - -class BasicInterpolation(Interpolation): - """Interpolation as implemented in the classic ConfigParser. - - The option values can contain format strings which refer to other values in - the same section, or values in the special default section. - - For example: - - something: %(dir)s/whatever - - would resolve the "%(dir)s" to the value of dir. All reference - expansions are done late, on demand. If a user needs to use a bare % in - a configuration file, she can escape it by writing %%. Other % usage - is considered a user error and raises `InterpolationSyntaxError'.""" - - _KEYCRE = re.compile(r"%\(([^)]+)\)s") - - def before_get(self, parser, section, option, value, defaults): - L = [] - self._interpolate_some(parser, option, L, value, section, defaults, 1) - return ''.join(L) - - def before_set(self, parser, section, option, value): - tmp_value = value.replace('%%', '') # escaped percent signs - tmp_value = self._KEYCRE.sub('', tmp_value) # valid syntax - if '%' in tmp_value: - raise ValueError("invalid interpolation syntax in %r at " - "position %d" % (value, tmp_value.find('%'))) - return value - - def _interpolate_some(self, parser, option, accum, rest, section, map, - depth): - rawval = parser.get(section, option, raw=True, fallback=rest) - if depth > MAX_INTERPOLATION_DEPTH: - raise InterpolationDepthError(option, section, rawval) - while rest: - p = rest.find("%") - if p < 0: - accum.append(rest) - return - if p > 0: - accum.append(rest[:p]) - rest = rest[p:] - # p is no longer used - c = rest[1:2] - if c == "%": - accum.append("%") - rest = rest[2:] - elif c == "(": - m = self._KEYCRE.match(rest) - if m is None: - raise InterpolationSyntaxError(option, section, - "bad interpolation variable reference %r" % rest) - var = parser.optionxform(m.group(1)) - rest = rest[m.end():] - try: - v = map[var] - except KeyError: - raise from_none(InterpolationMissingOptionError( - option, section, rawval, var)) - if "%" in v: - self._interpolate_some(parser, option, accum, v, - section, map, depth + 1) - else: - accum.append(v) - else: - raise InterpolationSyntaxError( - option, section, - "'%%' must be followed by '%%' or '(', " - "found: %r" % (rest,)) - - -class ExtendedInterpolation(Interpolation): - """Advanced variant of interpolation, supports the syntax used by - `zc.buildout'. Enables interpolation between sections.""" - - _KEYCRE = re.compile(r"\$\{([^}]+)\}") - - def before_get(self, parser, section, option, value, defaults): - L = [] - self._interpolate_some(parser, option, L, value, section, defaults, 1) - return ''.join(L) - - def before_set(self, parser, section, option, value): - tmp_value = value.replace('$$', '') # escaped dollar signs - tmp_value = self._KEYCRE.sub('', tmp_value) # valid syntax - if '$' in tmp_value: - raise ValueError("invalid interpolation syntax in %r at " - "position %d" % (value, tmp_value.find('$'))) - return value - - def _interpolate_some(self, parser, option, accum, rest, section, map, - depth): - rawval = parser.get(section, option, raw=True, fallback=rest) - if depth > MAX_INTERPOLATION_DEPTH: - raise InterpolationDepthError(option, section, rawval) - while rest: - p = rest.find("$") - if p < 0: - accum.append(rest) - return - if p > 0: - accum.append(rest[:p]) - rest = rest[p:] - # p is no longer used - c = rest[1:2] - if c == "$": - accum.append("$") - rest = rest[2:] - elif c == "{": - m = self._KEYCRE.match(rest) - if m is None: - raise InterpolationSyntaxError(option, section, - "bad interpolation variable reference %r" % rest) - path = m.group(1).split(':') - rest = rest[m.end():] - sect = section - opt = option - try: - if len(path) == 1: - opt = parser.optionxform(path[0]) - v = map[opt] - elif len(path) == 2: - sect = path[0] - opt = parser.optionxform(path[1]) - v = parser.get(sect, opt, raw=True) - else: - raise InterpolationSyntaxError( - option, section, - "More than one ':' found: %r" % (rest,)) - except (KeyError, NoSectionError, NoOptionError): - raise from_none(InterpolationMissingOptionError( - option, section, rawval, ":".join(path))) - if "$" in v: - self._interpolate_some(parser, opt, accum, v, sect, - dict(parser.items(sect, raw=True)), - depth + 1) - else: - accum.append(v) - else: - raise InterpolationSyntaxError( - option, section, - "'$' must be followed by '$' or '{', " - "found: %r" % (rest,)) - - -class LegacyInterpolation(Interpolation): - """Deprecated interpolation used in old versions of ConfigParser. - Use BasicInterpolation or ExtendedInterpolation instead.""" - - _KEYCRE = re.compile(r"%\(([^)]*)\)s|.") - - def before_get(self, parser, section, option, value, vars): - rawval = value - depth = MAX_INTERPOLATION_DEPTH - while depth: # Loop through this until it's done - depth -= 1 - if value and "%(" in value: - replace = functools.partial(self._interpolation_replace, - parser=parser) - value = self._KEYCRE.sub(replace, value) - try: - value = value % vars - except KeyError as e: - raise from_none(InterpolationMissingOptionError( - option, section, rawval, e.args[0])) - else: - break - if value and "%(" in value: - raise InterpolationDepthError(option, section, rawval) - return value - - def before_set(self, parser, section, option, value): - return value - - @staticmethod - def _interpolation_replace(match, parser): - s = match.group(1) - if s is None: - return match.group() - else: - return "%%(%s)s" % parser.optionxform(s) - - -class RawConfigParser(MutableMapping): - """ConfigParser that does not do interpolation.""" - - # Regular expressions for parsing section headers and options - _SECT_TMPL = r""" - \[ # [ - (?P
[^]]+) # very permissive! - \] # ] - """ - _OPT_TMPL = r""" - (?P