Skip to content

Commit d2e14c9

Browse files
feat: update core & tests
And fix remaining issues
1 parent c84da13 commit d2e14c9

29 files changed

+1839
-2166
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,11 @@ jobs:
3434
with:
3535
python-version: ${{matrix.python}}
3636
- name: Lint
37-
run: pipx run ruff check .
37+
continue-on-error: true
38+
run: pipx run ruff check . --output-format=github
3839
- name: Build
39-
run: pip install -e .
40+
run: pip install -v -e .[tests]
4041
env:
41-
CFLAGS: "-O0 -g"
42+
CFLAGS: -Wextra -Og -g -fno-omit-frame-pointer
4243
- name: Test
43-
shell: python
44-
# run: python -Wignore:::tree_sitter -munittest
45-
run: |-
46-
try: __import__('tree_sitter').Language(1048576)
47-
except RuntimeError as err: print(err)
48-
env:
49-
PYTHONFAULTHANDLER: 1
44+
run: python -munittest -v

.gitmodules

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,3 @@
11
[submodule "tree-sitter"]
22
path = tree_sitter/core
33
url = https://github.com/tree-sitter/tree-sitter
4-
[submodule "tree-sitter-embedded-template"]
5-
path = tests/fixtures/tree-sitter-embedded-template
6-
url = https://github.com/tree-sitter/tree-sitter-embedded-template
7-
[submodule "tree-sitter-html"]
8-
path = tests/fixtures/tree-sitter-html
9-
url = https://github.com/tree-sitter/tree-sitter-html
10-
[submodule "tree-sitter-javascript"]
11-
path = tests/fixtures/tree-sitter-javascript
12-
url = https://github.com/tree-sitter/tree-sitter-javascript
13-
[submodule "tree-sitter-json"]
14-
path = tests/fixtures/tree-sitter-json
15-
url = https://github.com/tree-sitter/tree-sitter-json
16-
[submodule "tree-sitter-python"]
17-
path = tests/fixtures/tree-sitter-python
18-
url = https://github.com/tree-sitter/tree-sitter-python
19-
[submodule "tree-sitter-rust"]
20-
path = tests/fixtures/tree-sitter-rust
21-
url = https://github.com/tree-sitter/tree-sitter-rust

docs/conf.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -54,30 +54,30 @@
5454
html_favicon = "_static/favicon.png"
5555

5656

57-
special_doc = regex('\S*self[^.]+')
57+
special_doc = regex("\S*self[^.]+")
5858

5959

6060
def process_signature(_app, _what, name, _obj, _options, _signature, return_annotation):
61-
if name == 'tree_sitter.Language':
62-
return '(ptr)', return_annotation
63-
if name == 'tree_sitter.Query':
64-
return '(language, source)', return_annotation
65-
if name == 'tree_sitter.Parser':
66-
return '(language, *, included_ranges=None, timeout_micros=None)', return_annotation
67-
if name == 'tree_sitter.Range':
68-
return '(start_point, end_point, start_byte, end_byte)', return_annotation
61+
if name == "tree_sitter.Language":
62+
return "(ptr)", return_annotation
63+
if name == "tree_sitter.Query":
64+
return "(language, source)", return_annotation
65+
if name == "tree_sitter.Parser":
66+
return "(language, *, included_ranges=None, timeout_micros=None)", return_annotation
67+
if name == "tree_sitter.Range":
68+
return "(start_point, end_point, start_byte, end_byte)", return_annotation
6969

7070

7171
def process_docstring(_app, what, name, _obj, _options, lines):
72-
if what == 'data':
72+
if what == "data":
7373
lines.clear()
74-
elif what == 'method':
75-
if name.endswith('__index__'):
76-
lines[0] = 'Converts ``self`` to an integer for use as an index.'
77-
elif name.endswith('__') and lines and 'self' in lines[0]:
78-
lines[0] = f'Implements ``{special_doc.search(lines[0]).group(0)}``.'
74+
elif what == "method":
75+
if name.endswith("__index__"):
76+
lines[0] = "Converts ``self`` to an integer for use as an index."
77+
elif name.endswith("__") and lines and "self" in lines[0]:
78+
lines[0] = f"Implements ``{special_doc.search(lines[0]).group(0)}``."
7979

8080

8181
def setup(app):
82-
app.connect('autodoc-process-signature', process_signature)
83-
app.connect('autodoc-process-docstring', process_docstring)
82+
app.connect("autodoc-process-signature", process_signature)
83+
app.connect("autodoc-process-docstring", process_docstring)

pyproject.toml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ email = "maxbrunsfeld@gmail.com"
3131

3232
[project.optional-dependencies]
3333
docs = ["sphinx~=7.3", "sphinx-book-theme"]
34+
tests = [
35+
"tree-sitter-html",
36+
"tree-sitter-javascript",
37+
"tree-sitter-json",
38+
"tree-sitter-python",
39+
"tree-sitter-rust",
40+
]
3441

3542
[tool.ruff]
3643
target-version = "py39"
@@ -39,7 +46,7 @@ indent-width = 4
3946
extend-exclude = [
4047
".github",
4148
"__pycache__",
42-
"tests/fixtures",
49+
"setup.py",
4350
"tree_sitter/core",
4451
]
4552

@@ -49,6 +56,7 @@ indent-style = "space"
4956

5057
[tool.cibuildwheel]
5158
build-frontend = "build"
59+
test-extras = ["tests"]
5260
test-command = "python -munittest discover -s {project}/tests"
5361

5462
[tool.cibuildwheel.environment]

setup.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
"""Py-Tree-sitter"""
2-
31
from platform import system
42

5-
from setuptools import Extension, setup
3+
from setuptools import Extension, setup # type: ignore
64

75
setup(
86
packages=["tree_sitter"],
97
include_package_data=False,
108
package_data={
11-
"tree_sitter": ["py.typed", "*.pyi"]
9+
"tree_sitter": ["py.typed", "*.pyi"],
1210
},
1311
ext_modules=[
1412
Extension(
@@ -41,8 +39,12 @@
4139
extra_compile_args=[
4240
"-std=c11",
4341
"-fvisibility=hidden",
42+
"-Wno-cast-function-type",
4443
"-Werror=implicit-function-declaration",
45-
] if system() != "Windows" else None
44+
] if system() != "Windows" else [
45+
"/std:c11",
46+
"/wd4244",
47+
],
4648
)
47-
]
49+
],
4850
)
Lines changed: 0 additions & 1 deletion
This file was deleted.

tests/fixtures/tree-sitter-html

Lines changed: 0 additions & 1 deletion
This file was deleted.

tests/fixtures/tree-sitter-javascript

Lines changed: 0 additions & 1 deletion
This file was deleted.

tests/fixtures/tree-sitter-json

Lines changed: 0 additions & 1 deletion
This file was deleted.

tests/fixtures/tree-sitter-python

Lines changed: 0 additions & 1 deletion
This file was deleted.

tests/fixtures/tree-sitter-rust

Lines changed: 0 additions & 1 deletion
This file was deleted.

tests/test_language.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
from unittest import TestCase
2+
3+
from tree_sitter import Language, Query
4+
5+
import tree_sitter_html
6+
import tree_sitter_javascript
7+
import tree_sitter_json
8+
import tree_sitter_python
9+
import tree_sitter_rust
10+
11+
12+
class TestLanguage(TestCase):
13+
def setUp(self):
14+
self.html = tree_sitter_html.language()
15+
self.javascript = tree_sitter_javascript.language()
16+
self.json = tree_sitter_json.language()
17+
self.python = tree_sitter_python.language()
18+
self.rust = tree_sitter_rust.language()
19+
20+
def test_init_not_positive(self):
21+
self.assertRaises(ValueError, Language, -1)
22+
23+
def test_init_segv(self):
24+
self.assertRaises(RuntimeError, Language, 1024)
25+
26+
def test_properties(self):
27+
lang = Language(self.python)
28+
self.assertEqual(lang.version, 14)
29+
self.assertEqual(lang.node_kind_count, 274)
30+
self.assertEqual(lang.parse_state_count, 2831)
31+
self.assertEqual(lang.field_count, 32)
32+
33+
def test_node_kind_for_id(self):
34+
lang = Language(self.json)
35+
self.assertEqual(lang.node_kind_for_id(1), "{")
36+
self.assertEqual(lang.node_kind_for_id(3), "}")
37+
38+
def test_id_for_node_kind(self):
39+
lang = Language(self.json)
40+
self.assertEqual(lang.id_for_node_kind(":", False), 4)
41+
self.assertEqual(lang.id_for_node_kind("string", True), 20)
42+
43+
def test_node_kind_is_named(self):
44+
lang = Language(self.json)
45+
self.assertFalse(lang.node_kind_is_named(4))
46+
self.assertTrue(lang.node_kind_is_named(20))
47+
48+
def test_node_kind_is_visible(self):
49+
lang = Language(self.json)
50+
self.assertTrue(lang.node_kind_is_visible(2))
51+
52+
def test_field_name_for_id(self):
53+
lang = Language(self.json)
54+
self.assertEqual(lang.field_name_for_id(1), "key")
55+
self.assertEqual(lang.field_name_for_id(2), "value")
56+
57+
def test_field_id_for_name(self):
58+
lang = Language(self.json)
59+
self.assertEqual(lang.field_id_for_name("key"), 1)
60+
self.assertEqual(lang.field_id_for_name("value"), 2)
61+
62+
def test_next_state(self):
63+
lang = Language(self.javascript)
64+
self.assertNotEqual(lang.next_state(1, 1), 0)
65+
66+
def test_lookahead_iterator(self):
67+
lang = Language(self.javascript)
68+
self.assertIsNotNone(lang.lookahead_iterator(0))
69+
self.assertIsNone(lang.lookahead_iterator(9999))
70+
71+
def test_query(self):
72+
lang = Language(self.json)
73+
query = lang.query("(string) @string")
74+
self.assertIsInstance(query, Query)
75+
76+
def test_eq(self):
77+
self.assertEqual(Language(self.json), Language(self.json))
78+
self.assertNotEqual(Language(self.rust), Language(self.html))
79+
80+
def test_int(self):
81+
for name in ["html", "javascript", "json", "python", "rust"]:
82+
with self.subTest(language=name):
83+
ptr = getattr(self, name)
84+
lang = Language(ptr)
85+
self.assertEqual(int(lang), ptr)
86+
self.assertEqual(hash(lang), ptr)

tests/test_lookahead_iterator.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from unittest import TestCase
2+
3+
from tree_sitter import Language, Parser
4+
5+
import tree_sitter_rust
6+
7+
8+
class TestLookaheadIterator(TestCase):
9+
@classmethod
10+
def setUpClass(self):
11+
self.rust = Language(tree_sitter_rust.language())
12+
13+
def test_lookahead_iterator(self):
14+
parser = Parser(self.rust)
15+
cursor = parser.parse(b"struct Stuff{}").walk()
16+
17+
self.assertEqual(cursor.goto_first_child(), True) # struct
18+
self.assertEqual(cursor.goto_first_child(), True) # struct keyword
19+
20+
next_state = cursor.node.next_parse_state
21+
22+
self.assertNotEqual(next_state, 0)
23+
self.assertEqual(
24+
next_state, self.rust.next_state(cursor.node.parse_state, cursor.node.grammar_id)
25+
)
26+
self.assertLess(next_state, self.rust.parse_state_count)
27+
self.assertEqual(cursor.goto_next_sibling(), True) # type_identifier
28+
self.assertEqual(next_state, cursor.node.parse_state)
29+
self.assertEqual(cursor.node.grammar_name, "identifier")
30+
self.assertNotEqual(cursor.node.grammar_id, cursor.node.kind_id)
31+
32+
expected_symbols = ["//", "/*", "identifier", "line_comment", "block_comment"]
33+
lookahead = self.rust.lookahead_iterator(next_state)
34+
self.assertEqual(lookahead.language, self.rust)
35+
self.assertListEqual(list(lookahead.iter_names()), expected_symbols)
36+
37+
lookahead.reset_state(next_state)
38+
self.assertListEqual(list(lookahead.iter_names()), expected_symbols)
39+
40+
lookahead.reset_state(next_state, self.rust)
41+
self.assertListEqual(
42+
list(map(self.rust.node_kind_for_id, list(iter(lookahead)))), expected_symbols
43+
)

0 commit comments

Comments
 (0)