Skip to content

Commit 3e9cf63

Browse files
committed
LatexFormatter methods for creating begin/end latex environments return a string; writing to buffer occurs in write_result() (pandas-dev#25436)
1 parent 59e7f04 commit 3e9cf63

File tree

2 files changed

+81
-73
lines changed

2 files changed

+81
-73
lines changed

pandas/core/generic.py

+16-10
Original file line numberDiff line numberDiff line change
@@ -2781,9 +2781,10 @@ class (index) object 'bird' 'bird' 'mammal' 'mammal'
27812781
def to_latex(self, buf=None, columns=None, col_space=None, header=True,
27822782
index=True, na_rep='NaN', formatters=None, float_format=None,
27832783
sparsify=None, index_names=True, bold_rows=False,
2784-
column_format=None, longtable=None, caption=None,
2785-
label=None, escape=None, encoding=None, decimal='.',
2786-
multicolumn=None, multicolumn_format=None, multirow=None):
2784+
column_format=None, longtable=None, escape=None,
2785+
encoding=None, decimal='.', multicolumn=None,
2786+
multicolumn_format=None, multirow=None, caption=None,
2787+
label=None):
27872788
r"""
27882789
Render an object to a LaTeX tabular, longtable, or nested
27892790
table/tabular environment.
@@ -2793,6 +2794,7 @@ def to_latex(self, buf=None, columns=None, col_space=None, header=True,
27932794
27942795
.. versionchanged:: 0.20.2
27952796
Added to Series.
2797+
27962798
.. versionchanged:: 0.25.0
27972799
Added caption and label arguments.
27982800
@@ -2834,13 +2836,6 @@ def to_latex(self, buf=None, columns=None, col_space=None, header=True,
28342836
By default, the value will be read from the pandas config
28352837
module. Use a longtable environment instead of tabular. Requires
28362838
adding a \usepackage{longtable} to your LaTeX preamble.
2837-
caption : str, optional
2838-
The LaTeX caption to be placed inside \caption{} in the output.
2839-
.. versionadded:: 0.25.0
2840-
label : str, optional
2841-
The LaTeX label to be placed inside \label{} in the output.
2842-
This is used with \ref{} in the main .tex file.
2843-
.. versionadded:: 0.25.0
28442839
escape : bool, optional
28452840
By default, the value will be read from the pandas config
28462841
module. When set to False prevents from escaping latex special
@@ -2871,6 +2866,17 @@ def to_latex(self, buf=None, columns=None, col_space=None, header=True,
28712866
28722867
.. versionadded:: 0.20.0
28732868
2869+
caption : str, optional
2870+
The LaTeX caption to be placed inside ``\caption{}`` in the output.
2871+
2872+
.. versionadded:: 0.25.0
2873+
2874+
label : str, optional
2875+
The LaTeX label to be placed inside ``\label{}`` in the output.
2876+
This is used with ``\ref{}`` in the main ``.tex`` file.
2877+
2878+
.. versionadded:: 0.25.0
2879+
28742880
Returns
28752881
-------
28762882
str or None

pandas/io/formats/latex.py

+65-63
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,7 @@ def pad_empties(x):
110110
raise AssertionError('column_format must be str or unicode, '
111111
'not {typ}'.format(typ=type(column_format)))
112112

113-
if self.longtable:
114-
self._write_longtable_begin(buf, column_format)
115-
else:
116-
self._write_tabular_begin(buf, column_format)
113+
buf.write(self._build_latex_begin_env(column_format))
117114

118115
buf.write('\\toprule\n')
119116

@@ -166,10 +163,7 @@ def pad_empties(x):
166163
if self.multirow and i < len(strrows) - 1:
167164
self._print_cline(buf, i, len(strcols))
168165

169-
if self.longtable:
170-
self._write_longtable_end(buf)
171-
else:
172-
self._write_tabular_end(buf)
166+
buf.write(self._build_latex_end_env())
173167

174168
def _format_multicolumn(self, row, ilevels):
175169
r"""
@@ -246,73 +240,81 @@ def _print_cline(self, buf, i, icol):
246240
# remove entries that have been written to buffer
247241
self.clinebuf = [x for x in self.clinebuf if x[0] != i]
248242

249-
def _write_tabular_begin(self, buf, column_format):
243+
def _build_latex_begin_env(self, column_format):
250244
"""
251-
write the beginning of a tabular environment or
252-
nested table/tabular environments including caption and label
253-
"""
254-
if self.caption is None and self.label is None:
255-
# then write output only in a tabular environment
256-
pass
257-
else:
258-
# then write output in a nested table/tabular environment
259-
if self.caption is None:
260-
caption_ = ''
261-
else:
262-
caption_ = '\n\\caption{{{}}}'.format(self.caption)
245+
Write the beginning of the latex environment.
263246
264-
if self.label is None:
265-
label_ = ''
266-
else:
267-
label_ = '\n\\label{{{}}}'.format(self.label)
268-
269-
buf.write('\\begin{{table}}\n\\centering{}{}\n'.format(
270-
caption_,
271-
label_
272-
))
273-
274-
buf.write('\\begin{{tabular}}{{{fmt}}}\n'.format(fmt=column_format))
247+
This can be a tabular environment or nested table/tabular environments
248+
including caption/label depending on the arguments passed to
249+
``LatexFormatter.__init__()``.
275250
276-
def _write_longtable_begin(self, buf, column_format):
251+
:return: string to be written to ``buf``
277252
"""
278-
write the beginning of a longtable environment including caption and
279-
label if provided by user
280-
"""
281-
buf.write('\\begin{{longtable}}{{{fmt}}}\n'.format(fmt=column_format))
253+
str_ = ''
254+
if self.longtable:
255+
str_ += '\\begin{{longtable}}{{{fmt}}}\n'.format(fmt=column_format)
282256

283-
if self.caption is None and self.label is None:
284-
pass
285-
else:
286-
if self.caption is None:
257+
if self.caption is None and self.label is None:
287258
pass
288259
else:
289-
buf.write('\\caption{{{}}}'.format(self.caption))
290-
291-
if self.label is None:
260+
if self.caption is None:
261+
pass
262+
else:
263+
str_ += '\\caption{{{}}}'.format(self.caption)
264+
265+
if self.label is None:
266+
pass
267+
else:
268+
str_ += '\\label{{{}}}'.format(self.label)
269+
270+
# a double-backslash is required at the end of the line
271+
# as discussed here:
272+
# https://tex.stackexchange.com/questions/219138
273+
str_ += '\\\\\n'
274+
else:
275+
if self.caption is None and self.label is None:
276+
# then write output only in a tabular environment
292277
pass
293278
else:
294-
buf.write('\\label{{{}}}'.format(self.label))
279+
# then write output in a nested table/tabular environment
280+
if self.caption is None:
281+
caption_ = ''
282+
else:
283+
caption_ = '\n\\caption{{{}}}'.format(self.caption)
284+
285+
if self.label is None:
286+
label_ = ''
287+
else:
288+
label_ = '\n\\label{{{}}}'.format(self.label)
289+
290+
str_ += '\\begin{{table}}\n\\centering{}{}\n'.format(
291+
caption_,
292+
label_
293+
)
295294

296-
# a double-backslash is required at the end of the line
297-
# as discussed here:
298-
# https://tex.stackexchange.com/questions/219138
299-
buf.write('\\\\\n')
295+
str_ += '\\begin{{tabular}}{{{fmt}}}\n'.format(fmt=column_format)
300296

301-
def _write_tabular_end(self, buf):
297+
return str_
298+
299+
def _build_latex_end_env(self):
302300
"""
303-
write the end of a tabular environment or nested table/tabular
304-
environment
301+
Write the end of the latex environment.
302+
303+
This can be a tabular environment or nested table/tabular environments
304+
depending on the arguments passed to ``LatexFormatter.__init__()``.
305+
306+
:return: string to be written to ``buf``
305307
"""
306-
buf.write('\\bottomrule\n')
307-
buf.write('\\end{tabular}\n')
308-
if self.caption is None and self.label is None:
309-
pass
308+
str_ = ''
309+
310+
if self.longtable:
311+
str_ += '\\end{longtable}\n'
310312
else:
311-
buf.write('\\end{table}\n')
313+
str_ += '\\bottomrule\n'
314+
str_ += '\\end{tabular}\n'
315+
if self.caption is None and self.label is None:
316+
pass
317+
else:
318+
str_ += '\\end{table}\n'
312319

313-
@staticmethod
314-
def _write_longtable_end(buf):
315-
"""
316-
write the end of a longtable environment
317-
"""
318-
buf.write('\\end{longtable}\n')
320+
return str_

0 commit comments

Comments
 (0)