-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathPSPUtils.py
94 lines (75 loc) · 2.75 KB
/
PSPUtils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
"""A bunch of utility functions for the PSP generator.
Copyright (c) by Jay Love, 2000 (mailto:jsliv@jslove.org)
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee or royalty is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation or portions thereof, including modifications,
that you make.
This software is based in part on work done by the Jakarta group.
"""
class PSPParserException(Exception):
"""PSP parser error."""
def removeQuotes(s):
return s.replace(r'%\\>', '%>')
def isExpression(s):
"""Check whether this is a PSP expression."""
return s.startswith('<%=') and s.endswith('%>')
def getExpr(s):
"""Get the content of a PSP expression."""
if s.startswith('<%=') and s.endswith('%>'):
return s[3:-2]
return ''
def checkAttributes(tagType, attrs, validAttrs):
"""Check for mandatory and optional atributes."""
attrs = set(attrs)
mandatoryAttrs = validAttrs[0]
for attr in mandatoryAttrs:
try:
attrs.remove(attr)
except KeyError:
raise PSPParserException(
f'{tagType}: Mandatory attribute {attr} missing') from None
optionalAttrs = validAttrs[1]
for attr in attrs:
if attr not in optionalAttrs:
raise PSPParserException('{tagType}: Invalid attribute {attr}')
def splitLines(text, keepends=False):
"""Split text into lines."""
return text.splitlines(keepends)
def startsNewBlock(line):
"""Determine whether a code line starts a new block."""
line = line.strip()
if line.startswith('#'):
return False
try:
compile(line, '<string>', 'exec')
except SyntaxError:
try:
compile(line + '\n pass', '<string>', 'exec')
except Exception:
pass
else:
return True
else:
return False
return line.endswith(':')
def normalizeIndentation(pySource):
"""Take code block that may be too indented and move it all to the left."""
lines = splitLines(pySource, True)
minIndent = None
indents = []
for line in lines:
strippedLine = line.lstrip(' \t')
indent = len(line) - len(strippedLine)
indents.append(len(line) - len(strippedLine))
if strippedLine.lstrip('\r\n') and not strippedLine.startswith('#'):
if minIndent is None or indent < minIndent:
minIndent = indent
if not minIndent:
break
if minIndent:
pySource = ''.join(
line[min(minIndent, indent):]
for line, indent in zip(lines, indents))
return pySource