Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Save state after each build.
  • Loading branch information
JulienPalard committed Oct 17, 2023
commit 19e8934265d3ad00ff6d381df95f941b9039a1db
71 changes: 51 additions & 20 deletions build_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
from argparse import ArgumentParser
from contextlib import suppress, contextmanager
from dataclasses import dataclass
from datetime import datetime as dt, timezone
from time import perf_counter
import filecmp
import json
import logging
Expand Down Expand Up @@ -354,20 +356,6 @@ def locate_nearest_version(available_versions, target_version):
return tuple_to_version(found)


def translation_branch(repo: Repository, needed_version: str):
"""Some cpython versions may be untranslated, being either too old or
too new.

This function looks for remote branches on the given repo, and
returns the name of the nearest existing branch.

It could be enhanced to also search for tags.
"""
remote_branches = repo.run("branch", "-r").stdout
branches = re.findall(r"/([0-9]+\.[0-9]+)$", remote_branches, re.M)
return locate_nearest_version(branches, needed_version)


@contextmanager
def edit(file: Path):
"""Context manager to edit a file "in place", use it as:
Expand Down Expand Up @@ -652,13 +640,15 @@ def full_build(self):

def run(self) -> bool:
"""Build and publish a Python doc, for a language, and a version."""
start_time = perf_counter()
try:
self.cpython_repo.switch(self.version.branch_or_tag)
if self.language.tag != "en":
self.clone_translation()
self.build_venv()
self.build()
self.copy_build_to_webroot()
self.save_state(build_duration=perf_counter() - start_time)
except Exception as err:
logging.exception(
"Exception while building %s version %s",
Expand All @@ -676,10 +666,13 @@ def checkout(self) -> Path:
return self.build_root / "cpython"

def clone_translation(self):
"""Clone the translation repository from github.
self.translation_repo.update()
self.translation_repo.switch(self.translation_branch)

@property
def translation_repo(self):
"""See PEP 545 for translations repository naming convention."""

See PEP 545 for repository naming convention.
"""
locale_repo = f"https://github.com/python/python-docs-{self.language.tag}.git"
locale_clone_dir = (
self.build_root
Expand All @@ -688,9 +681,21 @@ def clone_translation(self):
/ self.language.iso639_tag
/ "LC_MESSAGES"
)
repo = Repository(locale_repo, locale_clone_dir)
repo.update()
repo.switch(translation_branch(repo, self.version.name))
return Repository(locale_repo, locale_clone_dir)

@property
def translation_branch(self):
"""Some cpython versions may be untranslated, being either too old or
too new.

This function looks for remote branches on the given repo, and
returns the name of the nearest existing branch.

It could be enhanced to also search for tags.
"""
remote_branches = self.translation_repo.run("branch", "-r").stdout
branches = re.findall(r"/([0-9]+\.[0-9]+)$", remote_branches, re.M)
return locate_nearest_version(branches, self.version.name)

def build(self):
"""Build this version/language doc."""
Expand Down Expand Up @@ -922,6 +927,32 @@ def copy_build_to_webroot(self):
self.language.tag,
)

def save_state(self, build_duration):
"""Save current cpython sha1 and current translation sha1.

Using this we can deduce if a rebuild is needed or not.
"""
state_file = self.build_root / "state.toml"
try:
states = tomlkit.parse(state_file.read_text(encoding="UTF-8"))
except FileNotFoundError:
states = tomlkit.document()

state = {}
state["cpython_sha"] = self.cpython_repo.run("rev-parse", "HEAD").stdout.strip()
if self.language.tag != "en":
state["translation_sha"] = self.translation_repo.run(
"rev-parse", "HEAD"
).stdout.strip()
state["last_build"] = dt.now(timezone.utc)
state["last_build_duration"] = build_duration

states.setdefault("build", {}).setdefault(self.language.tag, {})[
self.version.name
] = state

state_file.write_text(tomlkit.dumps(states), encoding="UTF-8")


def symlink(www_root: Path, language: Language, directory: str, name: str, group: str):
"""Used by major_symlinks and dev_symlink to maintain symlinks."""
Expand Down