File size: 6,151 Bytes
985c397 | 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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | #! python
# SPDX-License-Identifier: LGPL-2.1-or-later
# (c) 2007 Jürgen Riegel
import os
def ensureDir(path, mode=0o777):
try:
os.makedirs(path, mode)
except OSError as err:
# https://docs.python.org/3/tutorial/errors.html
# raise an error unless it's about an already existing directory
print("Dir Exist")
# if errno != 17 or not os.path.isdir(path):
# raise
def convertMultilineString(str):
str = str.replace("\n", "\\n")
str = str.replace('"', '\\"')
return str
"Yet Another Python Templating Utility, Version 1.2"
import sys
# utility stuff to avoid tests in the mainline code
class _nevermatch:
"Polymorphic with a regex that never matches"
def match(self, line):
return None
_never = _nevermatch() # one reusable instance of it suffices
def identity(string, why):
"A do-nothing-special-to-the-input, just-return-it function"
return string
def nohandle(string):
"A do-nothing handler that just re-raises the exception"
raise
# and now the real thing
class copier:
"Smart-copier (YAPTU) class"
def copyblock(self, cur_line=0, last=None):
"Main copy method: process lines [i,last) of block"
def repl(match, self=self):
"return the eval of a found expression, for replacement"
# uncomment for debug: print ('!!! replacing',match.group(1))
expr = self.preproc(match.group(1), "eval")
try:
return str(eval(expr, self.globals, self.locals))
except Exception:
return str(self.handle(expr))
block = self.locals["_bl"]
if last is None:
last = len(block)
while cur_line < last:
line = block[cur_line]
match = self.restat.match(line)
if match: # a statement starts "here" (at line block[i])
# i is the last line to _not_ process
stat = match.string[match.end(0) :].strip()
j = cur_line + 1 # look for 'finish' from here onwards
nest = 1 # count nesting levels of statements
while j < last:
line = block[j]
# first look for nested statements or 'finish' lines
if self.restend.match(line): # found a statement-end
nest = nest - 1 # update (decrease) nesting
if nest == 0:
break # j is first line to _not_ process
elif self.restat.match(line): # found a nested statement
nest = nest + 1 # update (increase) nesting
elif nest == 1: # look for continuation only at this nesting
match = self.recont.match(line)
if match: # found a contin.-statement
nestat = match.string[match.end(0) :].strip()
stat = "%s _cb(%s,%s)\n%s" % (stat, cur_line + 1, j, nestat)
cur_line = j # again, i is the last line to _not_ process
j = j + 1
stat = self.preproc(stat, "exec")
stat = "%s _cb(%s,%s)" % (stat, cur_line + 1, j)
# for debugging, uncomment...: print(f"-> Executing on line {cur_line}: {stat}")
exec(stat, self.globals, self.locals)
cur_line = j + 1
else: # normal line, just copy with substitution
try:
self.ouf.write(self.regex.sub(repl, line).encode("utf8"))
except TypeError:
self.ouf.write(self.regex.sub(repl, line))
cur_line = cur_line + 1
def __init__(
self,
regex=_never,
dict=None,
restat=_never,
restend=_never,
recont=_never,
preproc=identity,
handle=nohandle,
ouf=sys.stdout,
):
"Initialize self's attributes"
self.regex = regex
if dict is not None:
self.globals = dict
else:
self.globals = {}
self.globals["sys"] = sys
self.locals = {"_cb": self.copyblock}
self.restat = restat
self.restend = restend
self.recont = recont
self.preproc = preproc
self.handle = handle
self.ouf = ouf
def copy(self, block=None, inf=sys.stdin):
"Entry point: copy-with-processing a file, or a block of lines"
if block is None:
block = inf.readlines()
self.locals["_bl"] = block
self.copyblock()
def replace(template, dict, file):
"Test: copy a block of lines, with full processing"
import re
rex = re.compile(r"@([^@]+)@")
rbe = re.compile(r"\+")
ren = re.compile(r"-")
rco = re.compile(r"= ")
x = 23 # just a variable to try substitution
cop = copier(rex, dict, rbe, ren, rco)
lines_block = [line + "\n" for line in template.split("\n")]
cop.ouf = file
cop.copy(lines_block)
if __name__ == "__main__":
"Test: copy a block of lines, with full processing"
import re
rex = re.compile(r"@([^@]+)@")
rbe = re.compile(r"\+")
ren = re.compile(r"-")
rco = re.compile(r"= ")
x = 23 # just a variable to try substitution
cop = copier(rex, globals(), rbe, ren, rco)
lines_block = [
line + "\n"
for line in """
A first, plain line -- it just gets copied.
A second line, with @x@ substitutions.
+ x+=1 # non-block statements MUST end with comments
-
Now the substitutions are @x@.
+ if x>23:
After all, @x@ is rather large!
= else:
After all, @x@ is rather small!
-
+ for i in range(3):
Also, @i@ times @x@ is @i*x@.
-
One last, plain line at the end.""".split(
"\n"
)
]
print("*** input:")
print("".join(lines_block))
print("*** output:")
cop.copy(lines_block)
|