# encoding: utf-8 """ Custom element classes related to the numbering part """ from . import OxmlElement from .shared import CT_DecimalNumber from .simpletypes import ST_DecimalNumber from .xmlchemy import ( BaseOxmlElement, OneAndOnlyOne, RequiredAttribute, ZeroOrMore, ZeroOrOne ) class CT_Num(BaseOxmlElement): """ ```` element, which represents a concrete list definition instance, having a required child that references an abstract numbering definition that defines most of the formatting details. """ abstractNumId = OneAndOnlyOne('w:abstractNumId') lvlOverride = ZeroOrMore('w:lvlOverride') numId = RequiredAttribute('w:numId', ST_DecimalNumber) def add_lvlOverride(self, ilvl): """ Return a newly added CT_NumLvl () element having its ``ilvl`` attribute set to *ilvl*. """ return self._add_lvlOverride(ilvl=ilvl) @classmethod def new(cls, num_id, abstractNum_id): """ Return a new ```` element having numId of *num_id* and having a ```` child with val attribute set to *abstractNum_id*. """ num = OxmlElement('w:num') num.numId = num_id abstractNumId = CT_DecimalNumber.new( 'w:abstractNumId', abstractNum_id ) num.append(abstractNumId) return num class CT_NumLvl(BaseOxmlElement): """ ```` element, which identifies a level in a list definition to override with settings it contains. """ startOverride = ZeroOrOne('w:startOverride', successors=('w:lvl',)) ilvl = RequiredAttribute('w:ilvl', ST_DecimalNumber) def add_startOverride(self, val): """ Return a newly added CT_DecimalNumber element having tagname ``w:startOverride`` and ``val`` attribute set to *val*. """ return self._add_startOverride(val=val) class CT_NumPr(BaseOxmlElement): """ A ```` element, a container for numbering properties applied to a paragraph. """ ilvl = ZeroOrOne('w:ilvl', successors=( 'w:numId', 'w:numberingChange', 'w:ins' )) numId = ZeroOrOne('w:numId', successors=('w:numberingChange', 'w:ins')) # @ilvl.setter # def _set_ilvl(self, val): # """ # Get or add a child and set its ``w:val`` attribute to *val*. # """ # ilvl = self.get_or_add_ilvl() # ilvl.val = val # @numId.setter # def numId(self, val): # """ # Get or add a child and set its ``w:val`` attribute to # *val*. # """ # numId = self.get_or_add_numId() # numId.val = val class CT_Numbering(BaseOxmlElement): """ ```` element, the root element of a numbering part, i.e. numbering.xml """ num = ZeroOrMore('w:num', successors=('w:numIdMacAtCleanup',)) def add_num(self, abstractNum_id): """ Return a newly added CT_Num () element referencing the abstract numbering definition identified by *abstractNum_id*. """ next_num_id = self._next_numId num = CT_Num.new(next_num_id, abstractNum_id) return self._insert_num(num) def num_having_numId(self, numId): """ Return the ```` child element having ``numId`` attribute matching *numId*. """ xpath = './w:num[@w:numId="%d"]' % numId try: return self.xpath(xpath)[0] except IndexError: raise KeyError('no element with numId %d' % numId) @property def _next_numId(self): """ The first ``numId`` unused by a ```` element, starting at 1 and filling any gaps in numbering between existing ```` elements. """ numId_strs = self.xpath('./w:num/@w:numId') num_ids = [int(numId_str) for numId_str in numId_strs] for num in range(1, len(num_ids)+2): if num not in num_ids: break return num