Compare commits

...
6 Commits
3 changed files with 64 additions and 67 deletions

No files matched your search

+3
View File
@@ -1 +1,4 @@
Program to generate a csv for importing calendar events
If using python 3.12 + need to `pip install --upgrade setuptools`
+4 -4
View File
@@ -16,17 +16,17 @@ EVENT_LIST = ( # ------------- --------
(SUNDAY, [4 ], 10, 00, 12, 00, "Main Campus", "Sunday Service", "Sunday Service 10:00am", "Prayer Room open from 8:30 AM to 9:30 AM. Worship Service starts at 10:00 AM. Fourth Sunday of the month is Coins for Kids Sunday"),
(SUNDAY, [5 ], 10, 00, 12, 00, "Main Campus", "Sunday Service", "Sunday Service 10:00am", "Prayer Room open from 8:30 AM to 9:30 AM. Worship Service starts at 10:00 AM. Fifth Sunday of the month is Potluck Sunday"),
(SUNDAY, [1, 2, 3, 4, 5, 6], 18, 00, 19, 00, "Main Campus", "Sunday Service", "Sunday Eventing Service", ""),
(MONDAY, [1 ], 18, 00, 19, 30, "Main Campus", "Connecting Point", "Level Up 6:00pm", ""),
(MONDAY, [1 ], 18, 00, 19, 30, "Main Campus", "Woman's Meeting", "Level Up 6:00pm", ""),
(MONDAY, [2 ], 18, 00, 19, 30, "Main Campus", "Woman's Meeting", "Ladies Night Out 6:00pm", "Come join us for a time of fun and fellowship\n\nBabysitting will be provided."),
(MONDAY, [4 ], 16, 00, 17, 00, "Main Campus", "Dementia Support", "Dementia Support Group 4:00pm", "Dementia and Alzheimer's Support Group"),
(TUESDAY, [1, 2, 3, 4, 5, 6], 18, 00, 20, 00, "Main Campus", "Grief Share", "Grief Share 6:00pm", ""),
(WEDNESDAY, [1, 2, 3, 4, 5 ], 7, 00, 8, 00, "SOCO", "Youth Group", "Youth Bible Study 7:00am", "Coffee and bible study for high school age youth"),
(WEDNESDAY, [2 ], 8, 00, 12, 00, "Main Campus", "Connecting Point", "Connecting Point 8:00am", ""),
(WEDNESDAY, [3 ], 11, 30, 14, 00, "Main Campus", "Silver Seekers", "Silver Seekers 11:30am", "For those 60 and up. Join us for some food and some exciting events and fellowship."),
(WEDNESDAY, [1, 2, 3, 4, 5 ], 18, 00, 20, 00, "Main Campus", "Youth Group", "Youth Group 6:00pm", ""),
(WEDNESDAY, [3 ], 11, 30, 14, 00, "Main Campus", "Silver Seekers", "Silver Seekers 11:30am", "For those 60 and up. Join us for some food and some exciting events and fellowship."),
(WEDNESDAY, [1, 2, 3, 4, 5 ], 18, 00, 20, 00, "Main Campus", "Mid Week Service", "Mid Week Service 6:00pm", ""),
(THURSDAY, [1, 2, 3, 4, 5 ], 10, 00, 12, 00, "Main Campus", "Woman's Meeting", "Woman's Meeting 10:00am", "Woman 2 Woman Bible Study"),
(FRIDAY, [1, 2, 3, 4 ], 18, 30, 20, 30, "Main Campus", "Men's Meeting", "For Men Only 6:30pm", "Men's Bible Study"),
(FRIDAY, [5 ], 19, 00, 21, 00, "Main Campus", "Movie Night", "Family Movie Night 7:00pm", "To Be Announced"),
(SATURDAY, [1 ], 9, 00, 12, 00, "Main Campus", "Cleanup", "Church Cleanup 9:00am", "Working hearts and hands for God's House"),
(SATURDAY, [2 ], 8, 00, 10, 00, "Main Campus", "Men's Meeting", "Men's Breakfast 8:00am", ""),
# (--------, [- ], 18, 00, 20, 00, "Main Campus", "Youth Group", "South County Youth Group 6:00pm", ""),
)
+57 -63
View File
@@ -6,31 +6,11 @@ CHURCH CALENDAR CSV GENERATOR
import calendar
from dataclasses import dataclass
from datetime import date, datetime
from pprint import pprint
import sys
import click
from dataclass_csv import DataclassWriter
from events import EVENT_LIST
"""
build a list of months / weeks / day of the month in those weeks
months 1-12, weeks 0-5 days of week 5 6 are the 1st and 2nd of month
MONTHS[1] [0] [ 0 0 0 0 0 1 2 ]
due to how months work
week 0 can have null days (represented by 0's)
weeks 1 - 4 will have all 7 days present
week 5 may have 7 days or nulls
week 6 can have a monday and/or tuesday in them if the 1st falls on a
saturday or sunday in week 0
EVENT_LIST has weeks as 1-6 while MONTHS has weeks as 0-5, offsetting will
be necessary
"""
def initalize_events(event_list):
""" convert EVENT_LIST into monthly_events """
monthly_events = [[] for _ in range(7)]
@@ -38,14 +18,8 @@ def initalize_events(event_list):
monthly_events[event[0]].append(event[1:])
return monthly_events
def debug_print(data, condition=True, end="\n"):
"""Conditionally print data using pprint.
Args:
data: The data to be printed.
condition: A boolean value. If True, the data will be printed.
"""
"""Conditionally print data."""
if condition:
print(data, end=end)
@@ -58,7 +32,6 @@ def initalize_year(year: int) -> dict[int, list[list[int]]]:
@dataclass
class Event():
"""Event for CSV export"""
# pylint: disable=too-many-instance-attributes
event_name: str
venue_name: str
organizer_name: str
@@ -86,20 +59,13 @@ def suffix(day: int) -> str:
result = 'rd'
return result
def sort_events(events: list[Event]) -> list[Event]:
"""sort events"""
events = sorted(events, key=lambda k: (k.start_date, k.start_time))
return events
def create_event(name: str,
location: str,
categories: str,
description: str,
start,
finish) -> None:
"""create event"""
# pylint: disable=too-many-arguments
finish) -> Event:
"""create event object"""
event = Event(name,
location,
"",
@@ -116,12 +82,10 @@ def create_event(name: str,
"",
description)
return event
# events.append(event)
def write_calendar(events: list[Event], filename) -> None:
"""write calendar to csv file"""
with open(filename, "w", encoding="utf-8") as handle:
with open(filename, "w", encoding="utf-8", newline="") as handle:
writer = DataclassWriter(handle, events, Event)
writer.map("event_name").to("EVENT NAME")
writer.map("venue_name").to("VENUE NAME")
@@ -140,7 +104,6 @@ def write_calendar(events: list[Event], filename) -> None:
writer.map("event_description").to("EVENT DESCRIPTION")
writer.write()
def process_day(events, year, month, day, day_events):
"""process all events for one day"""
for event_item in day_events:
@@ -151,47 +114,78 @@ def process_day(events, year, month, day, day_events):
events.append(event)
return events
def process_month(months, monthly_events, year, month, week_of_month, week, events):
"""process one months of events"""
def process_month(monthly_events, year, month, week, events, weekday_counters):
"""process one week of events using weekday occurrence counters"""
for day_of_week, day in enumerate(week):
if day > 0:
"""
month, week_of_month, day_of_week, day
use monthly_events[day_of_week]
"""
debug_print(f" {day_of_week}-{day:02d}", DEBUG)
day_events = [x[1:] for x in monthly_events[day_of_week] if week_of_month + 1 in x[0]]
# Increment the occurrence count for this specific weekday (0=Mon, 6=Sun)
weekday_counters[day_of_week] += 1
current_occurrence = weekday_counters[day_of_week]
debug_print(f" {day_of_week}-{day:02d} (Occurrence: {current_occurrence})", DEBUG)
# Filter events matching this day of week and this specific occurrence (e.g., 2nd Monday)
day_events = [x[1:] for x in monthly_events[day_of_week] if current_occurrence in x[0]]
events = process_day(events, year, month, day, day_events)
debug_print("", DEBUG)
return events
def process_months(months, monthly_events, year):
"""process full year of months and return list of events"""
def process_months(months_dict, monthly_events, year, month_range):
"""process selected months and return list of events"""
events = []
for month in range(1, 13):
if month not in month_range:
continue
debug_print(f"MONTH: {month}", DEBUG)
for week_of_month, week in enumerate(months[month]):
# Initialize counters for the month to track 1st, 2nd, etc. occurrence of each weekday
weekday_counters = [0] * 7
for week_of_month, week in enumerate(months_dict[month]):
debug_print(f"{week_of_month} {week}", DEBUG)
events = process_month(months, monthly_events, year, month, week_of_month, week, events)
events = process_month(monthly_events, year, month, week, events, weekday_counters)
return events
# @click.argument('filename', type=click.File('w'), default="calendar.csv", required=False)
def validate_months(ctx, param, value):
"""Validates and processes the --months option."""
if value is None:
return list(range(1, 13))
parts = value.split('-')
if len(parts) == 1:
try:
month = int(parts[0])
if 1 <= month <= 12:
return [month]
raise click.BadParameter("Month must be between 1 and 12.")
except ValueError:
raise click.BadParameter("Invalid month format.")
elif len(parts) == 2:
try:
start, end = int(parts[0]), int(parts[1])
if 1 <= start <= 12 and 1 <= end <= 12 and start <= end:
return list(range(start, end + 1))
raise click.BadParameter("Invalid month range.")
except ValueError:
raise click.BadParameter("Invalid range format.")
raise click.BadParameter("Use a single number or a range (e.g., 1-3).")
@click.command()
@click.option("--debug", "-d", is_flag=True, default=False, help="Print debug output")
@click.option('--year', "-y", type=int, default=date.today().year, help='Specify the year.')
@click.option('--months', '-m', 'month_range', callback=validate_months, default=None,
help='A single month (1-12) or a range (e.g., 1-3).')
@click.argument('filename', default="calendar.csv", required=False)
def main(debug, year, filename):
"""Create a .csv file of church events for the year. Modify events.py to change events"""
def main(debug, year, month_range, filename):
"""Create a .csv file of church events for the year."""
global DEBUG
DEBUG = debug
months = initalize_year(year)
months_dict = initalize_year(year)
monthly_events = initalize_events(EVENT_LIST)
events = process_months(months, monthly_events, year)
# events = sort_events(events)
events = process_months(months_dict, monthly_events, year, month_range)
write_calendar(events, filename)
sys.exit(0)
if __name__ == "__main__":
main() # pylint: disable=E1120
main()