Improve hatch scripts and create executables

This commit is contained in:
Sina Atalay
2025-02-04 14:16:39 -05:00
parent de24974c65
commit 0ddd489951
26 changed files with 300 additions and 167 deletions

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 60 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 63 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 57 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 75 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 51 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

View File

@@ -56,6 +56,10 @@ This is done with [Development containers](https://containers.dev/), and the env
These commands are defined in the [`pyproject.toml`](https://github.com/rendercv/rendercv/blob/main/pyproject.toml) file.
- Build the package
```bash
hatch run build
```
- Format the code with [Black](https://github.com/psf/black) and [Ruff](https://github.com/astral-sh/ruff)
```bash
hatch run format
@@ -80,6 +84,18 @@ These commands are defined in the [`pyproject.toml`](https://github.com/rendercv
```bash
hatch run test-and-report
```
- Update [schema.json](https://github.com/rendercv/rendercv/blob/main/schema.json)
```bash
hatch run update-schema
```
- Update [`examples`](https://github.com/rendercv/rendercv/tree/main/examples) folder
```bash
hatch run update-examples
```
- Create an executable version of RenderCV with [PyInstaller](https://www.pyinstaller.org/)
```bash
hatch run create-executables
```
- Preview the documentation as you write it
```bash
hatch run docs:serve
@@ -88,14 +104,6 @@ These commands are defined in the [`pyproject.toml`](https://github.com/rendercv
```bash
hatch run docs:build
```
- Update [schema.json](https://github.com/rendercv/rendercv/blob/main/schema.json)
```bash
hatch run docs:update-schema
```
- Update [`examples`](https://github.com/rendercv/rendercv/tree/main/examples) folder
```bash
hatch run docs:update-examples
```
- Update figures of the entry types in the "[Structure of the YAML Input File](../user_guide/structure_of_the_yaml_input_file.md)"
```bash
hatch run docs:update-entry-figures

View File

@@ -13,12 +13,12 @@ Once the changes are pushed to the `main` branch, the [`deploy-docs.yaml`](https
The `examples` folder includes example YAML files for all the built-in themes, along with their corresponding PDF outputs. Also, there are PNG files of the first pages of each theme in [`docs/assets/images`](https://github.com/rendercv/rendercv/tree/main/docs/assets/images). These examples are shown in [`README.md`](https://github.com/rendercv/rendercv/blob/main/README.md).
These files are generated using [`docs/update_examples.py`](https://github.com/rendercv/rendercv/blob/main/docs/update_examples.py). The contents of the examples are taken from the [`create_a_sample_data_model`](https://docs.rendercv.com/reference/data/#rendercv.data.create_a_sample_data_model) function from [`rendercv.data`](https://docs.rendercv.com/reference/data/).
These files are generated using [`scripts/update_examples.py`](https://github.com/rendercv/rendercv/blob/main/scripts/update_examples.py). The contents of the examples are taken from the [`create_a_sample_data_model`](https://docs.rendercv.com/reference/data/#rendercv.data.create_a_sample_data_model) function from [`rendercv.data`](https://docs.rendercv.com/reference/data/).
Run the following command to update the `examples` folder.
```bash
hatch run docs:update-examples
hatch run update-examples
```
Once a new release is created on GitHub, the [`publish-to-pypi.yaml`](https://github.com/rendercv/rendercv/blob/main/.github/workflows/publish-to-pypi.yaml) workflow will be automatically triggered, and the `examples` folder will be updated to the most recent version.
@@ -27,7 +27,7 @@ Once a new release is created on GitHub, the [`publish-to-pypi.yaml`](https://gi
There are example figures for each entry type for each theme in the "[Structure of the YAML Input File](../user_guide/structure_of_the_yaml_input_file.md)" page.
The figures are generated using [`docs/update_entry_figures.py`](https://github.com/rendercv/rendercv/blob/main/docs/update_entry_figures.py).
The figures are generated using [`scripts/update_entry_figures.py`](https://github.com/rendercv/rendercv/blob/main/scripts/update_entry_figures.py).
Run the following command to update the figures.
@@ -41,12 +41,12 @@ Once a new release is created on GitHub, the [`publish-to-pypi.yaml`](https://gi
The schema of RenderCV's input file is defined using [Pydantic](https://docs.pydantic.dev/latest/). Pydantic allows automatic creation and customization of JSON schemas from Pydantic models.
The JSON Schema is also generated using [`docs/update_schema.py`](https://github.com/rendercv/rendercv/blob/main/docs/update_schema.py). It uses [`generate_json_schema`](https://docs.rendercv.com/reference/data/#rendercv.data.generate_json_schema) function from [`rendercv.data`](https://docs.rendercv.com/reference/data/).
The JSON Schema is also generated using [`scripts/update_schema.py`](https://github.com/rendercv/rendercv/blob/main/scripts/update_schema.py). It uses [`generate_json_schema`](https://docs.rendercv.com/reference/data/#rendercv.data.generate_json_schema) function from [`rendercv.data`](https://docs.rendercv.com/reference/data/).
Run the following command to update the JSON Schema.
```bash
hatch run docs:update-schema
hatch run update-schema
```
Once a new release is created on GitHub, the [`publish-to-pypi.yaml`](https://github.com/rendercv/rendercv/blob/main/.github/workflows/publish-to-pypi.yaml) workflow will be automatically triggered, and `schema.json` will be updated to the most recent version.

View File

@@ -7,17 +7,12 @@ are coming from this script.
import io
import pathlib
import shutil
import tempfile
from typing import get_args
import fitz
import pdfCropMargins
import pydantic
import ruamel.yaml
import rendercv.data as data
import rendercv.renderer as renderer
import rendercv.themes.options as theme_options
repository_root = pathlib.Path(__file__).parent.parent
@@ -153,123 +148,3 @@ def define_env(env):
env.variables["available_bullets"] = ", ".join(
[f"`{bullet}`" for bullet in get_args(theme_options.BulletPoint)]
)
def render_pngs_from_pdf(pdf_file_path: pathlib.Path) -> list[pathlib.Path]:
"""Render a PNG file for each page of the given PDF file.
Args:
pdf_file_path: The path to the PDF file.
Returns:
The paths to the rendered PNG files.
"""
# check if the file exists:
if not pdf_file_path.is_file():
message = f"The file {pdf_file_path} doesn't exist!"
raise FileNotFoundError(message)
# convert the PDF to PNG:
png_directory = pdf_file_path.parent
png_file_name = pdf_file_path.stem
png_files = []
pdf = fitz.open(pdf_file_path) # open the PDF file
for page in pdf: # iterate the pages
image = page.get_pixmap(dpi=300) # type: ignore
png_file_path = png_directory / f"{png_file_name}_{page.number + 1}.png" # type: ignore
image.save(png_file_path)
png_files.append(png_file_path)
return png_files
def generate_entry_figures():
"""Generate an image for each entry type and theme."""
# Generate PDF figures for each entry type and theme
entries = data.read_a_yaml_file(
repository_root / "docs" / "user_guide" / "sample_entries.yaml"
)
entry_types = entries.keys()
entries = SampleEntries(**entries)
themes = data.available_themes
with tempfile.TemporaryDirectory() as temporary_directory:
# Create temporary directory
temporary_directory_path = pathlib.Path(temporary_directory)
for theme in themes:
design_dictionary = {
"theme": theme,
"page": {
"show_page_numbering": False,
"show_last_updated_date": False,
},
}
for entry_type in entry_types:
# Create data model with only one section and one entry
data_model = data.RenderCVDataModel(
cv=data.CurriculumVitae(
sections={entry_type: [getattr(entries, entry_type)]}
),
design=design_dictionary,
)
# Render
typst_file_path = renderer.create_a_typst_file_and_copy_theme_files(
data_model, temporary_directory_path
)
pdf_file_path = renderer.render_a_pdf_from_typst(typst_file_path)
# Prepare output directory and file path
output_directory = image_assets_directory / theme
output_directory.mkdir(parents=True, exist_ok=True)
output_pdf_file_path = output_directory / f"{entry_type}.pdf"
# Remove file if it exists
if output_pdf_file_path.exists():
output_pdf_file_path.unlink()
# Crop margins
pdfCropMargins.crop(
argv_list=[
"-p4",
"100",
"0",
"100",
"0",
"-a4",
"0",
"-30",
"0",
"-30",
"-o",
str(output_pdf_file_path.absolute()),
str(pdf_file_path.absolute()),
]
)
# Convert PDF to image
png_file_path = render_pngs_from_pdf(output_pdf_file_path)[0]
desired_png_file_path = output_pdf_file_path.with_suffix(".png")
# If image exists, remove it
if desired_png_file_path.exists():
desired_png_file_path.unlink()
# Move image to desired location
png_file_path.rename(desired_png_file_path)
# Remove PDF file
output_pdf_file_path.unlink()
def update_index():
"""Update index.md file by copying README.md file."""
index_file_path = repository_root / "docs" / "index.md"
readme_file_path = repository_root / "README.md"
shutil.copy(readme_file_path, index_file_path)
if __name__ == "__main__":
generate_entry_figures()
print("Entry figures generated successfully.") # NOQA: T201

View File

@@ -1,86 +0,0 @@
"""This script generates the `examples` folder in the repository root."""
import os
import pathlib
import shutil
import rendercv.cli as cli
import rendercv.data as data
import rendercv.renderer as renderer
repository_root = pathlib.Path(__file__).parent.parent
rendercv_path = repository_root / "rendercv"
image_assets_directory = pathlib.Path(__file__).parent / "assets" / "images"
def generate_examples():
"""Generate example YAML and PDF files."""
examples_directory_path = pathlib.Path(__file__).parent.parent / "examples"
# Check if examples directory exists. If not, create it
if not examples_directory_path.exists():
examples_directory_path.mkdir()
os.chdir(examples_directory_path)
themes = data.available_themes
for theme in themes:
cli.cli_command_new(
"John Doe",
theme,
dont_create_theme_source_files=True,
dont_create_markdown_source_files=True,
)
yaml_file_path = examples_directory_path / "John_Doe_CV.yaml"
# Rename John_Doe_CV.yaml
proper_theme_name = theme.capitalize() + "Theme"
new_yaml_file_path = (
examples_directory_path / f"John_Doe_{proper_theme_name}_CV.yaml"
)
if new_yaml_file_path.exists():
new_yaml_file_path.unlink()
yaml_file_path.rename(new_yaml_file_path)
yaml_file_path = new_yaml_file_path
# Generate PDF file
cli.cli_command_render(yaml_file_path)
output_pdf_file = (
examples_directory_path / "rendercv_output" / "John_Doe_CV.pdf"
)
output_typst_file = (
examples_directory_path / "rendercv_output" / "John_Doe_CV.typ"
)
# Move PDF file to examples directory
new_pdf_file_path = examples_directory_path / f"{yaml_file_path.stem}.pdf"
if new_pdf_file_path.exists():
new_pdf_file_path.unlink()
output_pdf_file.rename(new_pdf_file_path)
# Convert first page of PDF to image
png_file_paths = renderer.render_pngs_from_typst(output_typst_file)
first_page_png_file_path = png_file_paths[0]
if len(png_file_paths) > 1:
# Remove other pages
for png_file_path in png_file_paths[1:]:
png_file_path.unlink()
desired_png_file_path = image_assets_directory / f"{theme}.png"
# If image exists, remove it
if desired_png_file_path.exists():
desired_png_file_path.unlink()
# Move image to desired location
first_page_png_file_path.rename(desired_png_file_path)
# Remove rendercv_output directory
rendercv_output_directory = examples_directory_path / "rendercv_output"
shutil.rmtree(rendercv_output_directory)
if __name__ == "__main__":
generate_examples()
print("Examples generated successfully.") # NOQA: T201

View File

@@ -1,18 +0,0 @@
"""This script generates the JSON schema (schema.json) in the repository root."""
import pathlib
import rendercv.data as data
repository_root = pathlib.Path(__file__).parent.parent
def generate_schema():
"""Generate the schema."""
json_schema_file_path = repository_root / "schema.json"
data.generate_json_schema_file(json_schema_file_path)
if __name__ == "__main__":
generate_schema()
print("Schema generated successfully.") # NOQA: T201