Skip to content

Commit

Permalink
Add python bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
snikch committed Feb 20, 2025
1 parent b3a88cf commit 4bfe901
Show file tree
Hide file tree
Showing 16 changed files with 257 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,10 @@ jobs:
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo publish
pypi:
uses: tree-sitter/workflows/.github/workflows/package-pypi.yml@main
secrets:
PYPI_API_TOKEN: ${{secrets.PYPI_API_TOKEN}}
with:
generate: true
package-name: groq-tree-sitter-nix
Binary file added bindings/python/.DS_Store
Binary file not shown.
Binary file not shown.
12 changes: 12 additions & 0 deletions bindings/python/tests/test_binding.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from unittest import TestCase

import tree_sitter
import tree_sitter_nix


class TestLanguage(TestCase):
def test_can_load_grammar(self):
try:
tree_sitter.Language(tree_sitter_nix.language())
except Exception:
self.fail("Error loading Nix grammar")
22 changes: 22 additions & 0 deletions bindings/python/tree_sitter_nix.egg-info/PKG-INFO
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Metadata-Version: 2.2
Name: tree-sitter-nix
Version: 0.1.0
Summary: Nix grammar for tree-sitter
License: MIT
Project-URL: Homepage, https://github.com/tree-sitter/tree-sitter-nix
Keywords: incremental,parsing,tree-sitter,nix
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Compilers
Classifier: Topic :: Text Processing :: Linguistic
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: core
Requires-Dist: tree-sitter~=0.24; extra == "core"

# tree-sitter-nix

[![Build Status](https://github.com/nix-community/tree-sitter-nix/actions/workflows/nix-github-actions.yml/badge.svg)](https://github.com/nix-community/tree-sitter-nix/actions/workflows/nix-github-actions.yml)

Nix grammar for [tree-sitter](https://github.com/tree-sitter/tree-sitter).
16 changes: 16 additions & 0 deletions bindings/python/tree_sitter_nix.egg-info/SOURCES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
LICENSE
README.md
pyproject.toml
setup.py
bindings/python/tree_sitter_nix/__init__.py
bindings/python/tree_sitter_nix/__init__.pyi
bindings/python/tree_sitter_nix/binding.c
bindings/python/tree_sitter_nix/py.typed
bindings/python/tree_sitter_nix.egg-info/PKG-INFO
bindings/python/tree_sitter_nix.egg-info/SOURCES.txt
bindings/python/tree_sitter_nix.egg-info/dependency_links.txt
bindings/python/tree_sitter_nix.egg-info/not-zip-safe
bindings/python/tree_sitter_nix.egg-info/requires.txt
bindings/python/tree_sitter_nix.egg-info/top_level.txt
src/parser.c
src/scanner.c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

1 change: 1 addition & 0 deletions bindings/python/tree_sitter_nix.egg-info/not-zip-safe
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

3 changes: 3 additions & 0 deletions bindings/python/tree_sitter_nix.egg-info/requires.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

[core]
tree-sitter~=0.24
2 changes: 2 additions & 0 deletions bindings/python/tree_sitter_nix.egg-info/top_level.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
_binding
tree_sitter_nix
42 changes: 42 additions & 0 deletions bindings/python/tree_sitter_nix/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""Nix grammar for tree-sitter"""

from importlib.resources import files as _files

from ._binding import language


def _get_query(name, file):
query = _files(f"{__package__}.queries") / file
globals()[name] = query.read_text()
return globals()[name]


def __getattr__(name):
# NOTE: uncomment these to include any queries that this grammar contains:

# if name == "HIGHLIGHTS_QUERY":
# return _get_query("HIGHLIGHTS_QUERY", "highlights.scm")
# if name == "INJECTIONS_QUERY":
# return _get_query("INJECTIONS_QUERY", "injections.scm")
# if name == "LOCALS_QUERY":
# return _get_query("LOCALS_QUERY", "locals.scm")
# if name == "TAGS_QUERY":
# return _get_query("TAGS_QUERY", "tags.scm")

raise AttributeError(f"module {__name__!r} has no attribute {name!r}")


__all__ = [
"language",
# "HIGHLIGHTS_QUERY",
# "INJECTIONS_QUERY",
# "LOCALS_QUERY",
# "TAGS_QUERY",
]


def __dir__():
return sorted(__all__ + [
"__all__", "__builtins__", "__cached__", "__doc__", "__file__",
"__loader__", "__name__", "__package__", "__path__", "__spec__",
])
10 changes: 10 additions & 0 deletions bindings/python/tree_sitter_nix/__init__.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from typing import Final

# NOTE: uncomment these to include any queries that this grammar contains:

# HIGHLIGHTS_QUERY: Final[str]
# INJECTIONS_QUERY: Final[str]
# LOCALS_QUERY: Final[str]
# TAGS_QUERY: Final[str]

def language() -> object: ...
35 changes: 35 additions & 0 deletions bindings/python/tree_sitter_nix/binding.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include <Python.h>

typedef struct TSLanguage TSLanguage;

TSLanguage *tree_sitter_nix(void);

static PyObject* _binding_language(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) {
return PyCapsule_New(tree_sitter_nix(), "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);
}
Empty file.
29 changes: 29 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "tree-sitter-nix"
description = "Nix grammar for tree-sitter"
version = "0.1.0"
keywords = ["incremental", "parsing", "tree-sitter", "nix"]
classifiers = [
"Intended Audience :: Developers",
"Topic :: Software Development :: Compilers",
"Topic :: Text Processing :: Linguistic",
"Typing :: Typed",
]
authors = []
requires-python = ">=3.10"
license.text = "MIT"
readme = "README.md"

[project.urls]
Homepage = "https://github.com/tree-sitter/tree-sitter-nix"

[project.optional-dependencies]
core = ["tree-sitter~=0.24"]

[tool.cibuildwheel]
build = "cp310-*"
build-frontend = "build"
77 changes: 77 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -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_nix/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_nix", "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_nix": ["*.pyi", "py.typed"],
"tree_sitter_nix.queries": ["*.scm"],
},
ext_package="tree_sitter_nix",
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
)

0 comments on commit 4bfe901

Please sign in to comment.