Skip to content

Commit

Permalink
Fix for table stdout detection in some cases.
Browse files Browse the repository at this point in the history
When a table is created prior to sys.stdout being changed to some other
file object, as can be the case when a pager is used, the table would
incorrectly assume it was not drawing to a tty when it came time to
print output and would not use the proper terminal size, despite using
the correct renderer class.

This patch changes the Table.file attr to be a lazy property that checks
the user override value and otherwise returns the current value of
sys.stdout.
  • Loading branch information
mayfield committed Apr 9, 2017
1 parent 61718a2 commit 0b70402
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 14 deletions.
31 changes: 21 additions & 10 deletions shellish/layout/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,18 +149,13 @@ def __init__(self, columns=None, headers=None, accessors=None, width=None,
self.headers = tuple(headers or ())
self.width = width
self.flex = flex
self.file = file if file is not None else sys.stdout
self._file = file
self.hide_header = hide_header
self.hide_footer = hide_footer
self.column_mask = column_mask
self.align_rows = align_rows
self.default_renderer = None
if not renderer:
if not self.file.isatty():
renderer = 'plain'
else:
renderer = 'terminal'
self.renderer_class = self.lookup_renderer(renderer)
self.renderer = renderer
if cliptext is not None:
self.cliptext = cliptext
if column_padding is not None:
Expand All @@ -184,8 +179,23 @@ def close(self, exception=None):
if self.default_renderer:
self.default_renderer.close(exception=exception)

def lookup_renderer(self, name):
return self.renderer_types[name]
@property
def file(self):
if self._file is not None:
return self._file
else:
return sys.stdout

def make_renderer(self):
if not self.renderer:
if not self.file.isatty():
renderer = 'plain'
else:
renderer = 'terminal'
else:
renderer = self.renderer
Renderer = self.renderer_types[renderer]
return Renderer(self)

@classmethod
def register_renderer(cls, renderer):
Expand Down Expand Up @@ -317,6 +327,7 @@ def ns2table(ns):
}
return ns2table


def make_accessors(self, columns):
""" Accessors can be numeric keys for sequence row data, string keys
for mapping row data, or a callable function. For numeric and string
Expand Down Expand Up @@ -370,7 +381,7 @@ def print(self, rows):
rendered yet, we will make a renderer instance which will freeze
state. """
if not self.default_renderer:
self.default_renderer = self.renderer_class(self)
self.default_renderer = self.make_renderer()
self.default_renderer.print(rows)

def print_row(self, row):
Expand Down
8 changes: 4 additions & 4 deletions test/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
def calc_table(*columns, width=100, data=None, flex=False, **kwargs):
t = L.Table(columns=columns, width=width, flex=flex, column_padding=0,
**kwargs)
renderer = t.renderer_class(t)
renderer = t.make_renderer()
renderer.print(data or [])
return renderer.widths

Expand Down Expand Up @@ -190,11 +190,11 @@ def test_columns_from_accessors(self):

def test_columns_width_spec_only(self):
output, t = self.table(columns=[None, None, None])
t.renderer_class(t)
t.make_renderer()

def test_columns_empty_style_spec(self):
output, t = self.table(columns=[{}, {}, {}])
t.renderer_class(t)
t.make_renderer()

def test_empty_iter(self):
output, t = self.table([None])
Expand Down Expand Up @@ -412,7 +412,7 @@ class JSONTableRenderer(unittest.TestCase):

def setUp(self):
t = L.Table([None], renderer='json')
self.r = t.renderer_class(t)
self.r = t.make_renderer()

def test_make_key_snakecase(self):
self.assertEqual(self.r.make_key('snake_case'), 'snakeCase')
Expand Down

0 comments on commit 0b70402

Please sign in to comment.