Skip to content

Commit

Permalink
simplify a bit
Browse files Browse the repository at this point in the history
  • Loading branch information
czoido committed Dec 20, 2024
1 parent 859c512 commit 434da37
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 22 deletions.
13 changes: 9 additions & 4 deletions conan/cli/command.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import argparse
import inspect
import textwrap
from contextlib import redirect_stdout

from conan.api.output import ConanOutput
from conan.errors import ConanException
Expand Down Expand Up @@ -68,6 +68,8 @@ def _init_formatters(self, parser):
if formatters:
help_message = "Select the output format: {}".format(", ".join(formatters))
parser.add_argument('-f', '--format', action=OnceArgument, help=help_message)
parser.add_argument("--out-file", action=OnceArgument,
help="Write the output of the command to the specified file instead of stdout.")

@property
def name(self):
Expand All @@ -84,7 +86,7 @@ def doc(self):
def _format(self, parser, info, *args):
parser_args, _ = parser.parse_known_args(*args)

formatarg = getattr(parser_args, "format", "text")
formatarg = getattr(parser_args, "format", None) or "text"
out_file = getattr(parser_args, "out_file", None)

try:
Expand All @@ -93,8 +95,11 @@ def _format(self, parser, info, *args):
raise ConanException("{} is not a known format. Supported formatters are: {}".format(
formatarg, ", ".join(self._help_formatters)))

if out_file and "out_file" in inspect.signature(formatter).parameters.keys():
formatter(info, out_file=out_file)
if out_file:
with open(out_file, 'w') as f:
with redirect_stdout(f):
formatter(info)
ConanOutput().info(f"Formatted output saved to '{out_file}'")
else:
formatter(info)

Expand Down
4 changes: 1 addition & 3 deletions conan/cli/commands/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from conan.api.output import ConanOutput, cli_out_write, Color
from conan.cli import make_abs_path
from conan.cli.args import common_graph_args, validate_common_graph_args
from conan.cli.command import conan_command, conan_subcommand, OnceArgument
from conan.cli.command import conan_command, conan_subcommand
from conan.cli.commands.list import prepare_pkglist_compact, print_serial
from conan.cli.formatters.graph import format_graph_html, format_graph_json, format_graph_dot
from conan.cli.formatters.graph.build_order_html import format_build_order_html
Expand Down Expand Up @@ -192,8 +192,6 @@ def graph_info(conan_api, parser, subparser, *args):
help="Deployer output folder, base build folder by default if not set")
subparser.add_argument("--build-require", action='store_true', default=False,
help='Whether the provided reference is a build-require')
subparser.add_argument("--out-file", action=OnceArgument,
help="Filename of the file to save the output of the formatter.")

args = parser.parse_args(*args)

Expand Down
8 changes: 2 additions & 6 deletions conan/cli/formatters/graph/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
BINARY_DOWNLOAD, BINARY_BUILD, BINARY_MISSING, BINARY_UPDATE
from conans.client.graph.graph_error import GraphConflictError
from conans.client.installer import build_id
from conans.util.files import load, save
from conans.util.files import load


# FIXME: Check all this code when format_graph_[html/dot] use serialized graph
Expand Down Expand Up @@ -138,15 +138,11 @@ def format_graph_dot(result):
cli_out_write(_render_graph(graph, None, template, template_folder))


def format_graph_json(result, out_file=None):
def format_graph_json(result):
graph = result["graph"]
field_filter = result.get("field_filter")
package_filter = result.get("package_filter")
serial = graph.serialize()
serial = filter_graph(serial, package_filter=package_filter, field_filter=field_filter)
json_result = json.dumps({"graph": serial}, indent=4)
if out_file is not None:
ConanOutput().info(f"Formatted output saved to '{out_file}'")
save(out_file, json_result)
return
cli_out_write(json_result)
9 changes: 0 additions & 9 deletions test/integration/command/info/info_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,12 +435,3 @@ def requirements(self):

c.run("graph info . -c tools.graph:vendor=build --build='lib*'")
c.assert_listed_binary({"lib/1.0": (NO_SETTINGS_PACKAGE_ID, "Build")})


def test_write_formatter_to_file():
c = TestClient(light=True)
c.save({"conanfile.py": GenConanfile("pkg", "0.1")})
c.run("graph info . --format=json --out-file=graph.json")
assert "Formatted output saved to 'graph.json'" in c.out
graph = json.loads(c.load("graph.json"))
assert len(graph["graph"]["nodes"]) == 1
31 changes: 31 additions & 0 deletions test/integration/command_v2/test_output.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import json

from conan.test.assets.genconanfile import GenConanfile
from conan.test.utils.tools import TestClient
from conan.test.utils.env import environment_update
Expand Down Expand Up @@ -260,3 +262,32 @@ def test_exception_errors(self):
t.run("create . -vquiet", assert_error=True)
assert "ERROR: Tagged error" not in t.out
assert "ConanException: Untagged error" not in t.out


def test_formatter_redirection_to_file():
c = TestClient(light=True)
c.save({"conanfile.py": GenConanfile("pkg", "0.1")})

c.run("config home --out-file=cmd_out.txt")
assert "Formatted output saved to 'cmd_out.txt'" in c.out
cmd_out = c.load("cmd_out.txt")
assert f"{c.cache_folder}\n" == cmd_out
assert not f"{c.cache_folder}\n" == c.stdout

c.run("graph info . --format=json --out-file=graph.json")
assert "Formatted output saved to 'graph.json'" in c.out
graph = json.loads(c.load("graph.json"))
assert len(graph["graph"]["nodes"]) == 1
assert not "nodes" in c.stdout

c.run("graph info . --format=html --out-file=graph.html")
assert "Formatted output saved to 'graph.html'" in c.out
html = c.load("graph.html")
assert "<head>" in html
assert not "<head>" in c.stdout

c.run("install . --format=json --out-file=graph.json")
assert "Formatted output saved to 'graph.json'" in c.out
graph = json.loads(c.load("graph.json"))
assert len(graph["graph"]["nodes"]) == 1
assert not "nodes" in c.stdout

0 comments on commit 434da37

Please sign in to comment.