From 39f4d280fbee356c0fa9d69028693e012624d634 Mon Sep 17 00:00:00 2001 From: Dorian Santner Date: Tue, 5 Dec 2023 22:03:53 +0100 Subject: [PATCH] #3 Add initial prototype from pyGRAZ meetup --- content/blog/first-post/contents.lr | 24 ++++++++- poetry.lock | 38 +++++++++++++- pyproject.toml | 1 + scripts/convert_pygraz_csv_to_lektor.py | 67 +++++++++++++++++++++++++ 4 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 scripts/convert_pygraz_csv_to_lektor.py diff --git a/content/blog/first-post/contents.lr b/content/blog/first-post/contents.lr index cf71e2c..1bfd02e 100644 --- a/content/blog/first-post/contents.lr +++ b/content/blog/first-post/contents.lr @@ -1,4 +1,6 @@ -## title: Hello Website +## title: + +Hello Website ## pub_date: 2023-12-05 @@ -6,4 +8,22 @@ body: -This is an example blog post. Not much here but that's not the point :) +## This is an example blog post. Not much here but that's not the point :) + +## author: Thomas Aglassinger + +body: + +Die pyGRAZ-Webseite wird von einer dynamischen Django-Anwendung auf eine statisch generierte Seite umgestellt unter Verwendung des Lektor CMS. Dies beinhalte u.a. Umwandlung der Datenbankeinträge unserer Treffen seit 2008. Die liegen derzeit als JSON-Dateien vor und sollen am Ende Markdown-Dokumente sein. + +Das machen wir gemeinsam im Rahmen eines Coding-Dojos. + +Der Ablauf in bewährter Manier: Alle Teilnehmer nutzen den selben Computer, um die Aufgabe umzusetzen. Eine Person ist der Pilot, der programmiert. Eine andere Person nimmt die Rolle des Co-Piloten ein und unterstützt den Piloten beim Konzipieren und Designen. Nach 2 Minuten gibt es einen Wechsel: Der Pilot geht ins Publikum, der Co-Pilot wird zum Piloten und eine neue Person aus dem Publikum wird zum Co-Piloten. Damit ist sichergestellt, dass alle etwas beitragen können. Bei Bedarf kann sich der Co-Pilot Unterstützung aus dem Publikum holen, so dass immer etwas zu tun ist und niemand stecken bleibt. Siehe dazu auch z.B. [Coding Dojo 101](https://humberto.io/blog/coding-dojo-101/). + +## Das Ziel eines Dojos ist ja, Spaß zu haben und am Ende etwas neues gelernt zu haben. + +## pub_date: 2023-12-05 + +## title: pyGRAZ Website-Umstellung + +twitter_handle: roskakori diff --git a/poetry.lock b/poetry.lock index cc62e7b..878930a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,9 +1,10 @@ -# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. +# This file is automatically @generated by Poetry and should not be changed by hand. [[package]] name = "babel" version = "2.13.1" description = "Internationalization utilities" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -21,6 +22,7 @@ dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] name = "blinker" version = "1.7.0" description = "Fast, simple object-to-object and broadcast signaling" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -32,6 +34,7 @@ files = [ name = "certifi" version = "2023.11.17" description = "Python package for providing Mozilla's CA Bundle." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -43,6 +46,7 @@ files = [ name = "cfgv" version = "3.4.0" description = "Validate configuration and produce human readable error messages." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -54,6 +58,7 @@ files = [ name = "charset-normalizer" version = "3.3.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -153,6 +158,7 @@ files = [ name = "click" version = "8.1.7" description = "Composable command line interface toolkit" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -167,6 +173,7 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -178,6 +185,7 @@ files = [ name = "distlib" version = "0.3.7" description = "Distribution utilities" +category = "dev" optional = false python-versions = "*" files = [ @@ -189,6 +197,7 @@ files = [ name = "exifread" version = "3.0.0" description = "Read Exif metadata from tiff and jpeg files." +category = "main" optional = false python-versions = "*" files = [ @@ -203,6 +212,7 @@ dev = ["mypy (==0.950)", "pylint (==2.13.8)"] name = "filelock" version = "3.13.1" description = "A platform independent file lock." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -219,6 +229,7 @@ typing = ["typing-extensions (>=4.8)"] name = "filetype" version = "1.2.0" description = "Infer file type and MIME type of any file/buffer. No external dependencies." +category = "main" optional = false python-versions = "*" files = [ @@ -230,6 +241,7 @@ files = [ name = "flask" version = "2.3.3" description = "A simple framework for building complex web applications." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -252,6 +264,7 @@ dotenv = ["python-dotenv"] name = "identify" version = "2.5.32" description = "File identification library for Python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -266,6 +279,7 @@ license = ["ukkonen"] name = "idna" version = "3.6" description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -277,6 +291,7 @@ files = [ name = "inifile" version = "0.4.1" description = "A small INI library for Python." +category = "main" optional = false python-versions = "*" files = [ @@ -287,6 +302,7 @@ files = [ name = "itsdangerous" version = "2.1.2" description = "Safely pass data to untrusted environments and back." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -298,6 +314,7 @@ files = [ name = "jinja2" version = "3.1.2" description = "A very fast and expressive template engine." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -315,6 +332,7 @@ i18n = ["Babel (>=2.7)"] name = "lektor" version = "3.3.10" description = "A static content management system." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -347,6 +365,7 @@ ipython = ["ipython", "traitlets"] name = "markupsafe" version = "2.1.3" description = "Safely add untrusted strings to HTML/XML markup." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -416,6 +435,7 @@ files = [ name = "mistune" version = "0.8.4" description = "The fastest markdown parser in pure Python" +category = "main" optional = false python-versions = "*" files = [ @@ -427,6 +447,7 @@ files = [ name = "nodeenv" version = "1.8.0" description = "Node.js virtual environment builder" +category = "dev" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" files = [ @@ -441,6 +462,7 @@ setuptools = "*" name = "pip" version = "23.3.1" description = "The PyPA recommended tool for installing Python packages." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -452,6 +474,7 @@ files = [ name = "platformdirs" version = "4.1.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -467,6 +490,7 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-co name = "pre-commit" version = "3.5.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -485,6 +509,7 @@ virtualenv = ">=20.10.0" name = "python-slugify" version = "8.0.1" description = "A Python slugify application that also handles Unicode" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -502,6 +527,7 @@ unidecode = ["Unidecode (>=1.1.1)"] name = "pytz" version = "2023.3.post1" description = "World timezone definitions, modern and historical" +category = "main" optional = false python-versions = "*" files = [ @@ -513,6 +539,7 @@ files = [ name = "pyyaml" version = "6.0.1" description = "YAML parser and emitter for Python" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -572,6 +599,7 @@ files = [ name = "requests" version = "2.31.0" description = "Python HTTP for Humans." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -593,6 +621,7 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "setuptools" version = "69.0.2" description = "Easily download, build, install, upgrade, and uninstall Python packages" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -609,6 +638,7 @@ testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jar name = "text-unidecode" version = "1.3" description = "The most basic Text::Unidecode port" +category = "main" optional = false python-versions = "*" files = [ @@ -620,6 +650,7 @@ files = [ name = "urllib3" version = "2.1.0" description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -636,6 +667,7 @@ zstd = ["zstandard (>=0.18.0)"] name = "virtualenv" version = "20.25.0" description = "Virtual Python Environment builder" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -656,6 +688,7 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess name = "watchdog" version = "3.0.0" description = "Filesystem events monitoring" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -695,6 +728,7 @@ watchmedo = ["PyYAML (>=3.10)"] name = "werkzeug" version = "2.3.8" description = "The comprehensive WSGI web application library." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -711,4 +745,4 @@ watchdog = ["watchdog (>=2.3)"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "5f17ef402bb270316b731e7d1c852fc029e2cb48ae793e3c273ec95f35210b1a" +content-hash = "d83d2bea57553f73a7c4c8e9dbf099275d1e5cad5899a1038ded1088f70ab3e3" diff --git a/pyproject.toml b/pyproject.toml index 02fbc30..7a4168f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,6 +9,7 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.10" lektor = "^3.3.10" +python-slugify = "^8.0.1" [tool.poetry.group.dev.dependencies] diff --git a/scripts/convert_pygraz_csv_to_lektor.py b/scripts/convert_pygraz_csv_to_lektor.py new file mode 100644 index 0000000..235934f --- /dev/null +++ b/scripts/convert_pygraz_csv_to_lektor.py @@ -0,0 +1,67 @@ +import csv +import pathlib +from datetime import datetime + +from slugify import slugify + +CSV_FOLDER = pathlib.Path(__file__).parent / "data" +BLOG_FOLDER = pathlib.Path(__file__).parent.parent / "blog" + +csv_names = [ + "meetups_location.csv", + "meetups_meetup.csv", + "meetups_session.csv", + "meetups_sessiontype.csv", +] + + +def csv_id_to_rows(basename: str) -> dict[str, list[dict]]: + result = {} + with open(CSV_FOLDER / basename, newline="") as csv_file: + reader = csv.DictReader(csv_file) + for row in reader: + result[row["id"]] = row + return result + + +data = {basename: csv_id_to_rows(basename) for basename in csv_names} + + +def convert(): + # print(data) + # keys = {k:mydata[0].keys() for k, mydata in data.items()} + # pprint(keys) + sessions = data["meetups_session.csv"] + meetups = data["meetups_meetup.csv"] + for session_id, session in sessions.items(): + meetup_id = session["meetup_id"] + if meetup_id == "": + print("warning, sesson ohne meetup:", session_id) + continue + + meetup = meetups[meetup_id] + + # chase date + start_date_as_string = meetup["start_date"].replace(" ", "T") + ":00" + start_date = datetime.fromisoformat(start_date_as_string) + date_as_string = start_date.date().isoformat() + + # create folder + content_directory = ( + BLOG_FOLDER / f"{date_as_string}-{slugify(session['title'])}" + ) + content_directory.mkdir(parents=True, exist_ok=True) + + # make content-file + with open(content_directory / "contents.lr", "w") as f: + f.write(f"body: \n{session['abstract']}\n") + f.write("---\n") + f.write("author: TODO\n") + f.write("---\n") + f.write(f"title: {session['title']}\n") + + print(CSV_FOLDER) + + +if __name__ == "__main__": + convert()