_protoc_compiler.pyx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. # Copyright 2020 The gRPC authors.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. from cython.operator cimport dereference
  15. from libc cimport stdlib
  16. from libcpp.string cimport string
  17. from libcpp.utility cimport pair
  18. from libcpp.vector cimport vector
  19. import warnings
  20. cdef extern from "grpc_tools/main.h" namespace "grpc_tools":
  21. cppclass cProtocError "::grpc_tools::ProtocError":
  22. string filename
  23. int line
  24. int column
  25. string message
  26. cppclass cProtocWarning "::grpc_tools::ProtocWarning":
  27. string filename
  28. int line
  29. int column
  30. string message
  31. int protoc_main(int argc, char *argv[])
  32. int protoc_get_protos(char* protobuf_path,
  33. vector[string]* include_path,
  34. vector[pair[string, string]]* files_out,
  35. vector[cProtocError]* errors,
  36. vector[cProtocWarning]* wrnings) nogil except +
  37. int protoc_get_services(char* protobuf_path,
  38. vector[string]* include_path,
  39. vector[pair[string, string]]* files_out,
  40. vector[cProtocError]* errors,
  41. vector[cProtocWarning]* wrnings) nogil except +
  42. def run_main(list args not None):
  43. cdef char **argv = <char **>stdlib.malloc(len(args)*sizeof(char *))
  44. for i in range(len(args)):
  45. argv[i] = args[i]
  46. return protoc_main(len(args), argv)
  47. class ProtocError(Exception):
  48. def __init__(self, filename, line, column, message):
  49. self.filename = filename
  50. self.line = line
  51. self.column = column
  52. self.message = message
  53. def __repr__(self):
  54. return "ProtocError(filename=\"{}\", line={}, column={}, message=\"{}\")".format(
  55. self.filename, self.line, self.column, self.message)
  56. def __str__(self):
  57. return "{}:{}:{} error: {}".format(self.filename.decode("ascii"),
  58. self.line, self.column, self.message.decode("ascii"))
  59. class ProtocWarning(Warning):
  60. def __init__(self, filename, line, column, message):
  61. self.filename = filename
  62. self.line = line
  63. self.column = column
  64. self.message = message
  65. def __repr__(self):
  66. return "ProtocWarning(filename=\"{}\", line={}, column={}, message=\"{}\")".format(
  67. self.filename, self.line, self.column, self.message)
  68. __str__ = __repr__
  69. class ProtocErrors(Exception):
  70. def __init__(self, errors):
  71. self._errors = errors
  72. def errors(self):
  73. return self._errors
  74. def __repr__(self):
  75. return "ProtocErrors[{}]".join(repr(err) for err in self._errors)
  76. def __str__(self):
  77. return "\n".join(str(err) for err in self._errors)
  78. cdef _c_protoc_error_to_protoc_error(cProtocError c_protoc_error):
  79. return ProtocError(c_protoc_error.filename, c_protoc_error.line,
  80. c_protoc_error.column, c_protoc_error.message)
  81. cdef _c_protoc_warning_to_protoc_warning(cProtocWarning c_protoc_warning):
  82. return ProtocWarning(c_protoc_warning.filename, c_protoc_warning.line,
  83. c_protoc_warning.column, c_protoc_warning.message)
  84. cdef _handle_errors(int rc, vector[cProtocError]* errors, vector[cProtocWarning]* wrnings, bytes protobuf_path):
  85. for warning in dereference(wrnings):
  86. warnings.warn(_c_protoc_warning_to_protoc_warning(warning))
  87. if rc != 0:
  88. if dereference(errors).size() != 0:
  89. py_errors = [_c_protoc_error_to_protoc_error(c_error)
  90. for c_error in dereference(errors)]
  91. raise ProtocErrors(py_errors)
  92. raise Exception("An unknown error occurred while compiling {}".format(protobuf_path))
  93. def get_protos(bytes protobuf_path, list include_paths):
  94. cdef vector[string] c_include_paths = include_paths
  95. cdef vector[pair[string, string]] files
  96. cdef vector[cProtocError] errors
  97. # NOTE: Abbreviated name used to avoid shadowing of the module name.
  98. cdef vector[cProtocWarning] wrnings
  99. rc = protoc_get_protos(protobuf_path, &c_include_paths, &files, &errors, &wrnings)
  100. _handle_errors(rc, &errors, &wrnings, protobuf_path)
  101. return files
  102. def get_services(bytes protobuf_path, list include_paths):
  103. cdef vector[string] c_include_paths = include_paths
  104. cdef vector[pair[string, string]] files
  105. cdef vector[cProtocError] errors
  106. # NOTE: Abbreviated name used to avoid shadowing of the module name.
  107. cdef vector[cProtocWarning] wrnings
  108. rc = protoc_get_services(protobuf_path, &c_include_paths, &files, &errors, &wrnings)
  109. _handle_errors(rc, &errors, &wrnings, protobuf_path)
  110. return files