Skip to content

Commit

Permalink
fix: handle missing tree-sitter-language binaries (#4046)
Browse files Browse the repository at this point in the history
  • Loading branch information
tconbeer authored Jan 22, 2024
1 parent d9ecd9f commit 9f43d30
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `SelectionList` option IDs are usable as soon as the widget is instantiated https://github.com/Textualize/textual/issues/3903
- Fix issue with `Strip.crop` when crop window start aligned with strip end https://github.com/Textualize/textual/pull/3998
- Fixed Strip.crop_extend https://github.com/Textualize/textual/pull/4011
- Fixed a crash if the `TextArea` language was set but tree-sitter lanuage binaries were not installed https://github.com/Textualize/textual/issues/4045


## [0.47.1] - 2023-01-05
Expand Down
12 changes: 10 additions & 2 deletions src/textual/document/_syntax_aware_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,16 @@ def __init__(
if isinstance(language, str):
if language not in BUILTIN_LANGUAGES:
raise SyntaxAwareDocumentError(f"Invalid language {language!r}")
self.language = get_language(language)
self._parser = get_parser(language)
# If tree-sitter-languages is not installed properly, get_language
# and get_parser may raise an OSError when unable to load their
# resources
try:
self.language = get_language(language)
self._parser = get_parser(language)
except OSError as e:
raise SyntaxAwareDocumentError(
f"Could not find binaries for {language!r}"
) from e
else:
self.language = language
self._parser = Parser()
Expand Down
31 changes: 30 additions & 1 deletion tests/text_area/test_languages.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

from textual.app import App, ComposeResult
from textual.widgets import TextArea
from textual.widgets.text_area import LanguageDoesNotExist
from textual.widgets.text_area import (
Document,
LanguageDoesNotExist,
SyntaxAwareDocument,
)


class TextAreaApp(App):
Expand Down Expand Up @@ -96,3 +100,28 @@ async def test_register_language_existing_language():

# We've overridden the highlight query with a blank one, so there are no highlights.
assert text_area._highlights == {}


@pytest.mark.syntax
async def test_language_binary_missing(monkeypatch: pytest.MonkeyPatch):
# mock a failed installation of tree-sitter-language binaries by
# raising an OSError from get_language
def raise_oserror(_):
raise OSError(
"/path/to/tree_sitter_languages/languages.so: "
"cannot open shared object file: No such file or directory"
)

monkeypatch.setattr(
"textual.document._syntax_aware_document.get_language", raise_oserror
)

app = TextAreaApp()
async with app.run_test():
text_area = app.query_one(TextArea) # does not crash
assert text_area.language == "python"
# resulting document is not a SyntaxAwareDocument and does not
# support highlights
assert isinstance(text_area.document, Document)
assert not isinstance(text_area.document, SyntaxAwareDocument)
assert text_area._highlights == {}

0 comments on commit 9f43d30

Please sign in to comment.