def installModFromGit(self, pkg, result): # Update instead if already exists if pkg.installDir.exists(): return self.updateModFromGit(pkg, result) # Install else: try: # Init repo, get manifest gh = self.RepoImpl(pkg.git) gh.syncManifestHttp() # Check dependencies based on manifest.ini or metadata.txt (depsOk, failedDependencies) = deps.check_dependencies(gh.manifest) if not depsOk: result.failedDependencies = failedDependencies return result # Clone and update submodules repo, _ = clone_local(pkg.git, pkg.installDir, branch='master') if repo.submodules: repo.submodule_update(recursive=True) result.ok = True except: log(traceback.format_exc()) result.ok = False return result
def installModFromHttpZip(self, pkg, result): try: # Init repo, get manifest gh = self.RepoImpl(pkg.git) gh.syncManifestHttp() # Check dependencies based on manifest.ini or metadata.txt (depsOk, failedDependencies) = deps.check_dependencies(gh.manifest) if not depsOk: result.failedDependencies = failedDependencies return result # Download mater zip zip_path = Path(tempfile.mktemp(suffix=".zip")) if http_download(gh.getZipUrl(), zip_path): exploded = Path(tempfile.mktemp(suffix="_zip")) zlib.unzip(zip_path, exploded) # Remove old if exists if pkg.installDir.exists(): shutil.rmtree(pkg.installDir, ignore_errors=True) # Move exploded dir to install dir for entry_path in exploded.iterdir(): if entry_path.is_dir(): shutil.move(entry_path, pkg.installDir) result.ok = True break # Only one zip directory is expected except: log(traceback.format_exc()) result.ok = False return result
def __init__(self, content): try: parser = configparser.ConfigParser() parser.read_string(content) for section, items in parser.items(): self.__setattr__(section, ManifestSection(items.items())) except: log("Invalid manifest file")
def uninstall(self, pkg): log("Uninstalling {}".format(pkg.name)) try: if hasattr(pkg, 'installFile') and pkg.type == 'Macro': uninstall_macro(pkg.installFile) elif hasattr(pkg, 'installDir') and pkg.type == 'Workbench': shutil.rmtree(pkg.installDir, ignore_errors=True) except BaseException as e: log_err(str(e))
def requestStarted(self, request): # Parse Url url = request.requestUrl() path = url.path() query = QtCore.QUrlQuery(url) params = {k: unquote(v) for k, v in query.queryItems()} # Fix Windows URL (This is insane) win_fix = WINDOWS_PATH_PATTERN.match(path) if win_fix: path = win_fix.group(1) # Prepare response buffer buf = QtCore.QBuffer(parent=self) request.destroyed.connect(buf.deleteLater) buf.open(QtCore.QIODevice.WriteOnly) # Match Action action = None action_match = ACTION_URL_PATTERN.match(path) if action_match: action = action_match.group(1) if path.endswith('.html') or action: # Prepare Response object response = Response(self, buf, request) request.destroyed.connect(response.deleteLater) # Call handler to do the real work # ! Important: requestHandler can work in another thread. # ! response.send() should be called from the handler # ! to send any content. self.requestHandler(path, action, params, request, response) else: file_path = Path(path) content_type = get_supported_mimetype(file_path) if file_path.exists(): with open(file_path, 'rb') as f: buf.write(f.read()) buf.seek(0) buf.close() request.reply(content_type.encode(), buf) else: buf.close() request.reply(content_type.encode(), buf) log("Path does not exists: ", str(file_path))
def register_custom_schemes(): try: from PySide2.QtWebEngineCore import QWebEngineUrlScheme except ImportError: log('Outdated QT version, some graphics will be not available') else: scheme_reg = QWebEngineUrlScheme(EXTMAN_URL_SCHEME) scheme_reg.setFlags(QWebEngineUrlScheme.SecureScheme | QWebEngineUrlScheme.LocalScheme | QWebEngineUrlScheme.LocalAccessAllowed | QWebEngineUrlScheme.ContentSecurityPolicyIgnored | 0x80 # QWebEngineUrlScheme.CorsEnabled ) QWebEngineUrlScheme.registerScheme(scheme_reg)
def updateModFromGit(self, pkg, result): # Install instead if not exists if not pkg.installDir.exists(): return self.installModFromGit(pkg, result) # Update else: try: # Init repo, get manifest gh = self.RepoImpl(pkg.git) gh.syncManifestHttp() # Check dependencies based on manifest.ini or metadata.txt (depsOk, failedDependencies) = deps.check_dependencies(gh.manifest) if not depsOk: result.failedDependencies = failedDependencies return result # Upgrade to git if necessary import git bare_path = Path(pkg.installDir, '.git') if not bare_path.exists(): bare, _ = gh.clone(bare_path, bare=True) config_set(bare, 'core', 'bare', False) repo = git.Repo(pkg.installDir) repo.head.reset('--hard') # Pull repo = git.Git(pkg.installDir) repo.pull('--depth=1') repo = git.Repo(pkg.installDir) for mod in repo.submodules: mod.update(init=True, recursive=True) result.ok = True except: log(traceback.format_exc()) result.ok = False return result
def http_download(url, path, headers=None, timeout=30): urllib_init() try: with request.urlopen(request.Request(url, headers=headers or {}), timeout=timeout) as stream: with open(path, 'wb') as localFile: block = 8192 while True: p = stream.read(block) if not p: break localFile.write(p) return True except errors.URLError as ex: log(url, str(ex.reason)) except: log(traceback.format_exc()) return False
def installMod(self, pkg): # Get Git info git_available, _, git_version, git_python, git_version_ok = install_info( ) # Get zip info zip_available = zlib.is_zip_available() # Initialize result result = InstallResult(gitAvailable=git_available, gitPythonAvailable=git_python is not None, zipAvailable=zip_available, gitVersionOk=git_version_ok, gitVersion=git_version) # Check valid install dir in_mods = get_mod_path() == pkg.installDir.parent in_macros = pkg.installFile and get_macro_path( ) in pkg.installFile.parents if not in_mods and not in_macros: log('Invalid install dir: {0}'.format(pkg.installDir)) result.ok = False result.invalidInstallDir = True return result # Try Git install if git_available and git_version_ok and git_python: result = self.installModFromGit(pkg, result) # Try zip/http install elif zip_available: result = self.installModFromHttpZip(pkg, result) if result.ok: try: self.linkMacrosFromMod(pkg) except: # ! TODO: Rollback everything if macro links fail? pass return result
def eval_expr(match): try: etype = match.group(1) eexpr = match.group(2) # Translate shortcut if etype == 't:': return tr(eexpr) # Eval Expression elif etype == 'e:': return compile_and_execute(eexpr, model, 'eval') # Execute Statement elif etype == 'x:': return compile_and_execute(eexpr, model, 'exec') # Resolve local symbol else: return str( model.get(eexpr, '???{0}{1}???'.format(etype, eexpr))) except: # Catch All Errors/Exceptions log(traceback.format_exc()) log("Error executing expression {0} in template {1}".format( eexpr, path)) return 'Error:' + traceback.format_exc()
def http_get(url, headers=None, timeout=30, decode='utf-8'): urllib_init() data = None try: with request.urlopen(request.Request(url, headers=headers or {}), timeout=timeout) as f: block = 8192 if decode: data = '' else: data = [] while True: p = f.read(block) if not p: break if isinstance(p, bytes) and decode: p = p.decode(decode) data += p except errors.URLError as ex: log(url, str(ex.reason)) except: log(traceback.format_exc()) return data
def installMacro(self, pkg): (git_available, _, git_version, git_python, git_version_ok) = install_info() # Initialize result result = InstallResult(gitAvailable=git_available, gitPythonAvailable=git_python is not None, zipAvailable=zlib.is_zip_available(), gitVersionOk=git_version_ok, gitVersion=git_version) # Ensure last version if available locally src_dir = self.downloadMacroList() # Get path of source macro file src_file = Path(src_dir, pkg.basePath, pkg.installFile.name) # Copy Macro files = [] try: macros_dir = get_macro_path() if not macros_dir.exists(): macros_dir.mkdir(parents=True) log('Installing', pkg.installFile) shutil.copy2(src_file, pkg.installFile) files.append(pkg.installFile) # Copy files if pkg.files: for f in pkg.files: file_base_path = utils.path_relative(f) dst = Path(pkg.installDir, file_base_path).absolute() src = Path(src_dir, pkg.basePath, file_base_path).absolute() log('Installing ', dst) if pkg.installDir not in dst.parents: result.message = tr( 'Macro package attempts to install files outside of permitted path' ) raise Exception() if src_dir not in src.parents: result.message = tr( 'Macro package attempts to access files outside of permitted path' ) raise Exception() dst_dir = dst.parent if dst_dir != pkg.installDir and dst_dir not in files and not dst_dir.exists( ): dst_dir.mkdir(parents=True) files.append(dst_dir) shutil.copy2(src, dst) files.append(dst) result.ok = True except: log(traceback.format_exc()) result.ok = False if not result.message: result.message = tr( 'Macro was not installed, please contact the maintainer.') # Rollback files.sort(reverse=True) for f in files: try: log("Rollback ", f) if f.is_file(): f.unlink() elif f.is_dir(): shutil.rmtree(f, ignore_errors=True) except: log(traceback.format_exc()) return result
def Initialize(self): log("ExtMan Initialized")