pythonpython-3.xpylatex

Attribute error when working with 'self' and 'with'


I'm working on a Python script to generate a report in PDF using PyLatex. I set up a class ReportGeneration.

Inside, a table 'overview_table' is defined. When I try to work with table from 2 functions, it gives me the error: AttributeError: args

A small snippet of the init method:

self.doc = Document()
self.doc.documentclass = Command(
   'documentclass',
    options=['12pt'],
    arguments=['article']
    )
# Set up preamble (cannot share code)
self.overview_table = self.doc.create(LongTable("| l | l | l |")) 

The first function, that works perfectly when called is as follows:

    def set_up_overview(self):
        with self.doc.create(Section('Overview')):
            self.doc.append(Command('centering'))
            with self.overview_table as table:
                table.add_hline()
                table.add_row(bold("Index"), bold("File Name"), bold("Result"))
                table.add_hline()
                table.end_table_header()

The second function is as follows:

    def add_data_to_report(self):
        with self.overview_table as overview_table:
            overview_table.add_hline()

Calling the second function crashes the program. I've tried searching for similar errors, but the closest I could get was that __enter__ was not defined. I'm not sure how to proceed from there.

The complete error message is

  File "/Users/user/IdeaProjects/report/src/reportgen.py", line 46, in add_data_to_report
    with self.overview_table as overview_table:
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/contextlib.py", line 133, in __enter__
    del self.args, self.kwds, self.func
AttributeError: args

It'll be great help if someone can explain what went wrong. Thanks!


Solution

  • It seems that the pylatex package has used the @contextlib.contextmanager decorator on the create method.

        @contextmanager
        def create(self, child):
            """Add a LaTeX object to current container, context-manager style.
            Args
            ----
            child: `~.Container`
                An object to be added to the current container
            """
    
            prev_data = self.data
            self.data = child.data  # This way append works appends to the child
    
            yield child  # allows with ... as to be used as well
    
            self.data = prev_data
            self.append(child)
    

    As mentioned in the contextlib documentation,

    The function being decorated must return a generator-iterator when called. This iterator must yield exactly one value, which will be bound to the targets in the with statement’s as clause, if any.

    This means that you can use the returned value from the create function only once in a context as you have done.

    I would recommend you do one of