github.com/xzntrc/go-enry/v2@v2.0.0-20230215091818-766cc1d65498/python/enry.py (about) 1 """ 2 Python library calling enry Go implementation trough cFFI (API, out-of-line) and Cgo. 3 """ 4 5 from _c_enry import ffi, lib 6 7 ## cgo -> ffi helpers 8 def py_bytes_to_go(py_bytes: bytes): 9 c_bytes = ffi.new("char[]", len(py_bytes)) 10 go_slice = ffi.new("GoSlice *", [c_bytes, len(py_bytes), len(py_bytes)]) 11 return (go_slice[0], c_bytes) 12 13 def py_str_to_go(py_str: str): 14 str_bytes = py_str.encode() 15 c_str = ffi.new("char[]", str_bytes) 16 go_str = ffi.new("_GoString_ *", [c_str, len(str_bytes)]) 17 return (go_str[0], c_str) 18 19 def go_str_to_py(go_str: str): 20 str_len = go_str.n 21 if str_len > 0: 22 return ffi.unpack(go_str.p, go_str.n).decode() 23 return "" 24 25 def go_bool_to_py(go_bool: bool): 26 return go_bool == 1 27 28 29 ## API, TODO(bzz): add docstrings 30 def language(filename: str, content: bytes) -> str: 31 fName, c_str = py_str_to_go(filename) 32 fContent, c_bytes = py_bytes_to_go(content) 33 guess = lib.GetLanguage(fName, fContent) 34 lang = go_str_to_py(guess) 35 return lang 36 37 def language_by_extension(filename: str) -> str: 38 fName, c_str = py_str_to_go(filename) 39 guess = lib.GetLanguageByExtension(fName) 40 lang = go_str_to_py(guess.r0) 41 return lang 42 43 def language_by_filename(filename: str) -> str: 44 fName, c_str = py_str_to_go(filename) 45 guess = lib.GetLanguageByFilename(fName) 46 lang = go_str_to_py(guess.r0) 47 return lang 48 49 def is_vendor(filename: str) -> bool: 50 fName, c_str = py_str_to_go(filename) 51 guess = lib.IsVendor(fName) 52 return go_bool_to_py(guess) 53 54 def is_generated(filename: str, content: bytes) -> bool: 55 fname, c_str = py_str_to_go(filename) 56 fcontent, c_bytes = py_bytes_to_go(content) 57 guess = lib.IsGenerated(fname, fcontent) 58 return go_bool_to_py(guess) 59 60 61 ## Tests 62 from collections import namedtuple 63 64 def main(): 65 TestFile = namedtuple("TestFile", "name, content, lang") 66 files = [ 67 TestFile("Parse.hs", b"", "Haskell"), TestFile("some.cpp", b"", "C++"), 68 TestFile("orand.go", b"", "Go"), TestFile("type.h", b"", "C"), 69 TestFile(".bashrc", b"", "Shell"), TestFile(".gitignore", b"", "Ignore List") 70 ] 71 72 print("\nstrategy: extension") 73 for f in files: 74 lang = language_by_extension(f.name) 75 print("\tfile: {:10s} language: '{}'".format(f.name, lang)) 76 77 print("\nstrategy: filename") 78 for f in files: 79 lang = language_by_filename(f.name) 80 print("\tfile: {:10s} language: '{}'".format(f.name, lang)) 81 82 print("\ncheck: is vendor?") 83 for f in files: 84 vendor = is_vendor(f.name) 85 print("\tfile: {:10s} vendor: '{}'".format(f.name, vendor)) 86 87 print("\nstrategy: all") 88 for f in files: 89 lang = language(f.name, f.content) 90 print("\tfile: {:10s} language: '{}'".format(f.name, lang)) 91 assert lang == f.lang, "Expected '{}' but got '{}'".format(f.lang, lang) 92 93 if __name__ == "__main__": 94 main()