diff --git a/pym/calculate/lib/utils/device.py b/pym/calculate/lib/utils/device.py index 85b1cd0..b381759 100644 --- a/pym/calculate/lib/utils/device.py +++ b/pym/calculate/lib/utils/device.py @@ -720,3 +720,43 @@ devfs = Devfs() udev = Udev() lvm = Lvm(LvmCommand()) raid = Raid(MdadmCommand()) + +class HwinfoError(Exception): + pass + +class HwinfoTimeout(HwinfoError): + pass + +class HwinfoNotExists(HwinfoError): + pass + +class Hwinfo(object): + """ + Объект получения информации из hwinfo + """ + command_timeout = 20 + @property + def hwinfo_cmd(self): + return files.getProgPath("/usr/sbin/hwinfo") + + def framebuffer(self): + """ + Получить вывод hwinfo --framebuffer + """ + return self.run("--framebuffer") + + def run(self, *command): + if not self.hwinfo_cmd: + raise HwinfoNotExists() + try: + return files.process(*[self.hwinfo_cmd] + list(command), + **{'timeout':self.command_timeout}).read() + except files.ProcessTimeout: + raise HwinfoTimeout() + + def resolutions(self): + """ + Получить допустимые разрешения фреймбуффера + """ + re_modes = re.compile("^\s+Mode 0x[0-9a-f]+:\s+(\d+x\d+)\s",re.M) + return tuple(sorted(unique(re_modes.findall(self.framebuffer())))) diff --git a/pym/calculate/lib/utils/files.py b/pym/calculate/lib/utils/files.py index d5ca057..ee7cbce 100644 --- a/pym/calculate/lib/utils/files.py +++ b/pym/calculate/lib/utils/files.py @@ -113,6 +113,8 @@ class PipeProcess(StdoutableProcess): def get_stdout(self): return PIPE +class ProcessTimeout(FilesError): + pass class process(StdoutableProcess): """Execute system command by Popen @@ -160,6 +162,7 @@ class process(StdoutableProcess): self.envdict = kwarg.get("envdict", os.environ.copy()) self.envdict["LANG"] = kwarg.get('lang', 'C') self.langc = "langc" in kwarg + self.timeout = kwarg.get("timeout", None) self.stderr = kwarg.get("stderr", PIPE) self.cwd = kwarg.get("cwd", None) @@ -226,7 +229,10 @@ class process(StdoutableProcess): _stderr = self.pipe.stderr.fileno() reads = [_stdout, _stderr] while True: - ret = select.select(reads, [], []) + ret = select.select(reads, [], [], self.timeout) + if not ret[0]: + self.kill() + raise ProcessTimeout() for fd in ret[0]: if fd == _stdout: s = self.pipe.stdout.readline() @@ -264,7 +270,11 @@ class process(StdoutableProcess): try: self._open() if self.cacheresult is None: - self.cacheresult, self.cacheerr = self.pipe.communicate() + if self.timeout is None: + self.cacheresult, self.cacheerr = self.pipe.communicate() + else: + for line in self.readByLine(): + pass return self.cacheresult except KeyboardInterrupt: self.kill() diff --git a/pym/calculate/lib/utils/portage.py b/pym/calculate/lib/utils/portage.py index ed94162..e2a0c9f 100644 --- a/pym/calculate/lib/utils/portage.py +++ b/pym/calculate/lib/utils/portage.py @@ -1289,7 +1289,6 @@ class SimpleRepositoryMapper(Mapping): class EbuildInfoError(Exception): pass - class EbuildInfo(object): """ Информация о ebuild (DEPEND) из metadata @@ -1303,7 +1302,12 @@ class EbuildInfo(object): self._meta_info_path = path.join(meta_path, atom) if not path.exists(self._meta_info_path): raise EbuildInfoError("Package is not found") - self._info = self._get_info() + self._info = self.prepare_use_flags(self._get_info()) + + @staticmethod + def prepare_use_flags(d): + d["IUSE"] = tuple(sorted(x for x in d.get("IUSE","").split(' ') if x )) + return d def _get_info(self): with open(self._meta_info_path, 'r') as f: @@ -1325,7 +1329,7 @@ class EbuildInfo(object): # if res: # for k in self.support_keys: # if other[k] != self[k]: - # print k,":", other[k], "!=", self[k] + # print "DEBUG:", k,":", other[k], "!=", self[k] return res @@ -1360,7 +1364,7 @@ class InstalledPackageInfo(object): info[key] = value.strip() rep_path = path.join(self._pkg_path, 'repository') info['repository'] = readFile(rep_path).strip() - return info + return EbuildInfo.prepare_use_flags(info) def __getitem__(self, item): return self._info[item] diff --git a/pym/calculate/lib/utils/tools.py b/pym/calculate/lib/utils/tools.py index e4621ed..373dee2 100644 --- a/pym/calculate/lib/utils/tools.py +++ b/pym/calculate/lib/utils/tools.py @@ -27,7 +27,7 @@ from os import path import time from abc import ABCMeta, abstractmethod from types import GeneratorType - +from math import sqrt try: @@ -602,3 +602,27 @@ class Brokenable(object): return f(self, *args, **kw) return wrapper return decor + + +def get_best_nearest_resolution(preferred_res, support_res, aspect_only=False): + """ + Получить наилучшее ближайшее к preferred_res разрешенение из support_res. + + Разрешение берётся ближайшее по размеру диагонали, с применением "штрафного" + коэфициента по разнице аспектов + """ + width, height = map(int, preferred_res.split('x')) + gep = sqrt(height ** 2 + width ** 2) + k = float(width) / float(height) + s = float(width) * float(height) + support_res_int = (tuple(map(int, x.split("x"))) for x in support_res) + support_res_int = ((x, y, sqrt(y*y + x*x), abs(x/float(y)-k)) + for x, y in support_res_int) + if not aspect_only: + support_res_int = [(x,y,g,dasp) + for x,y,g,dasp in support_res_int if x <= width and y <= height] + if not support_res_int: + return None + keyfunc = lambda x,y,g, dasp: g -g * dasp + bestRes = max(support_res_int, key=lambda x:keyfunc(*x) ) + return "%sx%s" % bestRes[0:2] diff --git a/pym/calculate/lib/variables/X11.py b/pym/calculate/lib/variables/X11.py index 8dbc040..a5fe87b 100644 --- a/pym/calculate/lib/variables/X11.py +++ b/pym/calculate/lib/variables/X11.py @@ -62,17 +62,18 @@ class VariableOsX11Resolution(Variable): if self.Get('os_root_type') != 'usb-hdd': xlog = "/var/log/Xorg.0.log" if os.access(xlog, os.R_OK): - reXorgLogParser = re.compile( + logdata = open(xlog, 'r').read() + for re_pat in ( + "Output [\S]+ using initial mode (\d+)x(\d+)", "Virtual screen size determined to be" - " ([0-9]+)\s*x\s*([0-9]+)|" - 'Setting mode "(\d+)x(\d+)[0-9@]"|' - "Output [\S]+ using initial mode (\d+)x(\d+)|" - "Virtual size is (\d+)x(\d+)", re.S) - resXorgLogParser = reXorgLogParser.search( - open(xlog, 'r').read()) - if resXorgLogParser: - return "%sx%s" % filter(lambda x: x, - resXorgLogParser.groups())[:2] + " ([0-9]+)\s*x\s*([0-9]+)", + 'Setting mode "(\d+)x(\d+)[0-9@]"', + "Virtual size is (\d+)x(\d+)"): + reXorgLogParser = re.compile(re_pat, re.S) + resXorgLogParser = reXorgLogParser.search(logdata) + if resXorgLogParser: + return "%sx%s" % filter(lambda x: x, + resXorgLogParser.groups())[:2] # get resolution from xorg.conf xorgconf = "/etc/X11/xorg.conf"