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

Detect terminal text-based-browsers better and block them #1483

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions tests/core/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,8 @@ def test_open_in_browser_success(
) -> None:
# Set DISPLAY environ to be able to run test in CI
os.environ["DISPLAY"] = ":0"
# Set TERM environ to be able to check text-browsers
os.environ["TERM"] = "xterm-256color"
Comment on lines +430 to +431
Copy link
Collaborator

Choose a reason for hiding this comment

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

Your test changes make the tests pass, but don't test the expectations from the new behavior:

  • is the environment variable unchanged?
  • can we test specifically what happens if there is no 'valid' webbrowser found?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'm a bit confused about writing the tests for this. The TERM environ doesn't really change, how do we test its transitory absence?
Also writing a test specifically for text_browser sounds good but again not sure what we can test. We can assert if TERM environ doesn't exist inos.environ but that's a value we are setting and not what we are fetching from the function.

mocked_report_success = mocker.patch(MODULE + ".Controller.report_success")
mock_get = mocker.patch(MODULE + ".webbrowser.get")
mock_open = mock_get.return_value.open
Expand All @@ -447,6 +449,7 @@ def test_open_in_browser_fail__no_browser_controller(
self, mocker: MockerFixture, controller: Controller
) -> None:
os.environ["DISPLAY"] = ":0"
os.environ["TERM"] = "xterm-256color"
error = "No runnable browser found"
mocked_report_error = mocker.patch(MODULE + ".Controller.report_error")
mocker.patch(MODULE + ".webbrowser.get").side_effect = webbrowser.Error(error)
Expand Down
4 changes: 4 additions & 0 deletions zulipterminal/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,8 @@ def open_in_browser(self, url: str) -> None:
try:
# Checks for a runnable browser in the system and returns
# its browser controller, if found, else reports an error
term = os.environ.get("TERM") # Saving the original value
del os.environ["TERM"] # Temporarily deleting variable
Comment on lines +413 to +414
Copy link
Collaborator

Choose a reason for hiding this comment

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

This looks like pop.

browser_controller = webbrowser.get()
# Suppress stdout and stderr when opening browser
with suppress_output():
Expand All @@ -424,6 +426,8 @@ def open_in_browser(self, url: str) -> None:
[f"The link was successfully opened using {browser_name}"]
)
except webbrowser.Error as e:
if isinstance(term, str):
os.environ["TERM"] = term # resetting
Comment on lines +429 to +430
Copy link
Collaborator

Choose a reason for hiding this comment

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

This certainly shouldn't be in the exceptional block. As it is now, TERM will not be reset if there is no error. If you want something to happen in every case, you could use finally.

The simplest solution would be to reset TERM as soon as the browser is determined. If so, this may be clearer with two try blocks, so you can isolate the 'only-terminal-browsers' error from others.

That is, unless the webbrowser module does other detection of this kind after that point, which could require the environment to be set for later operations?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Using finally is a very good idea!
Re using 2 try blocks, we don't need that since TERM environ isn't used anywhere during or after unsetting it. Resetting it in finally seems better it seems like the cleaner approach.

# Set a footer text if no runnable browser is located
self.report_error([f"ERROR: {e}"])

Expand Down
Loading