Home > Enterprise >  AtributeError: can't set attribute for python list property
AtributeError: can't set attribute for python list property

Time:12-17

I'm working with the python-docx library from a forked version, and I'm having an issue with editing the elements list as it is defined as a property.

# docx.document.Document
@property
def elements(self):
    return self._body.elements

I tried to go with the solution mentioned here but the error AtributeError: can't set attribute still popping out.
Next thing I tried is adding the setter to the attribute derived from self._body and editing the code:

# docx.blkcntnr.BlockItemContainer

@property
def elements(self):
    """
    A list containing the elements in this container (paragraph and tables), in document order.
    """
    return [element(item,self.part) for item in self._element.getchildren()]

I've tried to add the setter in both levels but ended up again with the error AtributeError: can't set attribute

The setter I wrote:

@elements.setter
def elements(self, value):
    return value 

The implementation I tired:

elements_list = docx__document.elements
elem_list = []
docx__document.elements = elements_list = elem_list

The main problem with that code is docx__document.elements still contains all the elements that are supposed to have been deleted!

Editing the library was like this:

# Inside docx.document.Document
@property
def elements(self):
    return self._body.elements

@elements.setter
def elements(self, value=None):
    self._body.elements = value
    gc.collect()
    return value

The other part:

# Inside docx.blkcntnr.BlockItemContainer

@property
def elements(self):
    """
    A list containing the elements in this container (paragraph and tables), in document order.
    """
    return [element(item,self.part) for item in self._element.getchildren()]


@elements.setter
def elements(self, value):
    """
    A list containing the elements in this container (paragraph and tables), in document order.
    """
    return value

Related question [Update]


If I did add a setter for this property :

# docx.document.Document

@property
def elements(self):
    return self._body.elements

Should I add also a setter for the property:

# docx.blkcntnr.BlockItemContainer

@property
def elements(self):
    """
    A list containing the elements in this container (paragraph and tables), in document order.
    """
    return [element(item,self.part) for item in self._element.getchildren()]

Because the value of document.elemetns is actually the value from document._body.elements, am I right?

Any help would appreciate it!

CodePudding user response:

First a word of warning: if you edit a library, those changes will be wiped away if/when you upgrade the library.

While your question is still not reproducible, I can see now what the problem is.

Setters need to mutate some kind of state to be useful. They don't return values.

# Inside docx.document.Document

@elements.setter
def elements(self, value):
    self._body.elements = value


# Inside docx.blkcntnr.BlockItemContainer

@elements.setter
def elements(self, value):
    # FIXME

Unfortunately, I haven't been able to figure out how to implement docx.blkcntnr.BlockItemContainer.elements.setter in a way that neatly replaces the XML tree.

Since it looks like you want to use it to wipe a document clear, why not simply instantiate a new Document instead, like so?

docx__document = docx.Document()
  • Related