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