|
34 | 34 | from bookserver.db import init_models, term_models |
35 | 35 | from bookserver.config import settings |
36 | 36 | from runestone.pretext.chapter_pop import manifest_data_to_db |
| 37 | +from runestone.server.utils import _build_runestone_book, _build_ptx_book |
37 | 38 |
|
38 | 39 |
|
39 | 40 | class Config(object): |
@@ -400,200 +401,6 @@ def build(config, clone, ptx, gen, manifest, course): |
400 | 401 | _build_runestone_book(course) |
401 | 402 |
|
402 | 403 |
|
403 | | -def _build_runestone_book(course): |
404 | | - try: |
405 | | - if os.path.exists("pavement.py"): |
406 | | - sys.path.insert(0, os.getcwd()) |
407 | | - from pavement import options, dest, project_name |
408 | | - else: |
409 | | - click.echo( |
410 | | - "I can't find a pavement.py file in {} you need that to build".format( |
411 | | - os.getcwd() |
412 | | - ) |
413 | | - ) |
414 | | - exit(1) |
415 | | - except ImportError as e: |
416 | | - click.echo("You do not appear to have a good pavement.py file.") |
417 | | - print(e) |
418 | | - exit(1) |
419 | | - |
420 | | - if project_name != course: |
421 | | - click.echo( |
422 | | - "Error: {} and {} do not match. Your course name needs to match the project_name in pavement.py".format( |
423 | | - course, project_name |
424 | | - ) |
425 | | - ) |
426 | | - exit(1) |
427 | | - |
428 | | - res = subprocess.call("runestone build --all", shell=True) |
429 | | - if res != 0: |
430 | | - click.echo("building the book failed, check the log for errors and try again") |
431 | | - exit(1) |
432 | | - click.echo("Build succeedeed... Now deploying to published") |
433 | | - if dest != "./published": |
434 | | - click.echo( |
435 | | - "Incorrect deployment directory. dest should be ./published in pavement.py" |
436 | | - ) |
437 | | - exit(1) |
438 | | - |
439 | | - res = subprocess.call("runestone deploy", shell=True) |
440 | | - if res == 0: |
441 | | - click.echo("Success! Book deployed") |
442 | | - else: |
443 | | - click.echo("Deploy failed, check the log to see what went wrong.") |
444 | | - |
445 | | - |
446 | | -def _build_ptx_book(config, gen, manifest, course): |
447 | | - if not os.path.exists("project.ptx"): |
448 | | - click.echo("PreTeXt books need a project.ptx file") |
449 | | - sys.exit(1) |
450 | | - else: |
451 | | - main_file = check_project_ptx() |
452 | | - tree = ET.parse(main_file) |
453 | | - root = tree.getroot() |
454 | | - ElementInclude.include(root, base_url=main_file) # include all xi:include parts |
455 | | - if gen: |
456 | | - res = subprocess.call("pretext generate web") |
457 | | - if res != 0: |
458 | | - click.echo("Failed to build") |
459 | | - # build the book |
460 | | - res = subprocess.call("pretext build runestone", shell=True) |
461 | | - if res != 0: |
462 | | - click.echo("Building failed") |
463 | | - sys.exit(1) |
464 | | - # process the manifest |
465 | | - el = root.find("./docinfo/document-id") |
466 | | - if el is not None: |
467 | | - cname = el.text |
468 | | - if cname != course: |
469 | | - click.echo( |
470 | | - f"Error course: {course} does not match document-id: {cname}" |
471 | | - ) |
472 | | - sys.exit(1) |
473 | | - else: |
474 | | - click.echo("Missing document-id please add to <docinfo>") |
475 | | - sys.exit(1) |
476 | | - |
477 | | - mpath = Path(os.getcwd(), "published", cname, manifest) |
478 | | - process_manifest(cname, mpath) |
479 | | - # Fetch and copy the runestone components release as advertised by the manifest |
480 | | - # - Use wget to get all the js files and put them in _static |
481 | | - click.echo("populating with the latest runestone files") |
482 | | - populate_static(config, mpath, course) |
483 | | - # update the library page |
484 | | - click.echo("updating library...") |
485 | | - update_library(config, mpath, course) |
486 | | - |
487 | | - |
488 | | -import pdb |
489 | | - |
490 | | - |
491 | | -def process_manifest(cname, mpath): |
492 | | - click.echo("processing manifest...") |
493 | | - if os.path.exists(mpath): |
494 | | - manifest_data_to_db(cname, mpath) |
495 | | - else: |
496 | | - raise IOError( |
497 | | - f"You must provide a valid path to a manifest file: {mpath} does not exist." |
498 | | - ) |
499 | | - |
500 | | - |
501 | | -def check_project_ptx(): |
502 | | - tree = ET.parse("project.ptx") |
503 | | - targ = tree.find(".//target[@name='runestone']") |
504 | | - if not targ: |
505 | | - click.echo("No runestone target in project.ptx - please add one") |
506 | | - sys.exit(1) |
507 | | - else: |
508 | | - dest = targ.find("./output-dir") |
509 | | - if "published" not in dest.text: |
510 | | - click.echo("destination for build must be in published/<document-id>") |
511 | | - sys.exit(1) |
512 | | - main = targ.find("./source") |
513 | | - if main is not None: |
514 | | - return main.text |
515 | | - else: |
516 | | - click.echo("No main source file specified") |
517 | | - sys.exit(1) |
518 | | - |
519 | | - |
520 | | -def extract_docinfo(tree, string, attr=None): |
521 | | - el = tree.find(f"./{string}") |
522 | | - if attr is not None and el is not None: |
523 | | - print(f"{el.attrib[attr]=}") |
524 | | - return el.attrib[attr].strip() |
525 | | - |
526 | | - if el is not None: |
527 | | - # using method="text" will strip the outer tag as well as any html tags in the value |
528 | | - return ET.tostring(el, encoding="unicode", method="text").strip() |
529 | | - return "" |
530 | | - |
531 | | - |
532 | | -def update_library(config: Config, mpath, course): |
533 | | - tree = ET.parse(mpath) |
534 | | - docinfo = tree.find("./library-metadata") |
535 | | - eng = create_engine(config.dburl) |
536 | | - title = extract_docinfo(docinfo, "title") |
537 | | - subtitle = extract_docinfo(docinfo, "subtitle") |
538 | | - description = extract_docinfo(docinfo, "blurb") |
539 | | - shelf = extract_docinfo(docinfo, "shelf") |
540 | | - click.echo(f"{title} : {subtitle}") |
541 | | - try: |
542 | | - res = eng.execute(f"select * from library where basecourse = '{course}'") |
543 | | - except: |
544 | | - click.echo("Missing library table? You may need to run an alembic migration.") |
545 | | - sys.exit() |
546 | | - |
547 | | - if res.rowcount == 0: |
548 | | - eng.execute( |
549 | | - f"""insert into library |
550 | | - (title, subtitle, description, shelf_section, basecourse ) |
551 | | - values('{title}', '{subtitle}', '{description}', '{shelf}', '{course}') """ |
552 | | - ) |
553 | | - else: |
554 | | - eng.execute( |
555 | | - f"""update library set |
556 | | - title = '{title}', |
557 | | - subtitle = '{subtitle}', |
558 | | - description = '{description}', |
559 | | - shelf_section = '{shelf}' |
560 | | - where basecourse = '{course}' |
561 | | - """ |
562 | | - ) |
563 | | - |
564 | | - |
565 | | -def populate_static(config: Config, mpath: Path, course: str): |
566 | | - |
567 | | - # <runestone-services version="6.2.1"/> |
568 | | - sdir = mpath.parent / "_static" |
569 | | - current_version = "" |
570 | | - if (sdir / "webpack_static_imports.xml").exists(): |
571 | | - tree = ET.parse(sdir / "webpack_static_imports.xml") |
572 | | - current_version = tree.find("./version").text |
573 | | - else: |
574 | | - sdir.mkdir(mode=775, exist_ok=True) |
575 | | - tree = ET.parse(mpath) |
576 | | - el = tree.find("./runestone-services[@version]") |
577 | | - version = el.attrib["version"].strip() |
578 | | - # Do not download if the versions already match. |
579 | | - if version != current_version: |
580 | | - click.echo(f"Fetching {version} files to {sdir} ") |
581 | | - for f in os.listdir(sdir): |
582 | | - try: |
583 | | - os.remove(sdir / f) |
584 | | - except: |
585 | | - click.echo(f"ERROR - could not delete {f}") |
586 | | - # call wget non-verbose, recursive, no parents, no hostname, no directoy copy files to sdir |
587 | | - # trailing slash is important or otherwise you will end up with everything below runestone |
588 | | - subprocess.call( |
589 | | - f"""wget -nv -r -np -nH -nd -P {sdir} https://runestone.academy/cdn/runestone/{version}/ |
590 | | - """, |
591 | | - shell=True, |
592 | | - ) |
593 | | - else: |
594 | | - click.echo(f"_static files already up to date for {version}") |
595 | | - |
596 | | - |
597 | 404 | # |
598 | 405 | # inituser |
599 | 406 | # |
|
0 commit comments