Display tabular data in a visually appealing ASCII table format

Overview

PrettyTable

Jazzband PyPI version Supported Python versions PyPI downloads GitHub Actions status codecov Code style: Black

Installation

Install via pip:

python -m pip install -U prettytable

Install latest development version:

python -m pip install -U git+https://github.com/jazzband/prettytable

Or from requirements.txt:

-e git://github.com/jazzband/prettytable.git#egg=prettytable

Tutorial on how to use the PrettyTable API

Getting your data into (and out of) the table

Let's suppose you have a shiny new PrettyTable:

from prettytable import PrettyTable
x = PrettyTable()

and you want to put some data into it. You have a few options.

Row by row

You can add data one row at a time. To do this you can set the field names first using the field_names attribute, and then add the rows one at a time using the add_row method:

x.field_names = ["City name", "Area", "Population", "Annual Rainfall"]
x.add_row(["Adelaide", 1295, 1158259, 600.5])
x.add_row(["Brisbane", 5905, 1857594, 1146.4])
x.add_row(["Darwin", 112, 120900, 1714.7])
x.add_row(["Hobart", 1357, 205556, 619.5])
x.add_row(["Sydney", 2058, 4336374, 1214.8])
x.add_row(["Melbourne", 1566, 3806092, 646.9])
x.add_row(["Perth", 5386, 1554769, 869.4])

All rows at once

When you have a list of rows, you can add them in one go with add_rows:

x.field_names = ["City name", "Area", "Population", "Annual Rainfall"]
x.add_rows(
    [
        ["Adelaide", 1295, 1158259, 600.5],
        ["Brisbane", 5905, 1857594, 1146.4],
        ["Darwin", 112, 120900, 1714.7],
        ["Hobart", 1357, 205556, 619.5],
        ["Sydney", 2058, 4336374, 1214.8],
        ["Melbourne", 1566, 3806092, 646.9],
        ["Perth", 5386, 1554769, 869.4],
    ]
)

Column by column

You can add data one column at a time as well. To do this you use the add_column method, which takes two arguments - a string which is the name for the field the column you are adding corresponds to, and a list or tuple which contains the column data:

x.add_column("City name",
["Adelaide","Brisbane","Darwin","Hobart","Sydney","Melbourne","Perth"])
x.add_column("Area", [1295, 5905, 112, 1357, 2058, 1566, 5386])
x.add_column("Population", [1158259, 1857594, 120900, 205556, 4336374, 3806092,
1554769])
x.add_column("Annual Rainfall",[600.5, 1146.4, 1714.7, 619.5, 1214.8, 646.9,
869.4])

Mixing and matching

If you really want to, you can even mix and match add_row and add_column and build some of your table in one way and some of it in the other. Tables built this way are kind of confusing for other people to read, though, so don't do this unless you have a good reason.

Importing data from a CSV file

If you have your table data in a comma-separated values file (.csv), you can read this data into a PrettyTable like this:

from prettytable import from_csv
with open("myfile.csv") as fp:
    mytable = from_csv(fp)

Importing data from a database cursor

If you have your table data in a database which you can access using a library which confirms to the Python DB-API (e.g. an SQLite database accessible using the sqlite module), then you can build a PrettyTable using a cursor object, like this:

import sqlite3
from prettytable import from_db_cursor

connection = sqlite3.connect("mydb.db")
cursor = connection.cursor()
cursor.execute("SELECT field1, field2, field3 FROM my_table")
mytable = from_db_cursor(cursor)

Getting data out

There are three ways to get data out of a PrettyTable, in increasing order of completeness:

  • The del_row method takes an integer index of a single row to delete.
  • The del_column method takes a field name of a single column to delete.
  • The clear_rows method takes no arguments and deletes all the rows in the table - but keeps the field names as they were so you that you can repopulate it with the same kind of data.
  • The clear method takes no arguments and deletes all rows and all field names. It's not quite the same as creating a fresh table instance, though - style related settings, discussed later, are maintained.

Displaying your table in ASCII form

PrettyTable's main goal is to let you print tables in an attractive ASCII form, like this:

+-----------+------+------------+-----------------+
| City name | Area | Population | Annual Rainfall |
+-----------+------+------------+-----------------+
| Adelaide  | 1295 |  1158259   |      600.5      |
| Brisbane  | 5905 |  1857594   |      1146.4     |
| Darwin    | 112  |   120900   |      1714.7     |
| Hobart    | 1357 |   205556   |      619.5      |
| Melbourne | 1566 |  3806092   |      646.9      |
| Perth     | 5386 |  1554769   |      869.4      |
| Sydney    | 2058 |  4336374   |      1214.8     |
+-----------+------+------------+-----------------+

You can print tables like this to stdout or get string representations of them.

Printing

To print a table in ASCII form, you can just do this:

print(x)

The old x.printt() method from versions 0.5 and earlier has been removed.

To pass options changing the look of the table, use the get_string() method documented below:

print(x.get_string())

Stringing

If you don't want to actually print your table in ASCII form but just get a string containing what would be printed if you use print(x), you can use the get_string method:

mystring = x.get_string()

This string is guaranteed to look exactly the same as what would be printed by doing print(x). You can now do all the usual things you can do with a string, like write your table to a file or insert it into a GUI.

Controlling which data gets displayed

If you like, you can restrict the output of print(x) or x.get_string to only the fields or rows you like.

The fields argument to these methods takes a list of field names to be printed:

print(x.get_string(fields=["City name", "Population"]))

gives:

+-----------+------------+
| City name | Population |
+-----------+------------+
| Adelaide  |  1158259   |
| Brisbane  |  1857594   |
| Darwin    |   120900   |
| Hobart    |   205556   |
| Melbourne |  3806092   |
| Perth     |  1554769   |
| Sydney    |  4336374   |
+-----------+------------+

The start and end arguments take the index of the first and last row to print respectively. Note that the indexing works like Python list slicing - to print the 2nd, 3rd and 4th rows of the table, set start to 1 (the first row is row 0, so the second is row 1) and set end to 4 (the index of the 4th row, plus 1):

print(x.get_string(start=1, end=4))

prints:

+-----------+------+------------+-----------------+
| City name | Area | Population | Annual Rainfall |
+-----------+------+------------+-----------------+
| Brisbane  | 5905 |    1857594 | 1146.4          |
| Darwin    | 112  |     120900 | 1714.7          |
| Hobart    | 1357 |     205556 | 619.5           |
+-----------+------+------------+-----------------+

Changing the alignment of columns

By default, all columns in a table are centre aligned.

All columns at once

You can change the alignment of all the columns in a table at once by assigning a one character string to the align attribute. The allowed strings are "l", "r" and "c" for left, right and centre alignment, respectively:

x.align = "r"
print(x)

gives:

+-----------+------+------------+-----------------+
| City name | Area | Population | Annual Rainfall |
+-----------+------+------------+-----------------+
|  Adelaide | 1295 |    1158259 |           600.5 |
|  Brisbane | 5905 |    1857594 |          1146.4 |
|    Darwin |  112 |     120900 |          1714.7 |
|    Hobart | 1357 |     205556 |           619.5 |
| Melbourne | 1566 |    3806092 |           646.9 |
|     Perth | 5386 |    1554769 |           869.4 |
|    Sydney | 2058 |    4336374 |          1214.8 |
+-----------+------+------------+-----------------+
One column at a time

You can also change the alignment of individual columns based on the corresponding field name by treating the align attribute as if it were a dictionary.

x.align["City name"] = "l"
x.align["Area"] = "c"
x.align["Population"] = "r"
x.align["Annual Rainfall"] = "c"
print(x)

gives:

+-----------+------+------------+-----------------+
| City name | Area | Population | Annual Rainfall |
+-----------+------+------------+-----------------+
| Adelaide  | 1295 |    1158259 |      600.5      |
| Brisbane  | 5905 |    1857594 |      1146.4     |
| Darwin    | 112  |     120900 |      1714.7     |
| Hobart    | 1357 |     205556 |      619.5      |
| Melbourne | 1566 |    3806092 |      646.9      |
| Perth     | 5386 |    1554769 |      869.4      |
| Sydney    | 2058 |    4336374 |      1214.8     |
+-----------+------+------------+-----------------+
Sorting your table by a field

You can make sure that your ASCII tables are produced with the data sorted by one particular field by giving get_string a sortby keyword argument, which must be a string containing the name of one field.

For example, to print the example table we built earlier of Australian capital city data, so that the most populated city comes last, we can do this:

print(x.get_string(sortby="Population"))

to get:

+-----------+------+------------+-----------------+
| City name | Area | Population | Annual Rainfall |
+-----------+------+------------+-----------------+
| Darwin    | 112  |   120900   |      1714.7     |
| Hobart    | 1357 |   205556   |      619.5      |
| Adelaide  | 1295 |  1158259   |      600.5      |
| Perth     | 5386 |  1554769   |      869.4      |
| Brisbane  | 5905 |  1857594   |      1146.4     |
| Melbourne | 1566 |  3806092   |      646.9      |
| Sydney    | 2058 |  4336374   |      1214.8     |
+-----------+------+------------+-----------------+

If we want the most populated city to come first, we can also give a reversesort=True argument.

If you always want your tables to be sorted in a certain way, you can make the setting long-term like this:

x.sortby = "Population"
print(x)
print(x)
print(x)

All three tables printed by this code will be sorted by population (you could do x.reversesort = True as well, if you wanted). The behaviour will persist until you turn it off:

x.sortby = None

If you want to specify a custom sorting function, you can use the sort_key keyword argument. Pass this a function which accepts two lists of values and returns a negative or positive value depending on whether the first list should appear before or after the second one. If your table has n columns, each list will have n+1 elements. Each list corresponds to one row of the table. The first element will be whatever data is in the relevant row, in the column specified by the sort_by argument. The remaining n elements are the data in each of the table's columns, in order, including a repeated instance of the data in the sort_by column.

Changing the appearance of your table - the easy way

By default, PrettyTable produces ASCII tables that look like the ones used in SQL database shells. But if can print them in a variety of other formats as well. If the format you want to use is common, PrettyTable makes this easy for you to do using the set_style method. If you want to produce an uncommon table, you'll have to do things slightly harder (see later).

Setting a table style

You can set the style for your table using the set_style method before any calls to print or get_string. Here's how to print a table in a format which works nicely with Microsoft Word's "Convert to table" feature:

from prettytable import MSWORD_FRIENDLY
x.set_style(MSWORD_FRIENDLY)
print(x)

In addition to MSWORD_FRIENDLY there are currently two other in-built styles you can use for your tables:

  • DEFAULT - The default look, used to undo any style changes you may have made
  • PLAIN_COLUMNS - A borderless style that works well with command line programs for columnar data
  • MARKDOWN - A style that follows Markdown syntax
  • ORGMODE - A table style that fits Org mode syntax

Other styles are likely to appear in future releases.

Changing the appearance of your table - the hard way

If you want to display your table in a style other than one of the in-built styles listed above, you'll have to set things up the hard way.

Don't worry, it's not really that hard!

Style options

PrettyTable has a number of style options which control various aspects of how tables are displayed. You have the freedom to set each of these options individually to whatever you prefer. The set_style method just does this automatically for you.

The options are these:

  • border - A boolean option (must be True or False). Controls whether or not a border is drawn around the table.
  • header - A boolean option (must be True or False). Controls whether or not the first row of the table is a header showing the names of all the fields.
  • hrules - Controls printing of horizontal rules after rows. Allowed values: FRAME, HEADER, ALL, NONE - note that these are variables defined inside the prettytable module so make sure you import them or use prettytable.FRAME etc.
  • vrules - Controls printing of vertical rules between columns. Allowed values: FRAME, ALL, NONE.
  • int_format - A string which controls the way integer data is printed. This works like: print("%<int_format>d" % data)
  • float_format - A string which controls the way floating point data is printed. This works like: print("%<float_format>f" % data)
  • padding_width - Number of spaces on either side of column data (only used if left and right paddings are None).
  • left_padding_width - Number of spaces on left hand side of column data.
  • right_padding_width - Number of spaces on right hand side of column data.
  • vertical_char - Single character string used to draw vertical lines. Default is |.
  • horizontal_char - Single character string used to draw horizontal lines. Default is -.
  • junction_char - Single character string used to draw line junctions. Default is +.

You can set the style options to your own settings in two ways:

Setting style options for the long term

If you want to print your table with a different style several times, you can set your option for the long term just by changing the appropriate attributes. If you never want your tables to have borders you can do this:

x.border = False
print(x)
print(x)
print(x)

Neither of the 3 tables printed by this will have borders, even if you do things like add extra rows in between them. The lack of borders will last until you do:

x.border = True

to turn them on again. This sort of long-term setting is exactly how set_style works. set_style just sets a bunch of attributes to pre-set values for you.

Note that if you know what style options you want at the moment you are creating your table, you can specify them using keyword arguments to the constructor. For example, the following two code blocks are equivalent:

x = PrettyTable()
x.border = False
x.header = False
x.padding_width = 5

x = PrettyTable(border=False, header=False, padding_width=5)

Changing style options just once

If you don't want to make long-term style changes by changing an attribute like in the previous section, you can make changes that last for just one get_string by giving those methods keyword arguments. To print two "normal" tables with one borderless table between them, you could do this:

print(x)
print(x.get_string(border=False))
print(x)

Displaying your table in JSON

PrettyTable will also print your tables in JSON, as a list of fields and an array of rows. Just like in ASCII form, you can actually get a string representation - just use get_json_string().

Displaying your table in HTML form

PrettyTable will also print your tables in HTML form, as <table>s. Just like in ASCII form, you can actually get a string representation - just use get_html_string(). HTML printing supports the fields, start, end, sortby and reversesort arguments in exactly the same way as ASCII printing.

Styling HTML tables

By default, PrettyTable outputs HTML for "vanilla" tables. The HTML code is quite simple. It looks like this:

<table>
  <thead>
    <tr>
      <th>City name</th>
      <th>Area</th>
      <th>Population</th>
      <th>Annual Rainfall</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Adelaide</td>
      <td>1295</td>
      <td>1158259</td>
      <td>600.5</td>
    </tr>
    <tr>
      <td>Brisbane</td>
      <td>5905</td>
      <td>1857594</td>
      <td>1146.4</td>
      ...
    </tr>
  </tbody>
</table>

If you like, you can ask PrettyTable to do its best to mimic the style options that your table has set using inline CSS. This is done by giving a format=True keyword argument to get_html_string method. Note that if you always want to print formatted HTML you can do:

x.format = True

and the setting will persist until you turn it off.

Just like with ASCII tables, if you want to change the table's style for just one get_html_string you can pass those methods keyword arguments - exactly like print and get_string.

Setting HTML attributes

You can provide a dictionary of HTML attribute name/value pairs to the get_html_string method using the attributes keyword argument. This lets you specify common HTML attributes like name, id and class that can be used for linking to your tables or customising their appearance using CSS. For example:

print(x.get_html_string(attributes={"name":"my_table", "class":"red_table"}))

will print:

<table name="my_table" class="red_table">
  <thead>
    <tr>
      <th>City name</th>
      <th>Area</th>
      <th>Population</th>
      <th>Annual Rainfall</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      ... ... ...
    </tr>
  </tbody>
</table>

Miscellaneous things

Copying a table

You can call the copy method on a PrettyTable object without arguments to return an identical independent copy of the table.

If you want a copy of a PrettyTable object with just a subset of the rows, you can use list slicing notation:

new_table = old_table[0:5]

Contributing

After editing files, use the Black linter to auto-format changed lines.

python -m pip install black
black prettytable*.py
Comments
  • Deploy to Jazzband package index from Travis CI

    Deploy to Jazzband package index from Travis CI

    For https://github.com/jazzband/prettytable/issues/18.

    This will:

    • deploy to TestPyPI on merges to master (to ensure the release mechanism runs smoothly before release day)
    • deploy to production PyPI on tags
    • using https://github.com/pypa/gh-action-pypi-publish

    TODO

    Create API tokens (https://pypi.org/help/#apitoken) and save at GitHub Actions:

    • [ ] Create an API token called prettytable-ci at https://test.pypi.org/manage/account/token/
    • [ ] Save as test_pypi_password at https://github.com/jazzband/prettytable/settings/secrets/new
    • [ ] Create an API token called prettytable-ci at https://pypi.org/manage/account/token/
    • [ ] Save as pypi_password at https://github.com/jazzband/prettytable/settings/secrets/new

    I can do (1) and (3), but don't have access to https://github.com/jazzband/prettytable/settings/secrets/new to do (2) or (4).

    @flaper87 Do you have access to https://github.com/jazzband/prettytable/settings/secrets/new, or is this also a roadie-only task?

    release 
    opened by hugovk 29
  • New PyPI release?

    New PyPI release?

    The last release on PyPI is 0.7.2 from Apr 7, 2013.

    • https://pypi.org/project/PrettyTable/#history

    There's been a few fixes in the past 6 years, would it be possible to make a new release to PyPI?

    Ping @flaper87

    Thank you!

    release 
    opened by hugovk 24
  • Better display of Chinese

    Better display of Chinese

    The display width of one Chinese character is not equal to the display width of two space characters. I recommend using chr (12288) as a filler for Chinese content.

    print('[中文]')
    print(f"[{chr(12288)}{chr(12288)}]")
    print(f"[{' ' * 4}]")
    
    [中文]
    [  ]
    [    ]
    
    opened by wuhuanyan 17
  • Add type hints from typeshed

    Add type hints from typeshed

    Let's add type hints to PrettyTable.

    The good news is much of the work is already done because typeshed has .pyi signature stubs:

    • https://github.com/python/typeshed/tree/master/stubs/prettytable/prettytable

    And here are some resources for automating the conversion of stubs into inline annotations:

    • https://typing.readthedocs.io/en/latest/#type-hint-and-stub-integration

    Tasks:

    • [x] Add this to .pre-commit-config.yaml so pre-commit adds this import to Python files and we can use newer typing Syntax on older Python 3.7:
    diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
    index 3dbc9c0..316e7f5 100644
    --- a/.pre-commit-config.yaml
    +++ b/.pre-commit-config.yaml
    @@ -15,6 +15,7 @@ repos:
         rev: 5.10.1
         hooks:
           - id: isort
    +        args: [--add-import=from __future__ import annotations]
     
       - repo: https://github.com/PyCQA/flake8
         rev: 5.0.4
    
    • [x] Apply the type hints from typeshed to this repo
    • [ ] Add mypy via pre-commit and make mypy pass (can be follow-up PR if there's much to do)
    • [x] Add py.typed and "Typing :: Typed" Trove classifier
    enhancement help wanted Hacktoberfest good first issue 
    opened by hugovk 15
  • Colorful Tables and Themes

    Colorful Tables and Themes

    I recently suggested a new enhancement (#86) and now I've created it.

    It includes:

    • Themes (colorful tables)
    • Easy Customization
    • Kwarg included (so you can do x = PrettyTable(theme = THEME.NAME))
    • A new class for themes specifically
    • Tutorial for creating / using / customizing / adding themes

    :D

    changelog: Added 
    opened by BD103 13
  • Add colorful tables and themes

    Add colorful tables and themes

    Hello! I am back again. I felt bad after leaving the original PR stale, so I came back and redid it.

    (Better late than never!)

    I tried to follow all the programming standards with Pre-commit and the likewise. Some of my goals for this are:

    • [x] Be able to print tables colored with ANSI sequences
    • [x] Custom themes
    • [x] ~Re-implement previous themes~
    • [x] Follow all standards enforced by pre-commit, etc.
    • [x] Don't create any breaking changes (part of the reason this is a separate module)
    • [x] Sufficient coverage with Pytest

    Thank you for putting up with me, ~BD103

    (Fixes #86)

    changelog: Added 
    opened by BD103 11
  • Unused Argument in _format_row

    Unused Argument in _format_row

    This isn't a big problem but,

    I had just found a unused argument 'options' in implementation of _format_rows. I thought to let you guys know that. If this is already reported I am really sorry, you see I am pretty new to this stuff.

    Describe the solution you'd like

    There are a six locations of the format row implementation . I don't know if this is even helpful . I am guessing that it is there to add a new feature. If that's the case I am really sorry.

    opened by Sarath191181208 11
  • Updated pre-commit with mypy

    Updated pre-commit with mypy

    Issue: https://github.com/jazzband/prettytable/issues/203

    mypy is added to pre-commit but doesn't pass yet. The error messages are below. I'm working on them but anybody else is welcome to pitch in as well.

    src/prettytable/prettytable.py:137: error: Need type annotation for "_field_names" (hint: "_field_names: List[<type>] = ...")
    src/prettytable/prettytable.py:138: error: Need type annotation for "_rows" (hint: "_rows: List[<type>] = ...")
    src/prettytable/prettytable.py:150: error: Need type annotation for "_widths" (hint: "_widths: List[<type>] = ...")
    src/prettytable/prettytable.py:209: error: Need type annotation for "_none_format" (hint: "_none_format: Dict[<type>, <type>] = ...")
    src/prettytable/prettytable.py:2042: error: Argument 2 to "dumps" has incompatible type "**Dict[str, object]"; expected "bool"
    src/prettytable/prettytable.py:2042: error: Argument 2 to "dumps" has incompatible type "**Dict[str, object]"; expected "Optional[Type[JSONEncoder]]"
    src/prettytable/prettytable.py:2042: error: Argument 2 to "dumps" has incompatible type "**Dict[str, object]"; expected "Union[None, int, str]"
    src/prettytable/prettytable.py:2042: error: Argument 2 to "dumps" has incompatible type "**Dict[str, object]"; expected "Optional[Tuple[str, str]]"
    src/prettytable/prettytable.py:2042: error: Argument 2 to "dumps" has incompatible type "**Dict[str, object]"; expected "Optional[Callable[[Any], Any]]"
    src/prettytable/prettytable.py:2423: error: Need type annotation for "tables" (hint: "tables: List[<type>] = ...")
    src/prettytable/prettytable.py:2424: error: Need type annotation for "last_row" (hint: "last_row: List[<type>] = ...")
    src/prettytable/prettytable.py:2425: error: Need type annotation for "rows" (hint: "rows: List[<type>] = ...")
    src/prettytable/__init__.py:52: error: Name "importlib_metadata" already defined (by an import)
    src/prettytable/colortable.py:37: error: Self argument missing for a non-static method (or an invalid type for self)
    tests/test_prettytable.py:304: error: Module "prettytable" is not valid as a type
    tests/test_prettytable.py:305: error: prettytable? has no attribute "get_string"
    tests/test_prettytable.py:309: error: Module "prettytable" is not valid as a type
    tests/test_prettytable.py:310: error: prettytable? has no attribute "get_html_string"
    tests/test_prettytable.py:314: error: Module "prettytable" is not valid as a type
    tests/test_prettytable.py:315: error: prettytable? has no attribute "get_latex_string"
    tests/test_prettytable.py:319: error: Module "prettytable" is not valid as a type
    tests/test_prettytable.py:320: error: prettytable? has no attribute "field_names"
    tests/test_prettytable.py:328: error: prettytable? has no attribute "get_string"
    tests/test_prettytable.py:367: error: Module "prettytable" is not valid as a type
    tests/test_prettytable.py:369: error: prettytable? has no attribute "get_string"
    tests/test_prettytable.py:370: error: prettytable? has no attribute "get_string"
    tests/test_prettytable.py:374: error: Module "prettytable" is not valid as a type
    tests/test_prettytable.py:376: error: prettytable? has no attribute "get_html_string"
    tests/test_prettytable.py:377: error: prettytable? has no attribute "get_html_string"
    tests/test_prettytable.py:381: error: Module "prettytable" is not valid as a type
    tests/test_prettytable.py:383: error: prettytable? has no attribute "get_latex_string"
    tests/test_prettytable.py:384: error: prettytable? has no attribute "get_latex_string"
    tests/test_prettytable.py:420: error: Module "prettytable" is not valid as a type
    tests/test_prettytable.py:421: error: prettytable? has no attribute "get_string"
    tests/test_prettytable.py:422: error: prettytable? has no attribute "get_string"
    tests/test_prettytable.py:528: error: Module "prettytable" is not valid as a type
    tests/test_prettytable.py:529: error: prettytable? has no attribute "get_string"
    tests/test_prettytable.py:533: error: Module "prettytable" is not valid as a type
    tests/test_prettytable.py:534: error: prettytable? has no attribute "get_string"
    tests/test_prettytable.py:537: error: Incompatible types in assignment (expression has type "Set[int]", variable has type "List[int]")
    tests/test_prettytable.py:784: error: "PrettyTable" has no attribute "caching"
    Found 41 errors in 4 files (checked 5 source files)
    
    changelog: Added 
    opened by phershbe 10
  • Implement Jazzband guidelines for prettytable

    Implement Jazzband guidelines for prettytable

    This issue tracks the implementation of the Jazzband guidelines for the project prettytable.

    See the TODO list below for the generally required tasks, but feel free to update it in case the project requires it.

    (Based on the list at https://github.com/jazzband/tablib/issues/378.)

    Feel free to ping a Jazzband roadie if you have any question.

    TODOs

    • [x] Fix all links in the docs (and README file etc) from old to new repo
    • [x] Add the Jazzband badge to the README file -> https://github.com/jazzband/prettytable/pull/20
    • [x] Add the Jazzband contributing guideline to the CONTRIBUTING.md or CONTRIBUTING.rst file
    • [x] Check if continuous testing works (e.g. Travis-CI, CircleCI, AppVeyor, etc) -> https://travis-ci.org/jazzband/prettytable
    • [x] Check if test coverage services work (e.g. Coveralls, Codecov, etc) -> https://codecov.io/gh/jazzband/prettytable
    • [x] Add jazzband account to PyPI project as maintainer role (e.g. URL: https://pypi.org/manage/project/prettytable/collaboration/)
    • [n/a] Add jazzband-bot as maintainer to the Read the Docs project (e.g. URL: https://readthedocs.org/dashboard/prettytable/users/)
    • [n/a] Add incoming GitHub webhook integration to Read the Docs project (e.g. URL: https://readthedocs.org/dashboard/prettytable/integrations/)
    • [x] Fix project URL in GitHub project description -> No URL
    • [n/a] Review project if other services are used and port them to Jazzband -> there's a Fussy Fox integration that's not set up: https://github.com/jazzband/prettytable/runs/188061304. I've not used this service before, do we need it here?
    • [x] Decide who is project lead for the project (if at all)
    • [x] Set up CI for Jazzband project releases if needed and open ticket if yes
    opened by hugovk 10
  • Add type hints from typeshed

    Add type hints from typeshed

    Issue: https://github.com/jazzband/prettytable/issues/203

    I didn't do the third part yet... Add mypy via pre-commit and make mypy pass (can be follow-up PR if there's much to do) ...as I'm newer to contributing and didn't want to get overwhelmed. I can open a new issue so that it doesn't get forgotten and work on that next.

    Used merge_pyi to integrate the type annotations and added appropriate args to .pre-commit-config.yaml in order for pre-commit to add the import to Python files so that newer typing syntax can be used on older Python 3.7 (as described in the issue).

    Note: Did not use Black to format as it was deleting spaces in the docstrings which presumably are supposed to be there; can use Black and then add the spaces again after if that's better.

    changelog: Added hacktoberfest-accepted 
    opened by phershbe 8
  • "Border=False" turns off all table-lines

    What did you do?

    table.border = False
    

    What did you expect to happen?

    As stated: "Controls whether a border is drawn around the table." I wanted to keep the lines in the middle of the table but not the lines on the outside.

      City name | Area | Population | Annual Rainfall  
     -----------+------+------------+----------------- 
       Adelaide | 1295 |  1158259   |      600.5       
       Brisbane | 5905 |  1857594   |      1146.4      
        Darwin  | 112  |   120900   |      1714.7      
        Hobart  | 1357 |   205556   |      619.5       
        Sydney  | 2058 |  4336374   |      1214.8      
      Melbourne | 1566 |  3806092   |      646.9       
        Perth   | 5386 |  1554769   |      869.4       
    

    What actually happened?

    All lines disappeared

     City name  Area  Population  Annual Rainfall
      Adelaide  1295   1158259         600.5
      Brisbane  5905   1857594         1146.4
       Darwin   112     120900         1714.7
       Hobart   1357    205556         619.5
       Sydney   2058   4336374         1214.8
     Melbourne  1566   3806092         646.9
       Perth    5386   1554769         869.4
    

    What versions are you using?

    • OS: Ubuntu 20.04
    • Python: 3.8.6
    • PrettyTable: 3.2.0

    Please include code that reproduces the issue.

    The best reproductions are self-contained scripts with minimal dependencies.

    from prettytable import PrettyTable
    table = PrettyTable()
    table.field_names = ["City name", "Area", "Population", "Annual Rainfall"]
    table.add_rows(
        [
            ["Adelaide", 1295, 1158259, 600.5],
            ["Brisbane", 5905, 1857594, 1146.4],
            ["Darwin", 112, 120900, 1714.7],
            ["Hobart", 1357, 205556, 619.5],
            ["Sydney", 2058, 4336374, 1214.8],
            ["Melbourne", 1566, 3806092, 646.9],
            ["Perth", 5386, 1554769, 869.4],
        ])
    table.border = False
    print(table)
    
    opened by SteffenBrinckmann 8
  • Refactor old %-formatting to use format() builtin

    Refactor old %-formatting to use format() builtin

    The old %-formatting is not ageing well in modern Python code, and has largely been superseded by format strings driven by the format() built-in. This PR pivots away from the % operator when used for string operations.

    One notable change is to the behaviour of int_format and float_format, which have been changed to optionally allowed to end with alpha char, e.g. #08x or 8.3G. Previously, only float_format optionally ended with f.

    changelog: Changed 
    opened by mwtoews 5
  • Removing all padding still results in padding existing.

    Removing all padding still results in padding existing.

    What did you do?

    Set all padding to zero, and removed all VRules

    What did you expect to happen?

    ============================================================
    Name                              Played     Won       Chips
    ============================================================
    xxxxxxxxxxxxxxxxxxxx                  xxasdfasdfzxcvzxcvzxcv
    1                   xxxxxxxxxxxxxxxxxxxx      xx           4
    ============================================================
    

    What actually happened?

    =================================================================
     Name                               Played      Won        Chips 
    =================================================================
     xxxxxxxxxxxxxxxxxxxx                   xx asdfasdf zxcvzxcvzxcv 
     1                    xxxxxxxxxxxxxxxxxxxx       xx            4 
    =================================================================
    

    What I was trying to actually achieve, but struggled to find the options for:

    ===============================================================
    Name                               Played      Won        Chips
    ===============================================================
    xxxxxxxxxxxxxxxxxxxx                   xx asdfasdf zxcvzxcvzxcv
    1                    xxxxxxxxxxxxxxxxxxxx       xx            4
    ===============================================================
    
    

    Basically, it appear impossible to create tables on PrettyTable that have zero padding, namely because space padding characters are added automatically. see: https://github.com/jazzband/prettytable/blob/master/src/prettytable/prettytable.py#L1869

    even if it would be intuitive for zero padding to mean minimum padding for internal padding, it doesn't make sense for it to exist for the outside edges.

    As it is, it's acting like what I would have expected if the vrule character was set to " " and the cross characters set to "="

    opened by ryantheleach 0
  • Printing Latex Column

    Printing Latex Column

    I have a dict()

    A2 = {
        'Variable':['Bundle Diameter','Shell Diameter','Shell Side Cross Flow area','Volumetric Flowrate','Shell Side Velocity'],
        'Result':[3.4, 34, 78.23, 1 ,  2],
        'Unit' : ['$in$', '$in$', '$ft^2$', '$ft^{3}s^{-1}$', '$fts^{-1}$']}
    

    How can I construct code such that in jupyter Unit column rendered as Latex

    opened by defencedog 1
  • Does not align when there is Chinese

    Does not align when there is Chinese

    This is my code

    table = pt.PrettyTable(["设备名称", "iRules名称", "阶段", "内容", "次数"])
    # table = pt.PrettyTable(["device", "iRules", "stage", "content", "count"])
    table.align["阶段"] = "l"
    table.align["内容"] = "l"
    for item, count in data.items():
        row = [self.obj, irules, item[0], item[1], count]
        table.add_row(row)
    print(table)
    

    output:

    +--------------------------+-----------------------+--------------+-----------------------------------------------------------+------+
    |         设备名称         |       iRules名称      | 阶段         | 内容                                                      | 次数 |
    +--------------------------+-----------------------+--------------+-----------------------------------------------------------+------+
    | bigip01_15.1.3_60.13.com | irules_ncmps_hslhttp  | HTTP_REQUEST | ERR_NOT_SUPPORTED (line 1) invoked from within HTTP::host |  4   |
    | bigip01_15.1.3_60.13.com | irules_ncmps_hslhttp  | RULE_INIT    | can't read b: no such variable while executing set a      |  5   |
    +--------------------------+-----------------------+--------------+-----------------------------------------------------------+------+
    

    by the way, how do I make the content left aligned but the header center aligned?

    thanks!!!

    opened by douloveppt 0
  • PrettyTable 3.4.1 KeyError in _stringify_header + self._justify(fieldname, width, self._align[field])

    PrettyTable 3.4.1 KeyError in _stringify_header + self._justify(fieldname, width, self._align[field])

    Is this my error or from PrettyTable?

    What did you do?

    • Try to print my PrettyTable instance

    What did you expect to happen?

    • Get a string value similar to
    +-----+-------------+-------------+-------+-------------+
    |  x  | y (h=val_0) | y (h=val_1) |  ...  | y (h=val_n) |
    +-----+-------------+-------------+-------+-------------+
    | x_0 |     y_0     |     y_1     |  ...  |     y_n     |
    +-----+-------------+-------------+-------+-------------+
    | x_1 |     y_0     |     y_1     |  ...  |     y_n     |
    +-----+-------------+-------------+-------+-------------+
    | ... |     ...     |     ...     |  ...  |     ...     |
    +-----+-------------+-------------+-------+-------------+
    | x_k |     y_0     |     y_1     |  ...  |     y_n     |
    +-----+-------------+-------------+-------+-------------+
    

    What actually happened?

    Traceback (most recent call last):
      File "/home/alejandro/Desktop/test.py", line 236, in <module>
        Create_Table(values)
      File "/home/alejandro/Desktop/test.py", line 205, in Create_Table
        print(table)
      File "/home/alejandro/.local/lib/python3.10/site-packages/prettytable/prettytable.py", line 327, in __str__
        return self.get_string()
      File "/home/alejandro/.local/lib/python3.10/site-packages/prettytable/prettytable.py", line 1717, in get_string
        lines.append(self._stringify_header(options))
      File "/home/alejandro/.local/lib/python3.10/site-packages/prettytable/prettytable.py", line 1854, in _stringify_header
        + self._justify(fieldname, width, self._align[field])
    KeyError: 'y (h=0.1)'
    

    What versions are you using?

    • OS: Ubuntu 22.04
    • Python: 3.10
    • PrettyTable: 3.4.1

    Please include code that reproduces the issue.

    The best reproductions are self-contained scripts with minimal dependencies.

    from prettytable import PrettyTable
    
    # values is a dict, where keys are floats and values are lists of tuples
    def Create_Table(values: dict):
    
        table = PrettyTable()
    
        table.field_names = ["x"]
    
        for x in values:
            row_temp = [x]
    
            for y_h in values[x]:
               # add y value
                row_temp.append(y_h[0])
                column_name = "y (h={})".format(str(y_h[1]))
                #check if the value is currently added to names
                if column_name not in table.field_names:
                    table.field_names.append(column_name)
            table.add_row(row_temp)
    
        print(table)
    
    question 
    opened by alejocp00 4
Releases(3.5.0)
  • 3.5.0(Oct 28, 2022)

    Added

    • Add py.typed and update setup.cfg (#211) @phershbe
    • Add type hints from typeshed (#205) @phershbe

    Changed

    • Convert from setuptools to hatchling (#212) @hugovk
    Source code(tar.gz)
    Source code(zip)
  • 3.4.1(Sep 2, 2022)

  • 3.4.0(Aug 25, 2022)

    Added

    • Add option to specify line break character used in pagination (#193) @myheroyuki
    • Add header alignment attribute (#183) @myheroyuki

    Fixed

    • None annotation for __init__ constructors/functions (#186) @ShobanChiddarth
    Source code(tar.gz)
    Source code(zip)
  • 3.3.0(May 5, 2022)

    Added

    • Support Python 3.11 (#181) @hugovk
    • Add flag to preserve internal borders when border=False (#180) @myheroyuki

    Fixed

    • Alignment timing fix (#179) @myheroyuki
    Source code(tar.gz)
    Source code(zip)
  • 3.2.0(Mar 7, 2022)

    Added

    • Use concrete built-in exceptions instead of Exception base class (#169) @hugovk

    Fixed

    • Fix width for custom none_format (#174) @av-guy
    • Enforce max widths for field names (#171) @OlafvdSpek
    Source code(tar.gz)
    Source code(zip)
  • 3.1.1(Feb 16, 2022)

  • 3.1.0(Feb 13, 2022)

  • 3.0.0(Jan 6, 2022)

  • 2.5.0(Dec 20, 2021)

  • 2.4.0(Nov 3, 2021)

  • 2.3.0(Nov 1, 2021)

    Added

    • Add Jupyter repr and default interpreter repr methods (#146) @amirali
    • Add custom format support (#136) @davzucky
    • Add method to generate LaTex formatted string (#133) @kinianlo

    Changed

    • Remove unused options argument in _format_rows and _format_row (#138) @Sarath191181208
    Source code(tar.gz)
    Source code(zip)
  • 2.2.1(Sep 26, 2021)

  • 2.2.0(Aug 27, 2021)

    Added

    • Add support for Python 3.10 (#125) @hugovk
    • Update issue templates (#123) @hugovk
    • Add support for positional junction characters and add "double_border" table style (#104) @guysz
    • Access properties instead of protected fields in _get_options() (#115) @guysz
    • Use declarative metadata and support PyPy3 (#117) @hugovk
    • Add auto index column (#106) @erictzimas

    Changed

    • Refactor for readability and avoid merge conflicts (#119) @hugovk
    • Remove exclamation marks from exceptions (#101) @hugovk
    Source code(tar.gz)
    Source code(zip)
  • 2.1.0(Mar 2, 2021)

    Added

    • Support formatting options in get_json_string() (#83) @kluelesskk

    Changed

    • Replace setuptools/pkg_resources with importlib.metadata for getting version (#96) @hugovk

    Fixed

    • Docs: Add documentation for align, max_width, etc. (#98) @endolith
    • Docs: Remove reference to Python 2.x print statement in README (#95) @johnthagen
    • Docs: Update get_html_string with thead and tbody tags (#84) @hugovk
    Source code(tar.gz)
    Source code(zip)
  • 2.0.0(Nov 14, 2020)

    Added

    • Add tbody and thead tags (#81) @hugovk
    • Add add_rows to add several rows at once (#75) @hugovk
    • Add Python 3.10-dev to CI Tests (#73) @dlintott

    Changed

    • Stop testing on Travis CI due to new open-source limitations (#79) @hugovk
    • Move to src/ and tests/ layout (#69) @hugovk

    Removed

    • Drop support for EOL Python 2.7 and 3.5 (#68) @hugovk

    Fixed

    • Fix padding_width = 0 (#80) @hugovk
    • Don't create universal wheel for Python 2 (and 3) (#78) @hugovk
    • Fix docs to match code: from_cursor -> from_db_cursor (#77) @hugovk
    • readme: update function name in example (#71) @antoine-gallix
    Source code(tar.gz)
    Source code(zip)
  • 1.0.1(Oct 9, 2020)

    Fixed

    • Add setuptools as a dependency (#66) @ksunden
    • Fix string comparison and deprecation warning (#62) @hugovk
    • Update release checklist to deploy from GitHub Actions (#61) @hugovk
    • Use Release Drafter to draft GH Releases from labelled PRs (#63) @hugovk
    Source code(tar.gz)
    Source code(zip)
Structured Logging for Python

structlog makes logging in Python faster, less painful, and more powerful by adding structure to your log entries. It's up to you whether you want str

Hynek Schlawack 2.3k Jan 05, 2023
changedetection.io - The best and simplest self-hosted website change detection monitoring service

changedetection.io - The best and simplest self-hosted website change detection monitoring service. An alternative to Visualping, Watchtower etc. Designed for simplicity - the main goal is to simply

7.3k Jan 01, 2023
Display tabular data in a visually appealing ASCII table format

PrettyTable Installation Install via pip: python -m pip install -U prettytable Install latest development version: python -m pip install -U git+https

Jazzband 924 Jan 05, 2023
APT-Hunter is Threat Hunting tool for windows event logs

APT-Hunter is Threat Hunting tool for windows event logs which made by purple team mindset to provide detect APT movements hidden in the sea of windows event logs to decrease the time to uncover susp

824 Jan 08, 2023
dash-manufacture-spc-dashboard is a dashboard for monitoring read-time process quality along manufacture production line

In our solution based on plotly, dash and influxdb, the user will firstly generate the specifications for different robots, and then a wide range of interactive visualizations for different machines

Dequn Teng 1 Feb 13, 2022
Track Nano accounts and notify via log file or email

nano-address-notifier Track accounts and notify via log file or email Required python libs

Joohansson (Json) 4 Nov 08, 2021
ClusterMonitor - a very simple python script which monitors and records the CPU and RAM consumption of submitted cluster jobs

ClusterMonitor A very simple python script which monitors and records the CPU and RAM consumption of submitted cluster jobs. Usage To start recording

23 Oct 04, 2021
Soda SQL Data testing, monitoring and profiling for SQL accessible data.

Soda SQL Data testing, monitoring and profiling for SQL accessible data. What does Soda SQL do? Soda SQL allows you to Stop your pipeline when bad dat

Soda Data Monitoring 51 Jan 01, 2023
Log4j alternative for Python

Log4p Log4p is the most secure logging library ever created in this and all other universes. Usage: import log4p log4p.log('"Wow, this library is sec

Isaak Uchakaev 15 Dec 16, 2022
giving — the reactive logger

giving is a simple, magical library that lets you log or "give" arbitrary data throughout a program and then process it as an event stream.

Olivier Breuleux 0 May 24, 2022
A Fast, Extensible Progress Bar for Python and CLI

tqdm tqdm derives from the Arabic word taqaddum (تقدّم) which can mean "progress," and is an abbreviation for "I love you so much" in Spanish (te quie

tqdm developers 23.7k Jan 01, 2023
A demo of Prometheus+Grafana for monitoring an ML model served with FastAPI.

ml-monitoring Jeremy Jordan This repository provides an example setup for monitoring an ML system deployed on Kubernetes.

Jeremy Jordan 176 Jan 01, 2023
Debugging-friendly exceptions for Python

Better tracebacks This is a more helpful version of Python's built-in exception message: It shows more code context and the current values of nearby v

Clemens Korndörfer 1.2k Dec 28, 2022
Integrates a UPS monitored by NUT into OctoPrint

OctoPrint UPS This OctoPrint plugin interfaces with a UPS monitored by NUT (Network UPS Tools). Requirements NUT must be configured by the user. This

Shawn Bruce 11 Jul 05, 2022
Logging system for the TPC software.

tpc_logger Logging system for the TPC software. The TPC Logger class provides a singleton for logging information within C++ code or in the python API

UC Davis Machine Learning 1 Jan 10, 2022
A very basic esp32-based logic analyzer capable of sampling digital signals at up to ~3.2MHz.

A very basic esp32-based logic analyzer capable of sampling digital signals at up to ~3.2MHz.

Davide Della Giustina 43 Dec 27, 2022
Robust and effective logging for Python 2 and 3.

Robust and effective logging for Python 2 and 3.

Chris Hager 1k Jan 04, 2023
HTTP(s) "monitoring" webpage via FastAPI+Jinja2. Inspired by https://github.com/RaymiiOrg/bash-http-monitoring

python-http-monitoring HTTP(s) "monitoring" powered by FastAPI+Jinja2+aiohttp. Inspired by bash-http-monitoring. Installation can be done with pipenv

itzk 39 Aug 26, 2022
Espion is a mini-keylogger tool that keeps track of all keys a user presses on his/her keyboard

Espion is a mini-keylogger tool that keeps track of all keys a user presses on his/her keyboard. The details get displayed on the terminal window and also stored in a log file.

Anurag.R.Simha 1 Apr 24, 2022
A cool logging replacement for Python.

Welcome to Logbook Travis AppVeyor Supported Versions Latest Version Test Coverage Logbook is a nice logging replacement. It should be easy to setup,

1.4k Nov 11, 2022