Пример #1
0
def saveResourceText(FileName_, Resource_):
    """
    Сохранить ресурс в файле в текстовом формате.
    @param FileName_: Полное имя ресурсного файла.
    @param Resource_: Словарно-списковая структура спецификации.
    @return: Возвращает результат выполнения операции True/False.
    """
    try:
        f = None
        # Если необходимые папки не созданы, то создать их
        dir_name = os.path.dirname(FileName_)
        try:
            os.makedirs(dir_name)
        except:
            pass

        f = open(FileName_, 'w')
        text = textfunc.StructToTxt(Resource_)
        f.write(text)
        f.close()
        log.info(u'Файл <%s> сохранен в текстовом формате.' % FileName_)
        return True
    except:
        if f:
            f.close()
        log.error(u'Ошибка сохраненения файла <%s> в текстовом формате.' %
                  FileName_)
        return False
Пример #2
0
 def setScanOptions(self, **options):
     """
     Установить опции сканирования
     @param options: Значения опций.
     @return: True - все прошло удачно / False - ошибка.
     """
     try:
         global SCAN_OPTIONS_ORDER
         for option_name in SCAN_OPTIONS_ORDER:
             if option_name in options:
                 option_val = options[option_name]
                 try:
                     setattr(self.scan_device_obj, option_name, option_val)
                     log.info(
                         u'Установка опции сканирования <%s>. Значение <%s>'
                         % (option_name, option_val))
                     # Запомнить выставленные значения опций
                     # Может быть так что устанавливаем опции в устройстве
                     # а они по не понятной причине не выставляются:-(
                     self.options[option_name] = option_val
                 except:
                     log.warning(
                         u'Ошибка установки опции сканирования <%s>. Значение <%s>'
                         % (option_name, option_val))
         return True
     except:
         log.fatal(u'Ошибка установки опций сканирования')
     return False
Пример #3
0
def copyDir(src_directory, dst_directory, bReWrite=False, bAddDir=True):
    """
    Функция папку src_directory в папку dst_directory со всеми внутренними поддиректориями
    и файлами.
    @param src_directory: Папка/директория,  которая копируется.
    @param dst_directory: Папка/директория, в которую копируется src_directory.
    @param bReWrite: Указание перезаписи директории,
        если она уже существует.
    @param bAddDir: Указание производить дополнение папки,
        в случае ко когда копируемые файлы/папки существуют.
    @return: Функция возвращает результат выполнения операции True/False.    
    """
    try:
        to_dir = os.path.join(dst_directory, os.path.basename(src_directory))
        if os.path.exists(to_dir) and bReWrite:
            log.info(u'Удаление папки <%s>' % to_dir)
            shutil.rmtree(to_dir, 1)
        if os.path.exists(to_dir) and bAddDir:
            return addCopyDir(src_directory, to_dir)
        else:
            log.info(u'Копировние папки <%s> в <%s>' % (src_directory, to_dir))
            shutil.copytree(src_directory, to_dir)
        return True
    except:
        log.fatal(u'Ошибка копирования папки из <%s> в <%s>' % (src_directory, dst_directory))
        return False
Пример #4
0
    def delWorksheet(self, XMLFileName_=None, SheetName_=None):
        """
        Удалить безвозвратно лист.
        @param XMLFileName_: Имя XML файла книги. Если не определено,
        то имеется ввиду активная книга.
        @param SheetName_: Имя листа в указанной книге. Если не указано,
        то имеется ввиду первый лист.
        @return: True-лист удален, False-лист по какойто причине не удален.
        """
        XMLFileName_ = self._unificXMLFileName(XMLFileName_)

        SheetName_ = self._unicode2str(SheetName_)

        # Определить книгу
        workbook_data = self._findWorkbookData(XMLFileName_)
        if workbook_data is None:
            log.warning('Workbook <%s> not found' % XMLFileName_)
            return False
        # Найти и удалить лист
        result = False
        for i, data in enumerate(workbook_data['children']):
            if data['name'] == 'Worksheet':
                if SheetName_ is None:
                    # Если имя листа не определено, то просто удалить первый попавшийся лист
                    del workbook_data['children'][i]
                    result = True
                    break
                else:
                    # Если имя листа определено, то проверить на соответствие имен листов
                    if data['Name'] == SheetName_:
                        log.info('Delete <%s> worksheet' % SheetName_)
                        del workbook_data['children'][i]
                        result = True
                        break
        return result
Пример #5
0
def glue_pdf_files(out_pdf_filename, *pdf_filenames):
    """
    Процедура склеивания/объединения PDf файлов в один.
    @param out_pdf_filename: Полное наименование результирующего PDF файла.
    @param pdf_filenames: Список имен файлов-источников.
        Объединение происходит в порядке указанном списком pdf_filenames.
        Если какой либо файл отсутствует, то объединение происходит без него.
    @return: True - объединение прошло успешно / False - ошибка по какой-либо причине.
    """
    try:
        merger = PyPDF2.PdfFileMerger()
        filenames = [
            filename for filename in pdf_filenames
            if filename.lower().endswith('.pdf') and os.path.exists(filename)
        ]
        for filename in filenames:
            pdf_file = open(filename, 'rb')
            log.debug(u'Объединение PDF файла <%s> => <%s>' %
                      (filename, out_pdf_filename))
            reader = PyPDF2.PdfFileReader(pdf_file)
            merger.append(reader)

        out_pdf_filename = os.path.abspath(out_pdf_filename)
        if os.path.exists(out_pdf_filename):
            log.info(u'Удаление файла <%s>' % out_pdf_filename)
            try:
                os.remove(out_pdf_filename)
            except:
                log.fatal(u'Ошибка удаления файла <%s>' % out_pdf_filename)
        log.debug(u'Запись результирующего файла <%s>' % out_pdf_filename)
        merger.write(out_pdf_filename)
        return True
    except:
        log.fatal(u'Ошибка склеивания/объединения PDF файлов')
    return False
Пример #6
0
 def _existTagBand(self):
     """
     Присутствует в шаблоне колонка тегов бендов?
         Если не существует, то далее считаем,
         что весь шаблон - это  заголовок отчета [header].
     @return: True - колонка тегов бендов есть в шаблоне / False - нет.
     """
     log.info(u'Колонка тегов бендов: %s' % str(self._tag_band_col))
     return self._tag_band_col is not None
Пример #7
0
def icCopyFilesByMask(fromMask, toMask, Rewrite_=True, bDelImage=False):
    """
    Копирует файлы по маске. Пример: "C:\WRK\p*.dbf" -> "Y:\WRK\pkt*.dbf"

    @type fromMask: C{string}
    @param fromMask: Маска, задающая файлы, которые надо копировать.
    @type toMask: C{string}
    @param toMask:Маска задает, куда надо копировать файлы.
    @type bDelImage: C{bool}
    @param bDelImage: Признак удаления образа файла. Если True - аналог переноса
    файлов с переименованием.
    """
    fileList = []

    fromMask = util.icUpper(fromMask.replace('\\', '/'))
    toMask = toMask.replace('\\', '/')
    dirName = '/'.join(fromMask.split('/')[:-1])
    #   Регулярное выражение для сравнения
    rm = re.compile(
        fromMask.replace('.', '\\.').replace('*', '.*').replace('$', '\\$'))
    ml1 = fromMask.split('*')
    ml2 = toMask.split('*')

    if os.path.isdir(dirName):
        #   Определяем список файлов
        dir_list = os.listdir(dirName)

        for indx, fl in enumerate(dir_list):
            path, fileName = os.path.split(fl)

            #   Определяем расширение файла
            try:
                ext = fileName.split('.')[1]
            except:
                ext = None

            fn = util.icUpper(dirName + '/' + fl)

            # Если очередное имя не является именем директории и удовлетворяет
            # шаблону, то соответствующий файл копируется в нужное место.
            if not os.path.isdir(fn) and truth(rm.match(fn)):
                #   Определяем новое имя файла
                copyName = fn
                for i, s in enumerate(ml2):
                    if i < len(ml1):
                        if ml1[i] and s:
                            copyName = copyName.replace(ml1[i], s)
                    else:
                        break

                log.info(u'Copy file %s -> %s' % (fn, copyName))
                if icCopyFile(fn, copyName, Rewrite_) and bDelImage:
                    Remove(fn)
                    log.info(u'Delete file <%s>' % fn)
    else:
        log.warning(u'Dir <%> didn\'t find' % dirName)
Пример #8
0
 def runExtScan(self):
     """
     Запуск внешнего инструмента сканирования.
     @return: True/False.
     """
     if self.ext_scan_cmd:
         log.info(u'Запуск комманды <%s>' % self.ext_scan_cmd)
         os.system(self.ext_scan_cmd)
         return True
     return False
Пример #9
0
 def OpenOffice(self, ODSFileName_):
     """
     Открыть.
     @param ODSFileName_: Имя ods файла, содержащего сгенерированный отчет.
     """
     if ODSFileName_ and os.path.exists(ODSFileName_):
         cmd = 'libreoffice %s&' % ODSFileName_
         log.info('Command <%s>' % cmd)
         os.system(cmd)
     else:
         log.warning(u'Открытие. Файл <%s> не найден' % ODSFileName_)
Пример #10
0
 def PrintOffice(self, ODSFileName_):
     """
     Печать отчета с помощью CALC.
     @param ODSFileName_: Имя ods файла, содержащего сгенерированный отчет.
     """
     if ODSFileName_ and os.path.exists(ODSFileName_):
         cmd = 'libreoffice -p %s&' % ODSFileName_
         log.info(u'Command <%s>' % cmd)
         os.system(cmd)
     else:
         log.warning(u'Печать. Файл <%s> не найден.' % ODSFileName_)
Пример #11
0
    def Update(self, RepTemplateFileName_=None):
        """
        Обновить шаблон отчета в системе генератора отчетов.
        @param RepTemplateFileName_: Имя файла шаблона отчета.
            Если None, то должен производиться запрос на выбор этого файла.
        @return: Имя файла файла шаблона или None в случае ошибки.
        """
        if RepTemplateFileName_ is None:
            filename = dlg.getFileDlg(
                self._ParentForm, u'Выберите шаблон отчета:',
                u'Microsoft Excel 2003 XML (*.xml)|*.xml|Электронные таблицы ODF (*.ods)|*.ods',
                self.getReportDir())
        else:
            filename = os.path.abspath(os.path.normpath(RepTemplateFileName_))

        if os.path.isfile(filename):

            # Конвертация
            log.debug(u'Начало конвертации <%s>' % filename)
            tmpl_filename = None
            template = None
            if os.path.exists(
                    os.path.splitext(filename)[0] + DEFAULT_TEMPLATE_EXT):
                tmpl_filename = os.path.splitext(
                    filename)[0] + DEFAULT_TEMPLATE_EXT
                template = icreptemplate.icODSReportTemplate()
            elif os.path.exists(
                    os.path.splitext(filename)[0] + ODS_TEMPLATE_EXT):
                tmpl_filename = os.path.splitext(
                    filename)[0] + ODS_TEMPLATE_EXT
                template = icreptemplate.icODSReportTemplate()
            elif os.path.exists(
                    os.path.splitext(filename)[0] + XLS_TEMPLATE_EXT):
                tmpl_filename = os.path.splitext(
                    filename)[0] + XLS_TEMPLATE_EXT
                template = icreptemplate.icXLSReportTemplate()
            elif os.path.exists(
                    os.path.splitext(filename)[0] + XML_TEMPLATE_EXT):
                tmpl_filename = os.path.splitext(
                    filename)[0] + XML_TEMPLATE_EXT
                template = icreptemplate.icExcelXMLReportTemplate()
            else:
                log.warning(u'Not find report template for <%s>' % filename)
            if template:
                rep_template = template.read(tmpl_filename)
                new_filename = os.path.splitext(
                    filename)[0] + DEFAULT_REPORT_TEMPLATE_EXT
                res.saveResourcePickle(new_filename, rep_template)
            log.info(u'Конец конвертации')
            return new_filename
        else:
            log.warning(u'Не найден файл источника шаблона <%s>' % filename)
        return None
Пример #12
0
    def open(self, TemplateFile_):
        """
        Открыть файл шаблона отчета.
        @param TemplateFile_: Файл шаблона отчета.
        """
        try:
            ods_filename = os.path.splitext(TemplateFile_)[0] + '.ods'
            cmd = 'unoconv --format=ods %s' % TemplateFile_
            log.info(u'Выполнение комманды <%s>' % cmd)
            os.system(cmd)

            return icODSReportTemplate.open(self, ods_filename)
        except:
            log.fatal(u'Ошибка открытия файла шаблона <%s>' % TemplateFile_)
        return None
Пример #13
0
 def setOptions(self, **options):
     """
     Установить опции сканирования в диалоговом окне.
     @param options: Опции.
     @return: True/False.
     """
     for option_name, option_value in options.items():
         if hasattr(self, option_name):
             try:
                 setattr(self, option_name, option_value)
                 log.info(u'Установлена опция <%s>. Значение <%s>' %
                          (option_name, option_value))
             except:
                 log.warning(u'Ошибка установки опции <%s>. Значние <%s>' %
                             (option_name, option_value))
     # После установки атрибутов отобразить их в диалоговом окне
     self.showOptions()
Пример #14
0
def remove_file(filename):
    """
    Удалить файл.
    @param filename: Имя файла.
    @return: True/False.
    """
    if not os.path.exists(filename):
        log.warning(u'Удаление. Файл <%s> не найден' % filename)
        return False

    try:
        os.remove(filename)
        log.info(u'Файл <%s> удален' % filename)
        return True
    except:
        log.fatal(u'Ошибка удаления файла <%s>' % filename)
    return False
Пример #15
0
 def _genXMLReport(self, Rep_):
     """
     Генерация отчета и сохранение его в XML файл.
     @param Rep_: Полное описание шаблона отчета.
     @return: Возвращает имя xml файла или None в случае ошибки.
     """
     if Rep_ is None:
         Rep_ = self._Rep
     data_rep = self.GenerateReport(Rep_)
     if data_rep:
         rep_file = icrepfile.icExcelXMLReportFile()
         rep_file_name = os.path.join(
             self.getReportDir(),
             '%s_report_result.xml' % str(data_rep['name']))
         rep_file.write(rep_file_name, data_rep)
         log.info(u'Сохранение отчета в файл <%s>' % rep_file_name)
         return rep_file_name
     return None
Пример #16
0
    def save(self, report_data=None, is_virtual_excel=True):
        """
        Сохранить результаты генерации в файл
        @param report_data: Сгенерированный отчет.
        @param is_virtual_excel: Сохранение произвести с помощью VirtualExcel?
            True - да, False - Сохранение производится конвертацией с помощью UNOCONV.
            ВНИМАНИЕ! При конвертации с помощью UNOCONV ячейки не образмериваются.
                Размеры ячеек остаются по умолчанию.
                UNOCONV транслирует не все стили и атрибуты ячеек.
        @return: Имя сохраненного файла или None, если сохранения не произошло.
        """
        if report_data:
            rep_file = icrepfile.icExcelXMLReportFile()
            save_dir = self.getProfileDir()
            if not save_dir:
                save_dir = icrepgensystem.DEFAULT_REPORT_DIR
            # print(u'DBG:', save_dir, report_data, type(report_data))
            xml_rep_file_name = os.path.join(
                save_dir, '%s_report_result.xml' % report_data['name'])
            rep_file_name = os.path.join(
                save_dir, '%s_report_result.ods' % report_data['name'])

            rep_file.write(xml_rep_file_name, report_data)

            if is_virtual_excel:
                log.info(u'Конвертация отчета <%s> в файл <%s>' %
                         (textfunc.toUnicode(xml_rep_file_name),
                          textfunc.toUnicode(rep_file_name)))
                v_excel = icexcel.icVExcel()
                v_excel.Load(xml_rep_file_name)
                v_excel.SaveAs(rep_file_name)
            else:
                # ВНИМАНИЕ! UNOCONV транслирует не все стили и атрибуты ячеек
                # Поэтому сначала используется Virtual Excel
                cmd = 'unoconv --format=ods %s' % xml_rep_file_name
                log.info(
                    u'UNOCONV. Конвертация отчета <%s> в файл <%s>. (%s)' %
                    (textfunc.toUnicode(xml_rep_file_name),
                     textfunc.toUnicode(rep_file_name),
                     textfunc.toUnicode(cmd)))
                os.system(cmd)

            return rep_file_name
        return None
Пример #17
0
def delAllFilesFilter(directory, *file_filter):
    """
    Удаление всех файлов из папки с фильтрацией по маске файла. Удаление
    рекурсивное по поддиректориям.
    @param directory: Папка-источник.
    @param file_filter: Список масок файлов которые нужно удалить.
        Например '*_pkl.tab'.
    """
    try:
        # Сначала обработка в поддиректориях
        subdirs = getSubDirs(directory)
        if subdirs:
            for sub_dir in subdirs:
                delAllFilesFilter(sub_dir, *file_filter)
        for file_mask in file_filter:
            del_files = getFilesByMask(os.path.join(directory, file_mask))
            for del_file in del_files:
                os.remove(del_file)
                log.info(u'Удаление файла <%s>' % del_file)
        return True
    except:
        log.fatal(u'Ошибка удаления файлов %s из папки <%s>' % (str(file_filter), directory))
        return None
Пример #18
0
    def PreviewOffice(self, ODSFileName_):
        """
        Открыть отчет в режиме предварительного просмотра.
        @param ODSFileName_: Имя ods файла, содержащего сгенерированный отчет.
        """
        if not os.path.exists(ODSFileName_):
            log.warning(u'Предварительный просмотр. Файл <%s> не найден' %
                        ODSFileName_)
            return

        pdf_filename = os.path.splitext(ODSFileName_)[0] + '.pdf'
        if os.path.exists(pdf_filename):
            try:
                os.remove(pdf_filename)
            except:
                log.error(u'Delete file <%s>' % pdf_filename)

        cmd = 'unoconv --format=pdf %s' % ODSFileName_
        log.info(u'UNOCONV. Command <%s>' % cmd)
        os.system(cmd)

        cmd = 'evince %s&' % pdf_filename
        log.info(u'EVINCE. Command <%s>' % cmd)
        os.system(cmd)
Пример #19
0
def createReportResourceFile(template_filename):
    """
    Создать ресурсный файл шаблона по имени запрашиваемого.
    @param template_filename: Имя запрашиваемого файла шаблона.
    @return: Скорректированное имя созданного файла шаблона или None в случае ошибки.
    """
    # Коррекция имени файла с учетом русских букв в имени файла
    dir_name = os.path.dirname(template_filename)
    base_filename = os.path.basename(template_filename).replace(' ', '_')
    base_filename = textfunc.rus2lat(base_filename) if textfunc.isRUSText(
        base_filename) else base_filename
    norm_tmpl_filename = os.path.join(dir_name, base_filename)

    log.info(u'Создание нового файла шаблона <%s>' % norm_tmpl_filename)
    # Последовательно проверяем какой файл можно взять за основу для шаблона
    for ext in report_generator.SRC_REPORT_EXT:
        src_filename = os.path.splitext(template_filename)[0] + ext
        unicode_src_filename = textfunc.toUnicode(src_filename)
        if os.path.exists(src_filename):
            # Да такой файл есть и он может выступать
            # в качестве источника для шаблона
            log.info(u'Найден источник шаблона отчета <%s>' %
                     unicode_src_filename)
            try:
                rep_generator = report_generator.createReportGeneratorSystem(
                    ext)
                return rep_generator.Update(src_filename)
            except:
                log.fatal(u'Ошибка конвертации шаблона отчета <%s> -> <%s>' %
                          (unicode_src_filename, norm_tmpl_filename))
            return None

    log.warning(
        u'Не найдены источники шаблонов отчета в папке <%s> для <%s>' %
        (dir_name, textfunc.toUnicode(os.path.basename(template_filename))))
    return None
Пример #20
0
    def copyToScanDir(self, scan_filename=None, scan_dir=None, doRemove=True):
        """
        Копировать файл - результат сканирования в папку.
        @param scan_filename: Результирующий файл сканирования.
            Если не указан, то берется файл по умолчанию.
        @param scan_dir: Папка сканирования.
        @param doRemove: Произвести перенос файла?
        @return: True/False
        """
        if scan_filename is None:
            scan_filename = config.DEFAULT_SCAN_FILENAME

        if scan_dir is None:
            scan_dir = self.scan_dir

        if not os.path.exists(scan_filename):
            log.warning(u'Не существует файл скана <%s>' % scan_filename)
            return False

        if scan_dir:
            if not os.path.exists(scan_dir):
                try:
                    os.makedirs(scan_dir)
                    log.info(u'Создана папка сканирования <%s>' % scan_dir)
                except OSError:
                    log.fatal(u'Ошибка создания папки сканирования <%s>' %
                              scan_dir)
                    return False

            new_filename = os.path.join(scan_dir,
                                        os.path.basename(scan_filename))
            if scan_filename != new_filename:
                shutil.copyfile(scan_filename, new_filename)
                log.info(u'Копирование файла <%s> в директорию <%s>' %
                         (scan_filename, scan_dir))
                if doRemove:
                    try:
                        os.remove(scan_filename)
                        log.info(u'Удален файл <%s>' % scan_filename)
                    except:
                        log.fatal(u'Ошибка удаления файла <%s>' %
                                  scan_filename)
            return True
        else:
            log.warning(u'Не определена папка сканирования')
        return False
Пример #21
0
    def _getSQLQueryTable(self, report, db_url=None, sql=None):
        """
        Получить таблицу запроса.
        @param report: Шаблон отчета.
        @param db_url: Connection string в виде url. Например
            postgresql+psycopg2://postgres:[email protected]:5432/realization.
        @param sql: Текст SQL запроса.
        @return: Функция возвращает словарь -
            ТАБЛИЦА ЗАПРОСА ПРЕДСТАВЛЯЕТСЯ В ВИДЕ СЛОВАРЯ 
            {'__fields__':имена полей таблицы,'__data__':данные таблицы}
        """
        result = None
        # Инициализация
        db_connection = None
        try:
            if not db_url:
                data_source = report['data_source']

                if not data_source:
                    # Учет случая когда источник данных не определен
                    log.warning(u'Не определен источник данных в отчете')
                    return {'__fields__': list(), '__data__': list()}

                signature = data_source[:4].upper()
                if signature != DB_URL_SIGNATURE:
                    log.warning('Not support DB type <%s>' % signature)
                    return result
                # БД задается с помощью стандартного DB URL
                db_url = data_source[4:].lower().strip()

            log.info(u'DB connection <%s>' % db_url)
            # Установить связь с БД
            db_connection = sqlalchemy.create_engine(db_url)
            # Освободить БД
            # db_connection.dispose()
            log.info(u'DB SQL <%s>' % textfunc.toUnicode(sql, 'utf-8'))
            sql_result = db_connection.execute(sql)
            rows = sql_result.fetchall()
            cols = rows[0].keys() if rows else []

            # Закрыть связь
            db_connection.dispose()
            db_connection = None

            # ТАБЛИЦА ЗАПРОСА ПРЕДСТАВЛЯЕТСЯ В ВИДЕ СЛОВАРЯ
            # {'__fields__':имена полей таблицы,'__data__':данные таблицы} !!!
            result = {'__fields__': cols, '__data__': list(rows)}
            return result
        except:
            if db_connection:
                # Закрыть связь
                db_connection.dispose()

            # Вывести сообщение об ошибке в лог
            log.fatal(u'Ошибка определения таблицы SQL запроса <%s>.' % sql)
            log.error(u'''ВНИМАНИЕ! Если возникает ошибка в модуле:
        ----------------------------------------------------------------------------------------------
        File "/usr/lib/python2.7/dist-packages/sqlalchemy/engine/default.py", line 324, in do_execute
            cursor.execute(statement, parameters)
        TypeError: 'dict' object does not support indexing
        ----------------------------------------------------------------------------------------------        
        Это означает что SQLAlchemy не может распарсить SQL выражение. 
        Необходимо вместо <%> использовать <%%> в SQL выражении. 
                    ''')

        return None
Пример #22
0
def main(argv):
    """
    Основная запускающая функция.
    @param argv: Список параметров коммандной строки.
    """
    # Разбираем аргументы командной строки
    try:
        options, args = getopt.getopt(argv, 'h?vdl', [
            'help', 'version', 'debug', 'log', 'scanner=', 'source=', 'mode=',
            'multi_scan', 'preview', 'page_size=', 'area=', 'scan_dir=',
            'file_name=', 'file_type=', 'ext_cmd=', 'pack_mode', 'pack_pages=',
            'glue', 'max_sheets='
        ])
    except getopt.error as msg:
        log.error(str(msg), bForcePrint=True)
        log.info(__doc__)
        sys.exit(2)

    # Инициализоция системы журналирования
    log.init(config)

    txt_version = '.'.join([str(ver) for ver in __version__])
    cmd_options = dict()
    for option, arg in options:
        if option in ('-h', '--help', '-?'):
            print(__doc__)
            sys.exit(0)
        elif option in ('-v', '--version'):
            print('icScanner version: %s' % txt_version)
            sys.exit(0)
        elif option in ('-d', '--debug'):
            config.set_glob_var('DEBUG_MODE', True)
        elif option in ('-l', '--log'):
            config.set_glob_var('LOG_MODE', True)
        elif option in ('--scanner', ):
            cmd_options['scanner'] = arg
        elif option in ('--source', ):
            cmd_options['scan_source'] = arg
        elif option in ('--mode', ):
            cmd_options['scan_mode'] = arg
        elif option in ('--multi_scan', ):
            cmd_options['is_multi_scan'] = True
        elif option in ('--preview', ):
            cmd_options['is_preview'] = True
        elif option in ('--page_size', ):
            if arg in ('A4', 'a4'):
                cmd_options['page_size'] = scan_manager.A4_PORTRAIT_PAGE_SIZE
            elif arg in ('A3', 'a3'):
                cmd_options['page_size'] = scan_manager.A3_PORTRAIT_PAGE_SIZE
            else:
                log.warning(u'Не обрабатываемый размер страницы <%s>' % arg)
        elif option in ('--area', ):
            try:
                area = tuple([float(x.strip()) for x in arg.split(',')])
                cmd_options['scan_area'] = area
            except:
                log.fatal(
                    u'Ошибка парсинга параметра области сканирования <%s>' %
                    arg)
        elif option in ('--scan_dir', ):
            cmd_options['scan_dir'] = arg
        elif option in ('--file_name', ):
            cmd_options['scan_filename'] = arg
        elif option in ('--file_type', ):
            cmd_options['scan_filetype'] = arg.lower()
        elif option in ('--depth', ):
            cmd_options['depth'] = int(arg)
        elif option in ('--ext_cmd', ):
            cmd_options['ext_scan_cmd'] = arg
        elif option in ('--pack_mode', ):
            cmd_options['pack_mode'] = True
        elif option in ('--pack_pages', ):
            cmd_options['pack_pages'] = arg
        elif option in ('--max_sheets', ):
            config.set_glob_var('DEFAULT_SCANNER_MAX_SHEETS', int(arg))
        else:
            log.warning(u'Не обрабатываемый параметр коммандной строки <%s>' %
                        option)

    # По умолчанию пакетный режим отключен+
    #                                     v
    if not cmd_options.get('pack_mode', False):
        # Внимание! Приложение создается для
        # управления диалоговыми окнами
        app = wx.PySimpleApp()
        # ВНИМАНИЕ! Выставить русскую локаль
        # Это необходимо для корректного отображения календарей,
        # форматов дат, времени, данных и т.п.
        locale = wx.Locale()
        locale.Init(wx.LANGUAGE_RUSSIAN)

        scanner_dlg.do_scan_dlg(options=cmd_options,
                                title=u'Сканирование. icScanner ' +
                                txt_version)
        app.MainLoop()
    else:
        # В пакетном режиме не используем диалоговое окно
        # Но в случае режима склеивания документа по частям диалоговые окна используются
        filenames = cmd_options.get('scan_filename', u'').split(';')
        pack_page_list = cmd_options.get('pack_pages', u'').split(';')
        n_pages = [
            int(pack_page.split('/')[0])
            if '/' in pack_page else int(pack_page)
            for pack_page in pack_page_list
        ]
        duplexes = [
            bool(int(pack_page.split('/')[1])) if '/' in pack_page else False
            for pack_page in pack_page_list
        ]
        scan_filenames = [(filename, n_pages[i] if i < len(n_pages) else 1,
                           duplexes[i] if i < len(duplexes) else False)
                          for i, filename in enumerate(filenames)]
        scan_admin = scanner_dlg.icScanAdministrator()
        # Установить дополнительные опции из коммандной строки
        scan_admin.setExtOptions(scan_dir=cmd_options['scan_dir'])
        scan_admin.runScanPack(*scan_filenames)
Пример #23
0
    def runScan(self):
        """
        Запусть процесс сканирования,
        согласно выставленным параметрам.
        @return: True/False
        """
        if self.scan_manager is None:
            log.warning(u'Не определен менеджер сканирования')
            return False
        if self.scanner is None:
            log.warning(u'Не определено устройство сканирования')
            return False

        self.scan_manager.init()

        self.scan_manager.open(self.scanner)

        # Выставить все опции
        options = dict()
        if self.scan_source:
            options['source'] = self.scan_source
        if self.scan_mode:
            options['mode'] = self.scan_mode
        if self.depth:
            options['depth'] = self.depth
        if self.page_size:
            options['page_width'] = self.page_size[0]
            options['page_height'] = self.page_size[1]
        else:
            # ВНИМАНИЕ! Если не определить размер страницы
            # край скана будет обрезаться
            # По умолчанию A4 портретной ориентации
            options['page_width'] = 210.0
            options['page_height'] = 297.0
        if self.scan_area:
            options['tl_x'] = self.scan_area[0]
            options['tl_y'] = self.scan_area[1]
        if self.scan_area and self.page_size:
            options['br_x'] = self.page_size[0] - self.scan_area[2]
            options['br_y'] = self.page_size[1] - self.scan_area[3]
        else:
            # ВНИМАНИЕ! Если не определить размер страницы
            # край скана будет обрезаться
            # По умолчанию A4 портретной ориентации
            options['br_x'] = 210.0
            options['br_y'] = 297.0

        self.scan_manager.setScanOptions(**options)

        # Определение имени файла сканирования
        scan_filename = os.path.join(
            ic_file.getHomeDir(), config.PROFILE_DIRNAME, self.scan_filename +
            '.' + self.scan_filetype
        ) if self.scan_filename else config.DEFAULT_SCAN_FILENAME
        if os.path.exists(scan_filename):
            # Удалить старый файл сканирования
            try:
                os.remove(scan_filename)
                log.info(u'Удален файл <%s>' % scan_filename)
            except OSError:
                log.fatal(u'Ошибка удаления файла <%s>' % scan_filename)
        log.debug(u'Сканирование в файл <%s>' % scan_filename)

        try:
            if not self.is_multi_scan:
                result = self.scan_manager.singleScan(scan_filename)
            else:
                result = self.scan_manager.multiScan(scan_filename)

            if not result:
                # Какая-то ошибка сканирования
                dlg.getErrBox(
                    u'ОШИБКА',
                    u'Ошибка сканирования. Проверте листы в лотке сканера')
                return False

            if self.scan_dir:
                self.copyToScanDir(scan_filename, self.scan_dir)

            if self.is_preview:
                self.previewScanFile(scan_filename)
            return True
        except:
            log.fatal(u'Ошибка сканирования')
        return False
Пример #24
0
    def runScanPack(self, *scan_filenames):
        """
        Запусть процесс сканирования в режиме пакетной обработки,
        согласно выставленным параметрам.
        @param scan_filenames: Имена файлов скана с указанием количества листов
            и признака 2-стороннего сканирования.
            Например:
                (scan001, 3, True), (scan002, 1, False), (scn003, 2, True), ...
        @return: True/False
        """
        if self.scan_manager is None:
            log.warning(u'Не определен менеджер сканирования')
            return False
        if self.scanner is None:
            log.warning(u'Не определено устройство сканирования')
            return False

        self.scan_manager.init()
        self.scan_manager.open(self.scanner)

        # Выставить все опции
        options = dict()
        if self.scan_source:
            options['source'] = self.scan_source
        if self.scan_mode:
            options['mode'] = self.scan_mode
        if self.depth:
            options['depth'] = self.depth
        if self.page_size:
            options['page_width'] = self.page_size[0]
            options['page_height'] = self.page_size[1]
        else:
            # ВНИМАНИЕ! Если не определить размер страницы
            # край скана будет обрезаться
            # По умолчанию A4 портретной ориентации
            options['page_width'] = 210.0
            options['page_height'] = 297.0
        if self.scan_area:
            options['tl_x'] = self.scan_area[0]
            options['tl_y'] = self.scan_area[1]
        if self.scan_area and self.page_size:
            options['br_x'] = self.page_size[0] - self.scan_area[2]
            options['br_y'] = self.page_size[1] - self.scan_area[3]
        else:
            # ВНИМАНИЕ! Если не определить размер страницы
            # край скана будет обрезаться
            # По умолчанию A4 портретной ориентации
            options['br_x'] = 210.0
            options['br_y'] = 297.0

        self.scan_manager.setScanOptions(**options)

        scans = [(os.path.join(ic_file.getHomeDir(), config.PROFILE_DIRNAME,
                               scan_filename + '.' + self.scan_filetype)
                  if scan_filename else config.DEFAULT_SCAN_FILENAME,
                  int(n_pages), bool(is_duplex))
                 for scan_filename, n_pages, is_duplex in scan_filenames]
        for scan_filename, n_pages, is_duplex in scans:
            full_scan_filename = os.path.join(
                os.environ.get('HOME', '/home/user'), config.PROFILE_DIRNAME,
                scan_filename)
            if os.path.exists(full_scan_filename):
                # Удалить старый файл сканирования
                try:
                    os.remove(full_scan_filename)
                    log.info(u'Удален ранее отсканированный файл <%s>' %
                             full_scan_filename)
                except OSError:
                    log.fatal(u'Ошибка удаления файла <%s>' %
                              full_scan_filename)

        try:
            scan_filenames = self.scan_manager.scan_pack(scan_filenames=scans)

            # Перенос отсканированных файлов в результирующую папку
            if self.scan_dir and os.path.exists(self.scan_dir):
                for scan_filename in scan_filenames:
                    if scan_filename and os.path.exists(scan_filename):
                        log.debug(
                            u'Перенос файла <%s> в результирующую папку <%s>' %
                            (scan_filename, self.scan_dir))
                        self.copyToScanDir(scan_filename, self.scan_dir)
                    else:
                        log.warning(
                            u'Не определен результирующий файл сканирования')
            else:
                log.warning(u'Не определена результирующая папка сканирования')

            return True
        except:
            log.fatal(u'Ошибка сканирования в режиме пакетной обработки')

        return False
Пример #25
0
def ic_eval(expr,
            logType=-1,
            evalSpace=None,
            msg='',
            globSpace=None,
            compileKey=None):
    """
    Функция выполняет предобработку вычисляемого выражения, вычисляет с использование стандартной,
    функции eval(...), а также обрабатывает исключения. В качестве локального пространства имен
    используется словарь evalSpace. В качестве глобального пространства имен берется словарь возвращаемый
    функцией globals(). Если передается уникальный идентификатор выполняемого выражения, то
    функция откомпилирует выражение и сохранит в буфере для последующего использования.

    @type expr: C{string}
    @param expr: Вычисляемое выражение.
    @type logType: C{int}
    @param logType: Тип лога (0 - консоль, 1- файл, 2- окно лога)
    @param evalSpace: Пространство имен, необходимых для вычисления выражения
    @type evalSpace: C{dictionary}
    @type msg: C{string}
    @param msg: Сообщение, которое дополнительно выводится при ошибке. Если параметр None,
        то сообщение об ошибке не выводится.
    @param globalSpace: Глобальное пространство имен.
    @type globalSpace: C{dictionary}
    @type compileKey: C{int}
    @param compileKey: Идентификатор компилированного выражения.
    """
    # В режиме отладки если определены точки остонова в выражении,
    # вызовы перенаправляются в служебный модуль, в котором соответствующие
    # вычисляемые выражения представляются функциями с уникальным именами. Такой
    # прием позволяет воспользоваться стандартым отладчиком pdb.py.

    if (evalSpace and compileKey and '__runtime_mode' in evalSpace
            and evalSpace['__runtime_mode'] == IC_RUNTIME_MODE_DEBUG):
        try:
            subsys = resource.icGetResPath().split('/')[-1]
            MyExec('import %s.debug as debugModul' % subsys)
            newSpace = eval('debugModul.f_%s(_esp)' % compileKey, globSpace,
                            evalSpace)
            evalSpace.update(newSpace)

            if '_resultEval' in evalSpace:
                ret = evalSpace['_resultEval']

            log.info(u'EXECUTE ATTRIBUTE DEBUG FUNCTION f%s(_esp)' %
                     compileKey)
            return True, ret
        except:
            pass

    if globSpace is None:
        globSpace = globals()

    #   Отсекаем по типу выражения
    if not isinstance(expr, str):
        return 0, None

    #   Отсекаем пустые строки
    if expr == '':
        return 1, ''

    bSuccess, ret = 1, None
    evalSpace['_resultEval'] = None

    #####################################################
    #   Если выражение уже откомпилировано, то пытаемся
    #   его выполнить
    bCompile = False

    if compileKey:
        try:
            s = GetCompileString(compileKey, 'eval')

            if s:
                ret = eval(s, globSpace, evalSpace)
                bCompile = True
            else:
                s = GetCompileString(compileKey, 'exec')

                if s:
                    exec(s, globSpace, evalSpace)
                    bCompile = True

                    if '_resultEval' in evalSpace:
                        ret = evalSpace['_resultEval']
        except:
            if msg is not None:
                ret = u'EXEC[EVAL] EXCEPTION IN %s: exec(%s)' % (msg, expr)
                log.fatal(ret)

            return 0, ret
    #############################################

    #   Компилируем и выполняем, если выражение еще
    #   не компилировалось
    if not bCompile:
        try:
            if expr[0] == '@':
                expr = expr[1:]

            expr = expr.replace('\r\n', '\n').replace('\r', '\n')

            s = compile(expr, '<string>', 'eval')
            ret = eval(s, globSpace, evalSpace)

            if compileKey:
                SetCompileString(compileKey, 'eval', s)

        except:
            try:
                expr += '\n'

                s = compile(expr, '<string>', 'exec')
                exec(s, globSpace, evalSpace)

                if compileKey:
                    SetCompileString(compileKey, 'exec', s)

                if '_resultEval' in evalSpace:
                    ret = evalSpace['_resultEval']

            except:
                bSuccess = 0
                if msg is not None:
                    ret = u'EXEC EXCEPTION IN %s: exec(%s)' % (msg, expr)
                    log.fatal(ret)

    return bSuccess, ret
Пример #26
0
def readAndEvalFile(filename, dictRpl={}, bRefresh=False):
    """
    Функция читает файл и выполняет его.
    
    @type filename: C{string}
    @param filename: Имя ресурсного файла.
    @type dictRpl: C{dictionary}
    @param dictRpl: Словарь замен.
    @type bRefresh: C{bool}
    @param bRefresh: Признак того, что файл надо перечитать даже если он
        буферезирован.
    """
    obj = None

    try:
        #   Проверяем есть ли в буфферном файле такой объект, если есть, то его и возвращаем
        if not bRefresh and filename in Buff_readAndEvalFile:
            return Buff_readAndEvalFile[filename]

        nm = os.path.basename(filename)
        pt = nm.find('.')

        if pt >= 0:
            filepcl = os.path.dirname(
                filename) + '/' + nm[:pt] + '_pkl' + nm[pt:]
        else:
            filepcl = os.path.dirname(filename) + '/' + nm + '_pkl'

        #   Проверяем нужно ли компилировать данную структуру по следующим признакам:
        # наличие скомпилированного файла, по времени последней модификации.
        try:
            if (os.path.isfile(filepcl) and not os.path.isfile(filename)) or \
                    (os.path.getmtime(filename) < os.path.getmtime(filepcl)):
                #   Пытаеся прочитать сохраненную структуру если
                # время последней модификации текстового представления меньше,
                # времени последней модификации транслированного варианта.
                fpcl = None
                try:
                    fpcl = open(filepcl)
                    obj = cPickle.load(fpcl)
                    fpcl.close()

                    #   Сохраняем объект в буфере
                    Buff_readAndEvalFile[filename] = obj

                    log.info(u'Load from <%s>' % filepcl)
                    return obj
                except:
                    if fpcl:
                        fpcl.close()

        except:
            pass

        #   Пытаемся прочитать cPickle, если не удается считаем, что в файле
        #   хранится текст. Читаем его, выполняем, полученный объект сохраняем
        #   на диске для последующего использования
        if os.path.isfile(filename):

            try:
                fpcl = open(filename)
                obj = cPickle.load(fpcl)
                fpcl.close()

                #   Сохраняем объект в буфере
                Buff_readAndEvalFile[filename] = obj

                log.info(u'Load file <cPickle Format> <%s>' % filename)
                return obj
            except:
                log.fatal(u'<Non cPickle Format. Try to compile text>')

        #   Открываем текстовое представление, если его нет, то создаем его
        f = open(filename)
        txt = f.read().replace('\r\n', '\n')
        f.close()

        for key in dictRpl:
            txt = txt.replace(key, dictRpl[key])

        #   Выполняем
        obj = eval(txt)

        #   Сохраняем объект в буфере
        Buff_readAndEvalFile[filename] = obj

        #   Сохраняем транслированный вариант
        fpcl = open(filepcl, 'w')
        log.info(u'create: <%s>' % filepcl)
        cPickle.dump(obj, fpcl, PICKLE_PROTOCOL)
        fpcl.close()

    except IOError:
        log.fatal(u'Ошибка открытия файла <%s>' % filename)
        obj = None
    except:
        log.fatal(u'Ошибка при трансляции файла <%s>' % filename)
        obj = None

    return obj
Пример #27
0
    def generate(self,
                 RepTemplate_,
                 QueryTable_,
                 NameSpace_=None,
                 CoordFill_=None):
        """
        Генерация отчета.
        @param RepTemplate_: Структура шаблона отчета (см. спецификации).
        @param QueryTable_: Таблица запроса. 
            Словарь следующей структуры:
                {
                    '__name__':имя таблицы запроса,
                    '__fields__':[имена полей],
                    '__data__':[список списков значений],
                    '__sub__':{словарь данных подотчетов},
                }.
        @param NameSpace_: Пространство имен шаблона.
            Обычный словарь:
                {
                    'имя переменной': значение переменной, 
                }.
            ВНИМАНИЕ! Этот словарь может передаваться в таблице запроса
                ключ __variables__.
        @param CoordFill_: Координатное заполнение значений ячеек.
            Формат:
                {
                    (Row,Col): 'Значение',
                }.
            ВНИМАНИЕ! Этот словарь может передаваться в таблице запроса
                ключ __coord_fill__.
        @return: Заполненную структуру отчета.
        """
        try:
            # Покоординатная замена значений ячеек
            self._CoordFill = CoordFill_
            if QueryTable_ and '__coord_fill__' in QueryTable_:
                if self._CoordFill is None:
                    self._CoordFill = dict()
                self._CoordFill.update(QueryTable_['__coord_fill__'])

            # Инициализация списка групп
            self._RepGrp = list()

            # I. Определить все бэнды в шаблоне и ячейки сумм
            if isinstance(RepTemplate_, dict):
                self._Template = RepTemplate_
            else:
                # Вывести сообщение об ошибке в лог
                log.warning(u'Ошибка типа шаблона отчета <%s>.' %
                            type(RepTemplate_))
                return None

            # Инициализация имени отчета
            if 'name' in QueryTable_ and QueryTable_['name']:
                # Если таблица запроса именована, то значит это имя готового отчета
                self._RepName = str(QueryTable_['name'])
            elif 'name' in self._Template:
                self._RepName = self._Template['name']

            # Заполнить пространство имен
            self._NameSpace = NameSpace_
            if self._NameSpace is None:
                self._NameSpace = dict()
            self._NameSpace.update(self._Template['variables'])
            if QueryTable_ and '__variables__' in QueryTable_:
                self._NameSpace.update(QueryTable_['__variables__'])
            log.debug(u'Переменные отчета: %s' % self._NameSpace.keys())

            # Библиотека стилей
            self._StyleLib = None
            if 'style_lib' in self._Template:
                self._StyleLib = self._Template['style_lib']

            self._TemplateSheet = self._Template['sheet']
            self._TemplateSheet = self._initSumCells(self._TemplateSheet)

            # II. Инициализация таблицы запроса
            self._QueryTbl = QueryTable_
            # Определить количество записей в таблице запроса
            self._QueryTblRecCount = 0
            if self._QueryTbl and '__data__' in self._QueryTbl:
                self._QueryTblRecCount = len(self._QueryTbl['__data__'])

            # Проинициализировать бенды групп
            for grp in self._Template['groups']:
                grp['old_rec'] = None

            time_start = time.time()
            log.info(u'Отчет <%s>. Запуск генерации' %
                     textfunc.toUnicode(self._RepName))

            # III. Вывод данных в отчет
            # Создать отчет
            self._Rep = copy.deepcopy(IC_REP_TMPL)
            self._Rep['name'] = self._RepName

            # Инициализация необходимых переменных
            field_idx = {}  # Индексы полей
            i = 0
            i_rec = 0
            # Перебор полей таблицы запроса
            if self._QueryTbl and '__fields__' in self._QueryTbl:
                for cur_field in self._QueryTbl['__fields__']:
                    field_idx[cur_field] = i
                    i += 1

            # Если записи в таблице запроса есть, то ...
            if self._QueryTblRecCount:
                # Проинициализировать текущую строку для использования
                # ее в заголовке отчета
                rec = self._QueryTbl['__data__'][i_rec]
                # Заполнить словарь текущей записи
                for field_name in field_idx.keys():
                    val = rec[field_idx[field_name]]
                    # Предгенерация значения данных ячейки
                    self._CurRec[field_name] = val
                # Прописать индекс текущей записи
                self._CurRec['ic_sys_num_rec'] = i_rec

            # Верхний колонтитул
            if self._Template['upper']:
                self._genUpper(self._Template['upper'])

            # Вывести в отчет заголовок
            self._genHeader(self._Template['header'])

            # Главный цикл
            # Перебор записей таблицы запроса
            while i_rec < self._QueryTblRecCount:
                # Обработка групп
                # Проверка смены группы в описании всех групп
                # и найти индекс самой общей смененной группы
                i_grp_out = -1  # индекс самой общей смененной группы
                # Флаг начала генерации (примечания групп не выводяться)
                start_gen = False
                for i_grp in range(len(self._Template['groups'])):
                    grp = self._Template['groups'][i_grp]
                    if grp['old_rec']:
                        # Проверить условие вывода примечания группы
                        if self._CurRec[grp['field']] != grp['old_rec'][
                                grp['field']]:
                            i_grp_out = i_grp
                            break
                    else:
                        i_grp_out = 0
                        start_gen = True
                        break
                if i_grp_out != -1:
                    # Вывести примечания
                    if start_gen is False:
                        for i_grp in range(
                                len(self._Template['groups']) - 1,
                                i_grp_out - 1, -1):
                            grp = self._Template['groups'][i_grp]
                            self._genGrpFooter(grp)
                    # Вывести заголовки
                    for i_grp in range(i_grp_out,
                                       len(self._Template['groups'])):
                        grp = self._Template['groups'][i_grp]
                        grp['old_rec'] = copy.deepcopy(self._CurRec)
                        self._genGrpHeader(grp)

                # Область данных
                self._genDetail(self._Template['detail'])

                # Увеличить суммы суммирующих ячеек
                self._sumIterate(self._TemplateSheet, self._CurRec)

                # Перейти на следующую запись
                i_rec += 1
                # Заполнить словарь текущей записи
                if i_rec < self._QueryTblRecCount:
                    rec = self._QueryTbl['__data__'][i_rec]
                    # Заполнить словарь текущей записи
                    for field_name in field_idx.keys():
                        val = rec[field_idx[field_name]]
                        # Предгенерация значения данных ячейки
                        self._CurRec[field_name] = val
                    # Прописать индекс текущей записи
                    self._CurRec['ic_sys_num_rec'] = i_rec

            # Вывести примечания после области данных
            for i_grp in range(len(self._Template['groups']) - 1, -1, -1):
                grp = self._Template['groups'][i_grp]
                if grp['old_rec']:
                    self._genGrpFooter(grp)
                else:
                    break
            # Вывести в отчет примечание отчета
            self._genFooter(self._Template['footer'])
            # Нижний колонтитул
            if self._Template['under']:
                self._genUnder(self._Template['under'])

            # Параметры страницы
            self._Rep['page_setup'] = self._Template['page_setup']

            # Прогресс бар
            log.info(
                u'Отчет <%s>. Окончание генерации. Время: %d сек.' %
                (textfunc.toUnicode(self._RepName), time.time() - time_start))

            return self._Rep
        except:
            # Вывести сообщение об ошибке в лог
            log.fatal(u'Ошибка генерации отчета.')
            return None