Compare commits

..

No commits in common. "0d0d1e841990d2a9def2d6989341b661277fa987" and "697419acacd8ea5fda4ae0bffe7029440f19c42b" have entirely different histories.

10 changed files with 419 additions and 683 deletions

View File

@ -662,103 +662,42 @@ def xlist_ii(parasite_id,host_id,new_name,new_code):
print(r3.text) print(r3.text)
print("\n\n") print("\n\n")
def course_term_summary_2():
lines = codecs.open('cache/term_summary.txt','r','utf-8').readlines()
output = codecs.open('cache/term_summary.html','w','utf-8')
for L in lines:
try:
L = L.strip()
print(L)
if re.search('unpublished',L):
m = re.search(r"'id': (\d+),",L)
m2 = re.search(r"'course_code': '(.+?)',",L)
if m:
ss = "<br />Course: <a href='%s' target='_blank'>%s</a><br />" % ("https://ilearn.gavilan.edu/courses/"+str(m.group(1)), m2.group(1))
output.write( ss )
print(ss+"\n")
except Exception as e:
print(e)
def course_term_summary_3():
# doesn't work cause of single, not double quotes?!?!
lines = codecs.open('cache/term_summary.txt','r','utf-8').readlines()
output = codecs.open('cache/term_summary.html','w','utf-8')
for L in lines:
try:
L = L.strip()
print(L)
ll = json.loads(L)
print(ll)
print(ll['course_code'])
if ll['workflow_state'] == 'unpublished':
ss = "<br />Course: <a href='%s' target='_blank'>%s</a><br />" % ("https://ilearn.gavilan.edu/courses/"+str(ll['id']), ll['course_code'] )
output.write( ss )
print(ss+"\n")
except Exception as e:
print(e)
# check number of students and publish state of all shells in a term
def all_semester_course_sanity_check(): def all_semester_course_sanity_check():
t = 181 c = getCoursesInTerm(178,0,0) # sp23
term = "sp24" codecs.open('cache/courses_in_term_178.json','w','utf-8').write(json.dumps(c,indent=2))
c = getCoursesInTerm(t,0,0) output = codecs.open('cache/courses_w_sections.csv','w','utf-8')
sched1 = requests.get(f"http://gavilan.cc/schedule/{term}_sched_expanded.json").json() output.write( ",".join(['what','id','parent_course_id','sis_course_id','name']) + "\n" )
sched = { x['crn']: x for x in sched1 }
#codecs.open('cache/courses_in_term_{t}.json','w','utf-8').write(json.dumps(c,indent=2))
#output = codecs.open('cache/courses_w_sections.csv','w','utf-8')
#output.write( ",".join(['what','id','parent_course_id','sis_course_id','name']) + "\n" )
output2 = codecs.open('cache/courses_checker.csv','w','utf-8') output2 = codecs.open('cache/courses_checker.csv','w','utf-8')
output2.write( ",".join(['id','sis_course_id','name','state','mode','startdate','students']) + "\n" ) output2.write( ",".join(['id','sis_course_id','name','state','students']) + "\n" )
htmlout = codecs.open('cache/courses_checker.html','w','utf-8')
htmlout.write('<html><body><table>\n')
htmlout.write(f'<tr><td><b>Name</b></td><td><b>SIS ID</b></td><td><b>State</b></td><td><b>Mode</b></td><td><b>Start Date</b></td><td><b># Stu</b></td></tr>\n')
i = 0 i = 0
for course in c: for course in c:
u2 = url + '/api/v1/courses/%s?include[]=total_students' % str(course['id']) u2 = url + '/api/v1/courses/%s?include[]=total_students' % str(course['id'])
course['info'] = fetch(u2) course['info'] = fetch(u2)
#print(json.dumps(course['info'],indent=2))
# correlate to schedule
crn = course['sis_course_id'][7:]
ctype = '?'
cstart = '?'
ts = '?' ts = '?'
if crn in sched: try:
ctype = sched[crn]['type'] ts = course['info']['total_students']
cstart = sched[crn]['start'] except Exception as e:
ts = sched[crn]['act'] pass
info = [ 'course', course['id'], '', course['sis_course_id'], course['name'], course['workflow_state'], ts ] info = [ 'course', course['id'], '', course['sis_course_id'], course['name'], course['workflow_state'], ts ]
info = list(map(str,info)) info = list(map(str,info))
info2 = [ course['id'], course['sis_course_id'], course['name'], course['workflow_state'], ctype, cstart, ts ] info2 = [ course['id'], course['sis_course_id'], course['name'], course['workflow_state'], ts ]
info2 = list(map(str,info2)) info2 = list(map(str,info2))
output2.write( ",".join(info2) + "\n" ) output2.write( ",".join(info2) + "\n" )
output2.flush() output2.flush()
print(info2) print(info2)
#output.write( ",".join(info) + "\n" ) output.write( ",".join(info) + "\n" )
uu = f"https://ilearn.gavilan.edu/courses/{course['id']}"
htmlout.write(f'<tr><td><a href="{uu}" target="_blank">{course["name"]}</a></td><td>{course["sis_course_id"]}</td><td>{course["workflow_state"]}</td><td>{ctype}</td><td>{cstart}</td><td>{ts}</td></tr>\n')
htmlout.flush()
#uu = url + '/api/v1/courses/%s/sections' % str(course['id']) #uu = url + '/api/v1/courses/%s/sections' % str(course['id'])
#course['sections'] = fetch(uu) #course['sections'] = fetch(uu)
#s_info = [ [ 'section', y['id'], y['course_id'], y['sis_course_id'], y['name'], y['total_students'] ] for y in course['sections'] ] #s_info = [ [ 'section', y['id'], y['course_id'], y['sis_course_id'], y['name'], y['total_students'] ] for y in course['sections'] ]
#for row in s_info: #for row in s_info:
# print(row) # print(row)
# output.write( ",".join( map(str,row) ) + "\n" ) # output.write( ",".join( map(str,row) ) + "\n" )
#output.flush() output.flush()
i += 1 i += 1
#if i % 5 == 0: if i % 5 == 0:
# codecs.open('cache/courses_w_sections.json','w','utf-8').write(json.dumps(c,indent=2)) codecs.open('cache/courses_w_sections.json','w','utf-8').write(json.dumps(c,indent=2))
#codecs.open('cache/courses_w_sections.json','w','utf-8').write(json.dumps(c,indent=2)) codecs.open('cache/courses_w_sections.json','w','utf-8').write(json.dumps(c,indent=2))
htmlout.write('</table></body></html>\n')
def eslCrosslister(): def eslCrosslister():
@ -1072,7 +1011,7 @@ def enroll_gott_workshops():
#'GOTT 5: Essentials of Blended Learning (HyFlex)2023-06-25 17:00:00': 17987, #'GOTT 5: Essentials of Blended Learning (HyFlex)2023-06-25 17:00:00': 17987,
#'GOTT 1: Intro to Teaching Online with Canvas2023-05-29 17:00:00': 17985, #'GOTT 1: Intro to Teaching Online with Canvas2023-05-29 17:00:00': 17985,
#'GOTT 1: Intro to Teaching Online with Canvas2023-08-20 17:00:00': 17994 #'GOTT 1: Intro to Teaching Online with Canvas2023-08-20 17:00:00': 17994
'GOTT 1: Intro to Online Teaching2024-01-02 16:00:00': 19278, 'GOTT 1: Intro to Online Teaching2024-01-02 16:00:00': 19221,
'GOTT 2: Intro to Asynchronous Teaching and Learning2024-01-02 16:00:00': 19222, 'GOTT 2: Intro to Asynchronous Teaching and Learning2024-01-02 16:00:00': 19222,
'GOTT 5: Essentials of Blended Learning2024-01-02 16:00:00': 19223, 'GOTT 5: Essentials of Blended Learning2024-01-02 16:00:00': 19223,
'GOTT 6: Intro to Live Online Teaching and Learning2024-01-14 16:00:00': 19224, 'GOTT 6: Intro to Live Online Teaching and Learning2024-01-14 16:00:00': 19224,
@ -1430,7 +1369,7 @@ def teacher_to_many_shells():
import os, pickle import os, pickle
def create_sandboxes(): def create_sandboxes():
courses_to_sandbox = [ (19278, ' Sandbox GOTT1 WI24'), courses_to_sandbox = [ (19221, ' Sandbox GOTT1 WI24'),
(19222, ' Sandbox GOTT2 WI24'), (19222, ' Sandbox GOTT2 WI24'),
(19223, ' Sandbox GOTT5 WI24'), (19223, ' Sandbox GOTT5 WI24'),
#(19224, ' Sandbox GOTT6 WI24') #(19224, ' Sandbox GOTT6 WI24')
@ -1448,7 +1387,6 @@ def create_sandboxes():
for crs_id, label in courses_to_sandbox: for crs_id, label in courses_to_sandbox:
crs_info = getCourses(crs_id) crs_info = getCourses(crs_id)
print(json.dumps(crs_info,indent=2))
c_name = crs_info['name'] c_name = crs_info['name']
print(f"Students in course {crs_id}: {c_name}" ) print(f"Students in course {crs_id}: {c_name}" )
enrolled = course_enrollment(crs_id) enrolled = course_enrollment(crs_id)
@ -1572,6 +1510,47 @@ def create_sandboxes():
def course_term_summary_2():
lines = codecs.open('cache/term_summary.txt','r','utf-8').readlines()
output = codecs.open('cache/term_summary.html','w','utf-8')
for L in lines:
try:
L = L.strip()
print(L)
if re.search('unpublished',L):
m = re.search(r"'id': (\d+),",L)
m2 = re.search(r"'course_code': '(.+?)',",L)
if m:
ss = "<br />Course: <a href='%s' target='_blank'>%s</a><br />" % ("https://ilearn.gavilan.edu/courses/"+str(m.group(1)), m2.group(1))
output.write( ss )
print(ss+"\n")
except Exception as e:
print(e)
def course_term_summary_3():
# doesn't work cause of single, not double quotes?!?!
lines = codecs.open('cache/term_summary.txt','r','utf-8').readlines()
output = codecs.open('cache/term_summary.html','w','utf-8')
for L in lines:
try:
L = L.strip()
print(L)
ll = json.loads(L)
print(ll)
print(ll['course_code'])
if ll['workflow_state'] == 'unpublished':
ss = "<br />Course: <a href='%s' target='_blank'>%s</a><br />" % ("https://ilearn.gavilan.edu/courses/"+str(ll['id']), ll['course_code'] )
output.write( ss )
print(ss+"\n")
except Exception as e:
print(e)
## ## ## ##
## ## ## ##
## ## Course Nav and External Tools ## ## Course Nav and External Tools
@ -1579,8 +1558,8 @@ def create_sandboxes():
## ## ## ##
def do_gav_connect(): def do_gav_connect():
term = 181 term = 180
sem = "202430" sem = "202370"
get_fresh = 1 get_fresh = 1
crns = [sem + "-" + x.strip() for x in open('cache/starfish.txt','r').readlines()] crns = [sem + "-" + x.strip() for x in open('cache/starfish.txt','r').readlines()]
target = len(crns) target = len(crns)
@ -2017,14 +1996,17 @@ if __name__ == "__main__":
8: ['Save enrollments in a course', course_enrollment], 8: ['Save enrollments in a course', course_enrollment],
9: ['Simple list of course data, search by sis_id', course_search_by_sis], 9: ['Simple list of course data, search by sis_id', course_search_by_sis],
10: ['Overview of a term', course_term_summary], 10: ['Overview of a term', course_term_summary],
20: ['process the semester overview output (10)', course_term_summary_2],
35: ['Check all courses & their sections in semester', all_semester_course_sanity_check],
11: ['Enroll ORIENTATION and STEM student shells after catching up database.', enroll_o_s_students], 11: ['Enroll ORIENTATION and STEM student shells after catching up database.', enroll_o_s_students],
12: ['Enroll stem students', enroll_stem_students_live], 12: ['Enroll stem students', enroll_stem_students_live],
13: ['Enroll orientation students (refresh local db)', enroll_orientation_students], 13: ['Enroll orientation students (refresh local db)', enroll_orientation_students],
14: ['Enroll ART students', enroll_art_students_live], 14: ['Enroll ART students', enroll_art_students_live],
15: ['List users who passed GOTT 1 / Bootcamp', get_gott1_passers],
16: ['List users who passed Plagiarism Module', get_plague_passers],
18: ['Create some sandbox courses', create_sandboxes],
19: ['make courses visible to auth users', modify_courses],
20: ['process the semester overview output (10)', course_term_summary_2],
22: ['Get a course info by id',getCourses], 22: ['Get a course info by id',getCourses],
23: ['Reset course conclude date',update_course_conclude], 23: ['Reset course conclude date',update_course_conclude],
@ -2035,22 +2017,19 @@ if __name__ == "__main__":
17: ['Remove "new analytics" from all courses navs in a semester', remove_n_analytics], 17: ['Remove "new analytics" from all courses navs in a semester', remove_n_analytics],
21: ['Add course evals', add_evals], 21: ['Add course evals', add_evals],
31: ['Fine tune term dates and winter session', course_by_depts_terms], 27: ['Fine tune term dates and winter session', course_by_depts_terms],
#32: ['Cross-list classes', xlist ], 3: ['Cross-list classes', xlist ],
#33: ['Cross list helper', eslCrosslister], 6: ['Cross list helper', eslCrosslister],
34: ['Cross list a semester from file', semester_cross_lister], 28: ['Cross list a semester from file', semester_cross_lister],
36: ['Quick course list', quick_sem_course_list ], 29: ['Check all courses & their sections in semester', all_semester_course_sanity_check],
37: ['Cross list CWE courses', xlist_cwe], 30: ['Quick course list', quick_sem_course_list ],
38: ['Create calendar event', create_calendar_event], 31: ['Cross list CWE courses', xlist_cwe],
39: ['list all assignments', list_all_assignments], 34: ['Create calendar event', create_calendar_event],
35: ['list all assignments', list_all_assignments],
40: ['Enroll GOTT Workshops', enroll_gott_workshops], 40: ['Enroll GOTT Workshops', enroll_gott_workshops],
41: ['Create some sandbox courses', create_sandboxes],
42: ['Add teacher to many shells', teacher_to_many_shells], 42: ['Add teacher to many shells', teacher_to_many_shells],
43: ['Bulk unenroll from course', bulk_unenroll], 43: ['Bulk unenroll from course', bulk_unenroll],
44: ['List users who passed GOTT 1 / Bootcamp', get_gott1_passers],
45: ['List users who passed Plagiarism Module', get_plague_passers],
46: ['make courses visible to auth users', modify_courses],
# 24: ['Add course evals to whole semester',instructor_list_to_activate_evals], # 24: ['Add course evals to whole semester',instructor_list_to_activate_evals],
# 21: ['Add announcements to homepage', change_course_ann_homepage], # 21: ['Add announcements to homepage', change_course_ann_homepage],
# TODO wanted: group shell for each GP (guided pathway) as a basic student services gateway.... # TODO wanted: group shell for each GP (guided pathway) as a basic student services gateway....

View File

@ -258,7 +258,7 @@ def Memoize( func):
"""
class MyRepl: class MyRepl:
description = { description = {
"switch ": "Switch stream. You can use either 'switch public' or 'switch mine'", "switch ": "Switch stream. You can use either 'switch public' or 'switch mine'",
@ -319,11 +319,16 @@ class MyRepl:
@Memoize @Memoize
def cycle_color(self, s): def cycle_color(self, s):
#Cycle the colors_shuffle """
Cycle the colors_shuffle
"""
return next(self.cyc) return next(self.cyc)
def ascii_art(self, text): def ascii_art(self, text):
"""
Draw the Ascii Art
"""
return return
#fi = figlet_format(text, font='doom') #fi = figlet_format(text, font='doom')
#for i in fi.split('\n'): #for i in fi.split('\n'):
@ -331,6 +336,9 @@ class MyRepl:
def close_window(self, ): def close_window(self, ):
"""
Close screen
"""
global screen global screen
screen.keypad(0); screen.keypad(0);
curses.nocbreak(); curses.nocbreak();
@ -339,6 +347,9 @@ class MyRepl:
def suggest(self, word): def suggest(self, word):
"""
Find suggestion
"""
rel = [] rel = []
if not word: return rel if not word: return rel
word = word.lower() word = word.lower()
@ -356,13 +367,18 @@ class MyRepl:
def curses_print_word(self, word,color_pair_code): def curses_print_word(self, word,color_pair_code):
"""
Print a word
"""
global screen global screen
word = word.encode('utf8') word = word.encode('utf8')
screen.addstr(word,curses.color_pair(color_pair_code)) screen.addstr(word,curses.color_pair(color_pair_code))
def curses_print_line(self, line,color_pair_code): def curses_print_line(self, line,color_pair_code):
#Print a line, scroll down if need """
Print a line, scroll down if need
"""
global screen global screen
line = line.encode('utf8') line = line.encode('utf8')
y,x = screen.getyx() y,x = screen.getyx()
@ -380,6 +396,9 @@ class MyRepl:
def redraw(self, start_y,end_y,fallback_y,fallback_x): def redraw(self, start_y,end_y,fallback_y,fallback_x):
"""
Redraw lines from buf
"""
global screen global screen
for cursor in range(start_y,end_y): for cursor in range(start_y,end_y):
screen.move(cursor,0) screen.move(cursor,0)
@ -393,6 +412,9 @@ class MyRepl:
def scroll_down(self, noredraw,fallback_y,fallback_x): def scroll_down(self, noredraw,fallback_y,fallback_x):
"""
Scroll down 1 line
"""
global screen global screen
# Recreate buf # Recreate buf
# noredraw = n means that screen will scroll down n-1 line # noredraw = n means that screen will scroll down n-1 line
@ -409,6 +431,9 @@ class MyRepl:
def clear_upside(self, n,y,x): def clear_upside(self, n,y,x):
"""
Clear n lines upside
"""
global screen global screen
for i in range(1,n+1): for i in range(1,n+1):
screen.move(y-i,0) screen.move(y-i,0)
@ -418,7 +443,9 @@ class MyRepl:
def display_suggest(self, y,x,word): def display_suggest(self, y,x,word):
# Display box of suggestion """
Display box of suggestion
"""
global screen global screen
g = self.g g = self.g
side = 2 side = 2
@ -516,6 +543,9 @@ class MyRepl:
def inputloop(self, ): def inputloop(self, ):
"""
Main loop input
"""
global screen global screen
word = '' word = ''
screen.addstr("\n" + self.g['prefix'],curses.color_pair(7)) screen.addstr("\n" + self.g['prefix'],curses.color_pair(7))
@ -725,4 +755,5 @@ def repl():
def repl(): def repl():
repl_degs() repl_degs()
"""

View File

@ -1867,18 +1867,8 @@ WHERE
connection.close() connection.close()
def add_sessions(filename='cache/pd_sp24.csv'):
out = codecs.open('cache/pd_sp24.sql','w','utf-8')
with codecs.open(filename, 'r','utf-8') as file:
reader = csv.DictReader(file)
for dirty_row in reader:
row = {k: v.replace("'", "''") for k, v in dirty_row.items()} # Escape single quotes in CSV data
out.write(f"INSERT INTO conf_sessions \
(title, starttime, mode, location, location_irl, `desc`, `type`, length, track, gets_survey, is_flex_approved, category, parent) \
VALUES ('{row['title']}', '{row['starttime']}', '{row['mode']}', '{row['location']}', '{row['location_irl']}', '{row['desc']}', 101, 1, 1, 1, 1, 0, 1364);\n")
def add_sessions():
def add_sessions2():
j_in = json.loads( codecs.open('cache/2023sessions.json','r','utf-8').read()) j_in = json.loads( codecs.open('cache/2023sessions.json','r','utf-8').read())
# Function to format the starttime # Function to format the starttime
@ -1898,7 +1888,7 @@ def add_sessions2():
track = 1 track = 1
id = 1341 id = 1341
f = "id, title, `desc`, `type`, length, starttime, track, location, location_irl, mode, gets_survey, is_flex_approved, parent" f = "id, title, desc, type, length, starttime, track, location, location_irl, mode, gets_survey, is_flex_approved, parent"
fields = ",".join([ ugh(x) for x in f.split(', ') ]) fields = ",".join([ ugh(x) for x in f.split(', ') ])
for session_data in j_in: for session_data in j_in:
@ -1937,7 +1927,7 @@ def test_long_running():
def courses_to_sched(): def courses_to_sched():
# Correlate rows in courses table with an id to rows in schedule table. # Correlate rows in courses table with an id to rows in schedule table.
conn,cur = db('cache/canvas_data/data.db') conn,cur = db('cache/canvas_data/data20231012.db')
q = "SELECT canvasid, code, sis, schedule FROM courses ORDER BY sis DESC" q = "SELECT canvasid, code, sis, schedule FROM courses ORDER BY sis DESC"
conn.row_factory = dict_factory conn.row_factory = dict_factory

View File

@ -1197,10 +1197,10 @@ def fetch_current_rosters():
if len(seen_files)==3: if len(seen_files)==3:
print(' -> %s building data file...' % dt_label) print(' -> %s building data file...' % dt_label)
convert_roster_files(this_sem,year,dt_label) convert_roster_files(this_sem,year,dt_label)
print(' -> moving files...') print(' -> moving files...')
move_to_folder(this_sem,year,dt_label,seen_files) move_to_folder(this_sem,year,dt_label,seen_files)
else: else:
print(" * No courses file. Not moving files.") print(" * No courses file. Not moving files.")
else: else:
print("--> Don't see files.") print("--> Don't see files.")
sftp.close() sftp.close()
@ -1209,11 +1209,11 @@ def fetch_current_rosters_auto():
fetch_minute = "58" fetch_minute = "58"
schedule.every().hour.at(f":{fetch_minute}").do(fetch_current_rosters) schedule.every().hour.at(f":{fetch_minute}").do(fetch_current_rosters)
#schedule.every().day.at("12:35").do(sync_non_interactive) schedule.every().day.at("12:35").do(sync_non_interactive)
#schedule.every().day.at("21:00").do(sync_non_interactive) schedule.every().day.at("21:00").do(sync_non_interactive)
#print(f"running every hour on the :{fetch_minute}\n") print(f"running every hour on the :{fetch_minute}\n")
while True: while True:
try: try:
schedule.run_pending() schedule.run_pending()

View File

@ -1,145 +1,287 @@
aiofiles==23.2.1 anaconda-client==1.6.5
aiohttp==3.9.3 anaconda-navigator==1.6.9
aiohttp-retry==2.8.3 anaconda-project==0.8.0
aiomysql==0.2.0 asn1crypto==0.22.0
aiosignal==1.3.1 astroid==1.5.3
annoy==1.17.3 astropy==2.0.2
async-timeout==4.0.3 atomicfile==1.0.1
asyncpg==0.29.0 attrs==18.2.0
attrs==23.2.0 Automat==0.7.0
Babel==2.14.0 Babel==2.5.0
bcrypt==4.1.2 backports.shutil-get-terminal-size==1.0.0
beautifulsoup4==4.12.3 bcrypt==3.1.7
bidict==0.22.1 beautifulsoup4==4.6.0
blinker==1.7.0 bitarray==0.8.1
certifi==2024.2.2 bkcharts==0.2
cffi==1.16.0 blaze==0.11.3
charset-normalizer==3.3.2 bleach==2.0.0
click==8.1.7 blinker==1.4
colorama==0.4.6 bokeh==0.12.10
contourpy==1.2.0 boto==2.48.0
courlan==1.0.0 boto3==1.10.20
cryptography==42.0.2 botocore==1.13.20
cycler==0.12.1 Bottleneck==1.2.1
dateparser==1.2.0 certifi==2019.9.11
deepdiff==6.7.1 cffi==1.10.0
docxcompose==1.4.0 chardet==3.0.4
docxtpl==0.16.7 clfparser==0.3
durable-rules==2.0.28 click==6.7
filelock==3.13.1 cloudpickle==0.4.0
Flask==3.0.1 clyent==1.2.2
Flask-SocketIO==5.3.6 coinmarketcap==5.0.3
Flask-SSE==1.0.0 colorama==0.3.9
fonttools==4.47.2 colorlog==4.0.2
frozenlist==1.4.1 conda==4.3.30
fsspec==2023.12.2 conda-build==3.0.27
funcy==2.0 conda-verify==2.0.0
gensim==4.3.2 constantly==15.1.0
greenlet==3.0.3 contextlib2==0.5.5
h11==0.14.0 cryptography==2.5
html2markdown==0.1.7 cssselect==1.0.3
htmldate==1.7.0 cycler==0.10.0
huggingface-hub==0.20.3 cymem==2.0.2
idna==3.6 Cython==0.28.5
instructure-dap-client==0.3.18 cytoolz==0.9.0.1
itsdangerous==2.1.2 dask==0.15.3
Jinja2==3.1.3 datashape==0.5.4
joblib==1.3.2 DAWG-Python==0.7.2
json_strong_typing==0.3.2 decorator==4.1.2
jsondiff==2.0.0 deepdiff==5.0.2
jsonschema==4.21.1 deeppavlov==0.1.6
jsonschema-specifications==2023.12.1 dill==0.2.9
jusText==3.0.0 distributed==1.19.1
kiwisolver==1.4.5 dnspython==2.0.0
langcodes==3.3.0 docopt==0.6.2
lark==1.1.9 docutils==0.14
linkify-it-py==2.0.2 docx==0.2.4
lxml==5.1.0 durable-rules==2.0.28
Markdown==3.5.2 email-validator==1.1.1
markdown-it-py==3.0.0 emoji==0.5.4
markdownify==0.11.6 en-core-web-lg==2.0.0
MarkupSafe==2.1.5 en-core-web-sm==2.0.0
matplotlib==3.8.2 entrypoints==0.2.3
mdit-py-plugins==0.4.0 et-xmlfile==1.0.1
mdurl==0.1.2 fastcache==1.0.2
minizinc==0.9.0 filelock==2.0.12
mpmath==1.3.0 flasgger==0.9.1
multidict==6.0.4 Flask==1.0.2
networkx==3.2.1 Flask-Caching==1.9.0
nltk==3.8.1 Flask-Cors==3.0.6
numpy==1.26.3 Flask-HTTPAuth==4.1.0
ordered-set==4.1.0 Flask-Login==0.5.0
orjson==3.9.12 Flask-Mail==0.9.1
packaging==23.2 Flask-SocketIO==4.3.1
paho-mqtt==1.6.1 Flask-SQLAlchemy==2.4.4
pampy==0.3.0 Flask-User==1.0.2.2
pandas==2.2.0 Flask-WTF==0.14.3
paramiko==3.4.0 funcy==1.14
path-dict==4.0.0 fuzzywuzzy==0.16.0
pathlib==1.0.1 gensim==3.8.3
pdfminer==20191125 gevent==1.2.2
pdfminer.six==20231228 gevent-websocket==0.10.1
pillow==10.2.0 glob2==0.5
pyarrow==15.0.0 glob3==0.0.1
pycparser==2.21 gmpy2==2.0.8
pycryptodome==3.20.0 graphviz==0.15
pygame==2.5.2 greenlet==0.4.12
Pygments==2.17.2 h5py==2.8.0
PyJWT==2.8.0 heapdict==1.0.0
PyMySQL==1.1.0 html2text==2018.1.9
PyNaCl==1.5.0 html5lib==0.999999999
pypandoc==1.12 hyperlink==18.0.0
pyparsing==3.1.1 idna==2.8
PyPDF2==3.0.1 imageio==2.2.0
pysftp==0.2.9 imagesize==0.7.1
python-dateutil==2.8.2 importlib-metadata==2.0.0
python-docx==1.1.0 incremental==17.5.0
python-engineio==4.8.2 inflection==0.3.1
python-socketio==5.11.0 ipdb==0.13.4
pytz==2024.1 ipykernel==4.6.1
pywin32==306 ipython==6.1.0
PyYAML==6.0.1 ipython-genutils==0.2.0
redis==5.0.1 ipywidgets==7.0.0
referencing==0.33.0 isort==4.2.15
regex==2023.12.25 itsdangerous==0.24
requests==2.31.0 jdcal==1.3
rich==13.7.0 jedi==0.10.2
rpds-py==0.17.1 Jinja2==2.10
safetensors==0.4.2 jmespath==0.9.4
schedule==1.2.1 jsondiff==1.2.0
scikit-learn==1.4.0 jsonschema==2.6.0
scipy==1.12.0 jupyter-client==5.1.0
sentence-transformers==2.3.1 jupyter-console==5.2.0
sentencepiece==0.1.99 jupyter-core==4.3.0
simple-websocket==1.0.0 jupyterlab==0.27.0
simpy==4.1.1 jupyterlab-launcher==0.4.0
six==1.16.0 Keras==2.2.0
smart-open==6.4.0 Keras-Applications==1.0.2
sortedcontainers==2.4.0 Keras-Preprocessing==1.0.1
soupsieve==2.5 lazy-object-proxy==1.3.1
SQLAlchemy==2.0.25 llvmlite==0.20.0
striprtf==0.0.26 locket==0.2.0
sympy==1.12 lxml==4.1.0
textdistance==4.6.1 Markdown==3.3.3
textual==0.48.2 MarkupSafe==1.0
threadpoolctl==3.2.0 matplotlib==2.1.0
tld==0.13 mccabe==0.6.1
tokenizers==0.15.1 mistune==0.7.4
tomd==0.1.3 mmh3==2.5.1
toolz==0.12.1 more-itertools==5.0.0
torch==2.2.0 mpmath==0.19
tqdm==4.66.1 msgpack==0.5.6
trafilatura==1.7.0 msgpack-numpy==0.4.3.2
transformers==4.37.2 msgpack-python==0.4.8
types-aiofiles==23.2.0.20240106 multipledispatch==0.4.9
typing_extensions==4.9.0 murmurhash==1.0.2
tzdata==2023.4 mysql-connector==2.1.6
tzlocal==5.2 mysql-connector-python==8.0.15
uc-micro-py==1.0.2 navigator-updater==0.1.0
urllib3==2.2.0 nbconvert==5.3.1
Werkzeug==3.0.1 nbformat==4.4.0
Whoosh==2.7.4 ndg-httpsclient==0.5.1
wsproto==1.2.0 networkx==2.0
xlwt==1.3.0 nltk==3.2.5
yarl==1.9.4 nose==1.3.7
yattag==1.15.2 notebook==5.0.0
nrepl-python-client==0.0.3
numba==0.35.0+10.g143f70e90
numexpr==2.6.2
numpy==1.14.5
numpydoc==0.7.0
odo==0.5.1
olefile==0.44
openpyxl==2.4.8
ordered-set==4.0.2
ortools==7.1.6720
overrides==1.9
packaging==16.8
paho-mqtt==1.5.0
pampy==0.3.0
pandas==0.23.1
pandas-datareader==0.8.1
pandocfilters==1.4.2
paramiko==2.7.1
parsel==1.5.1
partd==0.3.8
passlib==1.7.2
path.py==10.3.1
pathlib==1.0.1
pathlib2==2.3.0
patsy==0.4.1
peewee==3.9.5
pep8==1.7.0
pervane==0.0.66
pexpect==4.2.1
pickleshare==0.7.4
Pillow==4.2.1
pkginfo==1.4.1
plac==0.9.6
plotly==4.14.1
ply==3.10
preshed==2.0.1
prompt-toolkit==1.0.15
protobuf==3.7.1
psutil==5.4.0
ptyprocess==0.5.2
py==1.4.34
pyasn1==0.4.5
pyasn1-modules==0.2.4
pycodestyle==2.3.1
pycosat==0.6.2
pycparser==2.18
pycrypto==2.6.1
pycurl==7.43.0
pydbus==0.6.0
PyDispatcher==2.0.5
pyflakes==1.6.0
Pygments==2.2.0
PyHamcrest==1.9.0
pylint==1.7.4
pymorphy2==0.8
pymorphy2-dicts==2.4.393442.3710985
pymorphy2-dicts-ru==2.4.404381.4453942
PyNaCl==1.3.0
pync==2.0.3
pyodbc==4.0.17
pyOpenSSL==18.0.0
pypandoc==1.4
pyparsing==2.2.0
pysftp==0.2.9
PySocks==1.6.7
pyTelegramBotAPI==3.5.2
pytest==3.2.1
python-dateutil==2.6.1
python-engineio==3.13.2
python-socketio==4.6.0
pytz==2017.2
PyWavelets==0.5.2
PyYAML==3.12
pyzmq==16.0.2
QtAwesome==0.4.4
qtconsole==4.3.1
QtPy==1.3.1
Quandl==3.4.8
queuelib==1.5.0
rake-nltk==1.0.4
readline==6.2.4.1
regex==2018.1.10
requests==2.22.0
requests-cache==0.5.2
retrying==1.3.3
rope==0.10.5
ruamel-yaml==0.11.14
rusenttokenize==0.0.4
s3transfer==0.2.1
schedule==0.6.0
scikit-image==0.13.0
scikit-learn==0.19.1
scipy==1.1.0
Scrapy==1.6.0
seaborn==0.8
service-identity==18.1.0
simplegeneric==0.8.1
singledispatch==3.4.0.3
six==1.12.0
smart-open==3.0.0
snowballstemmer==1.2.1
sortedcollections==0.5.3
sortedcontainers==1.5.7
spacy==2.0.18
Sphinx==1.6.3
sphinxcontrib-websupport==1.0.1
spyder==3.2.4
SQLAlchemy==1.1.13
statsmodels==0.8.0
striprtf==0.0.11
summa==1.2.0
sympy==1.1.1
tables==3.4.2
tblib==1.3.2
terminado==0.6
testpath==0.3.1
textdistance==4.2.0
thinc==6.12.1
toolz==0.8.2
tornado==4.5.2
tqdm==4.23.4
traitlets==4.3.2
Twisted==18.9.0
typing==3.6.2
ujson==1.35
unicodecsv==0.14.1
urllib3==1.25.7
w3lib==1.20.0
wcwidth==0.1.7
webencodings==0.5.1
Werkzeug==0.14.1
widgetsnbextension==3.0.2
wrapt==1.10.11
WTForms==2.3.1
xlrd==1.1.0
XlsxWriter==1.0.2
xlwt==1.3.0
yattag==1.11.1
youtube-dl==2019.11.5
zict==0.1.3
zipp==3.4.0
zope.interface==4.6.0

View File

@ -1,287 +0,0 @@
anaconda-client==1.6.5
anaconda-navigator==1.6.9
anaconda-project==0.8.0
asn1crypto==0.22.0
astroid==1.5.3
astropy==2.0.2
atomicfile==1.0.1
attrs==18.2.0
Automat==0.7.0
Babel==2.5.0
backports.shutil-get-terminal-size==1.0.0
bcrypt==3.1.7
beautifulsoup4==4.6.0
bitarray==0.8.1
bkcharts==0.2
blaze==0.11.3
bleach==2.0.0
blinker==1.4
bokeh==0.12.10
boto==2.48.0
boto3==1.10.20
botocore==1.13.20
Bottleneck==1.2.1
certifi==2019.9.11
cffi==1.10.0
chardet==3.0.4
clfparser==0.3
click==6.7
cloudpickle==0.4.0
clyent==1.2.2
coinmarketcap==5.0.3
colorama==0.3.9
colorlog==4.0.2
conda==4.3.30
conda-build==3.0.27
conda-verify==2.0.0
constantly==15.1.0
contextlib2==0.5.5
cryptography==2.5
cssselect==1.0.3
cycler==0.10.0
cymem==2.0.2
Cython==0.28.5
cytoolz==0.9.0.1
dask==0.15.3
datashape==0.5.4
DAWG-Python==0.7.2
decorator==4.1.2
deepdiff==5.0.2
deeppavlov==0.1.6
dill==0.2.9
distributed==1.19.1
dnspython==2.0.0
docopt==0.6.2
docutils==0.14
docx==0.2.4
durable-rules==2.0.28
email-validator==1.1.1
emoji==0.5.4
en-core-web-lg==2.0.0
en-core-web-sm==2.0.0
entrypoints==0.2.3
et-xmlfile==1.0.1
fastcache==1.0.2
filelock==2.0.12
flasgger==0.9.1
Flask==1.0.2
Flask-Caching==1.9.0
Flask-Cors==3.0.6
Flask-HTTPAuth==4.1.0
Flask-Login==0.5.0
Flask-Mail==0.9.1
Flask-SocketIO==4.3.1
Flask-SQLAlchemy==2.4.4
Flask-User==1.0.2.2
Flask-WTF==0.14.3
funcy==1.14
fuzzywuzzy==0.16.0
gensim==3.8.3
gevent==1.2.2
gevent-websocket==0.10.1
glob2==0.5
glob3==0.0.1
gmpy2==2.0.8
graphviz==0.15
greenlet==0.4.12
h5py==2.8.0
heapdict==1.0.0
html2text==2018.1.9
html5lib==0.999999999
hyperlink==18.0.0
idna==2.8
imageio==2.2.0
imagesize==0.7.1
importlib-metadata==2.0.0
incremental==17.5.0
inflection==0.3.1
ipdb==0.13.4
ipykernel==4.6.1
ipython==6.1.0
ipython-genutils==0.2.0
ipywidgets==7.0.0
isort==4.2.15
itsdangerous==0.24
jdcal==1.3
jedi==0.10.2
Jinja2==2.10
jmespath==0.9.4
jsondiff==1.2.0
jsonschema==2.6.0
jupyter-client==5.1.0
jupyter-console==5.2.0
jupyter-core==4.3.0
jupyterlab==0.27.0
jupyterlab-launcher==0.4.0
Keras==2.2.0
Keras-Applications==1.0.2
Keras-Preprocessing==1.0.1
lazy-object-proxy==1.3.1
llvmlite==0.20.0
locket==0.2.0
lxml==4.1.0
Markdown==3.3.3
MarkupSafe==1.0
matplotlib==2.1.0
mccabe==0.6.1
mistune==0.7.4
mmh3==2.5.1
more-itertools==5.0.0
mpmath==0.19
msgpack==0.5.6
msgpack-numpy==0.4.3.2
msgpack-python==0.4.8
multipledispatch==0.4.9
murmurhash==1.0.2
mysql-connector==2.1.6
mysql-connector-python==8.0.15
navigator-updater==0.1.0
nbconvert==5.3.1
nbformat==4.4.0
ndg-httpsclient==0.5.1
networkx==2.0
nltk==3.2.5
nose==1.3.7
notebook==5.0.0
nrepl-python-client==0.0.3
numba==0.35.0+10.g143f70e90
numexpr==2.6.2
numpy==1.14.5
numpydoc==0.7.0
odo==0.5.1
olefile==0.44
openpyxl==2.4.8
ordered-set==4.0.2
ortools==7.1.6720
overrides==1.9
packaging==16.8
paho-mqtt==1.5.0
pampy==0.3.0
pandas==0.23.1
pandas-datareader==0.8.1
pandocfilters==1.4.2
paramiko==2.7.1
parsel==1.5.1
partd==0.3.8
passlib==1.7.2
path.py==10.3.1
pathlib==1.0.1
pathlib2==2.3.0
patsy==0.4.1
peewee==3.9.5
pep8==1.7.0
pervane==0.0.66
pexpect==4.2.1
pickleshare==0.7.4
Pillow==4.2.1
pkginfo==1.4.1
plac==0.9.6
plotly==4.14.1
ply==3.10
preshed==2.0.1
prompt-toolkit==1.0.15
protobuf==3.7.1
psutil==5.4.0
ptyprocess==0.5.2
py==1.4.34
pyasn1==0.4.5
pyasn1-modules==0.2.4
pycodestyle==2.3.1
pycosat==0.6.2
pycparser==2.18
pycrypto==2.6.1
pycurl==7.43.0
pydbus==0.6.0
PyDispatcher==2.0.5
pyflakes==1.6.0
Pygments==2.2.0
PyHamcrest==1.9.0
pylint==1.7.4
pymorphy2==0.8
pymorphy2-dicts==2.4.393442.3710985
pymorphy2-dicts-ru==2.4.404381.4453942
PyNaCl==1.3.0
pync==2.0.3
pyodbc==4.0.17
pyOpenSSL==18.0.0
pypandoc==1.4
pyparsing==2.2.0
pysftp==0.2.9
PySocks==1.6.7
pyTelegramBotAPI==3.5.2
pytest==3.2.1
python-dateutil==2.6.1
python-engineio==3.13.2
python-socketio==4.6.0
pytz==2017.2
PyWavelets==0.5.2
PyYAML==3.12
pyzmq==16.0.2
QtAwesome==0.4.4
qtconsole==4.3.1
QtPy==1.3.1
Quandl==3.4.8
queuelib==1.5.0
rake-nltk==1.0.4
readline==6.2.4.1
regex==2018.1.10
requests==2.22.0
requests-cache==0.5.2
retrying==1.3.3
rope==0.10.5
ruamel-yaml==0.11.14
rusenttokenize==0.0.4
s3transfer==0.2.1
schedule==0.6.0
scikit-image==0.13.0
scikit-learn==0.19.1
scipy==1.1.0
Scrapy==1.6.0
seaborn==0.8
service-identity==18.1.0
simplegeneric==0.8.1
singledispatch==3.4.0.3
six==1.12.0
smart-open==3.0.0
snowballstemmer==1.2.1
sortedcollections==0.5.3
sortedcontainers==1.5.7
spacy==2.0.18
Sphinx==1.6.3
sphinxcontrib-websupport==1.0.1
spyder==3.2.4
SQLAlchemy==1.1.13
statsmodels==0.8.0
striprtf==0.0.11
summa==1.2.0
sympy==1.1.1
tables==3.4.2
tblib==1.3.2
terminado==0.6
testpath==0.3.1
textdistance==4.2.0
thinc==6.12.1
toolz==0.8.2
tornado==4.5.2
tqdm==4.23.4
traitlets==4.3.2
Twisted==18.9.0
typing==3.6.2
ujson==1.35
unicodecsv==0.14.1
urllib3==1.25.7
w3lib==1.20.0
wcwidth==0.1.7
webencodings==0.5.1
Werkzeug==0.14.1
widgetsnbextension==3.0.2
wrapt==1.10.11
WTForms==2.3.1
xlrd==1.1.0
XlsxWriter==1.0.2
xlwt==1.3.0
yattag==1.11.1
youtube-dl==2019.11.5
zict==0.1.3
zipp==3.4.0
zope.interface==4.6.0

View File

@ -7,7 +7,7 @@ from flask import send_from_directory
import hashlib, funcy, platform, requests import hashlib, funcy, platform, requests
from datetime import datetime from datetime import datetime
#from orgpython import to_html from orgpython import to_html
from localcache import sqlite_file, db # personnel_meta # personnel_fetch from localcache import sqlite_file, db # personnel_meta # personnel_fetch
from localcache import user_enrolled_in from localcache import user_enrolled_in
@ -253,10 +253,10 @@ def writing(fname):
if ext == "md": if ext == "md":
src = inp.read() src = inp.read()
return style + markdown.markdown(src) + in_form(editor(src),fname) return style + markdown.markdown(src) + in_form(editor(src),fname)
#if ext == "org": if ext == "org":
# src = inp.read() src = inp.read()
# return (src, toc=True, offset=0, highlight=True) return to_html(src, toc=True, offset=0, highlight=True)
if ext == "rtto_htmlf": if ext == "rtf":
text = "<br />\n".join( rtf_to_text(inp.read()).split('\n') ) text = "<br />\n".join( rtf_to_text(inp.read()).split('\n') )
return style + text return style + text
if ext == "docx": if ext == "docx":

View File

@ -15,7 +15,7 @@
import pysftp, os, datetime, requests, re, json, sqlite3, codecs, csv, sys import pysftp, os, datetime, requests, re, json, sqlite3, codecs, csv, sys
import funcy, os.path, shutil, urllib import funcy, os.path, shutil, urllib
from datetime import datetime from datetime import datetime, strptime
from collections import defaultdict from collections import defaultdict
#from datetime import strptime #from datetime import strptime
from time import mktime from time import mktime
@ -521,8 +521,8 @@ def course_2060_dates(crn=""):
print ( 'I couldn\'t find that CRN in ' + schedfile ) print ( 'I couldn\'t find that CRN in ' + schedfile )
else: else:
a = s['date'].split(' - ') a = s['date'].split(' - ')
beginT = datetime.strptime(a[0],"%b %d, %Y") beginT = strptime(a[0],"%b %d, %Y")
endT = datetime.strptime(a[1],"%b %d, %Y") endT = strptime(a[1],"%b %d, %Y")
# Begin and end dates - direct from schedule # Begin and end dates - direct from schedule
# Calculate 20% / 60% dates. # Calculate 20% / 60% dates.
@ -587,7 +587,7 @@ def hours_calc_pulldata(course_id=''):
if results: if results:
for hit in results: for hit in results:
hitT = datetime.strptime(str(hit['created_at']),"%Y-%m-%dT%H:%M:%SZ") hitT = strptime(str(hit['created_at']),"%Y-%m-%dT%H:%M:%SZ")
hittime = datetime.datetime.fromtimestamp( mktime(hitT) ) hittime = datetime.datetime.fromtimestamp( mktime(hitT) )
if hittime > endDT: bag[4] += 1 if hittime > endDT: bag[4] += 1

119
ui.py
View File

@ -1,119 +0,0 @@
from textual.app import App, ComposeResult
from textual.widgets import Placeholder, Static, Button, Digits
from textual.containers import Container, VerticalScroll
from textual import events, on
from textual.reactive import Reactive, var
from textual.css.query import NoMatches
from itertools import cycle
hellos = cycle(
[
"Hola",
"Bonjour",
"Guten tag",
"Salve",
"Nǐn hǎo",
"Olá",
"Asalaam alaikum",
"Konnichiwa",
"Anyoung haseyo",
"Zdravstvuyte",
"Hello",
]
)
class Hello(Static):
# Display a greeting.
DEFAULT_CSS = """
Hello {
width: 40;
height: 9;
padding: 1 2;
background: $panel;
border: $secondary tall;
content-align: center middle;
}
"""
def on_mount(self) -> None:
self.next_word()
def on_click(self) -> None:
self.next_word()
def next_word(self) -> None:
# Get a new hello and update the content area.
hello = next(hellos)
self.update(f"{hello}, [b]World[/b]!")
class MyApp(App):
value = var("")
"""
async def startup(self):
await self.bind("q", "action_quit")
await self.push_view(self.control)
# Left area with numbers
numbers = "\n".join(str(i) for i in range(1, 501))
self.view.grid.set_focus("content")
h = Hello()
self.view.add_right(
#VerticalScroll(StrContent(numbers), name="Numbers"),
h,
width=50,
padding=(0,1),
)
# Right area with lorem ipsum placeholder
lorem_ipsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
self.view.add_right(
# VerticalScroll(StrContent(lorem_ipsum), name="Lorem"),
Static(lorem_ipsum, name="Lorem"),
width=50,
padding=(0,1),
)
# Command input at the bottom
self.view.add_bottom(Static("Enter command: "), height=3)
"""
def action_quit(self):
self.exit()
"""
class CanvasApp(App):
# A Textual app to manage canvas.
BINDINGS = [("d", "toggle_dark", "Toggle dark mode")]
def compose(self) -> ComposeResult:
# Create child widgets for the app.
yield Header()
yield Footer()
def quit(self):
self.exit()
def action_toggle_dark(self) -> None:
# An action to toggle dark mode.
self.dark = not self.dark
"""
def text_app():
app = MyApp()
app.run()
text_app()

View File

@ -1789,8 +1789,8 @@ def track_user(id=0,qid=0):
url_addition = "" url_addition = ""
if 1: # hard code dates if 1: # hard code dates
start_date = "2023-08-01T00:00:00-07:00" start_date = "2023-01-01T00:00:00-07:00"
end_date = "2024-01-01T00:00:00-07:00" end_date = "2023-08-01T00:00:00-07:00"
url_addition = f"?start_time={start_date}&end_time={end_date}" url_addition = f"?start_time={start_date}&end_time={end_date}"
elif 'last_days_log' in info: elif 'last_days_log' in info:
print("There's existing log data for %s (%s)" % (info['name'] , info['sis_user_id'])) print("There's existing log data for %s (%s)" % (info['name'] , info['sis_user_id']))