Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at flake-libs 163 lines 4.5 kB view raw
1{ 2 lib, 3 stdenv, 4 buildPythonPackage, 5 pytestCheckHook, 6 tree-sitter, 7 symlinkJoin, 8 writeTextDir, 9 pythonOlder, 10 # `name`: grammar derivation pname in the format of `tree-sitter-<lang>` 11 name, 12 grammarDrv, 13}: 14let 15 inherit (grammarDrv) version; 16 17 snakeCaseName = lib.replaceStrings [ "-" ] [ "_" ] name; 18 drvPrefix = "python-${name}"; 19 # If the name of the grammar attribute differs from the grammar's symbol name, 20 # it could cause a symbol mismatch at load time. This manually curated collection 21 # of overrides ensures the binding can find the correct symbol 22 langIdentOverrides = { 23 tree_sitter_org_nvim = "tree_sitter_org"; 24 }; 25 langIdent = langIdentOverrides.${snakeCaseName} or snakeCaseName; 26in 27buildPythonPackage { 28 inherit version; 29 pname = drvPrefix; 30 31 src = symlinkJoin { 32 name = "${drvPrefix}-source"; 33 paths = [ 34 (writeTextDir "${snakeCaseName}/__init__.py" '' 35 from ._binding import language 36 37 __all__ = ["language"] 38 '') 39 (writeTextDir "${snakeCaseName}/binding.c" '' 40 #include <Python.h> 41 42 typedef struct TSLanguage TSLanguage; 43 44 TSLanguage *${langIdent}(void); 45 46 static PyObject* _binding_language(PyObject *self, PyObject *args) { 47 return PyLong_FromVoidPtr(${langIdent}()); 48 } 49 50 static PyMethodDef methods[] = { 51 {"language", _binding_language, METH_NOARGS, 52 "Get the tree-sitter language for this grammar."}, 53 {NULL, NULL, 0, NULL} 54 }; 55 56 static struct PyModuleDef module = { 57 .m_base = PyModuleDef_HEAD_INIT, 58 .m_name = "_binding", 59 .m_doc = NULL, 60 .m_size = -1, 61 .m_methods = methods 62 }; 63 64 PyMODINIT_FUNC PyInit__binding(void) { 65 return PyModule_Create(&module); 66 } 67 '') 68 (writeTextDir "setup.py" '' 69 from platform import system 70 from setuptools import Extension, setup 71 72 73 setup( 74 packages=["${snakeCaseName}"], 75 ext_package="${snakeCaseName}", 76 ext_modules=[ 77 Extension( 78 name="_binding", 79 sources=["${snakeCaseName}/binding.c"], 80 extra_objects = ["${grammarDrv}/parser"], 81 extra_compile_args=( 82 ["-std=c11"] if system() != 'Windows' else [] 83 ), 84 ) 85 ], 86 ) 87 '') 88 (writeTextDir "pyproject.toml" '' 89 [build-system] 90 requires = ["setuptools", "wheel"] 91 build-backend = "setuptools.build_meta" 92 93 [project] 94 name="${snakeCaseName}" 95 description = "${langIdent} grammar for tree-sitter" 96 version = "${version}" 97 keywords = ["parsing", "incremental", "python"] 98 classifiers = [ 99 "Development Status :: 4 - Beta", 100 "Intended Audience :: Developers", 101 "License :: OSI Approved :: MIT License", 102 "Topic :: Software Development :: Compilers", 103 "Topic :: Text Processing :: Linguistic", 104 ] 105 106 requires-python = ">=3.8" 107 license.text = "MIT" 108 readme = "README.md" 109 110 [project.optional-dependencies] 111 core = ["tree-sitter~=0.21"] 112 113 [tool.cibuildwheel] 114 build = "cp38-*" 115 build-frontend = "build" 116 '') 117 (writeTextDir "tests/test_language.py" '' 118 from ${snakeCaseName} import language 119 from tree_sitter import Language, Parser 120 121 # This test only checks that the binding can load the grammar from the compiled shared object. 122 # It does not verify the grammar itself; that is tested in 123 # `pkgs/development/tools/parsing/tree-sitter/grammar.nix`. 124 125 def test_language(): 126 lang = Language(language()) 127 assert lang is not None 128 parser = Parser() 129 parser.language = lang 130 tree = parser.parse(bytes("", "utf-8")) 131 assert tree is not None 132 '') 133 ]; 134 }; 135 136 preConfigure = lib.optionalString stdenv.hostPlatform.isDarwin '' 137 export DYLD_LIBRARY_PATH="${grammarDrv}" 138 ''; 139 140 preCheck = '' 141 # https://github.com/NixOS/nixpkgs/issues/255262 142 rm -r ${snakeCaseName} 143 ''; 144 145 disabled = pythonOlder "3.8"; 146 147 nativeCheckInputs = [ 148 tree-sitter 149 pytestCheckHook 150 ]; 151 pythonImportsCheck = [ snakeCaseName ]; 152 153 meta = { 154 description = "Python bindings for ${name}"; 155 license = lib.licenses.mit; 156 maintainers = with lib.maintainers; [ 157 a-jay98 158 adfaure 159 mightyiam 160 stepbrobd 161 ]; 162 }; 163}