<s> import cgi <EOL> import types <EOL> from itertools import islice <EOL> from collections import Sequence , Mapping , MutableSequence <EOL> _MISSING = object ( ) <EOL> """<STR_LIT>""" <EOL> def to_text ( obj ) : <EOL> try : <EOL> text = unicode ( obj ) <EOL> except : <EOL> try : <EOL> text = unicode ( repr ( obj ) ) <EOL> except : <EOL> text = unicode ( object . __repr__ ( obj ) ) <EOL> return text <EOL> def escape_html ( obj ) : <EOL> text = to_text ( obj ) <EOL> return cgi . escape ( text , quote = True ) <EOL> _DNR = set ( [ types . NoneType , types . BooleanType , types . IntType , types . LongType , <EOL> types . ComplexType , types . FloatType , types . StringType , <EOL> types . UnicodeType , types . NotImplementedType , types . SliceType , <EOL> types . FunctionType , types . MethodType , types . BuiltinFunctionType , <EOL> types . GeneratorType ] ) <EOL> class UnsupportedData ( TypeError ) : <EOL> pass <EOL> class InputType ( object ) : <EOL> def __init__ ( self , * a , ** kw ) : <EOL> pass <EOL> def get_entry_seq ( self , data_seq , headers ) : <EOL> return [ self . get_entry ( entry , headers ) for entry in data_seq ] <EOL> class DictInputType ( InputType ) : <EOL> def check_type ( self , obj ) : <EOL> return isinstance ( obj , Mapping ) <EOL> def guess_headers ( self , obj ) : <EOL> return obj . keys ( ) <EOL> def get_entry ( self , obj , headers ) : <EOL> return [ obj . get ( h ) for h in headers ] <EOL> def get_entry_seq ( self , obj , headers ) : <EOL> return [ [ ci . get ( h ) for h in headers ] for ci in obj ] <EOL> class ObjectInputType ( InputType ) : <EOL> def check_type ( self , obj ) : <EOL> return type ( obj ) not in _DNR and hasattr ( obj , '<STR_LIT>' ) <EOL> def guess_headers ( self , obj ) : <EOL> headers = [ ] <EOL> for attr in dir ( obj ) : <EOL> try : <EOL> val = getattr ( obj , attr ) <EOL> except : <EOL> continue <EOL> if callable ( val ) : <EOL> continue <EOL> headers . append ( attr ) <EOL> return headers <EOL> def get_entry ( self , obj , headers ) : <EOL> values = [ ] <EOL> for h in headers : <EOL> try : <EOL> values . append ( getattr ( obj , h ) ) <EOL> except : <EOL> values . append ( None ) <EOL> return values <EOL> class ListInputType ( InputType ) : <EOL> def check_type ( self , obj ) : <EOL> return isinstance ( obj , MutableSequence ) <EOL> def guess_headers ( self , obj ) : <EOL> return None <EOL> def get_entry ( self , obj , headers ) : <EOL> return obj <EOL> def get_entry_seq ( self , obj_seq , headers ) : <EOL> return obj_seq <EOL> class TupleInputType ( InputType ) : <EOL> def check_type ( self , obj ) : <EOL> return isinstance ( obj , tuple ) <EOL> def guess_headers ( self , obj ) : <EOL> return None <EOL> def get_entry ( self , obj , headers ) : <EOL> return list ( obj ) <EOL> def get_entry_seq ( self , obj_seq , headers ) : <EOL> return [ list ( t ) for t in obj_seq ] <EOL> class NamedTupleInputType ( InputType ) : <EOL> def check_type ( self , obj ) : <EOL> return hasattr ( obj , '<STR_LIT>' ) and isinstance ( obj , tuple ) <EOL> def guess_headers ( self , obj ) : <EOL> return list ( obj . _fields ) <EOL> def get_entry ( self , obj , headers ) : <EOL> return [ getattr ( obj , h , None ) for h in headers ] <EOL> def get_entry_seq ( self , obj_seq , headers ) : <EOL> return [ [ getattr ( obj , h , None ) for h in headers ] for obj in obj_seq ] <EOL> class Table ( object ) : <EOL> _input_types = [ DictInputType ( ) , ListInputType ( ) , <EOL> NamedTupleInputType ( ) , TupleInputType ( ) , <EOL> ObjectInputType ( ) ] <EOL> _html_tr , _html_tr_close = '<STR_LIT>' , '<STR_LIT>' <EOL> _html_th , _html_th_close = '<STR_LIT>' , '<STR_LIT>' <EOL> _html_td , _html_td_close = '<STR_LIT>' , '<STR_LIT>' <EOL> _html_table_tag , _html_table_tag_close = '<STR_LIT>' , '<STR_LIT>' <EOL> def __init__ ( self , data = None , headers = _MISSING ) : <EOL> if headers is _MISSING : <EOL> headers = [ ] <EOL> if data : <EOL> headers , data = list ( data [ <NUM_LIT:0> ] ) , islice ( data , <NUM_LIT:1> , None ) <EOL> self . headers = headers or [ ] <EOL> self . _data = [ ] <EOL> self . _width = <NUM_LIT:0> <EOL> self . extend ( data ) <EOL> def extend ( self , data ) : <EOL> if not data : <EOL> return <EOL> self . _data . extend ( data ) <EOL> self . _set_width ( ) <EOL> self . _fill ( ) <EOL> def _set_width ( self , reset = False ) : <EOL> if reset : <EOL> self . _width = <NUM_LIT:0> <EOL> if self . _width : <EOL> return <EOL> if self . headers : <EOL> self . _width = len ( self . headers ) <EOL> return <EOL> self . _width = max ( [ len ( d ) for d in self . _data ] ) <EOL> def _fill ( self ) : <EOL> width , filler = self . _width , [ None ] <EOL> if not width : <EOL> return <EOL> for d in self . _data : <EOL> rem = width - len ( d ) <EOL> if rem > <NUM_LIT:0> : <EOL> d . extend ( filler * rem ) <EOL> return <EOL> @ classmethod <EOL> def from_dict ( cls , data , headers = _MISSING , max_depth = <NUM_LIT:1> ) : <EOL> return cls . from_data ( data = data , headers = headers , <EOL> max_depth = max_depth , _data_type = DictInputType ( ) ) <EOL> @ classmethod <EOL> def from_list ( cls , data , headers = _MISSING , max_depth = <NUM_LIT:1> ) : <EOL> return cls . from_data ( data = data , headers = headers , <EOL> max_depth = max_depth , _data_type = ListInputType ( ) ) <EOL> @ classmethod <EOL> def from_object ( cls , data , headers = _MISSING , max_depth = <NUM_LIT:1> ) : <EOL> return cls . from_data ( data = data , headers = headers , <EOL> max_depth = max_depth , _data_type = ObjectInputType ( ) ) <EOL> @ classmethod <EOL> def from_data ( cls , data , headers = _MISSING , max_depth = <NUM_LIT:1> , _data_type = None ) : <EOL> if max_depth < <NUM_LIT:1> : <EOL> return cls ( headers = headers ) <EOL> is_seq = isinstance ( data , Sequence ) <EOL> if is_seq : <EOL> if not data : <EOL> return cls ( headers = headers ) <EOL> to_check = data [ <NUM_LIT:0> ] <EOL> if not _data_type : <EOL> for it in cls . _input_types : <EOL> if it . check_type ( to_check ) : <EOL> _data_type = it <EOL> break <EOL> else : <EOL> is_seq = False <EOL> to_check = data <EOL> else : <EOL> if type ( data ) in _DNR : <EOL> return Table ( [ [ data ] ] , headers = headers ) <EOL> to_check = data <EOL> if not _data_type : <EOL> for it in cls . _input_types : <EOL> if it . check_type ( to_check ) : <EOL> _data_type = it <EOL> break <EOL> else : <EOL> raise UnsupportedData ( '<STR_LIT>' <EOL> % type ( data ) ) <EOL> if headers is _MISSING : <EOL> headers = _data_type . guess_headers ( to_check ) <EOL> if is_seq : <EOL> entries = _data_type . get_entry_seq ( data , headers ) <EOL> else : <EOL> entries = [ _data_type . get_entry ( data , headers ) ] <EOL> if max_depth > <NUM_LIT:1> : <EOL> new_max_depth = max_depth - <NUM_LIT:1> <EOL> for i , entry in enumerate ( entries ) : <EOL> for j , cell in enumerate ( entry ) : <EOL> if type ( cell ) in _DNR : <EOL> continue <EOL> try : <EOL> entries [ i ] [ j ] = cls . from_data ( cell , <EOL> max_depth = new_max_depth ) <EOL> except UnsupportedData : <EOL> continue <EOL> return cls ( entries , headers = headers ) <EOL> def __len__ ( self ) : <EOL> return len ( self . _data ) <EOL> def __getitem__ ( self , idx ) : <EOL> return self . _data [ idx ] <EOL> def __repr__ ( self ) : <EOL> cn = self . __class__ . __name__ <EOL> if self . headers : <EOL> return '<STR_LIT>' % ( cn , self . headers , self . _data ) <EOL> else : <EOL> return '<STR_LIT>' % ( cn , self . _data ) <EOL> def to_html ( self , orientation = None , wrapped = True , <EOL> with_headers = True , with_newlines = True , max_depth = <NUM_LIT:1> ) : <EOL> lines = [ ] <EOL> headers = [ ] <EOL> if with_headers and self . headers : <EOL> headers . extend ( self . headers ) <EOL> headers . extend ( [ None ] * ( self . _width - len ( self . headers ) ) ) <EOL> if wrapped : <EOL> lines . append ( self . _html_table_tag ) <EOL> orientation = orientation or '<STR_LIT>' <EOL> ol = orientation [ <NUM_LIT:0> ] . lower ( ) <EOL> if ol == '<STR_LIT:a>' : <EOL> ol = '<STR_LIT:h>' if len ( self ) > <NUM_LIT:1> else '<STR_LIT:v>' <EOL> if ol == '<STR_LIT:h>' : <EOL> self . _add_horizontal_html_lines ( lines , headers = headers , <EOL> max_depth = max_depth ) <EOL> elif ol == '<STR_LIT:v>' : <EOL> self . _add_vertical_html_lines ( lines , headers = headers , <EOL> max_depth = max_depth ) <EOL> else : <EOL> raise ValueError ( "<STR_LIT>" <EOL> "<STR_LIT>" % orientation ) <EOL> if wrapped : <EOL> lines . append ( self . _html_table_tag_close ) <EOL> sep = '<STR_LIT:\n>' if with_newlines else '<STR_LIT>' <EOL> return sep . join ( lines ) <EOL> def get_cell_html ( self , value ) : <EOL> return escape_html ( value ) <EOL> def _add_horizontal_html_lines ( self , lines , headers , max_depth ) : <EOL> to_html = self . get_cell_html <EOL> new_depth = max_depth - <NUM_LIT:1> if max_depth > <NUM_LIT:1> else max_depth <EOL> if max_depth > <NUM_LIT:1> : <EOL> new_depth = max_depth - <NUM_LIT:1> <EOL> if headers : <EOL> _thth = self . _html_th_close + self . _html_th <EOL> lines . append ( self . _html_tr + self . _html_th + <EOL> _thth . join ( [ to_html ( h ) for h in headers ] ) + <EOL> self . _html_th_close + self . _html_tr_close ) <EOL> trtd , _tdtd , _td_tr = ( self . _html_tr + self . _html_td , <EOL> self . _html_td_close + self . _html_td , <EOL> self . _html_td_close + self . _html_tr_close ) <EOL> for row in self . _data : <EOL> if max_depth > <NUM_LIT:1> : <EOL> _fill_parts = [ ] <EOL> for cell in row : <EOL> if isinstance ( cell , Table ) : <EOL> _fill_parts . append ( cell . to_html ( max_depth = new_depth ) ) <EOL> else : <EOL> _fill_parts . append ( to_html ( cell ) ) <EOL> else : <EOL> _fill_parts = [ to_html ( c ) for c in row ] <EOL> lines . append ( '<STR_LIT>' . join ( [ trtd , _tdtd . join ( _fill_parts ) , _td_tr ] ) ) <EOL> def _add_vertical_html_lines ( self , lines , headers , max_depth ) : <EOL> to_html = self . get_cell_html <EOL> new_depth = max_depth - <NUM_LIT:1> if max_depth > <NUM_LIT:1> else max_depth <EOL> tr , th , _th = self . _html_tr , self . _html_th , self . _html_th_close <EOL> td , _tdtd = self . _html_td , self . _html_td_close + self . _html_td <EOL> _td_tr = self . _html_td_close + self . _html_tr_close <EOL> for i in range ( self . _width ) : <EOL> line_parts = [ tr ] <EOL> if headers : <EOL> line_parts . extend ( [ th , to_html ( headers [ i ] ) , _th ] ) <EOL> if max_depth > <NUM_LIT:1> : <EOL> new_depth = max_depth - <NUM_LIT:1> <EOL> _fill_parts = [ ] <EOL> for row in self . _data : <EOL> cell = row [ i ] <EOL> if isinstance ( cell , Table ) : <EOL> _fill_parts . append ( cell . to_html ( max_depth = new_depth ) ) <EOL> else : <EOL> _fill_parts . append ( to_html ( row [ i ] ) ) <EOL> else : <EOL> _fill_parts = [ to_html ( row [ i ] ) for row in self . _data ] <EOL> line_parts . extend ( [ td , _tdtd . join ( _fill_parts ) , _td_tr ] ) <EOL> lines . append ( '<STR_LIT>' . join ( line_parts ) ) <EOL> def to_text ( self , with_headers = True ) : <EOL> lines = [ ] <EOL> widths = [ ] <EOL> headers = self . headers <EOL> for idx in range ( self . _width ) : <EOL> cur_widths = [ len ( unicode ( cur [ idx ] ) ) for cur in self . _data ] <EOL> if with_headers : <EOL> cur_widths . append ( len ( headers [ idx ] ) ) <EOL> widths . append ( max ( cur_widths ) ) <EOL> if with_headers : <EOL> lines . append ( '<STR_LIT>' . join ( [ h . center ( widths [ i ] ) <EOL> for i , h in enumerate ( headers ) ] ) ) <EOL> lines . append ( '<STR_LIT>' . join ( [ '<STR_LIT:->' * w for w in widths ] ) ) <EOL> for row in self . _data : <EOL> lines . append ( '<STR_LIT>' . join ( [ unicode ( col ) . center ( widths [ j ] ) <EOL> for j , col in enumerate ( row ) ] ) ) <EOL> return '<STR_LIT:\n>' . join ( lines ) <EOL> def main ( ) : <EOL> global t3 <EOL> data_dicts = [ { '<STR_LIT:id>' : <NUM_LIT:1> , '<STR_LIT:name>' : '<STR_LIT>' } , <EOL> { '<STR_LIT:id>' : <NUM_LIT:2> , '<STR_LIT:name>' : '<STR_LIT>' } ] <EOL> data_lists = [ [ '<STR_LIT:id>' , '<STR_LIT:name>' ] , <EOL> [ <NUM_LIT:1> , '<STR_LIT>' ] , <EOL> [ <NUM_LIT:2> , '<STR_LIT>' ] ] <EOL> t1 = Table ( data_lists ) <EOL> t2 = Table . from_dict ( data_dicts [ <NUM_LIT:0> ] ) <EOL> t3 = Table . from_dict ( data_dicts ) <EOL> t3 . extend ( [ [ <NUM_LIT:3> , '<STR_LIT>' ] , [ <NUM_LIT:4> ] ] ) <EOL> print t1 <EOL> print t2 <EOL> print t2 . to_html ( ) <EOL> print t3 <EOL> print t3 . to_html ( ) <EOL> print t3 . to_text ( ) <EOL> import re <EOL> t4 = Table . from_object ( re . compile ( '<STR_LIT>' ) ) <EOL> print t4 . to_text ( ) <EOL> import pdb ; pdb . set_trace ( ) <EOL> if __name__ == '<STR_LIT:__main__>' : <EOL> main ( ) </s>
