1# 2# Copyright (C) 2016-2019 by Razvan Radulescu, Nathan Lovato, and contributors 3# 4# This file is part of Power Sequencer. 5# 6# Power Sequencer is free software: you can redistribute it and/or modify it under the terms of the 7# GNU General Public License as published by the Free Software Foundation, either version 3 of the 8# License, or (at your option) any later version. 9# 10# Power Sequencer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 11# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12# GNU General Public License for more details. 13# 14# You should have received a copy of the GNU General Public License along with Power Sequencer. If 15# not, see <https://www.gnu.org/licenses/>. 16# 17from collections import deque 18from shutil import which 19 20 21class BSError(Exception): 22 """ 23 Custom Exception raised if Blender is called with a python script argument 24 and gives error while trying to execute the script. 25 """ 26 27 pass 28 29 30class ToolError(Exception): 31 """Raised if external dependencies aren't found on system. 32 """ 33 34 pass 35 36 37def checktools(tools): 38 tools = [(t, which(t) or "") for t in tools] 39 check = {"tools": tools, "test": all(map(lambda x: x[1], tools))} 40 if not check["test"]: 41 msg = ["BPSRender couldn't find external dependencies:"] 42 msg += [ 43 "[{check}] {tool}: {path}".format( 44 check="v" if path is not "" else "X", tool=tool, path=path or "NOT FOUND" 45 ) 46 for tool, path in check["tools"] 47 ] 48 msg += [ 49 ( 50 "Check if you have them properly installed and available in the PATH" 51 " environemnt variable." 52 ), 53 "Exiting...", 54 ] 55 raise ToolError("\n".join(msg)) 56 57 58def checkblender(what, search, cp, s): 59 """ 60 IMPURE 61 Check Blender output for python script execution error. 62 63 Parameters 64 ---------- 65 what: str 66 A tag used in the exception message. 67 search: iter(str) 68 One or more string(s) to search for in Blender's output. 69 cp: Popen 70 Blender subprocess. 71 s: PIPE 72 Blender's output. 73 74 Returns 75 ------- 76 out: PIPE 77 The same pipe `s` is returned so that it can be iterated over on later 78 steps. 79 """ 80 if not isinstance(search, list): 81 search = [search] 82 for search_item in search: 83 if search_item in s: 84 message = ( 85 "Script {what} was not properly executed in" " Blender".format(what=what), 86 "CMD: {cmd}".format(what=what, cmd=" ".join(cp.args)), 87 "DUMP:".format(what=what), 88 s, 89 ) 90 raise BSError("\n".join(message)) 91 return s 92 93 94def printw(cfg, text, s="\n", e="...", p="", **kwargs): 95 p = p or cfg["pre"]["work"] 96 print("{s}{p} {}{e}".format(text, s=s, e=e, p=p), **kwargs) 97 98 99def printd(cfg, text, s="", e=".", p="", **kwargs): 100 p = p or cfg["pre"]["done"] 101 printw(cfg, text, s=s, e=e, p=p, **kwargs) 102 103 104def prints(cfg, text, s="", e=".", p="", **kwargs): 105 p = p or cfg["pre"]["skip"] 106 printw(cfg, text, s=s, e=e, p=p, **kwargs) 107 108 109def kickstart(it): 110 deque(it, maxlen=0) 111