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.

219 lines
7.6 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.

from calculate.utils.calculateini import CalculateIniParser
import re
import sys
import os
import importlib
import importlib.util
import site
from calculate.vars.datavars import Variable, Namespace, HashVariable,\
TableVariable, IniCreated, DefaultValue
from calculate.utils.gentoo import ProfileWalker
from calculate.utils.fs import readFile
from calculate.utils.files import listDirectory
class NamespaceIniFiller(CalculateIniParser):
'''Класс, предназначенный для наполнения Namespace объекта переменными
из calculate.ini файла.'''
def error(self, lineno, s):
self.errors.append(lineno, s)
def fill(self, ns, data):
self.ns = ns
self.curns = self.ns
self.errors = []
self.parse(data)
def start_section(self, sections):
self.curns = self.ns
for section in sections:
if section not in self.curns.childs:
self.curns.addNamespace(Namespace(section))
self.curns = self.curns[section]
def clear_section(self, sections):
curns = self.ns
for section in sections:
if section not in curns.childs:
return
curns = curns[section]
curns.clearChilds()
def change_value(self, key, value):
self.curns[key].setValue(value)
def define_variable(self, key, value):
self.curns.addStringVariable(key, value)
def append_value(self, key, value):
l = self.curns[key].getValue().split(",")
vlist = value.split(",")
for v in vlist:
if v not in l:
l.append(v)
self.change_value(key, ",".join(l))
def remove_value(self, key, value):
l = self.curns[key].getValue().split(",")
vlist = value.split(",")
for v in vlist:
if v in l:
l.remove(v)
self.change_value(key, ",".join(l))
def define_key(self, section, key, value, optype):
Define = CalculateIniParser.Define
if optype == Define.assign:
if key not in self.curns:
self.define_variable(key, value)
else:
self.change_value(key, value)
elif optype == Define.append:
if key not in self.curns:
self.define_variable(key, value)
else:
self.append_value(key, value)
elif optype == Define.remove:
if key not in self.curns:
self.define_variable(key, value)
else:
self.remove_value(key, value)
def parse_error(self, line, lineno, col):
self.error(lineno, _("Syntax error: %s") % line)
class NamespaceIniFillerStrict(NamespaceIniFiller):
"""
Объект используемый для наполения Namespace объекта переменными
из calculate.ini файла, с возможность определять только
"""
availableSection = ["custom"]
def fill(self, ns, data):
self.canCreate = False
for newns in self.availableSection:
if newns not in ns:
ns.addNamespace(Namespace(newns))
super().fill(ns, data)
def start_section(self, sections):
self.curns = self.ns
self.canCreate = sections[0] in self.availableSection
for section in sections:
if section not in self.curns.childs:
if isinstance(self.curns, TableVariable) or self.canCreate:
self.curns.addNamespace(Namespace(section))
else:
self.curns = None
self.curns = self.curns[section]
#def clear_section(self, sections):
# curns = self.ns
# self.canCreate = sections[0] in self.availableSection
# for section in sections:
# if section not in curns.childs:
# return
# curns = curns[section]
# curns.clearChilds()
def define_variable(self, key, value):
if not self.canCreate:
pass
var = Variable(key)
var.addProperty(IniCreated(value))
self.curns.addVariable(var)
def change_value(self, key, value):
var = self.curns[key]
var.setValue(value)
if isinstance(var, HashVariable.HashValue):
var = var.master_variable
value = var.getValue()
prop = var.findProperty(DefaultValue)
if prop:
prop.value = value
else:
var.addProperty(DefaultValue(value))
var.invalidate()
class VariableLoader:
"""
Объект используемый для загрузки переменных из python модуля
"""
reUpper = re.compile("(.)([A-Z])")
def _get_varlike_attrs(self, obj):
"""
Получить список аттрибутов похожих на переменные
"""
for attrname in (x for x in dir(obj) if x[:1].isupper()):
yield self.reUpper.sub(r"\1_\2", attrname).lower(), \
getattr(obj, attrname)
def fill(self, ns, dirpath, package):
"""
Загрузить в namespace переменные из указанных модулей
"""
for fullfn in listDirectory(dirpath, fullpath=True):
dn, fn = os.path.split(fullfn)
if os.path.isdir(fullfn):
newns = ns.addNamespace(Namespace(fn))
self.fill(newns, fullfn, "%s.%s"%(package,fn))
elif fn.endswith(".py"):
module = self._load_module_source(package, fn, fullfn)
for varname, cls in self._get_varlike_attrs(module):
if Variable.isImplementation(cls):
ns.addVariable(cls(varname))
elif HashVariable.isImplementation(cls) or \
TableVariable.isImplementation(cls) or \
Namespace.isImplementation(cls):
_newns = ns.addNamespace(cls(varname,ns))
for _varname, _cls in self._get_varlike_attrs(cls):
if Variable.isImplementation(_cls):
_newns.addVariable(_cls(_varname))
@classmethod
def default(cls):
site_dirs = [os.path.normpath(x) for x in site.getsitepackages()]
for site_dir in site_dirs:
calculate_dir = os.path.join(site_dir, "calculate/vars")
if os.path.exists(calculate_dir):
return (calculate_dir, "calculate.vars")
def _load_module_source(self, package, name, path):
if name.startswith('calculate.vars.'):
full_name = name
else:
full_name = '.'.join([package, name])
if full_name in sys.modules:
return sys.modules[full_name]
spec = importlib.util.spec_from_file_location(full_name, path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
sys.modules[full_name] = module
return module
class ProfileFiller:
"""
Заполнитель значений переменных из файлов calculate.ini в профилях
"""
basename = "calculate.ini"
def get_repository_map(self, ns):
return {
x.name.getValue(): x.path.getValue()
for x in ns.os.gentoo.repositories
}
def fill(self, ns, profile_path):
nif = NamespaceIniFillerStrict()
pw = ProfileWalker(self.basename, self.get_repository_map(ns))
for fn in pw.find(profile_path):
nif.fill(ns, readFile(fn))