コード例 #1
0
class OermDataBase(object):

	def __init__(self, inputfile):

		self.filename		= inputfile
		self.lines			= []
		self.current_line	= 0
		self.current_page	= ""
		self.block			= Block()

	def __enter__(self):

		try:
			self.open_file = open(self.filename, mode="rb")

			struct_fmt	= ">4sB"
			struct_len = struct.calcsize(struct_fmt)
			data = self.open_file.read(struct_len)

			struct_unpack	= struct.Struct(struct_fmt).unpack_from
			magic_number	= struct_unpack(data)[0].decode("utf-8")
			# version			= struct_unpack(data)[1]

			if magic_number != "oerm":
				raise ValueError(_('{0} no es un archivo oerm válido!').format(self.filename))

		except Exception as err:
			print(_("Error al abrir el archivo: {0}").format(err))
			return None

		return self

	def __exit__(self, *args):
		self.open_file.close()
		return True

	def __iter__(self):
		return self

	def __next__(self):

		struct_fmt = '>L'
		struct_len = struct.calcsize(struct_fmt)
		struct_unpack = struct.Struct(struct_fmt).unpack_from

		data = self.open_file.read(struct_len)
		if not data:
			raise StopIteration

		longitud_bloque = struct_unpack(data)[0]

		self.open_file.seek(self.open_file.tell()-struct_len)
		data = self.open_file.read(longitud_bloque)
		if not data:
			raise StopIteration

		return self.block.load(data)
コード例 #2
0
class Report(object):
    """Clase para el manejo de un Reporte OERM.

	Args:
		database: Objeto :class:`openerm.Database`
		idrpt (int): Identificador único del reporte en el Database

	Example:
		>>> fuerom openerm.Database import Database
		>>> from openerm.Report import Report
		>>> db = Database(file = "out/zstd-level-3-1-22.test.oerm", mode="rb")
		>>> r = Report(db, 1)
		>>> for page in r:
		...     print(page[0:10])
		...
		Pagina 1 -
		Pagina 2 -
		Pagina 3 -
		Pagina 4 -
		Pagina 5 -
		Pagina 6 -
		Pagina 7 -
		Pagina 8 -
		Pagina 9 -
		Pagina 10
		Pagina 11

	**data**:
		========= ================================================
		Tipo	  Detalle
		========= ================================================
		int       Id del reporte
		string    Nombre del reporte
		long      Offset al contenedor de metadatos
		long      Max cantidad de páginas en los PageContainers
		long      Offset al primer PageContainer
		list      Lista de Offsets a los PageContainers
		========= ================================================

	"""

    # def __init__(self, file, data):
    def __init__(self, database, idrpt):

        data = (idrpt, ) + database.Index.reports[idrpt]

        self.file = database._file
        self.id = data[0]  #: id del reporte
        self.nombre = data[1]  #: Nombre del reporte
        self.metadata_offset = data[2]
        self.max_pages_in_container = data[3]
        self.first_p_container = data[4]
        self.containers_offset = data[5]
        self.total_containers = len(self.containers_offset)
        self.current_page = 1
        self.current_container = -1
        self.current_block_data = None
        self.block = Block()
        self.pagecontainer = PageContainer()
        self.metadatacontainer = MetadataContainer()
        self.metadata = {}  #: Metadatos del reporte
        self.total_pages = 0  #: Cantidad total de páginas del reporte

        self._get_report_data()

    def _get_block_data_from_container(self, container):

        container_offset = self.containers_offset[container]
        return self._get_block_data_from_offset(container_offset)

    def __len__(self):
        return self.total_pages

    def __iter__(self):
        return self

    def __next__(self):
        p = self.get_page(self.current_page)
        if not p:
            self.current_page = 1
            raise StopIteration
        else:
            self.current_page += 1
        return p

    def __str__(self):
        return "Report: {0} ".format(self.nombre)

    def get_page(self, pagenum):
        """Retorna una pagina del reporte

		Args:
			pagenum(int): Número de página

		Example:
			>>> from openerm.Database import Database
			>>> from openerm.Report import Report
			>>> db = Database(file = "out/zstd-level-3-1-22.test.oerm", mode="rb")
			>>> r = Report(db, 1)
			>>> p = r.get_page(5)
			>>> print(p[0:30])
			Pagina 5 -----------------
			ZSV
			>>>

		Return:
			string: Texto completo de la página

		"""
        container = int((pagenum - 1) / self.max_pages_in_container)
        if container > self.total_containers - 1:
            return None

        if container != self.current_container:
            self.current_block_data = self._get_block_data_from_container(
                container)
            # (longitud_bloque, tipo_bloque, tipo_compresion, tipo_encriptacion, longitud_datos, data, variable_data)
            self.pagecontainer.load(
                (self.current_block_data[5], self.current_block_data[6]))
            self.current_container = container

        relative_pagenum = pagenum - (container * self.max_pages_in_container)

        return self.pagecontainer.get_page(relative_pagenum)

    def _get_report_data(self):

        # La cantidad de contenedores - 1 por la cantidad de paginas x contenedor da el primer número
        last_container_offset = self.total_containers - 1
        total = (self.total_containers - 1) * self.max_pages_in_container
        # Leer el último contenedor para saber cuantas páginas quedaron en él
        data = self._get_block_data_from_container(last_container_offset)
        self.pagecontainer.load((data[5], data[6]))
        total += len(self.pagecontainer)

        self.total_pages = total

        # Metadatos
        _, _, tipo_compresion, _, _, data, _ = self._get_block_data_from_offset(
            self.metadata_offset)
        self.metadata = self.metadatacontainer.load(data)
        self.__dict__.update(self.metadata)

    def _get_block_data_from_offset(self, container_offset):

        self.file.seek(container_offset)

        struct_fmt = '>L'
        struct_len = struct.calcsize(struct_fmt)
        struct_unpack = struct.Struct(struct_fmt).unpack_from

        data = self.file.read(struct_len)
        if not data:
            return None

        longitud_bloque = struct_unpack(data)[0]

        self.file.seek(self.file.tell() - struct_len)
        data = self.file.read(longitud_bloque)
        if not data:
            return None

        # (longitud_bloque, tipo_bloque, tipo_compresion, tipo_encriptacion, longitud_datos, data, variable_data)
        return self.block.load(data)

    def find_text(self, text):
        """Búsqueda de un texto dentro del reporte

		Args:
			text (string): Patrón de texto a buscar

		Example:
			>>> from openerm.Database import Database
			>>> from openerm.Report import Report
			>>> db = Database(file = "out/.sin_compression_sin_encriptacion.oerm")
			>>> r = Report(db, 1)
			>>> report.find_text("IWY3")
			[(2, 10, 991, 'AGH8B2NULTCTJ0L-[IWY3]-4K6D8RRBYCRQCH')]

		Return:
			Lista de reportes y páginas
				* Reporte id
				* Página
				* Posición en la página
				* Extracto de la ocurrencia a modo de ejemplo
		"""
        def sample(find, text, pos, lfind):

            start = pos - 15
            end = pos + lfind + 15

            if start < 0:
                start = 0

            if end > len(text):
                end = len(text)

            return text[start:pos] + "-[" + find + "]-" + text[pos + lfind +
                                                               1:end]

        lfind = len(text)
        ocurrences = []
        for np in range(1, self.total_pages + 1):
            p = self.get_page(np)
            if p:
                pos = p.find(text)
                while pos >= 0:
                    sampletext = sample(text, p, pos, lfind)
                    ocurrences.append(
                        (self.id, np, pos, sampletext.replace("\n", "")))
                    pos = p.find(text, pos + 1)

        return ocurrences