2019-06-01 17:47:13 +00:00
|
|
|
"""
|
|
|
|
Python library calling enry Go implementation trough cFFI (API, out-of-line) and Cgo.
|
|
|
|
"""
|
|
|
|
|
|
|
|
from _c_enry import ffi, lib
|
|
|
|
|
2019-11-17 14:13:41 +00:00
|
|
|
## cgo -> ffi helpers
|
|
|
|
def py_bytes_to_go(py_bytes: bytes):
|
|
|
|
c_bytes = ffi.new("char[]", len(py_bytes))
|
|
|
|
go_slice = ffi.new("GoSlice *", [c_bytes, len(py_bytes), len(py_bytes)])
|
|
|
|
return (go_slice[0], c_bytes)
|
2019-06-01 19:30:07 +00:00
|
|
|
|
2019-11-17 14:13:41 +00:00
|
|
|
def py_str_to_go(py_str: str):
|
|
|
|
str_bytes = py_str.encode()
|
|
|
|
c_str = ffi.new("char[]", str_bytes)
|
|
|
|
go_str = ffi.new("_GoString_ *", [c_str, len(str_bytes)])
|
|
|
|
return (go_str[0], c_str)
|
2019-06-01 17:47:13 +00:00
|
|
|
|
2019-11-17 14:13:41 +00:00
|
|
|
def go_str_to_py(go_str: str):
|
2019-06-01 17:47:13 +00:00
|
|
|
str_len = go_str.n
|
|
|
|
if str_len > 0:
|
|
|
|
return ffi.unpack(go_str.p, go_str.n).decode()
|
|
|
|
return ""
|
|
|
|
|
2019-11-17 14:13:41 +00:00
|
|
|
def go_bool_to_py(go_bool: bool):
|
2019-06-01 19:30:07 +00:00
|
|
|
return go_bool == 1
|
|
|
|
|
|
|
|
|
2019-11-17 14:13:41 +00:00
|
|
|
## API, TODO(bzz): add docstrings
|
|
|
|
def language(filename: str, content: bytes) -> str:
|
|
|
|
fName, c_str = py_str_to_go(filename)
|
|
|
|
fContent, c_bytes = py_bytes_to_go(content)
|
|
|
|
guess = lib.GetLanguage(fName, fContent)
|
|
|
|
lang = go_str_to_py(guess)
|
|
|
|
return lang
|
2019-06-01 19:30:07 +00:00
|
|
|
|
2019-06-01 17:47:13 +00:00
|
|
|
def language_by_extension(filename: str) -> str:
|
2019-11-17 14:13:41 +00:00
|
|
|
fName, c_str = py_str_to_go(filename)
|
2019-06-01 17:47:13 +00:00
|
|
|
guess = lib.GetLanguageByExtension(fName)
|
|
|
|
lang = go_str_to_py(guess.r0)
|
|
|
|
return lang
|
|
|
|
|
2019-06-01 19:19:55 +00:00
|
|
|
def language_by_filename(filename: str) -> str:
|
2019-11-17 14:13:41 +00:00
|
|
|
fName, c_str = py_str_to_go(filename)
|
2019-06-01 19:19:55 +00:00
|
|
|
guess = lib.GetLanguageByFilename(fName)
|
|
|
|
lang = go_str_to_py(guess.r0)
|
|
|
|
return lang
|
|
|
|
|
2019-06-01 19:30:07 +00:00
|
|
|
def is_vendor(filename: str) -> bool:
|
2019-11-17 14:13:41 +00:00
|
|
|
fName, c_str = py_str_to_go(filename)
|
2019-06-01 19:30:07 +00:00
|
|
|
guess = lib.IsVendor(fName)
|
|
|
|
return go_bool_to_py(guess)
|
|
|
|
|
|
|
|
|
|
|
|
## Tests
|
2019-11-17 14:13:41 +00:00
|
|
|
from collections import namedtuple
|
2019-06-01 17:47:13 +00:00
|
|
|
|
|
|
|
def main():
|
2019-11-17 14:13:41 +00:00
|
|
|
TestFile = namedtuple("TestFile", "name, content, lang")
|
2019-06-01 19:30:07 +00:00
|
|
|
files = [
|
2019-11-17 14:13:41 +00:00
|
|
|
TestFile("Parse.hs", b"", "Haskell"), TestFile("some.cpp", b"", "C++"),
|
|
|
|
TestFile("orand.go", b"", "Go"), TestFile("type.h", b"", "C"),
|
|
|
|
TestFile(".bashrc", b"", "Shell"), TestFile(".gitignore", b"", "Ignore List")
|
2019-06-01 19:30:07 +00:00
|
|
|
]
|
2019-06-01 19:19:55 +00:00
|
|
|
|
2019-11-17 14:13:41 +00:00
|
|
|
print("\nstrategy: extension")
|
|
|
|
for f in files:
|
|
|
|
lang = language_by_extension(f.name)
|
|
|
|
print("\tfile: {:10s} language: '{}'".format(f.name, lang))
|
2019-06-01 17:47:13 +00:00
|
|
|
|
2019-06-01 19:19:55 +00:00
|
|
|
print("\nstrategy: filename")
|
2019-11-17 14:13:41 +00:00
|
|
|
for f in files:
|
|
|
|
lang = language_by_filename(f.name)
|
|
|
|
print("\tfile: {:10s} language: '{}'".format(f.name, lang))
|
2019-06-01 19:19:55 +00:00
|
|
|
|
2019-06-01 19:30:07 +00:00
|
|
|
print("\ncheck: is vendor?")
|
2019-11-17 14:13:41 +00:00
|
|
|
for f in files:
|
|
|
|
vendor = is_vendor(f.name)
|
|
|
|
print("\tfile: {:10s} vendor: '{}'".format(f.name, vendor))
|
|
|
|
|
|
|
|
print("\nstrategy: all")
|
|
|
|
for f in files:
|
|
|
|
lang = language(f.name, f.content)
|
|
|
|
print("\tfile: {:10s} language: '{}'".format(f.name, lang))
|
|
|
|
assert lang == f.lang, "Expected '{}' but got '{}'".format(f.lang, lang)
|
2019-06-01 17:47:13 +00:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|