From a11d5c4193ee2d0b270f4cce7b0c97c89619c529 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Thu, 13 May 2021 14:52:56 +0200 Subject: [PATCH 1/5] fix tests --- tests/igniter/test_bootstrap_repos.py | 280 +++++++++--------- .../lib/test_user_settings.py | 8 +- 2 files changed, 148 insertions(+), 140 deletions(-) rename tests/{pype => openpype}/lib/test_user_settings.py (95%) diff --git a/tests/igniter/test_bootstrap_repos.py b/tests/igniter/test_bootstrap_repos.py index 6c70380ab6..363efb815c 100644 --- a/tests/igniter/test_bootstrap_repos.py +++ b/tests/igniter/test_bootstrap_repos.py @@ -5,72 +5,75 @@ import sys from collections import namedtuple from pathlib import Path from zipfile import ZipFile +from uuid import uuid4 import appdirs import pytest from igniter.bootstrap_repos import BootstrapRepos -from igniter.bootstrap_repos import PypeVersion -from pype.lib import OpenPypeSettingsRegistry +from igniter.bootstrap_repos import OpenPypeVersion +from igniter.user_settings import OpenPypeSettingsRegistry @pytest.fixture def fix_bootstrap(tmp_path, pytestconfig): + """This will fix BoostrapRepos with temp paths.""" bs = BootstrapRepos() bs.live_repo_dir = pytestconfig.rootpath / 'repos' bs.data_dir = tmp_path return bs -def test_pype_version(): - v1 = PypeVersion(1, 2, 3) +def test_openpype_version(): + """Test determination of OpenPype versions.""" + v1 = OpenPypeVersion(1, 2, 3) assert str(v1) == "1.2.3" - v2 = PypeVersion(1, 2, 3, client="x") + v2 = OpenPypeVersion(1, 2, 3, client="x") assert str(v2) == "1.2.3-x" assert v1 < v2 - v3 = PypeVersion(1, 2, 3, variant="staging") + v3 = OpenPypeVersion(1, 2, 3, variant="staging") assert str(v3) == "1.2.3-staging" - v4 = PypeVersion(1, 2, 3, variant="staging", client="client") + v4 = OpenPypeVersion(1, 2, 3, variant="staging", client="client") assert str(v4) == "1.2.3-client-staging" assert v3 < v4 assert v1 < v4 - v5 = PypeVersion(1, 2, 3, variant="foo", client="x") + v5 = OpenPypeVersion(1, 2, 3, variant="foo", client="x") assert str(v5) == "1.2.3-x" assert v4 < v5 - v6 = PypeVersion(1, 2, 3, variant="foo") + v6 = OpenPypeVersion(1, 2, 3, variant="foo") assert str(v6) == "1.2.3" - v7 = PypeVersion(2, 0, 0) + v7 = OpenPypeVersion(2, 0, 0) assert v1 < v7 - v8 = PypeVersion(0, 1, 5) + v8 = OpenPypeVersion(0, 1, 5) assert v8 < v7 - v9 = PypeVersion(1, 2, 4) + v9 = OpenPypeVersion(1, 2, 4) assert v9 > v1 - v10 = PypeVersion(1, 2, 2) + v10 = OpenPypeVersion(1, 2, 2) assert v10 < v1 - v11 = PypeVersion(1, 2, 3, path=Path("/foo/bar")) + v11 = OpenPypeVersion(1, 2, 3, path=Path("/foo/bar")) assert v10 < v11 assert v5 == v2 sort_versions = [ - PypeVersion(3, 2, 1), - PypeVersion(1, 2, 3), - PypeVersion(0, 0, 1), - PypeVersion(4, 8, 10), - PypeVersion(4, 8, 20), - PypeVersion(4, 8, 9), - PypeVersion(1, 2, 3, variant="staging"), - PypeVersion(1, 2, 3, client="client") + OpenPypeVersion(3, 2, 1), + OpenPypeVersion(1, 2, 3), + OpenPypeVersion(0, 0, 1), + OpenPypeVersion(4, 8, 10), + OpenPypeVersion(4, 8, 20), + OpenPypeVersion(4, 8, 9), + OpenPypeVersion(1, 2, 3, variant="staging"), + OpenPypeVersion(1, 2, 3, client="client") ] res = sorted(sort_versions) @@ -88,25 +91,22 @@ def test_pype_version(): "5.6.3", "5.6.3-staging" ] - res_versions = [] - for v in str_versions: - res_versions.append(PypeVersion(version=v)) - + res_versions = [OpenPypeVersion(version=v) for v in str_versions] sorted_res_versions = sorted(res_versions) assert str(sorted_res_versions[0]) == str_versions[0] assert str(sorted_res_versions[-1]) == str_versions[5] with pytest.raises(ValueError): - _ = PypeVersion() + _ = OpenPypeVersion() with pytest.raises(ValueError): - _ = PypeVersion(major=1) + _ = OpenPypeVersion(major=1) with pytest.raises(ValueError): - _ = PypeVersion(version="booobaa") + _ = OpenPypeVersion(version="booobaa") - v11 = PypeVersion(version="4.6.7-client-staging") + v11 = OpenPypeVersion(version="4.6.7-client-staging") assert v11.major == 4 assert v11.minor == 6 assert v11.subversion == 7 @@ -115,15 +115,15 @@ def test_pype_version(): def test_get_main_version(): - ver = PypeVersion(1, 2, 3, variant="staging", client="foo") + ver = OpenPypeVersion(1, 2, 3, variant="staging", client="foo") assert ver.get_main_version() == "1.2.3" def test_get_version_path_from_list(): versions = [ - PypeVersion(1, 2, 3, path=Path('/foo/bar')), - PypeVersion(3, 4, 5, variant="staging", path=Path("/bar/baz")), - PypeVersion(6, 7, 8, client="x", path=Path("boo/goo")) + OpenPypeVersion(1, 2, 3, path=Path('/foo/bar')), + OpenPypeVersion(3, 4, 5, variant="staging", path=Path("/bar/baz")), + OpenPypeVersion(6, 7, 8, client="x", path=Path("boo/goo")) ] path = BootstrapRepos.get_version_path_from_list( "3.4.5-staging", versions) @@ -131,7 +131,7 @@ def test_get_version_path_from_list(): assert path == Path("/bar/baz") -def test_search_string_for_pype_version(printer): +def test_search_string_for_openpype_version(printer): strings = [ ("3.0.1", True), ("foo-3.0", False), @@ -142,106 +142,111 @@ def test_search_string_for_pype_version(printer): ] for ver_string in strings: printer(f"testing {ver_string[0]} should be {ver_string[1]}") - assert PypeVersion.version_in_str(ver_string[0])[0] == ver_string[1] + assert OpenPypeVersion.version_in_str(ver_string[0])[0] == ver_string[1] @pytest.mark.slow -def test_install_live_repos(fix_bootstrap, printer): - pype_version = fix_bootstrap.create_version_from_live_code() +def test_install_live_repos(fix_bootstrap, printer, monkeypatch, pytestconfig): + monkeypatch.setenv("OPENPYPE_ROOT", pytestconfig.rootpath.as_posix()) + monkeypatch.setenv("OPENPYPE_DATABASE_NAME", str(uuid4())) + openpype_version = fix_bootstrap.create_version_from_live_code() sep = os.path.sep expected_paths = [ - f"{pype_version.path}{sep}repos{sep}avalon-core", - f"{pype_version.path}{sep}repos{sep}avalon-unreal-integration", - f"{pype_version.path}" + f"{openpype_version.path}{sep}repos{sep}avalon-core", + f"{openpype_version.path}{sep}repos{sep}avalon-unreal-integration", + f"{openpype_version.path}" ] printer("testing zip creation") - assert os.path.exists(pype_version.path), "zip archive was not created" - fix_bootstrap.add_paths_from_archive(pype_version.path) + assert os.path.exists(openpype_version.path), "zip archive was not created" + fix_bootstrap.add_paths_from_archive(openpype_version.path) for ep in expected_paths: assert ep in sys.path, f"{ep} not set correctly" - printer("testing pype imported") - del sys.modules["pype"] - import pype # noqa: F401 + printer("testing openpype imported") + try: + del sys.modules["openpype"] + except KeyError: + # wasn't imported before + pass + import openpype # noqa: F401 - # test if pype is imported from specific location in zip - assert "pype" in sys.modules.keys(), "Pype not imported" - assert sys.modules["pype"].__file__ == \ - f"{pype_version.path}{sep}pype{sep}__init__.py" + # test if openpype is imported from specific location in zip + assert "openpype" in sys.modules.keys(), "OpenPype not imported" + assert sys.modules["openpype"].__file__ == \ + f"{openpype_version.path}{sep}openpype{sep}__init__.py" -def test_find_pype(fix_bootstrap, tmp_path_factory, monkeypatch, printer): - - test_pype = namedtuple("Pype", "prefix version suffix type valid") +def test_find_openpype(fix_bootstrap, tmp_path_factory, monkeypatch, printer): + test_openpype = namedtuple("OpenPype", "prefix version suffix type valid") test_versions_1 = [ - test_pype(prefix="foo-v", version="5.5.1", - suffix=".zip", type="zip", valid=False), - test_pype(prefix="bar-v", version="5.5.2-client", - suffix=".zip", type="zip", valid=True), - test_pype(prefix="baz-v", version="5.5.3-client-strange", - suffix=".zip", type="zip", valid=True), - test_pype(prefix="bum-v", version="5.5.4-staging", - suffix=".zip", type="zip", valid=True), - test_pype(prefix="zum-v", version="5.5.5-client-staging", - suffix=".zip", type="zip", valid=True), - test_pype(prefix="fam-v", version="5.6.3", - suffix=".zip", type="zip", valid=True), - test_pype(prefix="foo-v", version="5.6.3-staging", - suffix=".zip", type="zip", valid=True), - test_pype(prefix="fim-v", version="5.6.3", - suffix=".zip", type="zip", valid=False), - test_pype(prefix="foo-v", version="5.6.4", - suffix=".txt", type="txt", valid=False), - test_pype(prefix="foo-v", version="5.7.1", - suffix="", type="dir", valid=False), + test_openpype(prefix="foo-v", version="5.5.1", + suffix=".zip", type="zip", valid=False), + test_openpype(prefix="bar-v", version="5.5.2-client", + suffix=".zip", type="zip", valid=True), + test_openpype(prefix="baz-v", version="5.5.3-client-strange", + suffix=".zip", type="zip", valid=True), + test_openpype(prefix="bum-v", version="5.5.4-staging", + suffix=".zip", type="zip", valid=True), + test_openpype(prefix="zum-v", version="5.5.5-client-staging", + suffix=".zip", type="zip", valid=True), + test_openpype(prefix="fam-v", version="5.6.3", + suffix=".zip", type="zip", valid=True), + test_openpype(prefix="foo-v", version="5.6.3-staging", + suffix=".zip", type="zip", valid=True), + test_openpype(prefix="fim-v", version="5.6.3", + suffix=".zip", type="zip", valid=False), + test_openpype(prefix="foo-v", version="5.6.4", + suffix=".txt", type="txt", valid=False), + test_openpype(prefix="foo-v", version="5.7.1", + suffix="", type="dir", valid=False), ] test_versions_2 = [ - test_pype(prefix="foo-v", version="10.0.0", - suffix=".txt", type="txt", valid=False), - test_pype(prefix="lom-v", version="7.2.6", - suffix=".zip", type="zip", valid=True), - test_pype(prefix="bom-v", version="7.2.7-client", - suffix=".zip", type="zip", valid=True), - test_pype(prefix="woo-v", version="7.2.8-client-strange", - suffix=".zip", type="zip", valid=True), - test_pype(prefix="loo-v", version="7.2.10-client-staging", - suffix=".zip", type="zip", valid=True), - test_pype(prefix="kok-v", version="7.0.1", - suffix=".zip", type="zip", valid=True) + test_openpype(prefix="foo-v", version="10.0.0", + suffix=".txt", type="txt", valid=False), + test_openpype(prefix="lom-v", version="7.2.6", + suffix=".zip", type="zip", valid=True), + test_openpype(prefix="bom-v", version="7.2.7-client", + suffix=".zip", type="zip", valid=True), + test_openpype(prefix="woo-v", version="7.2.8-client-strange", + suffix=".zip", type="zip", valid=True), + test_openpype(prefix="loo-v", version="7.2.10-client-staging", + suffix=".zip", type="zip", valid=True), + test_openpype(prefix="kok-v", version="7.0.1", + suffix=".zip", type="zip", valid=True) ] test_versions_3 = [ - test_pype(prefix="foo-v", version="3.0.0", - suffix=".zip", type="zip", valid=True), - test_pype(prefix="goo-v", version="3.0.1", - suffix=".zip", type="zip", valid=True), - test_pype(prefix="hoo-v", version="4.1.0", - suffix=".zip", type="zip", valid=True), - test_pype(prefix="foo-v", version="4.1.2", - suffix=".zip", type="zip", valid=True), - test_pype(prefix="foo-v", version="3.0.1-client", - suffix=".zip", type="zip", valid=True), - test_pype(prefix="foo-v", version="3.0.1-client-strange", - suffix=".zip", type="zip", valid=True), - test_pype(prefix="foo-v", version="3.0.1-staging", - suffix=".zip", type="zip", valid=True), - test_pype(prefix="foo-v", version="3.0.1-client-staging", - suffix=".zip", type="zip", valid=True), - test_pype(prefix="foo-v", version="3.2.0", - suffix=".zip", type="zip", valid=True) + test_openpype(prefix="foo-v", version="3.0.0", + suffix=".zip", type="zip", valid=True), + test_openpype(prefix="goo-v", version="3.0.1", + suffix=".zip", type="zip", valid=True), + test_openpype(prefix="hoo-v", version="4.1.0", + suffix=".zip", type="zip", valid=True), + test_openpype(prefix="foo-v", version="4.1.2", + suffix=".zip", type="zip", valid=True), + test_openpype(prefix="foo-v", version="3.0.1-client", + suffix=".zip", type="zip", valid=True), + test_openpype(prefix="foo-v", version="3.0.1-client-strange", + suffix=".zip", type="zip", valid=True), + test_openpype(prefix="foo-v", version="3.0.1-staging", + suffix=".zip", type="zip", valid=True), + test_openpype(prefix="foo-v", version="3.0.1-client-staging", + suffix=".zip", type="zip", valid=True), + test_openpype(prefix="foo-v", version="3.2.0", + suffix=".zip", type="zip", valid=True) ] test_versions_4 = [ - test_pype(prefix="foo-v", version="10.0.0", - suffix="", type="dir", valid=True), - test_pype(prefix="lom-v", version="11.2.6", - suffix=".zip", type="dir", valid=False), - test_pype(prefix="bom-v", version="7.2.7-client", - suffix=".zip", type="zip", valid=True), - test_pype(prefix="woo-v", version="7.2.8-client-strange", - suffix=".zip", type="txt", valid=False) + test_openpype(prefix="foo-v", version="10.0.0", + suffix="", type="dir", valid=True), + test_openpype(prefix="lom-v", version="11.2.6", + suffix=".zip", type="dir", valid=False), + test_openpype(prefix="bom-v", version="7.2.7-client", + suffix=".zip", type="zip", valid=True), + test_openpype(prefix="woo-v", version="7.2.8-client-strange", + suffix=".zip", type="txt", valid=False) ] def _create_invalid_zip(path: Path): @@ -251,7 +256,7 @@ def test_find_pype(fix_bootstrap, tmp_path_factory, monkeypatch, printer): def _create_valid_zip(path: Path, version: str): with ZipFile(path, "w") as zf: zf.writestr( - "pype/version.py", f"__version__ = '{version}'\n\n") + "openpype/version.py", f"__version__ = '{version}'\n\n") def _create_invalid_dir(path: Path): path.mkdir(parents=True, exist_ok=True) @@ -259,9 +264,9 @@ def test_find_pype(fix_bootstrap, tmp_path_factory, monkeypatch, printer): fp.write("invalid") def _create_valid_dir(path: Path, version: str): - pype_path = path / "pype" - version_path = pype_path / "version.py" - pype_path.mkdir(parents=True, exist_ok=True) + openpype_path = path / "openpype" + version_path = openpype_path / "version.py" + openpype_path.mkdir(parents=True, exist_ok=True) with open(version_path, "w") as fp: fp.write(f"__version__ = '{version}'\n\n") @@ -283,15 +288,15 @@ def test_find_pype(fix_bootstrap, tmp_path_factory, monkeypatch, printer): with open(test_path, "w") as fp: fp.write("foo") - # in PYPE_PATH + # in OPENPYPE_PATH e_path = tmp_path_factory.mktemp("environ") # create files and directories for test for test_file in test_versions_1: _build_test_item(e_path, test_file) - # in pypePath registry - p_path = tmp_path_factory.mktemp("pypePath") + # in openPypePath registry + p_path = tmp_path_factory.mktemp("openPypePath") for test_file in test_versions_2: _build_test_item(p_path, test_file) @@ -310,10 +315,10 @@ def test_find_pype(fix_bootstrap, tmp_path_factory, monkeypatch, printer): for test_file in test_versions_4: _build_test_item(dir_path, test_file) - printer("testing finding Pype in given path ...") - result = fix_bootstrap.find_pype(g_path, include_zips=True) + printer("testing finding OpenPype in given path ...") + result = fix_bootstrap.find_openpype(g_path, include_zips=True) # we should have results as file were created - assert result is not None, "no Pype version found" + assert result is not None, "no OpenPype version found" # latest item in `result` should be latest version found. expected_path = Path( g_path / "{}{}{}".format( @@ -323,13 +328,13 @@ def test_find_pype(fix_bootstrap, tmp_path_factory, monkeypatch, printer): ) ) assert result, "nothing found" - assert result[-1].path == expected_path, "not a latest version of Pype 3" + assert result[-1].path == expected_path, "not a latest version of OpenPype 3" - monkeypatch.setenv("PYPE_PATH", e_path.as_posix()) + monkeypatch.setenv("OPENPYPE_PATH", e_path.as_posix()) - result = fix_bootstrap.find_pype(include_zips=True) + result = fix_bootstrap.find_openpype(include_zips=True) # we should have results as file were created - assert result is not None, "no Pype version found" + assert result is not None, "no OpenPype version found" # latest item in `result` should be latest version found. expected_path = Path( e_path / "{}{}{}".format( @@ -339,21 +344,22 @@ def test_find_pype(fix_bootstrap, tmp_path_factory, monkeypatch, printer): ) ) assert result, "nothing found" - assert result[-1].path == expected_path, "not a latest version of Pype 1" + assert result[-1].path == expected_path, "not a latest version of OpenPype 1" - monkeypatch.delenv("PYPE_PATH", raising=False) + monkeypatch.delenv("OPENPYPE_PATH", raising=False) # mock appdirs user_data_dir def mock_user_data_dir(*args, **kwargs): + """Mock local app data dir.""" return d_path.as_posix() monkeypatch.setattr(appdirs, "user_data_dir", mock_user_data_dir) fix_bootstrap.registry = OpenPypeSettingsRegistry() - fix_bootstrap.registry.set_item("pypePath", d_path.as_posix()) + fix_bootstrap.registry.set_item("openPypePath", d_path.as_posix()) - result = fix_bootstrap.find_pype(include_zips=True) + result = fix_bootstrap.find_openpype(include_zips=True) # we should have results as file were created - assert result is not None, "no Pype version found" + assert result is not None, "no OpenPype version found" # latest item in `result` should be latest version found. expected_path = Path( d_path / "{}{}{}".format( @@ -363,10 +369,10 @@ def test_find_pype(fix_bootstrap, tmp_path_factory, monkeypatch, printer): ) ) assert result, "nothing found" - assert result[-1].path == expected_path, "not a latest version of Pype 2" + assert result[-1].path == expected_path, "not a latest version of OpenPype 2" - result = fix_bootstrap.find_pype(e_path, include_zips=True) - assert result is not None, "no Pype version found" + result = fix_bootstrap.find_openpype(e_path, include_zips=True) + assert result is not None, "no OpenPype version found" expected_path = Path( e_path / "{}{}{}".format( test_versions_1[5].prefix, @@ -374,10 +380,10 @@ def test_find_pype(fix_bootstrap, tmp_path_factory, monkeypatch, printer): test_versions_1[5].suffix ) ) - assert result[-1].path == expected_path, "not a latest version of Pype 1" + assert result[-1].path == expected_path, "not a latest version of OpenPype 1" - result = fix_bootstrap.find_pype(dir_path, include_zips=True) - assert result is not None, "no Pype versions found" + result = fix_bootstrap.find_openpype(dir_path, include_zips=True) + assert result is not None, "no OpenPype versions found" expected_path = Path( dir_path / "{}{}{}".format( test_versions_4[0].prefix, @@ -385,4 +391,4 @@ def test_find_pype(fix_bootstrap, tmp_path_factory, monkeypatch, printer): test_versions_4[0].suffix ) ) - assert result[-1].path == expected_path, "not a latest version of Pype 4" + assert result[-1].path == expected_path, "not a latest version of OpenPype 4" diff --git a/tests/pype/lib/test_user_settings.py b/tests/openpype/lib/test_user_settings.py similarity index 95% rename from tests/pype/lib/test_user_settings.py rename to tests/openpype/lib/test_user_settings.py index 02342abbc9..2c58e1f35a 100644 --- a/tests/pype/lib/test_user_settings.py +++ b/tests/openpype/lib/test_user_settings.py @@ -1,5 +1,7 @@ +# -*- coding: utf-8 -*- +"""Test suite for User Settings.""" import pytest -from pype.lib import ( +from igniter.user_settings import ( IniSettingRegistry, JSONSettingRegistry, OpenPypeSecureRegistry @@ -9,9 +11,9 @@ import configparser @pytest.fixture -def secure_registry(tmpdir): +def secure_registry(): name = "pypetest_{}".format(str(uuid4())) - r = OpenPypeSecureRegistry(name, tmpdir) + r = OpenPypeSecureRegistry(name) yield r From fdfb0064aa1ef6550c8313bead55bc7d95b8dfe9 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Thu, 13 May 2021 14:58:19 +0200 Subject: [PATCH 2/5] fix hound --- tests/igniter/test_bootstrap_repos.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/tests/igniter/test_bootstrap_repos.py b/tests/igniter/test_bootstrap_repos.py index 363efb815c..54950c546e 100644 --- a/tests/igniter/test_bootstrap_repos.py +++ b/tests/igniter/test_bootstrap_repos.py @@ -142,7 +142,8 @@ def test_search_string_for_openpype_version(printer): ] for ver_string in strings: printer(f"testing {ver_string[0]} should be {ver_string[1]}") - assert OpenPypeVersion.version_in_str(ver_string[0])[0] == ver_string[1] + assert OpenPypeVersion.version_in_str(ver_string[0])[0] == \ + ver_string[1] @pytest.mark.slow @@ -173,7 +174,7 @@ def test_install_live_repos(fix_bootstrap, printer, monkeypatch, pytestconfig): # test if openpype is imported from specific location in zip assert "openpype" in sys.modules.keys(), "OpenPype not imported" assert sys.modules["openpype"].__file__ == \ - f"{openpype_version.path}{sep}openpype{sep}__init__.py" + f"{openpype_version.path}{sep}openpype{sep}__init__.py" def test_find_openpype(fix_bootstrap, tmp_path_factory, monkeypatch, printer): @@ -328,7 +329,8 @@ def test_find_openpype(fix_bootstrap, tmp_path_factory, monkeypatch, printer): ) ) assert result, "nothing found" - assert result[-1].path == expected_path, "not a latest version of OpenPype 3" + assert result[-1].path == expected_path, ("not a latest version of " + "OpenPype 3") monkeypatch.setenv("OPENPYPE_PATH", e_path.as_posix()) @@ -344,7 +346,8 @@ def test_find_openpype(fix_bootstrap, tmp_path_factory, monkeypatch, printer): ) ) assert result, "nothing found" - assert result[-1].path == expected_path, "not a latest version of OpenPype 1" + assert result[-1].path == expected_path, ("not a latest version of " + "OpenPype 1") monkeypatch.delenv("OPENPYPE_PATH", raising=False) @@ -369,7 +372,8 @@ def test_find_openpype(fix_bootstrap, tmp_path_factory, monkeypatch, printer): ) ) assert result, "nothing found" - assert result[-1].path == expected_path, "not a latest version of OpenPype 2" + assert result[-1].path == expected_path, ("not a latest version of " + "OpenPype 2") result = fix_bootstrap.find_openpype(e_path, include_zips=True) assert result is not None, "no OpenPype version found" @@ -380,7 +384,8 @@ def test_find_openpype(fix_bootstrap, tmp_path_factory, monkeypatch, printer): test_versions_1[5].suffix ) ) - assert result[-1].path == expected_path, "not a latest version of OpenPype 1" + assert result[-1].path == expected_path, ("not a latest version of " + "OpenPype 1") result = fix_bootstrap.find_openpype(dir_path, include_zips=True) assert result is not None, "no OpenPype versions found" @@ -391,4 +396,5 @@ def test_find_openpype(fix_bootstrap, tmp_path_factory, monkeypatch, printer): test_versions_4[0].suffix ) ) - assert result[-1].path == expected_path, "not a latest version of OpenPype 4" + assert result[-1].path == expected_path, ("not a latest version of " + "OpenPype 4") From c6bd91d7a474d7c1e377f6d271c4a1d70a2fbbe9 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Thu, 13 May 2021 15:30:12 +0200 Subject: [PATCH 3/5] fix test script on linux --- tools/run_tests.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/run_tests.sh b/tools/run_tests.sh index 5488be9430..3620ebc0e5 100755 --- a/tools/run_tests.sh +++ b/tools/run_tests.sh @@ -122,5 +122,4 @@ main () { PYTHONPATH=$original_pythonpath } - - +main From 876efd0bc4b41010d5c5395dc58fa9d2bb852429 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 13 May 2021 16:38:53 +0200 Subject: [PATCH 4/5] AE - added documentation for Settings --- website/docs/admin_hosts_aftereffects.md | 39 ++++++++++++++++++ .../admin_hosts_aftereffects_settings.png | Bin 0 -> 31766 bytes website/sidebars.js | 3 +- 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 website/docs/admin_hosts_aftereffects.md create mode 100644 website/docs/assets/admin_hosts_aftereffects_settings.png diff --git a/website/docs/admin_hosts_aftereffects.md b/website/docs/admin_hosts_aftereffects.md new file mode 100644 index 0000000000..dc43820465 --- /dev/null +++ b/website/docs/admin_hosts_aftereffects.md @@ -0,0 +1,39 @@ +--- +id: admin_hosts_aftereffects +title: AfterEffects Settings +sidebar_label: AfterEffects +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +## AfterEffects settings + +There is a couple of settings that could configure publishing process for **AfterEffects**. +All of them are Project based, eg. each project could have different configuration. + +Location: Settings > Project > AfterEffects + +![Harmony Project Settings](assets/admin_hosts_aftereffects_settings.png) + +## Publish plugins + +### Validate Scene Settings + +#### Skip Resolution Check for Tasks + +Set regex pattern(s) to look for in a Task name to skip resolution check against values from DB. + +#### Skip Timeline Check for Tasks + +Set regex pattern(s) to look for in a Task name to skip `frameStart`, `frameEnd` check against values from DB. + +### AfterEffects Submit to Deadline + +* `Use Published scene` - Set to True (green) when Deadline should take published scene as a source instead of uploaded local one. +* `Priority` - priority of job on farm +* `Primary Pool` - here is list of pool fetched from server you can select from. +* `Secondary Pool` +* `Frames Per Task` - number of sequence division between individual tasks (chunks) +making one job on farm. + diff --git a/website/docs/assets/admin_hosts_aftereffects_settings.png b/website/docs/assets/admin_hosts_aftereffects_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..9b879585f8c93026ed7389935107834d2aa3cae8 GIT binary patch literal 31766 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 z�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 Date: Thu, 13 May 2021 16:40:46 +0200 Subject: [PATCH 5/5] AE - added new schemas for settings Moved filtering from __init__ to Validator where it has more sense Added defaults --- openpype/hosts/aftereffects/api/__init__.py | 34 ------- .../publish/validate_scene_settings.py | 22 ++++- .../project_settings/aftereffects.json | 18 ++++ .../schemas/projects_schema/schema_main.json | 4 + .../schema_project_aftereffects.json | 90 +++++++++++++++++++ 5 files changed, 131 insertions(+), 37 deletions(-) create mode 100644 openpype/settings/defaults/project_settings/aftereffects.json create mode 100644 openpype/settings/entities/schemas/projects_schema/schema_project_aftereffects.json diff --git a/openpype/hosts/aftereffects/api/__init__.py b/openpype/hosts/aftereffects/api/__init__.py index e914c26435..5f6a64a6d0 100644 --- a/openpype/hosts/aftereffects/api/__init__.py +++ b/openpype/hosts/aftereffects/api/__init__.py @@ -112,38 +112,4 @@ def get_asset_settings(): "duration": duration } - try: - # temporary, in pype3 replace with api.get_current_project_settings - skip_resolution_check = ( - api.get_current_project_settings() - ["plugins"] - ["aftereffects"] - ["publish"] - ["ValidateSceneSettings"] - ["skip_resolution_check"] - ) - skip_timelines_check = ( - api.get_current_project_settings() - ["plugins"] - ["aftereffects"] - ["publish"] - ["ValidateSceneSettings"] - ["skip_timelines_check"] - ) - except KeyError: - skip_resolution_check = ['*'] - skip_timelines_check = ['*'] - - if os.getenv('AVALON_TASK') in skip_resolution_check or \ - '*' in skip_timelines_check: - scene_data.pop("resolutionWidth") - scene_data.pop("resolutionHeight") - - if entity_type in skip_timelines_check or '*' in skip_timelines_check: - scene_data.pop('fps', None) - scene_data.pop('frameStart', None) - scene_data.pop('frameEnd', None) - scene_data.pop('handleStart', None) - scene_data.pop('handleEnd', None) - return scene_data diff --git a/openpype/hosts/aftereffects/plugins/publish/validate_scene_settings.py b/openpype/hosts/aftereffects/plugins/publish/validate_scene_settings.py index cc7db3141f..5301a2f3ea 100644 --- a/openpype/hosts/aftereffects/plugins/publish/validate_scene_settings.py +++ b/openpype/hosts/aftereffects/plugins/publish/validate_scene_settings.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- """Validate scene settings.""" import os +import re import pyblish.api @@ -56,13 +57,26 @@ class ValidateSceneSettings(pyblish.api.InstancePlugin): hosts = ["aftereffects"] optional = True - skip_timelines_check = ["*"] # * >> skip for all - skip_resolution_check = ["*"] + skip_timelines_check = [".*"] # * >> skip for all + skip_resolution_check = [".*"] def process(self, instance): """Plugin entry point.""" expected_settings = api.get_asset_settings() - self.log.info("expected_settings::{}".format(expected_settings)) + self.log.info("config from DB::{}".format(expected_settings)) + + if any(re.search(pattern, os.getenv('AVALON_TASK')) + for pattern in self.skip_resolution_check): + expected_settings.pop("resolutionWidth") + expected_settings.pop("resolutionHeight") + + if any(re.search(pattern, os.getenv('AVALON_TASK')) + for pattern in self.skip_timelines_check): + expected_settings.pop('fps', None) + expected_settings.pop('frameStart', None) + expected_settings.pop('frameEnd', None) + expected_settings.pop('handleStart', None) + expected_settings.pop('handleEnd', None) # handle case where ftrack uses only two decimal places # 23.976023976023978 vs. 23.98 @@ -76,6 +90,8 @@ class ValidateSceneSettings(pyblish.api.InstancePlugin): duration = instance.data.get("frameEndHandle") - \ instance.data.get("frameStartHandle") + 1 + self.log.debug("filtered config::{}".format(expected_settings)) + current_settings = { "fps": fps, "frameStartHandle": instance.data.get("frameStartHandle"), diff --git a/openpype/settings/defaults/project_settings/aftereffects.json b/openpype/settings/defaults/project_settings/aftereffects.json new file mode 100644 index 0000000000..f54dbb9612 --- /dev/null +++ b/openpype/settings/defaults/project_settings/aftereffects.json @@ -0,0 +1,18 @@ +{ + "publish": { + "ValidateSceneSettings": { + "enabled": true, + "optional": true, + "active": true, + "skip_resolution_check": [".*"], + "skip_timelines_check": [".*"] + }, + "AfterEffectsSubmitDeadline": { + "use_published": true, + "priority": 50, + "primary_pool": "", + "secondary_pool": "", + "chunk_size": 1000000 + } + } +} \ No newline at end of file diff --git a/openpype/settings/entities/schemas/projects_schema/schema_main.json b/openpype/settings/entities/schemas/projects_schema/schema_main.json index 6bc158aa60..b4666b302a 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_main.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_main.json @@ -78,6 +78,10 @@ "type": "schema", "name": "schema_project_hiero" }, + { + "type": "schema", + "name": "schema_project_aftereffects" + }, { "type": "schema", "name": "schema_project_harmony" diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_aftereffects.json b/openpype/settings/entities/schemas/projects_schema/schema_project_aftereffects.json new file mode 100644 index 0000000000..63bf9274a3 --- /dev/null +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_aftereffects.json @@ -0,0 +1,90 @@ +{ + "type": "dict", + "collapsible": true, + "key": "aftereffects", + "label": "AfterEffects", + "is_file": true, + "children": [ + { + "type": "dict", + "collapsible": true, + "key": "publish", + "label": "Publish plugins", + "children": [ + { + "type": "dict", + "collapsible": true, + "key": "ValidateSceneSettings", + "label": "Validate Scene Settings", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + }, + { + "type": "label", + "label": "Validate if FPS and Resolution match shot data" + }, + { + "type": "list", + "key": "skip_resolution_check", + "object_type": "text", + "label": "Skip Resolution Check for Tasks" + }, + { + "type": "list", + "key": "skip_timelines_check", + "object_type": "text", + "label": "Skip Timeline Check for Tasks" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "AfterEffectsSubmitDeadline", + "label": "AfterEffects Submit to Deadline", + "children": [ + { + "type": "boolean", + "key": "use_published", + "label": "Use Published scene" + }, + { + "type": "number", + "key": "priority", + "label": "Priority" + }, + { + "type": "text", + "key": "primary_pool", + "label": "Primary Pool" + }, + { + "type": "text", + "key": "secondary_pool", + "label": "Secondary Pool" + }, + { + "type": "number", + "key": "chunk_size", + "label": "Frames Per Task" + } + ] + } + ] + } + ] +}