17 """A dumb configuration.rst generator that relies on source comments.""" 22 TARGET =
'docs/source/configuration.rst' 24 PREFIX =
""".. Copyright 2016 The Cartographer Authors 26 .. Licensed under the Apache License, Version 2.0 (the "License"); 27 you may not use this file except in compliance with the License. 28 You may obtain a copy of the License at 30 .. http://www.apache.org/licenses/LICENSE-2.0 32 .. Unless required by applicable law or agreed to in writing, software 33 distributed under the License is distributed on an "AS IS" BASIS, 34 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 35 See the License for the specific language governing permissions and 36 limitations under the License. 42 .. DO NOT EDIT! This documentation is AUTOGENERATED, please edit .proto files as 43 .. needed and run scripts/update_configuration_doc.py. 48 NODOC =
'Not yet documented.' 52 def __init__(self, name, package, preceding_comments):
63 self.
options.append((option_type, name, comments))
67 """Computes the list of Message objects of the option messages in a file.""" 68 line_iter = iter(proto_file)
71 for line
in line_iter:
73 if line.startswith(
'package'):
74 assert line[-1] ==
';' 75 package = line[7:-1].strip()
78 assert '}' not in line
84 for line
in line_iter:
89 elif line.startswith(
'//'):
91 comment = line[2:].strip()
92 if not comment.startswith(
'NEXT ID:'):
93 message_comments.append(comment)
94 elif line.startswith(
'message')
and line.endswith(
'Options {'):
95 message_name = package +
'.' + line[7:-1].strip()
100 print(
" Found '%s'." % message_name)
101 message =
Message(message_name, package, message_comments)
102 message_list.append(message)
107 for line
in line_iter:
111 message.AddTrailingComments(option_comments)
113 elif line.startswith(
'//'):
114 comment = line[2:].strip()
115 if not comment.startswith(
'NEXT ID:'):
116 option_comments.append(comment)
118 assert not line.startswith(
'required')
119 multiline +=
' ' + line
120 if not multiline.endswith(
';'):
122 assert len(multiline) < 200
123 option = multiline[:-1].strip().rstrip(
'0123456789').strip()
124 assert option.endswith(
'=')
125 if option.startswith(
'repeated'):
127 option_type, option_name = option[:-1].strip().split();
128 print(
" Option '%s'." % option_name)
130 message.AddOption(option_type, option_name, option_comments)
137 """Recursively parses all proto files into a list of Message objects.""" 139 for dirpath, dirnames, filenames
in os.walk(root):
140 for name
in filenames:
141 if name.endswith(
'.proto'):
142 path = os.path.join(dirpath, name)
143 print(
"Found '%s'..." % path)
144 assert not os.path.islink(path)
145 message_list.extend(
ParseProtoFile(io.open(path, encoding=
'UTF-8')))
150 """Raised when resolving a message name fails.""" 153 class Resolver(object):
157 def Resolve(self, message_name, package_name):
158 if message_name
in (
'bool',
'double',
'float',
'int32'):
160 if message_name.startswith(
'.'):
161 return message_name[1:]
162 package = package_name.split(
'.')
163 for levels
in range(len(package), -1, -1):
164 candidate =
'.'.join(package[0:levels]) +
'.' + message_name
168 'Resolving %s in %s failed.' % (message_name, package_name))
172 """Recursively generates documentation, sorts and writes it.""" 174 resolver =
Resolver(message.name
for message
in message_list)
177 for message
in message_list:
178 content = [message.name,
'=' * len(message.name),
'']
179 assert message.name
not in output_dict
180 output_dict[message.name] = content
181 if message.preceding_comments:
182 content.extend(preceding_comments)
184 for option_type, option_name, option_comments
in message.options:
188 if option_type
in (
'InitialTrajectoryPose',):
191 resolver.Resolve(option_type, message.package) +
' ' + option_name)
192 if not option_comments:
193 option_comments.append(NODOC)
194 for comment
in option_comments:
195 content.append(
' ' + comment)
197 if message.trailing_comments:
198 content.extend(message.trailing_comments)
201 output = [
'\n'.join(doc)
for key, doc
in sorted(list(output_dict.items()))]
202 print(
'\n\n'.join(output), file=output_file)
206 assert not os.path.islink(TARGET)
and os.path.isfile(TARGET)
207 assert not os.path.islink(ROOT)
and os.path.isdir(ROOT)
208 output_file = io.open(TARGET, mode=
'w', encoding=
'UTF-8', newline=
'\n')
209 output_file.write(PREFIX)
211 output_file.write(SUFFIX)
215 if __name__ ==
"__main__":
def Resolve(self, message_name, package_name)
def __init__(self, name_set)
def AddTrailingComments(self, comments)
def GenerateDocumentation(output_file, root)
def ParseProtoFile(proto_file)
def ParseProtoFilesRecursively(root)
def AddOption(self, option_type, name, comments)
def __init__(self, name, package, preceding_comments)