Remove logo data from templates, add logo args
Removed the hard-coded data: URIs from the template files. Implemented a --logo argument to provide a logo file, and a --no-logo argument to prevent the default logo from being displayed. Data URIs are now created on demand and passed as context to the templates. Bumped version to 0.1.3
This commit is contained in:
parent
4b523aa979
commit
df3d17ba58
9 changed files with 133 additions and 81 deletions
|
@ -1,6 +1,6 @@
|
||||||
# Kalente
|
# Kalente
|
||||||
|
|
||||||
<img src="img/kalente.png" alt="Kalente logo" width="200" height="200" align="right">
|
<img src="src/kalente/static/logo.png" alt="Kalente logo" width="200" height="200" align="right">
|
||||||
|
|
||||||
Kalente is a simple Python script for generating PDF calendars.
|
Kalente is a simple Python script for generating PDF calendars.
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "kalente"
|
name = "kalente"
|
||||||
version = "0.1.2"
|
version = "0.1.3"
|
||||||
authors = [
|
authors = [
|
||||||
{ name="Kumi Mitterer", email="kalente@kumi.email" },
|
{ name="Kumi Mitterer", email="kalente@kumi.email" },
|
||||||
]
|
]
|
||||||
|
|
2
requirements-dev.txt
Normal file
2
requirements-dev.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
djlint
|
||||||
|
black
|
|
@ -6,12 +6,15 @@ from datetime import date, timedelta
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from locale import setlocale, LC_ALL
|
from locale import setlocale, LC_ALL
|
||||||
|
from base64 import b64encode
|
||||||
|
|
||||||
from jinja2 import Environment, FileSystemLoader
|
from jinja2 import Environment, FileSystemLoader
|
||||||
from dateutil.parser import parse
|
from dateutil.parser import parse
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
|
NO_LOGO = ""
|
||||||
|
|
||||||
|
|
||||||
def get_day(
|
def get_day(
|
||||||
for_date: date = None,
|
for_date: date = None,
|
||||||
|
@ -25,11 +28,14 @@ def get_day(
|
||||||
"date_obj": day,
|
"date_obj": day,
|
||||||
"day": day.strftime("%A"),
|
"day": day.strftime("%A"),
|
||||||
"date": day.strftime(date_format),
|
"date": day.strftime(date_format),
|
||||||
"holiday": holidays.CountryHoliday(country_code, years=[for_date.year]).get(day),
|
"holiday": holidays.CountryHoliday(country_code, years=[for_date.year]).get(
|
||||||
|
day
|
||||||
|
),
|
||||||
"is_weekend": (day.weekday() in [5, 6]),
|
"is_weekend": (day.weekday() in [5, 6]),
|
||||||
}
|
}
|
||||||
return day_info
|
return day_info
|
||||||
|
|
||||||
|
|
||||||
def get_week(
|
def get_week(
|
||||||
for_date: date = None,
|
for_date: date = None,
|
||||||
country_code: Optional[str] = None,
|
country_code: Optional[str] = None,
|
||||||
|
@ -60,6 +66,7 @@ def get_week(
|
||||||
week_days.append(day_info)
|
week_days.append(day_info)
|
||||||
return week_days
|
return week_days
|
||||||
|
|
||||||
|
|
||||||
def get_month(
|
def get_month(
|
||||||
for_date: date = None,
|
for_date: date = None,
|
||||||
country_code: Optional[str] = None,
|
country_code: Optional[str] = None,
|
||||||
|
@ -87,6 +94,7 @@ def get_month(
|
||||||
|
|
||||||
return month_weeks
|
return month_weeks
|
||||||
|
|
||||||
|
|
||||||
def get_year(
|
def get_year(
|
||||||
for_date: date = None,
|
for_date: date = None,
|
||||||
country_code: Optional[str] = None,
|
country_code: Optional[str] = None,
|
||||||
|
@ -107,7 +115,10 @@ def get_year(
|
||||||
|
|
||||||
return year_months
|
return year_months
|
||||||
|
|
||||||
def generate_html(content, content_type, template_path: str = None):
|
|
||||||
|
def generate_html(
|
||||||
|
content, content_type, template_path: str = None, logo_path: str = None
|
||||||
|
):
|
||||||
if not template_path:
|
if not template_path:
|
||||||
template_name = "{}.html".format(content_type)
|
template_name = "{}.html".format(content_type)
|
||||||
file_loader = FileSystemLoader(Path(__file__).parent.absolute() / "templates")
|
file_loader = FileSystemLoader(Path(__file__).parent.absolute() / "templates")
|
||||||
|
@ -115,20 +126,35 @@ def generate_html(content, content_type, template_path: str = None):
|
||||||
template_name = template_path
|
template_name = template_path
|
||||||
file_loader = FileSystemLoader()
|
file_loader = FileSystemLoader()
|
||||||
|
|
||||||
|
if logo_path is None:
|
||||||
|
logo_path = Path(__file__).parent / "static" / "logo.png"
|
||||||
|
|
||||||
|
if logo_path:
|
||||||
|
# Let it throw, let it throw, let it throw...
|
||||||
|
with Path(logo_path).open("rb") as logo_file:
|
||||||
|
logo = b64encode(logo_file.read()).decode("utf-8")
|
||||||
|
mime_type = (
|
||||||
|
"image/png" if str(logo_path).endswith(".png") else "image/jpeg"
|
||||||
|
) # Doesn't matter much anyway.
|
||||||
|
data_uri = f"data:image/png;base64,{logo}"
|
||||||
|
|
||||||
env = Environment(loader=file_loader)
|
env = Environment(loader=file_loader)
|
||||||
template = env.get_template(template_name)
|
template = env.get_template(template_name)
|
||||||
|
|
||||||
|
context = {"logo": data_uri}
|
||||||
|
|
||||||
if content_type == "yearly":
|
if content_type == "yearly":
|
||||||
return template.render(year=content)
|
return template.render(year=content, **context)
|
||||||
elif content_type == "monthly":
|
elif content_type == "monthly":
|
||||||
return template.render(month=content, month_obj=content[1][0]["date_obj"])
|
return template.render(month=content, **context)
|
||||||
elif content_type == "weekly":
|
elif content_type == "weekly":
|
||||||
return template.render(week=content)
|
return template.render(week=content, **context)
|
||||||
elif content_type == "daily":
|
elif content_type == "daily":
|
||||||
return template.render(day=content)
|
return template.render(day=content, **context)
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid content type: {}".format(content_type))
|
raise ValueError("Invalid content type: {}".format(content_type))
|
||||||
|
|
||||||
|
|
||||||
def convert_html_to_pdf(content, output_filename, options=None):
|
def convert_html_to_pdf(content, output_filename, options=None):
|
||||||
options.setdefault("page-size", "A4")
|
options.setdefault("page-size", "A4")
|
||||||
options.setdefault("orientation", "Landscape")
|
options.setdefault("orientation", "Landscape")
|
||||||
|
@ -224,6 +250,20 @@ def main():
|
||||||
default=None,
|
default=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
logo_group = parser.add_mutually_exclusive_group()
|
||||||
|
logo_group.add_argument(
|
||||||
|
"--logo",
|
||||||
|
help="Path to the logo to use",
|
||||||
|
required=False,
|
||||||
|
default=None,
|
||||||
|
)
|
||||||
|
logo_group.add_argument(
|
||||||
|
"--no-logo",
|
||||||
|
action="store_true",
|
||||||
|
help="Don't use a logo",
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# Set locale to en_US.UTF-8 – for now, only English is supported
|
# Set locale to en_US.UTF-8 – for now, only English is supported
|
||||||
|
@ -277,20 +317,27 @@ def main():
|
||||||
if not args.type in ["daily", "weekly", "monthly", "yearly"]:
|
if not args.type in ["daily", "weekly", "monthly", "yearly"]:
|
||||||
raise ValueError(f"Invalid calendar type: {args.type}")
|
raise ValueError(f"Invalid calendar type: {args.type}")
|
||||||
|
|
||||||
|
if args.no_logo:
|
||||||
|
logo_path = NO_LOGO
|
||||||
|
else:
|
||||||
|
logo_path = args.logo
|
||||||
|
|
||||||
for i in range(count):
|
for i in range(count):
|
||||||
data = ({
|
data = (
|
||||||
|
{
|
||||||
"daily": get_day,
|
"daily": get_day,
|
||||||
"weekly": get_week,
|
"weekly": get_week,
|
||||||
"monthly": get_month,
|
"monthly": get_month,
|
||||||
"yearly": get_year
|
"yearly": get_year,
|
||||||
}[args.type])(for_date, country_code, args.date_format)
|
}[args.type]
|
||||||
html_content = generate_html(data, args.type, args.template)
|
)(for_date, country_code, args.date_format)
|
||||||
|
html_content = generate_html(data, args.type, args.template, logo_path)
|
||||||
pages.append(html_content)
|
pages.append(html_content)
|
||||||
for_date = {
|
for_date = {
|
||||||
"daily": lambda x: x["date_obj"] + timedelta(days=1),
|
"daily": lambda x: x["date_obj"] + timedelta(days=1),
|
||||||
"weekly": lambda x: x[-1]["date_obj"] + timedelta(days=1),
|
"weekly": lambda x: x[-1]["date_obj"] + timedelta(days=1),
|
||||||
"monthly": lambda x: x[1][0]["date_obj"] + timedelta(days=31),
|
"monthly": lambda x: x[1][0]["date_obj"] + timedelta(days=31),
|
||||||
"yearly": lambda x: x[11][5][0]["date_obj"] + timedelta(days=365)
|
"yearly": lambda x: x[11][5][0]["date_obj"] + timedelta(days=365),
|
||||||
}[args.type](data)
|
}[args.type](data)
|
||||||
|
|
||||||
conversion_options = {"orientation": "Portrait"} if args.type == "daily" else {}
|
conversion_options = {"orientation": "Portrait"} if args.type == "daily" else {}
|
||||||
|
|
Before Width: | Height: | Size: 3 MiB After Width: | Height: | Size: 3 MiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue