| 
									
										
										
										
											2012-11-21 07:40:46 +00:00
										 |  |  | # ##### BEGIN GPL LICENSE BLOCK ##### | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | #  This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  | #  modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  | #  as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  | #  of the License, or (at your option) any later version. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | #  This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | #  but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  | #  GNU General Public License for more details. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | #  You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  | #  along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  | #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # ##### END GPL LICENSE BLOCK ##### | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # <pep8 compliant> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Module with function to extract a doctree from an reStructuredText file. | 
					
						
							|  |  |  | # Named 'Mini' because we only parse the minimum data needed to check | 
					
						
							|  |  |  | # Python classes, methods and attributes match up to those in existing modules. | 
					
						
							|  |  |  | # (To test for documentation completeness) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # note: literalinclude's are not followed. | 
					
						
							|  |  |  | # could be nice to add but not really needed either right now. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import collections | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-07 13:54:13 +10:00
										 |  |  | Directive = collections.namedtuple( | 
					
						
							|  |  |  |     "Directive", | 
					
						
							|  |  |  |     ("type", | 
					
						
							|  |  |  |      "value", | 
					
						
							|  |  |  |      "value_strip", | 
					
						
							|  |  |  |      "line", | 
					
						
							|  |  |  |      "indent", | 
					
						
							|  |  |  |      "members")) | 
					
						
							| 
									
										
										
										
											2012-11-21 07:40:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def parse_rst_py(filepath): | 
					
						
							|  |  |  |     import re | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Get the prefix assuming the line is lstrip()'d | 
					
						
							|  |  |  |     # ..foo:: bar | 
					
						
							|  |  |  |     # --> | 
					
						
							|  |  |  |     # ("foo", "bar") | 
					
						
							|  |  |  |     re_prefix = re.compile(r"^\.\.\s([a-zA-Z09\-]+)::\s*(.*)\s*$") | 
					
						
							| 
									
										
										
										
											2013-01-15 23:17:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-21 07:40:46 +00:00
										 |  |  |     tree = collections.defaultdict(list) | 
					
						
							| 
									
										
										
										
											2012-11-22 05:15:52 +00:00
										 |  |  |     indent_map = {} | 
					
						
							|  |  |  |     indent_prev = 0 | 
					
						
							| 
									
										
										
										
											2012-11-21 07:40:46 +00:00
										 |  |  |     f = open(filepath, encoding="utf-8") | 
					
						
							|  |  |  |     for i, line in enumerate(f): | 
					
						
							|  |  |  |         line_strip = line.lstrip() | 
					
						
							|  |  |  |         # ^\.\.\s[a-zA-Z09\-]+::.*$ | 
					
						
							| 
									
										
										
										
											2016-02-01 00:47:10 +11:00
										 |  |  |         # if line.startswith(".. "): | 
					
						
							| 
									
										
										
										
											2012-11-21 07:40:46 +00:00
										 |  |  |         march = re_prefix.match(line_strip) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if march: | 
					
						
							|  |  |  |             directive, value = march.group(1, 2) | 
					
						
							|  |  |  |             indent = len(line) - len(line_strip) | 
					
						
							|  |  |  |             value_strip = value.replace("(", " ").split() | 
					
						
							|  |  |  |             value_strip = value_strip[0] if value_strip else "" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             item = Directive(type=directive, | 
					
						
							|  |  |  |                              value=value, | 
					
						
							|  |  |  |                              value_strip=value_strip, | 
					
						
							|  |  |  |                              line=i, | 
					
						
							|  |  |  |                              indent=indent, | 
					
						
							|  |  |  |                              members=[]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             tree[indent].append(item) | 
					
						
							| 
									
										
										
										
											2012-11-22 05:15:52 +00:00
										 |  |  |             if indent_prev < indent: | 
					
						
							|  |  |  |                 indent_map[indent] = indent_prev | 
					
						
							| 
									
										
										
										
											2012-11-21 07:40:46 +00:00
										 |  |  |             if indent > 0: | 
					
						
							| 
									
										
										
										
											2012-11-22 05:15:52 +00:00
										 |  |  |                 tree[indent_map[indent]][-1].members.append(item) | 
					
						
							|  |  |  |             indent_prev = indent | 
					
						
							| 
									
										
										
										
											2012-11-21 07:40:46 +00:00
										 |  |  |     f.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return tree[0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-07 13:54:13 +10:00
										 |  |  | def main(): | 
					
						
							| 
									
										
										
										
											2012-11-21 07:40:46 +00:00
										 |  |  |     # not intended use, but may as well print rst files passed as a test. | 
					
						
							|  |  |  |     import sys | 
					
						
							|  |  |  |     for arg in sys.argv: | 
					
						
							|  |  |  |         if arg.lower().endswith((".txt", ".rst")): | 
					
						
							|  |  |  |             items = parse_rst_py(arg) | 
					
						
							|  |  |  |             for i in items: | 
					
						
							|  |  |  |                 print(i) | 
					
						
							| 
									
										
										
										
											2015-06-07 13:54:13 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     main() |