Skip to content

Commit d571aae

Browse files
author
Steve Canny
committed
tbl: add Table.autofit getter
* Fixed sequencing of w:tblPr/w:tblStyle child element, was defaulting to unconditional append.
1 parent 0528a78 commit d571aae

File tree

6 files changed

+68
-11
lines changed

6 files changed

+68
-11
lines changed

docx/oxml/__init__.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -114,15 +114,17 @@ def OxmlElement(nsptag_str, attrs=None, nsdecls=None):
114114
register_element_cls('w:type', CT_SectType)
115115

116116
from docx.oxml.table import (
117-
CT_Row, CT_Tbl, CT_TblGrid, CT_TblGridCol, CT_TblPr, CT_Tc
117+
CT_Row, CT_Tbl, CT_TblGrid, CT_TblGridCol, CT_TblLayoutType, CT_TblPr,
118+
CT_Tc
118119
)
119-
register_element_cls('w:gridCol', CT_TblGridCol)
120-
register_element_cls('w:tbl', CT_Tbl)
121-
register_element_cls('w:tblGrid', CT_TblGrid)
122-
register_element_cls('w:tblPr', CT_TblPr)
123-
register_element_cls('w:tblStyle', CT_String)
124-
register_element_cls('w:tc', CT_Tc)
125-
register_element_cls('w:tr', CT_Row)
120+
register_element_cls('w:gridCol', CT_TblGridCol)
121+
register_element_cls('w:tbl', CT_Tbl)
122+
register_element_cls('w:tblGrid', CT_TblGrid)
123+
register_element_cls('w:tblLayout', CT_TblLayoutType)
124+
register_element_cls('w:tblPr', CT_TblPr)
125+
register_element_cls('w:tblStyle', CT_String)
126+
register_element_cls('w:tc', CT_Tc)
127+
register_element_cls('w:tr', CT_Row)
126128

127129
from docx.oxml.text import (
128130
CT_Br, CT_Jc, CT_P, CT_PPr, CT_R, CT_RPr, CT_Text, CT_Underline

docx/oxml/simpletypes.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,18 @@ class ST_String(XsdString):
264264
pass
265265

266266

267+
class ST_TblLayoutType(XsdString):
268+
269+
@classmethod
270+
def validate(cls, value):
271+
cls.validate_string(value)
272+
valid_values = ('fixed', 'autofit')
273+
if value not in valid_values:
274+
raise ValueError(
275+
"must be one of %s, got '%s'" % (valid_values, value)
276+
)
277+
278+
267279
class ST_TwipsMeasure(XsdUnsignedLong):
268280

269281
@classmethod

docx/oxml/table.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from . import parse_xml
1010
from .ns import nsdecls
11-
from .simpletypes import ST_TwipsMeasure
11+
from .simpletypes import ST_TblLayoutType, ST_TwipsMeasure
1212
from .xmlchemy import (
1313
BaseOxmlElement, OneAndOnlyOne, OneOrMore, OptionalAttribute, ZeroOrOne,
1414
ZeroOrMore
@@ -70,12 +70,40 @@ class CT_TblGridCol(BaseOxmlElement):
7070
w = OptionalAttribute('w:w', ST_TwipsMeasure)
7171

7272

73+
class CT_TblLayoutType(BaseOxmlElement):
74+
"""
75+
``<w:tblLayout>`` element, specifying whether column widths are fixed or
76+
can be automatically adjusted based on content.
77+
"""
78+
type = OptionalAttribute('w:type', ST_TblLayoutType)
79+
80+
7381
class CT_TblPr(BaseOxmlElement):
7482
"""
7583
``<w:tblPr>`` element, child of ``<w:tbl>``, holds child elements that
7684
define table properties such as style and borders.
7785
"""
78-
tblStyle = ZeroOrOne('w:tblStyle')
86+
tblStyle = ZeroOrOne('w:tblStyle', successors=(
87+
'w:tblpPr', 'w:tblOverlap', 'w:bidiVisual', 'w:tblStyleRowBandSize',
88+
'w:tblStyleColBandSize', 'w:tblW', 'w:jc', 'w:tblCellSpacing',
89+
'w:tblInd', 'w:tblBorders', 'w:shd', 'w:tblLayout', 'w:tblCellMar',
90+
'w:tblLook', 'w:tblCaption', 'w:tblDescription', 'w:tblPrChange'
91+
))
92+
tblLayout = ZeroOrOne('w:tblLayout', successors=(
93+
'w:tblLayout', 'w:tblCellMar', 'w:tblLook', 'w:tblCaption',
94+
'w:tblDescription', 'w:tblPrChange'
95+
))
96+
97+
@property
98+
def autofit(self):
99+
"""
100+
Return |False| if there is a ``<w:tblLayout>`` child with ``w:type``
101+
attribute set to ``'fixed'``. Otherwise return |True|.
102+
"""
103+
tblLayout = self.tblLayout
104+
if tblLayout is None:
105+
return True
106+
return False if tblLayout.type == 'fixed' else True
79107

80108
@property
81109
def style(self):

docx/table.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ def autofit(self):
4646
are adjusted in either case if total column width exceeds page width.
4747
Read/write boolean.
4848
"""
49+
return self._tblPr.autofit
4950

5051
def cell(self, row_idx, col_idx):
5152
"""

features/tbl-props.feature

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

66

7-
@wip
87
Scenario Outline: Get autofit layout setting
98
Given a table having an autofit layout of <autofit-setting>
109
Then the reported autofit setting is <reported-autofit>

tests/test_table.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ def it_can_apply_a_table_style_by_name(self, table_style_set_fixture):
6060
table.style = style_name
6161
assert table._tbl.xml == expected_xml
6262

63+
def it_knows_whether_it_should_autofit(self, autofit_get_fixture):
64+
table, expected_value = autofit_get_fixture
65+
assert table.autofit is expected_value
66+
6367
# fixtures -------------------------------------------------------
6468

6569
@pytest.fixture
@@ -76,6 +80,17 @@ def add_row_fixture(self):
7680
expected_xml = _tbl_bldr(rows=2, cols=2).xml()
7781
return table, expected_xml
7882

83+
@pytest.fixture(params=[
84+
('w:tbl/w:tblPr', True),
85+
('w:tbl/w:tblPr/w:tblLayout', True),
86+
('w:tbl/w:tblPr/w:tblLayout{w:type=autofit}', True),
87+
('w:tbl/w:tblPr/w:tblLayout{w:type=fixed}', False),
88+
])
89+
def autofit_get_fixture(self, request):
90+
tbl_cxml, expected_autofit = request.param
91+
table = Table(element(tbl_cxml), None)
92+
return table, expected_autofit
93+
7994
@pytest.fixture(params=[
8095
('w:tbl/w:tblPr', None),
8196
('w:tbl/w:tblPr/w:tblStyle{w:val=foobar}', 'foobar'),

0 commit comments

Comments
 (0)