Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add utilities for printing complex JSON objects #1099

Open
wants to merge 20 commits into
base: master
Choose a base branch
from

Conversation

rickwporter
Copy link

Rationale

Add utilities to make printing complex objects easier. It is common to use typer to receive JSON data from servers, and this makes it easier for users to print these JSON objects in a few common formats.

Changes

Added a rich_table.py:

  • RichTable class is a thin wrapper derived from rich.Table. It contains some default formatting for the tables, since it becomes confusing when tables are nested.
  • Added several functions starting with rich_table_factory() to create a RichTable with appropriate nesting based on the data returned by the data in the object.

Added OutputFormat and print_rich_object() to rich_utils.py:

  • OutputFormat is an enum suitable to use in typer.Option with the supported output formats
  • print_rich_object() takes care of formatting the provided object in the specified format, and and prints using the default console.

Example

Here's a simple Python example to leverage the new code:

#!/usr/bin/env python3
from typer import Typer
from typer.rich_utils import OutputFormat, print_rich_object

DATA = [
    {"name": "sna", "prop1": 1, "prop B": None, "blah": "zay"},
    {
        "name": "foo",
        "prop2": 2,
        "prop B": True,
    },
    {
        "name": "bar",
        1: "inverse",
    },
]

app = Typer()

@app.command()
def print_data(
    output_fmt: OutputFormat = OutputFormat.TEXT,
    indent: int = 2,
):
    data = DATA  # TODO: figure out how to get your data here
    print_rich_object(data, out_fmt=output_fmt, indent=indent)

if __name__ == "__main__":
    app()

Here's some sample output:

(.venv) Ricks-MBP:~/typer-rickwporter> ./example.py --help
                                                                                                                                                                                        
 Usage: example.py [OPTIONS]                                                                                                                                                            
                                                                                                                                                                                        
╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --output-fmt                [text|json|yaml]  [default: text]                                                                                                                        │
│ --indent                    INTEGER           [default: 2]                                                                                                                           │
│ --install-completion                          Install completion for the current shell.                                                                                              │
│ --show-completion                             Show completion for the current shell, to copy it or customize the installation.                                                       │
│ --help                                        Show this message and exit.                                                                                                            │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

(.venv) Ricks-MBP:~/typer-rickwporter> ./example.py
┏━━━━━━┳━━━━━━━━━━━━━━━━┓
┃ Name ┃ Properties     ┃
┡━━━━━━╇━━━━━━━━━━━━━━━━┩
│ sna  │  prop1   1     │
│      │  prop B  None  │
│      │  blah    zay   │
├──────┼────────────────┤
│ foo  │  prop2   2     │
│      │  prop B  True  │
├──────┼────────────────┤
│ bar  │  1  inverse    │
└──────┴────────────────┘
Found 3 items            
(.venv) Ricks-MBP:~/typer-rickwporter> ./example.py --output-fmt json
[
  {
    "name": "sna",
    "prop1": 1,
    "prop B": null,
    "blah": "zay"
  },
  {
    "name": "foo",
    "prop2": 2,
    "prop B": true
  },
  {
    "name": "bar",
    "1": "inverse"
  }
]
(.venv) Ricks-MBP:~/typer-rickwporter> ./example.py --output-fmt yaml
- blah: zay
  name: sna
  prop B: null
  prop1: 1
- name: foo
  prop B: true
  prop2: 2
- name: bar
  1: inverse

(.venv) Ricks-MBP:~/typer-rickwporter> 

@rickwporter
Copy link
Author

@tiangolo / @svlandeg / @patrick91 - can one of you add the feature tag to this PR? I forgot to add any labels in my initial PR creation, and I don't seem to have the ability to add a label. Thanks!

There are a couple little things in this PR which are not strictly necessary (e.g. adding --showlocals to the testing, adding .DS_Store to ignore list). I found them useful, but I'm happy to back out those changes if others think they're not worth including.

Happy for any feedback. Trying to make API development easier, so folks can just "dump" the JSON responses with some consistent formatting.

@svlandeg svlandeg added the feature New feature, enhancement or request label Dec 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature, enhancement or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants