def runWizard(self, Page): """ Запуск визарда с указанной страницы. """ code = CANCEL_PAGE_CODE if Page: code = Page.main() while code in (PREV_PAGE_CODE, NEXT_PAGE_CODE, True): log.debug(u'Страница %s. Результирующий код <%s>' % (Page.__class__.__name__, code)) if code == PREV_PAGE_CODE: Page.delScenarioScript() Page = Page.getPrev() elif code == NEXT_PAGE_CODE: Page.addScenarioScript() Page = Page.getNext() elif code is True: Page.addScenarioScript() Page = Page.getNext() if Page: code = Page.main() else: code = FINISH_PAGE_CODE if code == FINISH_PAGE_CODE or code is True: if Page: Page.addScenarioScript() return code
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 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 install(fInstallScript=None, fPrevInstallScript=None, fPostInstallScript=None, *args, **kwargs): """ Основная функция запуска инсталлятора. @param fInstallScript: Функция инсталляционного скрипта. @param fPrevInstallScript: Предварительный скрипт инсталляции. @param fPostInstallScript: Завершающий скрипт инсталляции. В качестве аргумента функция должна принимать объект визарда. """ wiz = icInstallCUIWizard(u'Инсталляция программного обеспечения') if fPrevInstallScript: fPrevInstallScript(wiz, *args, **kwargs) # Запустить функцию инсталляционного скрипта script_ok = False if fInstallScript: script_ok = fInstallScript(wiz, *args, **kwargs) # Визард всегда запускается с первой страницы if script_ok: wiz_result_code = wiz.runFirstPage() log.debug(u'Инсталяция. Код результата <%s>' % wiz_result_code) if fPostInstallScript: fPostInstallScript(wiz, *args, **kwargs)
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 _initPackages(self, dPackages): """ Инициализация списка пакетов. """ package_list = [] # Данные списка пакетов self.result = True if dPackages: log.debug(u'Список контролируемых пакетов:') for package_name, package_misc in dPackages.items(): if 'type' in package_misc: package_type = package_misc['type'] else: package_type = 'py' # Определение версии if 'ver' in package_misc: package_ver = package_misc['ver'] else: package_ver = '' if 'compare' in package_misc: package_compare = package_misc['compare'] else: package_compare = '==' # Проверка наличия пакетов result = False if package_type == 'py': result = util.check_python_library_version( package_name, package_ver, package_compare) # Если пакет не установлен, # то попытаться поставить его из пакетов инсталлятора if not result: autoinstall_pack = package_misc.get('auto', None) result = util.targz_install_python_package( autoinstall_pack) elif package_type == 'pkg': result = util.check_linux_package(package_name, package_ver, package_compare) self.result = self.result and result check_package_ver = package_ver if result else u'Не установлен/Не сооответствует версии %s' % package_ver line = (package_name, check_package_ver, result) log.debug(u'\t%s\tver: (%s)\t[%s]' % (package_name, check_package_ver, result)) package_list += list(line) # Создание списка пакетов self.dlg = self.create_dialog(sDialogType=utils.get_var('DIALOG_MODE'), items=package_list)
def get_inbox_doc_uuid(self): """ Список UUID входных документов УТМ. """ if self.cache_state and INBOX_STATE_NAME in self.cache_state: read_list = self.cache_state[INBOX_STATE_NAME].values() else: read_list = self.get_inbox_documents() result = list() if read_list and isinstance(read_list, list): result = [doc.get('uuid', str(uuid.uuid4())) for doc in read_list] log.debug(u'Список UUID входных документов УТМ %s' % result) return result
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. """ log.debug(u'Диагностика объекта <%s>.<%s>' % (self.__class__.__name__, self.name)) inbox_docs_uuid = self.get_inbox_doc_uuid() if inbox_docs_uuid is None: return False # log.debug(u'Входящие документы УТМ %s' % inbox_docs) for doc_uuid in inbox_docs_uuid: log.debug(u'УТМ. Входящие. Документ <%s>' % doc_uuid) return True
def loadSectionList(self, ini_settings, section, name, cfg_name): """ Загрузка списка секций из INI файла. @param ini_settings: Словарь содержания INI файла. @param section: Секция источника. @param name: Наименование параметра источника данных запрашиваемого списка секций. @param cfg_name: Имя списка секций в сонфигурационном файле. @return: True/False. """ ini_names = ini_settings.get(section, dict()).get(name, list()) cfg_sections = list() for ini_name in ini_names: # cfg_section = ini_settings.get(ini_name, dict()) cfg_section = self.buildSection(ini_settings, ini_name) cfg_section['name'] = ini_name log.debug(u'Собранная секция %s' % cfg_section.keys()) cfg_sections.append(cfg_section) config.set_cfg_var(cfg_name, cfg_sections)
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
def runFirstPage(self): """ Запуск первой страницы. """ if self.pages: first_page = self.pages[0] if first_page: code = self.runWizard(first_page) log.debug(u'Результирующий код <%s>' % code) if code == FINISH_PAGE_CODE or code is True: # Нажата кнопка <OK> # Сохранить настройки self.saveSettings() # Запустить сценарий на исполнение return self.doScenario() else: # Нажата кнопка <Cancel> pass return False
def _write_as_dict(self, **values): """ Записать данные в виде словаря в приемник данных. @param values: Словарь записываемых значений. @return: True/False. """ if not values: log.warning(u'Не определены переменные для записи') values = self.get_values_as_dict() log.debug(u'Взяты переменные из описания объекта: %s' % values) context = self.get_values_as_dict() self.print_context(context) result = True for value in values.values(): cmd = self.gen_code(value, context) # execfunc.exec_code_block(cmd) return result
def gen_correct_value(self, value, cur_state=None): """ Генерация значения с учетом порядка блоков кодов и ссылок. @param value: Генерируемое значение. @param cur_state: Текущее состояние объекта. @return: Признак произведенной замены, Сгенерированное значение. """ if cur_state is None: cur_state = dict([(name, getattr(self, name)) for name in self.values]) if txtgen.is_genered(value): replace_names = txtgen.get_raplace_names(value) replaces = dict() for name in replace_names: if name not in cur_state: log.error( u'Переменная <%s> не определена в описании объекта <%s>' % (name, self.name)) continue is_fill, replaces[name] = self.gen_correct_value( cur_state[name], cur_state) log.debug(u'\tЗамена <%s> => <%s> => <%s>' % (name, cur_state[name], replaces[name])) value = txtgen.gen(value, replaces) if self.parent.is_link(value): # Это просто ссылка без требования генерации value = self.parent.get_value_by_link(value) elif execfunc.is_code_python(value) or execfunc.is_code_func( value): # Это просто блок кода без требования генерации value = execfunc.exec_code_block(value) return True, value elif self.parent.is_link(value) and not txtgen.is_genered(value): # Это просто ссылка без требования генерации return True, self.parent.get_value_by_link(value) elif (execfunc.is_code_python(value) or execfunc.is_code_func(value)) and not txtgen.is_genered(value): # Это просто блок кода без требования генерации return True, execfunc.exec_code_block(value) return False, value
def diagnostic(self): """ Простая процедура прверки доступа к источнику данных. @return: True/False. """ result = False xml_filenames = self.get_xml_filenames() if xml_filenames: xml_file_exists = [ os.path.exists(xml_filename) for xml_filename in xml_filenames ] result = sum(xml_file_exists) == len(xml_file_exists) # Прочитать данные read_data = self.read_as_dict() log.debug(u'Прочитанные данные:') for name, value in read_data.items(): log.debug(u'\t<%s>\t%s' % (name, value)) return result
def _initProgramm(self, lProgrammss): """ """ self._programms = lProgrammss # Создание списка инсталируемых программ programm_list = [] if self._programms: log.debug(u'Список инсталлируемых программ:') for programm in self._programms: line = [ programm.get('name', programm.get('programm', '-')), programm.get('description', programm.get('programm', '-')), 'on' if programm.get('check', False) else 'off' ] log.debug(u'\t%s\t(%s)\t[%s]' % (line[0], line[1], line[2])) programm_list += line self.dlg = self.create_dialog(sDialogType=utils.get_var('DIALOG_MODE'), items=programm_list)
def print_context(self, context): """ Вывести в консоль внутренне состояние объекта источника данных. Функция сделана для отладки. """ log.debug(u'Состояние контекста <%s>.<%s>' % (self.__class__.__name__, self.name)) log.debug(u'\t[Переменная]\t\t[Значение]') for name, val in context.items(): try: val_codepage = strfunc.get_codepage(val) if isinstance( val, str) else txtgen.DEFAULT_ENCODING if val_codepage is None: val_codepage = txtgen.DEFAULT_ENCODING val = unicode( str(val), val_codepage) if not isinstance(val, unicode) else val log.debug(u'\t<%s>\t\t<%s>' % (name, val)) except UnicodeDecodeError: log.error(u'Ошибка отображения состояния переменной <%s>' % name) except UnicodeEncodeError: log.error(u'Ошибка отображения состояния переменной <%s>' % name)
def _read(self, *values): """ Чтение данных из источника данных. @param values: Список читаемых переменных. @return: Список прочианных значений. Если переменная не найдена или произошла ошибка чтения, то вместо значения подставляется None с указанием WARNING в журнале сообщений. """ if not values: log.warning(u'Не определены переменные для чтения в <%s>' % self.name) values = self.values log.debug(u'Переменные взяты из описания источника данных: %s' % values) try: # Прочитать все документы inbox_docs = self.get_inbox_documents() if inbox_docs is None: return False # Регистрация состояния if not self.cache_state: inbox = dict([(doc.get('uuid', str(uuid.uuid4())), doc) for doc in inbox_docs]) state = dict([(val, self.gen_code(getattr(self, val))) for val in values]) # state = self.get_values_as_dict(values) state[INBOX_STATE_NAME] = inbox self.reg_state(**state) self.cache_state = self.state return inbox_docs except: msg = u'Ошибка чтения входящих документов УТМ' log.fatal(msg) journal.write_msg(msg) return None
def _read_value(self, address): """ Прочитать значение по адресу из OPC сервера. @param address: Адрес. Адрес задается явно. @return: Прочитанное значение либо None в случае ошибки. """ connection = None try: # Создание связи 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 # Прочитать из OPC сервера val = connection.sources.ReadValueAsString('OPC_SERVER_NODE', self.opc_server, address) result = self.recode(val[0]) if val else None log.debug(u'UniReader. Адрес <%s>. Результат чтения данных %s' % (address, result)) return result except: msg = u'UniReader. Ошибка чтения значения по адресу <%s> в <%s>' % ( address, self.__class__.__name__) log.fatal(msg) journal.write_msg(msg) return None
def _read(self, *values): """ Прочитать данные из источника данных. @param values: Список получаемых значений. @return: Список записей/рекордсет. """ self.recordset = list() if not self.sql: msg = u'Не определено SQL выражение для получения данных в <%s>' % self.name log.warning(msg) journal.write_msg(msg) self.reg_state(recordset=self.recordset) return self.recordset sql = self.gen_sql_code(self.sql) if not sql.strip(): msg = u'Попытка выполнения пустого запроса SQL' log.warning(msg) journal.write_msg(msg) self.reg_state(recordset=self.recordset) return self.recordset try: self.connect() log.info(u'Выполнение SQL: <%s>' % sql) recordset = self.connection.execute(sql) self.disconnect() self.recordset = [dict(rec) for rec in recordset] log.debug(u'Результат запроса: %s' % str(self.recordset)) except: self.disconnect() msg = u'Ошибка получения данных в <%s>' % self.name log.fatal(msg) journal.write_msg(msg) self.recordset = list() self.reg_state(recordset=self.recordset) return self.recordset
def uninstall(fUninstallScript=None, fPrevUninstallScript=None, fPostUninstallScript=None, dProgramms=None, *args, **kwargs): """ Основная функция запуска деинсталлятора. @param Script_: Функция деинсталляционного скрипта. @param PrevInstallScript_: Предварительный скрипт деинсталляции. @param PostInstallScript_: Завершающий скрипт деинсталляции. @param Programms_; Описание инсталлируемы/Деинсталлируемых программ. В качестве аргумента функция должна принимать объект визарда. """ from . import uninstall_pages wiz = icInstallCUIWizard(u'Деинсталляция программного обеспечения') if fPrevUninstallScript: fPrevUninstallScript(wizard, *args, **kwargs) # Запустить функцию деинсталляционного скрипта script_ok = False if fUninstallScript: script_ok = fUninstallScript(wizard, *args, **kwargs) else: uninstall_pages.add_wizard_programm_uninstall_page(wiz, dProgramms) script_ok = True # Визард всегда запускается с первой страницы if script_ok: wiz_result_code = wiz.runFirstPage() log.debug(u'Деинсталяция. Код результата <%d>' % wiz_result_code) if fPostUninstallScript: fPostUninstallScript(wizard, *args, **kwargs)
def _read(self, *values): """ Чтение данных из источника данных. @param values: Список читаемых переменных. @return: Список прочитанных значений. Если переменная не найдена или произошла ошибка чтения, то вместо значения подставляется None с указанием WARNING в журнале сообщений. """ connection = None if not values: log.warning( u'UniReader. Не определены переменные для чтения в <%s>' % self.name) values = self.addresses log.debug( u'UniReader. Переменные взяты из описания источника данных: %s' % values) 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 # Подготовка переменных для чтения # Адреса всегда задаются строками addresses = self._gen_addresses(*values) log.debug(u'UniReader. Чтение адресов %s' % addresses) # Прочитать из OPC сервера result = list() for address in addresses: value = connection.sources.ReadValueAsString( 'OPC_SERVER_NODE', self.opc_server, address) result.append(self.recode(value) if value else None) # Регистрация состояния state = dict([(values[i], val) for i, val in enumerate(result)]) self.reg_state(**state) log.debug(u'UniReader. Результат чтения данных:') for i, value in enumerate(result): log.debug(u'\t%s\t=\t%s' % (addresses[i], value)) return result except: msg = u'UniReader. Ошибка чтения данных <%s>' % self.__class__.__name__ log.fatal(msg) journal.write_msg(msg) return None
def _read(self, *values): """ Чтение данных из источника данных. @param values: Список читаемых переменных. @return: Список прочитанных значений. Если переменная не найдена или произошла ошибка чтения, то вместо значения подставляется None с указанием WARNING в журнале сообщений. """ opc = None if not values: log.warning(u'Не определены переменные для чтения в <%s>' % self.name) values = self.addresses log.debug(u'Переменные взяты из описания источника данных: %s' % values) 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) # Подготовка переменных для чтения # Адреса всегда задаются строками addresses = self._gen_addresses(*values) log.debug(u'Чтение адресов %s' % addresses) # Прочитать из OPC сервера result = [self.recode(val[1]) if val and val[2] == 'Good' else None for val in opc.read(addresses)] # result = [val.encode('') if isinstance(val, unicode) else val for val in result] # result = [val for val in opc.read(addresses)] opc.close() # Регистрация состояния state = dict([(values[i], val) for i, val in enumerate(result)]) self.reg_state(**state) log.debug(u'Результат чтения данных %s' % result) return result except: if opc: opc.close() msg = u'Ошибка чтения данных <%s>' % self.__class__.__name__ log.fatal(msg) journal.write_msg(msg) return None
def get_inbox_documents(self): """ Запросить входящие документы. """ if self.cache_state and INBOX_STATE_NAME in self.cache_state: return self.cache_state[INBOX_STATE_NAME].values() content = self.get_http('/opt/out') if content is None: msg = u'Ошибка определения данных по адресу </opt/out>' log.warning(msg) journal.write_msg(msg) return None if not self.get_content_error(content): documents = list() if 'A' not in content: # Если не ссылка на документ, то это просто его содержание documents.append( dict(url=u'', uuid=str(uuid.uuid4()), content=content)) else: 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) return documents else: # log.debug(u'Обрабатываемые документы. URLs:') for document_url in document_urls: log.debug(u'\t%s' % document_url) for document_url in document_urls: if isinstance(document_url, str) or isinstance( document_url, unicode): log.debug(u'Получаем документ URL (str) <%s>' % document_url) document_content = self.get_http(document_url) documents.append( dict(url=document_url, uuid=str(uuid.uuid4()), content=document_content)) elif isinstance(document_url, dict): log.debug(u'Получаем документ URL (dict) <%s>' % document_url['#text']) document_content = self.get_http(document_url['#text']) documents.append( dict(url=document_url['#text'], uuid=document_url['@replyId'], content=document_content)) else: msg = u'Не обрабатываемый тип адреса документа <%s>' % document_url log.warning(msg) journal.write_msg(msg) return documents else: return None