header.py

Sat, 25 May 2019 09:41:33 +0200

author
Teemu Piippo <teemu@hecknology.net>
date
Sat, 25 May 2019 09:41:33 +0200
changeset 47
4da025d0b283
child 48
38b0919c1934
permissions
-rw-r--r--

added work on header check

47
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
1 import re
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
2 import linetypes
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
3
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
4 class Header:
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
5 def __init__(self):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
6 self.description = None
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
7 self.name = None
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
8 self.author = None
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
9 self.username = None
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
10 self.filetype = None
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
11 self.qualifiers = None
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
12 self.license = None
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
13 self.help = []
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
14 self.bfc = None
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
15 self.category = None
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
16 self.keywords = []
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
17 self.cmdline = None
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
18 self.history = []
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
19
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
20 class BadHeader:
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
21 def __init__(self, index, reason):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
22 self.index = index
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
23 self.reason = reason
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
24 def __repr__(self):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
25 return str.format(
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
26 'header.BadHeader(index = {index!r}, reason = {reason!r})',
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
27 index = self.index,
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
28 reason = self.reason,
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
29 )
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
30
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
31 geometrical_types = [
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
32 linetypes.LineSegment,
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
33 linetypes.Triangle,
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
34 linetypes.Quadrilateral,
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
35 linetypes.ConditionalLine,
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
36 ]
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
37
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
38 def is_suitable_header_object(entry):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
39 return not any(
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
40 isinstance(entry, linetype)
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
41 for linetype in [
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
42 *geometrical_types,
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
43 linetypes.Comment,
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
44 linetypes.Error,
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
45 ]
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
46 )
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
47
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
48 class HeaderError(Exception):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
49 def __init__(self, index, reason):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
50 self.index, self.reason = index, reason
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
51 def __repr__(self):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
52 return str.format(
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
53 'HeaderError({index!r}, {reason!r})',
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
54 index = self.index,
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
55 reason = self.reason,
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
56 )
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
57 def __str__(self):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
58 return reason
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
59
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
60 class HeaderParser:
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
61 def __init__(self):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
62 self.model_body = None
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
63 self.cursor = 0
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
64 self.problems = []
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
65 def parse(self, model_body):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
66 result = Header()
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
67 self.order = []
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
68 self.cursor = -1
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
69 self.model_body = model_body
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
70 self.skip_to_next()
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
71 result.description = self.current()
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
72 self.skip_to_next()
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
73 result.name = self.parse_pattern('^Name: (.+)$', 'name')[0]
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
74 self.skip_to_next()
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
75 result.author = self.parse_pattern('^Author: (.+)$', 'author')[0]
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
76 for header_entry in self.get_more_header_stuff():
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
77 if self.try_to_match(
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
78 '^!LDRAW_ORG ' +
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
79 '(' \
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
80 '(?:Unofficial_)?' \
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
81 'Part|' \
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
82 'Subpart|' \
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
83 'Primitive|' \
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
84 '8_Primitive|' \
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
85 '48_Primitive|' \
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
86 'Shortcut' \
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
87 ')\s?' \
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
88 '(ORIGINAL|UPDATE \d\d\d\d-\d\d)?$',
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
89 'part type'):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
90 result.filetype, result.qualifiers = self.groups
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
91 elif self.try_to_match(
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
92 '^!LICENSE (.+)$',
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
93 'license'):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
94 result.license = self.groups()
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
95 else:
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
96 self.parse_error("couldn't handle header metacommand: " + repr(header_entry.text))
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
97 return {
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
98 'header': result,
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
99 'end-index': self.cursor + 1,
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
100 }
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
101 def parse_error(self, message):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
102 raise HeaderError(index = self.cursor, reason = message)
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
103 def get_more_header_stuff(self):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
104 while True:
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
105 self.cursor += 1
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
106 if self.cursor >= len(self.model_body):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
107 break
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
108 entry = self.model_body[self.cursor]
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
109 if not is_suitable_header_object(entry):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
110 break
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
111 if isinstance(entry, linetypes.MetaCommand):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
112 yield entry
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
113 def skip_to_next(self, *, spaces_expected = 0):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
114 while True:
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
115 if self.cursor + 1 >= len(self.model_body):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
116 self.parse_error('stub ldraw file')
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
117 self.cursor += 1
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
118 entry = self.model_body[self.cursor]
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
119 if not is_suitable_header_object(entry):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
120 self.parse_error('header is incomplete')
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
121 if isinstance(entry, linetypes.MetaCommand):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
122 return
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
123 def try_to_match(self, pattern, patterntype):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
124 try:
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
125 self.groups = self.parse_pattern(pattern, patterntype)
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
126 except:
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
127 return False
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
128 def current(self):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
129 entry = self.model_body[self.cursor]
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
130 assert isinstance(entry, linetypes.MetaCommand)
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
131 return entry.text
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
132 def parse_pattern(self, pattern, description):
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
133 match = re.search(pattern, self.current())
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
134 if match:
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
135 self.order.append(description)
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
136 return match.groups()
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
137 else:
4da025d0b283 added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
138 self.parse_error(str.format("couldn't parse {}", description))

mercurial