X Tutup
Skip to content

Commit c6ec277

Browse files
author
Steve Canny
committed
sect: add Section.start_type getter
Added InvalidXmlError to docx.exceptions, caused a circular import error when trying to get it into enum from xmlchemy.
1 parent f5e4d3e commit c6ec277

File tree

9 files changed

+131
-2
lines changed

9 files changed

+131
-2
lines changed

docs/dev/analysis/features/sections.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ Inserting a section break (next page) produces this XML::
130130
<w:p>
131131
<w:pPr>
132132
<w:sectPr>
133+
<w:type w:val="oddPage"/>
133134
<w:pgSz w:w="12240" w:h="15840"/>
134135
<w:pgMar w:top="1440" w:right="1800" w:bottom="1440" w:left="1800" w:header="720" w:footer="720" w:gutter="0"/>
135136
<w:cols w:space="720"/>

docx/enum/base.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import sys
1010
import textwrap
1111

12+
from ..exceptions import InvalidXmlError
13+
1214

1315
def alias(*aliases):
1416
"""
@@ -184,6 +186,10 @@ def from_xml(cls, xml_val):
184186
Return the enumeration member corresponding to the XML value
185187
*xml_val*.
186188
"""
189+
if xml_val not in cls._xml_to_member:
190+
raise InvalidXmlError(
191+
"attribute value '%s' not valid for this type" % xml_val
192+
)
187193
return cls._xml_to_member[xml_val]
188194

189195
@classmethod

docx/exceptions.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,13 @@
88

99

1010
class PythonDocxError(Exception):
11-
"""Generic error class."""
11+
"""
12+
Generic error class.
13+
"""
14+
15+
16+
class InvalidXmlError(PythonDocxError):
17+
"""
18+
Raised when invalid XML is encountered, such as on attempt to access a
19+
missing required child element
20+
"""

docx/oxml/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ def OxmlElement(nsptag_str, attrs=None, nsdecls=None):
107107
register_element_cls('w:style', CT_Style)
108108
register_element_cls('w:styles', CT_Styles)
109109

110+
from docx.oxml.section import CT_SectPr, CT_SectType
111+
register_element_cls('w:sectPr', CT_SectPr)
112+
register_element_cls('w:type', CT_SectType)
113+
110114
from docx.oxml.table import (
111115
CT_Row, CT_Tbl, CT_TblGrid, CT_TblGridCol, CT_TblPr, CT_Tc
112116
)

docx/oxml/section.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# encoding: utf-8
2+
3+
"""
4+
Section-related custom element classes.
5+
"""
6+
7+
from ..enum.section import WD_SECTION_START
8+
from .xmlchemy import BaseOxmlElement, OptionalAttribute, ZeroOrOne
9+
10+
11+
class CT_SectPr(BaseOxmlElement):
12+
"""
13+
``<w:sectPr>`` element, the container element for section properties.
14+
"""
15+
type = ZeroOrOne('w:type')
16+
17+
@property
18+
def start_type(self):
19+
"""
20+
The member of the ``WD_SECTION_START`` enumeration corresponding to
21+
the value of the ``val`` attribute of the ``<w:type>`` child element,
22+
or ``WD_SECTION_START.NEW_PAGE`` if not present.
23+
"""
24+
type = self.type
25+
if type is None or type.val is None:
26+
return WD_SECTION_START.NEW_PAGE
27+
return type.val
28+
29+
30+
class CT_SectType(BaseOxmlElement):
31+
"""
32+
``<w:sectType>`` element, defining the section start type.
33+
"""
34+
val = OptionalAttribute('w:val', WD_SECTION_START)

docx/section.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,12 @@ class Section(object):
1414
def __init__(self, sectPr):
1515
super(Section, self).__init__()
1616
self._sectPr = sectPr
17+
18+
@property
19+
def start_type(self):
20+
"""
21+
The member of the ``WD_SECTION`` enumeration corresponding to the
22+
initial break behavior of this section, e.g. ``WD_SECTION.ODD_PAGE``
23+
if the section should begin on the next odd page.
24+
"""
25+
return self._sectPr.start_type

features/sct-section-props.feature

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ Feature: Access and change section properties
44
I need a way to get and set the properties of a section
55

66

7-
@wip
87
Scenario Outline: Get section start type
98
Given a section having start type <start-type>
109
Then the reported section start type is <start-type>

tests/oxml/unitdata/section.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# encoding: utf-8
2+
3+
"""
4+
Test data builders for section-related XML elements
5+
"""
6+
7+
from ...unitdata import BaseBuilder
8+
9+
10+
class CT_SectPrBuilder(BaseBuilder):
11+
__tag__ = 'w:sectPr'
12+
__nspfxs__ = ('w',)
13+
__attrs__ = ()
14+
15+
16+
class CT_SectTypeBuilder(BaseBuilder):
17+
__tag__ = 'w:type'
18+
__nspfxs__ = ('w',)
19+
__attrs__ = ('w:val',)
20+
21+
22+
def a_sectPr():
23+
return CT_SectPrBuilder()
24+
25+
26+
def a_type():
27+
return CT_SectTypeBuilder()

tests/test_section.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# encoding: utf-8
2+
3+
"""
4+
Test suite for the docx.section module
5+
"""
6+
7+
from __future__ import absolute_import, print_function, unicode_literals
8+
9+
import pytest
10+
11+
from docx.enum.section import WD_SECTION
12+
from docx.section import Section
13+
14+
from .oxml.unitdata.section import a_sectPr, a_type
15+
16+
17+
class DescribeSection(object):
18+
19+
def it_knows_its_start_type(self, start_type_fixture):
20+
section, expected_start_type = start_type_fixture
21+
assert section.start_type is expected_start_type
22+
23+
# fixtures -------------------------------------------------------
24+
25+
@pytest.fixture(params=[
26+
(None, WD_SECTION.NEW_PAGE),
27+
('continuous', WD_SECTION.CONTINUOUS),
28+
('nextPage', WD_SECTION.NEW_PAGE),
29+
('oddPage', WD_SECTION.ODD_PAGE),
30+
('evenPage', WD_SECTION.EVEN_PAGE),
31+
('nextColumn', WD_SECTION.NEW_COLUMN),
32+
])
33+
def start_type_fixture(self, request):
34+
type_val, expected_start_type = request.param
35+
sectPr_bldr = a_sectPr().with_nsdecls()
36+
if type_val is not None:
37+
sectPr_bldr.with_child(a_type().with_val(type_val))
38+
sectPr = sectPr_bldr.element
39+
section = Section(sectPr)
40+
return section, expected_start_type

0 commit comments

Comments
 (0)
X Tutup