diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..2fd2b4b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,31 @@ +FROM python:3.13.1-alpine3.20 + +ARG DIST_VERSION=1.0 +ARG DIST_FILENAME=dumbremind-${DIST_VERSION}-py3-none-any.whl + +RUN apk update && apk add bash && apk add wget + +# Timezone +RUN apk add tzdata +RUN cp /usr/share/zoneinfo/Europe/Paris /etc/localtime +RUN echo "Europe/Paris" > /etc/timezone + +# Clean apk cache +RUN rm -rf /var/cache/apk/* + +COPY docker/docker-init.sh /usr/local/bin/ +RUN chmod +x usr/local/bin/docker-init.sh + +RUN cd / +COPY dist/${DIST_FILENAME} / +RUN python3 -m pip install ${DIST_FILENAME} +# --target /app +RUN rm -f ${DIST_FILENAME} + +# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +# NEVER PUBLISH IMAGE ON PUBLIC REPOSITORY +COPY .env /.env +# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +WORKDIR / +CMD ["docker-init.sh"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9fb6181 --- /dev/null +++ b/Makefile @@ -0,0 +1,39 @@ +ifeq (run,$(firstword $(MAKECMDGOALS))) + # use the rest as arguments for "run" + RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) + # ...and turn them into do-nothing targets + $(eval $(RUN_ARGS):;@:) +endif + +.PHONY: all build run test + +# code quality +all: black typehint lint + +black: + uv run isort --multi-line 3 --profile black src/ tests/ + uv run black --target-version py311 src/ tests/ + +typehint: + uv run mypy --ignore-missing-imports src/ tests/ + +lint: + uv run pylint src/ + +# check +check: all + +# build +build: + # https://stackoverflow.com/questions/24347450/how-do-you-add-additional-files-to-a-wheel + rm -rf build/* dist/* *.egg-info + uv sync + uv build --wheel --out-dir dist + docker build -t source.madyanne.fr/yax/dumbremind . + +publish: + docker push source.madyanne.fr/yax/dumbremind + +# run +run: + uv run -m dumbremind diff --git a/README.md b/README.md index 89ff8ed..6e35d96 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,25 @@ Dumb CalDAV Reminder: definitively not a kind name but a very useful tool to retrieve CalDAV events and tasks and output them in a concise way. Combined with a cron and a notification system it should help my poor brain to be more efficient. -Usage : copy .env.default as .env then edit CalDAV connection parameters and and number of days to get. +## Usage + +copy .env.default as .env then edit CalDAV connection parameters and number of days to retrieve. + + uv run -m dumbremind + + # or make + make run + +## Docker : + +Warning: docker image is designed to be published on a private repository because it includes credentials from your .env file + + # build local image + make build + + # change publish target first (mine is source.madyanne.fr/yax/dumbremind) + make publish + + # run dumbremind in docker (adapt URI) and remove container on exit + docker run --rm source.madyanne.fr/yax/dumbremind -More to come: docker packaging \ No newline at end of file diff --git a/docker/docker-init.sh b/docker/docker-init.sh new file mode 100644 index 0000000..3d0a401 --- /dev/null +++ b/docker/docker-init.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +python3 -m dumbremind + +# catch for debug +#tail -f /dev/null \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 6a9698a..dde36b0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] -name = "caldav-reminder" +name = "dumbremind" version = "1.0" -description = "CalDav Reminder" +description = "Dumb Remind" readme = "README.md" authors = [ { name = "Yax" } @@ -12,14 +12,9 @@ dependencies = [ "python-dotenv>=1.1.1", ] -[dependency-groups] -dev = [ -] - -[tool.setuptools] - -[tool.setuptools.package-data] +[project.scripts] +dumbremind = "dumbremind:main" [build-system] -requires = ["setuptools>=61.0"] -build-backend = "setuptools.build_meta" +requires = ["uv_build>=0.8.17,<0.9.0"] +build-backend = "uv_build" \ No newline at end of file diff --git a/src/dumbremind/__init__.py b/src/dumbremind/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/caldav-reminder.py b/src/dumbremind/__main__.py similarity index 63% rename from caldav-reminder.py rename to src/dumbremind/__main__.py index 52297ec..7e2f874 100644 --- a/caldav-reminder.py +++ b/src/dumbremind/__main__.py @@ -56,25 +56,30 @@ def display_todo(todo: dict[str, str]): print("Todo : " + todo["summary"]) -url = 'https://' + quote_plus(USERNAME) + ":" + quote_plus(PASSWORD) \ - + '@' + BASE_URL + quote_plus(USERNAME) + '/' -start = date.today() -end = start + timedelta(days=NEXT_DAYS) -client = caldav.DAVClient(url) -calendars = client.principal().calendars() +def main(): + url = 'https://' + quote_plus(USERNAME) + ":" + quote_plus(PASSWORD) \ + + '@' + BASE_URL + quote_plus(USERNAME) + '/' + start = date.today() + end = start + timedelta(days=NEXT_DAYS) + client = caldav.DAVClient(url) + calendars = client.principal().calendars() -if not calendars: - print("No calendars defined for " + USERNAME) - sys.exit(0) + if not calendars: + print("No calendars defined for " + USERNAME) + sys.exit(0) -for cal in calendars: - events = cal.search(event=True, start=start, end=end, expand=True) \ - + cal.search(todo=True) - for event in events: - for component in event.icalendar_instance.walk(): - if component.name == "VEVENT": - display_event(fill_event(component, cal)) - elif component.name == "VTODO": - display_todo(fill_todo(component, cal)) + for cal in calendars: + events = cal.search(event=True, start=start, end=end, expand=True) \ + + cal.search(todo=True) + for event in events: + for component in event.icalendar_instance.walk(): + if component.name == "VEVENT": + display_event(fill_event(component, cal)) + elif component.name == "VTODO": + display_todo(fill_todo(component, cal)) -print(".") + print(".") + + +if __name__ == "__main__": + main()