Paste #227104 |
pasted on 14.10.2021 15:43
- Edit to this paste
- Raw
-
Compare with paste
#
Text paste
# -*- coding: utf-8 -*-
# Copyright 2012-2016 Mir Calculate. 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 pickle
import random
import threading
import sys
import os
import re
from os import path
import glob
import traceback
from traceback import print_exc
from .core_interfaces import (CoreServiceInterface, MethodsInterface)
from calculate.install.distr import Distributive
from calculate.lib.cl_log import log
from calculate.lib.utils.colortext import convert_console_to_xml
from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate
_ = lambda x: x
setLocalTranslate('cl_core3', sys.modules[__name__])
__ = getLazyLocalTranslate(_)
from calculate.lib.utils.files import (process, readFile, processProgress,
readLinesFile,
makeDirectory, getProgPath)
from calculate.lib.datavars import DataVarsError, CriticalError, Variable
from calculate.lib.utils.content import getCfgFiles
from itertools import *
import calculate.contrib
from spyne import String, Integer, Boolean, Array
from .api_types import ReturnedMessage, CommonInfo, ReturnProgress
from .api_types import (Field, GroupField, ViewInfo, ViewParams)
from calculate.lib.cl_template import Template
from calculate.lib.datavars import DataVars
from .loaded_methods import LoadedMethods
class CommonMethods(MethodsInterface):
def dispatchConf(self, filesApply=None, prefix="/"):
"""
Common dispatch conf. Using if ._cfg files created.
"""
def normalize_config(text):
"""
Нормализовать конфигурационный файл для сравнения:
* удалить calculate заголовок
* добавить перевод строки в конец если файл без перевода строки
"""
if text.endswith('\n'):
return Template.removeComment(text)
else:
return "%s\n" % Template.removeComment(text)
i_orig, i_data = 0, 1
i_mime, i_cfgname = 0, 1
cfg_files = getCfgFiles(prefix=prefix).items()
info = [x for x in cfg_files
if filesApply is None or x[i_data][0][i_cfgname] in filesApply]
max_info = len(info)
for ind, data in enumerate(info):
out = []
orig, data = data
data = data[0]
origdata = readFile(orig)
newdata = readFile(data[i_cfgname])
pattern = "%s/._cfg????_%s" % (os.path.dirname(orig),
os.path.basename(orig))
answ_map = {'usenew': 'use new', 'skip': 'next'}
dispatch_var = self.clVars.Get('cl_dispatch_conf')
for fn in glob.glob(pattern):
try:
if fn == data[i_cfgname]:
continue
os.unlink(fn)
except (OSError, IndexError):
pass
if (self.clVars.Get('cl_autoupdate_set') == 'on' or
origdata == newdata):
answ = "use new"
elif dispatch_var in answ_map:
answ = answ_map.get(dispatch_var)
else:
orig_content = normalize_config(readFile(orig))
new_content = normalize_config(readFile(data[i_cfgname]))
if orig_content == new_content:
answ = "use new"
else:
for i, s in enumerate(list(process("diff", "-Nu",
orig, data[i_cfgname]))):
s = convert_console_to_xml(s)
if s.startswith('+') and i > 1:
out.append('<font color="green">%s</font>' % s)
elif s.startswith('-') and i > 1:
out.append('<font color="red">%s</font>' % s)
else:
out.append(s)
self.printPre("<br/>".join(out))
self.printSUCCESS(_("({one} of {_all}) -- {fname}").format(
one=ind + 1, _all=max_info, fname=orig))
answ = self.askChoice(_("Choose a configuration action:"),
answers=(("zap new", _("Zap new")),
("use new", _("Use new")),
("next", _("Next"))))
if answ == "next":
continue
elif answ == "use new":
try:
with open(orig, 'w') as fd:
fd.write(readFile(data[i_cfgname]))
os.unlink(data[i_cfgname])
if filesApply:
try:
i = filesApply.index(data[i_cfgname])
filesApply[i] = orig
except Exception as e:
print(str(e))
except Exception as e:
print(str(e))
self.printERROR(
_("Failed to copy {ffrom} to {fto}").format(
ffrom=data[i_cfgname], fto=orig))
continue
elif answ == "zap new":
try:
os.unlink(data[i_cfgname])
if filesApply:
try:
filesApply.remove(data[i_cfgname])
except Exception as e:
print(str(e))
except OSError:
self.printERROR(
_("Failed to remove %s") % data[i_cfgname])
return True
def setVariable(self, varname, varvalue, force=False):
"""
Установить значение переменной
"""
self.clVars.Set(varname, varvalue, force=force)
return True
def invalidateVariables(self, *variables):
for varname in (x.rpartition('.')[2] for x in variables):
self.clVars.Invalidate(varname, force=True)
return True
def applyTemplates(self, target=None, useClt=None, cltFilter=False,
root=None, useDispatch=True, critical=False):
"""
Применить шаблоны.
Args:
target: дистрибутив, куда необходимо выполнить шаблоны (/ по умолчанию)
useClt: использовать clt шаблоны
cltFilter: применять фильтр на clt шаблоны
root: каталог, куда будут наложны шаблоны (cl_root_path)
"""
from calculate.lib.cl_template import (TemplatesError, ProgressTemplate)
if target is None:
chroot = '/'
elif isinstance(target, Distributive):
chroot = target.getDirectory()
else:
chroot = target
if root is None:
root = '/'
elif isinstance(root, Distributive):
root = root.getDirectory()
clt_filter = True if cltFilter in (True, "on") else False
self.clVars.Set("cl_chroot_path", chroot, True)
self.clVars.Set("cl_root_path", root, True)
# определение каталогов содержащих шаблоны
use_clt = useClt in ("on", True)
self.addProgress()
null_progress = lambda *args, **kw: None
dispatch = self.dispatchConf if useDispatch else None
cl_templ = ProgressTemplate(null_progress, self.clVars,
cltObj=use_clt,
cltFilter=clt_filter,
printSUCCESS=self.printSUCCESS,
printWARNING=self.printWARNING,
askConfirm=self.askConfirm,
dispatchConf=dispatch,
printERROR=self.printERROR,
critical=critical)
try:
cl_templ.applyTemplates()
if cl_templ.hasError():
if cl_templ.getError():
raise TemplatesError(cl_templ.getError())
finally:
if cl_templ:
if cl_templ.cltObj:
cl_templ.cltObj.closeFiles()
cl_templ.closeFiles()
return True
class CommonLink():
"""
Объект-связка объектов тип Install,Client,Action с Common объектом
"""
com = None
@staticmethod
def link_object(source, target):
for fn in (x for x in dir(CoreWsdl.Common) if not x.startswith("_")):
if hasattr(source, fn):
setattr(target, fn, getattr(source, fn))
def set_link(self, com):
"""
Установить связь с Common объектом
"""
self.com = com
self.link_object(com, self)
class ActionError(Exception):
pass
class Tasks():
"""
Класс для создания проверок необходимости запуска задачи в зависимости
от результатра работы предыдущих задач
"""
def __init__(self, check):
self.check = check
def __call__(self, result, all_result):
return self.check(result, all_result)
def __or__(self, y):
return Tasks(lambda result, all_result: self(result, all_result) or y(result, all_result))
def __ror__(self, y):
return Tasks(lambda result, all_result: y(result, all_result) or self(result, all_result))
def __and__(self, y):
return Tasks(lambda result, all_result: self(result, all_result) and y(result, all_result))
def __rand__(self, y):
return Tasks(lambda result, all_result: y(result, all_result) and self(result, all_result))
def __invert__(self):
return Tasks(lambda result, all_result: not self(result, all_result))
@classmethod
def _result(self, result, all_result):
return result
@classmethod
def success_all(cls, *tasks):
"""
Все указанные задачи выполнены и выполнены без ошибок
"""
return cls(
lambda *args: all(x in cls._result(*args) and cls._result(*args)[x] for x in tasks))
@classmethod
def success_one_of(cls, *tasks):
"""
Хотя бы одна из задач выполнена и хотя бы одна из выполненных без ошибок
"""
return cls(
lambda *args: any(cls._result(*args)[x] for x in tasks if x in cls._result(*args)))
@classmethod
def success(cls, inessential=()):
"""
Все ранее запущенные задачи успешно завершены, результат задач
inessential не важен
"""
return cls(lambda *args: all(cls._result(*args)[x] for x in cls._result(*args)
if x not in inessential))
@classmethod
def failed(cls, inessential=()):
"""
Хотя бы одна из задач завершилась неудачно, результат задач
inessential не важен
"""
return cls(lambda *args: any(not cls._result(*args)[x] for x in cls._result(*args)
if x not in inessential))
@classmethod
def failed_all(cls, *tasks):
"""
Выполнена хотя бы одна задача и все те, которые выполнены с ошибкой
"""
def not_empty_all(l):
l = list(l)
return bool(l and all(l))
return cls(
lambda *args: not_empty_all(not cls._result(*args)[x] for x in tasks if x in cls._result(*args)))
@classmethod
def failed_one_of(cls, *tasks):
"""
Хотя бы одна из указанных задач выполнена и выполнена с ошибкой
"""
return cls(
lambda *args: any(x in cls._result(*args) and not cls._result(*args)[x] for x in tasks))
@classmethod
def has(cls, *tasks):
"""
Был запуск всех перечисленных задач
"""
return cls(lambda *args: all(x in cls._result(*args) for x in tasks))
@classmethod
def hasnot(cls, *tasks):
"""
Не было запуска ни одной из перечисленных задач
"""
return cls(lambda *args: all(x not in cls._result(*args) for x in tasks))
@classmethod
def result(cls, task, eq=None, ne=None):
if eq:
wrapper = lambda *args: task in cls._result(*args) and cls._result(*args)[task] == eq
elif ne:
wrapper = lambda *args: task not in cls._result(*args) or cls._result(*args)[task] != ne
else:
wrapper = lambda *args: task in cls._result(*args) and cls._result(*args)[task]
return cls(wrapper)
@classmethod
def has_any(cls, *tasks):
"""
Был запуск любой из задач
"""
return cls(lambda *args: any(x in cls._result(*args) for x in tasks))
class AllTasks(Tasks):
@classmethod
def _result(cls, result, all_result):
return all_result
class Action(MethodsInterface):
"""
Класс для реализации выполнения действия
# default = {'depend':Tasks.success(),
# # прятать вывод
# 'hideout':False,
# # задача важна, в случае False результат
# # не сохраняется в self.result
# 'essential':True}
"""
eachvar = None
# список выполняемых задач
tasks = []
# список исключений, которые выводятся в сокращенном формате
# (ожидаемые ошибки)
# остальные выводятся с именем модуля и номером строки
native_error = ()
# сообщение об удачном завершении действия
successMessage = None
# сообщение при ошибке
failedMessage = None
# сообщение о прерывании
interruptMessage = None
# добавить стандартные сообщения в конце
finishMessage = True
def __init__(self):
if self.finishMessage:
tasks = []
if self.failedMessage:
tasks.append(
# вывести сообщение в случае ошибки
{'name': 'failed',
'error': self.failedMessage,
'depend': (Tasks.failed() & Tasks.hasnot("interrupt"))})
if self.successMessage:
tasks.append(
# вывести сообщение в случае успеха
{'name': 'success',
'message': self.successMessage,
'depend': (Tasks.success() & Tasks.hasnot("failed"))})
if self.interruptMessage:
tasks.append(
# вывести сообщение о том, что действие прервано
{'name': 'intmessage',
'error': self.interruptMessage,
'depend': (Tasks.has("interrupt"))})
self.tasks = self.tasks + tasks
self.group_name = ""
self.clVars = None
@classmethod
def program(cls, progName):
"""
Проверить наличие программы
"""
return lambda dv: bool(getProgPath(progName))
@classmethod
def packageInstalled(cls, pkg):
"""
Проверить было ли обновление пакета
"""
return lambda dv: False
@classmethod
def variables(cls, *varnames):
"""
Передать переменные как аргументы, поддерживается True,False
"""
return lambda dv: [dv.Get(x) if x not in (True, False) else x
for x in varnames]
reMethod = re.compile("^([A-Za-z]+)\.([A-Za-z0-9_]+)\(([^)]*)\)$")
reMessageVars = re.compile("\{([^}]+)\}")
def parseMethod(self, objs, dv, s, task):
"""
Разобрать строку метода, на объект, метод, аргументы
"""
result = self.reMethod.search(s)
if not result:
raise ActionError(_("Wrong method for task %s") % task)
objname, methodname, args = result.groups()
if objname not in objs:
raise ActionError(_("Object %s not found") % objname)
obj = objs[objname]
if not hasattr(obj, methodname):
raise ActionError(_("Method {method} for {obj} not found").
format(method=methodname, obj=objname))
def _convertMethodArg(param):
"""
Конвертировать аргумент для метода, взять по словарю,
либо строка - имя переменной
"""
param = param.strip()
mapstd = {'True': True,
'False': False,
'None': None,
'""': "",
"''": ""}
if param in mapstd:
return mapstd[param]
if param.isdigit():
return int(param)
if param.startswith('"') and param.endswith('"'):
return param.strip('"')
if param == 'eachvar':
return self.eachvar
_type = dv.getInfo(param).type
if _type == "int":
return dv.GetInteger(param)
if _type in ("bool", "boolauto"):
return dv.GetBool(param)
return dv.Get(param)
if args:
args = [_convertMethodArg(x) for x in args.split(',')]
else:
args = ()
return getattr(obj, methodname), args
def formatMessage(self, dv, message):
"""
Вставить значения переменных в текст сообщения
"""
class TextTrasformer():
@staticmethod
def first_letter_upper(s):
return "%s%s" % (s[0].upper(), s[1:])
tt = TextTrasformer()
def replace_value(match):
var = match.group(1)
if ":" in var:
var, func = var.split(':')
else:
func = None
if var == "eachvar":
val = self.eachvar
else:
val = dv.Get(var)
if type(val) in (list, tuple):
val = ", ".join(val)
if func:
if hasattr(tt, func):
val = getattr(tt, func)(val)
else:
val = getattr(val, func)()
return "{0}".format(val)
return self.reMessageVars.sub(replace_value, str(message))
def runCondition(self, func_condition):
"""
Запустить метод проверки условия (если аргумент называется Get,
то передавать в него не объект DataVars а метод Get,
если у нет аргументов, то не передавать туда аргументы
"""
args = []
arg_count = func_condition.__code__.co_argcount
for param_name in func_condition.__code__.co_varnames[:arg_count]:
if param_name in ('Get', 'GetBool', 'Select', 'ZipVars'):
args.append(getattr(self.clVars, param_name))
elif param_name == 'eachvar':
args.append(self.eachvar)
else:
args.append(self.clVars)
return func_condition(*args)
def getFormatMessage(self, action, *fields):
"""
Получить сообщение для вывода среди нескольких с приоритетом и
метод вывода
"""
for field in (x for x in fields if x in action):
if "error" in field:
print_func = self.printERROR
elif "warning" in field:
print_func = self.printWARNING
else:
print_func = self.printSUCCESS
return print_func, self.formatMessage(self.clVars, action[field])
return None, None
def get_tasks(self, tasks, result, all_result):
"""
Герератор задач (поддержка линейной обработки задач в группах)
"""
for task in tasks:
if "group" in task or "tasks" in task:
if all(self.get_condition_context(task, result,
all_result).values()):
self.group_name = task.get("group", "")
if "while" in task:
depend = task.get("while", [])
depend = (depend
if type(depend) in (list, tuple) else [depend])
depend.append(~Tasks.has_any("interrupt"))
while all([x(result, all_result) for x in depend]):
for action in self.get_tasks(task["tasks"],
result, all_result):
yield action
else:
for action in self.get_tasks(task["tasks"], result,
all_result):
yield action
if not self.group_name:
self.endGroup()
else:
self.group_name = ""
else:
yield task
def get_condition_context(self, action, result, all_result):
"""
Получить результаты проверки по зависимосятм и условиям
"""
group, op, name = action.get("name",
"<unknown>").rpartition(':')
# проверить по результатам
# если указанно группа к имени с '!', то проверяется
# только условие принадлежности задачи к группе
if group and group.endswith('!'):
group = group.strip('!')
depend = [Tasks.success_all(group)]
else:
depend = action.get("depend", Tasks.success())
depend = (depend
if type(depend) in (list, tuple) else [depend])
if group:
depend.append(Tasks.success_all(group))
depend_result = all([x(result, all_result) for x in depend])
# проверить по условиям
if depend_result:
condition_funcs = action.get("condition", lambda dv: True)
condition_funcs = (condition_funcs
if type(condition_funcs) in (list, tuple)
else [condition_funcs])
condition_result = all(
[self.runCondition(x) for x in condition_funcs])
else:
condition_result = True
return {'condition': condition_result, 'depend': depend_result}
def run(self, objs, dv):
"""Запустить список действий"""
class StubLogger():
def info(self, s):
pass
result = {}
all_result = {}
self.group_name = ""
self.clVars = dv
if dv.Get('cl_env_debug_set') == 'off' or \
dv.Get('cl_root_readonly') == 'on' or \
dv.Get('cl_ebuild_phase') or os.getuid():
logger = StubLogger()
else:
logger = log("core-action.log",
filename="/var/log/calculate/core-action.log",
formatter="%(asctime)s - %(levelname)s - %(message)s")
for obj in objs.values():
obj.set_link(self)
obj.clVars = dv
if hasattr(obj, "init"):
obj.init()
try:
self.beginFrame()
logger.info("Start {methodname}".format(
methodname=self.method_name))
for action in self.get_tasks(self.tasks, result, all_result):
foreach = action.get("foreach", "")
if foreach:
foreach = self.clVars.Get(foreach)
else:
foreach = [""]
self.eachvar = ""
for eachvar in foreach:
self.eachvar = eachvar
group, op, name = action.get("name",
"<unknown>").rpartition(':')
res = True
task = False
self.clVars.Set('cl_task_name', name, force=True)
try:
run_context = self.get_condition_context(action, result,
all_result)
actinfo = "Run" if all(run_context.values()) else "Skip"
logger.info(
"{action} {name}: condition: {condition}, "
"depend: {depend}".format(
action=actinfo,
name=name,
condition=run_context['condition'],
depend=run_context['depend']))
elsePrint, elseMessage = (
self.getFormatMessage(action, "else_error",
"else_warning",
"else_message"))
if (run_context['depend'] and
not run_context['condition'] and elseMessage):
if "else_error" in action:
all_result[name] = False
if action.get("essential", True):
result[name] = False
elsePrint(elseMessage)
if all(run_context.values()):
self.writeFile()
if self.group_name:
self.startGroup(str(self.group_name))
self.group_name = None
printFunc, message = self.getFormatMessage(
action, "error", "warning", "message")
if "confirm" in action and message:
all_result[name] = \
self.askConfirm(str(message),
action["confirm"])
result[name] = all_result[name]
continue
elif message:
# если действие с командой
if ("error" not in action and
"method" in action or
"command" in action):
self.startTask(str(message))
task = True
# действие содержит только сообщение
else:
if "error" in action:
res = False
printFunc(message)
# запустить метод объекта
if "method" in action:
try:
method, args = self.parseMethod(
objs, dv, action["method"], name)
if "decoration" in action:
decfunc, decargs = self.parseMethod(
objs, dv, action["decoration"],
name)
method = decfunc(*decargs)(method)
res = method(*args)
if res is None:
res = False
except CriticalError as e:
self.printERROR(str(e))
self.endFrame()
return False
except self.native_error as e:
if action.get('essential', True):
printerror = self.printERROR
else:
printerror = self.printWARNING
if hasattr(e, "addon") and e.addon:
printerror(str(e.addon))
printerror(str(e))
res = False
except Exception:
error = shortTraceback(*sys.exc_info())
self.printERROR(error)
res = False
# запустить системную команду
if "command" in action:
hideout = action.get("hideout", False)
cmdParam = [x.strip('"\'') for x
in re.findall('["\'][^"\']+["\']|\S+', action["command"])]
cmd = processProgress(*cmdParam)
for line in cmd.progress():
if not hideout:
self.printSUCCESS(line)
if cmd.failed():
lineCmd = cmd.pipe.stderr.read().split('\n')
for line in (x for x in lineCmd if x):
self.printERROR(line)
res = cmd.success()
all_result[name] = res
if action.get("essential", True):
result[name] = res
failedPrint, failedMessage = (
self.getFormatMessage(action, "failed_error",
"failed_warning",
"failed_message"))
if not res and failedPrint:
failedPrint(failedMessage)
if task and res in (True, False, "skip"):
self.endTask(res)
logger.info("{name}: Result is {result}".format(
name=name, result=res))
if res is True:
on_success = action.get('on_success', None)
if on_success:
on_success()
# else:
# print "[-] Skip ",name
except KeyboardInterrupt:
all_result[name] = False
if action.get("essential", True):
result[name] = False
self.endTask(False)
self.printWARNING(_("Task interrupted"))
all_result["interrupt"] = False
result["interrupt"] = False
logger.info("{name}: Interrupeted".format(name=name))
except self.native_error as e:
if action.get('essential', True):
printerror = self.printERROR
else:
printerror = self.printWARNING
if hasattr(e, "addon") and e.addon:
printerror(str(e.addon))
printerror(str(e))
result[name] = False
all_result[name] = False
logger.info("{name}: Native error".format(name=name))
except CriticalError as e:
self.printERROR(str(e))
self.endFrame()
return False
except BaseException as e:
result[name] = False
all_result[name] = False
error = shortTraceback(*sys.exc_info())
self.printERROR("%s:%s" % (name, error))
logger.info("{name}: Unknown exception {exp}".format(
name=name, exp=e.__class__.__name__))
finally:
dv.close()
self.endFrame()
if any(x in ("failed", "interrupt") for x in result):
return False
return True
# Never used. Why do we need it?
def commonView(self, sid, params, arg):
dv = self.get_cache(sid, arg, "vars")
if not dv:
dv = getattr(self, "%s_vars" % arg)()
else:
dv.processRefresh()
view = ViewInfo(dv, viewparams=params)
self.set_cache(sid, arg, "vars", dv, smart=False)
return view
def catchExcept(*skipException):
class wrapper:
def __init__(self, f_static):
f = f_static.__func__
self.f = f
self.__name__ = f.__name__
self.__code__ = f.__code__
self.__doc__ = f.__doc__
self.__name__ = f.__name__
def __call__(self, *args, **kwargs):
try:
return self.f(*args, **kwargs)
except BaseException as e:
from .api_types import ViewInfo, \
GroupField, Field
if isinstance(e, KeyboardInterrupt):
error = _("Task interrupted")
else:
error = str(e)
view = ViewInfo(groups=[])
group = GroupField(name=_("Error"), last=True)
group.fields = []
group.fields.append(Field(
name="error",
label=error,
default='color:red;',
element="error"))
view.groups.append(group)
if not any(isinstance(e, x)
for x in chain(skipException, (KeyboardInterrupt,))):
print(shortTraceback(*sys.exc_info()))
return view
return wrapper
def shortTraceback(e1, e2, e3):
"""
Return short traceback
"""
frame = e3
for i in traceback.format_exception(*(e1, e2, e3)):
print(i, end=' ')
while frame.tb_next:
frame = frame.tb_next
module, part = os.path.split(frame.tb_frame.f_code.co_filename)
if part.endswith('.py'):
part = part[:-3]
fallbackmod = part
modname = [part]
while module != '/' and not module.endswith('site-packages'):
module, part = os.path.split(module)
modname.insert(0, part)
if module.endswith('site-packages'):
modname = ".".join(modname)
else:
modname = fallbackmod
return "%s:%s(%s:%s)" % (e1.__name__, str(e2), modname, frame.tb_lineno)
class ActiveClientStatus():
Success = 0
Failed = 1
WrongSID = 2
class CoreWsdl(CoreServiceInterface):
# client signals about presence
@staticmethod
def active_clients(cls, sid):
# curThread = threading.currentThread()
# REMOTE_ADDR = curThread.REMOTE_ADDR
#why is this here?
# cls.get_lang(cls, sid, "from active clients")
if 0 < sid < cls.max_sid:
try:
# open file its session
sid_file = cls.sids + "/%d.sid" % sid
if not os.path.isfile(sid_file):
return ActiveClientStatus.Failed
# check sid in sid.db
if not (os.path.isfile(cls.sids_file) and
cls.find_sid_in_file(cls, sid)):
try:
os.unlink(sid_file)
except (OSError, IOError):
pass
return ActiveClientStatus.Failed
with cls.sid_locker:
with open(sid_file, "rb") as fd:
# read information about session
sid_inf = pickle.load(fd)
# reset counters
sid_inf[1] = 0
sid_inf[2] = 0
fd.close()
if not os.path.isfile(sid_file):
return ActiveClientStatus.Failed
fd = open(sid_file, "wb")
pickle.dump(sid_inf, fd)
fd.close()
return ActiveClientStatus.Success
except Exception:
return ActiveClientStatus.Failed
else:
return ActiveClientStatus.WrongSID
@staticmethod
def serv_get_methods(cls, client_type):
curThread = threading.currentThread()
certificate = curThread.client_cert
from .cert_cmd import find_cert_id
cert_id = find_cert_id(certificate, cls.data_path, cls.certbase)
rights = cls.serv_view_cert_right(cls, cert_id, cls.data_path, client_type)
return_list = []
if client_type == "console":
for meth in cls.return_conMethod():
right_flag = True
for right in LoadedMethods.rightsMethods[meth[1]]:
if right not in rights:
right_flag = False
if right_flag:
return_list.append(meth)
if not len(return_list):
return [['0', '0']]
return return_list
else:
for meth in cls.return_guiMethod():
right_flag = True
for right in LoadedMethods.rightsMethods[meth[1]]:
if right not in rights:
right_flag = False
if right_flag:
return_list.append(meth)
if not len(return_list):
return [['0', '0']]
return return_list
# return a list of methods for the console as list
@staticmethod
def return_conMethod():
from .loaded_methods import LoadedMethods
results = []
for item in LoadedMethods.conMethods:
temp = [item]
for i in LoadedMethods.conMethods[item]:
temp.append(i)
results.append(temp)
return results
# return a list of methods for the GUI as list
@staticmethod
def return_guiMethod():
from .loaded_methods import LoadedMethods
results = []
dv = DataVars()
dv.importVariables()
for item in LoadedMethods.guiMethods:
for i in range(0, len(LoadedMethods.guiMethods[item]), 4):
if LoadedMethods.guiMethods[item][i + 3]:
method_on = LoadedMethods.guiMethods[item][i + 3](dv.Get)
else:
method_on = True
if method_on:
temp = [item]
for j in range(3):
temp.append(LoadedMethods.guiMethods[item][i + j])
results.append(temp)
dv.close()
return results
# get available sessions
@staticmethod
def serv_get_sessions(cls):
result = []
fd = open(cls.sids_file, 'rb')
while 1:
try:
# read all on one record
list_sid = pickle.load(fd)
except (KeyError, IOError, EOFError):
break
# if session id found
result.append(str(list_sid[0]))
fd.close()
return result
# check client alive
@staticmethod
def client_alive(cls, sid, SIDS_DIR):
sid_path = SIDS_DIR + "/%d.sid" % sid
if not os.path.isfile(sid_path):
return 1
with cls.sid_locker:
with open(sid_path, "rb") as fd:
# read information about session
sid_inf = pickle.load(fd)
# flag absence client
fd.close()
if sid_inf[2] == 1:
return 0
else:
return 1
class Common(CommonMethods, MethodsInterface):
""" class to interact with the processes """
def __init__(self, process_dict, progress_dict, table_dict,
frame_list, pid):
self.process_dict = process_dict
self.progress_dict = progress_dict
self.progress_dict['id'] = 0
self.table_dict = table_dict
self.frame_list = frame_list
self.pid = pid
self.Num = 100000
def pauseProcess(self):
from .gen_pid import ProcessStatus
self.method_status = ProcessStatus.Paused
self.writeFile()
def resumeProcess(self):
from .gen_pid import ProcessStatus
self.method_status = ProcessStatus.Worked
self.writeFile()
def writeFile(self):
""" write data in file """
from .baseClass import Basic
from .gen_pid import ProcessMode
if not os.path.exists(Basic.pids):
makeDirectory(Basic.pids)
build_id = ""
try:
from calculate.builder.variables.action import Actions
if self.clVars.Get('cl_action') in Actions.All:
build_id = self.clVars.Get('builder.cl_builder_id')
except Exception as e:
if isinstance(e, KeyboardInterrupt):
raise
pid_file = path.join(Basic.pids, '%d.pid' % self.pid)
try:
with open(pid_file, 'wb') as f:
d = {'name': self.process_dict['method_name'],
'mode': ProcessMode.CoreDaemon,
'os_pid': os.getpid(),
'status': self.process_dict['status'],
'id': build_id
}
pickle.dump(d, f)
except (IOError, OSError) as e:
print(str(e))
print(_("Failed to write the PID file %s!") % pid_file)
def setProgress(self, perc, short_message=None, long_message=None):
try:
id = self.progress_dict['id']
self.progress_dict[id] = ReturnProgress(perc, short_message,
long_message)
except IOError:
pass
def setStatus(self, stat):
self.process_dict['status'] = stat
def setData(self, dat):
self.data_list = dat
def getStatus(self):
try:
return self.process_dict['status']
except IOError:
return -1
def getProgress(self):
try:
id = self.progress_dict['id']
if id in self.progress_dict:
return self.progress_dict[id].percent
except IOError:
pass
return 0
def getAnswer(self):
import time
while self.process_dict['answer'] is None:
time.sleep(0.5)
res = self.process_dict['answer']
self.process_dict['answer'] = None
self.frame_list.pop(len(self.frame_list) - 1)
self.process_dict['counter'] -= 1
return res
def addProgress(self, message=""):
id = random.randint(1, self.Num)
while id in self.progress_dict:
id = random.randint(1, self.Num)
self.progress_dict['id'] = id
self.progress_dict[id] = ReturnProgress(0, '', '')
self.addMessage(message_type='progress', id=id)
def printTable(self, table_name, head, body, fields=None,
onClick=None, addAction=None, step=None,
records=None):
id = random.randint(1, self.Num)
while id in self.table_dict:
id = random.randint(1, self.Num)
from .api_types import Table
table = Table(head=head, body=[[str(y) for y in x] for x in body],
fields=fields,
onClick=onClick, addAction=addAction, step=step,
values=None, records=records)
self.table_dict[id] = table
self.addMessage(message_type='table', message=table_name, id=id)
def addMessage(self, message_type='normal', message=None, id=None,
onlyShow='', default=None):
from .api_types import Message
if isinstance(message, bytes):
message = message.decode("UTF-8")
re_clean = re.compile('\[(?:\d+;)?\d+m')
messageObj = Message(
message_type=message_type,
message=(
None if message in (None, True, False)
else re_clean.sub('', message)),
result=message if message in (True, False) else None,
id=id, onlyShow=onlyShow, default=default)
try:
self.frame_list.append(messageObj)
except BaseException as e:
if isinstance(e, KeyboardInterrupt):
raise
print(_(("%s:" % message_type) + str(message)))
def dropProgress(self):
perc = self.getProgress()
if perc == 0:
self.setProgress(100)
elif self.getProgress() > 0:
self.setProgress(0 - self.getProgress())
else:
# self.setProgress(-100)
self.setProgress(perc)
def printSUCCESS(self, message='', onlyShow=None):
self.dropProgress()
self.addMessage(message_type='normal', message=message,
onlyShow=onlyShow)
def printPre(self, message='', onlyShow=None):
self.dropProgress()
self.addMessage(message_type='pre', message=message,
onlyShow=onlyShow)
def printDefault(self, message='', onlyShow=None):
self.dropProgress()
self.addMessage(message_type='plain', message=message,
onlyShow=onlyShow)
def printWARNING(self, message, onlyShow=None):
self.dropProgress()
self.addMessage(message_type='warning', message=message,
onlyShow=onlyShow)
def printERROR(self, message='', onlyShow=None):
self.dropProgress()
self.addMessage(message_type='error', message=message,
onlyShow=onlyShow)
def startTask(self, message, progress=False, num=1):
if progress:
self.addMessage(message_type='startTask', message=message, id=num)
self.addProgress()
else:
self.addMessage(message_type='startTask', message=message, id=num)
def setTaskNumber(self, number=None):
self.addMessage(message_type='taskNumber', message=str(number))
def endTask(self, result=None, progress_message=None):
self.addMessage(message_type='endTask', message=result)
self.setProgress(100, progress_message)
def askConfirm(self, message, default="yes"):
self.addMessage(message_type='confirm', message=message, default=default)
ret = self.getAnswer()
if ret == "":
return default
return ret
def isInteractive(self):
return True
def askChoice(self, message, answers=(("yes", "Yes"), ("no", "No"))):
self.addMessage(message_type='choice', message="%s|%s" % (
message,
",".join(("%s(%s)" % (x[0], x[1]) for x in answers))))
return self.getAnswer()
def askQuestion(self, message):
self.addMessage(message_type='question', message=message)
return self.getAnswer()
def askPassword(self, message, twice=False):
pas_repeat = 2 if twice else 1
self.addMessage(message_type='password', message=message,
id=pas_repeat)
return self.getAnswer()
def beginFrame(self, message=None):
self.addMessage(message_type='beginFrame', message=message)
def endFrame(self):
self.addMessage(message_type='endFrame')
def startGroup(self, message):
self.addMessage(message_type='startGroup', message=message)
def endGroup(self):
self.addMessage(message_type='endGroup')
# def cache(self, param):
# sid = self.process_dict['sid']
# self.args[sid] = collections.OrderedDict()
@staticmethod
def startprocess(cls, sid, target=None, method=None, method_name=None,
auto_delete=False, args_proc=()):
""" start process """
pid = cls.gen_pid(cls)
cls.add_sid_pid(cls, sid, pid)
import multiprocessing
if cls.manager is None:
cls.manager = multiprocessing.Manager()
# Manager for sending glob_process_dict between watcher and process
# manager = multiprocessing.Manager()
cls.glob_process_dict[pid] = cls.manager.dict()
cls.glob_process_dict[pid]['sid'] = sid
cls.glob_process_dict[pid]['status'] = 0
cls.glob_process_dict[pid]['time'] = ""
cls.glob_process_dict[pid]['answer'] = None
cls.glob_process_dict[pid]['name'] = ""
cls.glob_process_dict[pid]['flag'] = 0
cls.glob_process_dict[pid]['counter'] = 0
cls.glob_frame_list[pid] = cls.manager.list()
cls.glob_progress_dict[pid] = cls.manager.dict()
cls.glob_table_dict[pid] = cls.manager.dict()
# create object Common and send parameters
com = target(cls.glob_process_dict[pid],
cls.glob_progress_dict[pid],
cls.glob_table_dict[pid],
cls.glob_frame_list[pid], pid)
if len(com.__class__.__bases__) > 1 and \
hasattr(com.__class__.__bases__[1], '__init__'):
com.__class__.__bases__[1].__init__(com)
# start helper
com.method_name = method_name
p = multiprocessing.Process(target=cls.target_helper,
args=(cls, com, getattr(com, method)) +
(method_name,) + args_proc)
cls.process_pid[pid] = p
p.start()
if auto_delete:
# start watcher (for kill process on signal)
watcher = threading.Thread(target=cls.watcher_pid_proc,
args=(cls, sid, pid))
watcher.start()
return str(pid)
# wrap all method
@staticmethod
def target_helper(cls, com, target_proc, method_name, *args_proc):
if not os.path.exists(cls.pids):
os.system('mkdir %s' % cls.pids)
# PID_FILE = cls.pids + '/%d.pid'%com.pid
import datetime
dat = datetime.datetime.now()
com.process_dict['status'] = 1
com.process_dict['time'] = dat
# if method_name:
com.process_dict['method_name'] = method_name
com.process_dict['name'] = target_proc.__func__.__name__
try:
result = target_proc(*args_proc)
except Exception:
result = False
print_exc()
fd = open(cls.log_filename, 'a')
print_exc(file=fd)
fd.close()
try:
if result is True:
com.setStatus(0)
com.writeFile()
elif result is False:
if com.getStatus() == 1:
com.setStatus(2)
com.writeFile()
else:
if com.getStatus() == 1:
com.setStatus(2)
else:
com.setStatus(0)
com.writeFile()
try:
if 0 < com.getProgress() < 100:
com.setProgress(0 - com.getProgress())
if len(com.frame_list):
last_message = com.frame_list[len(com.frame_list) - 1]
if last_message.type != 'endFrame':
com.endFrame()
else:
com.endFrame()
except IOError:
pass
except Exception:
print_exc()
fd = open(cls.log_filename, 'a')
print_exc(file=fd)
fd.close()
com.endFrame()
@staticmethod
def serv_view_cert_right(cls, cert_id, data_path, client_type=None):
""" rights for the selected certificate """
try:
cert_id = int(cert_id)
except ValueError:
return ["-2"]
cert_file = data_path + '/client_certs/%s.crt' % str(cert_id)
if not os.path.exists(cert_file):
return ["-1"]
cert = readFile(cert_file)
# try:
import OpenSSL
certobj = OpenSSL.crypto.load_certificate(
OpenSSL.SSL.FILETYPE_PEM, cert)
com = certobj.get_extension(
certobj.get_extension_count() - 1).get_data()
groups = com.split(b':')[1].decode("UTF-8")
groups_list = groups.split(',')
# except:
# return ['-1']
results = []
find_flag = False
# if group = all and not redefined group all
if 'all' in groups_list:
fd = open(cls.group_rights, 'r')
t = fd.read()
# find all in group_rights file
for line in t.splitlines():
if not line:
continue
if line.split()[0] == 'all':
find_flag = True
break
if not find_flag:
result = []
if client_type == 'console':
for meth_list in cls.return_conMethod():
for right in LoadedMethods.rightsMethods[meth_list[1]]:
result.append(right)
else:
for meth_list in cls.return_guiMethod():
for right in LoadedMethods.rightsMethods[meth_list[1]]:
result.append(right)
result = uniq(result)
results = result
if 'all' not in groups_list or find_flag:
if not os.path.exists(cls.group_rights):
open(cls.group_rights, 'w').close()
with open(cls.group_rights) as fd:
t = fd.read()
for line in t.splitlines():
if not line:
continue
try:
words = line.split(' ', 1)
if len(words) < 2:
continue
# first word in line equal name input method
if words[0] in groups_list:
methods = words[1].split(',')
for i in methods:
results.append(i.strip())
except IndexError:
print('except IndexError in serv_view_cert_right')
continue
results = uniq(results)
add_list_rights = []
del_list_rights = []
with open(cls.rights) as fr:
t = fr.read()
for line in t.splitlines():
words = line.split()
meth = words[0]
for word in words:
try:
word = int(word)
except ValueError:
continue
# compare with certificat number
if cert_id == word:
# if has right
add_list_rights.append(meth)
if cert_id == -word:
del_list_rights.append(meth)
results += add_list_rights
results = uniq(results)
for method in results:
if method in del_list_rights:
results.remove(method)
if not results:
results.append("No Methods")
return results
@staticmethod
def get_lang(cls, sid, method_name=""):
""" get clients lang """
lang = None
SIDS_DIR = cls.sids
with cls.sid_locker:
sid_file = SIDS_DIR + "/%d.sid" % int(sid)
if os.path.exists(sid_file):
# fd = open(sid_file, 'r')
with open(sid_file, 'rb') as fd:
try:
list_sid = pickle.load(fd)
list_sid_sid = int(list_sid[0])
if sid == list_sid_sid:
# print("SID FOUND")
lang = list_sid[3]
except IOError:
print("some io error")
pass
except KeyError:
print("Key error")
pass
except EOFError:
print("EOF error")
pass
try:
# print(lang)
if lang.lower() not in ('uk', 'fr', 'ru', 'en'):
lang = "en"
except AttributeError:
# print("Attr error")
lang = "en"
import locale
try:
lang = locale.locale_alias[lang.lower()]
# print("lang got from locale: %s" % lang)
except (TypeError, AttributeError, IndexError, KeyError):
lang = locale.locale_alias['en']
# print("Setting lang: %s " % lang)
return lang
def create_symlink(data_path, old_data_path):
meths = LoadedMethods.conMethods
path_to_link = '/usr/bin'
core_wrapper = "/usr/libexec/calculate/cl-core-wrapper"
#path_to_user_link = '/usr/bin'
old_symlinks_file = os.path.join(old_data_path, 'conf/symlinks')
symlinks_file = os.path.join(data_path, 'conf/symlinks')
if not os.path.exists(os.path.join(data_path, 'conf')):
try:
os.makedirs(os.path.join(data_path, 'conf'))
except OSError:
print (_("cannot create directory %s")
% (os.path.join(data_path, 'conf')))
if os.path.exists(old_symlinks_file) and not os.path.exists(symlinks_file):
with open(symlinks_file, 'w') as fd:
fd.write(readFile(old_symlinks_file))
os.unlink(old_symlinks_file)
with open(symlinks_file, 'a') as fd:
for link in meths:
link_path = os.path.join(path_to_link, link)
if os.path.islink(link_path):
continue
if os.path.isfile(link_path):
red = '\033 * \033'
print(red + link_path + _(' is a file, not a link!'))
continue
try:
if (os.path.islink(link_path) and
os.readlink(link_path) != core_wrapper):
os.unlink(link_path)
os.symlink(core_wrapper, link_path)
fd.write(link_path + '\n')
except OSError as e:
print(e)
print(_('Symlink %s created') % link_path)
temp_text_file = ''
for line in readLinesFile(symlinks_file):
cmdname = os.path.basename(line)
if cmdname not in meths.keys() or not line.startswith(path_to_link):
if os.path.islink(line):
os.unlink(line)
print(_('Symlink %s deleted') % line)
else:
temp_text_file += line + '\n'
fd = open(symlinks_file, 'w')
fd.write(temp_text_file)
fd.close()
def initialization(cl_wsdl):
""" find modules for further added in server class """
cl_apis = []
for pack in cl_wsdl:
if pack:
module_name = '%s.wsdl_%s' % (pack.replace("-", "."),
pack.rpartition("-")[2])
import importlib
cl_wsdl_core = importlib.import_module(module_name)
try:
cl_apis.append(cl_wsdl_core.Wsdl)
except ImportError:
sys.stderr.write(_("Unable to import %s") % module_name)
return cl_apis
# Creation of secret key of the client
def new_key_req(key, cert_path, serv_host_name, port):
from .create_cert import (generateRSAKey, makePKey, makeRequest,
passphrase_callback)
rsa = generateRSAKey()
rsa.save_key(key + '_pub', cipher=None, callback=passphrase_callback)
pkey = makePKey(rsa)
pkey.save_key(key, cipher=None, callback=passphrase_callback)
req = makeRequest(rsa, pkey, serv_host_name, port)
if not req:
sys.exit()
crtreq = req.as_pem()
crtfile = open(cert_path + '/server.csr', 'wb')
crtfile.write(crtreq)
crtfile.close()
# delete dublicate from list
def uniq(seq):
seen = set()
seen_add = seen.add
return [x for x in seq if x not in seen and not seen_add(x)]
class WsdlMeta(type):
"""
Метакласс для создания методов по атрибуту methdos
"""
datavars = {}
def __new__(mcs, name, bases, attrs):
if "methods" in attrs:
for method in attrs["methods"]:
attrs[method['method_name']] = mcs.caller_constructor(**method)
attrs["%s_vars" % method[
'method_name']] = mcs.datavars_constructor(**method)
attrs["%s_view"
% method['method_name']] = mcs.view_constructor(**method)
return type.__new__(mcs, name, bases, attrs)
@classmethod
def close_datavars(mcs):
for dv in WsdlMeta.datavars.values():
dv.close()
@classmethod
def create_info_obj(mcs, **kwargs):
"""
Создание передаваемой структуры данных для WSDL
"""
def type_convert(s):
if "bool3" in s:
return String
if "bool" in s:
return Boolean
elif "table" in s:
return Array(Array(String))
elif "list" in s:
return Array(String)
else:
return String
d = {}
d["cl_console_args"] = Array(String)
if kwargs['datavars'] in WsdlMeta.datavars:
dv = WsdlMeta.datavars[kwargs['datavars']]
else:
dv = DataVars()
dv.importVariables()
dv.importVariables('calculate.%s.variables' % kwargs['datavars'])
dv.defaultModule = kwargs['datavars']
WsdlMeta.datavars[kwargs['datavars']] = dv
def group(*args, **kwargs):
for v in chain(kwargs.get('normal', ()), kwargs.get('expert', ())):
varname = v.rpartition(".")[2]
d[varname] = type_convert(dv.getInfo(v).type)
for gr in kwargs['groups']:
gr(group)
# if "brief" in kwargs:
#if "cl_page_count" not in d:
if True:
d["CheckOnly"] = Boolean
return d
@classmethod
def caller_constructor(mcs, **kwargs):
"""
Конструктор для создания метода-вызова для действия
"""
# @staticmethod
def wrapper(cls, sid, info):
# костыль для локализации install
callback_refresh = (
cls.fixInstallLocalization
if kwargs['method_name'] == 'install' else lambda cls, dv, sid: True)
return cls.callAction(cls, sid, info, logicClass=kwargs['logic'],
actionClass=kwargs['action'],
method_name=kwargs['method_name'],
callbackRefresh=callback_refresh,
invalidators=kwargs.get('invalidators', None)
)
wrapper.__name__ = kwargs['method_name']
wrapper = staticmethod(wrapper)
func = LoadedMethods.core_method(category=kwargs.get('category', None),
title=kwargs['title'],
image=kwargs.get('image', None),
gui=kwargs['gui'],
user=kwargs.get('user', False),
command=kwargs.get('command', None),
rights=kwargs['rights'],
depends=kwargs.get('depends', ()),
static_method=True)(
wrapper)
if "--start" in sys.argv:
info_obj = mcs.create_info_obj(**kwargs)
info_class = type("%sInfo" % kwargs["method_name"], (CommonInfo,),
info_obj)
#total hack: carry over info_class for later use
func.__func__.info_class = info_class
return func
@classmethod
def modify_datavars(mcs, dv, data):
"""
Поменять значения в datavars согласно data
"""
# установить заданные значения (!) принудительная установка
for k, v in data.items():
# если значение функция
if callable(v):
v = v(dv)
else:
if isinstance(v, (str)):
v = Variable._value_formatter.format(v, dv.Get)
dv.Set(k.strip('!'), v, force=k.endswith('!'))
@classmethod
def view_constructor(mcs, **kwargs):
"""
Конструктор для создания метода-представления
"""
# @staticmethod
def wrapper(cls, sid, params):
dv = cls.get_cache(sid, kwargs["method_name"], "vars")
lang_changed = False
if kwargs["groups"]:
def group(*args, **kwargs):
if isinstance(kwargs.get('normal', ()), (str)):
raise DataVarsError(_("Wrong normal varaiables list"))
if isinstance(kwargs.get('expert', ()), (str)):
raise DataVarsError(_("Wrong expert varaiables list"))
for gr in kwargs['groups']:
gr(group)
if not dv:
dv = getattr(cls, "%s_vars" % kwargs["method_name"])(cls,
params=params)
if hasattr(params, "clienttype"):
if params.clienttype == 'gui' and "guivars" in kwargs:
mcs.modify_datavars(dv, kwargs['guivars'])
if params.clienttype != 'gui' and "consolevars" in kwargs:
mcs.modify_datavars(dv, kwargs['consolevars'])
dv.Set('main.cl_client_type', params.clienttype, force=True)
else:
# костыль для метода install, который меняет локализацию
# интрефейса в зависимости от выбранного параметра lang
if kwargs["method_name"] == 'install':
lang_changed = cls.fixInstallLocalization(cls, sid, dv)
lang = dv.Get('install.os_install_locale_lang')
cls.set_cache(sid, "install", "lang", lang, smart=False)
dv.processRefresh()
cls.set_cache(sid, kwargs["method_name"], "vars", dv, smart=False)
if "brief" in kwargs and "name" in kwargs['brief']:
brief_label = str(kwargs['brief']['name'])
else:
brief_label = None
if kwargs["groups"]:
view = ViewInfo(dv, viewparams=params,
has_brief="brief" in kwargs,
allsteps=lang_changed,
brief_label=brief_label)
else:
view = ViewInfo()
return view
wrapper.__name__ = "%s_view" % kwargs['method_name']
wrapper = staticmethod(wrapper)
return catchExcept(kwargs.get("native_error", ()))(wrapper)
@classmethod
def datavars_constructor(mcs, **kwargs):
"""
Конструктор для создания метода описания параметров
"""
@staticmethod
def wrapper(cls, dv=None, params=None):
if not dv:
_dv = DataVars()
_dv.importVariables()
_dv.importVariables(
'calculate.%s.variables' % kwargs['datavars'])
_dv.defaultModule = kwargs['datavars']
_dv.flIniFile()
if params and params.help_set:
_dv.Set('cl_help_set', "on", force=True)
if params and params.dispatch_usenew:
_dv.Set('cl_dispatch_conf', "usenew", force=True)
if params:
if params.conargs:
conargs = list(params.conargs)
else:
conargs = []
if params.dispatch_usenew:
conargs.append("--force")
_dv.Set('cl_console_args', conargs, force=True)
else:
_dv = dv
# созданием группы переменных из datavars согласно параметрам groups
for groupfunc in kwargs['groups']:
groupfunc(_dv.addGroup)
if not dv:
mcs.modify_datavars(_dv, kwargs['setvars'])
# указание brief если нужно
if "brief" in kwargs:
_dv.addBrief(
next_label=str(kwargs['brief'].get('next', _('Next'))),
image=kwargs['brief'].get('image', None))
return _dv
return wrapper
class WsdlBase(metaclass=WsdlMeta):
"""
Базовый класс для автосоздания методов по описанию methods
"""
# __metaclass__ = WsdlMeta
def clearDataVars(func):
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
finally:
WsdlMeta.close_datavars()
return wrapper
class CustomButton():
@classmethod
def sort_argv(cls, args):
behavior = []
condition = None
for arg in args:
if callable(arg):
condition = arg
else:
behavior.append(arg)
return (behavior or None), condition
@classmethod
def run_method(cls, method_name, id, label, *args):
behavior, condition = cls.sort_argv(args)
return id, label, method_name, "button", behavior, condition
@classmethod
def open_method(cls, method_name, id, label, *args):
behavior, condition = cls.sort_argv(args)
return id, label, method_name, "button_view", behavior, condition
@classmethod
def next_button(cls, id=None, label=None):
return id, label, None, "button_next"
class Behavior():
@classmethod
def link(cls, source=None, target=None):
return "%s=%s" % (target, source)
@classmethod
def linkerror(cls, source=None, target=None):
return "%s->%s" % (source, target)
@classmethod
def setvalue(cls, variable=None, value=None):
return "%s!=%s" % (variable, value)