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/methods_func.py

785 lines
30 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 sys
import os
import argparse
import re
from calculate.lib.utils.common import getpass
from calculate.lib.cl_print import color_print
from calculate.lib.cl_lang import setLocalTranslate
from calculate.core.server.api_types import TableAdapter
from functools import reduce
_ = lambda x: x
setLocalTranslate('cl_core3', sys.modules[__name__])
from itertools import *
from .api_types import ViewInfoAdapter, ArrayReturnedMessage, FieldAdapter
from calculate.lib.utils.colortext import get_terminal_print, TextState
colorPrint = color_print()
class GotErrorField(Exception):
"""
Исключение о получение поля error среди
элементов view
"""
pass
class BoolAction(argparse.Action):
reTrue = re.compile("^(?:on|yes)$", re.I)
reFalse = re.compile("^(?:off|no)$", re.I)
available_values = ("on", "off","yes", "no")
def __init__(self, option_strings, dest, nargs="?",
const=None, default=None, type=None, choices=None,
required=False, help=None, metavar=None):
super().__init__(
option_strings=option_strings, dest=dest,
nargs=nargs, const=const, default=default,
type=type, choices=choices, required=required,
help=help, metavar=metavar)
def get_values(self, value):
value = value.lower()
for v in self.available_values:
if value == v:
return v
else:
return ""
def __call__(self, parser, ns, values, option_string=None):
if values is None:
values = "on"
else:
if self.reTrue.match(values):
values = "on"
if self.reFalse.match(values):
values = "off"
values = self.get_values(values)
if not values:
msg = _('the value may be {0}').format(
formatListOr(self.available_values))
parser.error(msg)
setattr(ns, self.dest, values)
class BoolAutoAction(BoolAction):
available_values = ("on", "off", "yes", "no", "auto")
def _print(*args):
print(" ".join((_u8(x) for x in args)))
def get_password(text1=None, text2=None, getfromstdin=False,
needrepeat=True):
if getfromstdin:
try:
passwd = ''
while not passwd:
passwd = sys.stdin.readline()
if not passwd:
return None
passwd = passwd.rstrip('\n')
return passwd
except BaseException:
return None
if not text1:
text1 = _('Password: ')
if not text2:
text2 = _('Repeat: ')
try:
pass1 = 'password'
pass2 = 'repeat'
while pass1 != pass2:
pass1 = getpass.getpass(text1)
if not needrepeat:
return pass1
pass2 = getpass.getpass(text2)
if pass1 != pass2:
print(_('Passwords do not match'))
except KeyboardInterrupt:
return None
passwd = pass1 if (pass1 and pass1 == pass2) else ''
return passwd
def listToArray(client, _list, _type='string'):
if not client:
return _list
array = client.factory.create('%sArray' % _type)
for i in _list:
array['%s' % _type].append(i)
return array
def listToArrayArray(client, _list, _type='string'):
if not client:
return _list
array_array = client.factory.create('%sArrayArray' % _type)
for i in _list:
array = client.factory.create('%sArray' % _type)
for j in i:
array[_type].append(j)
array_array['%sArray' % _type].append(array)
return array_array
def _getattr(obj, attr):
return getattr(obj, attr) if hasattr(obj, attr) else None
import argparse
import textwrap as _textwrap
from calculate.lib.utils.text import get_term_size, _u, _u8, _uu8, formatListOr
class RawAndDefaultsHelpFormatter(argparse.HelpFormatter):
def __init__(self, prog, max_help_position=24, **kwargs):
# Use the whole terminal width
height, width = get_term_size()
argparse.HelpFormatter.__init__(self, prog, width=width,
max_help_position=max_help_position,
**kwargs)
def _split_lines(self, text, width):
text = self._whitespace_matcher.sub(' ', _u(text)).strip()
return _uu8(*_textwrap.wrap(text, width))
def get_method_argparser(view, args, cl_core=False):
"""
Get argparser by ViewInfo get from WSDL server (or stub)
cl_core - argparser for cl_core (local call)
"""
error_flag = False
method = args.method
if cl_core:
progr = os.path.basename(sys.argv[0])
else:
progr = 'cl-console --method ' + method
bool_vars = ["f"]
def fix_bool_variables(args):
prevlen = 0
local_args = args
while prevlen != len(local_args):
prevlen = len(local_args)
local_args = reduce(lambda x, y: (
x + [y[:2], "-%s" % y[2:]]
if (len(y) > 2 and y[:1] == "-" and y[1:2] in bool_vars and
not y[2:].lower().startswith("on") and
not y[2:].lower().startswith("off"))
else x + [y]), local_args, [])
return local_args
def get_list(data):
if data is not None:
for entry in data if cl_core else data[0]:
yield entry
parser = argparse.ArgumentParser(
prog=progr, add_help=False, formatter_class=RawAndDefaultsHelpFormatter)
parser.fixBoolVariables = fix_bool_variables
for Group in (x for x in get_list(view.groups) if x.fields):
group = parser.add_argument_group(Group.name)
for field in get_list(Group.fields):
if field.element == 'error':
error_flag = True
colorPrint.printERROR(field.label)
elif field.opt:
opt = field.opt
data = {'dest': field.name, 'help': opt.help}
if "choice" in field.type and hasattr(field.opt, "syntax") and \
field.opt.syntax and "{" in field.opt.syntax:
lgroup = group.add_mutually_exclusive_group()
help = dict(((x[0].strip("'"), x[2]) for x
in (y.partition(' - ') for y
in field.help.split(',\n'))))
choice = field.choice
if not type(choice) in (list, tuple):
choice = choice.string
for val in (x for x in choice if x):
data['action'] = 'store_const'
# data['nargs'] = '?'
data['const'] = val
data['metavar'] = ""
if hasattr(field, "value") and field.value == val:
data['help'] = (help.get(val, field.help) +
" " + _("(by default)"))
else:
data['help'] = help.get(val, field.help)
lgroup.add_argument(field.opt.syntax.format(choice=val),
**data)
continue
if "password" in field.type:
data['action'] = "store_true"
if "need" in field.type:
data['help'] = argparse.SUPPRESS
else:
data['type'] = str
if field.element in ['check', 'check_tristate']:
if field.element == "check_tristate":
data['action'] = BoolAutoAction
else:
data['action'] = BoolAction
if field.value == 'on':
data['help'] = data['help'] + " " + _(
"(enabled by default)")
if opt.shortopt:
bool_vars.append(opt.shortopt[1])
elif field.element == 'radio' and field.type == 'bool':
data['action'] = BoolAction
if field.value == 'on':
data['help'] = data['help'] + " " + _(
"(enabled by default)")
if opt.shortopt:
bool_vars.append(opt.shortopt[1])
if field.element == 'table' and field.type != 'steps':
data['action'] = 'append'
if data.get('action') != "store_true":
data['metavar'] = opt.metavalue if opt.metavalue \
else field.name.upper()
# if ':' in data['metavar']:
# data['metavar'] = field.name.upper()
if "choice" in field.type:
if "list" in field.type:
data['help'] = "%s (%s)" % (
data['help'],
_("'list' for displaying possible values, "
"'none' is never one"))
else:
data['help'] = "%s (%s)" % (
data['help'],
_("'list' for displaying possible values"))
if "boolauto" in field.type:
data['metavar'] = "ON/OFF/AUTO"
elif "bool3" in field.type:
data['metavar'] = "ON/OFF/AUTO"
elif "bool" in field.type:
data['metavar'] = "ON/OFF"
try:
opts = [x for x in [opt.shortopt, opt.longopt] if x]
if any("-" not in x for x in opts):
data.pop('dest')
data['nargs'] = '?'
group.add_argument(*opts, **data)
except argparse.ArgumentError:
continue
group = parser.add_argument_group(_("Common arguments"))
group.add_argument(
'-f', '--force', action='store_true', default=False,
dest='no_questions', help=_('silent during the process'))
if error_flag:
raise GotErrorField
return parser
def set_obj_item(client, param_object, field_name, value):
"""
Set value for Info object. By client detect (local or WSDL call)
"""
if client:
param_object.__setitem__(field_name, value)
else:
setattr(param_object, field_name, value)
return param_object
def set_table_pwd(client, param_object, field, value):
if type(field.tablevalue.values) in [list, tuple]:
choice_values = field.tablevalue.values
# column = len(field.tablevalue.head)
else:
choice_values = field.tablevalue.values.ChoiceValue
# column = len(field.tablevalue.head.string)
# print ChoiceValue, column
found_flag = False
changed_string = None
if not getattr(param_object, field.name):
for column in range(len(choice_values)):
if found_flag:
break
if "password" in choice_values[column].typefield:
if hasattr(field.tablevalue.body, 'stringArray'):
body = field.tablevalue.body.stringArray
else:
body = field.tablevalue.body
for _row in body:
if hasattr(_row, 'string'):
row = _row.string
else:
if not _row[0]:
row = _row[1:]
else:
row = _row
if not row[column]:
row[column] = value
temp = []
for item in row:
temp.append(item) if item else temp.append('')
changed_string = temp
found_flag = True
break
else:
user_table = getattr(param_object, field.name)
if hasattr(user_table, 'stringArray'):
user_table = user_table.stringArray
for column in range(len(choice_values)):
if found_flag:
break
if "password" in choice_values[column].typefield:
for _row in user_table:
if hasattr(_row, 'string'):
row = _row.string
else:
if not _row[0]:
row = _row[1:]
else:
row = _row
if not row[column]:
row[column] = value
temp = []
for item in row:
temp.append(item) if item else temp.append('')
changed_string = temp
found_flag = True
break
# код выполняется через сетевую консоль
if client:
if not getattr(param_object, field.name):
setattr(param_object, field.name, field.tablevalue.body)
object_array = TableAdapter.get_matrix(param_object[field.name])
# код выполняется локально
else:
if not getattr(param_object, field.name):
setattr(param_object, field.name,
[x[1:] if not x[0] else x for x
in field.tablevalue.body])
object_array = getattr(param_object, field.name)
result = []
for _array in object_array:
temp = []
for item in _array:
temp.append(item) if item else temp.append('')
result.append(temp)
if changed_string:
for item in result:
if str(item[0]) == str(changed_string[0]):
result.remove(item)
result.append(changed_string)
if client:
param_object[field.name] = listToArrayArray(client, result)
else:
setattr(param_object, field.name, result)
return param_object
def display_error(error, args, groups):
params_text = ''
sys.stdout.write('\r')
sys.stdout.flush()
list_answer = False
varname, comments, values, value, list_value = None, None, None, None, []
if error.type != "commonerror":
for group in groups:
for field in group.fields:
if field.name == error.field:
if args is not None:
if (getattr(args, field.name) == "list" and
"choice" in field.type):
if error.field_obj:
field_obj = FieldAdapter.from_detect(error.field_obj)
list_answer = True
varname = (field_obj.label or
field_obj.name)
comments = field_obj.comments
values = field_obj.choice
value = field_obj.value
list_value = error.field_obj.listvalue or []
params_text += getErrorOnParam(args, field)
else:
if field.opt.shortopt or field.opt.longopt:
params_text += _('Wrong option ')
params_text += ' ' + ', '.join((x for x
in [field.opt.shortopt,field.opt.longopt] if x)) + '. %s'
if list_answer:
__print = get_terminal_print(colorPrint.defaultPrint)
__print.foreground(TextState.Colors.WHITE)(
_("%s values:") % varname)
__print("\n")
if comments and values:
maxlen = len(max(values, key=len))
for v, c in zip(values, comments):
if not v and not c:
continue
__print(" ")
__print.bold("[" + v + "]")
__print(" " * (maxlen - len(v)))
__print(" ")
__print(c)
if value == v or v in list_value:
__print(" ")
__print.bold.foreground(TextState.Colors.WHITE)("*")
__print("\n")
if not comments:
for v in (x for x in values if x):
__print(" ")
__print.bold("[" + v + "]")
if value == v:
__print(" ")
__print.bold.foreground(TextState.Colors.WHITE)("*")
__print("\n")
elif error.type != "commonerror":
colorPrint.printERROR(params_text % error)
else:
colorPrint.printWARNING(error)
def check_result_msg(method_result, view, input_error_dict=None, args=None):
if not input_error_dict:
input_error_dict = {}
password_errors = {}
method_result = ArrayReturnedMessage.from_detect(method_result)
view = ViewInfoAdapter.from_detect(view)
for error in method_result:
if error.type == 'pwderror':
password_errors[error.field] = error
continue
display_error(error, args, view.groups)
# если все ошибки связаны с паролем
if len(password_errors) == len(method_result):
if (not dict([x for x in input_error_dict.items()
if x not in password_errors.items()]) and
not dict([x for x in password_errors.items()
if x not in input_error_dict.items()])):
return None
return password_errors
else:
return None
def get_param_pwd(check_res, view, param_object, client=None,
stdin_passwd=False):
view = ViewInfoAdapter.from_detect(view)
for pwd_field in check_res:
if not stdin_passwd:
_print(check_res[pwd_field])
for group in view.groups:
for field in group.fields:
if field.name == pwd_field:
if field.element == 'table':
value = get_password(getfromstdin=stdin_passwd)
if value is None:
_print(check_res[pwd_field])
raise KeyboardInterrupt
set_table_pwd(client, param_object, field, value)
else:
value = get_password(getfromstdin=stdin_passwd)
if value is None:
_print(check_res[pwd_field])
raise KeyboardInterrupt
setattr(param_object, pwd_field, value)
return param_object
def collect_object(client, param_object, view, args, wait_thread=None,
stdin_passwd=False):
"""
Collect Info object by args
"""
steps = None
view = ViewInfoAdapter.from_detect(view)
for group in view.groups:
for field in group.fields:
#if field.uncompatible:
# continue
if (field.element in ['check', 'check_tristate'] and
field.type in ('bool', 'boolauto', 'bool3')) or (
field.element == 'radio' and field.type == 'bool'):
value = _getattr(args, field.name)
if field.type == 'bool3':
pass
else:
if value:
if _getattr(args, field.name).lower() in ['on', 'yes']:
value = True
elif _getattr(args,
field.name).lower() in ['off', 'no']:
value = False
else:
value = None
else:
value = None
param_object = set_obj_item(client, param_object,
field.name, value)
elif (field.element == 'input' and
field.name in ['cl_page_offset', 'cl_page_count']):
val = _getattr(args, field.name)
if not val:
val = 0
if wait_thread:
wait_thread.stop()
# param_object[field.name] = val
param_object = set_obj_item(client, param_object, field.name,
val)
elif field.element in ['input', 'openfile',
'file', 'radio', 'combo', 'comboEdit']:
param_object = set_obj_item(client, param_object, field.name,
_getattr(args, field.name))
elif 'passw' in field.element and _getattr(args, field.name) \
or field.type and "need" in field.type:
if wait_thread:
wait_thread.pause()
label = field.label or _("Password")
password = get_password(label + _(": "),
_('Repeat password: '),
getfromstdin=stdin_passwd,
needrepeat="one" not in field.type)
if password is None:
raise KeyboardInterrupt
param_object = set_obj_item(client, param_object, field.name,
password)
if wait_thread:
wait_thread.resume()
elif field.element in ['multichoice', 'multichoice_add',
'selecttable', 'selecttable_add']:
val = _getattr(args, field.name)
if val in ['off', 'none']:
if client:
value = listToArray(client, [None])
else:
value = []
else:
value = listToArray(client,
val.split(',')) if val else None
param_object = set_obj_item(client, param_object, field.name,
value)
elif field.element == 'table' and field.type != 'steps':
val = _getattr(args, field.name)
value = collect_table(field, val, client, wait_thread,
stdin_passwd)
param_object = set_obj_item(client, param_object, field.name,
value)
elif field.element == 'table' and field.type == 'steps':
steps = field
if hasattr(param_object, 'CheckAll'):
param_object = set_obj_item(client, param_object, 'CheckAll', True)
return param_object, steps
def convertArgDictToList(argDict):
"""
Convert list of dict like {'arg_1':None,'arg_2':'value2','arg_5':'value5'}
to [..,['','value2','','','value5']..] (iterator)
"""
for row in argDict:
yield [row[i] or '' for i in sorted(row.keys())]
def collect_table(field, val_list, client, wait_thread=None,
stdin_passwd=False):
def split_param(l, delimeter=","):
for x in l:
for y in x.split(delimeter):
yield y
if not val_list:
return None
# if specified syntax for table row
if hasattr(field.opt, "syntax") and field.opt.syntax:
#TODO this could be buggy in py3, check
reArgs = re.compile(field.opt.syntax)
# check for correct sentense
for wrong in filterfalse(reArgs.search, val_list):
# raise Error on wrong
raise ValueError(_("Wrong %s value syntax") %
(field.opt.shortopt or field.opt.longopt)
+ " " + wrong)
# create groupdict from all vals
argDict = [x.groupdict() for x in map(reArgs.search, val_list)]
# convert groupdicts to val_table
val_table = list(convertArgDictToList(argDict))
# standard syntax
else:
reduced_list = list(val_list)
val_table = [x.split(':') for x in reduced_list]
if type(field.tablevalue.values) in [list, tuple]:
choiceValue = field.tablevalue.values
else:
choiceValue = field.tablevalue.values.ChoiceValue
choiceValue = [x for x in choiceValue if x.typefield != 'readonly']
lenChoiceValue = len(choiceValue)
for wrong in (x for x in val_table if len(x) > lenChoiceValue):
if type(wrong) in (list, tuple):
wrong = ":".join(wrong)
raise ValueError(_("Wrong %s value syntax") %
(field.opt.shortopt or field.opt.longopt)
+ " " + wrong)
# obj_body = []
# if type(field.tablevalue.body) == list:
# temp_body = field.tablevalue.body
# else:
# temp_body = field.tablevalue.body.stringArray
# for obj_row in temp_body:
# if type(obj_row) != list:
# obj_row = obj_row.string
# for item in range(len(obj_row)):
# if not obj_row[item]:
# obj_row[item] = ''
# else:
# if obj_row:
# if obj_row[0] == '':
# obj_row.pop(0)
# obj_body.append(obj_row)
#
# obj_body = collect_obj_body(obj_body, field)
is_password_get = any('password' in x.typefield for x in choiceValue)
obj_body = []
for line in val_table:
received_password = None
if is_password_get:
if len(line) > 0 and line[0].lower() != '':
if wait_thread:
wait_thread.stop()
sys.stdout.write('\r')
sys.stdout.flush()
received_password = get_password(
_('Password for %s: ') % line[0],
_('Repeat password for %s: ') % line[0],
getfromstdin=stdin_passwd)
if received_password is None:
raise KeyboardInterrupt
temp_row = []
for val, choice_value in zip_longest(
line, (x for x in choiceValue if x.typefield != 'readonly'),
fillvalue=''):
typefield = choice_value.typefield
# if readonly, except first column
if typefield in ['check', 'check_tristate']:
if BoolAction.reTrue.match(val):
temp_row.append('on')
elif BoolAction.reFalse.match(val):
temp_row.append('off')
else:
temp_row.append(val)
elif typefield in ['input', 'combo', 'comboEdit', 'openfile',
'file', 'radio', 'text', 'multichoice',
'multichoice_add']:
temp_row.append(val)
elif typefield == 'password':
if received_password is not None:
temp_row.append(received_password)
else:
temp_row.append(val)
obj_body.append(temp_row)
if not obj_body:
obj_body = [[None]]
return listToArrayArray(client, obj_body)
def collect_obj_body(body, field):
field = FieldAdapter.from_detect(field)
column = len(field.tablevalue.head)
result_table = []
choice_value = field.tablevalue.values
for i in range(len(body)):
temp_row = []
for j in range(column):
# not adding if readonly
if j > (len(choice_value) + 1):
continue
typefield = choice_value[j].typefield
if typefield == 'readonly' and j > 0:
continue
elif typefield in ['check', 'check_tristate']:
if len(body[i]) < j + 1:
temp_row.append('')
continue
if not body[i][j]:
temp_row.append('')
elif body[i][j].lower() in ['on', 'yes']:
temp_row.append('on')
elif body[i][j].lower() in ['off', 'no']:
temp_row.append('off')
else:
temp_row.append(body[i][j])
elif typefield in ['input', 'combo', 'comboEdit', 'openfile',
'file', 'password', 'radio', 'text']:
if len(body[i]) < j + 1:
temp_row.append('')
elif not body[i][j]:
temp_row.append('')
else:
temp_row.append(body[i][j])
elif typefield in ['multichoice', 'multichoice_add']:
if len(body[i]) < j + 1:
temp_row.append('')
elif not body[i][j]:
temp_row.append('')
else:
temp_row.append(body[i][j])
result_table.append(temp_row)
return result_table
def getErrorOnParam(args, field):
"""
Get errors for param
"""
params_text = ""
if any("-" in x for x in (y for y in (field.opt.longopt, field.opt.shortopt) if y)):
param_name = ', '.join((x for x in [field.opt.shortopt, field.opt.longopt] if x))
else:
param_name = field.opt.metavalue
if getattr(args, field.name) is None and "need" not in field.type:
params_text += "%s. " + _("Use the parameter") + " "
params_text += param_name + '. '
else:
if "need" in field.type:
params_text += \
_('Error in field \'%s\'. ') % field.label + " %s"
elif getattr(args, field.name) == "list" and "choice" in field.type:
params_text += "%s"
else:
params_text += _('Error in parameter ')
params_text += param_name + '. %s'
return params_text