Home > Blockchain >  Attribute error when working with 'self' and 'with'
Attribute error when working with 'self' and 'with'

Time:11-27

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!

CodePudding user response:

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

  • do everything you want to do with the overview_table inside a single context (that would be inside the initial set_up_overview function in your case)
  • take a look at the pylatex documentation and see if you can use the values they have set using self.append(child) in the create method
  • add the yielded object as an attribute on your class
  • Related