1""" 2Python library calling enry Go implementation trough cFFI (API, out-of-line) and Cgo. 3""" 4 5from _c_enry import ffi, lib 6 7## cgo -> ffi helpers 8def 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 13def 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 19def 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 25def go_bool_to_py(go_bool: bool): 26 return go_bool == 1 27 28 29## API, TODO(bzz): add docstrings 30def 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 37def 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 43def 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 49def 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 54def 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 62from collections import namedtuple 63 64def 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 93if __name__ == "__main__": 94 main() 95