Commit 57e43ab2 authored by Carsten Eie Frigaard's avatar Carsten Eie Frigaard
Browse files

update

parent 4c419aa3
#!/usr/bin/env python3 #!/usr/bin/env python3
from Utils.dbg import ERR, DiagStdErr, PrettyPrintTracebackDiagnostics from Utils.dbg import ERR, DiagStdErr, PrettyPrintTracebackDiagnostics
from sys import stdout, stderr from sys import stdout, stderr
from html import escape, unescape
from urllib.parse import quote
def Str(t, checknonempty=True): def Str(t, checknonempty=True):
assert isinstance(t, str), f"exected string but got type='{type(t)}'" assert isinstance(t, str), f"exected string but got type='{type(t)}'"
...@@ -34,6 +37,8 @@ def Check(expr, msg): ...@@ -34,6 +37,8 @@ def Check(expr, msg):
Str(msg) Str(msg)
if not Bool(expr): if not Bool(expr):
ERR("EXPRESSION NOT FULLFILLED: " + msg) ERR("EXPRESSION NOT FULLFILLED: " + msg)
return False
return True
def Trim(s, checknonempty=True): def Trim(s, checknonempty=True):
s = Str(s, Bool(checknonempty)).replace("\t"," ") s = Str(s, Bool(checknonempty)).replace("\t"," ")
...@@ -69,6 +74,22 @@ def LoadText(filename, timeout=4000, split=True): ...@@ -69,6 +74,22 @@ def LoadText(filename, timeout=4000, split=True):
c = c.split("\n") c = c.split("\n")
return c return c
def HtmlEncode(s):
# for text in html page
return escape(Str(s, False))
def HtmlDecode(s):
return unescape(Str(s, False))
def UrlQuote(s):
# for file names in urls
s = quote(Str(s, False), safe='')
assert s.find("'") < 0
assert s.find('"') < 0
assert s.find(" ") < 0
return s
def MkHtmlPage(htmlcontent): def MkHtmlPage(htmlcontent):
assert Str(htmlcontent).find("DOCTYPE")<0 and htmlcontent.find("<html>")<=0 and htmlcontent.find("<body>")<=0 assert Str(htmlcontent).find("DOCTYPE")<0 and htmlcontent.find("<html>")<=0 and htmlcontent.find("<body>")<=0
......
...@@ -6,7 +6,6 @@ from Utils.mkutils import * ...@@ -6,7 +6,6 @@ from Utils.mkutils import *
from sys import argv from sys import argv
from argparse import ArgumentParser from argparse import ArgumentParser
from html import escape, unescape
if __name__ == '__main__': if __name__ == '__main__':
...@@ -16,20 +15,12 @@ if __name__ == '__main__': ...@@ -16,20 +15,12 @@ if __name__ == '__main__':
LEFT = '<' LEFT = '<'
RIGHT= '>' RIGHT= '>'
def HtmlEncode(s):
return escape(Str(s, False))
def HtmlDecode(s):
return unescape(Str(s, False))
def _mkHtml(tag, style=""): def _mkHtml(tag, style=""):
if len(Str(style, False)) > 0: if len(Str(style, False)) > 0:
if style[0]!=" ": if style[0]!=" ":
style = " " + style style = " " + style
if style.find("'") >= 0: Check(style.find("'") < 0, f"no plings in style, please, got style = '{style}'")
ERR(f"no plings in style, please, got style = '{style}'") Check(style.find('"') < 0, f"no quotes in style, please, got style = '{style}'")
if style.find('"') >= 0:
ERR(f"no quotes in style, please, got style = '{style}'")
return f"{LEFT}{Str(tag)}{style}{RIGHT}" return f"{LEFT}{Str(tag)}{style}{RIGHT}"
...@@ -84,8 +75,7 @@ if __name__ == '__main__': ...@@ -84,8 +75,7 @@ if __name__ == '__main__':
arg0 = Trim(args[0], checknonempty0) arg0 = Trim(args[0], checknonempty0)
arg1 = Trim(args[1], checknonempty1) arg1 = Trim(args[1], checknonempty1)
if arg0.find('"')>=0 or arg0.find("'")>=0: Check(arg0.find('"') < 0 and arg0.find("'") < 0, f"do not use pligs (') or quotes (\") in style command, style='{arg0}'")
ERR(f"do not use pligs (') or quotes (\") in style command, style='{arg0}'")
return arg0, arg1 return arg0, arg1
...@@ -104,18 +94,14 @@ if __name__ == '__main__': ...@@ -104,18 +94,14 @@ if __name__ == '__main__':
arg0 = Str(args[0], False) arg0 = Str(args[0], False)
arg1 = Trim(args[1]) arg1 = Trim(args[1])
if len(arg1)==0: Check( len(arg1) > 0, f"need second link argument or nonempty first argument, currently empty for arguments '{a}'")
ERR(f"need second link argument or nonempty first argument, currently empty for arguments '{a}'")
n_http = arg1.find("http://") n_http = arg1.find("http://")
n_https = arg1.find("https://") n_https = arg1.find("https://")
m = 7 + (1 if n_https==0 else 0) m = 7 + (1 if n_https==0 else 0)
if not (n_http==0 or n_https==0): Check(n_http==0 or n_https==0, f"link '{arg1}' does not begin with 'http://' or 'https://' as it should")
ERR(f"link '{arg1}' does not begin with 'http://' or 'https://' as it should") Check(arg1[m]!="/", f"link with triple '///', for '{arg1}'")
if arg1[m]=="/":
ERR(f"link with triple '///', for '{arg1}'")
if len(arg0)==0: if len(arg0)==0:
#n = arg1.rfind('/') #n = arg1.rfind('/')
...@@ -129,14 +115,11 @@ if __name__ == '__main__': ...@@ -129,14 +115,11 @@ if __name__ == '__main__':
if uselinkfilename: if uselinkfilename:
k = arg0.rfind("/") k = arg0.rfind("/")
if arg0[-1]=="/": Check(arg0[-1]!="/", f"can not generate file name, when link argument '{arg0}' ends in a slash '/'")
ERR(f"can not generate file name, when link argument '{arg0}' ends in a slash '/'") Check( k > 0, f"could not generate filename from link '{arg0}', need at least one slash '/'")
if k<=0:
ERR("could not generate filename from link '{arg0}', need at least one slash '/'")
arg0 = arg0[k+1:] arg0 = arg0[k+1:]
if len(arg0)==0: Check(len(arg0)>0, "link arg0 ends-up empty, this was not the way it should be")
ERR("link arg0 ends-up empty, this was not the way it should be")
exlink = True exlink = True
if arg1.find("au.dk")>0: if arg1.find("au.dk")>0:
...@@ -251,7 +234,7 @@ if __name__ == '__main__': ...@@ -251,7 +234,7 @@ if __name__ == '__main__':
head = "<br>\n<br>\n" head = "<br>\n<br>\n"
tail = "<br>\n<br>\n" tail = "<br>\n<br>\n"
else: else:
ERR(f"that odd, an unhandled command '{c}' that seem to be present in isCmd() list") Check(False, f"that odd, an unhandled command '{c}' that seem to be present in isCmd() list")
closetags = f"{left}/{c}{right}{tail}" if closing else "" closetags = f"{left}/{c}{right}{tail}" if closing else ""
v = f"{head}{left}{c}{style}{right}{a}{closetags}" v = f"{head}{left}{c}{style}{right}{a}{closetags}"
...@@ -264,7 +247,7 @@ if __name__ == '__main__': ...@@ -264,7 +247,7 @@ if __name__ == '__main__':
elif c=="img": elif c=="img":
v = Cmd.__MkImg(a, left, right) v = Cmd.__MkImg(a, left, right)
else: else:
ERR(f"unknown command '{c}' with argument(s) '{a}'") Check(False, f"unknown command '{c}' with argument(s) '{a}'")
self.__txt += v self.__txt += v
...@@ -339,11 +322,8 @@ if __name__ == '__main__': ...@@ -339,11 +322,8 @@ if __name__ == '__main__':
curr.Parse("\n") curr.Parse("\n")
if curr.State() != 0: Check(curr.State()==0, f"still in command parsing state={curr.State()}")
ERR(f"still in command parsing state={curr.State()}") Check(len(st)==0, f"still {len(st)} elements on stack, expected zero")
if len(st) != 0:
ERR(f"still {len(st)} elements on stack, expected zero")
txt = curr.Text() txt = curr.Text()
Dbg(verbose, f"{Col('CYAN')}{Str(txt)}{ColEnd()}", 3) Dbg(verbose, f"{Col('CYAN')}{Str(txt)}{ColEnd()}", 3)
...@@ -356,16 +336,13 @@ if __name__ == '__main__': ...@@ -356,16 +336,13 @@ if __name__ == '__main__':
if len(Trim(i, False))>0: if len(Trim(i, False))>0:
n = Str(i).find(']') n = Str(i).find(']')
if n<=0 or i[0]!='[': Check(not(n<=0 or i[0]!='['), f"refs need to be of the form '[key] value', got='{i}'")
ERR(f"refs need to be of the form '[key] value', got='{i}'")
key = i[0:n+1].strip() key = i[0:n+1].strip()
val = i[n+1:].strip() val = i[n+1:].strip()
if len(key)==0: Check(len(key) > 0, f"empty key in ref element='{i}'")
ERR(f"empty key in ref element='{i}'") Check(len(val) > 0, f"empty value in ref element='{i}'")
if len(val)==0:
ERR(f"empty value in ref element='{i}'")
Dbg(verbose, f" ParseRef(): found '{key}' => '{val}'", 2) Dbg(verbose, f" ParseRef(): found '{key}' => '{val}'", 2)
assert not r.get(key) assert not r.get(key)
...@@ -520,13 +497,14 @@ if __name__ == '__main__': ...@@ -520,13 +497,14 @@ if __name__ == '__main__':
verbose = Int(args.v) verbose = Int(args.v)
coursefile = Str(args.c) coursefile = Str(args.c)
ouptputfiledir = Str(args.o)
Dbg(verbose, f"{Col('PURPLE')}GENERATING html course from file '{coursefile}'..{ColEnd()}") Dbg(verbose, f"{Col('PURPLE')}GENERATING html course from file '{coursefile}'..{ColEnd()}")
htmlencoded = [HtmlEncode(i) for i in LoadCourseFile(coursefile)] htmlencoded = [HtmlEncode(i) for i in LoadCourseFile(coursefile)]
htmlstructure = ParseStructure(htmlencoded) htmlstructure = ParseStructure(htmlencoded)
MkHtml(htmlstructure, not Bool(args.t), Str(args.o)) MkHtml(htmlstructure, not Bool(args.t), outputfiledir)
Dbg(verbose, f"{Col('PURPLE')}DONE{ColEnd()}") Dbg(verbose, f"{Col('PURPLE')}DONE{ColEnd()}")
......
#!/usr/bin/env python3 #!/usr/bin/env python3
from Utils.dbg import ERR, WARN, isBool, isStr, isInt, isNatural, isTuple, isList, isDict
from Utils.colors import Col, ColEnd from Utils.colors import Col, ColEnd
from Utils.mkutils import * from Utils.mkutils import *
...@@ -15,14 +14,17 @@ if __name__ == '__main__': ...@@ -15,14 +14,17 @@ if __name__ == '__main__':
outputstr = "" outputstr = ""
def CheckTuple(t, secondisstr=False):
Check(len(Tuple(t)) ==2, "not a tuple with len=2")
Check(len(Str(t[0], False))>=0, "tuple first not of string type")
Check(isinstance(t[1], str) or (not secondisstr and isinstance(t[1], dict)), f"tuple second not of expected type(s), type={type(t[1])}")
return True
def Print(msg, outputfile): def Print(msg, outputfile):
global outputstr global outputstr
assert isStr(msg) outputstr += Str(msg) + "\n"
outputstr += msg + "\n"
def Find(root, excludepat): def Find(root, excludepat):
assert isList(excludepat)
tree = {} tree = {}
tree['trees'] = [] tree['trees'] = []
tree['files'] = [] tree['files'] = []
...@@ -34,7 +36,7 @@ if __name__ == '__main__': ...@@ -34,7 +36,7 @@ if __name__ == '__main__':
d = d[2:] d = d[2:]
skip = False skip = False
for j in excludepat: for j in List(excludepat):
if d.find(j)>=0: if d.find(j)>=0:
skip = True skip = True
break break
...@@ -48,17 +50,9 @@ if __name__ == '__main__': ...@@ -48,17 +50,9 @@ if __name__ == '__main__':
def PrintItem(i, level, isDir): def PrintItem(i, level, isDir):
def Tab(level, tab): def Tab(level, tab):
assert isNatural(level)
assert isStr(tab)
assert isBool(isDir)
#if htmlmode:
# return "", ""
# #return f"<p style='padding-left: {(level+1)*40}px;'>", "</p>"
t = "" t = ""
for n in range(level): for n in range(Int(level)):
t += tab t += Str(tab)
return t, "" return t, ""
...@@ -68,8 +62,7 @@ if __name__ == '__main__': ...@@ -68,8 +62,7 @@ if __name__ == '__main__':
def Link(i, isDir): def Link(i, isDir):
def CheckUrl(linkurl): def CheckUrl(linkurl):
assert Str(linkurl).find("'") < 0 assert Str(linkurl).find("'") < 0
if Bool(testurls):
if testurls:
sfx = linkurl.split(".")[-1] sfx = linkurl.split(".")[-1]
if sfx!="py": if sfx!="py":
#print(f"WEB GET test {linkurl}..") #print(f"WEB GET test {linkurl}..")
...@@ -78,42 +71,31 @@ if __name__ == '__main__': ...@@ -78,42 +71,31 @@ if __name__ == '__main__':
urlretrieve(linkurl, filename=None) urlretrieve(linkurl, filename=None)
except Exception as ex: except Exception as ex:
#PrettyPrintTracebackDiagnostics(ex) #PrettyPrintTracebackDiagnostics(ex)
print(f"{Col('LRED UNDERLINE')}EXCEPTION:{ColEnd()}{Col('LRED')} {ex}{ColEnd()}", stderr) Warn(f"{Col('LRED UNDERLINE')}EXCEPTION:{ColEnd()}{Col('LRED')} {ex}{ColEnd()}")
WARN(f"ignore test on link {linkurl}") Warn(f"ignore test on link {linkurl}")
return linkurl return linkurl
assert isStr(url) CheckTuple(i)
assert isBool(isDir)
assert isTuple(i) if Bool(isDir):
assert isBool(bsfileidmode) return Str(i[0])
if isDir:
return i[0]
assert isStr(i[0]) if Bool(bsfileidmode):
assert isStr(i[1]) filename = UrlQuote(Str(i[1]))
orgUnitId = Str(str(ouid) if Int(ouid>0) else "{orgUnitId}")
if bsfileidmode: # From BS: <a href="/d2l/common/dialogs/quickLink/quickLink.d2l?ou={orgUnitId}&amp;type=coursefile&amp;fileId=Kursusfiler%2fEksamen%2fScreenshot_mathcad_navn-og-studienummer.jpg" target="_self">dsf</a>
filename = Str(i[1].replace("/","%2f").replace(" ","%20"))
assert filename.find("'") < 0
assert filename.find('"') < 0
# <a href="/d2l/common/dialogs/quickLink/quickLink.d2l?ou={orgUnitId}&amp;type=coursefile&amp;fileId=Kursusfiler%2fEksamen%2fScreenshot_mathcad_navn-og-studienummer.jpg" target="_self">dsf</a>
orgUnitId = "{orgUnitId}"
if ouid > 0:
orgUnitId = str(ouid)
assert isStr(orgUnitId)
r = '<a href="/d2l/common/dialogs/quickLink/quickLink.d2l?ou=' + orgUnitId + '&amp;type=coursefile&amp;fileId='+filename+'" target="_self">'+i[0]+'</a>' r = '<a href="/d2l/common/dialogs/quickLink/quickLink.d2l?ou=' + orgUnitId + '&amp;type=coursefile&amp;fileId='+filename+'" target="_self">'+i[0]+'</a>'
else: else:
linkurl = CheckUrl(url + "/" + i[1]) linkurl = CheckUrl(Str(url) + "/" + i[1])
assert linkurl.find("'") < 0 assert linkurl.find("'") < 0
r = f"<a href='{linkurl}'>{i[0]}</a>" r = f"<a href='{linkurl}'>{i[0]}</a>"
return r return r
assert isTuple(i) CheckTuple(i)
assert isStr(i[0])
nbsp = "&nbsp;" nbsp = "&nbsp;"
tab = Tab(4*level, nbsp if htmlmode else " ") tab = Tab(4*level, nbsp if htmlmode else " ")
...@@ -123,36 +105,28 @@ if __name__ == '__main__': ...@@ -123,36 +105,28 @@ if __name__ == '__main__':
pre = f"<span style=\"font-family: 'courier new', courier, sans-serif\">" if htmlmode else "" pre = f"<span style=\"font-family: 'courier new', courier, sans-serif\">" if htmlmode else ""
post = "</span>" if htmlmode else "" post = "</span>" if htmlmode else ""
assert isTuple(tab) CheckTuple(tab, True)
r = pre + tab[0] + link + tab[1] + Newline() + post r = pre + tab[0] + link + tab[1] + Newline() + post
Print(r, outputfile) Print(r, outputfile)
return r return r
def PrintTree(tree, level=0): def PrintTree(tree, level=0):
assert isDict(tree)
assert isStr(url)
assert isBool(htmlmode)
files=0 files=0
dirs=0 dirs=0
for j in ['trees', 'files']: for j in ['trees', 'files']:
t = tree[j] t = List(Dict(tree)[j])
assert isList(t) d = List(sorted(tree[j]))
d = sorted(tree[j])
assert isList(d)
for i in d: for i in d:
CheckTuple(i, False)
isdict = isinstance(i[1], dict) isdict = isinstance(i[1], dict)
assert isTuple(i)
assert isdict == (j=='trees') assert isdict == (j=='trees')
PrintItem(i, level, isdict) PrintItem(i, level, isdict)
files += 1 files += 1
if j=='trees': if j=='trees':
r = (PrintTree(i[1], level+1)) r = Tuple((PrintTree(i[1], level+1)))
assert isTuple(r)
files += r[0] files += r[0]
dirs += 1 + r[1] dirs += 1 + r[1]
...@@ -188,27 +162,21 @@ if __name__ == '__main__': ...@@ -188,27 +162,21 @@ if __name__ == '__main__':
verbose = Int(args.v) verbose = Int(args.v)
testurls = Bool(args.t) testurls = Bool(args.t)
if testurls: Check(not testurls, "test urls not implemented yet")
WARN("test urls not implemented yet")
htmlmode = not Bool(args.plain) htmlmode = not Bool(args.plain)
header = Str(args.header, False) header = Str(args.header, False)
url = Str(args.url) url = Str(args.url)
if url[-1]=='/': Check(url[-1]!='/',"no trailing '/' in url, please remove")
ERR("no trailing '/' in url, please remove")
outputfile = Str(args.o) outputfile = Str(args.o)
bsfileidmode = Bool(args.bsfileidmode) bsfileidmode = Bool(args.bsfileidmode)
ouid = Str(args.ouid, False) ouid = Str(args.ouid, False)
if len(ouid)>0: ouid = Int(Int(int(ouid)) if len(ouid)>0 else -1, -1)
ouid = int(ouid)
else:
ouid = -1
assert isInt(ouid)
excludepath += "," + Str(args.excludepath) excludepath += "," + Str(args.excludepath)
assert excludepath.find(" ") < 0 assert excludepath.find(" ") < 0
...@@ -218,8 +186,7 @@ if __name__ == '__main__': ...@@ -218,8 +186,7 @@ if __name__ == '__main__':
#if bsfileidmode and len(url)>0: #if bsfileidmode and len(url)>0:
# ERR("cannot specify -url and -bsfileidmode at the same time") # ERR("cannot specify -url and -bsfileidmode at the same time")
if ouid>0 and not bsfileidmode: Check( not( ouid>0 and not bsfileidmode), "canot specify -ouid without -bsfileidmode")
ERR("canot specify -ouid without -bsfileidmode")
root = "./" root = "./"
Dbg(verbose, f"{Col('PURPLE')}GENERATING html file tree from root '{root}'" + (("" if bsfileidmode else f", (url='{url}')") if verbose > 0 else "") + f"..{ColEnd()}") Dbg(verbose, f"{Col('PURPLE')}GENERATING html file tree from root '{root}'" + (("" if bsfileidmode else f", (url='{url}')") if verbose > 0 else "") + f"..{ColEnd()}")
......
#!/usr/bin/env python3 #!/usr/bin/env python3
from Utils.dbg import ERR
from Utils.colors import Col, ColEnd from Utils.colors import Col, ColEnd
from Utils.mkutils import * from Utils.mkutils import *
from sys import argv from sys import argv
from argparse import ArgumentParser from argparse import ArgumentParser
from html import escape
if __name__ == '__main__': if __name__ == '__main__':
def ParseStructure(planlist): def ParseStructure(planlist):
...@@ -37,10 +34,8 @@ if __name__ == '__main__': ...@@ -37,10 +34,8 @@ if __name__ == '__main__':
N = len(s) N = len(s)
if N != expectedlen: if N != expectedlen:
if expectedlen < 0 and N < 2: if not Check(not(expectedlen < 0 and N < 2), f"expected more than one column in header '{h}', but got {N} column(s)"):
ERR(f"expected more than one column in header '{h}', but got {N} column(s)") Check(expectedlen <= 0, f"expected exactly {expectedlen} column(s) in line '{h}', but got {N} column(s)")
elif expectedlen >= 0:
ERR(f"expected exaclty {expectedlen} column(s) in line '{h}', but got {N} column(s)")
r = [] r = []
o = "" o = ""
...@@ -58,15 +53,13 @@ if __name__ == '__main__': ...@@ -58,15 +53,13 @@ if __name__ == '__main__':
Check(planlist[i]==expected, f"planlist missing tag '{expected}' at line {i}, got='{planlist[i]}'") Check(planlist[i]==expected, f"planlist missing tag '{expected}' at line {i}, got='{planlist[i]}'")
def CheckContent(elem): def CheckContent(elem):
if Str(elem)!=elem.lower(): Check(Str(elem)==elem.lower(), f"elem '{elem}' must be all-lower-case")
ERR(f"elem '{elem}' must be all-lower-case")
t = s.get(Str(elem)) t = s.get(Str(elem))
Check(isinstance(t, list), f"planlist missing {elem.