Skip to content

Commit 14928c6

Browse files
author
Steve Canny
committed
oxml: convert CT_Num to xmlchemy
Organize tests/parts/test_numbering.py a bit.
1 parent e17d371 commit 14928c6

File tree

5 files changed

+94
-41
lines changed

5 files changed

+94
-41
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
2+
Numbering Part
3+
==============
4+
5+
... having to do with numbering sequences for ordered lists, etc. ...
6+
7+
8+
Schema excerpt
9+
--------------
10+
11+
.. highlight:: xml
12+
13+
::
14+
15+
<xsd:complexType name="CT_Numbering">
16+
<xsd:sequence>
17+
<xsd:element name="numPicBullet" type="CT_NumPicBullet" minOccurs="0" maxOccurs="unbounded"/>
18+
<xsd:element name="abstractNum" type="CT_AbstractNum" minOccurs="0" maxOccurs="unbounded"/>
19+
<xsd:element name="num" type="CT_Num" minOccurs="0" maxOccurs="unbounded"/>
20+
<xsd:element name="numIdMacAtCleanup" type="CT_DecimalNumber" minOccurs="0"/>
21+
</xsd:sequence>
22+
</xsd:complexType>
23+
24+
<xsd:complexType name="CT_Num">
25+
<xsd:sequence>
26+
<xsd:element name="abstractNumId" type="CT_DecimalNumber"/>
27+
<xsd:element name="lvlOverride" type="CT_NumLvl" minOccurs="0" maxOccurs="9"/>
28+
</xsd:sequence>
29+
<xsd:attribute name="numId" type="ST_DecimalNumber" use="required"/>
30+
</xsd:complexType>
31+
32+
<xsd:complexType name="CT_NumLvl">
33+
<xsd:sequence>
34+
<xsd:element name="startOverride" type="CT_DecimalNumber" minOccurs="0"/>
35+
<xsd:element name="lvl" type="CT_Lvl" minOccurs="0"/>
36+
</xsd:sequence>
37+
<xsd:attribute name="ilvl" type="ST_DecimalNumber" use="required"/>
38+
</xsd:complexType>
39+
40+
<xsd:complexType name="CT_NumPr">
41+
<xsd:sequence>
42+
<xsd:element name="ilvl" type="CT_DecimalNumber" minOccurs="0"/>
43+
<xsd:element name="numId" type="CT_DecimalNumber" minOccurs="0"/>
44+
<xsd:element name="numberingChange" type="CT_TrackChangeNumbering" minOccurs="0"/>
45+
<xsd:element name="ins" type="CT_TrackChange" minOccurs="0"/>
46+
</xsd:sequence>
47+
</xsd:complexType>
48+
49+
<xsd:complexType name="CT_DecimalNumber">
50+
<xsd:attribute name="val" type="ST_DecimalNumber" use="required"/>
51+
</xsd:complexType>
52+
53+
<xsd:simpleType name="ST_DecimalNumber">
54+
<xsd:restriction base="xsd:integer"/>
55+
</xsd:simpleType>

docs/dev/analysis/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Feature Analysis
1010
.. toctree::
1111
:maxdepth: 1
1212

13+
features/numbering
1314
features/underline
1415
features/char-style
1516
features/breaks

docx/oxml/parts/numbering.py

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55
"""
66

77
from .. import OxmlElement
8-
from ..shared import CT_DecimalNumber
98
from ..ns import qn
10-
from ..xmlchemy import BaseOxmlElement
9+
from ..shared import CT_DecimalNumber
10+
from ..simpletypes import ST_DecimalNumber
11+
from ..xmlchemy import (
12+
BaseOxmlElement, OneAndOnlyOne, RequiredAttribute, ZeroOrMore
13+
)
1114

1215

1316
class CT_Num(BaseOxmlElement):
@@ -16,18 +19,16 @@ class CT_Num(BaseOxmlElement):
1619
instance, having a required child <w:abstractNumId> that references an
1720
abstract numbering definition that defines most of the formatting details.
1821
"""
19-
@property
20-
def abstractNumId(self):
21-
return self.find(qn('w:abstractNumId'))
22+
abstractNumId = OneAndOnlyOne('w:abstractNumId')
23+
lvlOverride = ZeroOrMore('w:lvlOverride')
24+
numId = RequiredAttribute('w:numId', ST_DecimalNumber)
2225

2326
def add_lvlOverride(self, ilvl):
2427
"""
2528
Return a newly added CT_NumLvl (<w:lvlOverride>) element having its
2629
``ilvl`` attribute set to *ilvl*.
2730
"""
28-
lvlOverride = CT_NumLvl.new(ilvl)
29-
self.append(lvlOverride)
30-
return lvlOverride
31+
return self._add_lvlOverride(ilvl=ilvl)
3132

3233
@classmethod
3334
def new(cls, num_id, abstractNum_id):
@@ -36,24 +37,22 @@ def new(cls, num_id, abstractNum_id):
3637
a ``<w:abstractNumId>`` child with val attribute set to
3738
*abstractNum_id*.
3839
"""
40+
num = OxmlElement('w:num')
41+
num.numId = num_id
3942
abstractNumId = CT_DecimalNumber.new(
4043
'w:abstractNumId', abstractNum_id
4144
)
42-
num = OxmlElement('w:num', {qn('w:numId'): str(num_id)})
4345
num.append(abstractNumId)
4446
return num
4547

46-
@property
47-
def numId(self):
48-
numId_str = self.get(qn('w:numId'))
49-
return int(numId_str)
50-
5148

5249
class CT_NumLvl(BaseOxmlElement):
5350
"""
5451
``<w:lvlOverride>`` element, which identifies a level in a list
5552
definition to override with settings it contains.
5653
"""
54+
ilvl = RequiredAttribute('w:ilvl', ST_DecimalNumber)
55+
5756
def add_startOverride(self, val):
5857
"""
5958
Return a newly added CT_DecimalNumber element having tagname
@@ -63,14 +62,6 @@ def add_startOverride(self, val):
6362
self.insert(0, startOverride)
6463
return startOverride
6564

66-
@classmethod
67-
def new(cls, ilvl):
68-
"""
69-
Return a new ``<w:lvlOverride>`` element having its ``ilvl``
70-
attribute set to *ilvl*.
71-
"""
72-
return OxmlElement('w:lvlOverride', {qn('w:ilvl'): str(ilvl)})
73-
7465

7566
class CT_NumPr(BaseOxmlElement):
7667
"""

docx/oxml/simpletypes.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,7 @@ class XsdUnsignedInt(BaseIntType):
149149
@classmethod
150150
def validate(cls, value):
151151
cls.validate_int_in_range(value, 0, 4294967295)
152+
153+
154+
class ST_DecimalNumber(XsdInt):
155+
pass

tests/parts/test_numbering.py

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,6 @@ def it_provides_access_to_the_numbering_definitions(
6262

6363
# fixtures -------------------------------------------------------
6464

65-
@pytest.fixture
66-
def blob_(self, request):
67-
return instance_mock(request, bytes)
68-
6965
@pytest.fixture
7066
def construct_fixture(
7167
self, partname_, content_type_, blob_, package_, parse_xml_,
@@ -75,14 +71,6 @@ def construct_fixture(
7571
numbering_elm_
7672
)
7773

78-
@pytest.fixture
79-
def content_type_(self, request):
80-
return instance_mock(request, str)
81-
82-
@pytest.fixture
83-
def init__(self, request):
84-
return initializer_mock(request, NumberingPart)
85-
8674
@pytest.fixture
8775
def load_fixture(
8876
self, numbering_part_load_, partname_, blob_, package_,
@@ -92,13 +80,6 @@ def load_fixture(
9280
numbering_part_load_, partname_, blob_, package_, numbering_part_
9381
)
9482

95-
@pytest.fixture
96-
def _NumberingDefinitions_(self, request, numbering_definitions_):
97-
return class_mock(
98-
request, 'docx.parts.numbering._NumberingDefinitions',
99-
return_value=numbering_definitions_
100-
)
101-
10283
@pytest.fixture
10384
def num_defs_fixture(
10485
self, _NumberingDefinitions_, numbering_elm_,
@@ -109,6 +90,27 @@ def num_defs_fixture(
10990
numbering_definitions_
11091
)
11192

93+
# fixture components ---------------------------------------------
94+
95+
@pytest.fixture
96+
def blob_(self, request):
97+
return instance_mock(request, bytes)
98+
99+
@pytest.fixture
100+
def content_type_(self, request):
101+
return instance_mock(request, str)
102+
103+
@pytest.fixture
104+
def init__(self, request):
105+
return initializer_mock(request, NumberingPart)
106+
107+
@pytest.fixture
108+
def _NumberingDefinitions_(self, request, numbering_definitions_):
109+
return class_mock(
110+
request, 'docx.parts.numbering._NumberingDefinitions',
111+
return_value=numbering_definitions_
112+
)
113+
112114
@pytest.fixture
113115
def numbering_definitions_(self, request):
114116
return instance_mock(request, _NumberingDefinitions)

0 commit comments

Comments
 (0)