Skip to content

Commit b0adbe6

Browse files
author
Steve Canny
committed
num: add Document.numbering_part
1 parent 2379769 commit b0adbe6

File tree

3 files changed

+82
-2
lines changed

3 files changed

+82
-2
lines changed

docx/api.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
import os
1212

1313
from docx.enum.text import WD_BREAK
14-
from docx.opc.constants import CONTENT_TYPE as CT
14+
from docx.opc.constants import CONTENT_TYPE as CT, RELATIONSHIP_TYPE as RT
1515
from docx.package import Package
16+
from docx.parts.numbering import NumberingPart
17+
from docx.shared import lazyproperty
1618

1719

1820
_thisdir = os.path.split(__file__)[0]
@@ -115,6 +117,19 @@ def inline_shapes(self):
115117
"""
116118
return self._document_part.inline_shapes
117119

120+
@lazyproperty
121+
def numbering_part(self):
122+
"""
123+
Instance of |NumberingPart| for this document. Creates an empty
124+
numbering part if one is not present.
125+
"""
126+
try:
127+
return self._document_part.part_related_by(RT.NUMBERING)
128+
except KeyError:
129+
numbering_part = NumberingPart.new()
130+
self._document_part.relate_to(numbering_part, RT.NUMBERING)
131+
return numbering_part
132+
118133
@property
119134
def paragraphs(self):
120135
"""

docx/parts/numbering.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# encoding: utf-8
2+
3+
"""
4+
|NumberingPart| and closely related objects
5+
"""
6+
7+
from __future__ import (
8+
absolute_import, division, print_function, unicode_literals
9+
)
10+
11+
from ..opc.package import Part
12+
13+
14+
class NumberingPart(Part):
15+
"""
16+
Proxy for the numbering.xml part containing numbering definitions for
17+
a document or glossary.
18+
"""
19+
@classmethod
20+
def new(cls):
21+
"""
22+
Return newly created empty numbering part, containing only the root
23+
``<w:numbering>`` element.
24+
"""
25+
raise NotImplementedError

tests/test_api.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212

1313
from docx.api import Document
1414
from docx.enum.text import WD_BREAK
15-
from docx.opc.constants import CONTENT_TYPE as CT
15+
from docx.opc.constants import CONTENT_TYPE as CT, RELATIONSHIP_TYPE as RT
1616
from docx.package import Package
1717
from docx.parts.document import DocumentPart, InlineShapes
18+
from docx.parts.numbering import NumberingPart
1819
from docx.table import Table
1920
from docx.text import Paragraph, Run
2021

@@ -123,6 +124,24 @@ def it_can_save_the_package(self, save_fixture):
123124
document.save(file_)
124125
package_.save.assert_called_once_with(file_)
125126

127+
def it_provides_access_to_the_numbering_part(self, num_part_get_fixture):
128+
document, document_part_, numbering_part_ = num_part_get_fixture
129+
numbering_part = document.numbering_part
130+
document_part_.part_related_by.assert_called_once_with(RT.NUMBERING)
131+
assert numbering_part is numbering_part_
132+
133+
def it_creates_numbering_part_on_first_access_if_not_present(
134+
self, num_part_create_fixture):
135+
document, NumberingPart_, document_part_, numbering_part_ = (
136+
num_part_create_fixture
137+
)
138+
numbering_part = document.numbering_part
139+
NumberingPart_.new.assert_called_once_with()
140+
document_part_.relate_to.assert_called_once_with(
141+
numbering_part_, RT.NUMBERING
142+
)
143+
assert numbering_part is numbering_part_
144+
126145
# fixtures -------------------------------------------------------
127146

128147
@pytest.fixture(params=[0, 1, 2, 5, 9])
@@ -220,6 +239,27 @@ def init_fixture(self, docx_, open_):
220239
def inline_shapes_(self, request):
221240
return instance_mock(request, InlineShapes)
222241

242+
@pytest.fixture
243+
def num_part_create_fixture(
244+
self, document, NumberingPart_, document_part_, numbering_part_):
245+
document_part_.part_related_by.side_effect = KeyError
246+
return document, NumberingPart_, document_part_, numbering_part_
247+
248+
@pytest.fixture
249+
def num_part_get_fixture(self, document, document_part_, numbering_part_):
250+
document_part_.part_related_by.return_value = numbering_part_
251+
return document, document_part_, numbering_part_
252+
253+
@pytest.fixture
254+
def NumberingPart_(self, request, numbering_part_):
255+
NumberingPart_ = class_mock(request, 'docx.api.NumberingPart')
256+
NumberingPart_.new.return_value = numbering_part_
257+
return NumberingPart_
258+
259+
@pytest.fixture
260+
def numbering_part_(self, request):
261+
return instance_mock(request, NumberingPart)
262+
223263
@pytest.fixture
224264
def open_(self, request, document_part_, package_):
225265
return method_mock(

0 commit comments

Comments
 (0)