mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 12:54:40 +01:00
change version comparsion, handling of venv and startup
This commit is contained in:
parent
2d3bb6a4d9
commit
10686e06c5
13 changed files with 1295 additions and 114 deletions
|
|
@ -14,8 +14,7 @@ from zipfile import ZipFile, BadZipFile
|
|||
from appdirs import user_data_dir
|
||||
from speedcopy import copyfile
|
||||
|
||||
from pype.lib import PypeSettingsRegistry
|
||||
from pype.version import __version__
|
||||
from .user_settings import PypeSettingsRegistry
|
||||
from .tools import load_environments
|
||||
|
||||
|
||||
|
|
@ -24,23 +23,23 @@ class PypeVersion:
|
|||
"""Class for storing information about Pype version.
|
||||
|
||||
Attributes:
|
||||
major (int): [1].2.3-variant-client
|
||||
minor (int): 1.[2].3-variant-client
|
||||
subversion (int): 1.2.[3]-variant-client
|
||||
variant (str): 1.2.3-[variant]-client
|
||||
client (str): 1.2.3-variant-[client]
|
||||
major (int): [1].2.3-client-variant
|
||||
minor (int): 1.[2].3-client-variant
|
||||
subversion (int): 1.2.[3]-client-variant
|
||||
client (str): 1.2.3-[client]-variant
|
||||
variant (str): 1.2.3-client-[variant]
|
||||
path (str): path to Pype
|
||||
|
||||
"""
|
||||
major = 0
|
||||
minor = 0
|
||||
subversion = 0
|
||||
variant = "production"
|
||||
variant = ""
|
||||
client = None
|
||||
path = None
|
||||
|
||||
_version_regex = re.compile(
|
||||
r"(?P<major>\d+)\.(?P<minor>\d+)\.(?P<sub>\d+)(-?((?P<variant>staging)|(?P<client>.+))(-(?P<cli>.+))?)?") # noqa: E501
|
||||
r"(?P<major>\d+)\.(?P<minor>\d+)\.(?P<sub>\d+)(-(?P<var1>staging)|-(?P<client>.+)(-(?P<var2>staging)))?") # noqa: E501
|
||||
|
||||
@property
|
||||
def version(self):
|
||||
|
|
@ -58,12 +57,12 @@ class PypeVersion:
|
|||
|
||||
def __init__(self, major: int = None, minor: int = None,
|
||||
subversion: int = None, version: str = None,
|
||||
variant: str = "production", client: str = None,
|
||||
variant: str = "", client: str = None,
|
||||
path: Path = None):
|
||||
self.path = path
|
||||
|
||||
if (
|
||||
major is None or minor is None or subversion is None
|
||||
major is None or minor is None or subversion is None
|
||||
) and version is None:
|
||||
raise ValueError("Need version specified in some way.")
|
||||
if version:
|
||||
|
|
@ -85,12 +84,13 @@ class PypeVersion:
|
|||
|
||||
def _compose_version(self):
|
||||
version = "{}.{}.{}".format(self.major, self.minor, self.subversion)
|
||||
if self.variant == "staging":
|
||||
version = "{}-{}".format(version, self.variant)
|
||||
|
||||
if self.client:
|
||||
version = "{}-{}".format(version, self.client)
|
||||
|
||||
if self.variant == "staging":
|
||||
version = "{}-{}".format(version, self.variant)
|
||||
|
||||
return version
|
||||
|
||||
@classmethod
|
||||
|
|
@ -101,10 +101,10 @@ class PypeVersion:
|
|||
"Cannot parse version string: {}".format(version_string))
|
||||
|
||||
variant = None
|
||||
if m.group("variant") == "staging":
|
||||
if m.group("var1") == "staging" or m.group("var2") == "staging":
|
||||
variant = "staging"
|
||||
|
||||
client = m.group("client") or m.group("cli")
|
||||
client = m.group("client")
|
||||
|
||||
return (int(m.group("major")), int(m.group("minor")),
|
||||
int(m.group("sub")), variant, client)
|
||||
|
|
@ -125,26 +125,48 @@ class PypeVersion:
|
|||
return hash(self.version)
|
||||
|
||||
def __lt__(self, other):
|
||||
if self.major < other.major:
|
||||
if (self.major, self.minor, self.subversion) < \
|
||||
(other.major, other.minor, other.subversion):
|
||||
return True
|
||||
|
||||
if self.major <= other.major and self.minor < other.minor:
|
||||
return True
|
||||
if self.major <= other.major and self.minor <= other.minor and \
|
||||
self.subversion < other.subversion:
|
||||
# 1.2.3-staging < 1.2.3-client-staging
|
||||
if self.get_main_version() == other.get_main_version() and \
|
||||
not self.client and self.variant and \
|
||||
other.client and other.variant:
|
||||
return True
|
||||
|
||||
# Directory takes precedence over file
|
||||
if (
|
||||
self.path
|
||||
and other.path
|
||||
and other.path.is_dir()
|
||||
and self.path.is_file()
|
||||
):
|
||||
# 1.2.3 < 1.2.3-staging
|
||||
if self.get_main_version() == other.get_main_version() and \
|
||||
not self.client and self.variant and \
|
||||
not other.client and not other.variant:
|
||||
return True
|
||||
|
||||
return self.major == other.major and self.minor == other.minor and \
|
||||
self.subversion == other.subversion and self.variant == "staging"
|
||||
# 1.2.3 < 1.2.3-client
|
||||
if self.get_main_version() == other.get_main_version() and \
|
||||
not self.client and not self.variant and \
|
||||
other.client and not other.variant:
|
||||
return True
|
||||
|
||||
# 1.2.3 < 1.2.3-client-staging
|
||||
if self.get_main_version() == other.get_main_version() and \
|
||||
not self.client and not self.variant and other.client:
|
||||
return True
|
||||
|
||||
# 1.2.3-client-staging < 1.2.3-client
|
||||
if self.get_main_version() == other.get_main_version() and \
|
||||
self.client and self.variant and \
|
||||
other.client and not other.variant:
|
||||
return True
|
||||
|
||||
# prefer path over no path
|
||||
if self.version == other.version and \
|
||||
not self.path and other.path:
|
||||
return True
|
||||
|
||||
# prefer path with dir over path with file
|
||||
return self.version == other.version and self.path and \
|
||||
other.path and self.path.is_file() and \
|
||||
other.path.is_dir()
|
||||
|
||||
def is_staging(self) -> bool:
|
||||
"""Test if current version is staging one."""
|
||||
|
|
@ -252,7 +274,12 @@ class BootstrapRepos:
|
|||
@staticmethod
|
||||
def get_local_live_version() -> str:
|
||||
"""Get version of local Pype."""
|
||||
return __version__
|
||||
|
||||
version = {}
|
||||
path = Path(os.path.dirname(__file__)).parent / "pype" / "version.py"
|
||||
with open(path, "r") as fp:
|
||||
exec(fp.read(), version)
|
||||
return version["__version__"]
|
||||
|
||||
@staticmethod
|
||||
def get_version(repo_dir: Path) -> Union[str, None]:
|
||||
|
|
@ -494,6 +521,7 @@ class BootstrapRepos:
|
|||
def find_pype(
|
||||
self,
|
||||
pype_path: Path = None,
|
||||
staging: bool = False,
|
||||
include_zips: bool = False) -> Union[List[PypeVersion], None]:
|
||||
"""Get ordered dict of detected Pype version.
|
||||
|
||||
|
|
@ -505,6 +533,8 @@ class BootstrapRepos:
|
|||
|
||||
Args:
|
||||
pype_path (Path, optional): Try to find Pype on the given path.
|
||||
staging (bool, optional): Filter only staging version, skip them
|
||||
otherwise.
|
||||
include_zips (bool, optional): If set True it will try to find
|
||||
Pype in zip files in given directory.
|
||||
|
||||
|
|
@ -549,6 +579,7 @@ class BootstrapRepos:
|
|||
result = PypeVersion.version_in_str(name)
|
||||
|
||||
if result[0]:
|
||||
detected_version: PypeVersion
|
||||
detected_version = result[1]
|
||||
|
||||
if file.is_dir():
|
||||
|
|
@ -614,7 +645,11 @@ class BootstrapRepos:
|
|||
continue
|
||||
|
||||
detected_version.path = file
|
||||
_pype_versions.append(detected_version)
|
||||
if staging and detected_version.is_staging():
|
||||
_pype_versions.append(detected_version)
|
||||
|
||||
if not staging and not detected_version.is_staging():
|
||||
_pype_versions.append(detected_version)
|
||||
|
||||
return sorted(_pype_versions)
|
||||
|
||||
|
|
|
|||
413
igniter/splash.txt
Normal file
413
igniter/splash.txt
Normal file
|
|
@ -0,0 +1,413 @@
|
|||
|
||||
|
||||
|
||||
*
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.*
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*
|
||||
.*
|
||||
*
|
||||
|
||||
|
||||
|
||||
.
|
||||
*
|
||||
.*
|
||||
*
|
||||
.
|
||||
|
||||
.
|
||||
*
|
||||
.*
|
||||
.*
|
||||
.*
|
||||
*
|
||||
.
|
||||
.
|
||||
*
|
||||
.*
|
||||
.*
|
||||
.*
|
||||
*
|
||||
.
|
||||
_.
|
||||
/**
|
||||
\ *
|
||||
\*
|
||||
*
|
||||
*
|
||||
.
|
||||
__.
|
||||
---*
|
||||
\ \*
|
||||
\ *
|
||||
\*
|
||||
*
|
||||
.
|
||||
\___.
|
||||
/* *
|
||||
\ \ *
|
||||
\ \*
|
||||
\ *
|
||||
\*
|
||||
.
|
||||
|____.
|
||||
/* *
|
||||
\|\ *
|
||||
\ \ *
|
||||
\ \ *
|
||||
\ \*
|
||||
\/.
|
||||
_/_____.
|
||||
/* *
|
||||
/ \ *
|
||||
\ \ *
|
||||
\ \ *
|
||||
\ \__*
|
||||
\/__.
|
||||
__________.
|
||||
--*-- ___*
|
||||
\ \ \/_*
|
||||
\ \ __*
|
||||
\ \ \_*
|
||||
\ \____\*
|
||||
\/____/.
|
||||
\____________ .
|
||||
/* ___ \*
|
||||
\ \ \/_\ *
|
||||
\ \ _____*
|
||||
\ \ \___/*
|
||||
\ \____\ *
|
||||
\/____/ .
|
||||
|___________ .
|
||||
/* ___ \ *
|
||||
\|\ \/_\ \ *
|
||||
\ \ _____/ *
|
||||
\ \ \___/ *
|
||||
\ \____\ / *
|
||||
\/____/ \.
|
||||
_/__________ .
|
||||
/* ___ \ *
|
||||
/ \ \/_\ \ *
|
||||
\ \ _____/ *
|
||||
\ \ \___/ ---*
|
||||
\ \____\ / \__*
|
||||
\/____/ \/__.
|
||||
____________ .
|
||||
--*-- ___ \ *
|
||||
\ \ \/_\ \ *
|
||||
\ \ _____/ *
|
||||
\ \ \___/ ---- *
|
||||
\ \____\ / \____\*
|
||||
\/____/ \/____/.
|
||||
____________
|
||||
/\ ___ \ .
|
||||
\ \ \/_\ \ *
|
||||
\ \ _____/ *
|
||||
\ \ \___/ ---- *
|
||||
\ \____\ / \____\ .
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \ .
|
||||
\ \ _____/ *
|
||||
\ \ \___/ ---- *
|
||||
\ \____\ / \____\ .
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ .
|
||||
\ \ \___/ ---- *
|
||||
\ \____\ / \____\ .
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/
|
||||
\ \ \___/ ---- *
|
||||
\ \____\ / \____\
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/
|
||||
\ \ \___/ ---- .
|
||||
\ \____\ / \____\
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ _
|
||||
\ \ \___/ ----
|
||||
\ \____\ / \____\
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___
|
||||
\ \ \___/ ----
|
||||
\ \____\ / \____\
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___
|
||||
\ \ \___/ ---- \
|
||||
\ \____\ / \____\
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___
|
||||
\ \ \___/ ---- \
|
||||
\ \____\ / \____\ \
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___
|
||||
\ \ \___/ ---- \
|
||||
\ \____\ / \____\ __\
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___
|
||||
\ \ \___/ ---- \
|
||||
\ \____\ / \____\ \__\
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___
|
||||
\ \ \___/ ---- \ \
|
||||
\ \____\ / \____\ \__\
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___
|
||||
\ \ \___/ ---- \ \
|
||||
\ \____\ / \____\ \__\
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___.
|
||||
\ \ \___/ ---- \ \\
|
||||
\ \____\ / \____\ \__\,
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ .
|
||||
\ \ \___/ ---- \ \\
|
||||
\ \____\ / \____\ \__\\,
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ _.
|
||||
\ \ \___/ ---- \ \\\
|
||||
\ \____\ / \____\ \__\\\
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ __.
|
||||
\ \ \___/ ---- \ \\ \
|
||||
\ \____\ / \____\ \__\\_/.
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___.
|
||||
\ \ \___/ ---- \ \\ \\
|
||||
\ \____\ / \____\ \__\\__\.
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ .
|
||||
\ \ \___/ ---- \ \\ \\
|
||||
\ \____\ / \____\ \__\\__\\.
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ _.
|
||||
\ \ \___/ ---- \ \\ \\\
|
||||
\ \____\ / \____\ \__\\__\\.
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ __.
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\_.
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ __.
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__.
|
||||
\/____/ \/____/
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ .
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ *
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ O*
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ oO*
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ .oO*
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ ..oO*
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ . .oO*
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ . p.oO*
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ . Py.oO*
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ . PYp.oO*
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ . PYPe.oO*
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ . PYPE .oO*
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ . PYPE c.oO*
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ . PYPE C1.oO*
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ . PYPE ClU.oO*
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ . PYPE CluB.oO*
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ . PYPE Club .oO*
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ . PYPE Club . ..
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ . PYPE Club . ..
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ . PYPE Club . .
|
||||
____________
|
||||
/\ ___ \
|
||||
\ \ \/_\ \
|
||||
\ \ _____/ ___ ___ ___
|
||||
\ \ \___/ ---- \ \\ \\ \
|
||||
\ \____\ / \____\ \__\\__\\__\
|
||||
\/____/ \/____/ . PYPE Club .
|
||||
43
igniter/terminal_splash.py
Normal file
43
igniter/terminal_splash.py
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Pype terminal animation."""
|
||||
import blessed
|
||||
from pathlib import Path
|
||||
from time import sleep
|
||||
|
||||
NO_TERMINAL = False
|
||||
|
||||
try:
|
||||
term = blessed.Terminal()
|
||||
except AttributeError:
|
||||
# this happens when blessed cannot find proper terminal.
|
||||
# If so, skip printing ascii art animation.
|
||||
NO_TERMINAL = True
|
||||
|
||||
|
||||
def play_animation():
|
||||
"""Play ASCII art Pype animation."""
|
||||
if NO_TERMINAL:
|
||||
return
|
||||
print(term.home + term.clear)
|
||||
frame_size = 7
|
||||
splash_file = Path(__file__).parent / "splash.txt"
|
||||
with splash_file.open("r") as sf:
|
||||
animation = sf.readlines()
|
||||
|
||||
animation_length = int(len(animation) / frame_size)
|
||||
current_frame = 0
|
||||
for _ in range(animation_length):
|
||||
frame = "".join(
|
||||
scanline
|
||||
for y, scanline in enumerate(
|
||||
animation[current_frame : current_frame + frame_size]
|
||||
)
|
||||
)
|
||||
|
||||
with term.location(0, 0):
|
||||
# term.aquamarine3_bold(frame)
|
||||
print(f"{term.bold}{term.aquamarine3}{frame}{term.normal}")
|
||||
|
||||
sleep(0.02)
|
||||
current_frame += frame_size
|
||||
print(term.move_y(7))
|
||||
145
igniter/tools.py
145
igniter/tools.py
|
|
@ -1,13 +1,104 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Tools used in **Igniter** GUI."""
|
||||
"""Tools used in **Igniter** GUI.
|
||||
|
||||
Functions ``compose_url()`` and ``decompose_url()`` are the same as in
|
||||
``pype.lib`` and they are here to avoid importing pype module before its
|
||||
version is decided.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import uuid
|
||||
from urllib.parse import urlparse
|
||||
from typing import Dict
|
||||
from urllib.parse import urlparse, parse_qs
|
||||
|
||||
from pymongo import MongoClient
|
||||
from pymongo.errors import ServerSelectionTimeoutError, InvalidURI
|
||||
|
||||
from pype.lib import decompose_url, compose_url
|
||||
|
||||
def decompose_url(url: str) -> Dict:
|
||||
"""Decompose mongodb url to its separate components.
|
||||
|
||||
Args:
|
||||
url (str): Mongodb url.
|
||||
|
||||
Returns:
|
||||
dict: Dictionary of components.
|
||||
|
||||
"""
|
||||
components = {
|
||||
"scheme": None,
|
||||
"host": None,
|
||||
"port": None,
|
||||
"username": None,
|
||||
"password": None,
|
||||
"auth_db": None
|
||||
}
|
||||
|
||||
result = urlparse(url)
|
||||
if result.scheme is None:
|
||||
_url = "mongodb://{}".format(url)
|
||||
result = urlparse(_url)
|
||||
|
||||
components["scheme"] = result.scheme
|
||||
components["host"] = result.hostname
|
||||
try:
|
||||
components["port"] = result.port
|
||||
except ValueError:
|
||||
raise RuntimeError("invalid port specified")
|
||||
components["username"] = result.username
|
||||
components["password"] = result.password
|
||||
|
||||
try:
|
||||
components["auth_db"] = parse_qs(result.query)['authSource'][0]
|
||||
except KeyError:
|
||||
# no auth db provided, mongo will use the one we are connecting to
|
||||
pass
|
||||
|
||||
return components
|
||||
|
||||
|
||||
def compose_url(scheme: str = None,
|
||||
host: str = None,
|
||||
username: str = None,
|
||||
password: str = None,
|
||||
port: int = None,
|
||||
auth_db: str = None) -> str:
|
||||
"""Compose mongodb url from its individual components.
|
||||
|
||||
Args:
|
||||
scheme (str, optional):
|
||||
host (str, optional):
|
||||
username (str, optional):
|
||||
password (str, optional):
|
||||
port (str, optional):
|
||||
auth_db (str, optional):
|
||||
|
||||
Returns:
|
||||
str: mongodb url
|
||||
|
||||
"""
|
||||
|
||||
url = "{scheme}://"
|
||||
|
||||
if username and password:
|
||||
url += "{username}:{password}@"
|
||||
|
||||
url += "{host}"
|
||||
if port:
|
||||
url += ":{port}"
|
||||
|
||||
if auth_db:
|
||||
url += "?authSource={auth_db}"
|
||||
|
||||
return url.format(**{
|
||||
"scheme": scheme,
|
||||
"host": host,
|
||||
"username": username,
|
||||
"password": password,
|
||||
"port": port,
|
||||
"auth_db": auth_db
|
||||
})
|
||||
|
||||
|
||||
def validate_mongo_connection(cnx: str) -> (bool, str):
|
||||
|
|
@ -21,30 +112,29 @@ def validate_mongo_connection(cnx: str) -> (bool, str):
|
|||
|
||||
"""
|
||||
parsed = urlparse(cnx)
|
||||
if parsed.scheme in ["mongodb", "mongodb+srv"]:
|
||||
# we have mongo connection string. Let's try if we can connect.
|
||||
components = decompose_url(cnx)
|
||||
mongo_args = {
|
||||
"host": compose_url(**components),
|
||||
"serverSelectionTimeoutMS": 1000
|
||||
}
|
||||
port = components.get("port")
|
||||
if port is not None:
|
||||
mongo_args["port"] = int(port)
|
||||
|
||||
try:
|
||||
client = MongoClient(**mongo_args)
|
||||
client.server_info()
|
||||
except ServerSelectionTimeoutError as e:
|
||||
return False, f"Cannot connect to server {cnx} - {e}"
|
||||
except ValueError:
|
||||
return False, f"Invalid port specified {parsed.port}"
|
||||
except InvalidURI as e:
|
||||
return False, str(e)
|
||||
else:
|
||||
return True, "Connection is successful"
|
||||
else:
|
||||
if parsed.scheme not in ["mongodb", "mongodb+srv"]:
|
||||
return False, "Not mongodb schema"
|
||||
# we have mongo connection string. Let's try if we can connect.
|
||||
components = decompose_url(cnx)
|
||||
mongo_args = {
|
||||
"host": compose_url(**components),
|
||||
"serverSelectionTimeoutMS": 1000
|
||||
}
|
||||
port = components.get("port")
|
||||
if port is not None:
|
||||
mongo_args["port"] = int(port)
|
||||
|
||||
try:
|
||||
client = MongoClient(**mongo_args)
|
||||
client.server_info()
|
||||
except ServerSelectionTimeoutError as e:
|
||||
return False, f"Cannot connect to server {cnx} - {e}"
|
||||
except ValueError:
|
||||
return False, f"Invalid port specified {parsed.port}"
|
||||
except InvalidURI as e:
|
||||
return False, str(e)
|
||||
else:
|
||||
return True, "Connection is successful"
|
||||
|
||||
|
||||
def validate_path_string(path: str) -> (bool, str):
|
||||
|
|
@ -109,5 +199,4 @@ def load_environments(sections: list = None) -> dict:
|
|||
continue
|
||||
merged_env = acre.append(merged_env, parsed_env)
|
||||
|
||||
env = acre.compute(merged_env, cleanup=True)
|
||||
return env
|
||||
return acre.compute(merged_env, cleanup=True)
|
||||
|
|
|
|||
466
igniter/user_settings.py
Normal file
466
igniter/user_settings.py
Normal file
|
|
@ -0,0 +1,466 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Package to deal with saving and retrieving user specific settings."""
|
||||
import os
|
||||
from datetime import datetime
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import json
|
||||
|
||||
# disable lru cache in Python 2
|
||||
try:
|
||||
from functools import lru_cache
|
||||
except ImportError:
|
||||
def lru_cache(maxsize):
|
||||
def max_size(func):
|
||||
def wrapper(*args, **kwargs):
|
||||
value = func(*args, **kwargs)
|
||||
return value
|
||||
return wrapper
|
||||
return max_size
|
||||
|
||||
# ConfigParser was renamed in python3 to configparser
|
||||
try:
|
||||
import configparser
|
||||
except ImportError:
|
||||
import ConfigParser as configparser
|
||||
|
||||
import platform
|
||||
|
||||
import appdirs
|
||||
import six
|
||||
|
||||
|
||||
@six.add_metaclass(ABCMeta)
|
||||
class ASettingRegistry():
|
||||
"""Abstract class defining structure of **SettingRegistry** class.
|
||||
|
||||
It is implementing methods to store secure items into keyring, otherwise
|
||||
mechanism for storing common items must be implemented in abstract
|
||||
methods.
|
||||
|
||||
Attributes:
|
||||
_name (str): Registry names.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, name):
|
||||
# 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 = {}
|
||||
|
||||
def set_item(self, name, value):
|
||||
# type: (str, str) -> None
|
||||
"""Set item to settings registry.
|
||||
|
||||
Args:
|
||||
name (str): Name of the item.
|
||||
value (str): Value of the item.
|
||||
|
||||
"""
|
||||
self._set_item(name, value)
|
||||
|
||||
@abstractmethod
|
||||
def _set_item(self, name, value):
|
||||
# type: (str, str) -> None
|
||||
# Implement it
|
||||
pass
|
||||
|
||||
def __setitem__(self, name, value):
|
||||
self._items[name] = value
|
||||
self._set_item(name, value)
|
||||
|
||||
def get_item(self, name):
|
||||
# type: (str) -> str
|
||||
"""Get item from settings registry.
|
||||
|
||||
Args:
|
||||
name (str): Name of the item.
|
||||
|
||||
Returns:
|
||||
value (str): Value of the item.
|
||||
|
||||
Raises:
|
||||
ValueError: If item doesn't exist.
|
||||
|
||||
"""
|
||||
return self._get_item(name)
|
||||
|
||||
@abstractmethod
|
||||
def _get_item(self, name):
|
||||
# type: (str) -> str
|
||||
# Implement it
|
||||
pass
|
||||
|
||||
def __getitem__(self, name):
|
||||
return self._get_item(name)
|
||||
|
||||
def delete_item(self, name):
|
||||
# type: (str) -> None
|
||||
"""Delete item from settings registry.
|
||||
|
||||
Args:
|
||||
name (str): Name of the item.
|
||||
|
||||
"""
|
||||
self._delete_item(name)
|
||||
|
||||
@abstractmethod
|
||||
def _delete_item(self, name):
|
||||
# type: (str) -> None
|
||||
"""Delete item from settings.
|
||||
|
||||
Note:
|
||||
see :meth:`pype.lib.user_settings.ARegistrySettings.delete_item`
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
def __delitem__(self, name):
|
||||
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`.
|
||||
|
||||
This class is using :mod:`configparser` (ini) files to store items.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, name, path):
|
||||
# type: (str, str) -> IniSettingRegistry
|
||||
super(IniSettingRegistry, self).__init__(name)
|
||||
# get registry file
|
||||
version = os.getenv("PYPE_VERSION", "N/A")
|
||||
self._registry_file = os.path.join(path, "{}.ini".format(name))
|
||||
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)
|
||||
now = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
|
||||
print("# {}".format(now), cfg)
|
||||
|
||||
def set_item_section(
|
||||
self, section, name, value):
|
||||
# type: (str, str, str) -> None
|
||||
"""Set item to specific section of ini registry.
|
||||
|
||||
If section doesn't exists, it is created.
|
||||
|
||||
Args:
|
||||
section (str): Name of section.
|
||||
name (str): Name of the item.
|
||||
value (str): Value of the item.
|
||||
|
||||
"""
|
||||
value = str(value)
|
||||
config = configparser.ConfigParser()
|
||||
|
||||
config.read(self._registry_file)
|
||||
if not config.has_section(section):
|
||||
config.add_section(section)
|
||||
current = config[section]
|
||||
current[name] = value
|
||||
|
||||
with open(self._registry_file, mode="w") as cfg:
|
||||
config.write(cfg)
|
||||
|
||||
def _set_item(self, name, value):
|
||||
# type: (str, str) -> None
|
||||
self.set_item_section("MAIN", name, value)
|
||||
|
||||
def set_item(self, name, value):
|
||||
# type: (str, str) -> None
|
||||
"""Set item to settings ini file.
|
||||
|
||||
This saves item to ``DEFAULT`` section of ini as each item there
|
||||
must reside in some section.
|
||||
|
||||
Args:
|
||||
name (str): Name of the item.
|
||||
value (str): Value of the item.
|
||||
|
||||
"""
|
||||
# this does the some, overridden just for different docstring.
|
||||
# we cast value to str as ini options values must be strings.
|
||||
super(IniSettingRegistry, self).set_item(name, str(value))
|
||||
|
||||
def get_item(self, name):
|
||||
# type: (str) -> str
|
||||
"""Gets item from settings ini file.
|
||||
|
||||
This gets settings from ``DEFAULT`` section of ini file as each item
|
||||
there must reside in some section.
|
||||
|
||||
Args:
|
||||
name (str): Name of the item.
|
||||
|
||||
Returns:
|
||||
str: Value of item.
|
||||
|
||||
Raises:
|
||||
ValueError: If value doesn't exist.
|
||||
|
||||
"""
|
||||
return super(IniSettingRegistry, self).get_item(name)
|
||||
|
||||
@lru_cache(maxsize=32)
|
||||
def get_item_from_section(self, section, name):
|
||||
# type: (str, str) -> str
|
||||
"""Get item from section of ini file.
|
||||
|
||||
This will read ini file and try to get item value from specified
|
||||
section. If that section or item doesn't exist, :exc:`ValueError`
|
||||
is risen.
|
||||
|
||||
Args:
|
||||
section (str): Name of ini section.
|
||||
name (str): Name of the item.
|
||||
|
||||
Returns:
|
||||
str: Item value.
|
||||
|
||||
Raises:
|
||||
ValueError: If value doesn't exist.
|
||||
|
||||
"""
|
||||
config = configparser.ConfigParser()
|
||||
config.read(self._registry_file)
|
||||
try:
|
||||
value = config[section][name]
|
||||
except KeyError:
|
||||
raise ValueError(
|
||||
"Registry doesn't contain value {}:{}".format(section, name))
|
||||
return value
|
||||
|
||||
def _get_item(self, name):
|
||||
# type: (str) -> str
|
||||
return self.get_item_from_section("MAIN", name)
|
||||
|
||||
def delete_item_from_section(self, section, name):
|
||||
# type: (str, str) -> None
|
||||
"""Delete item from section in ini file.
|
||||
|
||||
Args:
|
||||
section (str): Section name.
|
||||
name (str): Name of the item.
|
||||
|
||||
Raises:
|
||||
ValueError: If item doesn't exist.
|
||||
|
||||
"""
|
||||
self.get_item_from_section.cache_clear()
|
||||
config = configparser.ConfigParser()
|
||||
config.read(self._registry_file)
|
||||
try:
|
||||
_ = config[section][name]
|
||||
except KeyError:
|
||||
raise ValueError(
|
||||
"Registry doesn't contain value {}:{}".format(section, name))
|
||||
config.remove_option(section, name)
|
||||
|
||||
# if section is empty, delete it
|
||||
if len(config[section].keys()) == 0:
|
||||
config.remove_section(section)
|
||||
|
||||
with open(self._registry_file, mode="w") as cfg:
|
||||
config.write(cfg)
|
||||
|
||||
def _delete_item(self, name):
|
||||
"""Delete item from default section.
|
||||
|
||||
Note:
|
||||
See :meth:`~pype.lib.IniSettingsRegistry.delete_item_from_section`
|
||||
|
||||
"""
|
||||
self.delete_item_from_section("MAIN", name)
|
||||
|
||||
|
||||
class JSONSettingRegistry(ASettingRegistry):
|
||||
"""Class using json file as storage."""
|
||||
|
||||
def __init__(self, name, path):
|
||||
# type: (str, str) -> JSONSettingRegistry
|
||||
super(JSONSettingRegistry, self).__init__(name)
|
||||
#: str: name of registry file
|
||||
self._registry_file = os.path.join(path, "{}.json".format(name))
|
||||
now = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
|
||||
header = {
|
||||
"__metadata__": {
|
||||
"pype-version": os.getenv("PYPE_VERSION", "N/A"),
|
||||
"generated": now
|
||||
},
|
||||
"registry": {}
|
||||
}
|
||||
|
||||
if not os.path.exists(os.path.dirname(self._registry_file)):
|
||||
os.makedirs(os.path.dirname(self._registry_file), exist_ok=True)
|
||||
if not os.path.exists(self._registry_file):
|
||||
with open(self._registry_file, mode="w") as cfg:
|
||||
json.dump(header, cfg, indent=4)
|
||||
|
||||
@lru_cache(maxsize=32)
|
||||
def _get_item(self, name):
|
||||
# type: (str) -> object
|
||||
"""Get item value from registry json.
|
||||
|
||||
Note:
|
||||
See :meth:`pype.lib.JSONSettingRegistry.get_item`
|
||||
|
||||
"""
|
||||
with open(self._registry_file, mode="r") as cfg:
|
||||
data = json.load(cfg)
|
||||
try:
|
||||
value = data["registry"][name]
|
||||
except KeyError:
|
||||
raise ValueError(
|
||||
"Registry doesn't contain value {}".format(name))
|
||||
return value
|
||||
|
||||
def get_item(self, name):
|
||||
# type: (str) -> object
|
||||
"""Get item value from registry json.
|
||||
|
||||
Args:
|
||||
name (str): Name of the item.
|
||||
|
||||
Returns:
|
||||
value of the item
|
||||
|
||||
Raises:
|
||||
ValueError: If item is not found in registry file.
|
||||
|
||||
"""
|
||||
return self._get_item(name)
|
||||
|
||||
def _set_item(self, name, value):
|
||||
# type: (str, object) -> None
|
||||
"""Set item value to registry json.
|
||||
|
||||
Note:
|
||||
See :meth:`pype.lib.JSONSettingRegistry.set_item`
|
||||
|
||||
"""
|
||||
with open(self._registry_file, "r+") as cfg:
|
||||
data = json.load(cfg)
|
||||
data["registry"][name] = value
|
||||
cfg.truncate(0)
|
||||
cfg.seek(0)
|
||||
json.dump(data, cfg, indent=4)
|
||||
|
||||
def set_item(self, name, value):
|
||||
# type: (str, object) -> None
|
||||
"""Set item and its value into json registry file.
|
||||
|
||||
Args:
|
||||
name (str): name of the item.
|
||||
value (Any): value of the item.
|
||||
|
||||
"""
|
||||
self._set_item(name, value)
|
||||
|
||||
def _delete_item(self, name):
|
||||
# type: (str) -> None
|
||||
self._get_item.cache_clear()
|
||||
with open(self._registry_file, "r+") as cfg:
|
||||
data = json.load(cfg)
|
||||
del data["registry"][name]
|
||||
cfg.truncate(0)
|
||||
cfg.seek(0)
|
||||
json.dump(data, cfg, indent=4)
|
||||
|
||||
|
||||
class PypeSettingsRegistry(JSONSettingRegistry):
|
||||
"""Class handling Pype general settings registry.
|
||||
|
||||
Attributes:
|
||||
vendor (str): Name used for path construction.
|
||||
product (str): Additional name used for path construction.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.vendor = "pypeclub"
|
||||
self.product = "pype"
|
||||
path = appdirs.user_data_dir(self.product, self.vendor)
|
||||
super(PypeSettingsRegistry, self).__init__("pype_settings", path)
|
||||
|
|
@ -27,11 +27,12 @@ def play_animation():
|
|||
animation_length = int(len(animation) / frame_size)
|
||||
current_frame = 0
|
||||
for _ in range(animation_length):
|
||||
frame = ""
|
||||
y = 0
|
||||
for scanline in animation[current_frame:current_frame + frame_size]:
|
||||
frame += scanline
|
||||
y += 1
|
||||
frame = "".join(
|
||||
scanline
|
||||
for y, scanline in enumerate(
|
||||
animation[current_frame : current_frame + frame_size]
|
||||
)
|
||||
)
|
||||
|
||||
with term.location(0, 0):
|
||||
# term.aquamarine3_bold(frame)
|
||||
|
|
|
|||
|
|
@ -28,8 +28,6 @@ import platform
|
|||
import appdirs
|
||||
import six
|
||||
|
||||
from ..version import __version__
|
||||
|
||||
|
||||
@six.add_metaclass(ABCMeta)
|
||||
class ASettingRegistry():
|
||||
|
|
@ -213,11 +211,12 @@ class IniSettingRegistry(ASettingRegistry):
|
|||
# type: (str, str) -> IniSettingRegistry
|
||||
super(IniSettingRegistry, self).__init__(name)
|
||||
# get registry file
|
||||
version = os.getenv("PYPE_VERSION", "N/A")
|
||||
self._registry_file = os.path.join(path, "{}.ini".format(name))
|
||||
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 Pype {}".format(version), cfg)
|
||||
now = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
|
||||
print("# {}".format(now), cfg)
|
||||
|
||||
|
|
@ -368,7 +367,7 @@ class JSONSettingRegistry(ASettingRegistry):
|
|||
now = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
|
||||
header = {
|
||||
"__metadata__": {
|
||||
"pype-version": __version__,
|
||||
"pype-version": os.getenv("PYPE_VERSION", "N/A"),
|
||||
"generated": now
|
||||
},
|
||||
"registry": {}
|
||||
|
|
@ -459,9 +458,9 @@ class PypeSettingsRegistry(JSONSettingRegistry):
|
|||
product (str): Additional name used for path construction.
|
||||
|
||||
"""
|
||||
vendor = "pypeclub"
|
||||
product = "pype"
|
||||
|
||||
def __init__(self):
|
||||
self.vendor = "pypeclub"
|
||||
self.product = "pype"
|
||||
path = appdirs.user_data_dir(self.product, self.vendor)
|
||||
super(PypeSettingsRegistry, self).__init__("pype_settings", path)
|
||||
|
|
|
|||
3
setup.py
3
setup.py
|
|
@ -66,7 +66,8 @@ build_options = dict(
|
|||
includes=includes,
|
||||
excludes=excludes,
|
||||
bin_includes=bin_includes,
|
||||
include_files=include_files
|
||||
include_files=include_files,
|
||||
optimize=0
|
||||
)
|
||||
|
||||
icon_path = pype_root / "igniter" / "pype.ico"
|
||||
|
|
|
|||
59
start.py
59
start.py
|
|
@ -99,7 +99,16 @@ import traceback
|
|||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import acre
|
||||
# add dependencies folder to sys.pat for frozen code
|
||||
if getattr(sys, 'frozen', False):
|
||||
frozen_libs = os.path.normpath(
|
||||
os.path.join(os.path.dirname(sys.executable), "dependencies"))
|
||||
sys.path.append(frozen_libs)
|
||||
# add stuff from `<frozen>/dependencies` to PYTHONPATH.
|
||||
pythonpath = os.getenv("PYTHONPATH", "")
|
||||
paths = pythonpath.split(os.pathsep)
|
||||
paths.append(frozen_libs)
|
||||
os.environ["PYTHONPATH"] = os.pathsep.join(paths)
|
||||
|
||||
from igniter import BootstrapRepos
|
||||
from igniter.tools import load_environments
|
||||
|
|
@ -116,6 +125,15 @@ def set_environments() -> None:
|
|||
better handling of environments
|
||||
|
||||
"""
|
||||
try:
|
||||
import acre
|
||||
except ImportError:
|
||||
if getattr(sys, 'frozen', False):
|
||||
sys.path.append(os.path.join(
|
||||
os.path.dirname(sys.executable),
|
||||
"dependencies"
|
||||
))
|
||||
import acre
|
||||
try:
|
||||
env = load_environments(["global"])
|
||||
except OSError as e:
|
||||
|
|
@ -163,6 +181,7 @@ def set_modules_environments():
|
|||
"""
|
||||
|
||||
from pype.modules import ModulesManager
|
||||
import acre
|
||||
|
||||
modules_manager = ModulesManager()
|
||||
|
||||
|
|
@ -267,7 +286,8 @@ def _find_frozen_pype(use_version: str = None,
|
|||
"""
|
||||
|
||||
pype_version = None
|
||||
pype_versions = bootstrap.find_pype(include_zips=True)
|
||||
pype_versions = bootstrap.find_pype(include_zips=True,
|
||||
staging=use_staging)
|
||||
try:
|
||||
# use latest one found (last in the list is latest)
|
||||
pype_version = pype_versions[-1]
|
||||
|
|
@ -281,16 +301,6 @@ def _find_frozen_pype(use_version: str = None,
|
|||
if not pype_versions:
|
||||
raise RuntimeError("No Pype versions found.")
|
||||
|
||||
# find only staging versions
|
||||
if use_staging:
|
||||
staging_versions = [v for v in pype_versions if v.is_staging()]
|
||||
if not staging_versions:
|
||||
raise RuntimeError("No Pype staging versions found.")
|
||||
|
||||
staging_versions.sort()
|
||||
# get latest staging version (last in the list is latest)
|
||||
pype_version = staging_versions[-1]
|
||||
|
||||
# get path of version specified in `--use-version`
|
||||
version_path = BootstrapRepos.get_version_path_from_list(
|
||||
use_version, pype_versions)
|
||||
|
|
@ -322,18 +332,11 @@ def _find_frozen_pype(use_version: str = None,
|
|||
print(">>> Extracting zip file ...")
|
||||
version_path = bootstrap.extract_pype(pype_version)
|
||||
|
||||
os.environ["PYPE_VERSION"] = pype_version.version
|
||||
# inject version to Python environment (sys.path, ...)
|
||||
print(">>> Injecting Pype version to running environment ...")
|
||||
bootstrap.add_paths_from_directory(version_path)
|
||||
|
||||
# add stuff from `<frozen>/lib` to PYTHONPATH.
|
||||
pythonpath = os.getenv("PYTHONPATH", "")
|
||||
paths = pythonpath.split(os.pathsep)
|
||||
frozen_libs = os.path.normpath(
|
||||
os.path.join(os.path.dirname(sys.executable), "lib"))
|
||||
paths.append(frozen_libs)
|
||||
os.environ["PYTHONPATH"] = os.pathsep.join(paths)
|
||||
|
||||
# set PYPE_ROOT to point to currently used Pype version.
|
||||
os.environ["PYPE_ROOT"] = os.path.normpath(version_path.as_posix())
|
||||
|
||||
|
|
@ -347,7 +350,7 @@ def boot():
|
|||
# Play animation
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
from pype.lib.terminal_splash import play_animation
|
||||
from igniter.terminal_splash import play_animation
|
||||
|
||||
# don't play for silenced commands
|
||||
if all(item not in sys.argv for item in silent_commands):
|
||||
|
|
@ -363,7 +366,6 @@ def boot():
|
|||
# Determine mongodb connection
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
pype_mongo = ""
|
||||
try:
|
||||
pype_mongo = _determine_mongodb()
|
||||
except RuntimeError as e:
|
||||
|
|
@ -385,7 +387,6 @@ def boot():
|
|||
|
||||
if getattr(sys, 'frozen', False):
|
||||
# find versions of Pype to be used with frozen code
|
||||
version_path = None
|
||||
try:
|
||||
version_path = _find_frozen_pype(use_version, use_staging)
|
||||
except RuntimeError as e:
|
||||
|
|
@ -399,6 +400,7 @@ def boot():
|
|||
os.path.dirname(os.path.realpath(__file__)))
|
||||
# get current version of Pype
|
||||
local_version = bootstrap.get_local_live_version()
|
||||
os.environ["PYPE_VERSION"] = local_version
|
||||
if use_version and use_version != local_version:
|
||||
pype_versions = bootstrap.find_pype(include_zips=True)
|
||||
version_path = BootstrapRepos.get_version_path_from_list(
|
||||
|
|
@ -406,7 +408,9 @@ def boot():
|
|||
if version_path:
|
||||
# use specified
|
||||
bootstrap.add_paths_from_directory(version_path)
|
||||
|
||||
os.environ["PYPE_VERSION"] = use_version
|
||||
else:
|
||||
version_path = pype_root
|
||||
os.environ["PYPE_ROOT"] = pype_root
|
||||
repos = os.listdir(os.path.join(pype_root, "repos"))
|
||||
repos = [os.path.join(pype_root, "repos", repo) for repo in repos]
|
||||
|
|
@ -434,6 +438,8 @@ def boot():
|
|||
del sys.modules["pype.version"]
|
||||
except AttributeError:
|
||||
pass
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
from pype import cli
|
||||
from pype.lib import terminal as t
|
||||
|
|
@ -442,10 +448,9 @@ def boot():
|
|||
set_modules_environments()
|
||||
|
||||
info = get_info()
|
||||
info.insert(0, ">>> Using Pype from [ {} ]".format(
|
||||
os.path.dirname(cli.__file__)))
|
||||
info.insert(0, f">>> Using Pype from [ {version_path} ]")
|
||||
|
||||
t_width = os.get_terminal_size().columns
|
||||
t_width = os.get_terminal_size().columns - 2
|
||||
_header = f"*** Pype [{__version__}] "
|
||||
|
||||
info.insert(0, _header + "-" * (t_width - len(_header)))
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@ def test_pype_version():
|
|||
assert str(v3) == "1.2.3-staging"
|
||||
|
||||
v4 = PypeVersion(1, 2, 3, variant="staging", client="client")
|
||||
assert str(v4) == "1.2.3-staging-client"
|
||||
assert str(v4) == "1.2.3-client-staging"
|
||||
assert v3 < v4
|
||||
|
||||
v5 = PypeVersion(1, 2, 3, variant="foo", client="x")
|
||||
assert str(v5) == "1.2.3-x"
|
||||
|
|
@ -100,7 +101,7 @@ def test_pype_version():
|
|||
with pytest.raises(ValueError):
|
||||
_ = PypeVersion(version="booobaa")
|
||||
|
||||
v11 = PypeVersion(version="4.6.7-staging-client")
|
||||
v11 = PypeVersion(version="4.6.7-client-staging")
|
||||
assert v11.major == 4
|
||||
assert v11.minor == 6
|
||||
assert v11.subversion == 7
|
||||
|
|
@ -131,7 +132,7 @@ def test_search_string_for_pype_version(printer):
|
|||
("foo-3.0", False),
|
||||
("foo-3.0.1", True),
|
||||
("3", False),
|
||||
("foo-3.0.1-staging-client", True),
|
||||
("foo-3.0.1-client-staging", True),
|
||||
("foo-3.0.1-bar-baz", True)
|
||||
]
|
||||
for ver_string in strings:
|
||||
|
|
@ -178,7 +179,7 @@ def test_find_pype(fix_bootstrap, tmp_path_factory, monkeypatch, printer):
|
|||
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-staging-client",
|
||||
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),
|
||||
|
|
@ -201,7 +202,7 @@ def test_find_pype(fix_bootstrap, tmp_path_factory, monkeypatch, printer):
|
|||
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-staging-client",
|
||||
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)
|
||||
|
|
@ -222,7 +223,7 @@ def test_find_pype(fix_bootstrap, tmp_path_factory, monkeypatch, printer):
|
|||
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-staging-client",
|
||||
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)
|
||||
|
|
@ -254,8 +255,8 @@ 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 = path / "pype" / "version.py"
|
||||
pype_path = path / "pype" / "pype"
|
||||
version_path = pype_path / "version.py"
|
||||
pype_path.mkdir(parents=True, exist_ok=True)
|
||||
with open(version_path, "w") as fp:
|
||||
fp.write(f"__version__ = '{version}'\n\n")
|
||||
|
|
@ -306,7 +307,7 @@ def test_find_pype(fix_bootstrap, tmp_path_factory, monkeypatch, printer):
|
|||
_build_test_item(dir_path, test_file)
|
||||
|
||||
printer("testing finding Pype in given path ...")
|
||||
result = fix_bootstrap.find_pype(g_path, True)
|
||||
result = fix_bootstrap.find_pype(g_path, include_zips=True)
|
||||
# we should have results as file were created
|
||||
assert result is not None, "no Pype version found"
|
||||
# latest item in `result` should be latest version found.
|
||||
|
|
@ -317,6 +318,7 @@ def test_find_pype(fix_bootstrap, tmp_path_factory, monkeypatch, printer):
|
|||
test_versions_3[3].suffix
|
||||
)
|
||||
)
|
||||
assert result, "nothing found"
|
||||
assert result[-1].path == expected_path, "not a latest version of Pype 3"
|
||||
|
||||
monkeypatch.setenv("PYPE_PATH", e_path.as_posix())
|
||||
|
|
@ -332,6 +334,7 @@ def test_find_pype(fix_bootstrap, tmp_path_factory, monkeypatch, printer):
|
|||
test_versions_1[5].suffix
|
||||
)
|
||||
)
|
||||
assert result, "nothing found"
|
||||
assert result[-1].path == expected_path, "not a latest version of Pype 1"
|
||||
|
||||
monkeypatch.delenv("PYPE_PATH", raising=False)
|
||||
|
|
@ -350,14 +353,15 @@ def test_find_pype(fix_bootstrap, tmp_path_factory, monkeypatch, printer):
|
|||
# latest item in `result` should be latest version found.
|
||||
expected_path = Path(
|
||||
d_path / "{}{}{}".format(
|
||||
test_versions_2[4].prefix,
|
||||
test_versions_2[4].version,
|
||||
test_versions_2[4].suffix
|
||||
test_versions_2[3].prefix,
|
||||
test_versions_2[3].version,
|
||||
test_versions_2[3].suffix
|
||||
)
|
||||
)
|
||||
assert result, "nothing found"
|
||||
assert result[-1].path == expected_path, "not a latest version of Pype 2"
|
||||
|
||||
result = fix_bootstrap.find_pype(e_path, True)
|
||||
result = fix_bootstrap.find_pype(e_path, include_zips=True)
|
||||
assert result is not None, "no Pype version found"
|
||||
expected_path = Path(
|
||||
e_path / "{}{}{}".format(
|
||||
|
|
@ -368,12 +372,13 @@ def test_find_pype(fix_bootstrap, tmp_path_factory, monkeypatch, printer):
|
|||
)
|
||||
assert result[-1].path == expected_path, "not a latest version of Pype 1"
|
||||
|
||||
result = fix_bootstrap.find_pype(dir_path, True)
|
||||
result = fix_bootstrap.find_pype(dir_path, include_zips=True)
|
||||
assert result is not None, "no Pype versions found"
|
||||
expected_path = Path(
|
||||
e_path / "{}{}{}".format(
|
||||
dir_path / "{}{}{}".format(
|
||||
test_versions_4[0].prefix,
|
||||
test_versions_4[0].version,
|
||||
test_versions_4[0].suffix
|
||||
)
|
||||
)
|
||||
assert result[-1].path == expected_path, "not a latest version of Pype 4"
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ catch {
|
|||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "Cleaning cache files ... " -NoNewline
|
||||
Get-ChildItem $pype_root -Filter "*.pyc" -Force -Recurse | Remove-Item -Force
|
||||
Get-ChildItem $pype_root -Filter "*.pyo" -Force -Recurse | Remove-Item -Force
|
||||
Get-ChildItem $pype_root -Filter "__pycache__" -Force -Recurse | Remove-Item -Force -Recurse
|
||||
Write-Host "OK" -ForegroundColor green
|
||||
|
||||
|
|
@ -176,6 +177,7 @@ Write-Host "Building Pype ..."
|
|||
$out = & python setup.py build 2>&1
|
||||
|
||||
Set-Content -Path "$($pype_root)\build\build.log" -Value $out
|
||||
& python -B "$($pype_root)\tools\build_dependencies.py"
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "deactivating venv ..."
|
||||
|
|
|
|||
119
tools/build_dependencies.py
Normal file
119
tools/build_dependencies.py
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Script to fix frozen dependencies.
|
||||
|
||||
Because Pype code needs to run under different versions of Python interpreter
|
||||
(yes, even Python 2) we need to include all dependencies as source code
|
||||
without Python's system stuff. Cx-freeze puts everything into lib and compile
|
||||
it as .pyc/.pyo files and that doesn't work for hosts like Maya 2020 with
|
||||
their own Python interpreter and libraries.
|
||||
|
||||
This script will take ``site-packages`` and copy them to built Pype under
|
||||
``dependencies`` directory. It will then compare stuff inside with ``lib`` folder
|
||||
in frozen Pype, removing duplicities from there.
|
||||
|
||||
This must be executed after build finished and it is done by build PowerShell
|
||||
script.
|
||||
|
||||
Note: Speedcopy can be used for copying if server-side copy is important for
|
||||
speed.
|
||||
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import site
|
||||
from distutils.util import get_platform
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import blessed
|
||||
import time
|
||||
|
||||
|
||||
term = blessed.Terminal()
|
||||
|
||||
|
||||
def _print(msg: str, type: int = 0) -> None:
|
||||
"""Print message to console.
|
||||
|
||||
Args:
|
||||
msg (str): message to print
|
||||
type (int): type of message (0 info, 1 error, 2 note)
|
||||
|
||||
"""
|
||||
if type == 0:
|
||||
header = term.aquamarine3(">>> ")
|
||||
elif type == 1:
|
||||
header = term.orangered2("!!! ")
|
||||
elif type == 2:
|
||||
header = term.tan1("... ")
|
||||
else:
|
||||
header = term.darkolivegreen3("--- ")
|
||||
|
||||
print("{}{}".format(header, msg))
|
||||
|
||||
|
||||
_print("Starting dependency cleanup ...")
|
||||
start_time = time.time_ns()
|
||||
|
||||
# path to venv site packages
|
||||
sites = site.getsitepackages()
|
||||
|
||||
# WARNING: this assumes that all we've got is path to venv itself and
|
||||
# another path ending with 'site-packages' as is default. But because
|
||||
# this must run under different platform, we cannot easily check if this path
|
||||
# is the one, because under Linux and macOS site-packages are in different
|
||||
# location.
|
||||
site_pkg = None
|
||||
for s in sites:
|
||||
site_pkg = Path(s)
|
||||
if site_pkg.name == "site-packages":
|
||||
break
|
||||
|
||||
_print("Getting venv site-packages ...")
|
||||
assert site_pkg, "No venv site-packages are found."
|
||||
_print(f"Working with: {site_pkg}", 2)
|
||||
|
||||
# now, copy it to build directory
|
||||
build_dir = None
|
||||
if sys.platform.startswith("linux"):
|
||||
# TODO: what is it under linux?
|
||||
raise NotImplementedError("not implemented for linux yet")
|
||||
elif sys.platform == "darwin":
|
||||
# TODO: what is it under macOS?
|
||||
raise NotImplementedError("not implemented for macOS yet")
|
||||
elif sys.platform == "win32":
|
||||
# string is formatted as cx_freeze is doing it
|
||||
build_dir = "exe.{}-{}".format(get_platform(), sys.version[0:3])
|
||||
|
||||
# create full path
|
||||
build_dir = Path(os.path.dirname(__file__)).parent / "build" / build_dir
|
||||
|
||||
_print(f"Using build at {build_dir}", 2)
|
||||
assert build_dir.exists(), "Build directory doesn't exist"
|
||||
|
||||
deps_dir = build_dir / "dependencies"
|
||||
|
||||
# copy all files
|
||||
_print("Copying dependencies ...")
|
||||
shutil.copytree(site_pkg.as_posix(), deps_dir.as_posix())
|
||||
|
||||
# iterate over frozen libs and create list to delete
|
||||
libs_dir = build_dir / "lib"
|
||||
|
||||
to_delete = []
|
||||
_print("Finding duplicates ...")
|
||||
for d in libs_dir.iterdir():
|
||||
if (deps_dir / d.name) in deps_dir.iterdir():
|
||||
to_delete.append(d)
|
||||
_print(f"found {d}", 3)
|
||||
|
||||
# delete duplicates
|
||||
_print(f"Deleting {len(to_delete)} duplicates ...")
|
||||
for d in to_delete:
|
||||
if d.is_dir():
|
||||
shutil.rmtree(d)
|
||||
else:
|
||||
d.unlink()
|
||||
|
||||
end_time = time.time_ns()
|
||||
total_time = (end_time - start_time) / 1000000000
|
||||
_print(f"Dependency cleanup done in {total_time} secs.")
|
||||
|
|
@ -90,7 +90,7 @@ Write-Host "OK [ $p ]" -ForegroundColor green
|
|||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "Entering venv ..."
|
||||
try {
|
||||
. (".\venv\Scripts\Activate.ps1")
|
||||
. ("$($pype_root)\venv\Scripts\Activate.ps1")
|
||||
}
|
||||
catch {
|
||||
Write-Host "!!! Failed to activate" -ForegroundColor red
|
||||
|
|
@ -99,6 +99,9 @@ catch {
|
|||
}
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "Generating zip from current sources ..."
|
||||
Write-Host "... " -NoNewline -ForegroundColor Magenta
|
||||
Write-Host "arguments: " -NoNewline -ForegroundColor Gray
|
||||
Write-Host $ARGS -ForegroundColor White
|
||||
& python "$($pype_root)\start.py" generate-zip $ARGS
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue