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-2.1-lib/pym/cl_utils2.py

564 rivejä
25 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 2008-2010 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 struct
import termios
import fcntl
import cl_utils
import cl_profile
import ldap
class ldapFun(cl_profile._error):
'''Объект для работы с LDAP сервером
подключение к серверу и поиск данных
'''
def __init__(self, dnUser, password, host="localhost"):
self.conLdap = False
# Получаем соединение с LDAP
try:
self.conLdap = self.__ldapConnect(dnUser, password, host)
except ldap.LDAPError, e:
self.setError(e[0]['desc'])
def __ldapConnect(self, dnUser, password, host):
"""Соединение с LDAP сервером"""
conLdap = ldap.initialize('ldap://%s'%host)
conLdap.simple_bind_s(dnUser, password)
return conLdap
def ldapSearch(self,baseDN, searchScope, searchFilter, retrieveAttributes):
try:
ldap_result_id = self.conLdap.search(baseDN, searchScope,
searchFilter,
retrieveAttributes)
result_set = []
while 1:
result_type, result_data = self.conLdap.result(ldap_result_id,
0)
if (result_data == []):
break
else:
if result_type == ldap.RES_SEARCH_ENTRY:
result_set.append(result_data)
except ldap.NO_SUCH_OBJECT:
return []
except:
return False
return result_set
pcs = cl_utils.prettyColumnStr
class cl_help:
"""Объект для работы со справкой, и обработкой параметров.
Конструктор __init__ должен определить следующие переменные:
self.chapter список разделов справки, каждый элементы состоит из
имени раздела, флаг видимый/скрытый, кол-во переводов строк
после названия раздела, количество строк после раздела,
тип раздела
Пример: [("Copyright",False,0,2),"options"]
self.relService словарь связей сервисов и действующих опций
ключ - название сервиса, значение - список отображаемых
разделов отмеченных как "options"
Пример: {"samba":[_("Common options"),
_("Service Samba options")]}
self.relOptions словарь связей длинных опций помощи и выводимых разделов
помощи с опциями
ключ - параметр справки, значение список отображаемых
разделов справки
Пример: {"help-ldap":[_("Common options"),
_("Service LDAP options)]}
self.progName словарь имена используемых программ и их номера для
доступа к переменным
Пример: {'cl-groupadd':0, 'cl-groupdel':1}
self.data список данных для справки, каждый элемент словарь:
progAccess: список номеров программ отображающих
Пример: {'progAccess':(0,),
'shortOption':"g",
'longOption':"gid",
'optVal':"GID",
'helpChapter':_("Options"),
'help':_("use GID for the new group")
},
после заполнения параметров необходимо выполнить
self._cl_help__setParamHelp() для заполнения справки
"""
def __init__(self, cmdName):
# ширина консоли взята за 80
# -1 чтобы компенсировать расстрояние между колонками
self.consolewidth = 79
self.column_width = 32
self.cmdName = cmdName
#короткие опции командной строки
self.shortOpt = []
#длинные опции командной строки
self.longOpt = []
# массив разделов (заполняется в __setParamHelp)
self.chapterBloc = []
#optEnd = ""
#if "user" in self.cmdName and not "mod" in self.cmdName:
#optEnd = _("user")
#elif "group" in self.cmdName and not "mod" in self.cmdName:
#optEnd = _("group")
#self.__setParamHelp()
def getChapterNumber(self,NameChapter):
"""Получить номер раздела по имени"""
num = 0
for i in self.chapter:
if i[0] == NameChapter:
return num
num += 1
return False
def __setParamHelp(self):
"""Внутренняя функция формирования справки по данным
Перебирает все элементы списка data, проверяет их на доступность
данной программы, разбирает опции на среди data и формирует
для по ним справку.
"""
# сформировать нужное количество блоков раздела
self.chapterBloc = [""]*len(self.chapter)
#
sp = {}
i = 0
# перебираем все элементы справки собираем элементы опции
# так же формируем разделы не опции
for par in self.data:
# перебираем только те опции, которые принадлежат команде
if self.access(par):
# есть короткая (возможно есть и длинная)
if par.has_key("shortOption"):
sp[par["shortOption"]+":"+par["helpChapter"]] = i
# есть только длинная опция
elif par.has_key("longOption"):
sp[par["longOption"]+":"+par["helpChapter"]] = i
# формирование разделов не опций
else:
helpTxt = par['help']
numChapter = self.getChapterNumber(par['helpChapter'])
self.addChapterHelp(numChapter,helpTxt)
i += 1
# перебираем все "собранные" опции
# опции перебираются по порядку в списке date
# для сортировки по ключам следует применить код:
# for index in sorted(sp.keys()):
# par = self.data[sp[index]]
for index in sorted(sp.values()):
par = self.data[index]
numChapter = self.getChapterNumber(par['helpChapter'])
# если есть и короткая и длинная
if "shortOption" in par and "longOption" in par:
paraminfo = "-%s, --%s "%(par["shortOption"],par["longOption"])
# если есть только короткая
elif "shortOption" in par:
paraminfo = "-%s "%par["shortOption"]
# если только длинная
else:
paraminfo = "--%s "%par["longOption"]
# если указан параметр для опции
if "optVal" in par:
optVal = par["optVal"]
else:
optVal = ""
# вывод вида: " [-o, ][--option] [PARAM]" "helpstring"
helpTxt = pcs(" "+paraminfo+optVal, self.column_width, \
par['help'], self.consolewidth-self.column_width)
# добавить строку в нужный раздел
self.addChapterHelp(numChapter,helpTxt)
def getHelp(self, optionsChapters=False):
"""Выдать справку.
Выдает справку в случае если указан optionsChapters, то фильтрует по
типу разделов.
Параметры:
optionsChapters Flase или список опциональных разделов для
отображения
Возвращаемые параметры:
Строка со справкой.
"""
# Выдать справку
help = ""
# перебираем все элементы справочных блоков
iterChapterBloc = iter(self.chapterBloc)
# перебираем все разделы по параметрам
for (nameChapter, visibleChapter, beforeStrChapter, \
afterStrChapter, typeChapter) in self.chapter:
# получаем следующий блок (т.о. textChapterBloc соответ, chapter)
textChapterBloc = iterChapterBloc.next()
# если тип раздела опциональный
if optionsChapters and typeChapter=="options":
# проверяем нужно ли его отображать
if not (nameChapter in optionsChapters):
continue
bef = "\n"*beforeStrChapter
aft = "\n"*afterStrChapter
# если блок не пустой и раздел отображаемый
if len(textChapterBloc) > 0:
if visibleChapter:
help += nameChapter + ": " + bef
help += textChapterBloc + aft
help = help.rstrip()+"\n"
return help
def addChapterHelp(self, numChapter, helpTxt):
"""Добавить в раздел помощи numChapteк тектстовую строку helpTxt
Параметры:
numChapter номер раздела в который нужно добавить данные справки
helpTxt строка, содержащая данные
"""
self.chapterBloc[numChapter] += helpTxt
return True
def addData(self,dataHash):
# На будущее (добавляет опции)
self.data.append(dataHash)
return True
def handleCheckAccess(self,dataHash):
"""Замещаемый дополнительный обработчик проверки
доступности опции.
Входные параметры:
dataHash элементы списка данных справки (self.data)
"""
return True
def access(self,dataHash):
"""Доступна ли опция вызывающей программе
Параметры:
dataHash словарь элемент типа self.data
Возвращаемые параметры:
True/False доступна/недоступна
"""
# доступна ли опция вызывающей программе
# опция без progAccess доступна
numProg = self.progName[self.cmdName]
if 'progAccess' in dataHash:
if numProg in dataHash['progAccess']:
# вызов дополнительной проверки доступа к опции
return self.handleCheckAccess(dataHash)
else:
return False
else:
# вызов дополнительной проверки доступа к опции
return self.handleCheckAccess(dataHash)
def getTypeChapter(self, nameChapter):
"""Получить тип раздела по его имени
Параметры:
nameChapter название раздела
Возвращаемые параметры:
строка тип раздела
Flase(Boolean) такой раздел отсутствует
"""
# фильтруем список по имени раздела, помещаем в список тип раздела
filtered = [typeChapter for name, na, na, na, typeChapter \
in self.chapter if name == nameChapter]
# если среди фильтрованных есть хоть один элемент
if len(filtered) > 0:
# возвращаем - он запрашиваемый
return filtered[0]
else:
# такой раздел отсутствует
return False
def clearAllOpt(self):
"""Очистить все опции, полученные посредством getAllOpt"""
if len(self.shortOpt) > 0:
self.shortOpt = []
if len(self.longOpt) > 0:
self.longOpt = []
return True
def getAllOpt(self,typeOpt="all", optionsChapters=False):
"""Получить все доступные опции
Параметры:
typeOpt 'short'/'long'/'all', вернуть короткие или длинные
опции или все (возвращаются кортежем)
optionsChapters фильтр для опций по типам разделов (список,кортеж)
Возвращаемые параметры:
строка коротки или список строк длинных опций ('hb:c:wg:G:k:ms:u:')
"""
# Выдать все действующие опции
if typeOpt=="short" or typeOpt=="all":
if len(self.shortOpt) == 0:
for par in self.data:
if optionsChapters and\
self.getTypeChapter(par['helpChapter'])=="options":
if not (par['helpChapter'] in optionsChapters):
continue
if par.has_key("shortOption") and self.access(par):
if par.has_key("optVal"):
self.shortOpt.append(par["shortOption"]+':')
else:
self.shortOpt.append(par["shortOption"])
if typeOpt=="long" or typeOpt=="all":
if len(self.longOpt) == 0:
for par in self.data:
if optionsChapters and\
self.getTypeChapter(par['helpChapter'])=="options":
#print par["longOption"]
if not (par['helpChapter'] in optionsChapters):
continue
if par.has_key("longOption") and self.access(par):
if par.has_key("optVal"):
self.longOpt.append(par["longOption"]+'=')
else:
self.longOpt.append(par["longOption"])
if typeOpt=="short":
return "".join(self.shortOpt)
elif typeOpt=="long":
return self.longOpt
elif typeOpt=="all":
return ("".join(self.shortOpt),self.longOpt)
def getShortOpt(self,option):
"""Из любой опции получить короткую опцию.
Фильтрация также происходит и по названию команды.
Параметры:
option запрашиваемая опция
Возвращаемые параметры:
короткая опция, если же для длинной опции нет короткой, возвращается
пустая строка.
"""
# Из любой опции получаем короткую опцию
for par in self.data:
if par.has_key("shortOption") and self.access(par):
if (par.has_key("longOption") and\
par["longOption"] == option) or \
par["shortOption"] == option:
return par["shortOption"]
break
return ""
class cl_smartcon(object):
def getconsolewidth(self):
"""Получить ширину текущей консоли"""
s = struct.pack("HHHH", 0, 0, 0, 0)
fd_stdout = sys.stdout.fileno()
try:
x = fcntl.ioctl(fd_stdout, termios.TIOCGWINSZ, s)
except IOError:
# если ошибка то ширина 80 символов
return 80
#(rows, cols, x pixels, y pixels)
return struct.unpack("HHHH", x)[1]
def printRight(self, offsetLeft, offsetRight):
"""Добавляет необходимое количество пробелов:
количество пробелов = (ширина консоли - offsetLeft - offsetRight)
"""
cols = self.getconsolewidth()
for i in range(cols - offsetLeft - offsetRight):
sys.stdout.write(" ")
def colorPrint(self,attr,fg,bg,string):
"""Раскрашивает выводимое сообщение
Параметры:
attr - это атрибут
fg - цвет символа
bg - цвет фона
в случае если параметр равен "" то он не изменяется
attr может принимать следующие значения:
0 сбросить все атрибуты (вернуться в нормальный режим)
1 яркий (обычно включает толстый шрифт)
2 тусклый
3 подчёркнутый
5 мигающий
7 реверсный
8 невидимый
fg может принимать следующие значения:
30 чёрный
31 красный
32 зелёный
33 жёлтый
34 синий
35 фиолетовый
36 голубой
37 белый
bg может принимать следующие значения:
40 чёрный
41 красный
42 зелёный
43 жёлтый
44 синий
45 фиолетовый
46 голубой
47 белый
"""
lst = []
if attr:
lst.append(attr)
if fg:
lst.append(fg)
if bg:
lst.append(bg)
sys.stdout.write("\033[%sm%s\033[0m" %(";".join(lst),string))
def redBrightPrint(self, string):
"""Печатает яркое красное сообщение"""
self.colorPrint("1","31","",string)
def greenBrightPrint(self, string):
"""Печатает яркое зеленое сообщение"""
self.colorPrint("1","32","",string)
def yellowBrightPrint(self, string):
"""Печатает яркое желтое сообщение"""
self.colorPrint("1","33","",string)
def blueBrightPrint(self, string):
"""Печатает яркое cинее сообщение"""
self.colorPrint("1","34","",string)
def lenString(self, string):
"""Получаем длинну строки"""
stringUnicode = cl_utils._toUNICODE(string)
lenString = len(stringUnicode)
return lenString
def defaultPrint(self, string):
sys.stdout.write(string)
sys.stdout.flush()
def printLine(self, argL, argR, offsetL=0, printBR=True):
"""Печатает справа и слева консоли цветные сообщения"""
#Допустимые цвета
colorDict = {\
# цвет по умолчанию
'':self.defaultPrint,
# ярко зеленый
'greenBr':self.greenBrightPrint,
# ярко голубой
'blueBr':self.blueBrightPrint,
# ярко красный
'redBr':self.redBrightPrint,
# ярко желтый
'yellowBr':self.yellowBrightPrint,
}
# cмещение от левого края консоли
#offsetL = 0
for color,leftString in argL:
offsetL += self.lenString(leftString)
if colorDict.has_key(color):
# печатаем и считаем смещение
colorDict[color](leftString)
else:
colorDict[''](leftString)
# cмещение от правого края консоли
offsetR = 0
for color,rightString in argR:
offsetR += self.lenString(rightString)
# Добавляем пробелы
if offsetR:
self.printRight(offsetL, offsetR)
for color,rightString in argR:
if colorDict.has_key(color):
# печатаем и считаем смещение
colorDict[color](rightString)
else:
colorDict[''](rightString)
if printBR:
print ""
def printNotOK(self, string, offsetL=0, printBR=True):
"""Вывод на печать в случае сбоя"""
self.printLine((('greenBr',' * '),
('',string),
),
(('blueBr','['),
('redBr',' !! '),
('blueBr',']'),
), offsetL, printBR)
def printOnlyNotOK(self, string, offsetL=0, printBR=True):
"""Вывод на печать в случае сбоя"""
self.printLine((('', string),),
(('blueBr','['),
('redBr',' !! '),
('blueBr',']'),
), offsetL, printBR)
def printOK(self, string, offsetL=0, printBR=True):
"""Вывод на печать в случае успеха"""
self.printLine((('greenBr',' * '),
('',string),
),
(('blueBr','['),
('greenBr',' ok '),
('blueBr',']'),
), offsetL, printBR)
def printOnlyOK(self, string, offsetL=0, printBR=True):
"""Вывод на печать в случае успеха"""
self.printLine((('',string),),
(('blueBr','['),
('greenBr',' ok '),
('blueBr',']'),
), offsetL, printBR)
def printWARNING(self, string, offsetL=0, printBR=True):
"""Вывод на печать предупреждения"""
self.printLine((('yellowBr',' * '),
('',string),
),
(('',''),
), offsetL, printBR)
def printERROR(self, string, offsetL=0, printBR=True):
"""Вывод на печать предупреждения"""
self.printLine((('redBr',' * '),
('',string),
),
(('',''),
), offsetL, printBR)
def printSUCCESS(self, string, offsetL=0, printBR=True):
"""Вывод на печать в случае успеха без [ok] справа"""
self.printLine((('greenBr',' * '),
('',string),
),
(('',''),
), offsetL, printBR)