def create_dialog(self, sDialogType=wizard_page.URWID_DIALOG_TYPE, items=None): """ Создать диалог. """ if items is None: log.warning( u'Не определены элементы страницы устанавливаемых программ') return None if sDialogType == wizard_page.URWID_DIALOG_TYPE: return urwid_dialog.do_checklist(u'Выбор программ', cui_dialog.DEFAULT_DLG_HEIGHT, cui_dialog.DEFAULT_DLG_WIDTH, cui_dialog.DEFAULT_DLG_HEIGHT, *items) elif sDialogType == wizard_page.PYDLG_DIALOG_TYPE: return pydlg_dialog.do_checklist(u'Выбор программ', cui_dialog.DEFAULT_DLG_HEIGHT, cui_dialog.DEFAULT_DLG_WIDTH, cui_dialog.DEFAULT_DLG_HEIGHT, *items) else: log.warning(u'Не поддерживаемый тип диалога <%s>' % sDialogType) return None
def create(self, **properties): """ Создание объекта. По значениям свойств функция сама определяет какого типа будет объект. @param properties: Словарь свойств объекта. @return: Объект приемника данных или None в случае ошибки. """ name = properties.get('name', u'') # Сначала определяем тип объекта if 'type' in properties: type_name = properties['type'] else: log.error(u'Ошибка создания объекта. Не определен тип <%s>' % name) return None # Сначала проверяем является ли объект источником данных if type_name in src.DATA_SOURCES: return self.create_src(**properties) # Сначала проверяем является ли объект источником данных if type_name in dst.DATA_DESTINATIONS: return self.create_dst(**properties) log.warning( u'Тип <%s> объекта <%s> не зарегистрирован среди источнико или приемников данных' % (type_name, name)) return None
def get_xml_content_by_link(xml_content, link): """ Получить часть содержимого XML файла по пути. @param xml_content: Сродержимое XML файла. @param link: Запрашиваемый путь. Может быть представлен в виде списка или строки. Например: root/Documents/1/Document/Title/value @return: Часть содержимого или None если по этому пути ничего не найдено. """ log.debug(u'Получение содержимого XML файла по пути %s' % link) if type(link) in (str, unicode): link = link.split(XML_CONTENT_LINK_DELIMETER) if type(link) not in (list, tuple): log.error(u'Не корректный тип пути <%s> до содержимого XML файла' % type(link)) return None if not link: return xml_content if link[0] not in xml_content: log.warning(u'Не найден путь %s в содержимом %s XML файла' % (link, xml_content.keys())) return None elif link[0] in xml_content: return get_xml_content_by_link(xml_content[link[0]], link[1:]) return None
def get_xml_filenames(self): """ Определить список обрабатываемых XML файлов. @return: Cписок обрабатываемых XML файлов. """ if self.cache_xml_filenames: # Работаем с мгновенным слепком списка файлов return self.cache_xml_filenames if self.xml_filename is None: msg = u'Не определены XML файлы источника данных <%s>' % self.__class__.__name__ log.warning(msg) journal.write_msg(msg) return list() xml_filenames = list() if self.is_filename_pattern(self.xml_filename): # Если это шаблон, то получить список файлов xml_filenames = glob.glob(self.xml_filename) log.info(u'Найдены XML файлы в <%s>:' % self.xml_filename) for xml_filename in xml_filenames: log.info(u'\t%s' % xml_filename) # Это указание конкретного файла if os.path.exists(self.xml_filename): self.cache_xml_filenames = [self.xml_filename] return self.cache_xml_filenames # else: # log.warning(u'Не найден XML файл <%s> источника данных' % self.xml_filename) self.cache_xml_filenames = xml_filenames return self.cache_xml_filenames
def del_install_package(self, sPackageName): """ Удалить из списка проинсталлированных пакетов указанный пакет по наименованию. @param sPackageName: Наименование пакета. @return: True-удаление прошло нормально, False-удаление по каким то причинам не прошло. """ install_log_file = None try: if not os.path.exists(self.get_install_log_file_name()): log.warning(u'Файл <%s> не найден' % self.get_install_log_file_name()) return False install_log_file = open(self.get_install_log_file_name(), 'rt') lines = install_log_file.readlines() packages = dict([(line.split(';')[0].strip(), line.split(';')[1].strip()) for line in lines]) package_names = [line.split(';')[0].strip() for line in lines] install_log_file.close() install_log_file = None if sPackageName.strip() in package_names: del packages[sPackageName.strip()] return self._save_packages(packages) return False except: if install_log_file: install_log_file.close() raise
def parse_inbox_docs(self, doc_uuids=None, str_replaces=None, **content_links): """ Произвести сборку данных входных документов по запрашиваемым данным. @param doc_uuids: Список UUID необходимых входных документов. Если None, то обрабатываются все документы. @param str_replaces: Словарь замены в строковых значениях. Если словарь не определен замены не производятся. @param content_links: Словарь запрашиваемых данных у каждого документа. Например: { 'error': 'A/error', 'transport_uuid': 'A/url' } @return: Список заполненных словарей запрашиваемых данных для каждого документа. """ if doc_uuids is None: doc_uuids = self.get_inbox_doc_uuid() result = list() for doc_uuid in doc_uuids: if not doc_uuid: msg = u'УТМ. Не корректный UUID запрашиваемого документа <%s>' % doc_uuid log.warning(msg) journal.write_msg(msg) continue doc = self.parse_inbox_doc(doc_uuid, str_replaces=str_replaces, **content_links) if doc is not None: result.append(doc) log.debug(u'УТМ. Сборка данных входных документов %s' % result) return result
def _write(self, *values): """ Записать данные в приемник данных. @param values: Список записываемых значений @return: True/False. """ if self.template_fmt is None: msg = u'Не указан шаблон для заполнения форматированного текстового файла.' log.warning(msg) journal.write_msg(msg) return False if self.output_fmt is None: msg = u'Не указан выходной файл для заполнения форматированного текстового файла.' log.warning(msg) journal.write_msg(msg) return False context = self.get_values_as_dict() template = txtgen.gen(self.template_fmt, context) output = txtgen.gen(self.output_fmt, context) # Заполняем шаблон переменными gen_result = txtgen.gen_txt_file(template, output, context) return gen_result
def create_dialog(self, sDialogType=wizard_page.URWID_DIALOG_TYPE, items=None): """ Создать диалог. """ if items is None: log.warning( 'Install page. Not define items for package control page.') return None if sDialogType == wizard_page.URWID_DIALOG_TYPE: return urwid_dialog.do_list(u'Контроль установленных пакетов', cui_dialog.DEFAULT_DLG_HEIGHT, cui_dialog.DEFAULT_DLG_WIDTH, cui_dialog.DEFAULT_DLG_HEIGHT, *items) elif sDialogType == wizard_page.PYDLG_DIALOG_TYPE: return pydlg_dialog.do_list(u'Контроль установленных пакетов', cui_dialog.DEFAULT_DLG_HEIGHT, cui_dialog.DEFAULT_DLG_WIDTH, pydlg_dialog.DEFAULT_LIST_HEIGHT, *items) else: log.warning(u'Не поддерживаемый тип диалога <%s>' % sDialogType) return None
def get_content_error(self, content): """ Проверка возвращаемого значение/содержания на ошибки. @param content: Возвращаемое значение какой либо операции. @return: Текст ошибки, None - нет ошибки. """ if content is None: msg = u'Не определено содержание для проверки на ошибки' log.warning(msg) journal.write_msg(msg) return None if 'A' not in content: msg = u'Не корректный формат <%s>' % content log.warning(msg) journal.write_msg(msg) return None if 'error' in content['A']: err_txt = content['A']['error'] # Отобразить контент для отладки msg = u'Ошибка содержимого: <%s>' % content log.error(msg) journal.write_msg(msg) return err_txt return None
def load_xml_content(xml_filename, is_change_keys=True): """ Загрузить содержимое XML файла в словарно списковую структуру. @param xml_filename: Полное имя XML файла. @param is_change_keys: Произвести автоматическую замену ключей на короткие. @return: Словарно-списковая структура содержания XML файла. Или None в случае ошибки. """ if not os.path.exists(xml_filename): log.warning(u'XML файл <%s> не найден' % xml_filename) return None log.info(u'Загрузка содержимого файла <%s>' % xml_filename) xml_file = None try: xml_file = open(xml_filename, 'r') xml_txt = xml_file.read() xml_file.close() except: if xml_file: xml_file.close() log.fatal(u'Ошибка загрузки содержимого XML файла <%s>' % xml_filename) return None if not xml_txt.strip(): log.error(u'Файл <%s> пустой' % xml_filename) return dict() data = xmltodict.parse(xml_txt) if is_change_keys: data = change_keys_doc(data) return data
def create_dialog(self, sDialogType=wizard_page.URWID_DIALOG_TYPE, items=None): """ Создать диалог. """ if items is None: log.warning( 'Install page. Not define items for programm install page.') return None if sDialogType == wizard_page.URWID_DIALOG_TYPE: return urwid_dialog.do_checklist(u'Выбор программ', cui_dialog.DEFAULT_DLG_HEIGHT, cui_dialog.DEFAULT_DLG_WIDTH, cui_dialog.DEFAULT_DLG_HEIGHT, *items) elif sDialogType == wizard_page.PYDLG_DIALOG_TYPE: return pydlg_dialog.do_checklist(u'Выбор программ', cui_dialog.DEFAULT_DLG_HEIGHT, cui_dialog.DEFAULT_DLG_WIDTH, cui_dialog.DEFAULT_DLG_HEIGHT, *items) else: log.warning(u'Не поддерживаемы тип диалога <%s>' % sDialogType) return None
def read_as_dict(self, *values): """ Чтение данных из источника данных. @param values: Список читаемых переменных. @return: Словарь прочианных значений. Если переменная не найдена или произошла ошибка чтения, то вместо значения подставляется None с указанием WARNING в журнале сообщений. """ if not values: log.warning(u'Не определены переменные для чтения в <%s>' % self.name) values = self.values log.debug(u'Переменные взяты из описания источника данных: %s' % values) read_list = self.read(*values) result = None if read_list is None: return None elif not read_list and isinstance(read_list, list): return dict() elif read_list and isinstance(read_list, list): result = dict([(values[i], val) for i, val in enumerate(read_list)]) log.debug(u'Результат чтения данных в виде словаря %s' % result) return result
def uninstall(*argv): """ Главноя функция запуска деинсталляции. В качестве ключей могут быть параметры деинсталляции. [Параметры] --debug - включить все сервисы в режиме отладки --log - включить все сервисы в режиме журналирования --dialog - включить режим диалогов pythondialogs --urwid - включить режим диалогов urwid (по умолчанию) --check= - отметить секцию для установки --uncheck= - снять отметку секции для установки """ log.init(config) log.info(config.TITLE_TXT) try: from .ic.cui import install_wizard except Exception: from ic.cui import install_wizard # Разбираем аргументы командной строки try: options, args = getopt.getopt(argv, 'DL', ['debug', 'log', 'dialog', 'urwid', 'check=', 'uncheck=']) except getopt.error as msg: log.error(u'Ошибка параметров коммандной строки %s' % str(msg), bForcePrint=True) log.warning(__doc__, bForcePrint=True) sys.exit(2) programms = copy.deepcopy(config.UNINSTALL_PROGRAMM) for option, arg in options: if option in ('--debug', '-D'): utils.set_var('SERVICES_DEBUG_MODE', True) log.info(u'Деинсталяция. Установка режима отладки') elif option in ('--log', '-L'): utils.set_var('SERVICES_LOG_MODE', True) log.info('Деинсталяция. Установка режима журналирования') elif option in ('--dialog', ): utils.set_var('DIALOG_MODE', 'python-dialog') elif option in ('--urwid', ): utils.set_var('DIALOG_MODE', 'urwid') elif option in ('--check',): section = int(arg) if arg.isdigit() else arg programms = util.check_section(programms, section, True) elif option in ('--uncheck',): section = int(arg) if arg.isdigit() else arg programms = util.check_section(programms, section, False) result = install_wizard.uninstall(dProgramms=programms) log.info(config.TITLE_TXT) return result
def diagnostic(self): """ Простая процедура прверки доступа к источнику данных. @return: True/False. """ log.warning( u'Процедура диагностирования не определена для класса <%s>' % self.__class__.__name__)
def write(self, *values): """ Записать данные в приемник данных. @param values: Список записываемых значений @return: True/False. """ log.warning( u'Функция записи значений в приемник данных. не определена для класса <%s>' % self.__class__.__name__)
def write_as_dict(self, **values): """ Записать данные в виде словаря в приемник данных. @param values: Словарь записываемых значений. @return: True/False. """ log.warning( u'Функция записи значений в приемник данных. не определена для класса <%s>' % self.__class__.__name__)
def get_check_list(self): """ Список выбранных элементов. """ if self.dlg: return self.dlg.get_check_list() else: log.warning(u'Страница. Не определен диалог') return None
def find_inbox_document(self, doc_uuid): """ Найти входящий документ по его UUID. @param doc_uuid: UUID документа. @return: Словарь содержимого документа или None если документ не найден или ошибка. """ if self.cache_state and INBOX_STATE_NAME in self.cache_state: if doc_uuid in self.cache_state[INBOX_STATE_NAME]: return self.cache_state[INBOX_STATE_NAME][doc_uuid] else: msg = u'Кеш источника данных <%s>. Документ <%s> не найден во входящих' % ( self.name, doc_uuid) log.warning(msg) journal.write_msg(msg) else: content = self.get_http('/opt/out') if content: document_urls = content['A'].get('url', list()) if type(document_urls) not in (list, tuple): # ВНИМАНИЕ! Может быть только 1 документ # Все равно мы должны обрабатывать список document_urls = [document_urls] if not document_urls: msg = u'Список входящих документов пуст' log.warning(msg) journal.write_msg(msg) for document_url in document_urls: if isinstance( document_url, dict) and document_url['@replyId'] == doc_uuid: document_content = self.get_http(document_url['#text']) # ВНИМАНИЕ! Необходимо кроме содержания запоминать URL и ReplyID документа # иначе нельзя будет идентифицировать документ # return document_content return dict(url=document_url['#text'], uuid=doc_uuid, content=document_content) elif isinstance(document_url, str) or isinstance( document_url, unicode): # Внимание! Если документ имеет родительский документ - то есть и replyId, # если документ первичный - то и нет для него replyId # Т.е. не правильно ого искать по UUID log.warning( u'Поиск. Внешний первичный документ <%s> пропущен' % document_url) continue msg = u'Документ <%s> не найден во входящих' % doc_uuid log.warning(msg) journal.write_msg(msg) else: msg = u'Нет ответа от УТМ' log.warning(msg) journal.write_msg(msg) return None
def read_as_dict(self, *values): """ Чтение данных из источника данных. @param values: Список читаемых переменных. @return: Словарь прочианных значений. Если переменная не найдена или произошла ошибка чтения, то вместо значения подставляется None с указанием WARNING в журнале сообщений. """ log.warning( u'Функция чтения данных из источника данных. не определена для класса <%s>' % self.__class__.__name__)
def main(self): if self.dlg: result = self.dlg.main() if isinstance(result, tuple): # Может возвращать не только код, но необходим только код return result[0] else: return result else: log.warning(u'Страница. Не определен диалог') return None
def find_object(self, obj_name): """ Поиск объекта в зарегистрированных по имени. @param obj_name: Имя объекта. @return: Объект или None если объект с таким именем не найден. """ if obj_name in self.objects: return self.objects[obj_name] log.warning(u'Объект <%s> не найден среди зарегистрированных %s' % (obj_name, self.objects.keys())) return None
def init_settings(self): """ Проинициализировать конфигурационные переменные в соответствии с настройками. @return: True/False. """ ini_filename = config.get_cfg_var('SETTINGS_FILENAME') if ini_filename and not os.path.exists(ini_filename): log.warning( u'Файл настроек <%s> не найден. Используется файл настроек по умолчанию' % ini_filename) ini_filename = None return self.settings_manager.loadSettings(ini_filename)
def add_buttons(self, lButtons, sAlign=cui_dialog.BUTTONS_ALIGN_RIGHT): """ Добавление кнопок в диалоговое окно. @param lButtons: Список кнопок в формате: [('Текст',Возвращаемый код),...] @param sAlign: Выравнивание списка кнопок. """ if self.dlg: return self.dlg.add_buttons(lButtons, sAlign) else: log.warning(u'Страница. Не определен диалог') return None
def MessageBox(sText, sTitle, sDialogType=wizard_page.DEFAULT_DIALOG_TYPE): """ Диалоговое окно сообщения. @param sText: Текст сообщения. @param sTitle: Заголовок. @param sDialogType: Тип диалога. """ if sDialogType == wizard_page.URWID_DIALOG_TYPE: return urwid_message.urwidMessageBox(sText, sTitle) elif sDialogType == wizard_page.PYDLG_DIALOG_TYPE: return pydlg_message.pydlgMessageBox(sText, sTitle) else: log.warning(u'Не поддерживаемый тип диалога <%s>' % sDialogType) return None
def get_http(self, url): """ Получить содержание по URL. @param url: Адрес запроса. @return: Вовращает содержимое XML файла или None в случае ошибки. """ if not (url.startswith('http://') or url.startswith('https://')): log.warning( u'Указан не абсолютный адрес <%s> при получении содержания по адресу' % url) url = self.utm_url + url log.info(u'Преобразуем адрес к абсолютному виду <%s>' % url) try: output_xml_filename = os.path.join(self.output_dir, DEFAULT_OUTPUT_XML_FILENAME) if os.path.exists(output_xml_filename): try: log.info(u'Удаление файла <%s>' % output_xml_filename) os.remove(output_xml_filename) except: msg = u'Ошибка удаления файла <%s>' % output_xml_filename log.fatal(msg) journal.write_msg(msg) cmd = '"%s" --output "%s" -X GET %s' % (self.curl, output_xml_filename, url) execfunc.exec_shell(cmd) content = None if os.path.exists(output_xml_filename): try: content = xmlfunc.load_xml_content(output_xml_filename) except: msg = u'Ошибка XML файла данных <%s>' % output_xml_filename log.error(msg) journal.write_msg(msg) self._backup_error_file(output_xml_filename) raise else: msg = u'Не найден выходной файл УТМ <%s>' % output_xml_filename log.warning(msg) journal.write_msg(msg) return content except: msg = u'Ошибка получения содержания УТМ по адресу <%s>' % url log.fatal(msg) journal.write_msg(msg) return None
def _read(self, *values): """ Чтение данных из источника данных. @param values: Список читаемых переменных. @return: Список прочианных значений. Если переменная не найдена или произошла ошибка чтения, то вместо значения подставляется None с указанием WARNING в журнале сообщений. """ xml_filenames = self.get_xml_filenames() if not values: log.warning(u'Не определены переменные для чтения в <%s>' % self.name) values = self.values log.debug(u'Переменные взяты из описания источника данных: %s' % values) try: result = [list() for i in range(len(values))] for xml_filename in xml_filenames: # Получаем содержимое XML файла xml_content = xmlfunc.load_xml_content(xml_filename) for i, value in enumerate(values): value_path = getattr(self, value) xml_value = xmlfunc.get_xml_content_by_link( xml_content, value_path) result[i].append(xml_value) # Регистрация состояния state = dict([(values[i], val) for i, val in enumerate(result)]) self.reg_state(**state) if self.auto_remove: for xml_filename in xml_filenames: if os.path.exists(xml_filename): try: log.info(u'Удаление файла <%s>' % xml_filename) os.remove(xml_filename) except: msg = u'Ошибка удаления файла <%s>' % xml_filename log.fatal(msg) journal.write_msg(msg) return result except: log.fatal(u'Ошибка чтения данных из файлов %s' % xml_filenames) return None
def diagnostic(self): """ Простая процедура прверки доступа к источнику данных. @return: True/False. """ connection = None log.info(u'UniReader. Диагностика <%s>.<%s>' % (self.__class__.__name__, self.name)) if self.opc_server is None: msg = u'UniReader. Не определен OPC сервер в <%s>' % self.name log.warning(msg) journal.write_msg(msg) return False if self.topic is None: msg = u'UniReader. Не определен топик в <%s>' % self.name log.warning(msg) journal.write_msg(msg) return False try: # Создание клиента OPC connection = self.create_connection(self.uni_host) if connection is None: msg = u'Не возможно создать объект связи с UniReader. Хост <%s>' % self.uni_host log.error(msg) journal.write_msg(msg) return None # Контроль наличия процедуры чтения значений из OPC сервера rpc_methods = connection.system.listMethods() if 'sources.ReadValueAsString' not in rpc_methods: msg = u'UniReader. Процедура чтения значения из OPC сервера не найдена. Хост <%s>' % self.uni_host log.error(msg) journal.write_msg(msg) return None else: log.info(u'UniReader. Список методов удаленного вызова %s' % str(rpc_methods)) return True except: msg = u'UniReader. Ошибка диагностики <%s>' % self.__class__.__name__ log.fatal(msg) journal.write_msg(msg) return False
def reg_object(self, obj): """ Регистрация нового объекта в словаре внутренних объектов. Регистрация производиться по имени объекта. @param obj: Регистрируемый объект. @return: True - регистрация прошла успешно / False - ошибка. """ if hasattr(obj, 'name'): # Регистрация по имени name = getattr(obj, 'name') self.objects[name] = obj return True else: log.warning(u'Не возможно зарегистрировать объект класса <%s>' % obj.__class__.__name__) return None
def addScenarioScript(self): """ Добавить скрипты в список сценария. """ check_list = self.get_check_list() if not check_list: log.warning(u'Не определен список инсталируемых программ') return # log.debug('Check list <%s> programms %s' % (check_list, len(self._programms))) for i, check in enumerate(check_list): name = self._programms[i].get('name', 'programm_%d' % i) func = tools.getFuncStr(self._programms[i].get('script', None)) args = () kwargs = {} kwargs.update(self._programms[i]) kwargs.update({'page': self}) self.wizard.addScenarioScript(name, func, args, kwargs, check)
def _read_value(self, address): """ Прочитать значение по адресу из RSLinx. @param address: Адрес. Адрес задается явно. @return: Прочитанное значение либо None в случае ошибки. """ opc = None try: # Создание клиента OPC opc = self.create_opc_client(self.opc_host) if opc is None: msg = u'Не возможно создать объект клиента OPC. Хост <%s>' % self.opc_host log.error(msg) journal.write_msg(msg) return None # Список серверов OPC servers = opc.servers() if self.opc_server not in servers: msg = u'Сервер <%s> не найден среди %s' % (self.opc_server, servers) log.warning(msg) journal.write_msg(msg) opc.close() return None # Соедиенение с сервером server = self.opc_server opc.connect(server) # Прочитать из OPC сервера val = opc.read(address) result = self.recode(val[0]) if val and val[1] == 'Good' else None opc.close() log.debug(u'Адрес <%s>. Результат чтения данных %s' % (address, result)) return result except: if opc: opc.close() msg = u'Ошибка чтения значения по адресу <%s> в <%s>' % (address, self.__class__.__name__) log.fatal(msg) journal.write_msg(msg) return None