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-lib/pym/calculate/lib/datavars.py

2024 lines
70 KiB

9 years ago
# -*- coding: utf-8 -*-
12 years ago
# Copyright 2008-2016 Mir Calculate. http://www.calculate-linux.org
12 years ago
#
# 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.
13 years ago
import re
14 years ago
import sys
13 years ago
import importlib
from .utils.tools import drop_slash
3 years ago
from .utils.text import convertStrListDict, _u, _u8, formatListOr
from .utils.files import pathJoin
from .utils.portage import searchProfile, RepositorySubstituting, RepositoryPath
13 years ago
from os import path
import os
3 years ago
from collections import OrderedDict
from collections.abc import Iterable
from threading import RLock
from itertools import *
import operator
import traceback
from string import Formatter
from contextlib import contextmanager
3 years ago
# from types import StringTypes, GeneratorType
from types import GeneratorType
from .configparser import ConfigParser, ParsingError
13 years ago
from .cl_lang import setLocalTranslate, getLazyLocalTranslate
9 years ago
_ = lambda x: x
setLocalTranslate('cl_lib3', sys.modules[__name__])
__ = getLazyLocalTranslate(_)
9 years ago
def addStdConfig(fileLst, prefix='/'):
stdPath = path.join(prefix,
drop_slash(RepositoryPath.Calculate), "calculate.env")
9 years ago
if stdPath not in map(os.path.abspath, fileLst):
return [stdPath] + fileLst
return fileLst
9 years ago
def itemgetter(*args, **kwargs):
"""
itemgetter with alwaysTuple param, which used for force tuple elements
"""
9 years ago
alwaysTuple = kwargs.get('alwaysTuple', False)
if alwaysTuple:
9 years ago
if len(args) == 1:
return lambda x: (x[args[0]],)
return operator.itemgetter(*args)
9 years ago
class CriticalError(Exception):
"""Critical error"""
9 years ago
class DataVarsError(Exception):
"""Exception of getting variable values"""
9 years ago
class ImportModuleDataVarsError(DataVarsError):
"""Ошибка импортирования модуля"""
9 years ago
class VariableError(Exception):
"""Exception of sended by Variable"""
9 years ago
class PasswordError(VariableError):
"""Exception of password change error"""
9 years ago
class CommonVariableError(VariableError):
"""Exception for command line"""
9 years ago
def makePath(dirs, mode=755):
13 years ago
if not path.exists(dirs):
9 years ago
os.makedirs(dirs, mode)
13 years ago
READONLY = "r"
WRITEABLE = "w"
9 years ago
class HumanReadable():
9 years ago
Yes = True
No = False
Auto = None
class ValueFormatter(Formatter):
def get_field(self, field_name, args, kwargs):
Get = args[0]
if field_name.endswith("()"):
field_name, o, func = field_name.rpartition(".")
value = str(Get(field_name))
return getattr(value, func[:-2])(), None
return Get(field_name), None
class VariableInterface():
_value_formatter = ValueFormatter()
8 years ago
type = "string"
9 years ago
def Get(self, varname=None, humanreadable=False):
pass
def Choice(self, varname):
pass
def Select(self, selField, **kwargs):
pass
def select(self, *fields, **kw):
pass
def ZipVars(self, *argvVarNames, **kw):
9 years ago
pass
def uncompatible(self):
pass
def set(self, value):
pass
def get(self):
pass
def choice(self):
pass
def GetBool(self, varname):
pass
def GetInteger(self, varname):
pass
def invalidate(self, force=False):
pass
def is_console_set(self, varname):
pass
9 years ago
class Variable(VariableInterface):
13 years ago
"""
Class of variable. Need for creating calculate utilities variable
add fill method described by class with fill methods.
Instance attributes:
wasSet : boolean
variable value was set by _Set method
reqVars : List
list of variable which use this variable in fill method
invalid : boolean
invalid value
section : string
section of variable (main,install,builder and etc)
"""
9 years ago
class Types():
String = "string"
List = "list"
Choice = "choice"
Table = "table"
8 years ago
Boolean = "bool"
Object = "object"
Tristate = "bool3"
9 years ago
13 years ago
# label of variable
label = None
# opts for cmdline
opt = None
# metavalues
metavalue = None
13 years ago
# help information
help = None
# writeable variable
mode = WRITEABLE
# hidden variable
hide = True
# default value
value = None
# variable section
section = "main"
# variable name
name = ""
12 years ago
# syntax for opts
syntax = ""
# variable type: string, multichoice, list, number, choiceedit, table
# flag, yesno, password
type = "string"
# source column with data
source = None
9 years ago
# gui element type
element = None
# force check after variables in list
check_after = []
# fill value is true
untrusted = False
9 years ago
NONE, CHECK, UNCOMPAT, HUMAN = 0, 1, 2, 3
# при установке значения переменной устанавливает значение
# указанной переменной
alias = ""
# значение заполняется переменными
value_format = ""
8 years ago
# спец тип для gui
guitype = ""
On = "on"
Off = "off"
Auto = "auto"
EmptyTable = [[]]
Readonly = READONLY
Writable = WRITEABLE
9 years ago
def __init__(self, parent=None, **kwargs):
13 years ago
"""
Initialize instance
"""
self.modeGet = Variable.NONE
9 years ago
self.wasSet = False # variable is user or ini set
self.reqVars = [] # varaibles which used this value for fill
self.reqCheck = [] # variables which used this value for check
self.reqUncompat = [] # varaibles which used for uncompat
13 years ago
self.variableType = type
self.parent = parent
9 years ago
# self.value is None or self.name in self.parent.iniCache
self.invalid = True
self.name = self.getVariableName()
self.processInvalidate = False
# производится чтение из ini
self.bIniRead = False
self.init()
9 years ago
for key, val in kwargs.items():
setattr(self, key, val)
def init(self):
"""
Overridible init using for palce translatable strings
"""
pass
@classmethod
def getVariableName(cls):
return re.sub("(.)([A-Z])", "\\1_\\2", cls.__name__[8:]).lower()
12 years ago
def getCharType(self):
"""
Get symbol of type
"""
9 years ago
mapType = OrderedDict(table='t', list='l', choice='c', number='i',
bool='b')
12 years ago
for k in mapType.keys():
if k in self.type:
return mapType[k]
else:
return "s"
@property
def empty_value(self):
if "list" in self.type:
return []
elif "table" in self.type:
return [[]]
return ""
def is_console_set(self, varname):
return self.parent.is_console_set(varname)
def GetBool(self, varname):
return self.isTrue(self.Get(varname))
def GetInteger(self, varname):
return int(self.Get(varname))
9 years ago
def Get(self, varname=None, humanreadable=False):
"""Get value of other value"""
if not varname or varname == self.name:
return self._get()
3 years ago
varObj = self.parent.getInfo(varname)
9 years ago
# varObj.modeGet = Variable.UNCOMPAT
12 years ago
if not "." in varname:
3 years ago
# varname = "%s.%s" % tuple([self.section, varname])
varname = f"{self.section}.{varname}"
9 years ago
res = self.parent.Get(varname, humanreadable)
# build dependence for check and uncompatible
if varObj:
if self.modeGet == Variable.NONE:
9 years ago
if self not in varObj.reqVars:
varObj.reqVars.append(self)
if self.modeGet == Variable.CHECK:
9 years ago
if self not in varObj.reqCheck:
varObj.reqCheck.append(self)
elif self.modeGet == Variable.UNCOMPAT:
9 years ago
if varObj not in self.reqUncompat:
self.reqUncompat.append(varObj)
return res
9 years ago
def Choice(self, varname):
"""Choice from other value"""
return self.parent.Choice(varname)
14 years ago
9 years ago
def Select(self, selField, **kwargs):
"""Select by datavars"""
9 years ago
return self.parent.Select(selField, zipVars=self.ZipVars, **kwargs)
def select(self, *fields, **kw):
return self.parent.select(*fields, zip_vars=self.ZipVars, **kw)
def getRemoteInfo(self, envFile):
"""getRemoteInfo by datavars"""
return self.parent.getRemoteInfo(envFile)
def ZipVars(self, *argvVarNames, **kw):
"""
Get zipped values of variables specified by list 'argvVarNames'
"""
if "humanreadable" in kw:
hr = kw['humanreadable']
return list(zip(*(self.Get(x, humanreadable=hr) for x in argvVarNames)))
else:
return list(zip(*map(self.Get, argvVarNames)))
def _get_format_value(self):
return self._value_formatter.format(
self.__class__.value_format, self.Get)
def get(self):
"""
Overridable
Calculate value method
"""
if self.__class__.value_format:
return self._get_format_value()
if self.__class__.value:
return self.__class__.value
else:
return [] if "list" in self.type else ""
14 years ago
def humanReadable(self):
13 years ago
"""Return human readable value"""
val = self.Get()
9 years ago
if "choice" in self.type:
choiceVal, commentVal = self._choice()
if commentVal:
9 years ago
valDict = dict(zip(choiceVal, commentVal))
if "list" in self.type:
return [x if isinstance(x, (list, tuple))
else valDict.get(x, x) for x in val]
else:
9 years ago
return valDict.get(val, val)
return val
def _human(self):
9 years ago
oldModeGet = self.modeGet
try:
self.modeGet = Variable.HUMAN
return self.humanReadable()
finally:
self.modeGet = oldModeGet
def getHumanReadableAuto(self):
"""
Return humanreadable values for readonly variables
"""
if self.mode == READONLY:
return self._human()
else:
return self._get()
12 years ago
def iniread(self):
"""
Read from ini file
"""
if self.bIniRead:
return False
self.bIniRead = True
try:
value = self.parent.iniCache[self.fullname]
3 years ago
value = self.parent.unserialize(self.type, value)
# value = self.parent.unserialize(self.type,
# value.encode('utf-8'))
if self.mode == READONLY:
raise VariableError(
8 years ago
_("Attempting to rewrite readonly variable %s "
"via calculate.env") %
self.name)
else:
try:
self._set(value)
9 years ago
except Exception:
return False
return True
finally:
self.bIniRead = False
12 years ago
@property
def fullname(self):
return '%s.%s' % (self.section, self.name)
def _get(self):
13 years ago
"""
Standard inner method for getting value of variable.
"""
# variable need refill
if self.invalid:
# get net value
if self.fullname in self.parent.iniCache and self.iniread():
12 years ago
return self.value
else:
9 years ago
oldModeGet = self.modeGet
12 years ago
try:
self.modeGet = Variable.NONE
value = self.get()
self.untrusted = self.__class__.untrusted
12 years ago
finally:
self.modeGet = oldModeGet
13 years ago
# if value not equal previous value
if value != self.value:
# invalidate depended variables
self.invalidate()
13 years ago
# mark as filled
self.invalid = False
9 years ago
if hasattr(self.value, "close"):
13 years ago
self.value.close()
13 years ago
self.value = value
3 years ago
# return self.value
val = self.value
if isinstance(val, bytes):
val = str(val, encoding="UTF-8")
3 years ago
return val
def choice(self):
"""
Overridable
Generation list of allowable values
"""
13 years ago
return []
def _choice(self):
"""
Convert choice created by variable choice to two tuple (values,comments)
"""
res = self.choice()
9 years ago
if isinstance(res, GeneratorType):
res = tuple(res)
if res and type(res[0]) in (tuple, list):
return list(zip(*res))
else:
9 years ago
return res, None
8 years ago
def check_on(self):
pass
def check_off(self):
pass
9 years ago
def check(self, value):
"""
Overridable
Check method, for wrong value need raise VariableError
"""
8 years ago
if self.type == self.Types.Boolean:
if self.isTrue(value):
self.check_on()
else:
self.check_off()
14 years ago
pass
def uncompatible(self):
"""
Overridable
Using for check uncompatibility using variable with value of
other variables.
"""
return ""
def _uncompatible(self):
"""
Full check uncompatible
"""
try:
self.modeGet = Variable.UNCOMPAT
self.reqUncompat = []
return self.uncompatible()
finally:
self.modeGet = Variable.NONE
9 years ago
def set(self, value):
"""
Overridable
Using for replace value before set
"""
9 years ago
def convert(value):
12 years ago
if value and value.lower() != "auto":
return "on" if self.isTrue(value) else "off"
else:
return ""
9 years ago
if self.type == "bool":
value = "on" if self.isTrue(value) else "off"
if "bool" in self.type and "list" in self.type:
return [convert(x) for x in value]
if "int" in self.type:
return str(value)
13 years ago
return value
14 years ago
def raiseNothingValue(self):
"""
Using for override error message about nothing value.
"""
pass
9 years ago
def checkType(self, value):
13 years ago
"""Check value for type"""
if "int" in self.type:
8 years ago
if (value and not value.isdigit() and not value.startswith("-") and
not value[1:].isdigit()):
raise VariableError(
_("The value of variable '{varname}' must be integer"
9 years ago
).format(varname=self.label or self.name))
13 years ago
if "list" in self.type:
9 years ago
if not type(value) in (list, tuple):
raise VariableError(
9 years ago
_("The value for variable '{varname}' "
"may be {vartype} only").format(
varname=self.label or self.name,
vartype="list"))
error = _("Values for variable '{varname}' may be {vartype} only")
13 years ago
else:
9 years ago
value = repeat(value, 1)
error = _(
"The value for variable '{varname}' may be {vartype} only")
13 years ago
if "string" in self.type:
9 years ago
value, valuecopy = tee(value, 2)
if any(x for x in valuecopy if not isinstance(x, str)):
13 years ago
raise VariableError(error.format(
varname=self.label or self.name,
vartype="string"))
return
if "choice" in self.type:
8 years ago
choiceVal = self.choice() or []
9 years ago
if isinstance(choiceVal, GeneratorType):
choiceVal = tuple(choiceVal)
tipChoice = ['"%s" [%s]' % (x[1], x[0]) if type(x) in (list, tuple) else str(x) for x in choiceVal]
9 years ago
if choiceVal and type(choiceVal[0]) in (tuple, list):
choiceVal = [x[0] for x in choiceVal]
9 years ago
if "list-list" not in self.type:
value = repeat(value, 1)
for recval in value:
for val in recval:
name = self.label or self.name
if val == "list" and "choice" in self.type:
if "edit" in self.type:
if "list" in self.type:
error = _("Values for variable '{varname}' may "
"be {vartype}")
else:
9 years ago
error = _(
"The value for variable '{varname}' may be "
"{vartype}")
self.raiseWrongChoice(name, tipChoice, val, error)
if "choice" in self.type and not "choiceedit" in self.type:
8 years ago
if ((choiceVal and (val or val == "") and
val not in choiceVal or
val is None) or
not choiceVal):
if not choiceVal:
self.raiseNothingValue()
9 years ago
self.raiseWrongChoice(name, tipChoice, val, error)
9 years ago
def raiseWrongChoice(self, name, choiceVal, value, error):
raise VariableError(error.format(
9 years ago
varname=name,
vartype=formatListOr(choiceVal)))
13 years ago
9 years ago
def setValue(self, value, force=False):
"""
Standard action for set value
"""
self.value = self.set(value)
9 years ago
self.wasSet = True
self.invalid = False
# run check
if not force:
self._check()
9 years ago
def _set(self, value, force=False):
14 years ago
"""
13 years ago
Standard inner method for setting value for variable.
14 years ago
"""
13 years ago
# runc check choice
if type(value) == int:
value = str(value)
if not force:
try:
self.modeGet = Variable.CHECK
self.checkType(value)
finally:
self.modeGet = Variable.NONE
13 years ago
# if value change
9 years ago
if value != self.value or type(value) in (list, tuple):
self.invalidate(True)
9 years ago
if hasattr(self.value, "close"):
13 years ago
self.value.close()
13 years ago
# run set value
9 years ago
self.setValue(value, force)
9 years ago
def _check(self, value=None):
"""
Full check value
"""
if self.name != "cl_help_set" and not self.GetBool('cl_help_set'):
if value is None:
value = self.Get(self.name)
try:
self.modeGet = Variable.CHECK
self.untrusted = True
self.check(value)
self.untrusted = False
finally:
self.modeGet = Variable.NONE
13 years ago
9 years ago
def invalidate(self, force=False):
14 years ago
"""
13 years ago
Invalidate value of variable (drop filled value).
14 years ago
13 years ago
force : boolean=False
Drop value also for after manual set
14 years ago
"""
# fix possible infinite recursion on invalidating
if not self.processInvalidate and (force or not self.wasSet):
try:
# mark variable that in invalidation now
self.processInvalidate = True
self.wasSet = False
self.invalid = True
for var in self.reqVars:
var.invalidate()
var.untrusted = var.__class__.untrusted
for var in self.reqCheck:
var.untrusted = True
self.reqVars = []
self.reqCheck = []
finally:
# unmark process invalidate
self.processInvalidate = False
13 years ago
@classmethod
9 years ago
def isTrue(cls, value):
if type(value) == bool:
return value
value = value.lower()
if value in ('yes', 'on', 'true'):
return True
if value == 'auto':
return None
return False
9 years ago
def has_base_method(self, methodname):
"""
Проверить не изменился ли метод после наследования
"""
base_method = getattr(Variable, methodname)
9 years ago
method = getattr(self, methodname).__func__
return base_method == method
class TableVariable(Variable):
"""
Table type variable
"""
type = "table"
9 years ago
def set(self, value):
return value
9 years ago
def get(self, hr=HumanReadable.No):
"""Get table data"""
for varname, value in (x for x in ((y, self.Get(y)) for y in self.source) if not isinstance(x[1], list)):
raise VariableError(
9 years ago
_("Source variable %s does not contain a list") % varname)
return [list(x) for x in zip_longest(*[self.Get(x, humanreadable=hr)
for x in self.source], fillvalue='')] or [[]]
def getHumanReadableAuto(self):
"""
Return humanreadable values for readonly variables
"""
9 years ago
return self.get(hr=HumanReadable.Auto)
def humanReadable(self):
9 years ago
return self.get(hr=HumanReadable.Yes)
9 years ago
def __getWritableColumns(self, includeFirst=False):
"""
Get data for writable columns exclude index column
(Example: (1,'os_disk_mount)
"""
if includeFirst:
offset = 0
else:
offset = 1
# return list(filter(lambda x: self.parent.getInfo(x[1]).mode == WRITEABLE,
# enumerate(self.source[offset:])))
return [x for x in enumerate(self.source[offset:]) if self.parent.getInfo(x[1]).mode == WRITEABLE]
9 years ago
def check(self, value):
"""
Check table value - check all writeable columns.
"""
9 years ago
writeCols = list(self.__getWritableColumns(includeFirst=True))
error = []
if not any(value):
9 years ago
value = [[]] * len(writeCols)
else:
value = list(zip(*map(itemgetter(*map(itemgetter(0),
writeCols), alwaysTuple=True),value)))
for colInfo, values in zip(writeCols, value):
try:
9 years ago
self.parent.Check(colInfo[1], values)
except VariableError as e:
error.append(e)
if error:
raise VariableError(error)
def __isIndexWritable(self):
return self.parent.getInfo(self.source[0]).mode == WRITEABLE
9 years ago
def checkType(self, value):
"""Check table value type"""
# check type value (list and each element is list)
9 years ago
if not type(value) in (list, tuple) or \
any(i for i in value if not type(i) in (tuple, list)):
raise VariableError(
9 years ago
_("The value for {varname} may be '{vartype}' only").format(
varname=self.label or self.name,
vartype="table"))
# check len all entries
9 years ago
writeLen = len(list(self.__getWritableColumns())) + 1
for item in value:
9 years ago
if item and not len(item) in (writeLen, len(self.source)):
raise VariableError(
_("Wrong entry '{entry}' for table variable '{varname}'").
format(entry=str(item),
9 years ago
varname=(self.label or self.name).lower()) + "\n" +
_("Each entry must contains %d field(s)") % writeLen)
# check rewrite readonly index
if not self.__isIndexWritable():
indexValues = self.Get(self.source[0])
for item in value:
if item and not item[0] in indexValues:
self.raiseReadonlyIndexError(self.source[0],
self.name,
item[0])
9 years ago
def raiseReadonlyIndexError(self, fieldname="", variablename="",
value=""):
"""
Overriddible method for spcifing behavior on rewrite
readonly index
"""
raise DataVarsError(
8 years ago
_("Attempting to rewrite a readonly index field "
9 years ago
"{fieldname} in variable {variablename}").format(
fieldname=fieldname, variablename=variablename))
9 years ago
def setValue(self, value, force=False):
value = self.set(value)
self.untrusted = True
oldvalue = self.Get(self.name)
# get writable columns
writeCols = self.__getWritableColumns()
# get slicer
9 years ago
_slice = itemgetter(*map(itemgetter(0), writeCols),
alwaysTuple=True)
# create dict for writable columns
# if table not empty
if any(oldvalue):
# oldvalue = OrderedDict(map(lambda x: (x[0], _slice(x[1:])),
# oldvalue))
oldvalue = OrderedDict([(x[0], _slice(x[1:])) for x in oldvalue])
else:
oldvalue = OrderedDict()
# get new dict
if any(value):
if len(value[0]) == len(self.source):
# newval = OrderedDict(map(lambda x: (x[0], _slice(x[1:])),
# value))
newval = OrderedDict([(x[0], _slice(x[1:])) for x in value])
else:
# newval = OrderedDict(map(lambda x: (x[0], x[1:]), value))
newval = OrderedDict([(x[0], x[1:]) for x in value])
else:
newval = OrderedDict()
# if table with writable index field then replace all table
error = []
if self.__isIndexWritable():
if not force and any(value):
self.parent.Check(self.source[0], list(zip(*value))[0])
oldvalue = newval
try:
#py3 keys() now returns its own type instead of a list
self.parent.Set(self.source[0], list(oldvalue.keys()))
3 years ago
except VariableError as e:
error.append(e)
# update entry by index field
else:
oldvalue.update(newval)
oldvalValues = list(zip(*oldvalue.values()))
for col, vals in zip((x[1] for x in writeCols),
9 years ago
oldvalValues):
try:
9 years ago
self.parent.Set(col, list(vals))
3 years ago
except VariableError as e:
error.append(e)
9 years ago
for num, varname in writeCols[len(oldvalValues):]:
self.parent.Invalidate(varname, True)
if error:
raise VariableError(error)
else:
self.untrusted = False
9 years ago
class ReadonlyVariable(Variable):
"""
Alias for readonly variables
"""
mode = READONLY
9 years ago
12 years ago
class ActionVariable(ReadonlyVariable):
nonchroot = False
postinst = False
def get(self):
if self.nonchroot and self.Get('cl_chroot_status') == "on":
return "off"
if self.postinst and not self.Get('cl_ebuild_phase') in \
9 years ago
('', 'postinst', 'prerm'):
12 years ago
return "off"
return self.action(self.Get('cl_action'))
9 years ago
def action(self, cl_action):
return "off"
class FieldValue(VariableInterface):
"""
Table column variable
"""
type = "list"
source_variable = ""
column = 0
def get(self):
sourceVar = self.Get(self.source_variable)
9 years ago
if isinstance(sourceVar, Iterable):
if any(sourceVar):
3 years ago
return list(zip(*sourceVar))[self.column]
9 years ago
else:
return []
else:
9 years ago
raise VariableError(_("Field variable got not iterable value"))
class SourceReadonlyVariable(ReadonlyVariable):
"""
Source readonly variable (Using for table)
Example:
['os_location_source',...,'os_location_size'(this)]
"""
indexField = ""
def get(self):
return [x or "" for x in map(self.getMap().get,
self.Get(self.indexField))]
def humanReadable(self):
return [x or "" for x in map(self.getMapHumanReadable().get,
self.Get(self.indexField))]
def getMap(self):
return {}
def getMapHumanReadable(self):
return self.getMap()
9 years ago
class ReadonlyTableVariable(TableVariable):
"""
Alias for readonly table
"""
mode = READONLY
9 years ago
class SimpleDataVars():
"""
Simple datavars for temporary link var objs.
"""
systemRoot = "/"
def __init__(self, *objs):
self.allVars = {}
self.cache = {}
self.changed = set()
for obj in objs:
obj.parent = self
self.allVars[obj.getVariableName()] = obj
9 years ago
def Get(self, varname, humanreadable=HumanReadable.No):
12 years ago
varname = varname.rpartition(".")[2]
if not varname in self.cache:
if self.allVars.get(varname) is not None:
self.cache[varname] = self.allVars.get(varname).get()
else:
# ошибка возникает, когда такой переменной нет
# в этом пространстве переменных, например
# нет зависимой переменной
9 years ago
raise DataVarsError(_("Failed to get value %s") % varname)
return self.cache[varname]
def Set(self, varname, value):
varname = varname.rpartition(".")[2]
self.cache[varname] = value
self.changed.add(varname)
def Invalidate(self, varname):
varname = varname.rpartition(".")[2]
if varname in self.cache:
self.cache.pop(varname)
if varname in self.changed:
self.changed.remove(varname)
9 years ago
def GetBool(self, varname):
return Variable.isTrue(self.Get(varname))
9 years ago
def GetInteger(self, varname):
"""
Получить целочисленное значение
"""
try:
return int(self.Get(varname))
except ValueError:
return 0
9 years ago
def getInfo(self, varname):
return self.allVars.get(varname, None)
def __getitem__(self, item):
return self.Get(item)
def __setitem__(self, key, value):
self.Set(key, value)
def prepare_all(self):
for var in self.allVars.keys():
self.Get(var)
9 years ago
def flIniFileFrom(self, iniFile, system_root=''):
"""
Read variable values from ini files.
Return False if ini file is invalid.
"""
config = ConfigParser(strict=False)
12 years ago
if path.isdir(iniFile):
rs = RepositorySubstituting(self, system_root=system_root)
try:
config.read(addStdConfig(
searchProfile(iniFile, 'calculate.env',
repository_sub=rs),
prefix=self.systemRoot), encoding="utf-8")
except ParsingError:
raise DataVarsError(_("Error in calculate.env in profile"))
12 years ago
else:
try:
config.read(iniFile, encoding="utf-8")
except ParsingError:
raise DataVarsError(_("Error in %s") % iniFile)
importVars = {}
for varname, varobj in self.allVars.items():
if varobj.section not in importVars:
importVars[varobj.section] = \
(dict(config.items(varobj.section, raw=True))
9 years ago
if config.has_section(varobj.section)
else {})
if varname not in self.changed:
val = self.unserialize(
varobj.type or "string",
3 years ago
#TODO bin or string?
importVars[varobj.section].get(varname, ''))
if val and val != [[]] or varname in importVars[varobj.section]:
self.cache[varname] = val
@staticmethod
def serialize(varType, value):
12 years ago
"""
Serialize to string for ini file
"""
fixEmpty = lambda x: str(x) or "''"
9 years ago
# fixSpace = lambda x: "'%s'" % str(x) if " " in str(x) else str(x)
isListOrTuple = lambda x: type(x) in (list, tuple)
12 years ago
if isListOrTuple(value):
if "list" in varType:
return ",".join(map(fixEmpty, value))
12 years ago
elif "table" in varType:
return ",".join((":".join(map(fixEmpty, x)) for x in value))
12 years ago
return fixEmpty(value)
@staticmethod
def unserialize(varType, value):
12 years ago
"""
Unserialize form string for varname
"""
fixEmpty = lambda x: "" if x == "''" or x == '""' else x.strip()
def getList(delimeter=','):
def wrapper(val):
val = str(val)
if val == "":
return []
return [fixEmpty(x) for x in val.split(delimeter)]
return wrapper
12 years ago
if "list" in varType:
return getList()(value)
12 years ago
if "table" in varType:
return [getList(':')(x) for x in value.split(',')]
# if (isinstance(value, bytes)):
# value = str(value, "UTF-8")
return fixEmpty(value).strip("'").strip('"')
12 years ago
def ZipVars(self, *argvVarNames, **kw):
"""
Get zipped values of variables specified by list 'argvVarNames'
"""
if "humanreadable" in kw:
hr = kw['humanreadable']
return list(zip(*(self.Get(x, humanreadable=hr) for x in argvVarNames)))
else:
return list(zip(*(self.Get(x) for x in argvVarNames)))
def select(self, *fields, **kw):
"""
Новая функция выборки из табличных переменных
:param fields: необходимые поля
:param kw: аргумены выборки
:param limit: количество возвращаемых элементов
:param zip_vars: функция объединения переменных
:return:
"""
keywords = ["limit", "zip_vars"]
zip_vars = kw.get("zip_vars", self.ZipVars)
filter_chain = []
variables = list(fields)
for k in (x for x in kw if x not in keywords):
varname, op, funcname = k.partition("__")
if varname[2] != "_":
varname = varname.replace("_", ".", 1)
if not op:
funcname = "eq"
variables.append(varname)
func_maps = {
'eq': lambda x, y: lambda z: z[x] == y,
'ne': lambda x, y: lambda z: z[x] != y,
'in': lambda x, y: lambda z: z[x] in y,
'not_in': lambda x, y: lambda z: z[x] not in y,
'startswith': lambda x, y: lambda z: z[x].startswith(y)
}
filter_chain.append(func_maps[funcname](len(variables) - 1, kw[k]))
l = len(fields)
if l == 1:
9 years ago
ret_func = lambda x: x[0]
else:
9 years ago
ret_func = lambda x: x[:l]
def generator(limit):
c = 0
for x in zip_vars(*variables):
for f in filter_chain:
if not f(x):
break
else:
yield ret_func(x)
if limit and c >= limit:
break
else:
c += 1
limit = kw.get("limit", None)
if limit == 1:
for x in generator(limit):
return x
else:
if l == 1:
return ""
else:
9 years ago
return [""] * l
else:
return list(generator(limit))
9 years ago
def Select(self, selField, where="os_disk_dev", eq=None, ne=None,
_in=None, _notin=None, like=None, notlike=None, func=None,
_if=None,
9 years ago
sort=None, sortkey=None, limit=None, zipVars=None):
"""Select value from table variables"""
if zipVars is None:
zipVars = self.ZipVars
if func or _if:
if _if:
func = _if
3 years ago
if func.__code__.co_argcount > 1:
filterFunc = lambda x: func(*x[:func.__code__.co_argcount])
else:
filterFunc = func
9 years ago
elif eq is not None:
filterFunc = lambda x: x[0] == eq
elif ne is not None:
filterFunc = lambda x: x[0] != ne
elif _in is not None:
filterFunc = lambda x: x[0] in _in
elif _notin is not None:
filterFunc = lambda x: not x[0] in _notin
elif like is not None:
filterFunc = lambda x: re.compile(like).search(x[0])
elif notlike is not None:
filterFunc = lambda x: not re.compile(notlike).search(x[0])
else:
9 years ago
filterFunc = lambda x: x
9 years ago
if not type(where) in (tuple, list):
where = [where]
woffset = len(where)
3 years ago
9 years ago
if isinstance(selField, (tuple, list)):
count = len(selField) + woffset
mapFunc = lambda x: x[woffset:]
res = [x for x in zipVars(*(where + selField)) if filterFunc(x)]
else:
9 years ago
count = 1 + woffset
fields = where + [selField]
mapFunc = lambda x: x[woffset]
res = [x for x in zipVars(*(fields)) if filterFunc(x)]
if sort:
if "/" in sort:
9 years ago
sort, sortkey = sort.split('/')
sortkey = itemgetter(*map(int, sortkey.split(',')))
res.sort(key=sortkey, reverse=True if sort == "DESC" else False)
if limit == 1:
if not any(res):
9 years ago
res = [[""] * count]
return mapFunc(res[0])
else:
return [mapFunc(x) for x in res[:limit]]
12 years ago
class DataVars(SimpleDataVars):
13 years ago
"""
Class contains variables, perform creating variable objects by
class variable describer and variable filler.
Instance attributes:
moduleList : Dict
dictionary has section name with modules which describe variable
for this sectin
loadVariables : Dict
contains all initialized variables load from varObj and fillObj
requestVariables : List
contains var object which already run Get method. Use for detect
dependence of variables.
"""
defaultData = 'calculate.lib.variables'
12 years ago
reRightVar = re.compile(r'^(?:([a-z_]+)\.)?([a-z_0-9]+)$')
l = RLock()
def __init__(self):
3 years ago
super().__init__()
self.requestVariables = []
self.loadVariables = {}
self.allVars = {}
self.untrustedVariables = set()
self.refresh = []
self.groups = []
self.mapVarGroup = OrderedDict()
self.briefData = {}
self.filledVars = {}
12 years ago
self.defaultModule = "main"
self.importedModules = []
12 years ago
self.iniCache = {}
self.map_opt_vars = {}
@contextmanager
def useDefaultModule(self, modulename):
oldmodule = self.defaultModule
try:
self.defaultModule = modulename
yield self
finally:
self.defaultModule = oldmodule
9 years ago
def isModuleInstalled(self, module):
try:
9 years ago
importlib.import_module("calculate.%s.datavars" % module)
return True
9 years ago
except ImportError:
return False
9 years ago
def importData(self, data=None):
"""
Depricated function for support 3.0 utilities
"""
12 years ago
section = self.importVariables(data)
if data:
self.defaultModule = section
9 years ago
def importVariables(self, data=None):
14 years ago
"""
13 years ago
Import modules for variables. 'section' is section name, 'modList'
contains tuple with modules which discribe variable names and fill
methods
"""
# try import vars and fill modules specified by modList
if not data:
data = self.defaultData
14 years ago
try:
13 years ago
varModule = importlib.import_module(data)
3 years ago
except (ImportError, AttributeError) as e:
3 years ago
self.raiseModuleError(data, e)
9 years ago
return False
# get all Variable classes from module
# variable of class VariableClAction will be named cl_action
9 years ago
if hasattr(varModule, "section"):
section = varModule.section
else:
section = "main"
for varMod in [getattr(varModule, x) for x in dir(varModule)
if not x.startswith("_") and "Variable" not in x] + [varModule]:
3 years ago
for classname in filterfalse(
9 years ago
("ReadonlyVariable", "VariableInterface",
"Variable", "VariableError").__contains__,
(x for x in dir(varMod) if x.startswith("Variable"))):
9 years ago
varObj = getattr(varMod, classname)
varName = varObj.getVariableName()
12 years ago
if not varName in self.allVars:
9 years ago
self.allVars[varName] = (section, varObj)
12 years ago
self.importedModules.append(section)
return section
13 years ago
9 years ago
def raiseVariableNotFound(self, varname, *args, **kwargs):
# import traceback
# traceback.print_stack()
# print "Variable not found:", varname
9 years ago
raise DataVarsError(_("Variable %s not found") % varname)
9 years ago
def raiseModuleError(self, module, error, *args, **kwargs):
raise ImportModuleDataVarsError("\n".join([
9 years ago
_("Failed to import module %s") % module,
_("error") + ": " + str(error)]))
12 years ago
9 years ago
def loadVariable(self, varname, section=None):
13 years ago
"""
Initialize variable 'varname' from fillObj and varObj.
"""
if not self.allVars:
self.importVariables()
9 years ago
if section and section not in self.importedModules:
self.importVariables("calculate.%s.variables" % section)
12 years ago
self.flIniFile(onlySection=section)
9 years ago
if varname not in self.loadVariables:
13 years ago
if varname in self.allVars.keys():
9 years ago
section, varObj = self.allVars[varname]
newVar = varObj(parent=self, section=section)
if hasattr(newVar, "refresh"):
self.refresh.append(newVar)
13 years ago
self.loadVariables[varname] = newVar
else:
12 years ago
# this code using for raise exception or
# if replace raiseVariableNotFound method
# then return default value
self.loadVariables[varname] = \
12 years ago
self.raiseVariableNotFound(
9 years ago
varname, parent=self, section="main")
14 years ago
9 years ago
def exists(self, varName):
try:
self.Get(varName)
return True
9 years ago
except Exception:
return False
9 years ago
def defined(self, varName):
"""
Return exists or not varName
"""
return varName in self.allVars.keys()
9 years ago
def getIniVar(self, fullVarName):
13 years ago
"""
Get variable values from ini files. Variable specified by
'fullVarName' in format: section 'dot' variable. If specified
only variable then section will be 'main'
13 years ago
Example:
self.getIniVar('install.os_install_net_settings')
self.getIniVar('cl_action')
"""
calculateIniFiles = self.Get('main.cl_env_path')
13 years ago
section, dot, varname = fullVarName.rpartition('.')
if not section:
section = "main"
13 years ago
retVal = ""
for iniFile in calculateIniFiles:
if path.exists(iniFile):
config = ConfigParser(strict=False)
try:
config.read(iniFile, encoding="utf-8")
value = config[section][varname]
13 years ago
retVal = value
except ParsingError:
raise DataVarsError(_("Error in %s") % iniFile)
except KeyError:
pass
return retVal
13 years ago
def getRemoteInfo(self, envFile):
"""
Get information variables from envFile
Return dict:
section : { variable1 : value,
variable2 : value }
section2 : { variable : value }
"""
optionsInfo = {}
config = ConfigParser(strict=False)
config.read(envFile, encoding="utf-8")
allsect = config.sections()
for section in allsect:
options = {
# k.encode('utf-8'): convertStrListDict(v.encode('utf-8'))
k: convertStrListDict(v)
9 years ago
for k, v in config.items(section, raw=True)}
if options:
optionsInfo[section] = options
return optionsInfo
9 years ago
def flIniFile(self, raiseOnError=False, onlySection=None):
13 years ago
"""
Read variable values from ini files.
Return False if ini file is invalid.
"""
12 years ago
if not self.iniCache:
# get initialized section names
try:
make_profile = self.Get('main.cl_make_profile')
except VariableError as e:
action = self.Get('cl_action')
if not action or action in ['update_profile']:
return True
raise CriticalError(str(e))
if os.path.exists(make_profile):
profiledir = path.dirname(make_profile)
12 years ago
profiles = [('profile',
9 years ago
path.join(profiledir, os.readlink(make_profile)))]
12 years ago
else:
profiles = []
3 years ago
for iniName, iniFile in profiles + list(self.Get('main.cl_env_data')):
12 years ago
if path.exists(iniFile) or iniName == 'profile':
config = ConfigParser(strict=False)
12 years ago
if iniName == 'profile':
repos = RepositorySubstituting(self)
try:
config.read(addStdConfig(
9 years ago
searchProfile(iniFile, 'calculate.env',
repository_sub=repos)),
encoding="utf-8")
except ParsingError:
raise DataVarsError(
_("Error in profile calculate.env"))
12 years ago
else:
try:
config.read(iniFile, encoding="utf-8")
except ParsingError:
raise DataVarsError(
9 years ago
_("Error in %s") % iniFile)
iniSections = config.sections()
12 years ago
if not iniSections:
12 years ago
continue
12 years ago
if onlySection:
9 years ago
iniSections = tuple(set(iniSections) &
{str(onlySection)})
12 years ago
for section in iniSections:
9 years ago
for key, value in config.items(section, raw=True):
key = _u8(key)
fullkey = "%s.%s" % (section, key)
self.iniCache[fullkey] = value
12 years ago
if iniName != "profile":
self.filledVars[fullkey] = iniName
12 years ago
return True
13 years ago
9 years ago
def Get(self, varname, humanreadable=HumanReadable.No):
"""Threading safety Get"""
3 years ago
DataVars.l.acquire()
3 years ago
try:
9 years ago
var = self.__Get(varname, humanreadable)
finally:
DataVars.l.release()
3 years ago
return var
9 years ago
def isFromIni(self, varname):
12 years ago
"""
Check what value get from ini file
"""
9 years ago
section, varname = self.splitVarname(varname)
varname = "%s.%s" % (section, varname)
9 years ago
return self.filledVars[varname] if varname in self.filledVars else ""
12 years ago
9 years ago
def splitVarname(self, varname):
12 years ago
res = self.reRightVar.search(varname)
3 years ago
12 years ago
if res:
if res.group(1):
return res.groups()
else:
9 years ago
return self.defaultModule, res.group(2)
12 years ago
else:
9 years ago
raise DataVarsError(_("Wrong variable name %s") % varname)
12 years ago
9 years ago
def __Get(self, varname, humanreadable=HumanReadable.No):
13 years ago
"""
Get value of variable 'varname'
"""
try:
9 years ago
# tm = time.time()
# load variable if it isn't loaded
# if varname in ["install.os_lvm_data"]:
# print("DEBUG in __GET")
9 years ago
section, varname = self.splitVarname(varname)
3 years ago
9 years ago
if (varname not in self.loadVariables or
section not in self.importedModules):
try:
9 years ago
self.loadVariable(varname, section=section)
except ImportModuleDataVarsError:
if varname.startswith("ac_"):
return ""
raise
varObj = self.loadVariables[varname]
3 years ago
12 years ago
# check section
9 years ago
if varObj.section not in (section, "main"):
self.raiseVariableNotFound(varname, parent=self,
section=section)
# if varname in ["os_lvm_data"]:
# print("DEBUG2 in __GET")
# if for this variable already use Get method
if varObj.invalid and varObj in self.requestVariables:
varnames = "-".join((x.name for x in self.requestVariables + [varObj]))
raise DataVarsError(
9 years ago
_("Loop dependence of variables '%s'") % varnames)
# add this variable for list of requested variables
9 years ago
if humanreadable in (HumanReadable.No, HumanReadable.Auto):
self.requestVariables.append(varObj)
9 years ago
if humanreadable is HumanReadable.Auto:
res = varObj.getHumanReadableAuto()
9 years ago
elif humanreadable is HumanReadable.Yes:
res = varObj._human()
13 years ago
else:
res = varObj._get()
if not humanreadable:
if self.requestVariables:
self.requestVariables.pop()
return res
9 years ago
except BaseException:
while len(self.requestVariables):
self.requestVariables.pop()
raise
13 years ago
9 years ago
def Check(self, varname, value):
"""
Check varialbe value
"""
# load variable if it isn't loaded
if not varname in self.loadVariables:
self.loadVariable(varname)
varObj = self.loadVariables[varname]
varObj.checkType(value)
varObj._check(value)
13 years ago
def Choice(self, varname):
"""
Get choice value of variable 'varname'
"""
# load variable if it isn't loaded
9 years ago
if varname not in self.loadVariables:
13 years ago
self.loadVariable(varname)
varObj = self.loadVariables[varname]
return varObj._choice()[0]
13 years ago
def Uncompatible(self, varname):
"""
Check on compatible change value of this variable
Empty string if variable changable or string with error
"""
# load variable if it isn't loaded
9 years ago
if varname not in self.loadVariables:
self.loadVariable(varname)
varObj = self.loadVariables[varname]
return varObj._uncompatible()
9 years ago
def getRequired(self, varname):
"""
Generate list variables using in uncompatible check
"""
added = []
9 years ago
def genReqs(varObj):
if not varObj in added:
yield varObj
for var in varObj.reqVars:
for dep in genReqs(var):
yield dep
9 years ago
if hasattr(varObj, "source") and varObj.source:
3 years ago
for varsource in map(self.getInfo, varObj.source):
for dep in genReqs(varsource):
yield dep
9 years ago
for dep in genReqs(self.getInfo(varname)):
added.append(dep)
return added
9 years ago
def ChoiceAndComments(self, varname):
if varname not in self.loadVariables:
self.loadVariable(varname)
varObj = self.loadVariables[varname]
return varObj._choice()
13 years ago
def getInfo(self, varname):
"""
Get info (label and other for variable)
"""
9 years ago
section, varname = self.splitVarname(varname)
if varname not in self.loadVariables:
self.loadVariable(varname, section=section or None)
13 years ago
return self.loadVariables[varname]
13 years ago
9 years ago
def Set(self, varname, varvalue, force=False):
14 years ago
"""
13 years ago
Set value 'varvalue' for variable 'varname'
"""
varObj = self.getInfo(varname)
if force or varObj.mode != READONLY:
9 years ago
varObj._set(varvalue, force)
if varObj.alias:
9 years ago
self.Set(varObj.alias, varObj.value, force)
13 years ago
else:
raise DataVarsError(
8 years ago
_("Attempting to rewrite readonly variable %s") %
12 years ago
varname)
9 years ago
def Invalidate(self, varname, force=False, onlySet=False):
13 years ago
"""
Invalidate value of variable. Force - invalidate also for set values
"""
9 years ago
if varname not in self.loadVariables:
13 years ago
self.loadVariable(varname)
varObj = self.loadVariables[varname]
if not onlySet or varObj.wasSet:
varObj.invalidate(force or onlySet)
13 years ago
9 years ago
def getEnvFileByLocation(self, location):
"""
13 years ago
Get env file path by location alias. This path append to value
of variable 'cl_chroot_path'.
Return False if alias not found.
"""
calculateIniFile = self.Select('cl_env_path',
where='cl_env_location',
9 years ago
eq=location, limit=1)
13 years ago
if calculateIniFile:
9 years ago
return pathJoin(self.Get('main.cl_chroot_path'), calculateIniFile)
else:
13 years ago
return False
def Write(self, varname, val=None, force=False, location='system',
13 years ago
header=False):
"""
13 years ago
Write variable 'varname' to ini file. If set 'val', then to
variable before write perform value changing. 'force' use for
change value of read-only variables. 'location' must be ('system',
13 years ago
'local', 'remote') use for specify type of ini file location ini.
'header' use for specify section in ini file. If header not
specified then use default for this value section.
"""
# set value to variable if specified value
9 years ago
if val is not None:
self.Set(varname, val, force=force)
else:
if header:
9 years ago
vname = "%s.%s" % (header, varname)
else:
vname = "varname"
val = self.Get(vname)
13 years ago
# get path to target ini file
iniFile = self.getEnvFileByLocation(location)
9 years ago
if iniFile is not False:
13 years ago
# make parent directories
makePath(path.dirname(iniFile))
# get variable section if not specified header
if not header:
header = self.loadVariables[varname].section
# write value to ini file
3 years ago
from . import cl_ini_parser
9 years ago
config = cl_ini_parser.iniParser(iniFile)
val = self.serialize(self.getInfo(varname).type,
val)
writeVal = convertStrListDict(val)
9 years ago
if writeVal != config.getVar(header, varname):
if not config.setVar(header, {varname: writeVal}):
raise DataVarsError(
_("Unable to write variable {varname} into "
"'{location}'").format(varname=varname,
9 years ago
location=location))
13 years ago
return True
else:
raise DataVarsError(_("Unable to find alias '%s' for the "
9 years ago
"template variables path") % location)
13 years ago
def Delete(self, varname, location='system', header=False):
13 years ago
"""
Delete variable 'varname' from ini file and refresh value.
'location' must be ('system', 'local', 'remote') use for specify
13 years ago
type of ini file location ini. 'header' use for specify section in
ini file. If header not specified then use default for this value
section.
"""
# get path to target ini file
iniFile = self.getEnvFileByLocation(location)
9 years ago
if iniFile is not False:
13 years ago
# make parent directories
makePath(path.dirname(iniFile))
# get variable section if not specified header
if not header:
9 years ago
if varname not in self.loadVariables:
self.loadVariable(varname)
13 years ago
header = self.loadVariables[varname].section
# write value to ini file
3 years ago
from . import cl_ini_parser
9 years ago
config = cl_ini_parser.iniParser(iniFile)
13 years ago
allVars = config.getAreaVars(header)
if allVars is False:
return False
13 years ago
if varname in allVars.keys():
9 years ago
retDelVar = config.delVar(header, varname)
13 years ago
# if success delete value and this section empty
# of ini file then remove it
return retDelVar and (config.getAreaVars(header) or
config.delArea(header))
return True
13 years ago
else:
raise DataVarsError(_("Unable to find alias '%s' for the "
9 years ago
"template variables path") % location)
def processRefresh(self):
for refreshVar in self.refresh:
if not refreshVar.invalid:
refreshVar.refresh()
def close(self):
for varObj in self.loadVariables.values():
9 years ago
if hasattr(varObj, "close"):
varObj.close()
9 years ago
elif hasattr(varObj, "value") and hasattr(varObj.value, "close"):
varObj.value.close()
9 years ago
def addGroup(self, groupName, normal=(), expert=(), brief=(),
next_label=None,
brief_force=(), hide=(), expert_label=None, image='',
custom_buttons=()):
"""
Добавить группу переменных для метода
groupName - название группы
normal - регулярные настройки
expert - расширенные настройки
hide - кортеж имен переменных, которые необходимо скрыть в brief
image - изображение
brief - кортеж имен переменных, значение которых необходимо отобразите
в выводе-подтверждении
brief_force - кортеж имен переменных, значение которых необходимо
отобразите в выводе-подтверждении, даже если параметр является
несовместимым
expert_label - текст вместо стандартной надписи для отображения
расширенных параметров
next_label - название кнопки для запуска действия или перехода к
следующей группе
custom_buttons - список кортежей (название кнопки, текст на кнопке,
значение (метод), элемент ("button")
"""
default_next_label = _("Next")
default_expert_label = _("Click for advanced settings")
self.groups.append(
9 years ago
{'name': groupName,
'normal': normal,
'expert': expert,
'hide': hide,
'image': image,
'brief': brief,
'custom_buttons': custom_buttons,
'brief_force': brief_force,
'expert_label': expert_label or default_expert_label,
'next_label': next_label or default_next_label})
lastIndex = len(self.groups) - 1
for var in chain(normal, expert):
varname = var.rpartition('.')[2]
self.mapVarGroup[varname] = lastIndex
objVar = self.getInfo(var)
if objVar.opt is not None:
for opname in objVar.opt:
self.map_opt_vars[opname] = varname
return self
def is_console_set(self, varname):
for op in self.Get('main.cl_console_args'):
if self.map_opt_vars.get(op, '') == varname:
return True
return False
def getGroups(self):
"""
Get groups variables
"""
return self.groups
def clearGroups(self):
"""
Clear group (using for drop translate)
"""
self.groups = []
self.mapVarGroup = OrderedDict()
9 years ago
def addBrief(self, next_label=None, text=None, image=""):
self.briefData["next"] = next_label
self.briefData["help"] = text
self.briefData["image"] = image
def getBrief(self):
return self.briefData
9 years ago
def _dependSort(self, inlist):
"""
Sort variable use "check_after" attribute
"""
moved = []
inlist = list(inlist)
9 years ago
while inlist:
for i, el in enumerate(islice(inlist, 1, None)):
if el.name in inlist[0].check_after:
9 years ago
inlist.insert(0, inlist.pop(i + 1))
if inlist[0].name in moved:
9 years ago
raise VariableError("Loop depends for %s on check" %
(",".join(moved)))
moved.append(inlist[0].name)
break
else:
yield inlist.pop(0)
if inlist:
moved = [inlist[0].name]
9 years ago
def _nocheckSort(self, inlist):
"""
Place check variable without check (standard check method) at first
"""
afterlist = []
9 years ago
for var in inlist:
if (not var.source and not var.check_after and
var.has_base_method("check") and
var.has_base_method("uncompatible")):
yield var
else:
9 years ago
afterlist.append(var)
for var in afterlist:
yield var
9 years ago
def fixWsdlTableValue(self, varObj, val):
"""
Fix data get by wsdl (list-list) type
"""
if varObj.type == "table":
# multiLists = list(filter(lambda x: "list-list" in x[1],
# enumerate(
# [self.getInfo(x).type for x in
# varObj.source])))
multiLists = [x for x in enumerate([self.getInfo(x).type for x in varObj.source]) if "list-list" in x[1]]
if multiLists:
3 years ago
val = list(zip_longest(*val, fillvalue=""))
9 years ago
for col, typecol in multiLists:
if col < len(val):
val[col] = [x.split(',')
if isinstance(x, str) else x for x
in val[col]]
3 years ago
val = list(zip_longest(*val, fillvalue=""))
return val
9 years ago
def plainList(self, *elements):
"""
Make plain list from many dimensions
"""
for w in elements:
9 years ago
if type(w.message) in (list, tuple):
for i in self.plainList(*w.message):
yield i
else:
yield w
9 years ago
def printGroup(self, info):
"""
Вывести группу переменных
"""
3 years ago
print("=DEBUG.SET=")
for vname in sorted((x for x
in info._type_info.keys() if x.lower() == x)):
3 years ago
print("|", vname, "=", getattr(info, vname))
print("=DEBUG.DATAVARS=")
for vname in self.mapVarGroup.keys():
3 years ago
print("|", vname, "=", self.Get(vname))
print("=DEBUG.END=")
8 years ago
def checkGroups(self, info, allvars=False, invalidators=None):
"""
Check variables in group or all in info
"""
9 years ago
def compare_choice(part_s, *options):
part_s = part_s.lower()
options = [x.lower() for x in options]
return any(x == part_s for x in options)
9 years ago
def get_val_from_choice(choicedata, val):
"""
Получить похожее значение
"""
if val not in [x[0] for x in choicedata]:
# result = list(filter(lambda x: compare_choice(val, x[0], x[1]),
# choicedata))
result = [x for x in choicedata if compare_choice(val, x[0], x[1])]
9 years ago
if len(result) > 1:
raise VariableError(
_("Ambiguous choice:%s") % formatListOr((('"%s"(%s)' % (x[1], x[0])
if x[0] != x[1] else x[0]) for x in result)))
9 years ago
elif result:
return result[0][0]
return val
if not self.groups:
return []
errors = []
if self.groups:
keys = list(self.mapVarGroup.keys())
else:
keys = sorted((x for x in info._type_info.keys() if x.lower() == x))
varsByKeys = [self.getInfo(x) for x in keys]
groupVars = []
# invalidate default variables
9 years ago
if hasattr(info, "Default") and info.Default:
default = info.Default
for varname in default:
9 years ago
self.Invalidate(varname, onlySet=True)
else:
default = []
8 years ago
# проверить переменные, при смене значения которых нужно сбросить
# указанные зависимые, даже если пользователь уже изменял их значения
# это может быть использово при groupmod
if invalidators:
for k, vars in invalidators.items():
if hasattr(info, k):
val = getattr(info,k)
if val is not None and val != self.Get(k):
for var in vars:
self.Invalidate(var, force=True)
# look over all vars
9 years ago
for var, varObj in map(lambda x: (x.name, x),
self._nocheckSort(self._dependSort(varsByKeys))):
# if info skipped and send None
if info is None:
val = None
else:
# if variable not exists in info data - skip it
9 years ago
if not hasattr(info, var):
continue
# get value of variable from info
9 years ago
val = getattr(info, var)
# if type(val) == unicode:
# val = _u8(val)
9 years ago
varSendFromClient = val is not None and var not in default
varGroupUntrusted = varObj.untrusted and var in groupVars
9 years ago
varAllUntrusted = varObj.untrusted and allvars
# if group variable is not defined and
# variable send from client
# datavars has groups of variables
if not groupVars and varSendFromClient and self.groups:
# get normal and expert variables from group
groupIndex = self.mapVarGroup[var]
groupVars = list(self.groups[groupIndex]["normal"]) + \
list(self.groups[groupIndex]["expert"])
if varSendFromClient or varGroupUntrusted or varAllUntrusted \
9 years ago
or not info:
try:
uncomperr = self.Uncompatible(var)
# get value for final or group check
if val is None:
if not uncomperr:
9 years ago
self.Check(var, self.Get(var))
else:
9 years ago
val = self.fixWsdlTableValue(varObj, val)
if varObj.type in ("choice", "choice-list"):
choicedata = self.ChoiceAndComments(var)
if any(choicedata):
if choicedata[1] is None:
choicedata = [choicedata[0],
choicedata[0]]
choicedata = list(zip(*choicedata))
if varObj.type == "choice":
vals = [val]
else:
vals = val
res = []
for val in vals:
9 years ago
val = get_val_from_choice(choicedata, val)
res.append(val)
if varObj.type == "choice":
val = res[0]
else:
val = res
9 years ago
self.Set(var, val)
# raise error for atempt set uncompatible variable
if uncomperr:
raise VariableError(uncomperr)
9 years ago
except (VariableError, DataVarsError) as e:
# assemble all variable errors
messages = e if type(e) == list \
9 years ago
else [e]
mess = "\n".join((str(x) for x in messages))
9 years ago
mapError = {PasswordError: 'pwderror',
CommonVariableError: 'commonerror'}
for k, v in mapError.items():
if (isinstance(e, k) or type(e) == list and
9 years ago
all(isinstance(x, k) for x in
e)):
typeError = v
break
else:
typeError = 'error'
9 years ago
errors.append({'type': typeError, 'field': var,
'field_obj': self.getInfo(
var) if var else "",
'message': mess})
except BaseException as e:
3 years ago
for i in traceback.format_exception(*sys.exc_info()):
print(i, end=' ')
9 years ago
errors.append({'type': 'error', 'field': var,
'message': str(e)})
return errors
def printDependence(self):
9 years ago
for key, val in self.loadVariables.items():
if val.reqVars:
3 years ago
print(key, "->", [x.name for x in val.reqVars])
9 years ago
def printVars(self, filt=lambda x: x):
for i in sorted(filter(filt, self.allVars.keys())):
3 years ago
print("{0:<40} {1}".format(i, self.Get(i, True)))
def reinit(self):
"""
Using for update variable translatable elements (example: label)
"""
9 years ago
for key, var in self.loadVariables.items():
var.init()
9 years ago
def printWrong(self, filt=lambda x: x):
3 years ago
print("!!!WRONG VARS!!!")
for i in sorted((x for x in self.allVars.keys() if filt(x))):
if self.getInfo(i).untrusted:
3 years ago
print("{0:<40} {1}".format(i, self.Get(i, True)))