Robpol86 / terminaltables

Project no longer maintained.
https://github.com/matthewdeanmartin/terminaltables
MIT License
689 stars 71 forks source link

terminaltables will fail if one of the table_data is of integer type #18

Closed xrogaan closed 8 years ago

xrogaan commented 8 years ago

Since terminaltables relies on the fact that all data present in the table_data list to be of string type, it will try to execute string operations on each of them. However, sometimes, people just want to print some integer or float data.

A good practice would be to sanitize the data, and turn it all to string before doing any operation. Or only do such operations on string data.

Traceback (most recent call last):
  File "main.py", line 208, in <module>
    cm.from_input(uInput, sInput)
  File "main.py", line 180, in from_input
    print(table.table)
  File "C:\Python27\lib\site-packages\terminaltables\base_table.py", line 126, in table
    padded_table_data = self.padded_table_data
  File "C:\Python27\lib\site-packages\terminaltables\base_table.py", line 113, in padded_table_
data
    widths = self.column_widths
  File "C:\Python27\lib\site-packages\terminaltables\base_table.py", line 92, in column_widths
    return column_widths(self.table_data)
  File "C:\Python27\lib\site-packages\terminaltables\width_and_alignment.py", line 93, in colum
n_widths
    widths[i] = max(widths[i], string_width(max(row[i].splitlines(), key=len)))
AttributeError: 'int' object has no attribute 'splitlines'
Robpol86 commented 8 years ago

This is a bad idea because if terminaltables starts to handle converting non-string types to strings, it'll run into complicated scenarios with unicode encoding/decoding in different types of environments.

It's better to leave that up to the developer and let terminaltables just handle formatting strings into tables.

Robpol86 commented 8 years ago

Also for integers it should be fine but if I support integers, then I should also support floats, which runs into the problem of how much precision (decimal spaces) to show in floats.

xrogaan commented 8 years ago

You could always let the developer decide of that, by allowing them to pass a format for such type. Add a floatfmt argument to your BaseTable, and apply it when needed?

I'm also writing an issue as to how painful it is to wrap long stings with this library, but I'll write it here because I think it is relevant to the format and type issue. It ought to be simpler than to pass data to the library, then retrieve the max_width, then apply a wrap to the entirety of my data set, then reassign the data to the library. Can't the developer tell the library which column to wrap in an analogous way as how it handle text alignment? Tell me if you'd rather a new issue for this :)

Robpol86 commented 8 years ago

Passing additional arguments such as floatfmt just complicates terminaltables and makes that argument specific to floats. If somebody subclasses the float class or uses the decimal class it just makes things too complicates for me to support.

I am considering handling string wrapping in terminaltables. I'm tracking that here: https://github.com/Robpol86/terminaltables/issues/5

Once I'm done with my colorclass refactor I plan on spending some time with terminaltables and implementing a couple of new features. No ETA though.

xrogaan commented 8 years ago

Great, string wrapping!

Not to be annoying, but I'd like just to point out that it's not really the job of the library to rant about the type of data it has to handle. I have a large data set of strings and integer, and since I use this in an interactive environment, the integers need to remain integers as I have to do operations on them before and after printing to the user. Therefore, I find myself in the annoying position to transform my integer to string, then from string to integer whenever I need them. Yes, because they're not just in lists, they're part of an object that behave as a list, so that I can feed of list of those objects to terminaltables.

If you normalize the data before anything else, wouldn't that fix the issue at hand? I don't really understand your concerns about unicode.

Robpol86 commented 8 years ago

You'll just have to do list comprehension or something for just terminaltables. I don't want to be responsible for normalizing all types of data. Normalizing only some types of data is arbitrary and will lead to more people asking "why don't you support x if you support normalizing y".

If I normalize integers then:

  1. I'll need to normalize floats/decimals. I don't want to have a function argument for float formatting since what if the developer wants different precisions for different columns/cells?
  2. I'll need to normalize None and booleans. What if the developer wants an empty string instead of the string "None" or vice versa?
  3. I'll need to normalize utf-16, emoji, or any other kind of exotic string/unicode class/subclass. I'd also need (or be asked to) support bytearrays (python 3 decoded strings). I don't have any examples off hand but I just remember how much unicode in python is a pain in the butt to support in Linux, Windows, python 2.6 - 3.5. I'd need to handle unicode decoding errors.
  4. I'll need to figure out how to normalize classes developers write with complicated str() and unicode() methods. Will I need to do len() before or after normalizing?

I leave all this up to developers in their applications.

Robpol86 commented 8 years ago

I've changed my mind after these few months and have decided to support integers/floats/etc.