Merge branch 'develop' into feature/modules_using_keyring

This commit is contained in:
iLLiCiTiT 2021-04-09 10:01:32 +02:00
commit 91faeb5492
50 changed files with 733 additions and 685 deletions

View file

@ -166,14 +166,23 @@ sudo yum install qt5-qtbase-devel
<details>
<summary>Use pyenv to install Python version for OpenPype build</summary>
You will need **bzip2**, **readline** and **sqlite3** libraries.
You will need **bzip2**, **readline**, **sqlite3** and other libraries.
**Ubuntu:**
For more details about Python build environments see:
https://github.com/pyenv/pyenv/wiki#suggested-build-environment
**For Ubuntu:**
```sh
sudo apt install libbz2-dev libreadline-dev libsqlite3-dev
sudo apt-get update; sudo apt-get install --no-install-recommends make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
```
1) install **pyenv**
**For Centos:**
```sh
yum install gcc zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel tk-devel libffi-devel
```
**install pyenv**
```sh
curl https://pyenv.run | bash

View file

@ -14,7 +14,10 @@ from zipfile import ZipFile, BadZipFile
from appdirs import user_data_dir
from speedcopy import copyfile
from .user_settings import OpenPypeSettingsRegistry
from .user_settings import (
OpenPypeSecureRegistry,
OpenPypeSettingsRegistry
)
from .tools import get_openpype_path_from_db
@ -239,6 +242,7 @@ class BootstrapRepos:
self._app = "openpype"
self._log = log.getLogger(str(__class__))
self.data_dir = Path(user_data_dir(self._app, self._vendor))
self.secure_registry = OpenPypeSecureRegistry("mongodb")
self.registry = OpenPypeSettingsRegistry()
self.zip_filter = [".pyc", "__pycache__"]
self.openpype_filter = [

View file

@ -13,7 +13,7 @@ from .tools import (
validate_mongo_connection,
get_openpype_path_from_db
)
from .user_settings import OpenPypeSettingsRegistry
from .user_settings import OpenPypeSecureRegistry
from .version import __version__
@ -42,13 +42,13 @@ class InstallDialog(QtWidgets.QDialog):
def __init__(self, parent=None):
super(InstallDialog, self).__init__(parent)
self.registry = OpenPypeSettingsRegistry()
self.secure_registry = OpenPypeSecureRegistry("mongodb")
self.mongo_url = ""
try:
self.mongo_url = (
os.getenv("OPENPYPE_MONGO", "")
or self.registry.get_secure_item("openPypeMongo")
or self.secure_registry.get_item("openPypeMongo")
)
except ValueError:
pass

View file

@ -71,7 +71,7 @@ class InstallThread(QThread):
if not os.getenv("OPENPYPE_MONGO"):
# try to get it from settings registry
try:
self._mongo = bs.registry.get_secure_item(
self._mongo = bs.secure_registry.get_item(
"openPypeMongo")
except ValueError:
self.message.emit(
@ -82,7 +82,7 @@ class InstallThread(QThread):
self._mongo = os.getenv("OPENPYPE_MONGO")
else:
self.message.emit("Saving mongo connection string ...", False)
bs.registry.set_secure_item("openPypeMongo", self._mongo)
bs.secure_registry.set_item("openPypeMongo", self._mongo)
os.environ["OPENPYPE_MONGO"] = self._mongo
@ -169,7 +169,7 @@ class InstallThread(QThread):
f"!!! invalid mongo url {self._mongo}", True)
self.finished.emit(InstallResult(-1))
return
bs.registry.set_secure_item("openPypeMongo", self._mongo)
bs.secure_registry.set_item("openPypeMongo", self._mongo)
os.environ["OPENPYPE_MONGO"] = self._mongo
self.message.emit(f"processing {self._path}", True)

View file

@ -25,8 +25,112 @@ except ImportError:
import platform
import appdirs
import six
import appdirs
_PLACEHOLDER = object()
class OpenPypeSecureRegistry:
"""Store information using keyring.
Registry should be used for private data that should be available only for
user.
All passed registry names will have added prefix `OpenPype/` to easier
identify which data were created by OpenPype.
Args:
name(str): Name of registry used as identifier for data.
"""
def __init__(self, name):
try:
import keyring
except Exception:
raise NotImplementedError(
"Python module `keyring` is not available."
)
# hack for cx_freeze and Windows keyring backend
if platform.system().lower() == "windows":
from keyring.backends import Windows
keyring.set_keyring(Windows.WinVaultKeyring())
# Force "OpenPype" prefix
self._name = "/".join(("OpenPype", name))
def set_item(self, name, value):
# type: (str, str) -> None
"""Set sensitive item into system's keyring.
This uses `Keyring module`_ to save sensitive stuff into system's
keyring.
Args:
name (str): Name of the item.
value (str): Value of the item.
.. _Keyring module:
https://github.com/jaraco/keyring
"""
import keyring
keyring.set_password(self._name, name, value)
@lru_cache(maxsize=32)
def get_item(self, name, default=_PLACEHOLDER):
"""Get value of sensitive item from system's keyring.
See also `Keyring module`_
Args:
name (str): Name of the item.
default (Any): Default value if item is not available.
Returns:
value (str): Value of the item.
Raises:
ValueError: If item doesn't exist and default is not defined.
.. _Keyring module:
https://github.com/jaraco/keyring
"""
import keyring
value = keyring.get_password(self._name, name)
if value:
return value
if default is not _PLACEHOLDER:
return default
# NOTE Should raise `KeyError`
raise ValueError(
"Item {}:{} does not exist in keyring.".format(self._name, name)
)
def delete_item(self, name):
# type: (str) -> None
"""Delete value stored in system's keyring.
See also `Keyring module`_
Args:
name (str): Name of the item to be deleted.
.. _Keyring module:
https://github.com/jaraco/keyring
"""
import keyring
self.get_item.cache_clear()
keyring.delete_password(self._name, name)
@six.add_metaclass(ABCMeta)
@ -46,13 +150,6 @@ class ASettingRegistry():
# type: (str) -> ASettingRegistry
super(ASettingRegistry, self).__init__()
if six.PY3:
import keyring
# hack for cx_freeze and Windows keyring backend
if platform.system() == "Windows":
from keyring.backends import Windows
keyring.set_keyring(Windows.WinVaultKeyring())
self._name = name
self._items = {}
@ -127,78 +224,6 @@ class ASettingRegistry():
del self._items[name]
self._delete_item(name)
def set_secure_item(self, name, value):
# type: (str, str) -> None
"""Set sensitive item into system's keyring.
This uses `Keyring module`_ to save sensitive stuff into system's
keyring.
Args:
name (str): Name of the item.
value (str): Value of the item.
.. _Keyring module:
https://github.com/jaraco/keyring
"""
if six.PY2:
raise NotImplementedError(
"Keyring not available on Python 2 hosts")
import keyring
keyring.set_password(self._name, name, value)
@lru_cache(maxsize=32)
def get_secure_item(self, name):
# type: (str) -> str
"""Get value of sensitive item from system's keyring.
See also `Keyring module`_
Args:
name (str): Name of the item.
Returns:
value (str): Value of the item.
Raises:
ValueError: If item doesn't exist.
.. _Keyring module:
https://github.com/jaraco/keyring
"""
if six.PY2:
raise NotImplementedError(
"Keyring not available on Python 2 hosts")
import keyring
value = keyring.get_password(self._name, name)
if not value:
raise ValueError(
"Item {}:{} does not exist in keyring.".format(
self._name, name))
return value
def delete_secure_item(self, name):
# type: (str) -> None
"""Delete value stored in system's keyring.
See also `Keyring module`_
Args:
name (str): Name of the item to be deleted.
.. _Keyring module:
https://github.com/jaraco/keyring
"""
if six.PY2:
raise NotImplementedError(
"Keyring not available on Python 2 hosts")
import keyring
self.get_secure_item.cache_clear()
keyring.delete_password(self._name, name)
class IniSettingRegistry(ASettingRegistry):
"""Class using :mod:`configparser`.
@ -459,9 +484,10 @@ class OpenPypeSettingsRegistry(JSONSettingRegistry):
"""
def __init__(self):
def __init__(self, name=None):
self.vendor = "pypeclub"
self.product = "openpype"
if not name:
name = "openpype_settings"
path = appdirs.user_data_dir(self.product, self.vendor)
super(OpenPypeSettingsRegistry, self).__init__(
"openpype_settings", path)
super(OpenPypeSettingsRegistry, self).__init__(name, path)

View file

@ -1,4 +1,5 @@
import os
import subprocess
from openpype.lib import PreLaunchHook
@ -10,15 +11,32 @@ class LaunchWithWindowsShell(PreLaunchHook):
instead.
"""
order = 10
app_groups = ["resolve", "nuke", "nukex", "hiero", "nukestudio"]
# Should be as last hook becuase must change launch arguments to string
order = 1000
app_groups = ["nuke", "nukex", "hiero", "nukestudio"]
platforms = ["windows"]
def execute(self):
# Get comspec which is cmd.exe in most cases.
comspec = os.environ.get("COMSPEC", "cmd.exe")
# Add comspec to arguments list and add "/k"
new_args = [comspec, "/c"]
new_args.extend(self.launch_context.launch_args)
new_args = [
# Get comspec which is cmd.exe in most cases.
os.environ.get("COMSPEC", "cmd.exe"),
# NOTE change to "/k" if want to keep console opened
"/c",
# Convert arguments to command line arguments (as string)
"\"{}\"".format(
subprocess.list2cmdline(self.launch_context.launch_args)
)
]
# Convert list to string
# WARNING this only works if is used as string
args_string = " ".join(new_args)
self.log.info((
"Modified launch arguments to be launched with shell \"{}\"."
).format(args_string))
# Replace launch args with new one
self.launch_context.launch_args = new_args
self.launch_context.launch_args = args_string
# Change `creationflags` to CREATE_NEW_CONSOLE
self.launch_context.kwargs["creationflags"] = (
subprocess.CREATE_NEW_CONSOLE
)

View file

@ -10,7 +10,7 @@ import pyblish.api as pyblish
import openpype.hosts.aftereffects
log = logging.getLogger("pype.hosts.aftereffects")
log = logging.getLogger("openpype.hosts.aftereffects")
HOST_DIR = os.path.dirname(os.path.abspath(openpype.hosts.aftereffects.__file__))

View file

@ -46,6 +46,12 @@ class CollectAERender(abstract_collect_render.AbstractCollectRender):
"Please recreate instance.")
item_id = inst["members"][0]
work_area_info = self.stub.get_work_area(int(item_id))
if not work_area_info:
self.log.warning("Orphaned instance, deleting metadata")
self.stub.remove_instance(int(item_id))
continue
frameStart = work_area_info.workAreaStart
frameEnd = round(work_area_info.workAreaStart +

View file

@ -21,3 +21,4 @@ class RemovePublishHighlight(openpype.api.Extractor):
item = instance.data
comp_name = item["comp_name"].replace(stub.PUBLISH_ICON, '')
stub.rename_item(item["comp_id"], comp_name)
instance.data["comp_name"] = comp_name

View file

@ -39,7 +39,7 @@ def install():
avalon.data["familiesStateDefault"] = False
avalon.data["familiesStateToggled"] = family_states
log.info("pype.hosts.fusion installed")
log.info("openpype.hosts.fusion installed")
pyblish.register_host("fusion")
pyblish.register_plugin_path(PUBLISH_PATH)

View file

@ -13,7 +13,7 @@ class CollectFusionRenderMode(pyblish.api.InstancePlugin):
available tool does not visualize which render mode is set for the
current comp, please run the following line in the console (Py2)
comp.GetData("pype.rendermode")
comp.GetData("openpype.rendermode")
This will return the name of the current render mode as seen above under
Options.
@ -34,7 +34,7 @@ class CollectFusionRenderMode(pyblish.api.InstancePlugin):
raise RuntimeError("No comp previously collected, unable to "
"retrieve Fusion version.")
rendermode = comp.GetData("pype.rendermode") or "local"
rendermode = comp.GetData("openpype.rendermode") or "local"
assert rendermode in options, "Must be supported render mode"
self.log.info("Render mode: {0}".format(rendermode))

View file

@ -96,11 +96,11 @@ class SetRenderMode(QtWidgets.QWidget):
return self._comp.GetAttrs("COMPS_Name")
def _get_comp_rendermode(self):
return self._comp.GetData("pype.rendermode") or "local"
return self._comp.GetData("openpype.rendermode") or "local"
def _set_comp_rendermode(self):
rendermode = self.mode_options.currentText()
self._comp.SetData("pype.rendermode", rendermode)
self._comp.SetData("openpype.rendermode", rendermode)
self._comp.Print("Updated render mode to '%s'\n" % rendermode)
self.hide()

View file

@ -6,7 +6,7 @@ import openpype.hosts.hiero.api as phiero
avalon.api.install(phiero)
try:
__import__("pype.hosts.hiero.api")
__import__("openpype.hosts.hiero.api")
__import__("pyblish")
except ImportError as e:

View file

@ -9,7 +9,7 @@ from openpype import lib
from pyblish import api as pyblish
import openpype.hosts.photoshop
log = logging.getLogger("pype.hosts.photoshop")
log = logging.getLogger("openpype.hosts.photoshop")
HOST_DIR = os.path.dirname(os.path.abspath(openpype.hosts.photoshop.__file__))
PLUGINS_DIR = os.path.join(HOST_DIR, "plugins")

View file

@ -47,7 +47,7 @@ def install():
avalon.data["familiesStateDefault"] = False
avalon.data["familiesStateToggled"] = family_states
log.info("pype.hosts.resolve installed")
log.info("openpype.hosts.resolve installed")
pyblish.register_host("resolve")
pyblish.register_plugin_path(PUBLISH_PATH)

View file

@ -44,7 +44,7 @@ class ResolvePrelaunch(PreLaunchHook):
self.launch_context.env["PRE_PYTHON_SCRIPT"] = pre_py_sc
self.log.debug(f"-- pre_py_sc: `{pre_py_sc}`...")
try:
__import__("pype.hosts.resolve")
__import__("openpype.hosts.resolve")
__import__("pyblish")
except ImportError:

View file

@ -104,7 +104,8 @@ from .plugin_tools import (
from .local_settings import (
IniSettingRegistry,
JSONSettingRegistry,
PypeSettingsRegistry,
OpenPypeSecureRegistry,
OpenPypeSettingsRegistry,
get_local_site_id,
change_openpype_mongo_url
)
@ -217,7 +218,8 @@ __all__ = [
"IniSettingRegistry",
"JSONSettingRegistry",
"PypeSettingsRegistry",
"OpenPypeSecureRegistry",
"OpenPypeSettingsRegistry",
"get_local_site_id",
"change_openpype_mongo_url",

View file

@ -216,7 +216,7 @@ class Anatomy:
"""Returns value of root key from template."""
root_templates = []
for group in re.findall(self.root_key_regex, template):
root_templates.append(group)
root_templates.append("{" + group + "}")
if not root_templates:
return None

View file

@ -17,6 +17,10 @@ from openpype.settings import (
get_project_settings,
get_environments
)
from openpype.settings.constants import (
METADATA_KEYS,
M_DYNAMIC_KEY_LABEL
)
from . import (
PypeLogger,
Anatomy
@ -123,7 +127,16 @@ class ApplicationGroup:
self.host_name = host_name
variants = data.get("variants") or {}
key_label_mapping = variants.pop(M_DYNAMIC_KEY_LABEL, {})
for variant_name, variant_data in variants.items():
if variant_name in METADATA_KEYS:
continue
if "variant_label" not in variant_data:
variant_label = key_label_mapping.get(variant_name)
if variant_label:
variant_data["variant_label"] = variant_label
variants[variant_name] = Application(
variant_name, variant_data, self
)
@ -165,7 +178,7 @@ class Application:
enabled = False
if group.enabled:
enabled = data.get("enabled", True)
self.enabled = enabled
self.enabled = enabled
self.label = data.get("variant_label") or name
self.full_name = "/".join((group.name, name))
@ -265,22 +278,31 @@ class ApplicationManager:
self.tool_groups.clear()
self.tools.clear()
settings = get_system_settings()
settings = get_system_settings(
clear_metadata=False, exclude_locals=False
)
app_defs = settings["applications"]
for group_name, variant_defs in app_defs.items():
if group_name in METADATA_KEYS:
continue
group = ApplicationGroup(group_name, variant_defs, self)
self.app_groups[group_name] = group
for app in group:
# TODO This should be replaced with `full_name` in future
self.applications[app.full_name] = app
tools_definitions = settings["tools"]["tool_groups"]
tool_label_mapping = tools_definitions.pop(M_DYNAMIC_KEY_LABEL, {})
for tool_group_name, tool_group_data in tools_definitions.items():
if not tool_group_name:
if not tool_group_name or tool_group_name in METADATA_KEYS:
continue
tool_group_label = (
tool_label_mapping.get(tool_group_name) or tool_group_name
)
group = EnvironmentToolGroup(
tool_group_name, tool_group_data, self
tool_group_name, tool_group_label, tool_group_data, self
)
self.tool_groups[tool_group_name] = group
for tool in group:
@ -336,16 +358,24 @@ class EnvironmentToolGroup:
manager (ApplicationManager): Manager that creates the group.
"""
def __init__(self, name, data, manager):
def __init__(self, name, label, data, manager):
self.name = name
self.label = label
self._data = data
self.manager = manager
self._environment = data["environment"]
variants = data.get("variants") or {}
label_by_key = variants.pop(M_DYNAMIC_KEY_LABEL, {})
variants_by_name = {}
for variant_name, variant_env in variants.items():
tool = EnvironmentTool(variant_name, variant_env, self)
if variant_name in METADATA_KEYS:
continue
variant_label = label_by_key.get(variant_name) or variant_name
tool = EnvironmentTool(
variant_name, variant_label, variant_env, self
)
variants_by_name[variant_name] = tool
self.variants = variants_by_name
@ -372,8 +402,10 @@ class EnvironmentTool:
group (str): Name of group which wraps tool.
"""
def __init__(self, name, environment, group):
def __init__(self, name, label, environment, group):
self.name = name
self.variant_label = label
self.label = " ".join((group.label, label))
self.group = group
self._environment = environment
self.full_name = "/".join((group.name, name))
@ -804,10 +836,15 @@ class ApplicationLaunchContext:
self.log.debug("All prelaunch hook executed. Starting new process.")
# Prepare subprocess args
args = self.clear_launch_args(self.launch_args)
self.log.debug(
"Launching \"{}\" with args ({}): {}".format(
self.app_name, len(args), args
args_len_str = ""
if isinstance(self.launch_args, str):
args = self.launch_args
else:
args = self.clear_launch_args(self.launch_args)
args_len_str = " ({})".format(len(args))
self.log.info(
"Launching \"{}\" with args{}: {}".format(
self.app_name, args_len_str, args
)
)
# Run process
@ -853,7 +890,10 @@ class ApplicationLaunchContext:
Return:
list: Unpacked arguments.
"""
while True:
if isinstance(args, str):
return args
all_cleared = False
while not all_cleared:
all_cleared = True
new_args = []
for arg in args:
@ -865,8 +905,6 @@ class ApplicationLaunchContext:
new_args.append(arg)
args = new_args
if all_cleared:
break
return args

View file

@ -5,6 +5,7 @@ from datetime import datetime
from abc import ABCMeta, abstractmethod
import json
# TODO Use pype igniter logic instead of using duplicated code
# disable lru cache in Python 2
try:
from functools import lru_cache
@ -25,11 +26,115 @@ except ImportError:
import platform
import appdirs
import six
import appdirs
from .import validate_mongo_connection
_PLACEHOLDER = object()
class OpenPypeSecureRegistry:
"""Store information using keyring.
Registry should be used for private data that should be available only for
user.
All passed registry names will have added prefix `OpenPype/` to easier
identify which data were created by OpenPype.
Args:
name(str): Name of registry used as identifier for data.
"""
def __init__(self, name):
try:
import keyring
except Exception:
raise NotImplementedError(
"Python module `keyring` is not available."
)
# hack for cx_freeze and Windows keyring backend
if platform.system().lower() == "windows":
from keyring.backends import Windows
keyring.set_keyring(Windows.WinVaultKeyring())
# Force "OpenPype" prefix
self._name = "/".join(("OpenPype", name))
def set_item(self, name, value):
# type: (str, str) -> None
"""Set sensitive item into system's keyring.
This uses `Keyring module`_ to save sensitive stuff into system's
keyring.
Args:
name (str): Name of the item.
value (str): Value of the item.
.. _Keyring module:
https://github.com/jaraco/keyring
"""
import keyring
keyring.set_password(self._name, name, value)
@lru_cache(maxsize=32)
def get_item(self, name, default=_PLACEHOLDER):
"""Get value of sensitive item from system's keyring.
See also `Keyring module`_
Args:
name (str): Name of the item.
default (Any): Default value if item is not available.
Returns:
value (str): Value of the item.
Raises:
ValueError: If item doesn't exist and default is not defined.
.. _Keyring module:
https://github.com/jaraco/keyring
"""
import keyring
value = keyring.get_password(self._name, name)
if value is not None:
return value
if default is not _PLACEHOLDER:
return default
# NOTE Should raise `KeyError`
raise ValueError(
"Item {}:{} does not exist in keyring.".format(self._name, name)
)
def delete_item(self, name):
# type: (str) -> None
"""Delete value stored in system's keyring.
See also `Keyring module`_
Args:
name (str): Name of the item to be deleted.
.. _Keyring module:
https://github.com/jaraco/keyring
"""
import keyring
self.get_item.cache_clear()
keyring.delete_password(self._name, name)
@six.add_metaclass(ABCMeta)
class ASettingRegistry():
@ -48,13 +153,6 @@ class ASettingRegistry():
# type: (str) -> ASettingRegistry
super(ASettingRegistry, self).__init__()
if six.PY3:
import keyring
# hack for cx_freeze and Windows keyring backend
if platform.system() == "Windows":
from keyring.backends import Windows
keyring.set_keyring(Windows.WinVaultKeyring())
self._name = name
self._items = {}
@ -120,7 +218,7 @@ class ASettingRegistry():
"""Delete item from settings.
Note:
see :meth:`pype.lib.local_settings.ARegistrySettings.delete_item`
see :meth:`openpype.lib.user_settings.ARegistrySettings.delete_item`
"""
pass
@ -129,78 +227,6 @@ class ASettingRegistry():
del self._items[name]
self._delete_item(name)
def set_secure_item(self, name, value):
# type: (str, str) -> None
"""Set sensitive item into system's keyring.
This uses `Keyring module`_ to save sensitive stuff into system's
keyring.
Args:
name (str): Name of the item.
value (str): Value of the item.
.. _Keyring module:
https://github.com/jaraco/keyring
"""
if six.PY2:
raise NotImplementedError(
"Keyring not available on Python 2 hosts")
import keyring
keyring.set_password(self._name, name, value)
@lru_cache(maxsize=32)
def get_secure_item(self, name):
# type: (str) -> str
"""Get value of sensitive item from system's keyring.
See also `Keyring module`_
Args:
name (str): Name of the item.
Returns:
value (str): Value of the item.
Raises:
ValueError: If item doesn't exist.
.. _Keyring module:
https://github.com/jaraco/keyring
"""
if six.PY2:
raise NotImplementedError(
"Keyring not available on Python 2 hosts")
import keyring
value = keyring.get_password(self._name, name)
if not value:
raise ValueError(
"Item {}:{} does not exist in keyring.".format(
self._name, name))
return value
def delete_secure_item(self, name):
# type: (str) -> None
"""Delete value stored in system's keyring.
See also `Keyring module`_
Args:
name (str): Name of the item to be deleted.
.. _Keyring module:
https://github.com/jaraco/keyring
"""
if six.PY2:
raise NotImplementedError(
"Keyring not available on Python 2 hosts")
import keyring
self.get_secure_item.cache_clear()
keyring.delete_password(self._name, name)
class IniSettingRegistry(ASettingRegistry):
"""Class using :mod:`configparser`.
@ -218,7 +244,7 @@ class IniSettingRegistry(ASettingRegistry):
if not os.path.exists(self._registry_file):
with open(self._registry_file, mode="w") as cfg:
print("# Settings registry", cfg)
print("# Generated by Pype {}".format(version), cfg)
print("# Generated by OpenPype {}".format(version), cfg)
now = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
print("# {}".format(now), cfg)
@ -352,7 +378,7 @@ class IniSettingRegistry(ASettingRegistry):
"""Delete item from default section.
Note:
See :meth:`~pype.lib.IniSettingsRegistry.delete_item_from_section`
See :meth:`~openpype.lib.IniSettingsRegistry.delete_item_from_section`
"""
self.delete_item_from_section("MAIN", name)
@ -369,7 +395,7 @@ class JSONSettingRegistry(ASettingRegistry):
now = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
header = {
"__metadata__": {
"pype-version": os.getenv("OPENPYPE_VERSION", "N/A"),
"openpype-version": os.getenv("OPENPYPE_VERSION", "N/A"),
"generated": now
},
"registry": {}
@ -387,7 +413,7 @@ class JSONSettingRegistry(ASettingRegistry):
"""Get item value from registry json.
Note:
See :meth:`pype.lib.JSONSettingRegistry.get_item`
See :meth:`openpype.lib.JSONSettingRegistry.get_item`
"""
with open(self._registry_file, mode="r") as cfg:
@ -420,7 +446,7 @@ class JSONSettingRegistry(ASettingRegistry):
"""Set item value to registry json.
Note:
See :meth:`pype.lib.JSONSettingRegistry.set_item`
See :meth:`openpype.lib.JSONSettingRegistry.set_item`
"""
with open(self._registry_file, "r+") as cfg:
@ -452,8 +478,8 @@ class JSONSettingRegistry(ASettingRegistry):
json.dump(data, cfg, indent=4)
class PypeSettingsRegistry(JSONSettingRegistry):
"""Class handling Pype general settings registry.
class OpenPypeSettingsRegistry(JSONSettingRegistry):
"""Class handling OpenPype general settings registry.
Attributes:
vendor (str): Name used for path construction.
@ -461,11 +487,13 @@ class PypeSettingsRegistry(JSONSettingRegistry):
"""
def __init__(self):
def __init__(self, name=None):
self.vendor = "pypeclub"
self.product = "pype"
self.product = "openpype"
if not name:
name = "openpype_settings"
path = appdirs.user_data_dir(self.product, self.vendor)
super(PypeSettingsRegistry, self).__init__("pype_settings", path)
super(OpenPypeSettingsRegistry, self).__init__(name, path)
def _create_local_site_id(registry=None):
@ -473,7 +501,7 @@ def _create_local_site_id(registry=None):
from uuid import uuid4
if registry is None:
registry = PypeSettingsRegistry()
registry = OpenPypeSettingsRegistry()
new_id = str(uuid4())
@ -489,7 +517,7 @@ def get_local_site_id():
Identifier is created if does not exists yet.
"""
registry = PypeSettingsRegistry()
registry = OpenPypeSettingsRegistry()
try:
return registry.get_item("localId")
except ValueError:
@ -504,5 +532,9 @@ def change_openpype_mongo_url(new_mongo_url):
"""
validate_mongo_connection(new_mongo_url)
registry = PypeSettingsRegistry()
registry.set_secure_item("pypeMongo", new_mongo_url)
key = "openPypeMongo"
registry = OpenPypeSecureRegistry("mongodb")
existing_value = registry.get_item(key, None)
if existing_value is not None:
registry.delete_item(key)
registry.set_item(key, new_mongo_url)

View file

@ -400,9 +400,9 @@ class CustomAttributes(BaseAction):
def tools_attribute(self, event):
tools_data = []
for tool_name in self.app_manager.tools.keys():
for tool_name, tool in self.app_manager.tools.items():
tools_data.append({
tool_name: tool_name
tool_name: tool.label
})
# Make sure there is at least one item

View file

@ -1,4 +1,5 @@
import os
import time
import types
import logging
import traceback
@ -10,7 +11,6 @@ from openpype.lib import (
modules_from_path
)
log = PypeLogger.get_logger(__name__)
"""
@ -120,6 +120,18 @@ class FtrackServer:
if not session:
session = ftrack_api.Session(auto_connect_event_hub=True)
# Wait until session has connected event hub
if session._auto_connect_event_hub_thread:
# Use timeout from session (since ftrack-api 2.1.0)
timeout = getattr(session, "request_timeout", 60)
started = time.time()
while not session.event_hub.connected:
if (time.time() - started) > timeout:
raise RuntimeError((
"Connection to Ftrack was not created in {} seconds"
).format(timeout))
time.sleep(0.1)
self.session = session
if load_files:
if not self.handler_paths:

View file

@ -3,11 +3,11 @@ import sys
import logging
import getpass
import atexit
import tempfile
import threading
import datetime
import time
import queue
import appdirs
import pymongo
import requests
@ -165,7 +165,6 @@ class ProcessEventHub(SocketBaseEventHub):
def wait(self, duration=None):
"""Overriden wait
Event are loaded from Mongo DB when queue is empty. Handled event is
set as processed in Mongo DB.
"""
@ -252,7 +251,7 @@ class CustomEventHubSession(ftrack_api.session.Session):
self, server_url=None, api_key=None, api_user=None, auto_populate=True,
plugin_paths=None, cache=None, cache_key_maker=None,
auto_connect_event_hub=False, schema_cache_path=None,
plugin_arguments=None, **kwargs
plugin_arguments=None, timeout=60, **kwargs
):
self.kwargs = kwargs
@ -331,6 +330,7 @@ class CustomEventHubSession(ftrack_api.session.Session):
self._request.auth = ftrack_api.session.SessionAuthentication(
self._api_key, self._api_user
)
self.request_timeout = timeout
self.auto_populate = auto_populate
@ -368,8 +368,9 @@ class CustomEventHubSession(ftrack_api.session.Session):
# rebuilding types)?
if schema_cache_path is not False:
if schema_cache_path is None:
schema_cache_path = appdirs.user_cache_dir()
schema_cache_path = os.environ.get(
'FTRACK_API_SCHEMA_CACHE_PATH', tempfile.gettempdir()
'FTRACK_API_SCHEMA_CACHE_PATH', schema_cache_path
)
schema_cache_path = os.path.join(

View file

@ -40,8 +40,7 @@ class IdleManager(PypeModule, ITrayService):
name = "idle_manager"
def initialize(self, module_settings):
idle_man_settings = module_settings[self.name]
self.enabled = idle_man_settings["enabled"]
self.enabled = True
self.time_callbacks = collections.defaultdict(list)
self.idle_thread = None
@ -50,7 +49,8 @@ class IdleManager(PypeModule, ITrayService):
return
def tray_start(self):
self.start_thread()
if self.time_callbacks:
self.start_thread()
def tray_exit(self):
self.stop_thread()

View file

@ -45,11 +45,13 @@ class TimersManager(PypeModule, ITrayService, IIdleManager, IWebServerRoutes):
timers_settings = modules_settings[self.name]
self.enabled = timers_settings["enabled"]
auto_stop = timers_settings["auto_stop"]
# When timer will stop if idle manager is running (minutes)
full_time = int(timers_settings["full_time"] * 60)
# How many minutes before the timer is stopped will popup the message
message_time = int(timers_settings["message_time"] * 60)
self.auto_stop = auto_stop
self.time_show_message = full_time - message_time
self.time_stop_timer = full_time
@ -160,6 +162,9 @@ class TimersManager(PypeModule, ITrayService, IIdleManager, IWebServerRoutes):
def callbacks_by_idle_time(self):
"""Implementation of IIdleManager interface."""
# Time when message is shown
if not self.auto_stop:
return {}
callbacks = collections.defaultdict(list)
callbacks[self.time_show_message].append(lambda: self.time_callback(0))

View file

@ -54,11 +54,11 @@ def __main__():
print("Got Pype location from environment: {}".format(
os.environ.get('OPENPYPE_SETUP_PATH')))
pype_command = "pype.ps1"
pype_command = "openpype.ps1"
if platform.system().lower() == "linux":
pype_command = "pype"
elif platform.system().lower() == "windows":
pype_command = "pype.bat"
pype_command = "openpype.bat"
if kwargs.pype:
pype_root = kwargs.pype

View file

@ -20,8 +20,6 @@
},
"variants": {
"2020": {
"enabled": true,
"variant_label": "2020",
"executables": {
"windows": [
"C:\\Program Files\\Autodesk\\Maya2020\\bin\\maya.exe"
@ -41,8 +39,6 @@
}
},
"2019": {
"enabled": true,
"variant_label": "2019",
"executables": {
"windows": [
"C:\\Program Files\\Autodesk\\Maya2019\\bin\\maya.exe"
@ -62,8 +58,6 @@
}
},
"2018": {
"enabled": true,
"variant_label": "2018",
"executables": {
"windows": [
"C:\\Program Files\\Autodesk\\Maya2018\\bin\\maya.exe"
@ -84,86 +78,6 @@
}
}
},
"mayabatch": {
"enabled": true,
"label": "MayaBatch",
"icon": "{}/app_icons/maya.png",
"host_name": "maya",
"environment": {
"PYTHONPATH": [
"{OPENPYPE_ROOT}/avalon-core/setup/maya",
"{OPENPYPE_ROOT}/maya-look-assigner",
"{PYTHON_ENV}/python2/Lib/site-packages",
"{PYTHONPATH}"
],
"MAYA_DISABLE_CLIC_IPM": "Yes",
"MAYA_DISABLE_CIP": "Yes",
"MAYA_DISABLE_CER": "Yes",
"PYMEL_SKIP_MEL_INIT": "Yes",
"LC_ALL": "C",
"OPENPYPE_LOG_NO_COLORS": "Yes",
"MAYA_TEST": "{MAYA_VERSION}"
},
"variants": {
"2020": {
"enabled": true,
"variant_label": "2020",
"executables": {
"windows": [
"C:\\Program Files\\Autodesk\\Maya2020\\bin\\mayabatch.exe"
],
"darwin": [],
"linux": []
},
"arguments": {
"windows": [],
"darwin": [],
"linux": []
},
"environment": {
"MAYA_VERSION": "2020"
}
},
"2019": {
"enabled": true,
"variant_label": "2019",
"executables": {
"windows": [
"C:\\Program Files\\Autodesk\\Maya2019\\bin\\mayabatch.exe"
],
"darwin": [],
"linux": []
},
"arguments": {
"windows": [],
"darwin": [],
"linux": []
},
"environment": {
"MAYA_VERSION": "2019"
}
},
"2018": {
"enabled": true,
"variant_label": "2018",
"executables": {
"windows": [
"C:\\Program Files\\Autodesk\\Maya2018\\bin\\mayabatch.exe"
],
"darwin": [],
"linux": []
},
"arguments": {
"windows": [],
"darwin": [],
"linux": []
},
"environment": {
"MAYA_VERSION": "2018"
}
}
}
},
"nuke": {
"enabled": true,
"label": "Nuke",
@ -182,8 +96,6 @@
},
"variants": {
"12-2": {
"enabled": true,
"variant_label": "12.2",
"executables": {
"windows": [
"C:\\Program Files\\Nuke12.2v3\\Nuke12.2.exe"
@ -201,8 +113,6 @@
"environment": {}
},
"12-0": {
"enabled": true,
"variant_label": "12.0",
"executables": {
"windows": [
"C:\\Program Files\\Nuke12.0v1\\Nuke12.0.exe"
@ -220,8 +130,6 @@
"environment": {}
},
"11-3": {
"enabled": true,
"variant_label": "11.3",
"executables": {
"windows": [
"C:\\Program Files\\Nuke11.3v1\\Nuke11.3.exe"
@ -239,8 +147,6 @@
"environment": {}
},
"11-2": {
"enabled": true,
"variant_label": "11.2",
"executables": {
"windows": [
"C:\\Program Files\\Nuke11.2v2\\Nuke11.2.exe"
@ -254,6 +160,11 @@
"linux": []
},
"environment": {}
},
"__dynamic_keys_labels__": {
"12-2": "12.2",
"12-0": "12.0",
"11-3": "11.3"
}
}
},
@ -275,8 +186,6 @@
},
"variants": {
"12-2": {
"enabled": true,
"variant_label": "12.2",
"executables": {
"windows": [
"C:\\Program Files\\Nuke12.2v3\\Nuke12.2.exe"
@ -300,8 +209,6 @@
"environment": {}
},
"12-0": {
"enabled": true,
"variant_label": "12.0",
"executables": {
"windows": [
"C:\\Program Files\\Nuke12.0v1\\Nuke12.0.exe"
@ -325,8 +232,6 @@
"environment": {}
},
"11-3": {
"enabled": true,
"variant_label": "11.3",
"executables": {
"windows": [
"C:\\Program Files\\Nuke11.3v1\\Nuke11.3.exe"
@ -350,8 +255,6 @@
"environment": {}
},
"11-2": {
"enabled": true,
"variant_label": "11.2",
"executables": {
"windows": [
"C:\\Program Files\\Nuke11.2v2\\Nuke11.2.exe"
@ -371,6 +274,12 @@
]
},
"environment": {}
},
"__dynamic_keys_labels__": {
"12-2": "12.2",
"12-0": "12.0",
"11-3": "11.3",
"11-2": "11.2"
}
}
},
@ -392,8 +301,6 @@
},
"variants": {
"12-2": {
"enabled": true,
"variant_label": "12.2",
"executables": {
"windows": [
"C:\\Program Files\\Nuke12.2v3\\Nuke12.2.exe"
@ -417,8 +324,6 @@
"environment": {}
},
"12-0": {
"enabled": true,
"variant_label": "12.0",
"executables": {
"windows": [
"C:\\Program Files\\Nuke12.0v1\\Nuke12.0.exe"
@ -442,8 +347,6 @@
"environment": {}
},
"11-3": {
"enabled": true,
"variant_label": "11.3",
"executables": {
"windows": [
"C:\\Program Files\\Nuke11.3v1\\Nuke11.3.exe"
@ -467,8 +370,6 @@
"environment": {}
},
"11-2": {
"enabled": true,
"variant_label": "11.2",
"executables": {
"windows": [],
"darwin": [],
@ -486,6 +387,12 @@
]
},
"environment": {}
},
"__dynamic_keys_labels__": {
"12-2": "12.2",
"12-0": "12.0",
"11-3": "11.3",
"11-2": "11.2"
}
}
},
@ -507,8 +414,6 @@
},
"variants": {
"12-2": {
"enabled": true,
"variant_label": "12.2",
"executables": {
"windows": [
"C:\\Program Files\\Nuke12.2v3\\Nuke12.2.exe"
@ -532,8 +437,6 @@
"environment": {}
},
"12-0": {
"enabled": true,
"variant_label": "12.0",
"executables": {
"windows": [
"C:\\Program Files\\Nuke12.0v1\\Nuke12.0.exe"
@ -557,8 +460,6 @@
"environment": {}
},
"11-3": {
"enabled": true,
"variant_label": "11.3",
"executables": {
"windows": [
"C:\\Program Files\\Nuke11.3v1\\Nuke11.3.exe"
@ -582,8 +483,6 @@
"environment": {}
},
"11-2": {
"enabled": true,
"variant_label": "11.2",
"executables": {
"windows": [
"C:\\Program Files\\Nuke11.2v2\\Nuke11.2.exe"
@ -603,6 +502,12 @@
]
},
"environment": {}
},
"__dynamic_keys_labels__": {
"12-2": "12.2",
"12-0": "12.0",
"11-3": "11.3",
"11-2": "11.2"
}
}
},
@ -752,8 +657,6 @@
},
"variants": {
"18-5": {
"enabled": true,
"variant_label": "18.5",
"executables": {
"windows": [
"C:\\Program Files\\Side Effects Software\\Houdini 18.5.499\\bin\\houdini.exe"
@ -769,8 +672,6 @@
"environment": {}
},
"18": {
"enabled": true,
"variant_label": "18",
"executables": {
"windows": [],
"darwin": [],
@ -784,8 +685,6 @@
"environment": {}
},
"17": {
"enabled": true,
"variant_label": "17",
"executables": {
"windows": [],
"darwin": [],
@ -797,6 +696,11 @@
"linux": []
},
"environment": {}
},
"__dynamic_keys_labels__": {
"18-5": "18.5",
"18": "18",
"17": "17"
}
}
},
@ -815,8 +719,6 @@
},
"variants": {
"2-83": {
"enabled": true,
"variant_label": "2.83",
"executables": {
"windows": [
"C:\\Program Files\\Blender Foundation\\Blender 2.83\\blender.exe"
@ -838,8 +740,6 @@
"environment": {}
},
"2-90": {
"enabled": true,
"variant_label": "2.90",
"executables": {
"windows": [
"C:\\Program Files\\Blender Foundation\\Blender 2.90\\blender.exe"
@ -859,6 +759,10 @@
]
},
"environment": {}
},
"__dynamic_keys_labels__": {
"2-83": "2.83",
"2-90": "2.90"
}
}
},
@ -916,8 +820,6 @@
},
"variants": {
"animation_11-64bits": {
"enabled": true,
"variant_label": "11 (64bits)",
"executables": {
"windows": [
"C:\\Program Files\\TVPaint Developpement\\TVPaint Animation 11 (64bits)\\TVPaint Animation 11 (64bits).exe"
@ -933,8 +835,6 @@
"environment": {}
},
"animation_11-32bits": {
"enabled": true,
"variant_label": "11 (32bits)",
"executables": {
"windows": [
"C:\\Program Files (x86)\\TVPaint Developpement\\TVPaint Animation 11 (32bits)\\TVPaint Animation 11 (32bits).exe"
@ -948,6 +848,10 @@
"linux": []
},
"environment": {}
},
"__dynamic_keys_labels__": {
"animation_11-64bits": "11 (64bits)",
"animation_11-32bits": "11 (32bits)"
}
}
},
@ -1085,8 +989,6 @@
},
"variants": {
"4-24": {
"enabled": true,
"variant_label": "4.24",
"executables": {
"windows": [],
"darwin": [],
@ -1106,8 +1008,6 @@
"environment": {},
"variants": {
"python_3-7": {
"enabled": true,
"variant_label": "3.7",
"executables": {
"windows": [],
"darwin": [],
@ -1121,8 +1021,6 @@
"environment": {}
},
"python_2-7": {
"enabled": true,
"variant_label": "2.7",
"executables": {
"windows": [],
"darwin": [],
@ -1136,8 +1034,6 @@
"environment": {}
},
"terminal": {
"enabled": true,
"variant_label": "",
"executables": {
"windows": [],
"darwin": [],
@ -1149,6 +1045,10 @@
"linux": []
},
"environment": {}
},
"__dynamic_keys_labels__": {
"python_3-7": "Python 3.7",
"python_2-7": "Python 2.7"
}
}
},
@ -1160,8 +1060,6 @@
"environment": {},
"variants": {
"1-1": {
"enabled": true,
"variant_label": "1.1",
"executables": {
"windows": [],
"darwin": [],
@ -1173,6 +1071,9 @@
"linux": []
},
"environment": {}
},
"__dynamic_keys_labels__": {
"1-1": "1.1"
}
}
}

View file

@ -126,6 +126,7 @@
},
"timers_manager": {
"enabled": true,
"auto_stop": true,
"full_time": 15.0,
"message_time": 0.5
},
@ -165,8 +166,5 @@
},
"standalonepublish_tool": {
"enabled": true
},
"idle_manager": {
"enabled": true
}
}

View file

@ -226,7 +226,16 @@ class DictMutableKeysEntity(EndpointEntity):
self.is_group = True
def schema_validations(self):
# Allow to have not set label if keys are collapsible
# - this it to bypass label validation
used_temp_label = False
if self.is_group and not self.label and self.collapsible_key:
used_temp_label = True
self.label = "LABEL"
super(DictMutableKeysEntity, self).schema_validations()
if used_temp_label:
self.label = None
if not self.schema_data.get("object_type"):
reason = (

View file

@ -128,13 +128,21 @@ class AppsEnumEntity(BaseEnumEntity):
continue
group_label = app_group["label"].value
for variant_name, variant_entity in app_group["variants"].items():
variants_entity = app_group["variants"]
for variant_name, variant_entity in variants_entity.items():
enabled_entity = variant_entity.get("enabled")
if enabled_entity and not enabled_entity.value:
continue
variant_label = variant_entity["variant_label"].value
variant_label = None
if "variant_label" in variant_entity:
variant_label = variant_entity["variant_label"].value
elif hasattr(variants_entity, "get_key_label"):
variant_label = variants_entity.get_key_label(variant_name)
if not variant_label:
variant_label = variant_name
if group_label:
full_label = "{} {}".format(group_label, variant_label)
else:

View file

@ -20,24 +20,22 @@
"type": "raw-json"
},
{
"type": "dict",
"type": "dict-modifiable",
"key": "variants",
"children": [
{
"type": "schema_template",
"name": "template_host_variant",
"template_data": [
{
"app_variant_label": "2.83",
"app_variant": "2-83"
},
{
"app_variant_label": "2.90",
"app_variant": "2-90"
}
]
}
]
"collapsible_key": true,
"dynamic_label": false,
"use_label_wrap": false,
"object_type": {
"type": "dict",
"collapsible": true,
"checkbox_key": "enabled",
"children": [
{
"type": "schema_template",
"name": "template_host_variant_items"
}
]
}
}
]
}

View file

@ -20,18 +20,22 @@
"type": "raw-json"
},
{
"type": "dict",
"type": "dict-modifiable",
"key": "variants",
"children": [
{
"type": "schema_template",
"name": "template_host_variant",
"template_data": {
"app_variant_label": "1.1",
"app_variant": "1-1"
"collapsible_key": true,
"dynamic_label": false,
"use_label_wrap": false,
"object_type": {
"type": "dict",
"collapsible": true,
"checkbox_key": "enabled",
"children": [
{
"type": "schema_template",
"name": "template_host_variant_items"
}
}
]
]
}
}
]
}

View file

@ -20,28 +20,22 @@
"type": "raw-json"
},
{
"type": "dict",
"type": "dict-modifiable",
"key": "variants",
"children": [
{
"type": "schema_template",
"name": "template_host_variant",
"template_data": [
{
"app_variant_label": "18.5",
"app_variant": "18-5"
},
{
"app_variant_label": "18",
"app_variant": "18"
},
{
"app_variant_label": "17",
"app_variant": "17"
}
]
}
]
"collapsible_key": true,
"dynamic_label": false,
"use_label_wrap": false,
"object_type": {
"type": "dict",
"collapsible": true,
"checkbox_key": "enabled",
"children": [
{
"type": "schema_template",
"name": "template_host_variant_items"
}
]
}
}
]
}

View file

@ -20,28 +20,22 @@
"type": "raw-json"
},
{
"type": "dict",
"type": "dict-modifiable",
"key": "variants",
"children": [
{
"type": "schema_template",
"name": "template_host_variant",
"template_data": [
{
"app_variant_label": "2020",
"app_variant": "2020"
},
{
"app_variant_label": "2019",
"app_variant": "2019"
},
{
"app_variant_label": "2018",
"app_variant": "2018"
}
]
}
]
"collapsible_key": true,
"dynamic_label": false,
"use_label_wrap": false,
"object_type": {
"type": "dict",
"collapsible": true,
"checkbox_key": "enabled",
"children": [
{
"type": "schema_template",
"name": "template_host_variant_items"
}
]
}
}
]
}

View file

@ -1,47 +0,0 @@
{
"type": "dict",
"key": "mayabatch",
"label": "Autodesk Maya Batch",
"collapsible": true,
"checkbox_key": "enabled",
"children": [
{
"type": "boolean",
"key": "enabled",
"label": "Enabled"
},
{
"type": "schema_template",
"name": "template_host_unchangables"
},
{
"key": "environment",
"label": "Environment",
"type": "raw-json"
},
{
"type": "dict",
"key": "variants",
"children": [
{
"type": "schema_template",
"name": "template_host_variant",
"template_data": [
{
"app_variant_label": "2020",
"app_variant": "2020"
},
{
"app_variant_label": "2019",
"app_variant": "2019"
},
{
"app_variant_label": "2018",
"app_variant": "2018"
}
]
}
]
}
]
}

View file

@ -16,28 +16,22 @@
"type": "raw-json"
},
{
"type": "dict",
"type": "dict-modifiable",
"key": "variants",
"children": [
{
"type": "schema_template",
"name": "template_host_variant",
"template_data": [
{
"app_variant": "python_3-7",
"app_variant_label": "Python 3.7"
},
{
"app_variant": "python_2-7",
"app_variant_label": "Python 2.7"
},
{
"app_variant": "terminal",
"app_variant_label": "Terminal"
}
]
}
]
"collapsible_key": true,
"dynamic_label": false,
"use_label_wrap": false,
"object_type": {
"type": "dict",
"collapsible": true,
"checkbox_key": "enabled",
"children": [
{
"type": "schema_template",
"name": "template_host_variant_items"
}
]
}
}
]
}

View file

@ -20,24 +20,22 @@
"type": "raw-json"
},
{
"type": "dict",
"type": "dict-modifiable",
"key": "variants",
"children": [
{
"type": "schema_template",
"name": "template_host_variant",
"template_data": [
{
"app_variant_label": "Animation 11 (64bits)",
"app_variant": "animation_11-64bits"
},
{
"app_variant_label": "Animation 11 (32bits)",
"app_variant": "animation_11-32bits"
}
]
}
]
"collapsible_key": true,
"dynamic_label": false,
"use_label_wrap": false,
"object_type": {
"type": "dict",
"collapsible": true,
"checkbox_key": "enabled",
"children": [
{
"type": "schema_template",
"name": "template_host_variant_items"
}
]
}
}
]
}

View file

@ -20,20 +20,22 @@
"type": "raw-json"
},
{
"type": "dict",
"type": "dict-modifiable",
"key": "variants",
"children": [
{
"type": "schema_template",
"name": "template_host_variant",
"template_data": [
{
"app_variant": "4-24",
"app_variant_label": "4.24"
}
]
}
]
"collapsible_key": true,
"dynamic_label": false,
"use_label_wrap": false,
"object_type": {
"type": "dict",
"collapsible": true,
"checkbox_key": "enabled",
"children": [
{
"type": "schema_template",
"name": "template_host_variant_items"
}
]
}
}
]
}

View file

@ -15,48 +15,11 @@
"type": "text",
"key": "variant_label",
"label": "Variant label",
"placeholder": "Only \"Label\" is used if not filled."
"placeholder": "< {app_variant} >"
},
{
"type": "path",
"key": "executables",
"label": "Executables",
"multiplatform": true,
"multipath": true
},
{
"type":"separator"
},
{
"type": "dict",
"key": "arguments",
"label": "Arguments",
"use_label_wrap": false,
"children": [
{
"key": "windows",
"label": "Windows",
"type": "list",
"object_type": "text"
},
{
"key": "darwin",
"label": "MacOS",
"type": "list",
"object_type": "text"
},
{
"key": "linux",
"label": "Linux",
"type": "list",
"object_type": "text"
}
]
},
{
"key": "environment",
"label": "Environment",
"type": "raw-json"
"type": "schema_template",
"name": "template_host_variant_items"
}
]
}

View file

@ -0,0 +1,43 @@
[
{
"type": "path",
"key": "executables",
"label": "Executables",
"multiplatform": true,
"multipath": true
},
{
"type":"separator"
},
{
"type": "dict",
"key": "arguments",
"label": "Arguments",
"use_label_wrap": false,
"children": [
{
"key": "windows",
"label": "Windows",
"type": "list",
"object_type": "text"
},
{
"key": "darwin",
"label": "MacOS",
"type": "list",
"object_type": "text"
},
{
"key": "linux",
"label": "Linux",
"type": "list",
"object_type": "text"
}
]
},
{
"key": "environment",
"label": "Environment",
"type": "raw-json"
}
]

View file

@ -21,32 +21,22 @@
"type": "raw-json"
},
{
"type": "dict",
"type": "dict-modifiable",
"key": "variants",
"children": [
{
"type": "schema_template",
"name": "template_host_variant",
"template_data": [
{
"app_variant": "12-2",
"app_variant_label": "12.2"
},
{
"app_variant": "12-0",
"app_variant_label": "12.0"
},
{
"app_variant": "11-3",
"app_variant_label": "11.3"
},
{
"app_variant": "11-2",
"app_variant_label": "11.2"
}
]
}
]
"collapsible_key": true,
"dynamic_label": false,
"use_label_wrap": false,
"object_type": {
"type": "dict",
"collapsible": true,
"checkbox_key": "enabled",
"children": [
{
"type": "schema_template",
"name": "template_host_variant_items"
}
]
}
}
]
}

View file

@ -9,10 +9,6 @@
"type": "schema",
"name": "schema_maya"
},
{
"type": "schema",
"name": "schema_mayabatch"
},
{
"type": "schema_template",
"name": "template_nuke",

View file

@ -42,6 +42,11 @@
"key": "enabled",
"label": "Enabled"
},
{
"type": "boolean",
"key": "auto_stop",
"label": "Auto stop timer"
},
{
"type": "number",
"decimal": 2,
@ -176,20 +181,6 @@
"label": "Enabled"
}
]
},
{
"type": "dict",
"key": "idle_manager",
"label": "Idle Manager",
"collapsible": true,
"checkbox_key": "enabled",
"children": [
{
"type": "boolean",
"key": "enabled",
"label": "Enabled"
}
]
}
]
}

View file

@ -489,7 +489,7 @@ def apply_local_settings_on_system_settings(system_settings, local_settings):
# TODO This is temporary fix until launch arguments will be stored
# per platform and not per executable.
# - local settings store only executable
new_executables = [[executable, ""]]
new_executables = [executable]
new_executables.extend(platform_executables)
variants[app_name]["executables"] = new_executables
@ -645,13 +645,22 @@ def apply_local_settings_on_project_settings(
sync_server_config["remote_site"] = remote_site
def get_system_settings(clear_metadata=True):
def get_system_settings(clear_metadata=True, exclude_locals=None):
"""System settings with applied studio overrides."""
default_values = get_default_settings()[SYSTEM_SETTINGS_KEY]
studio_values = get_studio_system_settings_overrides()
result = apply_overrides(default_values, studio_values)
# Clear overrides metadata from settings
if clear_metadata:
clear_metadata_from_settings(result)
# Apply local settings
# Default behavior is based on `clear_metadata` value
if exclude_locals is None:
exclude_locals = not clear_metadata
if not exclude_locals:
# TODO local settings may be required to apply for environments
local_settings = get_local_settings()
apply_local_settings_on_system_settings(result, local_settings)
@ -659,40 +668,52 @@ def get_system_settings(clear_metadata=True):
return result
def get_default_project_settings(clear_metadata=True, exclude_locals=False):
def get_default_project_settings(clear_metadata=True, exclude_locals=None):
"""Project settings with applied studio's default project overrides."""
default_values = get_default_settings()[PROJECT_SETTINGS_KEY]
studio_values = get_studio_project_settings_overrides()
result = apply_overrides(default_values, studio_values)
# Clear overrides metadata from settings
if clear_metadata:
clear_metadata_from_settings(result)
if not exclude_locals:
local_settings = get_local_settings()
apply_local_settings_on_project_settings(
result, local_settings, None
)
# Apply local settings
if exclude_locals is None:
exclude_locals = not clear_metadata
if not exclude_locals:
local_settings = get_local_settings()
apply_local_settings_on_project_settings(
result, local_settings, None
)
return result
def get_default_anatomy_settings(clear_metadata=True, exclude_locals=False):
def get_default_anatomy_settings(clear_metadata=True, exclude_locals=None):
"""Project anatomy data with applied studio's default project overrides."""
default_values = get_default_settings()[PROJECT_ANATOMY_KEY]
studio_values = get_studio_project_anatomy_overrides()
# TODO uncomment and remove hotfix result when overrides of anatomy
# are stored correctly.
result = apply_overrides(default_values, studio_values)
# Clear overrides metadata from settings
if clear_metadata:
clear_metadata_from_settings(result)
if not exclude_locals:
local_settings = get_local_settings()
apply_local_settings_on_anatomy_settings(
result, local_settings, None
)
# Apply local settings
if exclude_locals is None:
exclude_locals = not clear_metadata
if not exclude_locals:
local_settings = get_local_settings()
apply_local_settings_on_anatomy_settings(
result, local_settings, None
)
return result
def get_anatomy_settings(project_name, site_name=None, exclude_locals=False):
def get_anatomy_settings(
project_name, site_name=None, clear_metadata=True, exclude_locals=None
):
"""Project anatomy data with applied studio and project overrides."""
if not project_name:
raise ValueError(
@ -709,7 +730,13 @@ def get_anatomy_settings(project_name, site_name=None, exclude_locals=False):
for key, value in project_overrides.items():
result[key] = value
clear_metadata_from_settings(result)
# Clear overrides metadata from settings
if clear_metadata:
clear_metadata_from_settings(result)
# Apply local settings
if exclude_locals is None:
exclude_locals = not clear_metadata
if not exclude_locals:
local_settings = get_local_settings()
@ -719,7 +746,9 @@ def get_anatomy_settings(project_name, site_name=None, exclude_locals=False):
return result
def get_project_settings(project_name, exclude_locals=False):
def get_project_settings(
project_name, clear_metadata=True, exclude_locals=None
):
"""Project settings with applied studio and project overrides."""
if not project_name:
raise ValueError(
@ -733,7 +762,14 @@ def get_project_settings(project_name, exclude_locals=False):
)
result = apply_overrides(studio_overrides, project_overrides)
clear_metadata_from_settings(result)
# Clear overrides metadata from settings
if clear_metadata:
clear_metadata_from_settings(result)
# Apply local settings
if exclude_locals is None:
exclude_locals = not clear_metadata
if not exclude_locals:
local_settings = get_local_settings()

View file

@ -10,12 +10,20 @@ from .constants import CHILD_OFFSET
class AppVariantWidget(QtWidgets.QWidget):
exec_placeholder = "< Specific path for this machine >"
def __init__(self, group_label, variant_entity, parent):
def __init__(self, group_label, variant_name, variant_entity, parent):
super(AppVariantWidget, self).__init__(parent)
self.executable_input_widget = None
variant_label = variant_entity.label
if variant_label is None:
parent_entity = variant_entity.parent
if hasattr(parent_entity, "get_key_label"):
variant_label = parent_entity.get_key_label(variant_name)
label = " ".join([group_label, variant_entity.label])
if not variant_label:
variant_label = variant_name
label = " ".join([group_label, variant_label])
expading_widget = ExpandingWidget(label, self)
content_widget = QtWidgets.QWidget(expading_widget)
@ -102,7 +110,7 @@ class AppGroupWidget(QtWidgets.QWidget):
valid_variants = {}
for key, entity in group_entity["variants"].items():
if entity["enabled"].value:
if "enabled" not in entity or entity["enabled"].value:
valid_variants[key] = entity
group_label = group_entity.label
@ -114,7 +122,7 @@ class AppGroupWidget(QtWidgets.QWidget):
widgets_by_variant_name = {}
for variant_name, variant_entity in valid_variants.items():
variant_widget = AppVariantWidget(
group_label, variant_entity, content_widget
group_label, variant_name, variant_entity, content_widget
)
widgets_by_variant_name[variant_name] = variant_widget
content_layout.addWidget(variant_widget)
@ -173,7 +181,10 @@ class LocalApplicationsWidgets(QtWidgets.QWidget):
# Check if has enabled any variant
enabled_variant = False
for variant_entity in entity["variants"].values():
if variant_entity["enabled"].value:
if (
"enabled" not in variant_entity
or variant_entity["enabled"].value
):
enabled_variant = True
break

View file

@ -103,7 +103,10 @@ class ModifiableDictEmptyItem(QtWidgets.QWidget):
self.key_is_valid = KEY_REGEX.match(key)
self.is_duplicated = self.entity_widget.is_key_duplicated(key)
key_input_state = ""
if self.is_duplicated or not self.key_is_valid:
# Collapsible key and empty key are not invalid
if self.collapsible_key and self.key_input.text() == "":
pass
elif self.is_duplicated or not self.key_is_valid:
key_input_state = "invalid"
elif key != "":
key_input_state = "modified"

View file

@ -296,7 +296,7 @@ def _determine_mongodb() -> str:
if not openpype_mongo:
# try system keyring
try:
openpype_mongo = bootstrap.registry.get_secure_item(
openpype_mongo = bootstrap.secure_registry.get_item(
"openPypeMongo")
except ValueError:
print("*** No DB connection string specified.")
@ -305,7 +305,7 @@ def _determine_mongodb() -> str:
igniter.open_dialog()
try:
openpype_mongo = bootstrap.registry.get_secure_item(
openpype_mongo = bootstrap.secure_registry.get_item(
"openPypeMongo")
except ValueError:
raise RuntimeError("missing mongodb url")

View file

@ -11,7 +11,7 @@ import pytest
from igniter.bootstrap_repos import BootstrapRepos
from igniter.bootstrap_repos import PypeVersion
from pype.lib import PypeSettingsRegistry
from pype.lib import OpenPypeSettingsRegistry
@pytest.fixture
@ -348,7 +348,7 @@ def test_find_pype(fix_bootstrap, tmp_path_factory, monkeypatch, printer):
return d_path.as_posix()
monkeypatch.setattr(appdirs, "user_data_dir", mock_user_data_dir)
fix_bootstrap.registry = PypeSettingsRegistry()
fix_bootstrap.registry = OpenPypeSettingsRegistry()
fix_bootstrap.registry.set_item("pypePath", d_path.as_posix())
result = fix_bootstrap.find_pype(include_zips=True)

View file

@ -1,10 +1,20 @@
import pytest
from pype.lib import IniSettingRegistry
from pype.lib import JSONSettingRegistry
from pype.lib import (
IniSettingRegistry,
JSONSettingRegistry,
OpenPypeSecureRegistry
)
from uuid import uuid4
import configparser
@pytest.fixture
def secure_registry(tmpdir):
name = "pypetest_{}".format(str(uuid4()))
r = OpenPypeSecureRegistry(name, tmpdir)
yield r
@pytest.fixture
def json_registry(tmpdir):
name = "pypetest_{}".format(str(uuid4()))
@ -19,21 +29,21 @@ def ini_registry(tmpdir):
yield r
def test_keyring(json_registry):
json_registry.set_secure_item("item1", "foo")
json_registry.set_secure_item("item2", "bar")
result1 = json_registry.get_secure_item("item1")
result2 = json_registry.get_secure_item("item2")
def test_keyring(secure_registry):
secure_registry.set_item("item1", "foo")
secure_registry.set_item("item2", "bar")
result1 = secure_registry.get_item("item1")
result2 = secure_registry.get_item("item2")
assert result1 == "foo"
assert result2 == "bar"
json_registry.delete_secure_item("item1")
json_registry.delete_secure_item("item2")
secure_registry.delete_item("item1")
secure_registry.delete_item("item2")
with pytest.raises(ValueError):
json_registry.get_secure_item("item1")
json_registry.get_secure_item("item2")
secure_registry.get_item("item1")
secure_registry.get_item("item2")
def test_ini_registry(ini_registry):

View file

@ -65,23 +65,20 @@ To build pype on linux you wil need:
- **[curl](https://curl.se)** on systems that doesn't have one preinstalled.
- Python header files installed (**python3-dev** on Ubuntu for example).
- **[CMake](https://cmake.org/)**: to build some external openPype dependencies.
- **bzip2**, **readline** and **sqlite3** libraries.
- **bzip2**, **readline**, **sqlite3** and other libraries.
Because some Linux distros come with newer Python version pre-installed, you might
need to install **3.7** version and make use of it explicitly.
Your best bet is probably using [pyenv](https://github.com/pyenv/pyenv).
You can use your package manager to install **git** and **cmake**.
You can use your package manager to install **git** and other packages to your build
environment.
Use curl for pyenv installation
:::note Install build requirements for **Ubuntu**
```sh
sudo apt install build-essential checkinstall
sudo apt install git cmake curl
sudo apt install libbz2-dev libreadline-dev libsqlite3-dev
sudo apt-get update; sudo apt-get install --no-install-recommends make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev git
```
In case you run in error about `xcb` when running Pype,
@ -95,8 +92,7 @@ sudo apt install qt5-default
:::note Install build requirements for **Centos**
```sh
sudo yum install git cmake python3-devel python3-pip
sudo yum install bzip2-devel readline-devel sqlite-devel
yum install gcc zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel tk-devel libffi-devel git
```
In case you run in error about `xcb` when running Pype,
@ -108,6 +104,8 @@ sudo yum install qt5-qtbase-devel
:::
For more information about setting your build environmet please refer to [pyenv suggested build environment](https://github.com/pyenv/pyenv/wiki#suggested-build-environment)
#### Common steps for all Distros
Use pyenv to prepare Python version for Pype build