Skip to content

Conversation

@dharapandya85
Copy link

@dharapandya85 dharapandya85 commented Aug 25, 2025

Fixes : #348

  • Have you followed the guidelines for contributing?
  • Have you signed the CLA?
  • Have you successfully run make lint && make test?

This PR extends the Emitter class to support structured data output in multiple formats(JSON,table), with a registry for adding formats.
Implementation Details

  • A method on the emitter to write structured data to stdout
  • Output methods: TableFormatter for human-readable tables,JSONFormatterfor machine-readable JSON
  • Implemented usage in examples.py
  • Unit tests covering all formatters and edge cases
  • Added Emitter.data() method which accepts structured data(list[dict]) and uses registered formatter based on the --format flag.
  • Implemented JSONFormatter to fetch JSON outputs with json.dumps
  • Implemented TableFormatter for printing rows and columns
  • Emitter.register_formate(name,formatter) allows registering new formats
  • Default registry includes JSON and table
  • Updated CLI (dispatcher.py) to add -- format{json,table}
  • Added example_36 in examples.py to demo usage.
  • Added unit tests in test_messages_emitter.py
  • TableFomattter, handles list of dicts, empty list and dict input
  • JSONFormatter serializes list of data

Example Run

python examples.py 36 table
>>> Running example_33 with args: ('table',)
TABLE output:
name  | status   | version
--------------------------
App A | active   | 1.0.1
App B | inactive | 2.3.0
python examples.py 36 json
>>> Running example_33 with args: ('json',)
JSON output:
[
  {
    "name": "App A",
    "version": "1.0.1",
    "status": "active"
  },
  {
    "name": "App B",
    "version": "2.3.0",
    "status": "inactive"
  }
]

@dharapandya85 dharapandya85 requested a review from tigarmo as a code owner August 25, 2025 04:24
class BaseFormatter(ABC):
@abstractmethod
def format(self,data:TabularData,headers:dict[str,str] | None=None)->str:
pass
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running make format should fix the formatting issue here

Copy link
Contributor

@lengau lengau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, please fix the broken tests and lint errors here.

@dharapandya85 dharapandya85 requested review from a team and medubelko as code owners October 1, 2025 11:49
@dharapandya85 dharapandya85 force-pushed the feat/emitter-data-output branch from f33ec01 to 7a4f4b5 Compare October 23, 2025 13:45
@dharapandya85 dharapandya85 force-pushed the feat/emitter-data-output branch from ae4958a to 00bd742 Compare November 27, 2025 09:05
Comment on lines 65 to 66
# messages.emit._initiated = False
# messages.emit._stopped = True
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should it be here?

examples.py Outdated
Comment on lines 607 to 610
# emit.message("Table output:")
# emit.data(sample_data,format="table")

# emit.structured(sample_data,fmt=fmt)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

@medubelko medubelko dismissed their stale review November 27, 2025 23:20

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
]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

something looks wrong with this file. Lot's of unnecessary changes

@dharapandya85 dharapandya85 force-pushed the feat/emitter-data-output branch 2 times, most recently from 2d05361 to e64a8dc Compare December 4, 2025 18:38
@dharapandya85 dharapandya85 force-pushed the feat/emitter-data-output branch from e64a8dc to 2afdf38 Compare December 4, 2025 18:40
@lengau lengau requested a review from Copilot December 5, 2025 20:46
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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, and TableFormatter classes for flexible output formatting
  • Implemented Emitter.data(), Emitter.table(), and Emitter.json() methods for structured data output
  • Added --format CLI 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.

"""
formatter = self._formatters.get(output_format)
if not formatter:
raise ValueError(f"Unsupported format: {format}")
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message references undefined variable format instead of the parameter output_format. This will raise a NameError.

Suggested change
raise ValueError(f"Unsupported format: {format}")
raise ValueError(f"Unsupported format: {output_format}")

Copilot uses AI. Check for mistakes.
Comment on lines +85 to +86
_ = headers
"""Format a list of rows into a table string."""
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring is placed after the parameter line and unused variable assignment. Move this docstring to line 84, immediately after the method signature.

Suggested change
_ = headers
"""Format a list of rows into a table string."""
"""Format a list of rows into a table string."""
_ = headers

Copilot uses AI. Check for mistakes.

def example_36(*args: str) -> None:
"""Demonstrate structured output formats."""
print(">>> Running example_36 with args:", args)
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The message incorrectly refers to 'example_33' instead of 'example_36', as shown in the description. This appears to be a copy-paste error.

Copilot uses AI. Check for mistakes.
Example:
-------
>>> formatter = JsonFormatter()
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Class name in docstring example should be JSONFormatter (matching the actual class name) instead of JsonFormatter.

Suggested change
>>> formatter = JsonFormatter()
>>> formatter = JSONFormatter()

Copilot uses AI. Check for mistakes.
Example:
-------
>>> formatter = JsonFormatter()
>>> formatter.format([{"name":"Alice","age":30})
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example code is missing a closing bracket ] and has unbalanced parentheses. Should be formatter.format([{\"name\":\"Alice\",\"age\":30}]).

Suggested change
>>> formatter.format([{"name":"Alice","age":30})
>>> formatter.format([{"name":"Alice","age":30}])

Copilot uses AI. Check for mistakes.
messages, "_get_log_filepath", lambda appname: tmp_path / FAKE_LOG_NAME
)

monkeypatch.setattr(messages, "_get_log_filepath", None)
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.

class _CustomArgumentParser(argparse.ArgumentParser):
"""ArgumentParser with custom error manager."""

Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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.

Suggested change
# Type annotation for instance attribute set in __init__; aids type checking.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Output formats for complex types

4 participants