Repository: conan-io/conan

Issue:
[feature] `conan graph info` should print to stdout
### What is your suggestion?

`conan graph info` should print its primary output – the YAML code containing the dependency graph info – to the standard output stream.

Currently, it is printed to the standard error stream, which is problematic because:
* It is not immediately obvious why piping the output to a file or program doesn't work. (Experienced users will soon find that adding `2>&1` to the command line helps, but to many, this is rather arcane knowledge.)
* The YAML code gets mixed up with the status messages printed at the start, so even if you do pipe stderr to a file, the result is not a valid YAML file.

I am aware that using e.g. `--format=json` *does* result in clean output being printed to stdout as desired, but this is not obvious from the documentation, and YAML does not seem to be among the supported formats for that switch. Ideally, I'd like to see something like `--format=yaml` being an implicit default.

### Have you read the CONTRIBUTING guide?

- [X] I've read the CONTRIBUTING guide


Discussion:

Resolving patch:
diff --git a/conan/cli/commands/list.py b/conan/cli/commands/list.py
--- a/conan/cli/commands/list.py
+++ b/conan/cli/commands/list.py
@@ -47,8 +47,8 @@ def print_serial(item, indent=None, color_index=None):
 
 
 def print_list_text(results):
-    """ Do litte format modification to serialized
-    list bundle so it looks prettier on text output
+    """ Do a little format modification to serialized
+    list bundle, so it looks prettier on text output
     """
     info = results["results"]
 
diff --git a/conan/cli/commands/upload.py b/conan/cli/commands/upload.py
--- a/conan/cli/commands/upload.py
+++ b/conan/cli/commands/upload.py
@@ -9,8 +9,8 @@
 
 
 def summary_upload_list(results):
-    """ Do litte format modification to serialized
-    list bundle so it looks prettier on text output
+    """ Do a little format modification to serialized
+    list bundle, so it looks prettier on text output
     """
     ConanOutput().subtitle("Upload summary")
     info = results["results"]
diff --git a/conan/cli/formatters/graph/graph_info_text.py b/conan/cli/formatters/graph/graph_info_text.py
--- a/conan/cli/formatters/graph/graph_info_text.py
+++ b/conan/cli/formatters/graph/graph_info_text.py
@@ -1,7 +1,7 @@
 import fnmatch
 from collections import OrderedDict
 
-from conan.api.output import ConanOutput
+from conan.api.output import ConanOutput, cli_out_write
 
 
 def filter_graph(graph, package_filter=None, field_filter=None):
@@ -27,23 +27,21 @@ def format_graph_info(result):
     field_filter = result["field_filter"]
     package_filter = result["package_filter"]
 
-    out = ConanOutput()
-    out.title("Basic graph information")
+    ConanOutput().subtitle("Basic graph information")
     serial = graph.serialize()
     serial = filter_graph(serial, package_filter, field_filter)
     for n in serial["nodes"].values():
-        out.writeln(f"{n['ref']}:")  # FIXME: This can be empty for consumers and it is ugly ":"
+        cli_out_write(f"{n['ref']}:")  # FIXME: This can be empty for consumers and it is ugly ":"
         _serial_pretty_printer(n, indent="  ")
     if graph.error:
         raise graph.error
 
 
 def _serial_pretty_printer(data, indent=""):
-    out = ConanOutput()
     for k, v in data.items():
         if isinstance(v, dict):
-            out.writeln(f"{indent}{k}:")
+            cli_out_write(f"{indent}{k}:")
             # TODO: increment color too
             _serial_pretty_printer(v, indent=indent+"  ")
         else:
-            out.writeln(f"{indent}{k}: {v}")
+            cli_out_write(f"{indent}{k}: {v}")


Test patch: