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

question: Forcing colors? #30

Closed
pawamoy opened this issue Oct 20, 2023 · 6 comments
Closed

question: Forcing colors? #30

pawamoy opened this issue Oct 20, 2023 · 6 comments

Comments

@pawamoy
Copy link
Sponsor Contributor

pawamoy commented Oct 20, 2023

To document my CLI, I use Markdown Exec which is able to execute code blocks and inject their output into the page, while converting ANSI colors to HTML style. My goal is to render the help message of my CLI with colors.

However, the code executed by Markdown Exec is executed in a subprocess, using pipes to capture standard output and error (subprocess.PIPE), and Cappa seems to do the common thing of detecting such pipes and disabling colors.

I initially thought that I could override this with the FORCE_COLOR=1 environment variable, since the Cappa backend uses Rich to print the help message. Unfortunately setting the variable seems to have no effect 🤔

I'm now trying to manually print the help message from Python, to investigate, but I'm getting lost in the code. Here's what I have:

Output.from_theme().output(format_help(cappa.Command(CommandMain), "insiders"))

...but it only prints Usage: insiders, without any colors.

So my questions are:

  • do you have any hint on how to force enable colors?
  • how can I programmatically print the help of a command?
@DanCardin
Copy link
Owner

DanCardin commented Oct 20, 2023

Both of

import subprocess
import os

output = subprocess.check_output(
    ["python", "test.py", "--help"],
    env={**os.environ, "FORCE_COLOR": "1"},
)
print(output)

and

# foo.py as FORCE_COLOR=1 python foo.py
import subprocess

output = subprocess.check_output(["python", "test.py", "--help"])
print(output)

Seem to output the ansi escape codes with my local testing

EDIT: woops, where test.py is some cappa program which calls cappa.parse on an object

@DanCardin
Copy link
Owner

The internal interface of bypassing parse or invoke is not really intentionally public/designed, but perhaps this is more like what your original snippet is trying to do?

from dataclasses import dataclass
import cappa
from cappa.help import format_help


@dataclass
class Main:
    asdf: str


command = cappa.Command(Main)
final_command = cappa.Command.collect(command)

# plus or minus
help_arg = create_help_arg()
version_arg = create_version_arg()
completion_arg = create_completion_arg()
final_command.add_meta_actions(
    help=help_arg, version=version_arg, completion=completion_arg
)
# end plus or minus

help = format_help(final_command, "insiders")
cappa.Output.from_theme().output(help)

This is obviously not ideal, because it's what cappa is doing internally rather than a purposely public API :P

@pawamoy
Copy link
Sponsor Contributor Author

pawamoy commented Oct 21, 2023

That's weird. The following command does not print colors on my end:

FORCE_COLOR=1 python -c "import subprocess, os; print(subprocess.check_output('python -minsiders -h'.split(), text=True))"

Same thing in an interactive session 🤔

This doesn't work either:

FORCE_COLOR=1 echo -e "$(python -m insiders -h)"

@DanCardin
Copy link
Owner

FORCE_COLOR=1 echo -e "$(python -m insiders -h)" doesn't output color, but echo -e "$(FORCE_COLOR=1 python -m insiders -h)" does

Although your first example does print color for me

@pawamoy
Copy link
Sponsor Contributor Author

pawamoy commented Oct 22, 2023

I had tried echo -e "$(FORCE_COLOR=1 python -m insiders -h)" too, and it doesn't output colors on my end either, that's really weird. There must be something in my environment. I'll try to add print statements to rich's code because I can't easily debug this in a shell subprocess 🤔

@pawamoy
Copy link
Sponsor Contributor Author

pawamoy commented Oct 22, 2023

OK, that was a painful investigation.

  • After a lot of print-debugging, and interactive debugging sessions which lead me nowhere...
  • I tried on another machine with very simple code and it worked:
      import cappa
      from cappa.help import format_help
      
      
      @cappa.command(name="yo")
      class CommandMain:
          arg: str = "hey"
      
      
      command = cappa.Command(CommandMain)
      final_command = cappa.Command.collect(command)
      help = format_help(final_command, "insiders")
      cappa.Output.from_theme().output(help)
  • So I tried on my current machine with the same code, and it worked too. Yet doing the same thing with the command imported from my "insiders" project, it failed.
  • So I commented out most of the things and ran the code again and again, slowly uncommenting things until colors stopped showing.

Conclusion: colors stop showing if I import run_copy (or anything else I guess) from copier. They're using Plumbum, so I suspect something there is messing with the terminal. So, not Cappa's fault 🚀

We can close this, as there's nothing actionable for Cappa here, and #35 is more suited for the second question.

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

No branches or pull requests

2 participants