diff --git a/src/coursebox.egg-info/SOURCES.txt b/src/coursebox.egg-info/SOURCES.txt index 811f494d4a0b56ff40080d2f33ee54719a2b460e..06d663209fbb7d8b29ba3984e16f5e9d97d41c4c 100644 --- a/src/coursebox.egg-info/SOURCES.txt +++ b/src/coursebox.egg-info/SOURCES.txt @@ -15,12 +15,14 @@ src/coursebox/admin/gitlab.py src/coursebox/book/__init__.py src/coursebox/book/exam_includer.py src/coursebox/core/__init__.py +src/coursebox/core/course.py src/coursebox/core/info.py src/coursebox/core/info_paths.py src/coursebox/core/projects.py src/coursebox/core/projects_info.py src/coursebox/core/projects_plagiarism.py src/coursebox/material/__init__.py +src/coursebox/material/documentation.py src/coursebox/material/homepage_lectures_exercises.py src/coursebox/material/lecture_questions.py src/coursebox/material/snipper.py diff --git a/src/coursebox/core/course.py b/src/coursebox/core/course.py new file mode 100644 index 0000000000000000000000000000000000000000..d8f8cb07d657b6a391450fbd0c03f0bcbfd1c959 --- /dev/null +++ b/src/coursebox/core/course.py @@ -0,0 +1,9 @@ + + +class Course: + # Basic class that represents a course. Use this class to add course-specific functionality. + + + + + pass \ No newline at end of file diff --git a/src/coursebox/core/info.py b/src/coursebox/core/info.py index ae0efee3cc790faa5d14a91d0a3e70f40aef4ed7..cfbf74dcdcccd51d89ffb8930d860b4292406574 100644 --- a/src/coursebox/core/info.py +++ b/src/coursebox/core/info.py @@ -430,7 +430,7 @@ def class_information(verbose=False, d['reports'][r['id']] = r r['handin'] = get_lecture_date(r['handin'], delta_days=int(d['handin_day_delta'])) r['handout'] = get_lecture_date(r['handout'], delta_days=int(d.get('handout_day_delta', 0))) - r['exercises'] = [e.strip() for e in r['exercises'].split(",") if len(e.strip()) > 0] + r['exercises'] = [] if r['exercises'] is None else [e.strip() for e in r['exercises'].split(",") if len(e.strip()) > 0] ice = xlsx_to_dicts(paths['information.xlsx'], sheet='ce', as_dict_list=True) diff --git a/src/coursebox/core/info_paths.py b/src/coursebox/core/info_paths.py index 2a19f50b1f178cc34b0bf3b8ef771704516c1392..c3e63f4a4272dda86bb839d6bdc65979ce0644fd 100644 --- a/src/coursebox/core/info_paths.py +++ b/src/coursebox/core/info_paths.py @@ -48,6 +48,7 @@ def get_paths(): '02450private': root_02450private, '02450public': root_02450public, '02450instructors': root_02450instructors, + 'instructors': root_02450instructors, '02450students': root_02450students, 'shared': root_02450public+"/shared", 'exams': root_02450private+"/Exam", diff --git a/src/coursebox/material/_extra_info.pkl b/src/coursebox/material/_extra_info.pkl new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/coursebox/material/documentation.py b/src/coursebox/material/documentation.py index b95974583d4327531aa3ad166ce92786c3520de2..e75c6912044a852820098777682047c95c5976a8 100644 --- a/src/coursebox/material/documentation.py +++ b/src/coursebox/material/documentation.py @@ -9,6 +9,18 @@ import pickle import datetime import subprocess from unitgrade_private.run import run +from coursebox.material.homepage_lectures_exercises import fix_shared +from coursebox.core.info_paths import get_paths + +def setup_notes(paths=None, dosvg=True): + from coursebox.material.homepage_lectures_exercises import fix_shared + if paths is None: + paths = get_paths() + # setup_student_files(run_files=True, cut_files=True, censor_files=False, setup_lectures=True, week=[], + # projects=[], verbose=False, convert_svg=False) + fix_shared(paths, output_dir=paths['02450public'] + "/Notes/Latex", dosvg=dosvg) + + def build_sphinx_documentation(cut_files=False, open_browser=True, build_and_copy_censored=True, CE=False, languages=('en', 'da'), show_all_solutions=False, tolerate_problems=False, # If False, WARNINGS and ERRORS in the spinx build process will lead to a compile error. Set to True during local development. @@ -17,9 +29,6 @@ def build_sphinx_documentation(cut_files=False, open_browser=True, build_and_cop CE_public=False, ): - # print("This functionality has been moved to coursebox.") - - from coursebox.core.info_paths import get_paths paths = get_paths() if CE: @@ -40,9 +49,11 @@ def build_sphinx_documentation(cut_files=False, open_browser=True, build_and_cop # This will build the student documentation (temporary). # The functionality here should match the gitlab ci file closely. - from cp_box.material.student_files import fix_all_shared_files - from cp_box.material.student_files import setup_student_files + # from irlc_box.material.student_files import fix_all_shared_files + # from cp_box.material.student_files import setup_student_files + # from coursebox.material.homepage_lectures_exercises import set + from coursebox.student_files.student_files import setup_student_files if os.path.isfile(d_ := f"{paths['book']}/{paths['course_number']}_Notes.pdf"): @@ -99,21 +110,40 @@ def build_sphinx_documentation(cut_files=False, open_browser=True, build_and_cop """ TH: What happens here is that we cache the report information so we can later load it (above) when rst source is build. The reason we split the code like this is because we don't have access to the report classes during the Sphinx build process, and that means some of the variables are not easily set. This is a bit of a dirty fix, but it works. """ - with open(os.path.dirname(os.path.abspath(__file__)) + "/_extra_info.pkl", 'wb') as f: + with open(extra_info := source + "/_extra_info.pkl", 'wb') as f: + print("Writing extra info to", extra_info) pickle.dump(x, f) for f in glob.glob(f"{paths['02450public']}/src/docs/templates/*.rst"): if f.endswith("blurb.rst") or f.endswith("base.rst"): continue # We dealt with these; nb. very hacky stuff. - PROJECTS = [int(os.path.basename(f)[len("project"):]) for f in glob.glob(f"{paths['02450public']}/src/cp/project*")] - WEEKS = [int(os.path.basename(f)[len("ex"):]) for f in glob.glob(f"{paths['02450public']}/src/cp/ex*") if not os.path.basename(f) == 'exam'] + # PROJECTS = [int(os.path.basename(f)[len("project"):]) for f in glob.glob(f"{paths['02450public']}/src/cp/project*")] + # WEEKS = [int(os.path.basename(f)[len("ex"):]) for f in glob.glob(f"{paths['02450public']}/src/cp/ex*") if not os.path.basename(f) == 'exam'] + + from coursebox.core.info_paths import core_conf + + PROJECTS = list(core_conf['projects_all'].keys()) + WEEKS = list(core_conf['weeks_all'].keys()) + pdfs = [] for g in glob.glob(paths['pdf_out'] +"/handout/*.pdf"): dst = paths['02450public'] + "/src/docs/assets/"+os.path.basename(g)[:-4] + "-handout.pdf" + if not os.path.isdir(os.path.dirname(dst)): + os.makedirs(os.path.dirname(dst)) shutil.copy(g, dst) pdfs.append(dst) + + for g in glob.glob(paths['pdf_out'] + "/*.pdf"): + if "_devel" in g: + continue + dst = paths['02450public'] + "/src/docs/assets/" + os.path.basename(g) + if not os.path.isdir(os.path.dirname(dst)): + os.makedirs(os.path.dirname(dst)) + shutil.copy(g, dst) + pdfs.append(dst) + for g in [paths['pdf_out'] + "/" + paths['course_number'] + "_Notes.pdf"]: dst = paths['02450public'] + "/src/docs/assets/" + os.path.basename(g) shutil.copy(g, dst) @@ -139,7 +169,6 @@ def build_sphinx_documentation(cut_files=False, open_browser=True, build_and_cop BAD_MODULES_DIR = False deploy_students_complete() # I guess this will build public and private. students_complete = paths['02450students'] + "_complete" - # PUBLIC_BUILD_DEST fns = [] # Blow public modules. This is because renamed files will otherwise stay around and when you later build the version @@ -156,11 +185,10 @@ def build_sphinx_documentation(cut_files=False, open_browser=True, build_and_cop TAG_EXTRA = '-t da' if not sphinx_cache: TAG_EXTRA += ' -a' - # " sphinx-build -b html source build -D language='da' -t da " + # " sphinx-build -b html source build -D language='da' -t da " _FINAL_BUILD_DEST = f"{PUBLIC_BUILD_DEST}{'/da' if l=='da' else ''}" - SET_PATH = f"""PYTHONPATH="{paths['02450students'] + '_complete'}" """ if os.name == 'nt': SET_PATH = "set "+SET_PATH +" && " @@ -193,7 +221,11 @@ def build_sphinx_documentation(cut_files=False, open_browser=True, build_and_cop my_env['PYTHONPATH'] = (paths['02450students'] + '_complete').replace("\\", "/") process = run(cmd, print_output=True, log_output=True, check=False, env=my_env) - + """r + cd /home/tuhe/Documents/02465students_complete/ && sphinx-build -b html docs/source ./public + cd "/home/tuhe/Documents/02465students_complete/docs" && sphinx-build -b html source "../../02465public/public" -a + + """ if os.name == 'nt': # time.sleep(10) process = run(cmd, print_output=True, log_output=True, check=False, env=my_env) @@ -231,26 +263,21 @@ Below is a summary of the problems we found: """) shutil.copy(f"{paths['shared']}/figures/{im}", f"{_FINAL_BUILD_DEST}/_images/{im}") - - if build_and_copy_censored: verbose = False setup_student_files(run_files=False, cut_files=False, censor_files=True, setup_lectures=cut_files, week=WEEKS, projects=PROJECTS, fix_shared_files=True, verbose=verbose, include_docs=True) - cmd_with_pythonpath = f"cd {paths['02450students']} && PYTHONPATH={paths['02450students']} sphinx-build -b html docs/source ./public {SPHINX_TAG}" - cmd = f"cd {paths['02450students']} && sphinx-build -b html docs/source ./public {SPHINX_TAG}" + cmd_with_pythonpath = f"cd {paths['02450students']}/docs && PYTHONPATH={paths['02450students']} sphinx-build -b html source ../public {SPHINX_TAG} -a" + cmd = f"cd {paths['02450students']}/docs && sphinx-build -b html source ../public {SPHINX_TAG} -a" # try: - # print("Running>", cmd) my_env = os.environ.copy() my_env['PYTHONPATH'] = paths['02450students'].replace("\\","/") print("> Building documentation based on .py-files that do not contain solutions based on command:\n", cmd_with_pythonpath) out = subprocess.run(cmd, shell=True, check=True, env=my_env, capture_output=False) - # glob.glob(f"{PUBLIC_BUILD_DEST}/_modules/**/*.html") - known_modules = set([os.path.relpath(f, PUBLIC_BUILD_DEST) for f in glob.glob(f"{PUBLIC_BUILD_DEST}/_modules/**/*.html", recursive=True) ] ) build_modules = set([os.path.relpath(f, f"{paths['02450students']}/public") for f in glob.glob(f"{paths['02450students']}/public/_modules/**/*.html", recursive=True) ] ) @@ -351,14 +378,19 @@ def _get_source(paths): def deploy_students_complete(verbose=False): from coursebox.core.info_paths import get_paths paths = get_paths() - from cp_box.material.student_files import setup_student_files + from coursebox.core.info_paths import core_conf + PROJECTS = list(core_conf['projects_all'].keys()) + WEEKS = list(core_conf['weeks_all'].keys()) + + # from cp_box.material.student_files import setup_student_files + from coursebox.student_files.student_files import setup_student_files studens_complete = paths['02450students'] + '_complete' if os.path.isdir(studens_complete): shutil.rmtree(paths['02450students'] + '_complete') - PROJECTS = [int(os.path.basename(f)[len("project"):]) for f in - glob.glob(f"{paths['02450public']}/src/cp/project*")] - WEEKS = [int(os.path.basename(f)[len("ex"):]) for f in glob.glob(f"{paths['02450public']}/src/cp/ex*") if - not os.path.basename(f) == 'exam'] + # PROJECTS = [int(os.path.basename(f)[len("project"):]) for f in + # glob.glob(f"{paths['02450public']}/src/cp/project*")] + # WEEKS = [int(os.path.basename(f)[len("ex"):]) for f in glob.glob(f"{paths['02450public']}/src/cp/ex*") if + # not os.path.basename(f) == 'exam'] # shutil.rmtree(paths['02450students'] + '_complete') cut_files=False # verbose=False @@ -366,3 +398,35 @@ def deploy_students_complete(verbose=False): setup_student_files(run_files=False, cut_files=cut_files, censor_files=False, setup_lectures=cut_files, week=WEEKS, projects=PROJECTS, fix_shared_files=cut_files, verbose=verbose, include_docs=True) + + +def fix_all_shared_files(paths=None, dosvg=False,compile_templates=True, verbose=False): + # Tue: Do these imports here to avoid circular imports. + from coursebox.core.info_paths import get_paths + # from irlc_box.irlc_main import setup_notes + # Make the chamor snapshot list. + setup_notes(dosvg=dosvg) + paths = get_paths() + # from coursebox.do + + for w in range(14): + out = paths['exercises'] + f"/ExercisesPython/Exercise{w}/latex" + if os.path.isdir(out): + fix_shared(paths, out, pdf2png=False,dosvg=dosvg, compile_templates=compile_templates, verbose=verbose) # , dosvg=dosvg <--- please update coursebox (script broken as is) + + out = paths['lectures'] + f"/Lecture_{w}/Latex" + if os.path.isdir(out): + fix_shared(paths, out, pdf2png=False, compile_templates=compile_templates, verbose=verbose) + + out = paths['exercises'] + f"/LatexCompilationDir/Latex" + if os.path.isdir(out): + fix_shared(paths, out, pdf2png=False, dosvg=dosvg, compile_templates=compile_templates, verbose=verbose) # , dosvg=dosvg <--- please update coursebox (script broken as is) + + # New 2023: Sync with documentation path. + out = paths['02450public'] + f"/src/docs/shared" + if os.path.isdir(out): + # I feel we need to convert the SVG images? + fix_shared(paths, out, pdf2png=dosvg, dosvg=dosvg, compile_templates=compile_templates, verbose=verbose) # , dosvg=dosvg <--- please update coursebox (script broken as is) + + + diff --git a/src/coursebox/material/homepage_lectures_exercises.py b/src/coursebox/material/homepage_lectures_exercises.py index 727363b32117a66308087745b71c6c7e5a3a4049..1794b51cd35f940ef1d02b634a9bc0e1f295b057 100644 --- a/src/coursebox/material/homepage_lectures_exercises.py +++ b/src/coursebox/material/homepage_lectures_exercises.py @@ -471,11 +471,11 @@ def make_exercises_projects_tutors(week=None, only_exercises=False, make_exercis info['lecture_handin'] = info['lectures'][handin_week-1] if info['CE']: - proj_base = paths['instructor'] + "/ExercisesShared/%sprojectCE_Base.tex"%(course_number, ) - proj_tex_out = paths['instructor'] + "/Project/latex%i/%sprojectCE.tex" % (1,course_number,) + proj_base = paths['02450instructors'] + "/ExercisesShared/%sprojectCE_Base.tex"%(course_number, ) + proj_tex_out = paths['02450instructors'] + "/Project/latex%i/%sprojectCE.tex" % (1,course_number,) else: - proj_base = paths['instructor'] + "/ExercisesShared/%sproject%i_Base.tex" % (course_number,proj+1,) - proj_tex_out = paths['instructor'] + "/Project/latex%i/%sproject%i.tex" % (proj+1, course_number, proj+1) + proj_base = paths['02450instructors'] + "/ExercisesShared/%sproject%i_Base.tex" % (course_number,proj+1,) + proj_tex_out = paths['02450instructors'] + "/Project/latex%i/%sproject%i.tex" % (proj+1, course_number, proj+1) info['week'] = -1 if not os.path.exists(proj_base): @@ -533,12 +533,12 @@ def make_exercises_projects_tutors(week=None, only_exercises=False, make_exercis } # get lang dir - if not os.path.exists("%s/Exercises%s"%(paths['instructor'], lang)): + if not os.path.exists("%s/Exercises%s"%(paths['instructors'], lang)): continue info.update(tv) - ex_base = "%s/ExercisesShared/%sex%i_Base.tex"%(paths['instructor'], course_number, w) - ex_tex_out = "%s/Exercises%s/Exercise%i/latex/%sex%i_%s.tex" % ( paths['instructor'], lang, w, course_number, w, lang) + ex_base = "%s/ExercisesShared/%sex%i_Base.tex"%(paths['instructors'], course_number, w) + ex_tex_out = "%s/Exercises%s/Exercise%i/latex/%sex%i_%s.tex" % ( paths['instructors'], lang, w, course_number, w, lang) # fbody = os.path.dirname(ex_tex_out) +f"/ex{w}_body.tex" if os.path.exists(ex_base): diff --git a/src/coursebox/student_files/student_files.py b/src/coursebox/student_files/student_files.py index 329fa3ea08283ce6f9b86369fd80f43659da3c4f..c5ba8d6ea77d1151a0133f96cad8efaa3311327d 100644 --- a/src/coursebox/student_files/student_files.py +++ b/src/coursebox/student_files/student_files.py @@ -6,6 +6,8 @@ from coursebox.material.homepage_lectures_exercises import fix_shared from snipper.snipper_main import censor_file from pathlib import Path import fnmatch +import glob +from coursebox.material.documentation import fix_all_shared_files def setup_student_files(run_files=True, cut_files=True, @@ -19,15 +21,22 @@ def setup_student_files(run_files=True, verbose=True, students_irlc_tools=None, # Destination dir for the irlc folder (the one we really want to deploy). midterms=None, # Can be a list: [0, 1] - include_docs=False, # Include the documentation directory, i.e. 02465public/pythontools/docs. + include_docs=False, # Include the documentation directory, i.e. 02465public/src/docs. convert_svg=True, # Whether to convert SVG file when deploying. Leave to true, unless we are doing CI/CD in which case inkscape may not be installed. package="cp", - fix_shared_files_func=None, + # fix_shared_files_func=None, ): if midterms is None: midterms = [] from coursebox.core import info_paths + # from coursebox.core.info import class_information + # info = class_information() + from coursebox.core.info import core_conf + PACKAGE = list(core_conf['projects_all'].values()).pop()['module_public'].split(".")[0] + + + week = [week] if isinstance(week, int) else week if verbose: @@ -39,13 +48,14 @@ def setup_student_files(run_files=True, if projects is None: projects = [] - public_irlc_tools = paths['02450public'] + "/src/cp" + public_irlc_tools = f"{paths['02450public']}/src/{PACKAGE}" + if students_irlc_tools is None: if censor_files: - students_irlc_tools = paths['02450students'] + "/cp" + students_irlc_tools = f"{paths['02450students']}/{PACKAGE}" else: - students_irlc_tools = paths['02450students'] + "_complete/cp" + students_irlc_tools = f"{paths['02450students']}_complete/{PACKAGE}" if not os.path.isdir(students_irlc_tools): os.makedirs(students_irlc_tools) @@ -75,7 +85,7 @@ def setup_student_files(run_files=True, if extra_dirs is None: - extra_dirs = ['utils', 'tests', 'exam/exam2023spring'] # 'assignments', + extra_dirs = ['utils', 'tests', 'exam/exam2023spring', 'pacman', 'gridworld', 'car'] # 'assignments', for m in midterms: if m == 0: extra_dirs += ['exam/midterm2023a'] @@ -158,7 +168,7 @@ def setup_student_files(run_files=True, if fix_shared_files: if verbose: print("> Homework fixed, copying shared files...") - fix_shared_files_func(paths=paths, compile_templates=False, verbose=verbose, dosvg=convert_svg) + fix_all_shared_files(paths=paths, compile_templates=False, verbose=verbose, dosvg=convert_svg) if verbose: print("> Removing excluded files from students gitlab directory...") @@ -173,7 +183,11 @@ def setup_student_files(run_files=True, else: os.remove(l) - shutil.copy(public_irlc_tools +"/../requirements.txt", students_irlc_tools +"/../requirements.txt") + for f in glob.glob(public_irlc_tools +"/../requirements*.txt"): + if "full" in os.path.basename(f): + continue + os.path.basename(f) # Copy requirements and all simiarly named files. + shutil.copy(f, students_irlc_tools +"/../"+os.path.basename(f)) # shutil.copy(public_irlc_tools +"/../requirements_conda.txt", students_irlc_tools +"/../requirements_conda.txt") # Don't think we need this anymore. Why copy docs if they cannot be compiled anyway? Perhaps for the complete docs? if include_docs: diff --git a/sym b/sym new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ym b/ym new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391