class TestOutputErrorFunctions(unittest.TestCase):

    def setUp(self):
        # Instantiate an Output Error object
        self.error = OutputError("This is an output error.")

    def tearDown(self):
        # Release instantiated objects
        del self.error

    def test_init(self):
        self.assertEqual(self.error.msg, "This is an output error.")
        self.assertIsNone(self.error.expr)
        # The caller is the OutputError instantiation of the setUp() function, so please update these lines if needed
        self.assertEqual(self.error.frame_info.filename, utest_path + 'test_utils_error_handling.py')
        self.assertEqual(self.error.frame_info.lineno, 86)
        self.assertEqual(self.error.frame_info.function, 'setUp')
        self.assertListEqual(self.error.frame_info.code_context, ['        self.error = OutputError("This is an output error.")\n'])

    def test_str(self):
        self.assertEqual(str(self.error), "  File \"" + utest_path + "test_utils_error_handling.py\", line 86, in setUp" + EOL + "    Error: This is an output error.")

    def test_handle(self):
        test = False
        try:
            print
            self.error.handle()
        except SystemExit:
            test = True
        self.assertTrue(test)
Example #2
0
class TestOutputErrorFunctions(unittest.TestCase):
    def setUp(self):
        # Instantiate an Output Error object
        self.error = OutputError("This is an output error.")

    def tearDown(self):
        # Release instantiated objects
        del self.error

    def test_init(self):
        self.assertEqual(self.error.msg, "This is an output error.")
        self.assertIsNone(self.error.expr)
        # The caller is the OutputError instantiation of the setUp() function, so please update these lines if needed
        self.assertEqual(self.error.frame_info.filename,
                         utest_path + 'test_utils_error_handling.py')
        self.assertEqual(self.error.frame_info.lineno, 86)
        self.assertEqual(self.error.frame_info.function, 'setUp')
        self.assertListEqual(
            self.error.frame_info.code_context,
            ['        self.error = OutputError("This is an output error.")\n'])

    def test_str(self):
        self.assertEqual(
            str(self.error), "  File \"" + utest_path +
            "test_utils_error_handling.py\", line 86, in setUp" + EOL +
            "    Error: This is an output error.")

    def test_handle(self):
        test = False
        try:
            print
            self.error.handle()
        except SystemExit:
            test = True
        self.assertTrue(test)
Example #3
0
def odt_write(object, filename, introduction=None, lmf2odt=lmf_to_odt, items=lambda lexical_entry: lexical_entry.get_lexeme(), sort_order=None, paradigms=False, reverse=False):
    """! @brief Write a document file.
    @param object The LMF instance to convert into document output format.
    @param filename The name of the document file to write with full path, for instance 'user/output.odt'.
    @param introduction The name of the text file with full path containing the introduction of the document, for instance 'user/config/introduction.txt'. Default value is None.
    @param lmf2odt A function giving the mapping from LMF representation information that must be written to ODT commands, in a defined order. Default value is 'lmf_to_odt' function defined in 'pylmflib/config/odt.py'. Please refer to it as an example.
    @param items Lambda function giving the item to sort. Default value is 'lambda lexical_entry: lexical_entry.get_lexeme()', which means that the items to sort are lexemes.
    @param sort_order Python list. Default value is 'None', which means that the document output is alphabetically ordered.
    @param paradigms A boolean value to introduce paradigms in document or not.
    @param reverse A boolean value to set if a reverse dictionary is wanted.
    """
    import string
    if sort_order is None:
        # Lowercase and uppercase letters must have the same rank
        sort_order = dict([(c, ord(c)) for c in string.lowercase])
        up = dict([(c, ord(c) + 32) for c in string.uppercase])
        sort_order.update(up)
        sort_order.update({'':0, ' ':0})
    textdoc = OpenDocumentText()
    # Styles
    s = textdoc.styles
    h1style = Style(name="Heading 1", family="paragraph")
    h1style.addElement(TextProperties(attributes={'fontsize':"24pt", 'fontweight':"bold" }))
    s.addElement(h1style)
    # An automatic style
    boldstyle = Style(name="Bold", family="text")
    boldprop = TextProperties(fontweight="bold", fontname="Arial", fontsize="8pt")
    boldstyle.addElement(boldprop)
    textdoc.automaticstyles.addElement(boldstyle)
    # Parse LMF values
    if object.__class__.__name__ == "LexicalResource":
        for lexicon in object.get_lexicons():
            # Document title
            h = H(outlinelevel=1, stylename=h1style, text=lexicon.get_id())
            textdoc.text.addElement(h)
            # Plain paragraph
            p = P(text=lexicon.get_label())
            # Text
            boldpart = Span(stylename=boldstyle, text="Test. ")
            p.addElement(boldpart)
            # Introduction
            if introduction is not None:
                p.addText(file_read(introduction))
                textdoc.text.addElement(p)
            # Page break
            #
            # Text body
            lmf2odt(lexicon, textdoc, items, sort_order, paradigms, reverse)
    else:
        raise OutputError(object, "Object to write must be a Lexical Resource.")
    textdoc.save(filename)
Example #4
0
def doc_write(object,
              filename,
              introduction=None,
              lmf2doc=lmf_to_doc,
              items=lambda lexical_entry: lexical_entry.get_lexeme(),
              sort_order=None,
              paradigms=False,
              reverse=False):
    """! @brief Write a document file.
    @param object The LMF instance to convert into document output format.
    @param filename The name of the document file to write with full path, for instance 'user/output.doc'.
    @param introduction The name of the text file with full path containing the introduction of the document, for instance 'user/config/introduction.txt'. Default value is None.
    @param lmf2doc A function giving the mapping from LMF representation information that must be written to docx commands, in a defined order. Default value is 'lmf_to_doc' function defined in 'pylmflib/config/doc.py'. Please refer to it as an example.
    @param items Lambda function giving the item to sort. Default value is 'lambda lexical_entry: lexical_entry.get_lexeme()', which means that the items to sort are lexemes.
    @param sort_order Python list. Default value is 'None', which means that the document output is alphabetically ordered.
    @param paradigms A boolean value to introduce paradigms in document or not.
    @param reverse A boolean value to set if a reverse dictionary is wanted.
    """
    import string
    if sort_order is None:
        # Lowercase and uppercase letters must have the same rank
        sort_order = dict([(c, ord(c)) for c in string.lowercase])
        up = dict([(c, ord(c) + 32) for c in string.uppercase])
        sort_order.update(up)
        sort_order.update({'': 0, ' ': 0})
    document = Document()
    # Adjust margins to 1 cm
    section = document.sections[0]
    section.top_margin = Cm(1)
    section.bottom_margin = Cm(1)
    section.left_margin = Cm(1)
    section.right_margin = Cm(1)
    # Parse LMF values
    if object.__class__.__name__ == "LexicalResource":
        for lexicon in object.get_lexicons():
            # Document title
            document.add_heading(lexicon.get_id(), 0)
            # Plain paragraph
            document.add_paragraph(lexicon.get_label())
            # Page break
            document.add_page_break()
            # Introduction
            if introduction is not None:
                document.add_paragraph(file_read(introduction))
            # Text body
            lmf2doc(lexicon, document, items, sort_order, paradigms, reverse)
    else:
        raise OutputError(object,
                          "Object to write must be a Lexical Resource.")
    document.save(filename)
Example #5
0
def mdf_write(object, filename, lmf2mdf=lmf_mdf, order=mdf_order):
    """! @brief Write an MDF file.
    @param object The LMF instance to convert into MDF output format.
    @param filename The name of the MDF file to write with full path, for instance 'user/output.txt'.
    @param lmf2mdf A Python dictionary describing the mapping between LMF representation and MDF markers. Default value is 'lmf_mdf' dictionary defined in 'pylmflib/config/mdf.py'. Please refer to it as an example.
    @param order A Python list defining the order in which MDF markers must be written, for instance ["lx", "ps"]. Default value is 'mdf_order' list defined in 'pylmflib/config/mdf.py'.
    """
    mdf_file = open_write(filename)
    # For each MDF marker, get the corresponding LMF value
    if object.__class__.__name__ == "Lexicon":
        for lexical_entry in object.get_lexical_entries():
            for marker in order:
                if type(marker) is list:
                    # Parse group of markers
                    parse_list(mdf_file, lmf2mdf, marker, lexical_entry)
                else:
                    value = lmf2mdf[marker](lexical_entry)
                    write_line(mdf_file, marker, value)
            # Separate lexical entries from each others with a blank line
            mdf_file.write(EOL)
    else:
        raise OutputError(object, "Object to write must be a Lexicon.")
    mdf_file.close()
Example #6
0
def lmf_to_doc(lexicon, document, items=lambda lexical_entry: lexical_entry.get_lexeme(), sort_order=None, paradigms=False, reverse=False):
    """! @brief Function to convert LMF lexical entry information to be written into docx commands.
    @param lexicon The Lexicon LMF instance to display.
    @param document The docx document to fill in.
    @param items Lambda function giving the item to sort. Default value is 'lambda lexical_entry: lexical_entry.get_lexeme()', which means that the items to sort are lexemes.
    @param sort_order Python list. Default value is 'None', which means that the document output is alphabetically ordered.
    @param paradigms A boolean value to introduce paradigms in document or not.
    @param reverse A boolean value to set if a reverse dictionary is wanted.
    """
    # Lexicon is already ordered
    level = 0
    previous_character = ''
    current_character = ''
    for lexical_entry in lexicon.get_lexical_entries():
        if type(sort_order) is type(dict()) or type(sort_order) is type(lambda l:l):
            # Check if current element is a lexeme starting with a different character than previous lexeme
            try:
                current_character = items(lexical_entry)[0]
                if sort_order[items(lexical_entry)[0:1]]:
                    current_character = items(lexical_entry)[0:1]
                if sort_order[items(lexical_entry)[0:2]]:
                    current_character = items(lexical_entry)[0:2]
            except IndexError:
                pass
            except KeyError:
                pass
            except TypeError:
                pass
            try:
                if ( (type(sort_order) is not type(dict())) and ((previous_character == '') or (sort_order(current_character) != sort_order(previous_character))) ) \
                    or ( (type(sort_order) is type(dict())) and (int(sort_order[current_character]) != int(sort_order[previous_character])) ):
                    # Do not consider special characters
                    if previous_character != '':
                        document.add_page_break()
                    previous_character = current_character
                    title = ''
                    if type(sort_order) is not type(dict()):
                        title += ' ' + current_character
                    else:
                        for key,value in sorted(sort_order.items(), key=lambda x: x[1]):
                            if int(value) == int(sort_order[current_character]):
                                title += ' ' + key
                    document.add_heading("-" + title + " -".decode(ENCODING), level=level+1)
            except KeyError:
                print Warning("Cannot sort item %s" % items(lexical_entry).encode(ENCODING))
            except IndexError:
                # Item is an empty string
                pass
        else:
            raise OutputError(object, "Sort order must be a dictionary.")
        if not reverse:
            # Lexeme
            lexeme = lexical_entry.get_lexeme()
            if lexical_entry.get_homonymNumber() is not None:
                # Add homonym number to lexeme
                lexeme += " (" + str(lexical_entry.get_homonymNumber()) + ")"
            # Add morphology if any
            morph = ""
            for morphology in lexical_entry.get_morphologies():
                morph += " " + morphology
            # Add dialect if any
            dialect = ""
            for sense in lexical_entry.get_senses():
                for usage_note in sense.find_usage_notes(language=config.xml.vernacular):
                    dialect += " [" + usage_note + "]"
            p = document.add_paragraph()
            p.add_run(lexeme).bold = True
            if morph != "":
                p.add_run(" Morph. :").italic = True
            p.add_run(morph)
            p.add_run(dialect)
            # Dialectal variants
            write_title = True
            for repr in lexical_entry.get_form_representations():
                if repr.get_geographicalVariant() is not None:
                    if write_title:
                        p.add_run(" Var. : ")
                        write_title = False
                    else:
                        p.add_run(" ; ")
                    p.add_run(repr.get_geographicalVariant()).bold = True
                    if repr.get_dialect() is not None:
                        p.add_run(" [" + repr.get_dialect() + "]")
            # Part of speech in italic
            if lexical_entry.get_partOfSpeech() is not None:
                p.add_run(". ")
                p.add_run(lexical_entry.get_partOfSpeech()).italic = True
            p.add_run(".")
            # Note grammaticale
            if len(lexical_entry.find_notes(type="grammar")) != 0:
                p = document.add_paragraph()
                p.add_run("  ")
                p.add_run("[Note grammaticale :")
                for note in lexical_entry.find_notes(type="grammar", language=config.xml.regional):
                    p.add_run(" ")
                    p.add_run(note).bold = True
                try:
                    for note in lexical_entry.find_notes(type="grammar", language=config.xml.French):
                        p.add_run(" ")
                        p.add_run(note)
                except AttributeError:
                    for note in lexical_entry.find_notes(type="grammar", language=config.xml.English):
                        p.add_run(" ")
                        p.add_run(note)
                for note in lexical_entry.find_notes(type="grammar", language=config.xml.vernacular):
                    p.add_run(" ")
                    p.add_run(note)
                for note in lexical_entry.find_notes(type="grammar", language=config.xml.national):
                    p.add_run(" ")
                    p.add_run(note)
                # Italic
                for note in lexical_entry.find_notes(type="grammar"):
                    p.add_run(" ")
                    p.add_run(note).italic = True
                p.add_run("].")
            for sense in lexical_entry.get_senses():
                # Glosses
                glosses = ""
                if sense.get_senseNumber() is not None:
                    p = document.add_paragraph()
                    p.add_run("  " + sense.get_senseNumber() + ")")
                for gloss in sense.find_glosses(language=config.xml.vernacular):
                    glosses += " " + gloss + "."
                if glosses == "":
                    glosses = glosses.rstrip(".")
                try:
                    for gloss in sense.find_glosses(language=config.xml.French):
                        glosses += " " + gloss + "."
                except AttributeError:
                    for gloss in sense.find_glosses(language=config.xml.English):
                        glosses += " " + gloss + "."
                glosses = glosses.rstrip(".")
                if glosses != "" and glosses[-1] != '.' and glosses[-1] != '!' and glosses[-1] != '?':
                    glosses += "."
                p.add_run(glosses)
                # Scientific name
                if lexical_entry.get_scientific_name() is not None:
                    p.add_run(" ")
                    p.add_run(lexical_entry.get_scientific_name()).italic = True
                    p.add_run(".")
                # Examples
                for context in sense.get_contexts():
                    p = document.add_paragraph()
                    examples = ""
                    vernacular_forms = context.find_written_forms(language=config.xml.vernacular)
                    for example in vernacular_forms:
                        p.add_run("  ")
                        p.add_run(example.split('[')[0]).bold = True
                        for element in example.split('[')[1:]:
                            p.add_run('[' + element)
                    try:
                        fra_forms = context.find_written_forms(language=config.xml.French)
                        if len(vernacular_forms) != 0 and len(fra_forms) != 0:
                            p.add_run(" ")
                        for example in fra_forms:
                            p.add_run(example)
                        if len(fra_forms) != 0 and fra_forms[0][-1] != '!' and fra_forms[0][-1] != '?':
                            p.add_run(".")
                    except AttributeError:
                        pass
                # Links
                if len(lexical_entry.get_related_forms("simple link")) != 0:
                    p = document.add_paragraph()
                    p.add_run("  Voir :").italic = True
                    for related_form in lexical_entry.get_related_forms("simple link"):
                        if related_form.get_lexical_entry() is not None:
                            # TODO : hyperlink
                            pass
                        p.add_run(" ")
                        p.add_run(related_form.get_lexeme().split('[')[0]).bold = True
                        for element in related_form.get_lexeme().split('[')[1:]:
                            p.add_run('[' + element)
                        try:
                            for written_form in related_form.find_written_forms(language=config.xml.French):
                                p.add_run(" " + written_form)
                        except AttributeError:
                            for written_form in related_form.find_written_forms(language=config.xml.English):
                                p.add_run(" " + written_form)
                    p.add_run(".")
                # Notes
                if len(lexical_entry.find_notes(type="general")) != 0:
                    p = document.add_paragraph()
                    p.add_run("  ")
                    p.add_run("[Note :")
                    for note in lexical_entry.find_notes(type="general"):
                        p.add_run(" ")
                        p.add_run(note)
                    p.add_run("].")
                # Note phonologique
                if len(lexical_entry.find_notes(type="phonology")) != 0:
                    p = document.add_paragraph()
                    p.add_run("  ")
                    p.add_run("[Note phonologique :")
                    for note in lexical_entry.find_notes(type="phonology"):
                        p.add_run(" ")
                        p.add_run(note)
                    p.add_run("].")
                # Note anthropologique
                if len(lexical_entry.find_notes(type="anthropology")) != 0:
                    p = document.add_paragraph()
                    p.add_run("  ")
                    p.add_run("[Note anthropologique :")
                    for note in lexical_entry.find_notes(type="anthropology"):
                        p.add_run(" ")
                        p.add_run(note)
                        p.add_run("].")
            if paradigms:
                if len(lexical_entry.get_word_forms()) != 0:
                    # Intense quote
                    document.add_paragraph('Paradigms', style='IntenseQuote')
                    # Table
                    table = document.add_table(rows=1, cols=2)
                    hdr_cells = table.rows[0].cells
                    hdr_cells[0].text = 'Paradigm'
                    hdr_cells[1].text = 'Form'
                for item in lexical_entry.find_paradigms(grammatical_number=pd_grammaticalNumber["sg"]):
                    row_cells = table.add_row().cells
                    row_cells[0].text = "sg"
                    row_cells[1].text = item
                for item in lexical_entry.find_paradigms(grammatical_number=pd_grammaticalNumber["pl"]):
                    row_cells = table.add_row().cells
                    row_cells[0].text = "pl"
                    row_cells[1].text = item
                for item in lexical_entry.find_paradigms(person=pd_person[1], grammatical_number=pd_grammaticalNumber['s']):
                    row_cells = table.add_row().cells
                    row_cells[0].text = "1s"
                    row_cells[1].text = item
                for item in lexical_entry.find_paradigms(person=pd_person[2], grammatical_number=pd_grammaticalNumber['s']):
                    row_cells = table.add_row().cells
                    row_cells[0].text = "2s"
                    row_cells[1].text = item
                for item in lexical_entry.find_paradigms(person=pd_person[3], grammatical_number=pd_grammaticalNumber['s']):
                    row_cells = table.add_row().cells
                    row_cells[0].text = "3s"
                    row_cells[1].text = item
                for item in lexical_entry.find_paradigms(anymacy=pd_anymacy[4], grammatical_number=pd_grammaticalNumber['s']):
                    row_cells = table.add_row().cells
                    row_cells[0].text = "4s"
                    row_cells[1].text = item
                for item in lexical_entry.find_paradigms(person=pd_person[1], grammatical_number=pd_grammaticalNumber['d']):
                    row_cells = table.add_row().cells
                    row_cells[0].text = "1d"
                    row_cells[1].text = item
                for item in lexical_entry.find_paradigms(person=pd_person[2], grammatical_number=pd_grammaticalNumber['d']):
                    row_cells = table.add_row().cells
                    row_cells[0].text = "2d"
                    row_cells[1].text = item
                for item in lexical_entry.find_paradigms(person=pd_person[3], grammatical_number=pd_grammaticalNumber['d']):
                    row_cells = table.add_row().cells
                    row_cells[0].text = "3d"
                    row_cells[1].text = item
                for item in lexical_entry.find_paradigms(anymacy=pd_anymacy[4], grammatical_number=pd_grammaticalNumber['d']):
                    row_cells = table.add_row().cells
                    row_cells[0].text = "4d"
                    row_cells[1].text = item
                for item in lexical_entry.find_paradigms(person=pd_person[1], grammatical_number=pd_grammaticalNumber['p']):
                    row_cells = table.add_row().cells
                    row_cells[0].text = "1p"
                    row_cells[1].text = item
                for item in lexical_entry.find_paradigms(person=pd_person[1], grammatical_number=pd_grammaticalNumber['p'], clusivity=pd_clusivity['e']):
                    row_cells = table.add_row().cells
                    row_cells[0].text = "1e"
                    row_cells[1].text = item
                for item in lexical_entry.find_paradigms(person=pd_person[1], grammatical_number=pd_grammaticalNumber['p'], clusivity=pd_clusivity['i']):
                    row_cells = table.add_row().cells
                    row_cells[0].text = "1i"
                    row_cells[1].text = item
                for item in lexical_entry.find_paradigms(person=pd_person[2], grammatical_number=pd_grammaticalNumber['p']):
                    row_cells = table.add_row().cells
                    row_cells[0].text = "2p"
                    row_cells[1].text = item
                for item in lexical_entry.find_paradigms(person=pd_person[3], grammatical_number=pd_grammaticalNumber['p']):
                    row_cells = table.add_row().cells
                    row_cells[0].text = "3p"
                    row_cells[1].text = item
                for item in lexical_entry.find_paradigms(anymacy=pd_anymacy[4], grammatical_number=pd_grammaticalNumber['p']):
                    row_cells = table.add_row().cells
                    row_cells[0].text = "4p"
                    row_cells[1].text = item
                if len(lexical_entry.get_word_forms()) != 0:
                    p = document.add_paragraph()
            # Handle subentries
            for related_form in lexical_entry.get_related_forms("subentry"):
                if related_form.get_lexical_entry() is not None:
                    p = document.add_paragraph()
                    p.add_run("  ")
                    p.add_run(related_form.get_lexeme().split('[')[0]).bold = True
                    for element in related_form.get_lexeme().split('[')[1:]:
                        p.add_run('[' + element.replace("GO(s)", "GOs").replace("GO(n)", "GOn").replace("WEM", "WE"))
                    for sense in related_form.get_lexical_entry().get_senses():
                        glosses = ""
                        for gloss in sense.find_glosses(language=config.xml.vernacular):
                            glosses += " " + gloss + "."
                        if glosses == "":
                            glosses = glosses.rstrip(".")
                        try:
                            for gloss in sense.find_glosses(language=config.xml.French):
                                glosses += " " + gloss + "."
                        except AttributeError:
                            for gloss in sense.find_glosses(language=config.xml.English):
                                glosses += " " + gloss + "."
                        if glosses == "":
                            glosses = glosses.rstrip(".")
                        p.add_run(glosses)
            p.add_run(EOL)
        else: # reverse
            # English gloss
            is_gloss = False
            for sense in lexical_entry.get_senses():
                for gloss in sense.find_glosses(language=config.xml.English):
                    if not is_gloss:
                        # Paragraph
                        p = document.add_paragraph()
                        # Write gloss in bold, except characters that are between brackets or square brackets
                        brackets = 0
                        bold = True
                        for c in gloss:
                            if c == '(' or c == '[':
                                # Write following characters in non-bold
                                brackets += 1
                                if brackets > 0:
                                    bold = False
                                else:
                                    bold = True
                                p.add_run(c).bold = bold
                            elif c == ')' or c == ']':
                                # Write following characters in bold
                                p.add_run(c).bold = bold
                                brackets -= 1
                                if brackets > 0:
                                    bold = False
                                else:
                                    bold = True
                            else:
                                p.add_run(c).bold = bold
                        if gloss[-1] != '?' and gloss[-1] != '!' and gloss[-1] != '.':
                            p.add_run(".")
                        p.add_run(" ")
                        is_gloss = True
            if is_gloss:
                # Scientific name
                if lexical_entry.get_scientific_name() is not None:
                    p.add_run(lexical_entry.get_scientific_name()).italic = True
                    p.add_run(". ")
                # Lexeme
                p.add_run(lexical_entry.get_lexeme())
                if lexical_entry.get_lexeme()[-1] != '?' and lexical_entry.get_lexeme()[-1] != '!' and lexical_entry.get_lexeme()[-1] != '.':
                    p.add_run(".")
Example #7
0
 def setUp(self):
     # Instantiate an Output Error object
     self.error = OutputError("This is an output error.")
Example #8
0
def tex_write(object,
              filename,
              preamble=None,
              introduction=None,
              lmf2tex=lmf_to_tex,
              font=None,
              items=lambda lexical_entry: lexical_entry.get_lexeme(),
              sort_order=None,
              paradigms=[],
              tables=[],
              title=None,
              tex_language=None):
    """! @brief Write a LaTeX file.
    Note that the lexicon must already be ordered at this point. Here, parameters 'items' and 'sort_order' are only used to define chapters.
    @param object The LMF instance to convert into LaTeX output format.
    @param filename The name of the LaTeX file to write with full path, for instance 'user/output.tex'.
    @param preamble The name of the LaTeX file with full path containing the LaTeX header of the document, for instance 'user/config/japhug.tex'. Default value is None.
    @param introduction The name of the LaTeX file with full path containing the LaTeX introduction of the document, for instance 'user/config/introduction.tex'. Default value is None.
    @param lmf2tex A function giving the mapping from LMF representation information that must be written to LaTeX commands, in a defined order. Default value is 'lmf_to_tex' function defined in 'pylmflib/config/tex.py'. Please refer to it as an example.
    @param font A Python dictionary giving the vernacular, national, regional fonts to apply to a text in LaTeX format.
    @param items Lambda function giving the item to sort. Default value is 'lambda lexical_entry: lexical_entry.get_lexeme()', which means that the items to sort are lexemes.
    @param sort_order Default value is 'None', which means that the LaTeX output is alphabetically ordered.
    @param paradigms A Python list of LaTeX filenames with full path containing the paradigms in LaTeX format. Default value is an empty list.
    @param tables The name of the LaTeX file with full path containing some notes to add at the end of the LaTeX document, for instance 'user/config/conclusion.tex'. Default value is None.
    @param title A Python string containing the title of the LaTeX document. Default value is None.
    @param tex_language A Python string giving the default language to set in LaTeX.
    """
    import string, os
    # Define font
    if font is None:
        font = config.xml.font
    tex_file = open_write(filename)
    # Add file header if any
    tex_file.write(file_read(preamble))
    # Continue the header if needed
    if title is not None:
        tex_file.write("\\title{" + unicode(title, "utf-8") + "}" + EOL)
    if tex_language is not None:
        tex_file.write("\setdefaultlanguage{" + tex_language + "}" + EOL)
    # Insert LaTeX commands to create a document
    tex_file.write(EOL + "\\begin{document}" + EOL)
    tex_file.write("\\maketitle" + EOL)
    tex_file.write("\\newpage" + EOL)
    # Add introduction if any
    if introduction is not None:
        tex_file.write("\\markboth{INTRODUCTION}{}" + EOL * 2)
    tex_file.write(file_read(introduction))
    # Add command for small caps
    tex_file.write(EOL + "\\def\\mytextsc{\\bgroup\\obeyspaces\\mytextscaux}" +
                   EOL)
    tex_file.write(
        "\\def\\mytextscaux#1{\\mytextscauxii #1\\relax\\relax\\egroup}" + EOL)
    tex_file.write("\\def\\mytextscauxii#1{%" + EOL)
    tex_file.write(
        "\\ifx\\relax#1\\else \\ifcat#1\\@sptoken{} \\expandafter\\expandafter\\expandafter\\mytextscauxii\\else"
        + EOL)
    tex_file.write(
        "\\ifnum`#1=\\uccode`#1 {\\normalsize #1}\\else {\\footnotesize \\uppercase{#1}}\\fi \\expandafter\\expandafter\\expandafter\\mytextscauxii\\expandafter\\fi\\fi}"
        + EOL * 2)
    # Configure space indent
    tex_file.write("\\setlength\\parindent{0cm}" + EOL)
    # Insert data path configuration
    # Unix-style paths
    audio_path = config.xml.audio_path
    graphic_path = os.path.abspath('.')
    if os.name != 'posix':
        # Windows-style paths
        audio_path = audio_path.replace("\\", "/")
        graphic_path = graphic_path.replace("\\", "/")
    tex_file.write(EOL + "\\addmediapath{" + audio_path.rstrip("/") + "}" +
                   EOL)
    tex_file.write("\\addmediapath{" + audio_path + "mp3}" + EOL)
    tex_file.write("\\addmediapath{" + audio_path + "wav}" + EOL)
    tex_file.write("\\graphicspath{{" + graphic_path +
                   "/pylmflib/output/img/}}" + EOL * 2)
    # Configure 2 columns
    tex_file.write("\\newpage" + EOL)
    tex_file.write("\\begin{multicols}{2}" + EOL * 2)
    if sort_order is None:
        # Lowercase and uppercase letters must have the same rank
        sort_order = dict([(c, ord(c)) for c in string.lowercase])
        up = dict([(c, ord(c) + 32) for c in string.uppercase])
        sort_order.update(up)
        sort_order.update({'': 0, ' ': 0})
    # For each element to write, get the corresponding LMF value
    if object.__class__.__name__ == "LexicalResource":
        for lexicon in object.get_lexicons():
            previous_character = ''
            current_character = ''
            # Lexicon is already ordered
            for lexical_entry in lexicon.get_lexical_entries():
                # Consider only main entries (subentries and components will be written as parts of the main entry)
                if lexical_entry.find_related_forms(
                        "main entry"
                ) == [] and lexical_entry.get_independentWord() is not False:
                    # Check if current element is a lexeme starting with a different character than previous lexeme
                    try:
                        current_character = items(lexical_entry)[0]
                        if sort_order[items(lexical_entry)[0:1]]:
                            current_character = items(lexical_entry)[0:1]
                        if sort_order[items(lexical_entry)[0:2]]:
                            current_character = items(lexical_entry)[0:2]
                    except IndexError:
                        pass
                    except KeyError:
                        pass
                    except TypeError:
                        pass
                    try:
                        if ( (type(sort_order) is not type(dict())) and ((previous_character == '') or (sort_order(current_character) != sort_order(previous_character))) ) \
                            or ( (type(sort_order) is type(dict())) and (int(sort_order[current_character]) != int(sort_order[previous_character])) ):
                            # Do not consider special characters
                            previous_character = current_character
                            tex_file.write("\\newpage" + EOL)
                            title = ''
                            if type(sort_order) is not type(dict()):
                                title += ' ' + font[NATIONAL](
                                    current_character)
                            else:
                                for key, value in sorted(sort_order.items(),
                                                         key=lambda x: x[1]):
                                    if int(value) == int(
                                            sort_order[current_character]):
                                        title += ' ' + font[VERNACULAR](key)
                            tex_file.write("\\section*{\\centering-" +
                                           handle_reserved(title) + " -}" +
                                           EOL)
                            #tex_file.write("\\pdfbookmark[1]{" + title + " }{" + title + " }" + EOL)
                        tex_file.write(lmf2tex(lexical_entry, font))
                        if len(paradigms) != 0:
                            tex_file.write(insert_references(lexical_entry))
                        # tex_file.write("\\lhead{\\firstmark}" + EOL)
                        # tex_file.write("\\rhead{\\botmark}" + EOL)
                        # Separate lexical entries from each others with a blank line
                        tex_file.write(EOL)
                        # Handle subentries
                        for related_form in lexical_entry.get_related_forms(
                                "subentry"):
                            if related_form.get_lexical_entry() is not None:
                                tex_file.write(
                                    lmf2tex(related_form.get_lexical_entry(),
                                            font))
                                if len(paradigms) != 0:
                                    tex_file.write(
                                        insert_references(
                                            related_form.get_lexical_entry()))
                                # Separate sub-entries from each others with a blank line
                                tex_file.write(EOL)
                    except KeyError:
                        print Warning("Cannot sort item %s" %
                                      items(lexical_entry).encode(ENCODING))
                    except IndexError:
                        # Item is an empty string
                        pass
    else:
        raise OutputError(object,
                          "Object to write must be a Lexical Resource.")
    # Insert LaTeX commands to finish the document properly
    tex_file.write("\end{multicols}" + EOL)
    # Insert paradigms if any
    for filename in paradigms:
        tex_file.write(EOL)
        tex_file.write("\\newpage" + EOL)
        tex_file.write("\markboth{paradigms}{}" + EOL)
        tex_file.write(file_read(filename))
        tex_file.write(EOL)
    # Insert other tables if any
    for filename in tables:
        tex_file.write(EOL)
        tex_file.write("\\newpage" + EOL)
        tex_file.write(file_read(filename))
        tex_file.write(EOL)
    tex_file.write("\end{document}" + EOL)
    tex_file.close()
 def setUp(self):
     # Instantiate an Output Error object
     self.error = OutputError("This is an output error.")