feat(emitter):add structured data output with JSON and table formatting#380
feat(emitter):add structured data output with JSON and table formatting#380dharapandya85 wants to merge 5 commits intocanonical:mainfrom
Conversation
lengau
left a comment
There was a problem hiding this comment.
Hi, please fix the broken tests and lint errors here.
f33ec01 to
7a4f4b5
Compare
ae4958a to
00bd742
Compare
craft_cli/pytest_plugin.py
Outdated
| # messages.emit._initiated = False | ||
| # messages.emit._stopped = True |
examples.py
Outdated
| # emit.message("Table output:") | ||
| # emit.data(sample_data,format="table") | ||
|
|
||
| # emit.structured(sample_data,fmt=fmt) |
Problem solved, and no doc changes that require my review.
pyproject.toml
Outdated
| "FBT002", # Boolean default value in function definition (preserving for backwards-comp) | ||
| "S101", # Use of `assert` detected | ||
| ] | ||
|
|
There was a problem hiding this comment.
something looks wrong with this file. Lot's of unnecessary changes
e64a8dc to
2afdf38
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds structured data output capabilities to the Emitter class, supporting JSON and table formatting for machine and human-readable output. The implementation includes a formatter registry pattern, CLI integration, and comprehensive test coverage.
Key changes:
- Added
BaseFormatter,JSONFormatter, andTableFormatterclasses for flexible output formatting - Implemented
Emitter.data(),Emitter.table(), andEmitter.json()methods for structured data output - Added
--formatCLI argument with json/table choices (filtered from help output)
Reviewed changes
Copilot reviewed 13 out of 14 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| craft_cli/messages.py | Core formatter classes and Emitter methods for structured data output |
| craft_cli/dispatcher.py | Added --format CLI argument and filtered it from command help |
| craft_cli/helptexts.py | Fixed help text generation when options list is empty |
| craft_cli/printer.py | Added raw_output parameter support to show() method |
| examples.py | Added example_36 demonstrating structured output formats |
| tests/unit/test_messages_emitter.py | Added unit tests for formatters and updated double init test |
| tests/unit/test_help.py | Updated tests to reflect filtered global options from help |
| tests/integration/test_messages_integration.py | Adjusted timing thresholds for test stability |
| craft_cli/init.py | Exposed Emitter and complete in public API |
| craft_cli/pytest_plugin.py | Added type ignore comments for pytest imports |
| craft_cli/completion/completion.py | Added explicit type annotation for template render |
| docs/conf.py | Added type ignore comment for sphinx import |
| pyproject.toml | File deleted (full file removal) |
Comments suppressed due to low confidence (1)
pyproject.toml:1
- The entire pyproject.toml file has been deleted. This removes critical project metadata, dependencies, and build configuration. This change should be reverted unless there's a deliberate migration to a different build system.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
craft_cli/messages.py
Outdated
|
|
||
| Example: | ||
| ------- | ||
| >>> formatter = JsonFormatter() |
There was a problem hiding this comment.
Class name in docstring example should be JSONFormatter (matching the actual class name) instead of JsonFormatter.
| >>> formatter = JsonFormatter() | |
| >>> formatter = JSONFormatter() |
| Example: | ||
| ------- | ||
| >>> formatter = JsonFormatter() | ||
| >>> formatter.format([{"name":"Alice","age":30}) |
There was a problem hiding this comment.
The example code is missing a closing bracket ] and has unbalanced parentheses. Should be formatter.format([{\"name\":\"Alice\",\"age\":30}]).
| >>> formatter.format([{"name":"Alice","age":30}) | |
| >>> formatter.format([{"name":"Alice","age":30}]) |
| messages, "_get_log_filepath", lambda appname: tmp_path / FAKE_LOG_NAME | ||
| ) | ||
|
|
||
| monkeypatch.setattr(messages, "_get_log_filepath", None) |
There was a problem hiding this comment.
Setting _get_log_filepath to None will cause an error when it's called as a function. This should be a lambda or mock function that returns a path.
|
|
||
| class _CustomArgumentParser(argparse.ArgumentParser): | ||
| """ArgumentParser with custom error manager.""" | ||
|
|
There was a problem hiding this comment.
[nitpick] This class attribute appears to be added without context. If this is documenting an existing attribute for type checking, consider adding a comment explaining its purpose.
| # Type annotation for instance attribute set in __init__; aids type checking. |
|
Hi @dharapandya85, Are you still actively working on this? I haven't seen any activity or responses to the open comments since 2025-Dec-05. |
@mr-cal, working on this project. |
000a63a to
1887069
Compare
1887069 to
1bcd53d
Compare
fix JSON formatter
1bcd53d to
19bdba0
Compare
craft_cli/dispatcher.py
Outdated
| class _CustomArgumentParser(argparse.ArgumentParser): | ||
| """ArgumentParser with custom error manager.""" | ||
|
|
||
| _help_builder: HelpBuilder |
There was a problem hiding this comment.
I don't understand why this is here?
craft_cli/dispatcher.py
Outdated
| parser.add_argument( | ||
| "--format", | ||
| choices=["json", "table"], | ||
| default="table", | ||
| help="Format for structured output", | ||
| ) |
There was a problem hiding this comment.
This should not be included by default on commands, as in many cases there is no structured output.
craft_cli/dispatcher.py
Outdated
|
|
||
| # produce the complete help message for the command | ||
| command_options = self._get_global_options() | ||
| command_options: list[tuple[str, str]] = [] |
There was a problem hiding this comment.
Doesn't this cause the global options to disappear?
tests/unit/test_messages_emitter.py
Outdated
| out = fmt.format({"foo": "bar"}) | ||
| assert "foo" in out | ||
| assert "bar" in out |
There was a problem hiding this comment.
Please test the full tabular output, not just that there are parts in it.
Fixes : #348
make lint && make test?This PR extends the
Emitterclass to support structured data output in multiple formats(JSON,table), with a registry for adding formats.Implementation Details
stdoutTableFormatterfor human-readable tables,JSONFormatterfor machine-readable JSONEmitter.data()method which accepts structured data(list[dict]) and uses registered formatter based on the--formatflag.JSONFormatterto fetch JSON outputs withjson.dumpsTableFormatterfor printing rows and columnsEmitter.register_formate(name,formatter)allows registering new formatsjson,table}example_36in examples.py to demo usage.test_messages_emitter.pyTableFomattter, handles list ofdicts, empty list anddictinputJSONFormatterserializes list of dataExample Run