<s> """<STR_LIT>""" <EOL> from io import StringIO <EOL> import warnings <EOL> import operator <EOL> from functools import partial <EOL> from itertools import groupby <EOL> from . . worksheet import Worksheet <EOL> from . . cell import coordinate_from_string , get_column_letter , Cell <EOL> from . excel import get_sheet_ids <EOL> from . strings import read_string_table <EOL> from . style import read_style_table , NumberFormat <EOL> from . . shared . date_time import SharedDate <EOL> from . worksheet import read_dimension <EOL> from . . shared . ooxml import ( MIN_COLUMN , MAX_COLUMN , PACKAGE_WORKSHEETS , <EOL> MAX_ROW , MIN_ROW , ARC_SHARED_STRINGS , ARC_APP , ARC_STYLE ) <EOL> from xml . etree . cElementTree import iterparse <EOL> from zipfile import ZipFile <EOL> from . . import cell <EOL> import re <EOL> import tempfile <EOL> import zlib <EOL> import zipfile <EOL> import struct <EOL> TYPE_NULL = Cell . TYPE_NULL <EOL> MISSING_VALUE = None <EOL> RE_COORDINATE = re . compile ( '<STR_LIT>' ) <EOL> SHARED_DATE = SharedDate ( ) <EOL> _COL_CONVERSION_CACHE = dict ( ( get_column_letter ( i ) , i ) for i in range ( <NUM_LIT:1> , <NUM_LIT> ) ) <EOL> def column_index_from_string ( str_col , _col_conversion_cache = _COL_CONVERSION_CACHE ) : <EOL> return _col_conversion_cache [ str_col ] <EOL> del _COL_CONVERSION_CACHE <EOL> RAW_ATTRIBUTES = [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] <EOL> try : <EOL> from collections import namedtuple <EOL> BaseRawCell = namedtuple ( '<STR_LIT>' , RAW_ATTRIBUTES ) <EOL> except ImportError : <EOL> warnings . warn ( """<STR_LIT>""" ) <EOL> class BaseRawCell ( object ) : <EOL> def __init__ ( self , * args ) : <EOL> assert len ( args ) == len ( RAW_ATTRIBUTES ) <EOL> for attr , val in zip ( RAW_ATTRIBUTES , args ) : <EOL> setattr ( self , attr , val ) <EOL> def _replace ( self , ** kwargs ) : <EOL> self . __dict__ . update ( kwargs ) <EOL> return self <EOL> class RawCell ( BaseRawCell ) : <EOL> """<STR_LIT>""" <EOL> @ property <EOL> def is_date ( self ) : <EOL> res = ( self . data_type == Cell . TYPE_NUMERIC <EOL> and self . number_format is not None <EOL> and ( '<STR_LIT:d>' in self . number_format <EOL> or '<STR_LIT:m>' in self . number_format <EOL> or '<STR_LIT:y>' in self . number_format <EOL> or '<STR_LIT:h>' in self . number_format <EOL> or '<STR_LIT:s>' in self . number_format <EOL> ) ) <EOL> return res <EOL> def iter_rows ( workbook_name , sheet_name , xml_source , range_string = '<STR_LIT>' , row_offset = <NUM_LIT:0> , column_offset = <NUM_LIT:0> ) : <EOL> archive = get_archive_file ( workbook_name ) <EOL> source = xml_source <EOL> if range_string : <EOL> min_col , min_row , max_col , max_row = get_range_boundaries ( range_string , row_offset , column_offset ) <EOL> else : <EOL> min_col , min_row , max_col , max_row = read_dimension ( xml_source = source ) <EOL> min_col = column_index_from_string ( min_col ) <EOL> max_col = column_index_from_string ( max_col ) + <NUM_LIT:1> <EOL> max_row += <NUM_LIT:6> <EOL> try : <EOL> string_table = read_string_table ( archive . read ( ARC_SHARED_STRINGS ) ) <EOL> except KeyError : <EOL> string_table = { } <EOL> style_table = read_style_table ( archive . read ( ARC_STYLE ) ) <EOL> source . seek ( <NUM_LIT:0> ) <EOL> p = iterparse ( source ) <EOL> return get_squared_range ( p , min_col , min_row , max_col , max_row , string_table , style_table ) <EOL> def get_rows ( p , min_column = MIN_COLUMN , min_row = MIN_ROW , max_column = MAX_COLUMN , max_row = MAX_ROW ) : <EOL> return groupby ( get_cells ( p , min_row , min_column , max_row , max_column ) , operator . attrgetter ( '<STR_LIT>' ) ) <EOL> def get_cells ( p , min_row , min_col , max_row , max_col , _re_coordinate = RE_COORDINATE ) : <EOL> for _event , element in p : <EOL> if element . tag == '<STR_LIT>' : <EOL> coord = element . get ( '<STR_LIT:r>' ) <EOL> column_str , row = _re_coordinate . match ( coord ) . groups ( ) <EOL> row = int ( row ) <EOL> column = column_index_from_string ( column_str ) <EOL> if min_col <= column <= max_col and min_row <= row <= max_row : <EOL> data_type = element . get ( '<STR_LIT:t>' , '<STR_LIT:n>' ) <EOL> style_id = element . get ( '<STR_LIT:s>' ) <EOL> value = element . findtext ( '<STR_LIT>' ) <EOL> yield RawCell ( row , column_str , coord , value , data_type , style_id , None ) <EOL> if element . tag == '<STR_LIT>' : <EOL> continue <EOL> element . clear ( ) <EOL> def get_range_boundaries ( range_string , row = <NUM_LIT:0> , column = <NUM_LIT:0> ) : <EOL> if '<STR_LIT::>' in range_string : <EOL> min_range , max_range = range_string . split ( '<STR_LIT::>' ) <EOL> min_col , min_row = coordinate_from_string ( min_range ) <EOL> max_col , max_row = coordinate_from_string ( max_range ) <EOL> min_col = column_index_from_string ( min_col ) + column <EOL> max_col = column_index_from_string ( max_col ) + column <EOL> min_row += row <EOL> max_row += row <EOL> else : <EOL> min_col , min_row = coordinate_from_string ( range_string ) <EOL> min_col = column_index_from_string ( min_col ) <EOL> max_col = min_col + <NUM_LIT:1> <EOL> max_row = min_row <EOL> return ( min_col , min_row , max_col , max_row ) <EOL> def get_archive_file ( archive_name ) : <EOL> return ZipFile ( archive_name , '<STR_LIT:r>' ) <EOL> def get_xml_source ( archive_file , sheet_name ) : <EOL> return archive_file . read ( '<STR_LIT>' % ( PACKAGE_WORKSHEETS , sheet_name ) ) <EOL> def get_missing_cells ( row , columns ) : <EOL> return dict ( [ ( column , RawCell ( row , column , '<STR_LIT>' % ( column , row ) , MISSING_VALUE , TYPE_NULL , None , None ) ) for column in columns ] ) <EOL> def get_squared_range ( p , min_col , min_row , max_col , max_row , string_table , style_table ) : <EOL> expected_columns = [ get_column_letter ( ci ) for ci in range ( min_col , max_col ) ] <EOL> current_row = min_row <EOL> for row , cells in get_rows ( p , min_row = min_row , max_row = max_row , min_column = min_col , max_column = max_col ) : <EOL> full_row = [ ] <EOL> if current_row < row : <EOL> for gap_row in range ( current_row , row ) : <EOL> dummy_cells = get_missing_cells ( gap_row , expected_columns ) <EOL> yield tuple ( [ dummy_cells [ column ] for column in expected_columns ] ) <EOL> current_row = row <EOL> temp_cells = list ( cells ) <EOL> retrieved_columns = dict ( [ ( c . column , c ) for c in temp_cells ] ) <EOL> missing_columns = list ( set ( expected_columns ) - set ( retrieved_columns . keys ( ) ) ) <EOL> replacement_columns = get_missing_cells ( row , missing_columns ) <EOL> for column in expected_columns : <EOL> if column in retrieved_columns : <EOL> cell = retrieved_columns [ column ] <EOL> if cell . style_id is not None : <EOL> style = style_table [ int ( cell . style_id ) ] <EOL> cell = cell . _replace ( number_format = style . number_format . format_code ) <EOL> if cell . internal_value is not None : <EOL> if cell . data_type == Cell . TYPE_STRING : <EOL> cell = cell . _replace ( internal_value = string_table [ int ( cell . internal_value ) ] ) <EOL> elif cell . data_type == Cell . TYPE_BOOL : <EOL> cell = cell . _replace ( internal_value = cell . internal_value == '<STR_LIT:True>' ) <EOL> elif cell . is_date : <EOL> cell = cell . _replace ( internal_value = SHARED_DATE . from_julian ( float ( cell . internal_value ) ) ) <EOL> elif cell . data_type == Cell . TYPE_NUMERIC : <EOL> cell = cell . _replace ( internal_value = float ( cell . internal_value ) ) <EOL> full_row . append ( cell ) <EOL> else : <EOL> full_row . append ( replacement_columns [ column ] ) <EOL> current_row = row + <NUM_LIT:1> <EOL> yield tuple ( full_row ) <EOL> class IterableWorksheet ( Worksheet ) : <EOL> def __init__ ( self , parent_workbook , title , workbook_name , <EOL> sheet_codename , xml_source ) : <EOL> Worksheet . __init__ ( self , parent_workbook , title ) <EOL> self . _workbook_name = workbook_name <EOL> self . _sheet_codename = sheet_codename <EOL> self . _xml_source = xml_source <EOL> def iter_rows ( self , range_string = '<STR_LIT>' , row_offset = <NUM_LIT:0> , column_offset = <NUM_LIT:0> ) : <EOL> """<STR_LIT>""" <EOL> return iter_rows ( workbook_name = self . _workbook_name , <EOL> sheet_name = self . _sheet_codename , <EOL> xml_source = self . _xml_source , <EOL> range_string = range_string , <EOL> row_offset = row_offset , <EOL> column_offset = column_offset ) <EOL> def cell ( self , * args , ** kwargs ) : <EOL> raise NotImplementedError ( "<STR_LIT>" ) <EOL> def range ( self , * args , ** kwargs ) : <EOL> raise NotImplementedError ( "<STR_LIT>" ) <EOL> def unpack_worksheet ( archive , filename ) : <EOL> temp_file = tempfile . TemporaryFile ( mode = '<STR_LIT>' , prefix = '<STR_LIT>' , suffix = '<STR_LIT>' ) <EOL> zinfo = archive . getinfo ( filename ) <EOL> if zinfo . compress_type == zipfile . ZIP_STORED : <EOL> decoder = None <EOL> elif zinfo . compress_type == zipfile . ZIP_DEFLATED : <EOL> decoder = zlib . decompressobj ( - zlib . MAX_WBITS ) <EOL> else : <EOL> raise zipfile . BadZipFile ( "<STR_LIT>" ) <EOL> archive . fp . seek ( _get_file_offset ( archive , zinfo ) ) <EOL> bytes_to_read = zinfo . compress_size <EOL> while True : <EOL> buff = archive . fp . read ( min ( bytes_to_read , <NUM_LIT> ) ) <EOL> if not buff : <EOL> break <EOL> bytes_to_read -= len ( buff ) <EOL> if decoder : <EOL> buff = decoder . decompress ( buff ) <EOL> temp_file . write ( buff ) <EOL> if decoder : <EOL> temp_file . write ( decoder . decompress ( '<STR_LIT>' ) ) <EOL> return temp_file <EOL> def _get_file_offset ( archive , zinfo ) : <EOL> try : <EOL> return zinfo . file_offset <EOL> except AttributeError : <EOL> archive . fp . seek ( zinfo . header_offset + <NUM_LIT> ) <EOL> file_name_len , extra_len = struct . unpack ( "<STR_LIT>" , archive . fp . read ( <NUM_LIT:4> ) ) <EOL> return zinfo . header_offset + <NUM_LIT:30> + file_name_len + extra_len </s>
