diff options
author | 2020-09-30 11:17:54 +1000 | |
---|---|---|
committer | 2020-09-30 11:17:54 +1000 | |
commit | f185ed096c1555adc108fb679b3e0a60671e0d3c (patch) | |
tree | 4f718686e8fc83881d6950c062d0e1f274e3e8b0 /docs/release/scripts/build/complay.py | |
parent | eb71a8564c36fd14098bb24d7acb76b2d6e0c7dc (diff) |
0.225 Release filestag225
Diffstat (limited to 'docs/release/scripts/build/complay.py')
-rw-r--r-- | docs/release/scripts/build/complay.py | 154 |
1 files changed, 109 insertions, 45 deletions
diff --git a/docs/release/scripts/build/complay.py b/docs/release/scripts/build/complay.py index ce760185015..34a43992b7c 100644 --- a/docs/release/scripts/build/complay.py +++ b/docs/release/scripts/build/complay.py @@ -97,7 +97,6 @@ class LayoutChecker(Minifyer): VARPATTERN = re.compile('^.*~[0-9A-Za-z_]+~.*$') FLOATCHARS = re.compile('^.*[.eE].*$') SHAPES = frozenset(('disk', 'dotmatrix', 'dotmatrix5dot', 'dotmatrixdot', 'led14seg', 'led14segsc', 'led16seg', 'led16segsc', 'led7seg', 'led8seg_gts1', 'rect')) - OBJECTS = frozenset(('backdrop', 'bezel', 'cpanel', 'marquee', 'overlay')) ORIENTATIONS = frozenset((0, 90, 180, 270)) YESNO = frozenset(('yes', 'no')) BLENDMODES = frozenset(('none', 'alpha', 'multiply', 'add')) @@ -111,6 +110,8 @@ class LayoutChecker(Minifyer): self.views = { } self.referenced_elements = { } self.referenced_groups = { } + self.group_collections = { } + self.current_collections = None def formatLocation(self): return '%s:%d:%d' % (self.locator.getSystemId(), self.locator.getLineNumber(), self.locator.getColumnNumber()) @@ -218,10 +219,6 @@ class LayoutChecker(Minifyer): self.variable_scopes[-1][attrs['name']] = False def checkBounds(self, attrs): - if self.have_bounds[-1]: - self.handleError('Duplicate element bounds') - else: - self.have_bounds[-1] = True left = self.checkFloatAttribute('bounds', attrs, 'left', 0.0) top = self.checkFloatAttribute('bounds', attrs, 'top', 0.0) right = self.checkFloatAttribute('bounds', attrs, 'right', 1.0) @@ -257,9 +254,15 @@ class LayoutChecker(Minifyer): if self.checkIntAttribute('orientation', attrs, 'rotate', 0) not in self.ORIENTATIONS: self.handleError('Element orientation attribute rotate "%s" is unsupported' % (attrs['rotate'], )) for name in ('swapxy', 'flipx', 'flipy'): - if attrs.get(name, 'no') not in self.YESNO: + if (attrs.get(name, 'no') not in self.YESNO) and (not self.VARPATTERN.match(attrs['yesno'])): self.handleError('Element orientation attribute %s "%s" is not "yes" or "no"' % (name, attrs[name])) + def checkColor(self, attrs): + self.checkColorChannel(attrs, 'red') + self.checkColorChannel(attrs, 'green') + self.checkColorChannel(attrs, 'blue') + self.checkColorChannel(attrs, 'alpha') + def checkColorChannel(self, attrs, name): channel = self.checkFloatAttribute('color', attrs, name, None) if (channel is not None) and ((0.0 > channel) or (1.0 < channel)): @@ -267,7 +270,7 @@ class LayoutChecker(Minifyer): def checkTag(self, tag, element, attr): if '' == tag: - self.handleError('Element %s attribute %s is empty', (element, attr)) + self.handleError('Element %s attribute %s is empty' % (element, attr)) else: if tag.find('^') >= 0: self.handleError('Element %s attribute %s "%s" contains parent device reference' % (element, attr, tag)) @@ -277,12 +280,22 @@ class LayoutChecker(Minifyer): self.handleError('Element %s attribute %s "%s" contains double separator' % (element, attr, tag)) def checkComponent(self, name, attrs): - state = self.checkIntAttribute(name, attrs, 'state', None) - if (state is not None) and (0 > state): - self.handleError('Element %s attribute state "%s" is negative' % (name, attrs['state'])) + statemask = self.checkIntAttribute(name, attrs, 'statemask', None) + stateval = self.checkIntAttribute(name, attrs, 'state', None) + if stateval is not None: + if 0 > stateval: + self.handleError('Element %s attribute state "%s" is negative' % (name, attrs['state'])) + if (statemask is not None) and (stateval & ~statemask): + self.handleError('Element %s attribute state "%s" has bits set that are clear in attribute statemask "%s"' % (name, attrs['state'], attrs['statemask'])) self.handlers.append((self.componentStartHandler, self.componentEndHandler)) - self.have_bounds.append(False) - self.have_color.append(False) + self.have_bounds.append({ }) + self.have_color.append({ }) + + def startObject(self): + self.handlers.append((self.objectStartHandler, self.objectEndHandler)) + self.have_bounds.append(None) + self.have_orientation.append(False) + self.have_color.append(None) def rootStartHandler(self, name, attrs): if 'mamelayout' != name: @@ -320,6 +333,7 @@ class LayoutChecker(Minifyer): self.handleError('Element element attribute defstate "%s" is negative' % (attrs['defstate'], )) self.handlers.append((self.elementStartHandler, self.elementEndHandler)) elif 'group' == name: + self.current_collections = { } if 'name' not in attrs: self.handleError('Element group missing attribute name') else: @@ -328,13 +342,16 @@ class LayoutChecker(Minifyer): self.generated_group_names = True if attrs['name'] not in self.groups: self.groups[attrs['name']] = self.formatLocation() + if not generated_name: + self.group_collections[attrs['name']] = self.current_collections elif not generated_name: self.handleError('Element group has duplicate name (previous %s)' % (self.groups[attrs['name']], )) self.handlers.append((self.groupViewStartHandler, self.groupViewEndHandler)) self.variable_scopes.append({ }) self.repeat_depth.append(0) - self.have_bounds.append(False) + self.have_bounds.append(None) elif ('view' == name) and (not self.repeat_depth[-1]): + self.current_collections = { } if 'name' not in attrs: self.handleError('Element view missing attribute name') else: @@ -345,7 +362,7 @@ class LayoutChecker(Minifyer): self.handlers.append((self.groupViewStartHandler, self.groupViewEndHandler)) self.variable_scopes.append({ }) self.repeat_depth.append(0) - self.have_bounds.append(False) + self.have_bounds.append(None) elif 'repeat' == name: if 'count' not in attrs: self.handleError('Element repeat missing attribute count') @@ -428,16 +445,25 @@ class LayoutChecker(Minifyer): def componentStartHandler(self, name, attrs): if 'bounds' == name: + state = self.checkIntAttribute(name, attrs, 'state', 0) + if state is not None: + if 0 > state: + self.handleError('Element bounds attribute state "%s" is negative' % (attrs['state'], )) + if state in self.have_bounds[-1]: + self.handleError('Duplicate bounds for state %d (previous %s)' % (state, self.have_bounds[-1][state])) + else: + self.have_bounds[-1][state] = self.formatLocation() self.checkBounds(attrs) elif 'color' == name: - if self.have_color[-1]: - self.handleError('Duplicate color element') - else: - self.have_color[-1] = True - self.checkColorChannel(attrs, 'red') - self.checkColorChannel(attrs, 'green') - self.checkColorChannel(attrs, 'blue') - self.checkColorChannel(attrs, 'alpha') + state = self.checkIntAttribute(name, attrs, 'state', 0) + if state is not None: + if 0 > state: + self.handleError('Element color attribute state "%s" is negative' % (attrs['state'], )) + if state in self.have_color[-1]: + self.handleError('Duplicate color for state %d (previous %s)' % (state, self.have_color[-1][state])) + else: + self.have_color[-1][state] = self.formatLocation() + self.checkColor(attrs) self.ignored_depth = 1 def componentEndHandler(self, name): @@ -446,12 +472,11 @@ class LayoutChecker(Minifyer): self.handlers.pop() def groupViewStartHandler(self, name, attrs): - if (name in self.OBJECTS) or ('element' == name): - refattr = 'ref' if 'element' == name else 'element' - if refattr not in attrs: - self.handleError('Element %s missing attribute %s' % (name, refattr)) - elif attrs[refattr] not in self.referenced_elements: - self.referenced_elements[attrs[refattr]] = self.formatLocation() + if 'element' == name: + if 'ref' not in attrs: + self.handleError('Element %s missing attribute ref' % (name, )) + elif attrs['ref'] not in self.referenced_elements: + self.referenced_elements[attrs['ref']] = self.formatLocation() if ('blend' in attrs) and (attrs['blend'] not in self.BLENDMODES) and not self.VARPATTERN.match(attrs['blend']): self.handleError('Element %s attribute blend "%s" is unsupported' % (name, attrs['blend'])) if 'inputtag' in attrs: @@ -460,21 +485,21 @@ class LayoutChecker(Minifyer): self.checkTag(attrs['inputtag'], name, 'inputtag') elif 'inputmask' in attrs: self.handleError('Element %s has inputmask attribute without inputtag attribute' % (name, )) - inputraw = self.checkIntAttribute(name, attrs, 'inputraw', None) - if (inputraw is not None): + inputraw = None + if 'inputraw' in attrs: + if (attrs['inputraw'] not in self.YESNO) and (not self.VARPATTERN.match(attrs['inputraw'])): + self.handleError('Element %s attribute inputraw "%s" is not "yes" or "no"' % (name, attrs['inputraw'])) + else: + inputraw = 'yes' == attrs['inputraw'] if 'inputmask' not in attrs: self.handleError('Element %s has inputraw attribute without inputmask attribute' % (name, )) if 'inputtag' not in attrs: self.handleError('Element %s has inputraw attribute without inputtag attribute' % (name, )) - if ((0 > inputraw) or (1 < inputraw)): - self.handleError('Element %s attribute inputraw "%s" not in valid range 0-1' % (name, attrs['inputraw'])) inputmask = self.checkIntAttribute(name, attrs, 'inputmask', None) if (inputmask is not None) and (0 == inputmask): if (inputraw is None) or (0 == inputraw): - self.handleError('Element %s has attribute inputmask "%s" is zero' % (name, attrs['inputmask'])) - self.handlers.append((self.objectStartHandler, self.objectEndHandler)) - self.have_bounds.append(False) - self.have_orientation.append(False) + self.handleError('Element %s attribute inputmask "%s" is zero' % (name, attrs['inputmask'])) + self.startObject(); elif 'screen' == name: if 'index' in attrs: index = self.checkIntAttribute(name, attrs, 'index', None) @@ -487,17 +512,20 @@ class LayoutChecker(Minifyer): self.checkTag(tag, name, 'tag') if self.BADTAGPATTERN.search(tag): self.handleError('Element screen attribute tag "%s" contains invalid characters' % (tag, )) - self.handlers.append((self.objectStartHandler, self.objectEndHandler)) - self.have_bounds.append(False) - self.have_orientation.append(False) + self.startObject(); elif 'group' == name: if 'ref' not in attrs: self.handleError('Element group missing attribute ref') - elif attrs['ref'] not in self.referenced_groups: - self.referenced_groups[attrs['ref']] = self.formatLocation() - self.handlers.append((self.objectStartHandler, self.objectEndHandler)) - self.have_bounds.append(False) - self.have_orientation.append(False) + else: + if attrs['ref'] not in self.referenced_groups: + self.referenced_groups[attrs['ref']] = self.formatLocation() + if (not self.VARPATTERN.match(attrs['ref'])) and (attrs['ref'] in self.group_collections): + for n, l in self.group_collections[attrs['ref']].items(): + if n not in self.current_collections: + self.current_collections[n] = l + else: + self.handleError('Element group instantiates collection with duplicate name "%s" from %s (previous %s)' % (n, l, self.current_collections[n])) + self.startObject(); elif 'repeat' == name: if 'count' not in attrs: self.handleError('Element repeat missing attribute count') @@ -507,13 +535,31 @@ class LayoutChecker(Minifyer): self.handleError('Element repeat attribute count "%s" is negative' % (attrs['count'], )) self.variable_scopes.append({ }) self.repeat_depth[-1] += 1 + elif 'collection' == name: + if 'name' not in attrs: + self.handleError('Element collection missing attribute name') + elif not self.VARPATTERN.match(attrs['name']): + if attrs['name'] not in self.current_collections: + self.current_collections[attrs['name']] = self.formatLocation() + else: + self.handleError('Element collection has duplicate name (previous %s)' % (self.current_collections[attrs['name']], )) + if attrs.get('visible', 'yes') not in self.YESNO: + self.handleError('Element collection attribute visible "%s" is not "yes" or "no"' % (attrs['visible'], )) + self.variable_scopes.append({ }) + self.collection_depth += 1 elif 'param' == name: self.checkParameter(attrs) self.ignored_depth = 1 elif 'bounds' == name: + if self.have_bounds[-1] is not None: + self.handleError('Duplicate element bounds (previous %s)' % (self.have_bounds[-1], )) + else: + self.have_bounds[-1] = self.formatLocation() self.checkBounds(attrs) if self.repeat_depth[-1]: self.handleError('Element bounds inside repeat') + elif self.collection_depth: + self.handleError('Element bounds inside collection') self.ignored_depth = 1 else: self.handleError('Encountered unexpected element %s' % (name, )) @@ -521,23 +567,37 @@ class LayoutChecker(Minifyer): def groupViewEndHandler(self, name): self.variable_scopes.pop() - if self.repeat_depth[-1]: + if 'collection' == name: + self.collection_depth -= 1 + elif self.repeat_depth[-1]: self.repeat_depth[-1] -= 1 else: + self.current_collections = None self.repeat_depth.pop() self.have_bounds.pop() self.handlers.pop() def objectStartHandler(self, name, attrs): if 'bounds' == name: + if self.have_bounds[-1] is not None: + self.handleError('Duplicate element bounds (previous %s)' % (self.have_bounds[-1], )) + else: + self.have_bounds[-1] = self.formatLocation() self.checkBounds(attrs) elif 'orientation' == name: self.checkOrientation(attrs) + if 'color' == name: + if self.have_color[-1] is not None: + self.handleError('Duplicate element color (previous %s)' % (self.have_color[-1], )) + else: + self.have_color[-1] = self.formatLocation() + self.checkColor(attrs) self.ignored_depth = 1 def objectEndHandler(self, name): self.have_bounds.pop() self.have_orientation.pop() + self.have_color.pop() self.handlers.pop() def setDocumentLocator(self, locator): @@ -549,6 +609,7 @@ class LayoutChecker(Minifyer): self.ignored_depth = 0 self.variable_scopes = [ ] self.repeat_depth = [ ] + self.collection_depth = 0 self.have_bounds = [ ] self.have_orientation = [ ] self.have_color = [ ] @@ -563,10 +624,13 @@ class LayoutChecker(Minifyer): self.views.clear() self.referenced_elements.clear() self.referenced_groups.clear() + self.group_collections.clear() + self.current_collections = None del self.handlers del self.ignored_depth del self.variable_scopes del self.repeat_depth + del self.collection_depth del self.have_bounds del self.have_orientation del self.have_color |