Пример #1
0
def read_notebook(meeting: Meeting, suffix: str = FileExtensions.Solutionbook):
    notebook_path = repositories.local_meeting_root(meeting) / repr(meeting)
    if not notebook_path.with_suffix(suffix).exists():
        return nbformat.v4.new_notebook()
    else:
        return nbformat.read(str(notebook_path.with_suffix(suffix)),
                             as_version=4)
Пример #2
0
def update_or_create_folders_and_files(meeting: Meeting):
    """Performs some initial directory creation / cleanup. Currently this
    implementation is quite destructive. Ideally, there's some way to go about
    *intelligently* merging work ~ so this would allow for some temporary titles
    and the like.

    Present file locations:
      - <group>/<semester>/<repr(meeting)>/<repr(meeting)>.solution.ipynb
      - ucfai.org/content/<group>/<semester>/<meeting-filename>.md
    """
    # TODO rename `placeholder` notebooks
    #      this requires changes in both the `paths.repo_meeting_folder` as well as the
    #      `paths.site_post`
    # TODO implement a way to track meetings – since `hugo-academic`'s docs doesn't
    #      work the same way Jekyll posts did (YYYY-MM-DD-<filename>.md), we need a new
    #      way to uniquely identify meetings (so we know which to clean and such)
    #      NOTE we might just be able to totally overwrite the group's contents on the
    #           site, since everything in, say, `core/fa19/*` (minus `_index.md`) is
    #           generated from the meeting's Solutionbook
    # TODO allow for meetings to be moved – this intuitively makes sense to resolve
    #      with the `filename` parameter, but may also need to consider the `date` (you
    #      can get all this from `repr(meeting)`)
    path = repositories.local_meeting_root(meeting)

    root = repositories.local_semester_root(meeting)

    local_neighbors = list(root.iterdir())

    for d in local_neighbors:
        date, name = d.stem[:10], d.stem[11:]

        # remove placeholder
        # rename by date
        shares_meet = ("meeting" in name
                       and int(name[-2:]) == meeting.number - 1)
        shares_date = (date == repr(meeting)[:10])
        if d.stem != repr(meeting) and (shares_meet or shares_date):
            old_path = d
            old_soln = d / "".join([d.stem, FileExtensions.Solutionbook])

            new_path = old_path.with_name(repr(meeting))
            new_soln = old_path / "".join(
                [repr(meeting), FileExtensions.Solutionbook])

            # NOTE: rename internal files before renaming the folder
            tqdm.write(f"renaming: {old_soln} -> {new_soln}")
            old_soln.rename(new_soln)
            tqdm.write(f"renaming: {old_path} -> {new_path}")
            old_path.rename(new_path)
            return
        # TODO: handle meeting swaps (e.g. meeting02 with meeting 06, etc.)
        # TODO: handle meeting renames with swaps
        # TODO: allow for renaming to propagate through to platforms like Kaggle

    path.mkdir(exist_ok=True, parents=True)
Пример #3
0
    def from_meeting(self, meeting: Meeting):
        nb = read_notebook(meeting)

        resources = {"output_extension": FileExtensions.Workbook}
        notebook, resources = super().from_notebook_node(nb, resources)

        # writer = FilesWriter(build_directory=str(paths.repo_meeting_folder(meeting)))
        # writer.write(json.dumps(notebook), resources, repr(meeting))
        filename = (repositories.local_meeting_root(meeting) /
                    repr(meeting)).with_suffix(FileExtensions.Workbook)
        open(filename, "w").write(notebook)

        return notebook, resources
Пример #4
0
    def from_meeting(self, meeting: Meeting):
        notebook_path = repositories.local_meeting_root(meeting) / "".join(
            [repr(meeting), FileExtensions.Solutionbook])

        # TODO concatenate front matter to notebook output
        front_matter = templates.load("meeting/hugo-front-matter.md.j2")
        front_matter = front_matter.render(
            **{
                "group": repr(meeting.group),
                "meeting": {
                    "title": meeting.required["title"],
                    "date": meeting.meta.date.isoformat(),
                    # TODO decide on what date qualifies to be `lastmod`
                    "lastmod": meeting.meta.date.isoformat(),
                    "authors": meeting.required["instructors"],
                    "tags": meeting.optional["tags"],
                    "description": meeting.required["description"],
                    "weight": meeting.number,
                    "room": meeting.meta.room,
                    "cover": meeting.required["cover"],
                },
                "semester": {
                    "full": str(meeting.group.semester),
                    "short": repr(meeting.group.semester),
                },
                "urls": {
                    "youtube": urlgen.youtube(meeting),
                    "slides": urlgen.slides(meeting),
                    "github": urlgen.github(meeting),
                    "kaggle": urlgen.kaggle(meeting),
                    "colab": urlgen.colab(meeting),
                },
            })

        # the notebook is output as a string, so treat it as such when concatenating
        notebook, resources = self.from_filename(str(notebook_path),
                                                 resources=None)
        resources.update({"output_extension": ".md"})

        writer = FilesWriter(
            build_directory=str(paths.site_group_folder_from_meeting(meeting)))

        front_matter_plus_notebook = f"{front_matter}\n{notebook}"

        writer.write(front_matter_plus_notebook, resources,
                     meeting.required["filename"])
        # writer.write(notebook, resources, meeting.required["filename"])

        return notebook, resources
Пример #5
0
def local_and_remote_kernels_diff(meeting: Meeting) -> bool:
    _configure_environment()
    remote_kernel = pull_kernel(meeting)

    if not remote_kernel:
        return True

    local_kernel = repositories.local_meeting_root(meeting) / "".join(
        [repr(meeting), FileExtensions.Workbook])

    remote_kernel_json = json.dumps(json.load(open(remote_kernel,
                                                   "r"))).encode("utf-8")
    local_kernel_json = json.dumps(json.load(open(local_kernel,
                                                  "r"))).encode("utf-8")

    remote_kernel_hash = sha256(bytes(remote_kernel_json)).hexdigest()
    local_kernel_hash = sha256(bytes(local_kernel_json)).hexdigest()

    remote_kernel.unlink()  # clean-up after diff

    return remote_kernel_hash != local_kernel_hash
Пример #6
0
    def from_meeting(self, meeting: Meeting):
        self.meeting = meeting

        nb = read_notebook(meeting)

        resources = {"output_extension": FileExtensions.Solutionbook}

        # NotebookExporter.from_notebook_node returns a notebook as a string
        notebook, resources = super().from_notebook_node(nb,
                                                         resources=resources)

        # to operate over the notebook, we need it to be a NotebookNode
        notebook = nbformat.reads(notebook, as_version=4)
        notebook.cells.insert(0, self._notebook_heading())

        # to write to disk, it now needs to be a string
        notebook = nbformat.writes(notebook)
        filename = (repositories.local_meeting_root(meeting) /
                    repr(meeting)).with_suffix(FileExtensions.Solutionbook)
        open(filename, "w").write(notebook)

        return notebook, resources