• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
15from libc cimport stdlib
16from libcpp.vector cimport vector
17from libcpp.utility cimport pair
18from libcpp.string cimport string
19
20from cython.operator cimport dereference
21
22import warnings
23
24cdef extern from "grpc_tools/main.h" namespace "grpc_tools":
25  cppclass cProtocError "::grpc_tools::ProtocError":
26    string filename
27    int line
28    int column
29    string message
30
31  cppclass cProtocWarning "::grpc_tools::ProtocWarning":
32    string filename
33    int line
34    int column
35    string message
36
37  int protoc_main(int argc, char *argv[])
38  int protoc_get_protos(char* protobuf_path,
39                        vector[string]* include_path,
40                        vector[pair[string, string]]* files_out,
41                        vector[cProtocError]* errors,
42                        vector[cProtocWarning]* wrnings) nogil except +
43  int protoc_get_services(char* protobuf_path,
44                          vector[string]* include_path,
45                          vector[pair[string, string]]* files_out,
46                          vector[cProtocError]* errors,
47                          vector[cProtocWarning]* wrnings) nogil except +
48
49def run_main(list args not None):
50  cdef char **argv = <char **>stdlib.malloc(len(args)*sizeof(char *))
51  for i in range(len(args)):
52    argv[i] = args[i]
53  return protoc_main(len(args), argv)
54
55class ProtocError(Exception):
56    def __init__(self, filename, line, column, message):
57        self.filename = filename
58        self.line = line
59        self.column = column
60        self.message = message
61
62    def __repr__(self):
63        return "ProtocError(filename=\"{}\", line={}, column={}, message=\"{}\")".format(
64                self.filename, self.line, self.column, self.message)
65
66    def __str__(self):
67        return "{}:{}:{} error: {}".format(self.filename.decode("ascii"),
68                self.line, self.column, self.message.decode("ascii"))
69
70class ProtocWarning(Warning):
71    def __init__(self, filename, line, column, message):
72        self.filename = filename
73        self.line = line
74        self.column = column
75        self.message = message
76
77    def __repr__(self):
78        return "ProtocWarning(filename=\"{}\", line={}, column={}, message=\"{}\")".format(
79                self.filename, self.line, self.column, self.message)
80
81    __str__ = __repr__
82
83
84class ProtocErrors(Exception):
85    def __init__(self, errors):
86        self._errors = errors
87
88    def errors(self):
89        return self._errors
90
91    def __repr__(self):
92        return "ProtocErrors[{}]".join(repr(err) for err in self._errors)
93
94    def __str__(self):
95        return "\n".join(str(err) for err in self._errors)
96
97cdef _c_protoc_error_to_protoc_error(cProtocError c_protoc_error):
98    return ProtocError(c_protoc_error.filename, c_protoc_error.line,
99            c_protoc_error.column, c_protoc_error.message)
100
101cdef _c_protoc_warning_to_protoc_warning(cProtocWarning c_protoc_warning):
102    return ProtocWarning(c_protoc_warning.filename, c_protoc_warning.line,
103            c_protoc_warning.column, c_protoc_warning.message)
104
105cdef _handle_errors(int rc, vector[cProtocError]* errors, vector[cProtocWarning]* wrnings, bytes protobuf_path):
106  for warning in dereference(wrnings):
107      warnings.warn(_c_protoc_warning_to_protoc_warning(warning))
108  if rc != 0:
109    if dereference(errors).size() != 0:
110       py_errors = [_c_protoc_error_to_protoc_error(c_error)
111               for c_error in dereference(errors)]
112       raise ProtocErrors(py_errors)
113    raise Exception("An unknown error occurred while compiling {}".format(protobuf_path))
114
115def get_protos(bytes protobuf_path, list include_paths):
116  cdef vector[string] c_include_paths = include_paths
117  cdef vector[pair[string, string]] files
118  cdef vector[cProtocError] errors
119  # NOTE: Abbreviated name used to avoid shadowing of the module name.
120  cdef vector[cProtocWarning] wrnings
121  rc = protoc_get_protos(protobuf_path, &c_include_paths, &files, &errors, &wrnings)
122  _handle_errors(rc, &errors, &wrnings, protobuf_path)
123  return files
124
125def get_services(bytes protobuf_path, list include_paths):
126  cdef vector[string] c_include_paths = include_paths
127  cdef vector[pair[string, string]] files
128  cdef vector[cProtocError] errors
129  # NOTE: Abbreviated name used to avoid shadowing of the module name.
130  cdef vector[cProtocWarning] wrnings
131  rc = protoc_get_services(protobuf_path, &c_include_paths, &files, &errors, &wrnings)
132  _handle_errors(rc, &errors, &wrnings, protobuf_path)
133  return files
134
135