Skip to content

Commit 6c7e32b

Browse files
committed
Merge pull request #3702 from cpcloud/read-and-friends-path-or-buf
ENH: allow to_html and to_latex to take a path for their first argument
2 parents b8942c9 + 5d38201 commit 6c7e32b

File tree

5 files changed

+72
-18
lines changed

5 files changed

+72
-18
lines changed

RELEASE.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ pandas 0.11.1
185185
into today's date
186186
- ``DataFrame.from_records`` did not accept empty recarrays (GH3682_)
187187
- ``DataFrame.to_csv`` will succeed with the deprecated option ``nanRep``, @tdsmith
188+
- ``DataFrame.to_html`` and ``DataFrame.to_latex`` now accept a path for
189+
their first argument (GH3702_)
188190

189191
.. _GH3164: https://github.com/pydata/pandas/issues/3164
190192
.. _GH2786: https://github.com/pydata/pandas/issues/2786
@@ -261,6 +263,7 @@ pandas 0.11.1
261263
.. _GH3676: https://github.com/pydata/pandas/issues/3676
262264
.. _GH3675: https://github.com/pydata/pandas/issues/3675
263265
.. _GH3682: https://github.com/pydata/pandas/issues/3682
266+
.. _GH3702: https://github.com/pydata/pandas/issues/3702
264267

265268
pandas 0.11.0
266269
=============

doc/source/v0.11.1.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,9 @@ Bug Fixes
273273

274274
- ``DataFrame.from_records`` did not accept empty recarrays (GH3682_)
275275

276+
- ``DataFrame.to_html`` and ``DataFrame.to_latex`` now accept a path for
277+
their first argument (GH3702_)
278+
276279
See the `full release notes
277280
<https://github.com/pydata/pandas/blob/master/RELEASE.rst>`__ or issue tracker
278281
on GitHub for a complete list.
@@ -314,3 +317,4 @@ on GitHub for a complete list.
314317
.. _GH3675: https://github.com/pydata/pandas/issues/3675
315318
.. _GH3682: https://github.com/pydata/pandas/issues/3682
316319
.. _GH3679: https://github.com/pydata/pandas/issues/3679
320+
.. _GH3702: https://github.com/pydata/pandas/issues/3702

pandas/core/format.py

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -364,21 +364,31 @@ def get_col_type(dtype):
364364
raise AssertionError(('column_format must be str or unicode, not %s'
365365
% type(column_format)))
366366

367-
self.buf.write('\\begin{tabular}{%s}\n' % column_format)
368-
self.buf.write('\\toprule\n')
369-
370-
nlevels = frame.index.nlevels
371-
for i, row in enumerate(izip(*strcols)):
372-
if i == nlevels:
373-
self.buf.write('\\midrule\n') # End of header
374-
crow = [(x.replace('_', '\\_')
375-
.replace('%', '\\%')
376-
.replace('&', '\\&') if x else '{}') for x in row]
377-
self.buf.write(' & '.join(crow))
378-
self.buf.write(' \\\\\n')
379-
380-
self.buf.write('\\bottomrule\n')
381-
self.buf.write('\\end{tabular}\n')
367+
def write(buf, frame, column_format, strcols):
368+
buf.write('\\begin{tabular}{%s}\n' % column_format)
369+
buf.write('\\toprule\n')
370+
371+
nlevels = frame.index.nlevels
372+
for i, row in enumerate(izip(*strcols)):
373+
if i == nlevels:
374+
buf.write('\\midrule\n') # End of header
375+
crow = [(x.replace('_', '\\_')
376+
.replace('%', '\\%')
377+
.replace('&', '\\&') if x else '{}') for x in row]
378+
buf.write(' & '.join(crow))
379+
buf.write(' \\\\\n')
380+
381+
buf.write('\\bottomrule\n')
382+
buf.write('\\end{tabular}\n')
383+
384+
if hasattr(self.buf, 'write'):
385+
write(self.buf, frame, column_format, strcols)
386+
elif isinstance(self.buf, basestring):
387+
with open(self.buf, 'w') as f:
388+
write(f, frame, column_format, strcols)
389+
else:
390+
raise TypeError('buf is not a file name and it has no write '
391+
'method')
382392

383393
def _format_col(self, i):
384394
formatter = self._get_formatter(i)
@@ -392,7 +402,14 @@ def to_html(self, classes=None):
392402
Render a DataFrame to a html table.
393403
"""
394404
html_renderer = HTMLFormatter(self, classes=classes)
395-
html_renderer.write_result(self.buf)
405+
if hasattr(self.buf, 'write'):
406+
html_renderer.write_result(self.buf)
407+
elif isinstance(self.buf, basestring):
408+
with open(self.buf, 'w') as f:
409+
html_renderer.write_result(f)
410+
else:
411+
raise TypeError('buf is not a file name and it has no write '
412+
' method')
396413

397414
def _get_formatted_column_labels(self):
398415
from pandas.core.index import _sparsify
@@ -574,7 +591,6 @@ def write_result(self, buf):
574591
indent = self._write_body(indent)
575592

576593
self.write('</table>', indent)
577-
578594
_put_lines(buf, self.elements)
579595

580596
def _write_header(self, indent):

pandas/core/series.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1222,7 +1222,11 @@ def to_string(self, buf=None, na_rep='NaN', float_format=None,
12221222
if buf is None:
12231223
return the_repr
12241224
else:
1225-
print >> buf, the_repr
1225+
try:
1226+
buf.write(the_repr)
1227+
except AttributeError:
1228+
with open(buf, 'w') as f:
1229+
f.write(the_repr)
12261230

12271231
def _get_repr(self, name=False, print_header=False, length=True, dtype=True,
12281232
na_rep='NaN', float_format=None):

pandas/tests/test_format.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,26 @@ def test_to_html(self):
12161216
frame = DataFrame(index=np.arange(200))
12171217
frame.to_html()
12181218

1219+
def test_to_html_filename(self):
1220+
biggie = DataFrame({'A': randn(200),
1221+
'B': tm.makeStringIndex(200)},
1222+
index=range(200))
1223+
1224+
biggie['A'][:20] = nan
1225+
biggie['B'][:20] = nan
1226+
with tm.ensure_clean('test.html') as path:
1227+
biggie.to_html(path)
1228+
with open(path, 'r') as f:
1229+
s = biggie.to_html()
1230+
s2 = f.read()
1231+
self.assertEqual(s, s2)
1232+
1233+
frame = DataFrame(index=np.arange(200))
1234+
with tm.ensure_clean('test.html') as path:
1235+
frame.to_html(path)
1236+
with open(path, 'r') as f:
1237+
self.assertEqual(frame.to_html(), f.read())
1238+
12191239
def test_to_html_with_no_bold(self):
12201240
x = DataFrame({'x': randn(5)})
12211241
ashtml = x.to_html(bold_rows=False)
@@ -1474,6 +1494,13 @@ def test_dict_entries(self):
14741494
self.assertTrue("'a': 1" in val)
14751495
self.assertTrue("'b': 2" in val)
14761496

1497+
def test_to_latex_filename(self):
1498+
with tm.ensure_clean('test.tex') as path:
1499+
self.frame.to_latex(path)
1500+
1501+
with open(path, 'r') as f:
1502+
self.assertEqual(self.frame.to_latex(), f.read())
1503+
14771504
def test_to_latex(self):
14781505
# it works!
14791506
self.frame.to_latex()

0 commit comments

Comments
 (0)