Skip to content

Commit d922569

Browse files
author
Steve Canny
committed
tbl: rewrite Table.style getter
* Add descriptive __repr__() for _TableStyle, otherwise it inherits the one from _ParagraphStyle. * Rewrite portions of api-add-table.feature to work with new style interface.
1 parent 3700d2d commit d922569

File tree

7 files changed

+66
-33
lines changed

7 files changed

+66
-33
lines changed

docx/oxml/table.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ class CT_Tbl(BaseOxmlElement):
5959
tblGrid = OneAndOnlyOne('w:tblGrid')
6060
tr = ZeroOrMore('w:tr')
6161

62+
@property
63+
def col_count(self):
64+
"""
65+
The number of grid columns in this table.
66+
"""
67+
return len(self.tblGrid.gridCol_lst)
68+
6269
def iter_tcs(self):
6370
"""
6471
Generate each of the `w:tc` elements in this table, left to right and
@@ -79,11 +86,15 @@ def new(cls):
7986
return tbl
8087

8188
@property
82-
def col_count(self):
89+
def tblStyle_val(self):
8390
"""
84-
The number of grid columns in this table.
91+
Value of `w:tblPr/w:tblStyle/@w:val` (a table style id) or |None| if
92+
not present.
8593
"""
86-
return len(self.tblGrid.gridCol_lst)
94+
tblStyle = self.tblPr.tblStyle
95+
if tblStyle is None:
96+
return None
97+
return tblStyle.val
8798

8899
@classmethod
89100
def _tbl_xml(cls):

docx/styles/style.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,9 @@ class _TableStyle(_ParagraphStyle):
253253

254254
__slots__ = ()
255255

256+
def __repr__(self):
257+
return '_TableStyle(\'%s\') id: %s' % (self.name, id(self))
258+
256259

257260
class _NumberingStyle(BaseStyle):
258261
"""

docx/table.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from __future__ import absolute_import, print_function, unicode_literals
88

99
from .blkcntnr import BlockItemContainer
10+
from .enum.style import WD_STYLE_TYPE
1011
from .oxml.simpletypes import ST_Merge
1112
from .shared import lazyproperty, Parented
1213

@@ -110,11 +111,18 @@ def rows(self):
110111
@property
111112
def style(self):
112113
"""
113-
String name of style to be applied to this table, e.g.
114-
'LightShading-Accent1'. Name is derived by removing spaces from the
115-
table style name displayed in the Word UI.
116-
"""
117-
return self._tblPr.style
114+
Read/write. A |_TableStyle| object representing the style applied to
115+
this table. The default table style for the document (often `Normal
116+
Table`) is returned if the table has no directly-applied style.
117+
Assigning |None| to this property removes any directly-applied table
118+
style causing it to inherit the default table style of the document.
119+
Note that the style name of a table style differs slightly from that
120+
displayed in the user interface; a hyphen, if it appears, must be
121+
removed. For example, `Light Shading - Accent 1` becomes `Light
122+
Shading Accent 1`.
123+
"""
124+
style_id = self._tbl.tblStyle_val
125+
return self.part.get_style(style_id, WD_STYLE_TYPE.TABLE)
118126

119127
@style.setter
120128
def style(self, value):

features/api-add-table.feature

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@ Feature: Add a table
33
As a programmer using the basic python-docx API
44
I need a method that adds a table at the end of the document
55

6+
67
Scenario: Add a table specifying only row and column count
78
Given a document
89
When I add a 2 x 2 table specifying only row and column count
910
Then the document contains a 2 x 2 table
10-
And the table style is 'LightShading-Accent1'
11+
And table.style is styles['Light Shading Accent 1']
12+
1113

14+
@wip
1215
Scenario: Add a table specifying style
1316
Given a document
14-
When I add a 2 x 2 table specifying style 'foobar'
17+
When I add a 2 x 2 table specifying style 'Table Grid'
1518
Then the document contains a 2 x 2 table
16-
And the table style is 'foobar'
19+
And table.style is styles['Table Grid']

features/steps/api.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ def when_add_2x2_table_specifying_only_row_and_col_count(context):
2020
document.add_table(rows=2, cols=2)
2121

2222

23-
@when('I add a 2 x 2 table specifying style \'foobar\'')
24-
def when_add_2x2_table_specifying_style_foobar(context):
23+
@when('I add a 2 x 2 table specifying style \'{style_name}\'')
24+
def when_add_2x2_table_specifying_style_name(context, style_name):
2525
document = context.document
26-
document.add_table(rows=2, cols=2, style='foobar')
26+
document.add_table(rows=2, cols=2, style=style_name)
2727

2828

2929
@when('I add a heading specifying level={level_str}')
@@ -159,9 +159,3 @@ def then_the_style_of_the_last_paragraph_is_style(context, style_name):
159159
assert paragraph.style.name == style_name, (
160160
'got %s' % paragraph.style.name
161161
)
162-
163-
164-
@then('the table style is \'{style}\'')
165-
def then_table_style_is_style(context, style):
166-
table = context.table_
167-
assert table.style == style

features/tbl-style.feature

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ Feature: Query and apply a table style
44
I need the ability to get and set the style of a table
55

66

7-
@wip
87
Scenario Outline: Get the style of a table
98
Given a table having <style> style
109
Then table.style is styles['<value>']

tests/test_table.py

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88

99
import pytest
1010

11+
from docx.enum.style import WD_STYLE_TYPE
1112
from docx.enum.table import WD_TABLE_ALIGNMENT
1213
from docx.oxml import parse_xml
1314
from docx.oxml.table import CT_Tc
15+
from docx.parts.document import DocumentPart
1416
from docx.shared import Inches
1517
from docx.table import _Cell, _Column, _Columns, _Row, _Rows, Table
1618
from docx.text.paragraph import Paragraph
@@ -42,9 +44,13 @@ def it_can_change_its_autofit_setting(self, autofit_set_fixture):
4244
table.autofit = new_value
4345
assert table._tbl.xml == expected_xml
4446

45-
def it_knows_its_table_style(self, table_style_get_fixture):
46-
table, style = table_style_get_fixture
47-
assert table.style == style
47+
def it_knows_its_table_style(self, style_get_fixture):
48+
table, style_id_, style_ = style_get_fixture
49+
style = table.style
50+
table.part.get_style.assert_called_once_with(
51+
style_id_, WD_STYLE_TYPE.TABLE
52+
)
53+
assert style is style_
4854

4955
def it_can_apply_a_table_style_by_name(self, table_style_set_fixture):
5056
table, style_name, expected_xml = table_style_set_fixture
@@ -219,20 +225,19 @@ def row_cells_fixture(self, _cells_, _column_count_):
219225
expected_cells = [3, 4, 5]
220226
return table, row_idx, expected_cells
221227

228+
@pytest.fixture
229+
def style_get_fixture(self, part_prop_):
230+
style_id = 'Barbaz'
231+
tbl_cxml = 'w:tbl/w:tblPr/w:tblStyle{w:val=%s}' % style_id
232+
table = Table(element(tbl_cxml), None)
233+
style_ = part_prop_.return_value.get_style.return_value
234+
return table, style_id, style_
235+
222236
@pytest.fixture
223237
def table_fixture(self):
224238
table = Table(None, None)
225239
return table
226240

227-
@pytest.fixture(params=[
228-
('w:tbl/w:tblPr', None),
229-
('w:tbl/w:tblPr/w:tblStyle{w:val=foobar}', 'foobar'),
230-
])
231-
def table_style_get_fixture(self, request):
232-
tbl_cxml, expected_style = request.param
233-
table = Table(element(tbl_cxml), None)
234-
return table, expected_style
235-
236241
@pytest.fixture(params=[
237242
('w:tbl/w:tblPr', 'foobar',
238243
'w:tbl/w:tblPr/w:tblStyle{w:val=foobar}'),
@@ -259,6 +264,16 @@ def _cells_(self, request):
259264
def _column_count_(self, request):
260265
return property_mock(request, Table, '_column_count')
261266

267+
@pytest.fixture
268+
def document_part_(self, request):
269+
return instance_mock(request, DocumentPart)
270+
271+
@pytest.fixture
272+
def part_prop_(self, request, document_part_):
273+
return property_mock(
274+
request, Table, 'part', return_value=document_part_
275+
)
276+
262277
@pytest.fixture
263278
def table(self):
264279
tbl = _tbl_bldr(rows=2, cols=2).element

0 commit comments

Comments
 (0)