<s> from __future__ import ( <EOL> absolute_import , <EOL> division , <EOL> print_function , <EOL> unicode_literals , <EOL> ) <EOL> import xml . sax . saxutils <EOL> from pydocx . constants import TWIPS_PER_POINT <EOL> from pydocx . exceptions import MalformedDocxException <EOL> from pydocx . export . numbering_span import ( <EOL> NumberingItem , <EOL> NumberingSpan , <EOL> NumberingSpanBuilder , <EOL> ) <EOL> from pydocx . openxml import wordprocessing , vml <EOL> from pydocx . openxml . packaging import WordprocessingDocument <EOL> class PyDocXExporter ( object ) : <EOL> numbering_span_builder_class = NumberingSpanBuilder <EOL> def __init__ ( self , path ) : <EOL> self . path = path <EOL> self . _document = None <EOL> self . _page_width = None <EOL> self . first_pass = False <EOL> self . footnote_tracker = [ ] <EOL> self . captured_runs = None <EOL> self . complex_field_runs = [ ] <EOL> self . node_type_to_export_func_map = { <EOL> wordprocessing . Document : self . export_document , <EOL> wordprocessing . Body : self . export_body , <EOL> wordprocessing . Paragraph : self . export_paragraph , <EOL> wordprocessing . Run : self . export_run , <EOL> wordprocessing . Text : self . export_text , <EOL> wordprocessing . Hyperlink : self . export_hyperlink , <EOL> wordprocessing . Break : self . export_break , <EOL> wordprocessing . NoBreakHyphen : self . export_no_break_hyphen , <EOL> wordprocessing . Table : self . export_table , <EOL> wordprocessing . TableRow : self . export_table_row , <EOL> wordprocessing . TableCell : self . export_table_cell , <EOL> wordprocessing . Drawing : self . export_drawing , <EOL> wordprocessing . SmartTagRun : self . export_smart_tag_run , <EOL> wordprocessing . InsertedRun : self . export_inserted_run , <EOL> wordprocessing . Picture : self . export_picture , <EOL> wordprocessing . DeletedRun : self . export_deleted_run , <EOL> wordprocessing . DeletedText : self . export_deleted_text , <EOL> wordprocessing . FootnoteReference : self . export_footnote_reference , <EOL> wordprocessing . Footnote : self . export_footnote , <EOL> wordprocessing . FootnoteReferenceMark : self . export_footnote_reference_mark , <EOL> wordprocessing . SdtRun : self . export_sdt_run , <EOL> wordprocessing . SdtContentRun : self . export_sdt_content_run , <EOL> wordprocessing . SdtBlock : self . export_sdt_block , <EOL> wordprocessing . SdtContentBlock : self . export_sdt_content_block , <EOL> wordprocessing . TabChar : self . export_tab_char , <EOL> wordprocessing . FieldChar : self . export_field_char , <EOL> wordprocessing . FieldCode : self . export_field_code , <EOL> wordprocessing . SimpleField : self . export_simple_field , <EOL> vml . Shape : self . export_vml_shape , <EOL> vml . ImageData : self . export_vml_image_data , <EOL> wordprocessing . EmbeddedObject : self . export_embedded_object , <EOL> NumberingSpan : self . export_numbering_span , <EOL> NumberingItem : self . export_numbering_item , <EOL> } <EOL> self . field_type_to_export_func_map = { <EOL> '<STR_LIT>' : getattr ( self , '<STR_LIT>' , None ) , <EOL> } <EOL> @ property <EOL> def document ( self ) : <EOL> if not self . _document : <EOL> self . document = self . load_document ( ) <EOL> return self . _document <EOL> @ document . setter <EOL> def document ( self , document ) : <EOL> self . _document = document <EOL> def load_document ( self ) : <EOL> self . document = WordprocessingDocument ( path = self . path ) <EOL> return self . document <EOL> @ property <EOL> def main_document_part ( self ) : <EOL> return self . document . main_document_part <EOL> @ property <EOL> def style_definitions_part ( self ) : <EOL> if self . main_document_part : <EOL> return self . main_document_part . style_definitions_part <EOL> @ property <EOL> def numbering_definitions_part ( self ) : <EOL> if self . main_document_part : <EOL> return self . main_document_part . numbering_definitions_part <EOL> def export ( self ) : <EOL> if self . main_document_part is None : <EOL> raise MalformedDocxException <EOL> document = self . main_document_part . document <EOL> if document : <EOL> self . first_pass = True <EOL> self . _first_pass_export ( ) <EOL> self . _post_first_pass_processing ( ) <EOL> self . first_pass = False <EOL> for result in self . export_node ( document ) : <EOL> yield result <EOL> def _first_pass_export ( self ) : <EOL> document = self . main_document_part . document <EOL> if document : <EOL> for result in self . export_node ( document ) : <EOL> pass <EOL> def _post_first_pass_processing ( self ) : <EOL> self . _convert_complex_fields_into_simple_fields ( ) <EOL> def _convert_complex_fields_into_simple_fields ( self ) : <EOL> if not self . complex_field_runs : <EOL> return <EOL> fields = [ ] <EOL> field = None <EOL> separate_triggered = False <EOL> previous_run = None <EOL> runs_to_remove_by_field = { } <EOL> runs_to_remove = set ( ) <EOL> for run in self . complex_field_runs : <EOL> for child in run . children : <EOL> if field is not None and previous_run is not None : <EOL> if previous_run . parent is not run . parent : <EOL> runs_to_remove_by_field [ field ] = runs_to_remove <EOL> runs_to_remove = set ( ) <EOL> fields . append ( field ) <EOL> field = wordprocessing . SimpleField ( instr = field . instr , children = [ ] ) <EOL> if isinstance ( child , wordprocessing . FieldChar ) : <EOL> separate_triggered = False <EOL> runs_to_remove . add ( run ) <EOL> if child . is_type_begin ( ) : <EOL> field = wordprocessing . SimpleField ( children = [ ] ) <EOL> elif child . is_type_end ( ) : <EOL> if field is not None : <EOL> runs_to_remove_by_field [ field ] = runs_to_remove <EOL> runs_to_remove = set ( ) <EOL> fields . append ( field ) <EOL> field = None <EOL> elif child . is_type_separate ( ) : <EOL> separate_triggered = True <EOL> if field is None : <EOL> pass <EOL> elif separate_triggered : <EOL> field . children . append ( run ) <EOL> runs_to_remove . add ( run ) <EOL> elif isinstance ( child , wordprocessing . FieldCode ) : <EOL> field . instr = child . content <EOL> runs_to_remove . add ( run ) <EOL> previous_run = run <EOL> for field in fields : <EOL> runs_to_remove = runs_to_remove_by_field . get ( field , set ( ) ) <EOL> if not field . children : <EOL> continue <EOL> first_run = field . children [ <NUM_LIT:0> ] <EOL> previous_parent_new_children = [ ] <EOL> for child in first_run . parent . children : <EOL> if child is first_run : <EOL> previous_parent_new_children . append ( field ) <EOL> elif child not in runs_to_remove : <EOL> previous_parent_new_children . append ( child ) <EOL> first_run . parent . children = previous_parent_new_children <EOL> field . parent = first_run . parent <EOL> for run in field . children : <EOL> run . parent = field <EOL> def export_node ( self , node ) : <EOL> caller = self . node_type_to_export_func_map . get ( type ( node ) ) <EOL> if callable ( caller ) : <EOL> results = caller ( node ) <EOL> if results is not None : <EOL> for result in results : <EOL> yield result <EOL> @ property <EOL> def page_width ( self ) : <EOL> if self . _page_width is None : <EOL> page_width = self . calculate_page_width ( ) <EOL> if page_width is None : <EOL> page_width = <NUM_LIT:0> <EOL> self . _page_width = page_width <EOL> return self . _page_width <EOL> def calculate_page_width ( self ) : <EOL> document = self . main_document_part . document <EOL> try : <EOL> page_size = document . body . final_section_properties . page_size <EOL> except AttributeError : <EOL> page_size = None <EOL> if page_size : <EOL> width = page_size . get ( '<STR_LIT:w>' ) <EOL> if not width : <EOL> return <EOL> try : <EOL> width = int ( float ( width ) ) <EOL> except ValueError : <EOL> return <EOL> return width / TWIPS_PER_POINT <EOL> def export_document ( self , document ) : <EOL> return self . export_node ( document . body ) <EOL> def yield_nested ( self , iterable , func ) : <EOL> for item in iterable : <EOL> for result in func ( item ) : <EOL> yield result <EOL> def yield_nested_with_line_breaks_between_paragraphs ( self , iterable , func ) : <EOL> '''<STR_LIT>''' <EOL> br = wordprocessing . Break ( ) <EOL> previous_was_paragraph = False <EOL> previous_was_empty = True <EOL> for item in iterable : <EOL> empty = True <EOL> is_paragraph = isinstance ( item , wordprocessing . Paragraph ) <EOL> for result in func ( item ) : <EOL> if empty : <EOL> empty = False <EOL> if is_paragraph and previous_was_paragraph and not previous_was_empty : <EOL> for br_result in func ( br ) : <EOL> yield br_result <EOL> yield result <EOL> previous_was_paragraph = is_paragraph <EOL> if not empty : <EOL> previous_was_empty = empty <EOL> def yield_numbering_spans ( self , items ) : <EOL> if self . first_pass : <EOL> for item in items : <EOL> yield item <EOL> return <EOL> builder = self . numbering_span_builder_class ( items ) <EOL> numbering_spans = builder . get_numbering_spans ( ) <EOL> for item in numbering_spans : <EOL> yield item <EOL> def export_body ( self , body ) : <EOL> children = self . yield_body_children ( body ) <EOL> return self . yield_nested ( children , self . export_node ) <EOL> def yield_body_children ( self , body ) : <EOL> return self . yield_numbering_spans ( body . children ) <EOL> def export_paragraph ( self , paragraph ) : <EOL> children = self . yield_paragraph_children ( paragraph ) <EOL> results = self . yield_nested ( children , self . export_node ) <EOL> if paragraph . effective_properties : <EOL> results = self . export_paragraph_apply_properties ( paragraph , results ) <EOL> return results <EOL> def yield_paragraph_children ( self , paragraph ) : <EOL> for child in paragraph . children : <EOL> yield child <EOL> def get_paragraph_styles_to_apply ( self , paragraph ) : <EOL> properties = paragraph . effective_properties <EOL> property_rules = [ <EOL> ( properties . justification , self . export_paragraph_property_justification ) , <EOL> ( True , self . export_paragraph_property_indentation ) , <EOL> ] <EOL> for actual_value , handler in property_rules : <EOL> if actual_value : <EOL> yield handler <EOL> def export_paragraph_property_justification ( self , paragraph , results ) : <EOL> return results <EOL> def export_paragraph_property_indentation ( self , paragraph , results ) : <EOL> return results <EOL> def export_paragraph_apply_properties ( self , paragraph , results ) : <EOL> styles_to_apply = self . get_paragraph_styles_to_apply ( paragraph ) <EOL> for func in styles_to_apply : <EOL> results = func ( paragraph , results ) <EOL> return results <EOL> def export_break ( self , br ) : <EOL> pass <EOL> def export_run ( self , run ) : <EOL> if self . first_pass : <EOL> if self . captured_runs is not None : <EOL> self . captured_runs . append ( run ) <EOL> results = self . yield_nested ( run . children , self . export_node ) <EOL> if run . effective_properties : <EOL> results = self . export_run_apply_properties ( run , results ) <EOL> return results <EOL> def get_run_styles_to_apply ( self , run ) : <EOL> properties = run . effective_properties <EOL> property_rules = [ <EOL> ( properties . bold , self . export_run_property_bold ) , <EOL> ( properties . italic , self . export_run_property_italic ) , <EOL> ( properties . underline , self . export_run_property_underline ) , <EOL> ( properties . caps , self . export_run_property_caps ) , <EOL> ( properties . small_caps , self . export_run_property_small_caps ) , <EOL> ( properties . strike , self . export_run_property_strike ) , <EOL> ( properties . dstrike , self . export_run_property_dstrike ) , <EOL> ( properties . vanish , self . export_run_property_vanish ) , <EOL> ( properties . hidden , self . export_run_property_hidden ) , <EOL> ( properties . vertical_align , self . export_run_property_vertical_align ) , <EOL> ] <EOL> for actual_value , handler in property_rules : <EOL> if actual_value : <EOL> yield handler <EOL> def export_run_apply_properties ( self , run , results ) : <EOL> styles_to_apply = self . get_run_styles_to_apply ( run ) <EOL> applied_styles = set ( ) <EOL> for func in styles_to_apply : <EOL> if func not in applied_styles : <EOL> results = func ( run , results ) <EOL> applied_styles . add ( func ) <EOL> return results <EOL> def export_run_property_bold ( self , run , results ) : <EOL> return results <EOL> def export_run_property_italic ( self , run , results ) : <EOL> return results <EOL> def export_run_property_underline ( self , run , results ) : <EOL> return results <EOL> def export_run_property_caps ( self , run , results ) : <EOL> return results <EOL> def export_run_property_small_caps ( self , run , results ) : <EOL> return results <EOL> def export_run_property_strike ( self , run , results ) : <EOL> return results <EOL> def export_run_property_dstrike ( self , run , results ) : <EOL> return results <EOL> def export_run_property_vanish ( self , run , results ) : <EOL> return results <EOL> def export_run_property_hidden ( self , run , results ) : <EOL> return results <EOL> def export_run_property_vertical_align ( self , run , results ) : <EOL> return results <EOL> def export_hyperlink ( self , hyperlink ) : <EOL> return self . yield_nested ( hyperlink . children , self . export_node ) <EOL> def export_text ( self , text ) : <EOL> if not text . text : <EOL> yield '<STR_LIT>' <EOL> else : <EOL> yield self . escape ( text . text ) <EOL> def export_deleted_text ( self , deleted_text ) : <EOL> pass <EOL> def export_no_break_hyphen ( self , hyphen ) : <EOL> yield '<STR_LIT:->' <EOL> def export_table ( self , table ) : <EOL> return self . yield_nested ( table . rows , self . export_node ) <EOL> def export_table_row ( self , table_row ) : <EOL> return self . yield_nested ( table_row . cells , self . export_node ) <EOL> def export_table_cell ( self , table_cell ) : <EOL> numbering_spans = self . yield_numbering_spans ( table_cell . children ) <EOL> return self . yield_nested ( numbering_spans , self . export_node ) <EOL> def escape ( self , text ) : <EOL> return xml . sax . saxutils . quoteattr ( text ) [ <NUM_LIT:1> : - <NUM_LIT:1> ] <EOL> def export_drawing ( self , drawing ) : <EOL> pass <EOL> def export_smart_tag_run ( self , smart_tag ) : <EOL> return self . yield_nested ( smart_tag . children , self . export_node ) <EOL> def export_inserted_run ( self , inserted_run ) : <EOL> return self . yield_nested ( inserted_run . children , self . export_node ) <EOL> def export_picture ( self , picture ) : <EOL> return self . yield_nested ( picture . children , self . export_node ) <EOL> def export_deleted_run ( self , deleted_run ) : <EOL> return self . yield_nested ( deleted_run . children , self . export_node ) <EOL> def export_footnote_reference ( self , footnote_reference ) : <EOL> if self . first_pass : <EOL> return <EOL> if footnote_reference . footnote is None : <EOL> return <EOL> self . footnote_tracker . append ( footnote_reference ) <EOL> footnote_index = len ( self . footnote_tracker ) <EOL> yield '<STR_LIT>' . format ( footnote_index ) <EOL> def export_footnote ( self , footnote ) : <EOL> return self . yield_nested ( footnote . children , self . export_node ) <EOL> def export_footnotes ( self ) : <EOL> if not self . footnote_tracker : <EOL> return <EOL> for footnote_reference in self . footnote_tracker : <EOL> footnote = footnote_reference . footnote <EOL> if footnote : <EOL> for result in self . export_node ( footnote ) : <EOL> yield result <EOL> def export_footnote_reference_mark ( self , footnote_reference_mark ) : <EOL> pass <EOL> def export_vml_shape ( self , shape ) : <EOL> return self . yield_nested ( shape . children , self . export_node ) <EOL> def export_embedded_object ( self , obj ) : <EOL> return self . yield_nested ( obj . children , self . export_node ) <EOL> def export_vml_image_data ( self , image_data ) : <EOL> pass <EOL> def export_sdt ( self , sdt ) : <EOL> return self . export_node ( sdt . content ) <EOL> def export_sdt_content ( self , sdt_content ) : <EOL> return self . yield_nested ( sdt_content . children , self . export_node ) <EOL> def export_sdt_run ( self , sdt_run ) : <EOL> return self . export_sdt ( sdt_run ) <EOL> def export_sdt_content_run ( self , sdt_content_run ) : <EOL> return self . export_sdt_content ( sdt_content_run ) <EOL> def export_sdt_block ( self , sdt_block ) : <EOL> return self . export_sdt ( sdt_block ) <EOL> def export_sdt_content_block ( self , sdt_content_block ) : <EOL> return self . export_sdt_content ( sdt_content_block ) <EOL> def export_tab_char ( self , tab_char ) : <EOL> pass <EOL> def export_numbering_span ( self , numbering_span ) : <EOL> return self . yield_nested ( numbering_span . children , self . export_node ) <EOL> def export_numbering_item ( self , numbering_item ) : <EOL> return self . yield_nested ( numbering_item . children , self . export_node ) <EOL> def export_simple_field ( self , simple_field ) : <EOL> default_results = self . yield_nested ( simple_field . children , self . export_node ) <EOL> parsed_instr = simple_field . parse_instr ( ) <EOL> if not parsed_instr : <EOL> return default_results <EOL> field_type , field_args = parsed_instr <EOL> func = self . field_type_to_export_func_map . get ( field_type , None ) <EOL> if callable ( func ) : <EOL> return func ( simple_field , field_args ) <EOL> return default_results <EOL> def export_field_char ( self , field_char ) : <EOL> if self . first_pass : <EOL> if field_char . is_type_begin ( ) : <EOL> self . captured_runs = [ field_char . parent ] <EOL> elif field_char . is_type_end ( ) and self . captured_runs is not None : <EOL> self . complex_field_runs . extend ( self . captured_runs ) <EOL> self . captured_runs = None <EOL> return <EOL> def export_field_code ( self , field_code ) : <EOL> pass </s>
