gitlab.com/thomasboni/go-enry/v2@v2.8.3-0.20220418031202-30b0d7a3de98/python/enry/utils.py (about)

     1  from _c_enry import ffi
     2  from enry.types import Guess
     3  from functools import wraps
     4  from typing import Hashable, List, Sequence
     5  
     6  
     7  def py_bytes_to_go(py_bytes: bytes):
     8      c_bytes = ffi.new("char[]", py_bytes)
     9      go_slice = ffi.new("GoSlice *", [c_bytes, len(py_bytes), len(py_bytes)])
    10      return (go_slice[0], c_bytes)
    11  
    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  
    20  def go_str_to_py(go_str: str):
    21      str_len = go_str.n
    22      if str_len > 0:
    23          return ffi.unpack(go_str.p, go_str.n).decode()
    24      return ""
    25  
    26  
    27  def init_go_slice():
    28      return ffi.new("GoSlice *")
    29  
    30  
    31  def go_str_slice_to_py(str_slice) -> List[str]:
    32      slice_len = str_slice.len
    33      char_arr = ffi.cast("char **", str_slice.data)
    34      return [ffi.string(char_arr[i]).decode() for i in range(slice_len)]
    35  
    36  
    37  def go_bool_to_py(go_bool: bool):
    38      return go_bool == 1
    39  
    40  
    41  def go_guess_to_py(guess) -> Guess:
    42      return Guess(go_str_to_py(guess.r0), go_bool_to_py(guess.r1))
    43  
    44  
    45  py_to_go = {
    46      str: py_str_to_go,
    47      bytes: py_bytes_to_go,
    48  }
    49  
    50  
    51  go_to_py = {
    52      str: go_str_to_py,
    53      bool: go_bool_to_py,
    54      Guess: go_guess_to_py,
    55  }
    56  
    57  
    58  def transform_types(in_types: Sequence[Hashable], out_type: Hashable):
    59      def decorator(fn):
    60          @wraps(fn)
    61          def inner(*args):
    62              args_transformed = [py_to_go[type_](arg) for type_, arg in zip(in_types, args)]
    63              return go_to_py[out_type](fn(*(arg[0] for arg in args_transformed)))
    64          return inner
    65      return decorator
    66  
    67  
    68  def transform_types_ret_str_slice(in_types: Sequence[Hashable]):
    69      def decorator(fn):
    70          @wraps(fn)
    71          def inner(*args):
    72              ret_slice = init_go_slice()
    73              args_transformed = [py_to_go[type_](arg) for type_, arg in zip(in_types, args)]
    74              fn(*(arg[0] for arg in args_transformed), ret_slice)
    75              return go_str_slice_to_py(ret_slice)
    76          return inner
    77      return decorator