forked from python-openxml/python-docx
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_table.py
More file actions
376 lines (300 loc) · 11.5 KB
/
test_table.py
File metadata and controls
376 lines (300 loc) · 11.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
# encoding: utf-8
"""
Test suite for the docx.table module
"""
from __future__ import absolute_import, print_function, unicode_literals
import pytest
from docx.table import (
_Cell, _Column, _ColumnCells, _Columns, _Row, _RowCells, _Rows, Table
)
from docx.text import Paragraph
from .oxml.unitdata.table import (
a_gridCol, a_tbl, a_tblGrid, a_tblPr, a_tblStyle, a_tc, a_tcPr, a_tr
)
from .oxml.unitdata.text import a_p, a_t, an_r
class DescribeTable(object):
def it_provides_access_to_the_table_rows(self, table):
rows = table.rows
assert isinstance(rows, _Rows)
def it_provides_access_to_the_table_columns(self, table):
columns = table.columns
assert isinstance(columns, _Columns)
def it_provides_access_to_a_cell_by_row_and_col_indices(self, table):
for row_idx in range(2):
for col_idx in range(2):
cell = table.cell(row_idx, col_idx)
assert isinstance(cell, _Cell)
tr = table._tbl.tr_lst[row_idx]
tc = tr.tc_lst[col_idx]
assert tc is cell._tc
def it_can_add_a_row(self, add_row_fixture):
table, expected_xml = add_row_fixture
row = table.add_row()
assert table._tbl.xml == expected_xml
assert isinstance(row, _Row)
assert row._tr is table._tbl.tr_lst[1]
def it_can_add_a_column(self, add_column_fixture):
table, expected_xml = add_column_fixture
column = table.add_column()
assert table._tbl.xml == expected_xml
assert isinstance(column, _Column)
assert column._gridCol is table._tbl.tblGrid.gridCol_lst[1]
def it_knows_its_table_style(self, table_style_fixture):
table, style = table_style_fixture
assert table.style == style
def it_can_apply_a_table_style_by_name(self, table_style_set_fixture):
table, style_name, expected_xml = table_style_set_fixture
table.style = style_name
assert table._tbl.xml == expected_xml
# fixtures -------------------------------------------------------
@pytest.fixture
def add_column_fixture(self):
tbl = _tbl_bldr(2, 1).element
table = Table(tbl)
expected_xml = _tbl_bldr(2, 2).xml()
return table, expected_xml
@pytest.fixture
def add_row_fixture(self):
tbl = _tbl_bldr(rows=1, cols=2).element
table = Table(tbl)
expected_xml = _tbl_bldr(rows=2, cols=2).xml()
return table, expected_xml
@pytest.fixture
def table(self):
tbl = _tbl_bldr(rows=2, cols=2).element
table = Table(tbl)
return table
@pytest.fixture
def table_style_fixture(self):
style = 'foobar'
tbl = (
a_tbl().with_nsdecls().with_child(
a_tblPr().with_child(
a_tblStyle().with_val(style)))
).element
table = Table(tbl)
return table, style
@pytest.fixture
def table_style_set_fixture(self):
# table ------------------------
tbl = a_tbl().with_nsdecls().with_child(a_tblPr()).element
table = Table(tbl)
# style_name -------------------
style_name = 'foobar'
# expected_xml -----------------
expected_xml = (
a_tbl().with_nsdecls().with_child(
a_tblPr().with_child(
a_tblStyle().with_val(style_name)))
).xml()
return table, style_name, expected_xml
class Describe_Cell(object):
def it_provides_access_to_the_paragraphs_it_contains(
self, cell_with_paragraphs):
cell = cell_with_paragraphs
paragraphs = cell.paragraphs
assert len(paragraphs) == 2
for p in paragraphs:
assert isinstance(p, Paragraph)
def it_can_replace_its_content_with_a_string_of_text(
self, cell_text_fixture):
cell, text, expected_xml = cell_text_fixture
cell.text = text
assert cell._tc.xml == expected_xml
# fixtures -------------------------------------------------------
@pytest.fixture
def cell_text_fixture(self):
# cell -------------------------
tc = (
a_tc().with_nsdecls().with_child(
a_tcPr()).with_child(
a_p()).with_child(
a_tbl()).with_child(
a_p())
).element
cell = _Cell(tc)
# text -------------------------
text = 'foobar'
# expected_xml -----------------
expected_xml = (
a_tc().with_nsdecls().with_child(
a_tcPr()).with_child(
a_p().with_child(
an_r().with_child(
a_t().with_text(text))))
).xml()
return cell, text, expected_xml
@pytest.fixture
def cell_with_paragraphs(self):
tc = (
a_tc().with_nsdecls()
.with_child(a_p())
.with_child(a_p())
.element
)
return _Cell(tc)
class Describe_Column(object):
def it_provides_access_to_the_column_cells(self, column):
cells = column.cells
assert isinstance(cells, _ColumnCells)
# fixtures -------------------------------------------------------
@pytest.fixture
def column(self):
return _Column(None, None)
class Describe_ColumnCells(object):
def it_knows_how_many_cells_it_contains(self, cells_fixture):
cells, cell_count = cells_fixture
assert len(cells) == cell_count
def it_can_iterate_over_its__Cell_instances(self, cells_fixture):
cells, cell_count = cells_fixture
actual_count = 0
for cell in cells:
assert isinstance(cell, _Cell)
actual_count += 1
assert actual_count == cell_count
def it_provides_indexed_access_to_cells(self, cells_fixture):
cells, cell_count = cells_fixture
for idx in range(-cell_count, cell_count):
cell = cells[idx]
assert isinstance(cell, _Cell)
def it_raises_on_indexed_access_out_of_range(self, cells_fixture):
cells, cell_count = cells_fixture
too_low = -1 - cell_count
too_high = cell_count
with pytest.raises(IndexError):
cells[too_low]
with pytest.raises(IndexError):
cells[too_high]
# fixtures -------------------------------------------------------
@pytest.fixture
def cells_fixture(self):
cell_count = 2
tbl = _tbl_bldr(rows=cell_count, cols=1).element
gridCol = tbl.tblGrid.gridCol_lst[0]
cells = _ColumnCells(tbl, gridCol)
return cells, cell_count
class Describe_Columns(object):
def it_knows_how_many_columns_it_contains(self, columns_fixture):
columns, column_count = columns_fixture
assert len(columns) == column_count
def it_can_interate_over_its__Column_instances(self, columns_fixture):
columns, column_count = columns_fixture
actual_count = 0
for column in columns:
assert isinstance(column, _Column)
actual_count += 1
assert actual_count == column_count
def it_provides_indexed_access_to_columns(self, columns_fixture):
columns, column_count = columns_fixture
for idx in range(-column_count, column_count):
column = columns[idx]
assert isinstance(column, _Column)
def it_raises_on_indexed_access_out_of_range(self, columns_fixture):
columns, column_count = columns_fixture
too_low = -1 - column_count
too_high = column_count
with pytest.raises(IndexError):
columns[too_low]
with pytest.raises(IndexError):
columns[too_high]
# fixtures -------------------------------------------------------
@pytest.fixture
def columns_fixture(self):
column_count = 2
tbl = _tbl_bldr(rows=2, cols=column_count).element
columns = _Columns(tbl)
return columns, column_count
class Describe_Row(object):
def it_provides_access_to_the_row_cells(self, cells_access_fixture):
row = cells_access_fixture
cells = row.cells
assert isinstance(cells, _RowCells)
# fixtures -------------------------------------------------------
@pytest.fixture
def cells_access_fixture(self):
tr = a_tr().with_nsdecls().element
row = _Row(tr)
return row
class Describe_RowCells(object):
def it_knows_how_many_cells_it_contains(self, cell_count_fixture):
cells, cell_count = cell_count_fixture
assert len(cells) == cell_count
def it_can_iterate_over_its__Cell_instances(self, cell_count_fixture):
cells, cell_count = cell_count_fixture
actual_count = 0
for cell in cells:
assert isinstance(cell, _Cell)
actual_count += 1
assert actual_count == cell_count
def it_provides_indexed_access_to_cells(self, cell_count_fixture):
cells, cell_count = cell_count_fixture
for idx in range(-cell_count, cell_count):
cell = cells[idx]
assert isinstance(cell, _Cell)
def it_raises_on_indexed_access_out_of_range(self, cell_count_fixture):
cells, cell_count = cell_count_fixture
too_low = -1 - cell_count
too_high = cell_count
with pytest.raises(IndexError):
cells[too_low]
with pytest.raises(IndexError):
cells[too_high]
# fixtures -------------------------------------------------------
@pytest.fixture
def cell_count_fixture(self):
cell_count = 2
tr_bldr = a_tr().with_nsdecls()
for idx in range(cell_count):
tr_bldr.with_child(a_tc())
tr = tr_bldr.element
cells = _RowCells(tr)
return cells, cell_count
class Describe_Rows(object):
def it_knows_how_many_rows_it_contains(self, rows_fixture):
rows, row_count = rows_fixture
assert len(rows) == row_count
def it_can_iterate_over_its__Row_instances(self, rows_fixture):
rows, row_count = rows_fixture
actual_count = 0
for row in rows:
assert isinstance(row, _Row)
actual_count += 1
assert actual_count == row_count
def it_provides_indexed_access_to_rows(self, rows_fixture):
rows, row_count = rows_fixture
for idx in range(-row_count, row_count):
row = rows[idx]
assert isinstance(row, _Row)
def it_raises_on_indexed_access_out_of_range(self, rows_fixture):
rows, row_count = rows_fixture
with pytest.raises(IndexError):
too_low = -1 - row_count
rows[too_low]
with pytest.raises(IndexError):
too_high = row_count
rows[too_high]
# fixtures -------------------------------------------------------
@pytest.fixture
def rows_fixture(self):
row_count = 2
tbl = _tbl_bldr(rows=row_count, cols=2).element
rows = _Rows(tbl)
return rows, row_count
# fixtures -----------------------------------------------------------
def _tbl_bldr(rows, cols):
tblGrid_bldr = a_tblGrid()
for i in range(cols):
tblGrid_bldr.with_child(a_gridCol())
tbl_bldr = a_tbl().with_nsdecls().with_child(tblGrid_bldr)
for i in range(rows):
tr_bldr = _tr_bldr(cols)
tbl_bldr.with_child(tr_bldr)
return tbl_bldr
def _tc_bldr():
return a_tc().with_child(a_p())
def _tr_bldr(cols):
tr_bldr = a_tr()
for i in range(cols):
tc_bldr = _tc_bldr()
tr_bldr.with_child(tc_bldr)
return tr_bldr