You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
calculate-utils-3-core/pym/core/server/func.py

1905 lines
74 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# -*- 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 calculate.core.server.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 .api_types import ReturnProgress
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 calculate.core.server.api_types import ReturnedMessage, CommonInfo
from calculate.core.server.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 = "zap new" #was 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 = "zap new" #was 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 calculate.core.server.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(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 calculate.core.server.gen_pid import ProcessStatus
self.method_status = ProcessStatus.Paused
self.writeFile()
def resumeProcess(self):
from calculate.core.server.gen_pid import ProcessStatus
self.method_status = ProcessStatus.Worked
self.writeFile()
def writeFile(self):
""" write data in file """
from .baseClass import Basic
from calculate.core.server.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
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('', [x for x in message if x >= ' '])),
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()
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[31m * \033[0m'
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', 'w')
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
# else:
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)
# print("got dv from cls: %s" % dv)
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
# print("dv groups: %s" % bool(dv.getGroups()))
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)
# print("dv before refresh groups: %s" % bool(dv.getGroups()))
dv.processRefresh()
# print("dv after refresh groups: %s" % bool(dv.getGroups()))
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"]:
# print("group view info creation")
# print(params)
# print(dv)
# print(brief_label)
# print(dv.getGroups())
# print("dv groups: %s" % bool(dv.getGroups()))
view = ViewInfo(dv, viewparams=params,
has_brief="brief" in kwargs,
allsteps=lang_changed,
brief_label=brief_label)
else:
# print("creating empty viewInfo")
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)