Множественные изменения для работы с цветным выводом

master3.3 3.2.0_alpha2
Mike Hiretsky 10 years ago
parent bae95d943c
commit 69740f6843

@ -14,41 +14,26 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import os, gettext
import os
import gettext
from gettext import gettext as _
import threading
import types
import sys
from cl_overriding import __findFileMO
import re
from gettext import Catalog
class lang:
"""Multilanguage class
Using:
import sys
from calculate.lib.cl_lang import lang
# set engligh language
tr = lang('en')
# set autodetect language
tr = lang()
# set translate domain calc
tr.setGlobalDomain('calc')
# set local translate domain
#tr.setLocalDomain('calc')
# set translate for this module
tr.setLanguage(sys.modules[__name__])
or
lang(_local="calc",__setLang=sys.modules[__name__])
class lang:
"""
Multilanguage class
"""
_modnames = {}
GP = [""]
def __init__(self):
self.nameDomain = self.GP[0]
#self.nameDomain = ''
self.__catalog = None
# translate language for all modules
self._translators = {}
@ -64,17 +49,16 @@ class lang:
if the module export other modules, then lang will be
set for them
Method must be call after module for translate"""
t = vars(module)
if glob:
for name,mod in vars(module).items():
if type(mod) == types.ModuleType and \
not name.startswith('__') and \
not name in sys.builtin_module_names and \
(hasattr(mod,'__file__') and (
"calculate" in mod.__file__ or
not mod.__file__.startswith('/usr/lib'))):
not name.startswith('__') and \
not name in sys.builtin_module_names and \
(hasattr(mod, '__file__') and (
"calculate" in mod.__file__ or
not mod.__file__.startswith('/usr/lib'))):
self.__setLang(mod)
self.setLanguage(mod,True)
self.setLanguage(mod, True)
return self.__setLang(module)
def __setLang(self,module):
@ -86,15 +70,20 @@ class lang:
module._ = self.__translate
self._modnames[module.__name__] = module._
def __gettranslate(self):
@staticmethod
def get_current_lang():
"""
Получить текущий язык
"""
env = os.environ
curThread = threading.currentThread()
if hasattr(curThread,"lang"):
l = curThread.lang
elif env.has_key('LANG'):
l = env['LANG'].split('.')[0].split("_")[0]
else:
l = "en"
cur_thread = threading.currentThread()
if hasattr(cur_thread, "lang"):
return cur_thread.lang
return env.get("LANG", "en_US.UTF-8").split('.')[0].split("_")[0]
def __gettranslate(self):
l = self.get_current_lang()
if l in self._translators:
return self._translators[l]
if l == 'en':
@ -147,8 +136,44 @@ def getLazyLocalTranslate(translateFunc):
class translate:
def __init__(self,s):
self.s = s
self._format_args = None
def __str__(self):
return translateFunc(self.s)
if self._format_args is None:
return translateFunc(self.s)
else:
return translateFunc(self.s).format(*self._format_args[0],
**self._format_args[1])
def __hash__(self):
return hash(self.s)
def format(self, *args, **kwargs):
self._format_args = (args,kwargs)
return self
return translate
class RegexpLocalization(object):
def __init__(self, domain, languages=[lang.get_current_lang()]):
try:
self.set_translate_dict(Catalog(domain,
languages=languages)._catalog)
except IOError:
self._catalog = {}
def set_translate_dict(self, d):
def create_key(k):
try:
return re.compile(k.replace("\\\\", "\\"))
except re.error:
return None
self._catalog = filter(lambda x: x[0],
((create_key(k), v) for k, v in
sorted(d.items(), reverse=True) if k))
def translate(self, s):
for k, v in self._catalog:
s = k.sub(v, s)
return s

@ -814,7 +814,7 @@ class SimpleDataVars:
"""
Unserialize form string for varname
"""
fixEmpty = lambda x:"" if x=="''" or x=='""' else x
fixEmpty = lambda x:"" if x=="''" or x=='""' else x.strip()
def getList(delimeter=','):
def wrapper(val):
if val == "":

@ -0,0 +1,52 @@
#-*- coding: utf-8 -*-
# Copyright 2014 Calculate Ltd. http://www.calculate-linux.org
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from printing import Print
from palette import TextState
from info import Terminal
Colors = TextState.Colors
from converter import ConsoleCodes256Converter, XmlConverter
from output import XmlOutput, ColorTerminal16Output, TerminalPositionOutput, \
ColorTerminal256Output
def convert_console_to_xml(s):
"""Преобразовать вывод консоли в xml для внутреннего использования"""
return ConsoleCodes256Converter(output=XmlOutput()).transform(s)
def get_color_print():
"""
Получить объект для вывода текста в цвете
"""
return Print(output=XmlOutput())
def get_terminal_output():
return (ColorTerminal256Output()
if Terminal().colors > 16
else ColorTerminal16Output())
def get_terminal_print(printfunc=lambda x: x):
"""
Получить объект для вывода в терминал
"""
# TODO: возвращать объект 256 или 16 терминал в зависимости от параметров
return Print(output=get_terminal_output(),
position_controller=TerminalPositionOutput(),
printfunc=printfunc)
def convert_xml_to_terminal(s):
return XmlConverter(output=get_terminal_output()).transform(s)

@ -17,13 +17,26 @@
from output import BaseOutput
from palette import (TextState, BaseColorMapping, ConsoleCodesInfo,
LightColorMapping, ConsoleColor256, XmlFormat)
from calculate.lib.utils.tools import SavableIterator
from calculate.lib.utils.tools import SavableIterator, ignore
from itertools import ifilter
from HTMLParser import HTMLParser
import re
class ConsoleCodesConverter(object):
class BaseConverter(object):
"""
Базовый класс обработки (ничего не конвертирует - возвращает как есть)
"""
def __init__(self, output=BaseOutput()):
self.output = output
def transform(self, s):
return self.output.outputText(s)
def detect(self, s):
return True
class ConsoleCodesConverter(BaseConverter):
"""Преобразователь текста из цветного консольного вывода через объект
форматирования.
@ -33,10 +46,11 @@ class ConsoleCodesConverter(object):
>>> outtext = "\033[32;1mHello\033[0;39m"
>>> cct.transform(outtext)
'Hello'
>>> from output import SpanCssOutput
>>> cct = ConsoleCodesConverter(SpanCssOutput())
>>> outtext = "\033[32;1mHello\033[0;39m"
>>> cct.transform(outtext)
'<span style="colortext:Green;font-weight:bold;">Hello</span>'
'<span style="color:Green;font-weight:bold;">Hello</span>'
"""
class CodeElement:
@ -52,7 +66,7 @@ class ConsoleCodesConverter(object):
def parse(self, code, codes):
"""Обработать код, вызвать действие"""
self.action()
return self.action()
def _next_code(self, other):
"""
@ -77,21 +91,22 @@ class ConsoleCodesConverter(object):
self.end = end
def tryParse(self, code):
cci = ConsoleCodesInfo
return code >= self.begin and code <= self.end
def parse(self, code, codes):
cci = ConsoleCodesInfo
return self.action(self.mapColors.get(code - self.begin,
TextState.Colors.DEFAULT))
def __init__(self, output=None, escSymb="\033"):
self.output = output or BaseOutput()
self.escSymb = escSymb
self.escBlock = r"{esc}\[(\d+(?:;\d+)*)m".format(esc=escSymb)
self.escBlock = (r"{esc}(?:\[(\d+(?:;\d+)*)m|"
"\]\d+;.*?\x07|\[\d*[A-D])".format(esc=escSymb))
self.otherSymb = "\r*\n"
self.reEscBlock = re.compile(self.escBlock)
self.reParse = re.compile(
"(?:{0})?(.*?)(?=$|{0})".format(self.escBlock),
"(?:{0}|({1}))?(.*?)(?=$|{0}|{1})".format(self.escBlock,
self.otherSymb),
re.DOTALL)
resetBoldHalfbright = lambda: (
(self.output.resetBold() or "") +
@ -124,8 +139,19 @@ class ConsoleCodesConverter(object):
background = self.ColorElement(begin=cci.BACKGROUND,
end=cci.BACKGROUND_END,
action=self.output.setBackground)
newline = element(lambda code: "\r" in code or "\n" in code,
self.output.newLine)
self.grams = [reset, bold, halfbright, underline, nounderline, normal,
invert, noinvert, foreground, background]
invert, noinvert, reset_foreground, reset_background,
foreground, background, newline]
def evaluteGram(self, code, codes=None):
"""Выполнить грамматику"""
if codes is None:
codes = SavableIterator([])
for gram in ifilter(lambda x: x.tryParse(code),
self.grams):
return gram.parse(code, codes)
def transform(self, s):
"""
@ -133,18 +159,18 @@ class ConsoleCodesConverter(object):
"""
def generator():
for ctrl, txt, _s in self.reParse.findall(s):
for ctrl, other, txt, _s in self.reParse.findall(s):
if ctrl:
codes = SavableIterator(ctrl.split(';'))
for code in codes:
code = int(code)
res = ""
for gram in ifilter(lambda x: x.tryParse(code),
self.grams):
res = gram.parse(code, codes)
break
res = self.evaluteGram(code, codes)
if res:
yield res
elif other:
res = self.evaluteGram(other)
if res:
yield res
if txt:
yield self.output.outputText(txt)
yield self.output.endText()
@ -199,30 +225,46 @@ class ConsoleCodes256Converter(ConsoleCodesConverter):
self.grams.insert(0, foreground256)
self.grams.insert(0, background256)
class XmlConverter(object):
class XmlConverter(BaseConverter):
"""
Преобразователь текста из внутреннего xml формата
"""
unescaper = XmlFormat.unescaper
def __init__(self, output=None):
Tags = XmlFormat.Tags
FontAttr = XmlFormat.FontAttributes
self.output = output or BaseOutput()
self.tagMap = {Tags.BOLD: self.output.setBold,
Tags.HALFBRIGHT: self.output.setHalfbright,
Tags.INVERT: self.output.setInvert,
Tags.UNDERLINE: self.output.setUnderline,
Tags.FONT: self.parseFont}
self.tagMap = {
Tags.BOLD: self.output.setBold,
Tags.HALFBRIGHT: self.output.setHalfbright,
Tags.INVERT: self.output.setInvert,
Tags.UNDERLINE: self.output.setUnderline,
Tags.FONT: self.parseFont
}
self.singletagMap = {
Tags.NEWLINE: self.output.newLine
}
self.colorMap = {FontAttr.FOREGROUND.lower(): self.output.setForeground,
FontAttr.BACKGROUND.lower(): self.output.setBackground}
self.reMatch = re.compile("<(?:%s)" % "|".join(self.tagMap.keys()),
re.I)
self.parser = HTMLParser()
self.parser.handle_starttag = self.startElementHandler
self.parser.handle_endtag = self.endElementHandler
self.parser.handle_data = self.characterDataHandler
self.parser = self.createParser()
def parseFont(self, attrs):
def createParser(self):
"""
Создать парсер HTML кода
"""
parser = HTMLParser()
parser.handle_starttag = self.startElementHandler
parser.handle_endtag = self.endElementHandler
parser.handle_data = self.characterDataHandler
parser.handle_startendtag = self.startendElementHandler
parser.handle_entityref = self.entityrefElementHandler
return parser
def parseFont(self, *attrs):
for k, v in attrs:
k = str(k).lower()
if k in self.colorMap:
@ -237,44 +279,73 @@ class XmlConverter(object):
def addResultToOutdata(f):
"""Добавить возвращаемый результат в список self.__outdata"""
def wrapper(self, *args):
res = f(self, *args)
if res:
self.__outdata.append(res)
return res
return wrapper
def _buildTaq(self, name, attrs=[], startendTag=False, endTag=False):
"""
Создать тэг по параметрам
"""
lslash, rslash = '', ''
if startendTag:
rslash = '/'
elif endTag:
lslash = '/'
if attrs:
return "<{name} {attrs}{rslash}>".format(
name=name, attrs=" ".join(['%s="%s"' % (k, v)
for k, v in attrs]),
rslash=rslash)
else:
return "<{lslash}{name}{rslash}>".format(lslash=lslash, name=name,
rslash=rslash)
@addResultToOutdata
def startElementHandler(self, name, attrs):
"""Обработчик начального тега"""
if name in self.tagMap:
self.output.pushState()
self.__tagStack.append(name)
if attrs:
return self.tagMap[name](attrs)
else:
return self.tagMap[name]()
with ignore(TypeError):
return self.tagMap[name](*attrs)
else:
if attrs:
s = "<%s %s>" % (name,
" ".join(['%s="%s"' % (k, v)
for k, v in attrs.items()]))
return self.output.outputText(s)
else:
return self.output.outputText("<%s>" % name)
return self.output.outputText(self._buildTaq(name, attrs))
@addResultToOutdata
def startendElementHandler(self, name, attrs):
"""Обработчик одиночного тега"""
if name in self.singletagMap:
with ignore(TypeError):
return self.singletagMap[name](*attrs)
else:
return self.output.outputText(
self._buildTaq(name, attrs, startendTag=True))
@addResultToOutdata
def endElementHandler(self, name):
"""Обработчик завершающего тега"""
if name in self.tagMap:
if name in self.__tagStack:
while self.__tagStack and self.__tagStack.pop() != name:
self.output.popState()
self.output.popState()
else:
return self.output.outputText("</%s>" % name)
return self.output.outputText(self._buildTaq(name, endTag=True))
@addResultToOutdata
def characterDataHandler(self, data):
return self.output.outputText(data)
"""Обработчик текста в тэгах"""
return self.output.outputText(self.unescaper(data))
@addResultToOutdata
def entityrefElementHandler(self, data):
return self.output.outputText(self.unescaper("&%s;" % data))
def detect(self, s):
return bool(self.reMatch.search(s))

@ -0,0 +1,43 @@
#-*- coding: utf-8 -*-
# Copyright 2014 Calculate Ltd. http://www.calculate-linux.org
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import curses
from os import environ
import sys
import struct
import fcntl
import termios
class Terminal(object):
def __init__(self):
curses.setupterm(environ.get('TERM', 'linux'))
@property
def colors(self):
return curses.tigetnum('colors')
@property
def width(self):
s = struct.pack("HHHH", 0, 0, 0, 0)
fd_stdout = sys.stdout.fileno()
try:
x = fcntl.ioctl(fd_stdout, termios.TIOCGWINSZ, s)
except IOError:
# если ошибка то ширина 80 символов
return 80
#(rows, cols, x pixels, y pixels)
return struct.unpack("HHHH", x)[1]

@ -13,8 +13,10 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import re
from xml.etree import ElementTree as ET
from calculate.lib.utils.text import MultiReplace
from palette import (TextState, BaseColorMapping,
ConsoleCodeMapping, LightColorMapping, ConsoleColor256,
ConsoleCodesInfo, SpanPalette, XmlFormat)
@ -128,6 +130,12 @@ class BaseOutput(object):
Восстановить состояние текста из стека
"""
def newLine(self):
"""
Вывести текст на новой строке
"""
return "\n"
class SaveAttrOutput(BaseOutput):
"""
Базовый класс с сохранением атрибутов
@ -317,6 +325,8 @@ class ColorTerminalOutput(SaveAttrOutput):
self.reset()
return self.outputText("")
def newLine(self):
return "\n"
class ColorTerminal256Output(ColorTerminalOutput):
"""
@ -404,7 +414,6 @@ class SpanCssOutput(SaveAttrOutput):
"""
Форматирует текст для вывода в консоль
"""
def __init__(self, state=None, palette=SpanPalette()):
SaveAttrOutput.__init__(self, state=state)
self.palette = palette
@ -465,19 +474,24 @@ class SpanCssOutput(SaveAttrOutput):
lattr, rattr = self.getTags(self.prev_state, self.current_state)
else:
lattr = rattr = ""
return lattr + s + rattr
return lattr + XmlFormat.escaper(s) + rattr
def endText(self):
self.reset()
return ""
def newLine(self):
return "<br/>"
class XmlOutput(SaveAttrOutput):
"""
Форматирует текст c описанием формата в XML для внутренней передачи
Bugs: игнорирует первоначальное состояние (state)
не экономное использование тэгов (например при выводе нескольких строк
"""
escaper = XmlFormat.escaper
def __init__(self, state=None):
super(XmlOutput, self).__init__(state=state)
self.clear_state = TextState()
@ -531,7 +545,7 @@ class XmlOutput(SaveAttrOutput):
for text in generator(element):
yield text
if root.text:
yield root.text
yield self.escaper(root.text)
yield "</%s>" % root.tag
return "".join(filter(None, list(generator(xml))))
@ -539,8 +553,113 @@ class XmlOutput(SaveAttrOutput):
if self.clear_state != self.current_state:
return self.xmlToString(self.getXML(self.current_state, s))
else:
return s
return self.escaper(s)
def endText(self):
self.reset()
return ""
def newLine(self):
return "<br/>"
class BasePositionOutput(object):
"""
Объект составляющий ESC последовательности для управлением местом вывода
"""
def moveCursorUp(self, count=1):
"""
Переместить курсор вверх
"""
return ""
def moveCursorDown(self, count=1):
"""
Переместить курсор вниз
"""
return ""
def moveCursorRight(self, count=1):
"""
Переместить курсор вправо
"""
return ""
def moveCursorLeft(self, count=1):
"""
Переместить курсор влево
"""
return ""
def clearLine(self, whole_line=False):
"""
Очистить строку от курсора до конца или всю строку
"""
return ""
def savePosition(self):
"""
Сохранить положение курсора
"""
return ""
def restorePosition(self):
"""
Восстановить положение курсора
"""
return ""
class TerminalPositionOutput(BasePositionOutput):
"""
Управление позицией вывода текста в терминале
"""
class Codes:
UP = 'A'
DOWN = 'B'
RIGHT = 'C'
LEFT = 'D'
CLEAR_LINE = 'K'
CLEAR_FROM_CURSOR = '1'
CLEAR_WHOLE_LINE = '2'
SAVE_POSITION = 's'
RESTORE_POSITION = 'u'
def _createEscCode(self, attrs):
"""
Создать ESC строку
"""
return '\033[%s' % attrs
def _moveCursor(self, direct, count):
if int(count) > 1:
count = str(count)
else:
count = ""
return self._createEscCode("%s%s" % (count, direct))
def moveCursorDown(self, count=1):
return self._moveCursor(self.Codes.DOWN, count)
def moveCursorUp(self, count=1):
return self._moveCursor(self.Codes.UP, count)
def moveCursorRight(self, count=1):
return self._moveCursor(self.Codes.RIGHT, count)
def moveCursorLeft(self, count=1):
return self._moveCursor(self.Codes.LEFT, count)
def clearLine(self, whole_line=False):
if whole_line:
mode_code = self.Codes.CLEAR_WHOLE_LINE
else:
mode_code = self.Codes.CLEAR_FROM_CURSOR
return self._createEscCode("%s%s"%(mode_code, self.Codes.CLEAR_LINE))
def savePosition(self):
return self._createEscCode(self.Codes.SAVE_POSITION)
def restorePosition(self):
return self._createEscCode(self.Codes.RESTORE_POSITION)

@ -17,6 +17,7 @@
import re
from itertools import chain
from math import pow
from calculate.lib.utils.text import MultiReplace
class ConsoleCodesInfo:
@ -371,6 +372,52 @@ class DarkPastelsPalette(SpanPalette):
["#709080", "#DCA3A3", "#72D5A3", "#F0DFAF",
"#94BFF3", "#EC93D3", "#93E0E3", "#FFFFFF"]))
class WhitePalette(SpanPalette):
"""
Палитра черное на белом
"""
defaultColor = ["#141414", "#141414", "#272727"]
defaultBackground = "#ffffff"
normalBright = dict(zip(TextState.normalColors,
["#141414", "#742523", "#237425", "#737423",
"#252374", "#742373", "#237374", "#c1c1c1"]))
highBright = dict(zip(TextState.lightColors,
["#272727", "#cc5755", "#55cc57", "#cacc55",
"#5755cc", "#cc55ca", "#55cacc", "#ffffff"]))
class GreyPaletteOld(SpanPalette):
"""
Палитра черное на светло-сером
"""
defaultColor = ["#101010", "#101010", "#505050"]
defaultBackground = "#e4e1e0"
normalBright = dict(zip(TextState.normalColors,
["#101010", "#902c2b", "#2b902c", "#8f902b",
"#2c2b90", "#902b8f", "#2b8f90", "#b9b9b9"]))
highBright = dict(zip(TextState.lightColors,
["#303030", "#c6403d", "#3dc640", "#c3c63d",
"#403dc6", "#c63dc3", "#3dc3c6", "#e4e1e0"]))
class GreyPalette(SpanPalette):
"""
Палитра черное на светло-сером
"""
defaultColor = ["#101010", "#101010", "#505050"]
defaultBackground = "#ffffff"
normalBright = dict(zip(TextState.normalColors,
["#101010", "#902c2b", "#2b902c", "#8f902b",
"#2c2b90", "#902b8f", "#2b8f90", "#b9b9b9"]))
highBright = dict(zip(TextState.lightColors,
["#303030", "#c6403d", "#3dc640", "#c3c63d",
"#403dc6", "#c63dc3", "#3dc3c6", "#ffffff"]))
class XmlFormat:
"""
Константы для внутреннего формата XML
@ -381,7 +428,12 @@ class XmlFormat:
FONT = "font"
HALFBRIGHT = "dark"
INVERT = "invert"
NEWLINE = "br"
class FontAttributes:
BACKGROUND = "bgColor"
FOREGROUND = "color"
escape_map = {'<': '&lt;', '>': '&gt;'}
escaper = MultiReplace(escape_map)
unescaper = MultiReplace({v: k for k, v in escape_map.items()})

@ -0,0 +1,81 @@
#-*- coding: utf-8 -*-
# Copyright 2014 Calculate Ltd. http://www.calculate-linux.org
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from output import BaseOutput, BasePositionOutput
class Print(object):
"""
Упрощенное получение строки при помощи Output объектов """
def __init__(self, output=BaseOutput(),
position_controller=BasePositionOutput(),
printfunc=lambda x:x):
self.output = output
self.position_controller = position_controller
self.buffer = []
self.printfunc = printfunc
@property
def bold(self):
self.buffer.append(self.output.setBold())
return self
def foreground(self, color):
self.buffer.append(self.output.setForeground(color))
return self
def background(self, color):
self.buffer.append(self.output.setBackground(color))
return self
@property
def invert(self):
self.buffer.append(self.output.setInvert())
return self
@property
def halflight(self):
self.buffer.append(self.output.setHalfbright())
return self
def up(self, count):
self.buffer.append(self.position_controller.moveCursorUp(count))
return self
def down(self, count):
self.buffer.append(self.position_controller.moveCursorDown(count))
return self
def right(self, count):
self.buffer.append(self.position_controller.moveCursorRight(count))
return self
def left(self, count):
self.buffer.append(self.position_controller.moveCursorLeft(count))
return self
@property
def clear_line(self):
self.buffer.append(self.position_controller.clearLine(whole_line=True))
return self
def __call__(self, s, *args, **kwargs):
s = s.format(*args, **kwargs)
self.buffer.append(self.output.outputText(s))
self.buffer.append(self.output.endText())
try:
return self.printfunc("".join(filter(None, self.buffer)))
finally:
self.buffer = []

@ -236,6 +236,7 @@ class process:
"""Failed or not"""
return self.returncode() != 0
def getModeFile(nameFile, mode="all"):
"""Выдает информацию о файле
mode=="all"
@ -691,6 +692,15 @@ def readFile(filename,tailbyte=None):
pass
return ""
def writeFile(filename):
"""
Открыть файл на запись и создать необходимые каталоги
"""
dn = path.dirname(filename)
if not path.exists(dn):
os.makedirs(dn)
return open(filename,'w')
import common
class getProgPath:

@ -15,8 +15,12 @@
# limitations under the License.
from itertools import tee
from contextlib import contextmanager
class SavableIterator:
"""
Итератор с возможность сохранять и восстанавливать состояние
"""
def __init__(self,seq):
self.seq = iter(seq)
self.back = None
@ -26,11 +30,93 @@ class SavableIterator:
def save(self):
self.seq, self.back = tee(self.seq)
return self
def restore(self):
if self.back:
self.seq, self.back = tee(self.back)
return self
def next(self):
return self.seq.next()
@contextmanager
def ignore(exception):
try:
yield
except exception:
pass
class AddonError(Exception):
"""
Исключение с добавочным сообщением
"""
def __init__(self, msg, addon=None):
self.message = msg
self.addon = addon
Exception.__init__(self, msg)
class FalseObject(object):
"""
Объект-заглушка при любом сравнении возвращает False
"""
def __lt__(self,other):
return False
def __nonzero__(self):
return False
__gt__ = __ge__ = __le__ = __eq__ = __ne__ = __lt__
class Sizes(object):
K = KiB = kibibyte = 1024
kB = kilobyte = 1000
M = MiB = mibibyte = K * 1024
Mb = megabyte = kB * 1000
G = GiB = gibibyte = M * 1024
Gb = gigabyte = Mb * 1000
T = TiB = tibibyte = G * 1024
Tb = terabyte = Gb * 1000
def __getattr__(self,name):
if name.startswith('from_'):
return lambda x:x*getattr(Sizes,name[5:])
elif name.startswith('to_'):
return lambda x:x/getattr(Sizes,name[3:])
else:
raise AttributeError
def imap_regexp(re_compiled, l, whole=False):
"""
Обработать список регулярным выражением и вернуть полученные группы
"""
if whole:
retfunc = lambda x: x.group()
else:
retfunc = lambda x: x.groups()
return (retfunc(x) for x in (re_compiled.search(x) for x in l) if x)
def cached(each_instance=False):
"""
Кэширование результата
"""
def cache_wrapper(func):
value = {}
def wrapper(*args, **kwargs):
if each_instance:
if args[0] not in value:
value[args[0]] = func(*args, **kwargs)
return value[args[0]]
else:
if not None in value:
value[None] = func(*args, **kwargs)
return value[None]
return wrapper
if each_instance in (True,False):
return cache_wrapper
else:
return cache_wrapper(each_instance)

Loading…
Cancel
Save