Convert ULSA enrollment HTML into beautiful schedule images (PNG, SVG, PDF)
Project description
ULSA Schedule Parser
Convert ugly ULSA enrollment HTML into beautiful schedule images.
PNG, SVG, and PDF output. Zero config. One command.
Installation • Usage • Output Formats • Architecture • API • Contributing
That enrollment HTML from ULSA? You know the one — a wall of
<table>soup with inline styles from 2005. ulsa-schedule parses it and renders a clean, color-coded schedule you can actually read.
One command. PNG by default, SVG for crisp vector output, PDF for printing. Conflict detection included.
HTML Input (imprimir_inscripcion.html)
↓ parse
Domain Model (Events, Days, Time slots)
↓ normalize
ScheduleView (grid + metadata)
↓ render
PNG / SVG / PDF
Quick Start
Install
pip install ulsa-schedule-parser
For PDF support:
pip install ulsa-schedule-parser[pdf]
From source:
git clone https://github.com/CharFranR/ULSA-Schedule-Parser.git
cd ULSA-Schedule-Parser
pip install .
Use
# PNG (default)
ulsa-schedule path/to/imprimir_inscripcion.html
# Custom output name
ulsa-schedule input.html -o my_schedule.png
# PDF
ulsa-schedule input.html -o schedule --pdf
# SVG (vector, scalable)
ulsa-schedule input.html -o schedule --svg
# All three at once
ulsa-schedule input.html -o schedule --pdf --svg
That's it. No config, no setup, no dependencies to wrestle with.
Output Formats
| Format | Flag | Requires | Best for |
|---|---|---|---|
| PNG | (default) | Pillow | Sharing, social media, quick view |
| SVG | --svg |
(none) | Web, scalable prints, editing |
--pdf |
ulsa-schedule-parser[pdf] |
Printing, formal documents |
How It Works
1. HTML file → BeautifulSoup extracts the schedule table
2. Events parsed into domain model (Day, Time, Event)
3. Consecutive events with same properties merged automatically
4. Normalization: 50-minute slots, lunch row insertion, conflict detection
5. Renderers output clean, color-coded schedules
Conflict detection: overlapping classes are flagged and marked with X patterns in the output.
Programmatic API
from ulsa_schedule import (
HtmlBs4ScheduleParser,
PillowScheduleRenderer,
SvgScheduleRenderer,
RenderScheduleUseCase,
)
# Parse and render
parser = HtmlBs4ScheduleParser()
renderer = PillowScheduleRenderer()
use_case = RenderScheduleUseCase(parser, renderer)
html = open("imprimir_inscripcion.html").read()
png_bytes, view = use_case.execute(html)
# view.has_conflicts → True if overlapping classes detected
# view.days → [Day.MON, Day.TUE, ...]
# view.grid → 2D list of CellRender objects
# view.time_labels → ["08:00 am", "09:00 am", ...]
# SVG instead
from ulsa_schedule import SvgScheduleRenderer
svg_bytes = SvgScheduleRenderer().render(view)
Architecture
ulsa_schedule/
├── domain/ # Pure business logic (no I/O)
│ ├── model.py # Event, Day, Time, ScheduleView, CellRender
│ └── normalize.py # Slot normalization, merge, lunch insertion
├── adapters/ # I/O adapters
│ ├── html_bs4.py # HTML parser (BeautifulSoup)
│ ├── render_pillow.py # PNG renderer (Pillow, bundled DejaVu Sans)
│ ├── render_svg.py # SVG renderer (zero dependencies)
│ └── render_reportlab.py # PDF renderer (optional)
├── use_cases/
│ └── render_schedule.py # Orchestration: parse → normalize → render
├── cli.py # CLI entrypoint
└── assets/fonts/ # Bundled DejaVuSans.ttf
Clean Architecture: domain has zero dependencies on adapters. Swap renderers, add new formats, or replace the parser without touching business logic.
CLI Reference
| Command | Description |
|---|---|
ulsa-schedule <input> |
Render to PNG (default) |
ulsa-schedule <input> -o out.png |
Custom output path |
ulsa-schedule <input> --pdf |
Also generate PDF |
ulsa-schedule <input> --svg |
Also generate SVG |
python -m ulsa_schedule <input> |
Module execution (same behavior) |
Exit Codes
| Code | Meaning |
|---|---|
0 |
Success |
2 |
Parse error (invalid HTML, missing table, file not found) |
3 |
Render error (PDF dependency missing, write failure) |
Development
# Clone and install dev dependencies
git clone https://github.com/CharFranR/ULSA-Schedule-Parser.git
cd ULSA-Schedule-Parser
pip install -e ".[pdf]"
# Run tests
python -m unittest discover -s tests -v
# Test without PDF (uninstall reportlab first)
pip uninstall reportlab
python -m unittest discover -s tests -v
License
Built with Python, BeautifulSoup4, Pillow, and ReportLab.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ulsa_schedule_parser-1.0.2-py3-none-any.whl.
File metadata
- Download URL: ulsa_schedule_parser-1.0.2-py3-none-any.whl
- Upload date:
- Size: 404.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f404c5951e91b7ff93d031f937cd177724da91d830ee11378cfdee418cbf686b
|
|
| MD5 |
b24d5b7924e924f4c39a6a8ae9803b0e
|
|
| BLAKE2b-256 |
7128d89e397f0588eba10e30ef2f2b9d6f7d9d79b82d37bd3cea2bc98927699c
|
Provenance
The following attestation bundles were made for ulsa_schedule_parser-1.0.2-py3-none-any.whl:
Publisher:
flujodetrabajo.yml on CharFranR/ULSA-Schedule-Parser
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ulsa_schedule_parser-1.0.2-py3-none-any.whl -
Subject digest:
f404c5951e91b7ff93d031f937cd177724da91d830ee11378cfdee418cbf686b - Sigstore transparency entry: 1207790076
- Sigstore integration time:
-
Permalink:
CharFranR/ULSA-Schedule-Parser@5425857f05a842360f4d4e09e79bc6879477434d -
Branch / Tag:
refs/tags/v1.0.2 - Owner: https://github.com/CharFranR
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
flujodetrabajo.yml@5425857f05a842360f4d4e09e79bc6879477434d -
Trigger Event:
release
-
Statement type: