From dffd961034f9f9549820e83644c08315849b58f8 Mon Sep 17 00:00:00 2001 From: ObserverOfTime Date: Fri, 16 May 2025 19:20:03 +0300 Subject: [PATCH] feat: enable go & python bindings --- bindings/go/binding.go | 15 ++++ bindings/go/binding_test.go | 15 ++++ bindings/python/tests/test_binding.py | 12 +++ bindings/python/tree_sitter_hcl/__init__.py | 5 ++ bindings/python/tree_sitter_hcl/__init__.pyi | 1 + bindings/python/tree_sitter_hcl/binding.c | 35 +++++++++ bindings/python/tree_sitter_hcl/py.typed | 0 go.mod | 7 ++ go.sum | 36 +++++++++ pyproject.toml | 28 +++++++ setup.py | 77 ++++++++++++++++++++ tree-sitter.json | 9 --- 12 files changed, 231 insertions(+), 9 deletions(-) create mode 100644 bindings/go/binding.go create mode 100644 bindings/go/binding_test.go create mode 100644 bindings/python/tests/test_binding.py create mode 100644 bindings/python/tree_sitter_hcl/__init__.py create mode 100644 bindings/python/tree_sitter_hcl/__init__.pyi create mode 100644 bindings/python/tree_sitter_hcl/binding.c create mode 100644 bindings/python/tree_sitter_hcl/py.typed create mode 100644 go.mod create mode 100644 go.sum create mode 100644 pyproject.toml create mode 100644 setup.py diff --git a/bindings/go/binding.go b/bindings/go/binding.go new file mode 100644 index 0000000..a3f6a75 --- /dev/null +++ b/bindings/go/binding.go @@ -0,0 +1,15 @@ +package tree_sitter_hcl + +// #cgo CFLAGS: -std=c11 -fPIC +// #include "../../src/parser.c" +// #if __has_include("../../src/scanner.c") +// #include "../../src/scanner.c" +// #endif +import "C" + +import "unsafe" + +// Get the tree-sitter Language for this grammar. +func Language() unsafe.Pointer { + return unsafe.Pointer(C.tree_sitter_hcl()) +} diff --git a/bindings/go/binding_test.go b/bindings/go/binding_test.go new file mode 100644 index 0000000..d5ca44c --- /dev/null +++ b/bindings/go/binding_test.go @@ -0,0 +1,15 @@ +package tree_sitter_hcl_test + +import ( + "testing" + + tree_sitter "github.com/tree-sitter/go-tree-sitter" + tree_sitter_hcl "github.com/tree-sitter-grammars/tree-sitter-hcl/bindings/go" +) + +func TestCanLoadGrammar(t *testing.T) { + language := tree_sitter.NewLanguage(tree_sitter_hcl.Language()) + if language == nil { + t.Errorf("Error loading HCL grammar") + } +} diff --git a/bindings/python/tests/test_binding.py b/bindings/python/tests/test_binding.py new file mode 100644 index 0000000..e6727f9 --- /dev/null +++ b/bindings/python/tests/test_binding.py @@ -0,0 +1,12 @@ +from unittest import TestCase + +import tree_sitter +import tree_sitter_hcl + + +class TestLanguage(TestCase): + def test_can_load_grammar(self): + try: + tree_sitter.Language(tree_sitter_hcl.language()) + except Exception: + self.fail("Error loading HCL grammar") diff --git a/bindings/python/tree_sitter_hcl/__init__.py b/bindings/python/tree_sitter_hcl/__init__.py new file mode 100644 index 0000000..d122c48 --- /dev/null +++ b/bindings/python/tree_sitter_hcl/__init__.py @@ -0,0 +1,5 @@ +"""HCL and terraform grammar for tree-sitter""" + +from ._binding import language + +__all__ = ["language"] diff --git a/bindings/python/tree_sitter_hcl/__init__.pyi b/bindings/python/tree_sitter_hcl/__init__.pyi new file mode 100644 index 0000000..3cca9bb --- /dev/null +++ b/bindings/python/tree_sitter_hcl/__init__.pyi @@ -0,0 +1 @@ +def language() -> object: ... diff --git a/bindings/python/tree_sitter_hcl/binding.c b/bindings/python/tree_sitter_hcl/binding.c new file mode 100644 index 0000000..6d6f8b8 --- /dev/null +++ b/bindings/python/tree_sitter_hcl/binding.c @@ -0,0 +1,35 @@ +#include + +typedef struct TSLanguage TSLanguage; + +TSLanguage *tree_sitter_hcl(void); + +static PyObject* _binding_language(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) { + return PyCapsule_New(tree_sitter_hcl(), "tree_sitter.Language", NULL); +} + +static struct PyModuleDef_Slot slots[] = { +#ifdef Py_GIL_DISABLED + {Py_mod_gil, Py_MOD_GIL_NOT_USED}, +#endif + {0, NULL} +}; + +static PyMethodDef methods[] = { + {"language", _binding_language, METH_NOARGS, + "Get the tree-sitter language for this grammar."}, + {NULL, NULL, 0, NULL} +}; + +static struct PyModuleDef module = { + .m_base = PyModuleDef_HEAD_INIT, + .m_name = "_binding", + .m_doc = NULL, + .m_size = 0, + .m_methods = methods, + .m_slots = slots, +}; + +PyMODINIT_FUNC PyInit__binding(void) { + return PyModuleDef_Init(&module); +} diff --git a/bindings/python/tree_sitter_hcl/py.typed b/bindings/python/tree_sitter_hcl/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..3deb14a --- /dev/null +++ b/go.mod @@ -0,0 +1,7 @@ +module github.com/tree-sitter-grammars/tree-sitter-hcl + +go 1.22 + +require github.com/tree-sitter/go-tree-sitter v0.24.0 + +require github.com/mattn/go-pointer v0.0.1 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..0a48bbe --- /dev/null +++ b/go.sum @@ -0,0 +1,36 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= +github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tree-sitter/go-tree-sitter v0.24.0 h1:kRZb6aBNfcI/u0Qh8XEt3zjNVnmxTisDBN+kXK0xRYQ= +github.com/tree-sitter/go-tree-sitter v0.24.0/go.mod h1:x681iFVoLMEwOSIHA1chaLkXlroXEN7WY+VHGFaoDbk= +github.com/tree-sitter/tree-sitter-c v0.21.5-0.20240818205408-927da1f210eb h1:A8425heRM8mylnv4H58FPUiH+aYivyitre0PzxrfmWs= +github.com/tree-sitter/tree-sitter-c v0.21.5-0.20240818205408-927da1f210eb/go.mod h1:dOF6gtQiF9UwNh995T5OphYmtIypkjsp3ap7r9AN/iA= +github.com/tree-sitter/tree-sitter-cpp v0.22.4-0.20240818224355-b1a4e2b25148 h1:AfFPZwtwGN01BW1jDdqBVqscTwetvMpydqYZz57RSlc= +github.com/tree-sitter/tree-sitter-cpp v0.22.4-0.20240818224355-b1a4e2b25148/go.mod h1:Bh6U3viD57rFXRYIQ+kmiYtr+1Bx0AceypDLJJSyi9s= +github.com/tree-sitter/tree-sitter-embedded-template v0.21.1-0.20240819044651-ffbf64942c33 h1:TwqSV3qLp3tKSqirGLRHnjFk9Tc2oy57LIl+FQ4GjI4= +github.com/tree-sitter/tree-sitter-embedded-template v0.21.1-0.20240819044651-ffbf64942c33/go.mod h1:CvCKCt3v04Ufos1zZnNCelBDeCGRpPucaN8QczoUsN4= +github.com/tree-sitter/tree-sitter-go v0.21.3-0.20240818010209-8c0f0e7a6012 h1:Xvxck3tE5FW7F7bTS97iNM2ADMyCMJztVqn5HYKdJGo= +github.com/tree-sitter/tree-sitter-go v0.21.3-0.20240818010209-8c0f0e7a6012/go.mod h1:T40D0O1cPvUU/+AmiXVXy1cncYQT6wem4Z0g4SfAYvY= +github.com/tree-sitter/tree-sitter-html v0.20.5-0.20240818004741-d11201a263d0 h1:c46K6uh5Dz00zJeU9BfjXdb8I+E4RkUdfnWJpQADXFo= +github.com/tree-sitter/tree-sitter-html v0.20.5-0.20240818004741-d11201a263d0/go.mod h1:hcNt/kOJHcIcuMvouE7LJcYdeFUFbVpBJ6d4wmOA+tU= +github.com/tree-sitter/tree-sitter-java v0.21.1-0.20240824015150-576d8097e495 h1:jrt4qbJVEFs4H93/ITxygHc6u0TGqAkkate7TQ4wFSA= +github.com/tree-sitter/tree-sitter-java v0.21.1-0.20240824015150-576d8097e495/go.mod h1:oyaR7fLnRV0hT9z6qwE9GkaeTom/hTDwK3H2idcOJFc= +github.com/tree-sitter/tree-sitter-javascript v0.21.5-0.20240818005344-15887341e5b5 h1:om4X9AVg3asL8gxNJDcz4e/Wp+VpQj1PY3uJXKr6EOg= +github.com/tree-sitter/tree-sitter-javascript v0.21.5-0.20240818005344-15887341e5b5/go.mod h1:nNqgPoV/h9uYWk6kYEFdEAhNVOacpfpRW5SFmdaP4tU= +github.com/tree-sitter/tree-sitter-json v0.21.1-0.20240818005659-bdd69eb8c8a5 h1:pfV3G3k7NCKqKk8THBmyuh2zA33lgYHS3GVrzRR8ry4= +github.com/tree-sitter/tree-sitter-json v0.21.1-0.20240818005659-bdd69eb8c8a5/go.mod h1:GbMKRjLfk0H+PI7nLi1Sx5lHf5wCpLz9al8tQYSxpEk= +github.com/tree-sitter/tree-sitter-php v0.22.9-0.20240819002312-a552625b56c1 h1:ZXZMDwE+IhUtGug4Brv6NjJWUU3rfkZBKpemf6RY8/g= +github.com/tree-sitter/tree-sitter-php v0.22.9-0.20240819002312-a552625b56c1/go.mod h1:UKCLuYnJ312Mei+3cyTmGOHzn0YAnaPRECgJmHtzrqs= +github.com/tree-sitter/tree-sitter-python v0.21.1-0.20240818005537-55a9b8a4fbfb h1:EXEM82lFM7JjJb6qiKZXkpIDaCcbV2obNn82ghwj9lw= +github.com/tree-sitter/tree-sitter-python v0.21.1-0.20240818005537-55a9b8a4fbfb/go.mod h1:lXCF1nGG5Dr4J3BTS0ObN4xJCCICiSu/b+Xe/VqMV7g= +github.com/tree-sitter/tree-sitter-ruby v0.21.1-0.20240818211811-7dbc1e2d0e2d h1:fcYCvoXdcP1uRQYXqJHRy6Hec+uKScQdKVtMwK9JeCI= +github.com/tree-sitter/tree-sitter-ruby v0.21.1-0.20240818211811-7dbc1e2d0e2d/go.mod h1:T1nShQ4v5AJtozZ8YyAS4uzUtDAJj/iv4YfwXSbUHzg= +github.com/tree-sitter/tree-sitter-rust v0.21.3-0.20240818005432-2b43eafe6447 h1:o9alBu1J/WjrcTKEthYtXmdkDc5OVXD+PqlvnEZ0Lzc= +github.com/tree-sitter/tree-sitter-rust v0.21.3-0.20240818005432-2b43eafe6447/go.mod h1:1Oh95COkkTn6Ezp0vcMbvfhRP5gLeqqljR0BYnBzWvc= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..f9fec0c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,28 @@ +[build-system] +requires = ["setuptools>=42", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "tree-sitter-hcl" +description = "HCL and terraform grammar for tree-sitter" +version = "1.1.0" +keywords = ["incremental", "parsing", "tree-sitter", "hcl"] +classifiers = [ + "Intended Audience :: Developers", + "Topic :: Software Development :: Compilers", + "Topic :: Text Processing :: Linguistic", + "Typing :: Typed", +] +requires-python = ">=3.10" +license.text = "Apache-2.0" +readme = "README.md" + +[project.urls] +Homepage = "https://github.com/tree-sitter-grammars/tree-sitter-hcl" + +[project.optional-dependencies] +core = ["tree-sitter~=0.24"] + +[tool.cibuildwheel] +build = "cp310-*" +build-frontend = "build" diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..ea81678 --- /dev/null +++ b/setup.py @@ -0,0 +1,77 @@ +from os import path +from platform import system +from sysconfig import get_config_var + +from setuptools import Extension, find_packages, setup +from setuptools.command.build import build +from setuptools.command.egg_info import egg_info +from wheel.bdist_wheel import bdist_wheel + +sources = [ + "bindings/python/tree_sitter_hcl/binding.c", + "src/parser.c", +] +if path.exists("src/scanner.c"): + sources.append("src/scanner.c") + +macros: list[tuple[str, str | None]] = [ + ("PY_SSIZE_T_CLEAN", None), + ("TREE_SITTER_HIDE_SYMBOLS", None), +] +if limited_api := not get_config_var("Py_GIL_DISABLED"): + macros.append(("Py_LIMITED_API", "0x030A0000")) + +if system() != "Windows": + cflags = ["-std=c11", "-fvisibility=hidden"] +else: + cflags = ["/std:c11", "/utf-8"] + + +class Build(build): + def run(self): + if path.isdir("queries"): + dest = path.join(self.build_lib, "tree_sitter_hcl", "queries") + self.copy_tree("queries", dest) + super().run() + + +class BdistWheel(bdist_wheel): + def get_tag(self): + python, abi, platform = super().get_tag() + if python.startswith("cp"): + python, abi = "cp310", "abi3" + return python, abi, platform + + +class EggInfo(egg_info): + def find_sources(self): + super().find_sources() + self.filelist.recursive_include("queries", "*.scm") + self.filelist.include("src/tree_sitter/*.h") + + +setup( + packages=find_packages("bindings/python"), + package_dir={"": "bindings/python"}, + package_data={ + "tree_sitter_hcl": ["*.pyi", "py.typed"], + "tree_sitter_hcl.queries": ["*.scm"], + }, + ext_package="tree_sitter_hcl", + ext_modules=[ + Extension( + name="_binding", + sources=sources, + extra_compile_args=cflags, + define_macros=macros, + include_dirs=["src"], + py_limited_api=limited_api, + ) + ], + cmdclass={ + "build": Build, + "bdist_wheel": BdistWheel, + "egg_info": EggInfo, + }, + zip_safe=False +) diff --git a/tree-sitter.json b/tree-sitter.json index 5666d2c..e37a856 100644 --- a/tree-sitter.json +++ b/tree-sitter.json @@ -27,14 +27,5 @@ "links": { "repository": "https://github.com/tree-sitter-grammars/tree-sitter-hcl" } - }, - "bindings": { - "c": true, - "go": false, - "node": true, - "python": false, - "rust": true, - "swift": true, - "zig": false } }