diff --git a/.github/workflows/update_schedule.yml b/.github/workflows/update_schedule.yml new file mode 100644 index 0000000..4d93021 --- /dev/null +++ b/.github/workflows/update_schedule.yml @@ -0,0 +1,32 @@ +name: Update schedule +on: + workflow_dispatch: + schedule: + - cron: "22 */2 * * *" +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: "3.11" + - run: | + cd scripts + pip install poetry + poetry install + poetry run python schedule_sync.py + env: + PRETALX_TOKEN: ${{ secrets.PRETALX_TOKEN }} + - run: git diff + - uses: EndBug/add-and-commit@v4 + with: + add: | + public/people + src/content/sessions + src/content/people + author_name: Robot + author_email: beep-boop@local + message: "Auto-update of schedule" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 3c77d84..6b68a20 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ data/SpeakerPack/* node_modules dist/ .astro +.envrc diff --git a/public/people/37TEMH.jpg b/public/people/37TEMH.jpg new file mode 100644 index 0000000..6dbbb2f Binary files /dev/null and b/public/people/37TEMH.jpg differ diff --git a/public/people/3C7EAA.jpg b/public/people/3C7EAA.jpg new file mode 100644 index 0000000..2f0c346 Binary files /dev/null and b/public/people/3C7EAA.jpg differ diff --git a/public/people/8UFZNX.jpg b/public/people/8UFZNX.jpg new file mode 100644 index 0000000..ee4826b Binary files /dev/null and b/public/people/8UFZNX.jpg differ diff --git a/public/people/9JGCPM.jpg b/public/people/9JGCPM.jpg new file mode 100644 index 0000000..8fefbba Binary files /dev/null and b/public/people/9JGCPM.jpg differ diff --git a/public/people/9SG3KG.jpg b/public/people/9SG3KG.jpg new file mode 100644 index 0000000..af218b8 Binary files /dev/null and b/public/people/9SG3KG.jpg differ diff --git a/public/people/A373NW.jpg b/public/people/A373NW.jpg new file mode 100644 index 0000000..bd5b2b7 Binary files /dev/null and b/public/people/A373NW.jpg differ diff --git a/public/people/AHET73.jpg b/public/people/AHET73.jpg new file mode 100644 index 0000000..7add6d7 Binary files /dev/null and b/public/people/AHET73.jpg differ diff --git a/public/people/BA8DVU.jpg b/public/people/BA8DVU.jpg new file mode 100644 index 0000000..e87e369 Binary files /dev/null and b/public/people/BA8DVU.jpg differ diff --git a/public/people/BALYAL.jpg b/public/people/BALYAL.jpg new file mode 100644 index 0000000..3403052 Binary files /dev/null and b/public/people/BALYAL.jpg differ diff --git a/public/people/BHTKP3.jpg b/public/people/BHTKP3.jpg new file mode 100644 index 0000000..944ba96 Binary files /dev/null and b/public/people/BHTKP3.jpg differ diff --git a/public/people/BUWU8Z.jpg b/public/people/BUWU8Z.jpg new file mode 100644 index 0000000..ea71b06 Binary files /dev/null and b/public/people/BUWU8Z.jpg differ diff --git a/public/people/CHHWUG.jpg b/public/people/CHHWUG.jpg new file mode 100644 index 0000000..be22942 Binary files /dev/null and b/public/people/CHHWUG.jpg differ diff --git a/public/people/CXEYFS.jpg b/public/people/CXEYFS.jpg new file mode 100644 index 0000000..7f4f546 Binary files /dev/null and b/public/people/CXEYFS.jpg differ diff --git a/public/people/D8UUB3.jpg b/public/people/D8UUB3.jpg new file mode 100644 index 0000000..d886b8a Binary files /dev/null and b/public/people/D8UUB3.jpg differ diff --git a/public/people/D9UMRR.jpg b/public/people/D9UMRR.jpg new file mode 100644 index 0000000..a826b21 Binary files /dev/null and b/public/people/D9UMRR.jpg differ diff --git a/public/people/E3XJKT.jpg b/public/people/E3XJKT.jpg new file mode 100644 index 0000000..e7975ef Binary files /dev/null and b/public/people/E3XJKT.jpg differ diff --git a/public/people/EAEYZM.jpg b/public/people/EAEYZM.jpg new file mode 100644 index 0000000..5e5d852 Binary files /dev/null and b/public/people/EAEYZM.jpg differ diff --git a/public/people/EKSXKG.jpg b/public/people/EKSXKG.jpg new file mode 100644 index 0000000..fc00a73 Binary files /dev/null and b/public/people/EKSXKG.jpg differ diff --git a/public/people/EXZMKL.jpg b/public/people/EXZMKL.jpg new file mode 100644 index 0000000..a561192 Binary files /dev/null and b/public/people/EXZMKL.jpg differ diff --git a/public/people/FB7A7U.jpg b/public/people/FB7A7U.jpg new file mode 100644 index 0000000..3046baa Binary files /dev/null and b/public/people/FB7A7U.jpg differ diff --git a/public/people/FM883L.jpg b/public/people/FM883L.jpg new file mode 100644 index 0000000..45aead3 Binary files /dev/null and b/public/people/FM883L.jpg differ diff --git a/public/people/GGBFN8.jpg b/public/people/GGBFN8.jpg new file mode 100644 index 0000000..2563270 Binary files /dev/null and b/public/people/GGBFN8.jpg differ diff --git a/public/people/H3M7XF.jpg b/public/people/H3M7XF.jpg new file mode 100644 index 0000000..2ea8e3a Binary files /dev/null and b/public/people/H3M7XF.jpg differ diff --git a/public/people/HU3WCT.jpg b/public/people/HU3WCT.jpg new file mode 100644 index 0000000..8ff70e2 Binary files /dev/null and b/public/people/HU3WCT.jpg differ diff --git a/public/people/HYXK8D.jpg b/public/people/HYXK8D.jpg new file mode 100644 index 0000000..cfe2cd3 Binary files /dev/null and b/public/people/HYXK8D.jpg differ diff --git a/public/people/JEXXZQ.jpg b/public/people/JEXXZQ.jpg new file mode 100644 index 0000000..65fe77d Binary files /dev/null and b/public/people/JEXXZQ.jpg differ diff --git a/public/people/JJFWEP.jpg b/public/people/JJFWEP.jpg new file mode 100644 index 0000000..ac6ff4a Binary files /dev/null and b/public/people/JJFWEP.jpg differ diff --git a/public/people/JRGRVG.jpg b/public/people/JRGRVG.jpg new file mode 100644 index 0000000..b7049ce Binary files /dev/null and b/public/people/JRGRVG.jpg differ diff --git a/public/people/JYUNEP.jpg b/public/people/JYUNEP.jpg new file mode 100644 index 0000000..a037240 Binary files /dev/null and b/public/people/JYUNEP.jpg differ diff --git a/public/people/KCADCR.jpg b/public/people/KCADCR.jpg new file mode 100644 index 0000000..91cf0e3 Binary files /dev/null and b/public/people/KCADCR.jpg differ diff --git a/public/people/KTZNUG.jpg b/public/people/KTZNUG.jpg new file mode 100644 index 0000000..8b35bfe Binary files /dev/null and b/public/people/KTZNUG.jpg differ diff --git a/public/people/LDFVBH.jpg b/public/people/LDFVBH.jpg new file mode 100644 index 0000000..d5ad241 Binary files /dev/null and b/public/people/LDFVBH.jpg differ diff --git a/public/people/LWZSTN.jpg b/public/people/LWZSTN.jpg new file mode 100644 index 0000000..e3f3773 Binary files /dev/null and b/public/people/LWZSTN.jpg differ diff --git a/public/people/MTGWEC.jpg b/public/people/MTGWEC.jpg new file mode 100644 index 0000000..ec8a5fd Binary files /dev/null and b/public/people/MTGWEC.jpg differ diff --git a/public/people/MY7QMZ.jpg b/public/people/MY7QMZ.jpg new file mode 100644 index 0000000..9a74b60 Binary files /dev/null and b/public/people/MY7QMZ.jpg differ diff --git a/public/people/N9ZZWG.jpg b/public/people/N9ZZWG.jpg new file mode 100644 index 0000000..cfb04fc Binary files /dev/null and b/public/people/N9ZZWG.jpg differ diff --git a/public/people/PFTMME.jpg b/public/people/PFTMME.jpg new file mode 100644 index 0000000..657c213 Binary files /dev/null and b/public/people/PFTMME.jpg differ diff --git a/public/people/PGYLJB.jpg b/public/people/PGYLJB.jpg new file mode 100644 index 0000000..3f6013a Binary files /dev/null and b/public/people/PGYLJB.jpg differ diff --git a/public/people/PZFRSS.jpg b/public/people/PZFRSS.jpg new file mode 100644 index 0000000..ee7ae72 Binary files /dev/null and b/public/people/PZFRSS.jpg differ diff --git a/public/people/QVZKDG.jpg b/public/people/QVZKDG.jpg new file mode 100644 index 0000000..5de1b03 Binary files /dev/null and b/public/people/QVZKDG.jpg differ diff --git a/public/people/QWCHX7.jpg b/public/people/QWCHX7.jpg new file mode 100644 index 0000000..4b33d2e Binary files /dev/null and b/public/people/QWCHX7.jpg differ diff --git a/public/people/RDLWJ8.jpg b/public/people/RDLWJ8.jpg new file mode 100644 index 0000000..9f26254 Binary files /dev/null and b/public/people/RDLWJ8.jpg differ diff --git a/public/people/RRK8EN.jpg b/public/people/RRK8EN.jpg new file mode 100644 index 0000000..e77ec16 Binary files /dev/null and b/public/people/RRK8EN.jpg differ diff --git a/public/people/RSUKRU.jpg b/public/people/RSUKRU.jpg new file mode 100644 index 0000000..1a8dc70 Binary files /dev/null and b/public/people/RSUKRU.jpg differ diff --git a/public/people/RTG9TS.jpg b/public/people/RTG9TS.jpg new file mode 100644 index 0000000..2de9ec2 Binary files /dev/null and b/public/people/RTG9TS.jpg differ diff --git a/public/people/RXNL8L.jpg b/public/people/RXNL8L.jpg new file mode 100644 index 0000000..3fa6276 Binary files /dev/null and b/public/people/RXNL8L.jpg differ diff --git a/public/people/TDZSSC.jpg b/public/people/TDZSSC.jpg new file mode 100644 index 0000000..4315627 Binary files /dev/null and b/public/people/TDZSSC.jpg differ diff --git a/public/people/TQKR8P.jpg b/public/people/TQKR8P.jpg new file mode 100644 index 0000000..74ac11c Binary files /dev/null and b/public/people/TQKR8P.jpg differ diff --git a/public/people/UJJAJF.jpg b/public/people/UJJAJF.jpg new file mode 100644 index 0000000..6c3cc0d Binary files /dev/null and b/public/people/UJJAJF.jpg differ diff --git a/public/people/VXBVLZ.jpg b/public/people/VXBVLZ.jpg new file mode 100644 index 0000000..52ac245 Binary files /dev/null and b/public/people/VXBVLZ.jpg differ diff --git a/public/people/VZTVRY.jpg b/public/people/VZTVRY.jpg new file mode 100644 index 0000000..1760e8e Binary files /dev/null and b/public/people/VZTVRY.jpg differ diff --git a/public/people/WLRBE3.jpg b/public/people/WLRBE3.jpg new file mode 100644 index 0000000..ee79b09 Binary files /dev/null and b/public/people/WLRBE3.jpg differ diff --git a/public/people/WXXHQL.jpg b/public/people/WXXHQL.jpg new file mode 100644 index 0000000..32caa15 Binary files /dev/null and b/public/people/WXXHQL.jpg differ diff --git a/public/people/WZK8XF.jpg b/public/people/WZK8XF.jpg new file mode 100644 index 0000000..86adc80 Binary files /dev/null and b/public/people/WZK8XF.jpg differ diff --git a/public/people/XDM3GY.jpg b/public/people/XDM3GY.jpg new file mode 100644 index 0000000..0aceb0e Binary files /dev/null and b/public/people/XDM3GY.jpg differ diff --git a/public/people/XLYVCH.jpg b/public/people/XLYVCH.jpg new file mode 100644 index 0000000..b410366 Binary files /dev/null and b/public/people/XLYVCH.jpg differ diff --git a/public/people/XWWMQL.jpg b/public/people/XWWMQL.jpg new file mode 100644 index 0000000..2705bf3 Binary files /dev/null and b/public/people/XWWMQL.jpg differ diff --git a/public/people/XZ9GLY.jpg b/public/people/XZ9GLY.jpg new file mode 100644 index 0000000..5223677 Binary files /dev/null and b/public/people/XZ9GLY.jpg differ diff --git a/public/people/YCFJET.jpg b/public/people/YCFJET.jpg new file mode 100644 index 0000000..03170cd Binary files /dev/null and b/public/people/YCFJET.jpg differ diff --git a/public/people/YEJTFV.jpg b/public/people/YEJTFV.jpg new file mode 100644 index 0000000..e592014 Binary files /dev/null and b/public/people/YEJTFV.jpg differ diff --git a/public/people/ZPQUMD.jpg b/public/people/ZPQUMD.jpg new file mode 100644 index 0000000..2e42f5b Binary files /dev/null and b/public/people/ZPQUMD.jpg differ diff --git a/public/people/ZY7KJB.jpg b/public/people/ZY7KJB.jpg new file mode 100644 index 0000000..8e203f5 Binary files /dev/null and b/public/people/ZY7KJB.jpg differ diff --git a/public/people/ZZLBQC.jpg b/public/people/ZZLBQC.jpg new file mode 100644 index 0000000..477c8e8 Binary files /dev/null and b/public/people/ZZLBQC.jpg differ diff --git a/public/people/placeholder.jpg b/public/people/placeholder.jpg new file mode 100644 index 0000000..8140834 Binary files /dev/null and b/public/people/placeholder.jpg differ diff --git a/scripts/poetry.lock b/scripts/poetry.lock new file mode 100644 index 0000000..c08f70f --- /dev/null +++ b/scripts/poetry.lock @@ -0,0 +1,372 @@ +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. + +[[package]] +name = "bleach" +version = "6.0.0" +description = "An easy safelist-based HTML-sanitizing tool." +optional = false +python-versions = ">=3.7" +files = [ + {file = "bleach-6.0.0-py3-none-any.whl", hash = "sha256:33c16e3353dbd13028ab4799a0f89a83f113405c766e9c122df8a06f5b85b3f4"}, + {file = "bleach-6.0.0.tar.gz", hash = "sha256:1a1a85c1595e07d8db14c5f09f09e6433502c51c595970edc090551f0db99414"}, +] + +[package.dependencies] +six = ">=1.9.0" +webencodings = "*" + +[package.extras] +css = ["tinycss2 (>=1.1.0,<1.2)"] + +[[package]] +name = "certifi" +version = "2023.5.7" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"}, + {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.1.0" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, + {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, +] + +[[package]] +name = "idna" +version = "3.4" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] + +[[package]] +name = "markdown" +version = "3.4.3" +description = "Python implementation of John Gruber's Markdown." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Markdown-3.4.3-py3-none-any.whl", hash = "sha256:065fd4df22da73a625f14890dd77eb8040edcbd68794bcd35943be14490608b2"}, + {file = "Markdown-3.4.3.tar.gz", hash = "sha256:8bf101198e004dc93e84a12a7395e31aac6a9c9942848ae1d99b9d72cf9b3520"}, +] + +[package.extras] +testing = ["coverage", "pyyaml"] + +[[package]] +name = "parse" +version = "1.19.1" +description = "parse() is the opposite of format()" +optional = false +python-versions = "*" +files = [ + {file = "parse-1.19.1-py2.py3-none-any.whl", hash = "sha256:371ed3800dc63983832159cc9373156613947707bc448b5215473a219dbd4362"}, + {file = "parse-1.19.1.tar.gz", hash = "sha256:cc3a47236ff05da377617ddefa867b7ba983819c664e1afe46249e5b469be464"}, +] + +[[package]] +name = "pillow" +version = "9.5.0" +description = "Python Imaging Library (Fork)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "Pillow-9.5.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:ace6ca218308447b9077c14ea4ef381ba0b67ee78d64046b3f19cf4e1139ad16"}, + {file = "Pillow-9.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d3d403753c9d5adc04d4694d35cf0391f0f3d57c8e0030aac09d7678fa8030aa"}, + {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ba1b81ee69573fe7124881762bb4cd2e4b6ed9dd28c9c60a632902fe8db8b38"}, + {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe7e1c262d3392afcf5071df9afa574544f28eac825284596ac6db56e6d11062"}, + {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f36397bf3f7d7c6a3abdea815ecf6fd14e7fcd4418ab24bae01008d8d8ca15e"}, + {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:252a03f1bdddce077eff2354c3861bf437c892fb1832f75ce813ee94347aa9b5"}, + {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:85ec677246533e27770b0de5cf0f9d6e4ec0c212a1f89dfc941b64b21226009d"}, + {file = "Pillow-9.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b416f03d37d27290cb93597335a2f85ed446731200705b22bb927405320de903"}, + {file = "Pillow-9.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1781a624c229cb35a2ac31cc4a77e28cafc8900733a864870c49bfeedacd106a"}, + {file = "Pillow-9.5.0-cp310-cp310-win32.whl", hash = "sha256:8507eda3cd0608a1f94f58c64817e83ec12fa93a9436938b191b80d9e4c0fc44"}, + {file = "Pillow-9.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:d3c6b54e304c60c4181da1c9dadf83e4a54fd266a99c70ba646a9baa626819eb"}, + {file = "Pillow-9.5.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:7ec6f6ce99dab90b52da21cf0dc519e21095e332ff3b399a357c187b1a5eee32"}, + {file = "Pillow-9.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:560737e70cb9c6255d6dcba3de6578a9e2ec4b573659943a5e7e4af13f298f5c"}, + {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96e88745a55b88a7c64fa49bceff363a1a27d9a64e04019c2281049444a571e3"}, + {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d9c206c29b46cfd343ea7cdfe1232443072bbb270d6a46f59c259460db76779a"}, + {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cfcc2c53c06f2ccb8976fb5c71d448bdd0a07d26d8e07e321c103416444c7ad1"}, + {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:a0f9bb6c80e6efcde93ffc51256d5cfb2155ff8f78292f074f60f9e70b942d99"}, + {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8d935f924bbab8f0a9a28404422da8af4904e36d5c33fc6f677e4c4485515625"}, + {file = "Pillow-9.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fed1e1cf6a42577953abbe8e6cf2fe2f566daebde7c34724ec8803c4c0cda579"}, + {file = "Pillow-9.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c1170d6b195555644f0616fd6ed929dfcf6333b8675fcca044ae5ab110ded296"}, + {file = "Pillow-9.5.0-cp311-cp311-win32.whl", hash = "sha256:54f7102ad31a3de5666827526e248c3530b3a33539dbda27c6843d19d72644ec"}, + {file = "Pillow-9.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:cfa4561277f677ecf651e2b22dc43e8f5368b74a25a8f7d1d4a3a243e573f2d4"}, + {file = "Pillow-9.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:965e4a05ef364e7b973dd17fc765f42233415974d773e82144c9bbaaaea5d089"}, + {file = "Pillow-9.5.0-cp312-cp312-win32.whl", hash = "sha256:22baf0c3cf0c7f26e82d6e1adf118027afb325e703922c8dfc1d5d0156bb2eeb"}, + {file = "Pillow-9.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:432b975c009cf649420615388561c0ce7cc31ce9b2e374db659ee4f7d57a1f8b"}, + {file = "Pillow-9.5.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:5d4ebf8e1db4441a55c509c4baa7a0587a0210f7cd25fcfe74dbbce7a4bd1906"}, + {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:375f6e5ee9620a271acb6820b3d1e94ffa8e741c0601db4c0c4d3cb0a9c224bf"}, + {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99eb6cafb6ba90e436684e08dad8be1637efb71c4f2180ee6b8f940739406e78"}, + {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dfaaf10b6172697b9bceb9a3bd7b951819d1ca339a5ef294d1f1ac6d7f63270"}, + {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:763782b2e03e45e2c77d7779875f4432e25121ef002a41829d8868700d119392"}, + {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:35f6e77122a0c0762268216315bf239cf52b88865bba522999dc38f1c52b9b47"}, + {file = "Pillow-9.5.0-cp37-cp37m-win32.whl", hash = "sha256:aca1c196f407ec7cf04dcbb15d19a43c507a81f7ffc45b690899d6a76ac9fda7"}, + {file = "Pillow-9.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322724c0032af6692456cd6ed554bb85f8149214d97398bb80613b04e33769f6"}, + {file = "Pillow-9.5.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:a0aa9417994d91301056f3d0038af1199eb7adc86e646a36b9e050b06f526597"}, + {file = "Pillow-9.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f8286396b351785801a976b1e85ea88e937712ee2c3ac653710a4a57a8da5d9c"}, + {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c830a02caeb789633863b466b9de10c015bded434deb3ec87c768e53752ad22a"}, + {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fbd359831c1657d69bb81f0db962905ee05e5e9451913b18b831febfe0519082"}, + {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8fc330c3370a81bbf3f88557097d1ea26cd8b019d6433aa59f71195f5ddebbf"}, + {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:7002d0797a3e4193c7cdee3198d7c14f92c0836d6b4a3f3046a64bd1ce8df2bf"}, + {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:229e2c79c00e85989a34b5981a2b67aa079fd08c903f0aaead522a1d68d79e51"}, + {file = "Pillow-9.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9adf58f5d64e474bed00d69bcd86ec4bcaa4123bfa70a65ce72e424bfb88ed96"}, + {file = "Pillow-9.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:662da1f3f89a302cc22faa9f14a262c2e3951f9dbc9617609a47521c69dd9f8f"}, + {file = "Pillow-9.5.0-cp38-cp38-win32.whl", hash = "sha256:6608ff3bf781eee0cd14d0901a2b9cc3d3834516532e3bd673a0a204dc8615fc"}, + {file = "Pillow-9.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:e49eb4e95ff6fd7c0c402508894b1ef0e01b99a44320ba7d8ecbabefddcc5569"}, + {file = "Pillow-9.5.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:482877592e927fd263028c105b36272398e3e1be3269efda09f6ba21fd83ec66"}, + {file = "Pillow-9.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3ded42b9ad70e5f1754fb7c2e2d6465a9c842e41d178f262e08b8c85ed8a1d8e"}, + {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c446d2245ba29820d405315083d55299a796695d747efceb5717a8b450324115"}, + {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8aca1152d93dcc27dc55395604dcfc55bed5f25ef4c98716a928bacba90d33a3"}, + {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:608488bdcbdb4ba7837461442b90ea6f3079397ddc968c31265c1e056964f1ef"}, + {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:60037a8db8750e474af7ffc9faa9b5859e6c6d0a50e55c45576bf28be7419705"}, + {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:07999f5834bdc404c442146942a2ecadd1cb6292f5229f4ed3b31e0a108746b1"}, + {file = "Pillow-9.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a127ae76092974abfbfa38ca2d12cbeddcdeac0fb71f9627cc1135bedaf9d51a"}, + {file = "Pillow-9.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:489f8389261e5ed43ac8ff7b453162af39c3e8abd730af8363587ba64bb2e865"}, + {file = "Pillow-9.5.0-cp39-cp39-win32.whl", hash = "sha256:9b1af95c3a967bf1da94f253e56b6286b50af23392a886720f563c547e48e964"}, + {file = "Pillow-9.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:77165c4a5e7d5a284f10a6efaa39a0ae8ba839da344f20b111d62cc932fa4e5d"}, + {file = "Pillow-9.5.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:833b86a98e0ede388fa29363159c9b1a294b0905b5128baf01db683672f230f5"}, + {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aaf305d6d40bd9632198c766fb64f0c1a83ca5b667f16c1e79e1661ab5060140"}, + {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0852ddb76d85f127c135b6dd1f0bb88dbb9ee990d2cd9aa9e28526c93e794fba"}, + {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:91ec6fe47b5eb5a9968c79ad9ed78c342b1f97a091677ba0e012701add857829"}, + {file = "Pillow-9.5.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cb841572862f629b99725ebaec3287fc6d275be9b14443ea746c1dd325053cbd"}, + {file = "Pillow-9.5.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c380b27d041209b849ed246b111b7c166ba36d7933ec6e41175fd15ab9eb1572"}, + {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c9af5a3b406a50e313467e3565fc99929717f780164fe6fbb7704edba0cebbe"}, + {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5671583eab84af046a397d6d0ba25343c00cd50bce03787948e0fff01d4fd9b1"}, + {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:84a6f19ce086c1bf894644b43cd129702f781ba5751ca8572f08aa40ef0ab7b7"}, + {file = "Pillow-9.5.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1e7723bd90ef94eda669a3c2c19d549874dd5badaeefabefd26053304abe5799"}, + {file = "Pillow-9.5.0.tar.gz", hash = "sha256:bf548479d336726d7a0eceb6e767e179fbde37833ae42794602631a070d630f1"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "ruamel-yaml" +version = "0.17.32" +description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" +optional = false +python-versions = ">=3" +files = [ + {file = "ruamel.yaml-0.17.32-py3-none-any.whl", hash = "sha256:23cd2ed620231677564646b0c6a89d138b6822a0d78656df7abda5879ec4f447"}, + {file = "ruamel.yaml-0.17.32.tar.gz", hash = "sha256:ec939063761914e14542972a5cba6d33c23b0859ab6342f61cf070cfc600efc2"}, +] + +[package.dependencies] +"ruamel.yaml.clib" = {version = ">=0.2.7", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.12\""} + +[package.extras] +docs = ["ryd"] +jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] + +[[package]] +name = "ruamel-yaml-clib" +version = "0.2.7" +description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" +optional = false +python-versions = ">=3.5" +files = [ + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5859983f26d8cd7bb5c287ef452e8aacc86501487634573d260968f753e1d71"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:debc87a9516b237d0466a711b18b6ebeb17ba9f391eb7f91c649c5c4ec5006c7"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:df5828871e6648db72d1c19b4bd24819b80a755c4541d3409f0f7acd0f335c80"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:efa08d63ef03d079dcae1dfe334f6c8847ba8b645d08df286358b1f5293d24ab"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win32.whl", hash = "sha256:763d65baa3b952479c4e972669f679fe490eee058d5aa85da483ebae2009d231"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:d000f258cf42fec2b1bbf2863c61d7b8918d31ffee905da62dede869254d3b8a"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:045e0626baf1c52e5527bd5db361bc83180faaba2ff586e763d3d5982a876a9e"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:1a6391a7cabb7641c32517539ca42cf84b87b667bad38b78d4d42dd23e957c81"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:9c7617df90c1365638916b98cdd9be833d31d337dbcd722485597b43c4a215bf"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:41d0f1fa4c6830176eef5b276af04c89320ea616655d01327d5ce65e50575c94"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win32.whl", hash = "sha256:f6d3d39611ac2e4f62c3128a9eed45f19a6608670c5a2f4f07f24e8de3441d38"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:da538167284de58a52109a9b89b8f6a53ff8437dd6dc26d33b57bf6699153122"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4b3a93bb9bc662fc1f99c5c3ea8e623d8b23ad22f861eb6fce9377ac07ad6072"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_12_0_arm64.whl", hash = "sha256:a234a20ae07e8469da311e182e70ef6b199d0fbeb6c6cc2901204dd87fb867e8"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:15910ef4f3e537eea7fe45f8a5d19997479940d9196f357152a09031c5be59f3"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:370445fd795706fd291ab00c9df38a0caed0f17a6fb46b0f607668ecb16ce763"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-win32.whl", hash = "sha256:ecdf1a604009bd35c674b9225a8fa609e0282d9b896c03dd441a91e5f53b534e"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-win_amd64.whl", hash = "sha256:f34019dced51047d6f70cb9383b2ae2853b7fc4dce65129a5acd49f4f9256646"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2aa261c29a5545adfef9296b7e33941f46aa5bbd21164228e833412af4c9c75f"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f01da5790e95815eb5a8a138508c01c758e5f5bc0ce4286c4f7028b8dd7ac3d0"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:40d030e2329ce5286d6b231b8726959ebbe0404c92f0a578c0e2482182e38282"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c3ca1fbba4ae962521e5eb66d72998b51f0f4d0f608d3c0347a48e1af262efa7"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-win32.whl", hash = "sha256:7bdb4c06b063f6fd55e472e201317a3bb6cdeeee5d5a38512ea5c01e1acbdd93"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:be2a7ad8fd8f7442b24323d24ba0b56c51219513cfa45b9ada3b87b76c374d4b"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:91a789b4aa0097b78c93e3dc4b40040ba55bef518f84a40d4442f713b4094acb"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:99e77daab5d13a48a4054803d052ff40780278240a902b880dd37a51ba01a307"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:3243f48ecd450eddadc2d11b5feb08aca941b5cd98c9b1db14b2fd128be8c697"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:8831a2cedcd0f0927f788c5bdf6567d9dc9cc235646a434986a852af1cb54b4b"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-win32.whl", hash = "sha256:3110a99e0f94a4a3470ff67fc20d3f96c25b13d24c6980ff841e82bafe827cac"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:92460ce908546ab69770b2e576e4f99fbb4ce6ab4b245345a3869a0a0410488f"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5bc0667c1eb8f83a3752b71b9c4ba55ef7c7058ae57022dd9b29065186a113d9"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:4a4d8d417868d68b979076a9be6a38c676eca060785abaa6709c7b31593c35d1"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bf9a6bc4a0221538b1a7de3ed7bca4c93c02346853f44e1cd764be0023cd3640"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a7b301ff08055d73223058b5c46c55638917f04d21577c95e00e0c4d79201a6b"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-win32.whl", hash = "sha256:d5e51e2901ec2366b79f16c2299a03e74ba4531ddcfacc1416639c557aef0ad8"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:184faeaec61dbaa3cace407cffc5819f7b977e75360e8d5ca19461cd851a5fc5"}, + {file = "ruamel.yaml.clib-0.2.7.tar.gz", hash = "sha256:1f08fd5a2bea9c4180db71678e850b995d2a5f4537be0e94557668cf0f5f9497"}, +] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "urllib3" +version = "2.0.3" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.7" +files = [ + {file = "urllib3-2.0.3-py3-none-any.whl", hash = "sha256:48e7fafa40319d358848e1bc6809b208340fafe2096f1725d05d67443d0483d1"}, + {file = "urllib3-2.0.3.tar.gz", hash = "sha256:bee28b5e56addb8226c96f7f13ac28cb4c301dd5ea8a6ca179c0b9835e032825"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "webencodings" +version = "0.5.1" +description = "Character encoding aliases for legacy web content" +optional = false +python-versions = "*" +files = [ + {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, + {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.11" +content-hash = "56a5423156c3b8e516c17a8f3b672f5d9e1feab856b7c15b5842eb97ccd332e2" diff --git a/scripts/pyproject.toml b/scripts/pyproject.toml new file mode 100644 index 0000000..d74d11c --- /dev/null +++ b/scripts/pyproject.toml @@ -0,0 +1,20 @@ +[tool.poetry] +name = "schedule-sync" +version = "0.1.0" +description = "" +authors = ["Daisy Leigh Brenecki "] + +[tool.poetry.dependencies] +python = "^3.11" +requests = "^2.31.0" +"ruamel.yaml" = "^0.17.32" +python-dateutil = "^2.8.2" +parse = "^1.19.1" +Markdown = "^3.4.3" +bleach = "^6.0.0" +pillow = "^9.5.0" + + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/scripts/schedule_sync.py b/scripts/schedule_sync.py new file mode 100644 index 0000000..395262c --- /dev/null +++ b/scripts/schedule_sync.py @@ -0,0 +1,254 @@ +import os +import os.path +import pathlib +from datetime import timedelta +from os import environ +from pprint import pprint + +import bleach +import dateutil.parser +import dateutil.tz +import requests +from markdown import Markdown +from parse import parse +from ruamel.yaml import YAML + +PRETALX_TOKEN = environ["PRETALX_TOKEN"] +AEST = dateutil.tz.gettz("Australia/Melbourne") +CONTENT_DIR = pathlib.Path("../src/content") +SESSIONS_DIR = CONTENT_DIR / "sessions" +PEOPLE_DIR = CONTENT_DIR / "people" +PUBLIC_DIR = pathlib.Path("../public") +PEOPLE_IMGS_DIR = PUBLIC_DIR / "people" + +TAG_IDS_TO_SKIP = {787} + +yaml = YAML() +md = Markdown() + + +def paginate(url): + next_url = url + while next_url: + res = requests.get( + next_url, + headers={"Authorization": f"Token {PRETALX_TOKEN}"}, + ) + res.raise_for_status() + data = res.json() + next_url = data["next"] + yield from data["results"] + + +def parse_markdown(text): + html = md.convert(text) + return bleach.clean( + html, + tags=( + "a", + "abbr", + "acronym", + "b", + "blockquote", + "code", + "em", + "i", + "li", + "ol", + "strong", + "ul", + "p", + "h2", + "h3", + "s", + "del", + "ins", + ), + ) + + +rooms = { + "Backup Speakers": 0, + "Curlyboi Theatre": 1, + "Platypus Hall": 2, + "Science, Data & Analytics": 1, + "DevOops": 2, + "Education": 3, + "Snakeoil Academy (Security & Privacy)": 4, +} + +tracks = { + "Our Connected Universe": "ocu", + "All Things Data!": "data", + "Education": "education", + "DjangoCon AU": "djangocon", + "Main Conference": None, +} + +answers = { + "Presentation Format": 853, + "Content Warning": 2459, + "Pronouns": 2461, + "Twitter": 2455, + "Fedi": 2506, +} + +format_answer = { + 1062: "L", # live + 1063: "P", # prerecord +} + +seen_speakers = set() + +yt_resp = requests.get( + "https://portal.nextdayvideo.com.au/main/C/pyconau/S/pyconau_2021.json" +) +yt_resp.raise_for_status() +youtube_slugs = { + x["conf_key"]: x["host_url"].rsplit("/", 1)[1] + for x in yt_resp.json() + if x["host_url"] is not None +} + +for entry in SESSIONS_DIR.glob("*"): + entry.unlink() + + +for session in paginate( + "https://pretalx.com/api/events/pyconau-2023/submissions/?state=confirmed&questions=2459" +): + # Do not schedule backups + # TODO manually add backups if they are unscheduled after the event. + # if rooms[session["slot"]["room"]["en"]] == 0: + # print("not scheduling backup") + # continue + print(session["code"]) + + if TAG_IDS_TO_SKIP.intersection(session["tag_ids"]): + print("skipping due to tag id") + continue + + speakers = [x["code"] for x in session["speakers"]] + seen_speakers.update(speakers) + with (SESSIONS_DIR / f'{session["code"]}.yml').open("w") as f: + # start = dateutil.parser.isoparse(session["slot"]["start"]).astimezone(AEST) + # end = dateutil.parser.isoparse(session["slot"]["end"]).astimezone(AEST) + # type_answer_id = format_answer[next( + # x["options"][0]["id"] for x in session["answers"] if x["question"]["id"] == answers["Presentation Format"] + # )] + cw = next( + ( + x["answer"] + for x in session["answers"] + if x["question"]["id"] == answers["Content Warning"] + ), + None, + ) + twitter = next( + ( + x["answer"] + for x in session["answers"] + if x["question"]["id"] == answers["Twitter"] + ), + None, + ) + fedi = next( + ( + x["answer"] + for x in session["answers"] + if x["question"]["id"] == answers["Fedi"] + ), + None, + ) + yaml.dump( + { + "title": session["title"], + # "start": start, + # "end": end, + # "room": rooms[session["slot"]["room"]["en"]], + # "track": tracks[session["track"]["en"]], + # "type": type_answer_id, + "abstract": parse_markdown(session["abstract"]), + "description": parse_markdown(session["description"]), + "code": session["code"], + "speakers": speakers, + "cw": parse_markdown(cw) if cw is not None else None, + "youtube_slug": youtube_slugs.get(session["code"]), + }, + f, + ) + +from io import BytesIO + +from PIL import Image + +with (PEOPLE_DIR / "_etags.yml").open("r") as f: + etags = yaml.load(f) + +# etags none? ensure empty +if not etags: + etags = {} + +for speaker in paginate( + "https://pretalx.com/api/events/pyconau-2023/speakers/?questions=2461,2455,2506" +): + if speaker["code"] not in seen_speakers: + continue + has_pic = False + try: + if speaker["avatar"] is not None: + etag = etags.get(speaker["code"], None) + print(speaker["avatar"]) + avatar_resp = requests.get( + speaker["avatar"], + headers={"If-None-Match": etag} if etag is not None else {}, + ) + if avatar_resp.status_code == 304: + print("ETag match") + continue + avatar_resp.raise_for_status() + if "ETag" in avatar_resp.headers: + etags[speaker["code"]] = avatar_resp.headers["ETag"] + im = Image.open(BytesIO(avatar_resp.content)) + im = im.convert("RGB") + im.thumbnail((128, 128)) + im.save(str(PEOPLE_IMGS_DIR / f'{speaker["code"]}.jpg')) + has_pic = True + except Exception as e: + print(speaker["code"], speaker["avatar"], e) + with (PEOPLE_DIR / f'{speaker["code"]}.yml').open("w") as f: + yaml.dump( + { + "name": speaker["name"], + "pronouns": next( + ( + x["answer"] + for x in speaker["answers"] + if x["question"]["id"] == answers["Pronouns"] + ), + None, + ), + "twitter": next( + ( + x["answer"] + for x in speaker["answers"] + if x["question"]["id"] == answers["Twitter"] + ), + None, + ), + "fedi": next( + ( + x["answer"] + for x in speaker["answers"] + if x["question"]["id"] == answers["Fedi"] + ), + None, + ), + "bio": parse_markdown(speaker["biography"] or ""), + "has_pic": has_pic, + }, + f, + ) + +with (PEOPLE_DIR / "_etags.yml").open("w") as f: + yaml.dump(etags, f) diff --git a/src/components/Profile.astro b/src/components/Profile.astro new file mode 100644 index 0000000..e5489a9 --- /dev/null +++ b/src/components/Profile.astro @@ -0,0 +1,60 @@ +--- +import type { CollectionEntry } from "astro:content" +export type Props = { + person: CollectionEntry<"people"> + bio: boolean +} +const { person, bio } = Astro.props as Props +const photo = person.data.has_pic + ? `/people/${person.id}.jpg` + : "/people/placeholder.jpg" +--- + + + +
+ + +
+ {person.data.name} + { + person.data.pronouns && ( + + {[person.data.pronouns, person.data.fedi, person.data.twitter] + .filter((x) => !!x) + .join(" • ")} + + ) + } + {bio && person.data.bio && } +
+
diff --git a/src/components/ProseList.astro b/src/components/ProseList.astro new file mode 100644 index 0000000..96633cc --- /dev/null +++ b/src/components/ProseList.astro @@ -0,0 +1,23 @@ +--- +export type Props = { + items: any[] +} +let { items } = Astro.props as Props +--- + +{ + items.length === 1 ? ( + items[0] + ) : items.length === 2 ? ( + <> + {items[0]} and {items[1]} + + ) : ( + <> + {items.slice(0, items.length - 2).map((item) => ( + <>{item}, + ))}{" "} + and {items[items.length - 1]} + + ) +} diff --git a/src/content/config.ts b/src/content/config.ts index b4610fb..189ec46 100644 --- a/src/content/config.ts +++ b/src/content/config.ts @@ -11,8 +11,33 @@ const sponsors = defineCollection({ const pages = defineCollection({ schema: z.object({ title: z.string(), order: z.number().optional() }), }) +const sessions = defineCollection({ + schema: z.object({ + title: z.string(), + abstract: z.string(), + description: z.string(), + code: z.string(), + speakers: z.array(z.string()), + cw: z.string().nullable(), + youtube_slug: z.string().nullable(), + }), + type: "data", +}) +const people = defineCollection({ + schema: z.object({ + name: z.string(), + pronouns: z.string().nullable(), + bio: z.string(), + has_pic: z.boolean(), + twitter: z.string().nullable().optional(), + fedi: z.string().nullable().optional(), + }), + type: "data", +}) export const collections = { sponsors, pages, + sessions, + people, } diff --git a/src/content/people/_etags.yml b/src/content/people/_etags.yml new file mode 100644 index 0000000..ac2064f --- /dev/null +++ b/src/content/people/_etags.yml @@ -0,0 +1,51 @@ +BUWU8Z: '"601d2ea6-496852"' +XDM3GY: '"6458e8fc-3a80"' +JRGRVG: '"64618736-399e3"' +JJFWEP: '"645d94f9-61e8"' +E3XJKT: '"640e7900-26d2e"' +9SG3KG: '"61beed09-1c664"' +RTG9TS: '"6231393d-de67"' +VXBVLZ: '"609b2b68-19c61"' +H3M7XF: '"644a0cce-da327"' +9JGCPM: '"601d2e9a-25ce5"' +UJJAJF: '"63a3afa2-24767"' +XLYVCH: '"646429c3-34dfc"' +FB7A7U: '"64375714-342ff"' +3C7EAA: '"643f3ff0-1c478"' +BA8DVU: '"6440913a-f9d4"' +PZFRSS: '"63f56c99-33eb7"' +TDZSSC: '"6445d80e-1502a"' +HYXK8D: '"60bec3da-1807b"' +ZZLBQC: '"63913a22-1b681"' +VZTVRY: '"645313a4-3be6"' +YCFJET: '"645747e7-656c0"' +JEXXZQ: '"64599e59-15011"' +JYUNEP: '"64599e95-35981"' +EXZMKL: '"61bac512-61499"' +PGYLJB: '"6462da08-ae8b"' +EAEYZM: '"6397d16c-6e70"' +ZPQUMD: '"64062cde-2201fb"' +FM883L: '"61984bb6-5a9c5"' +QWCHX7: '"61a6cbcd-14ccd"' +MY7QMZ: '"601d2e91-14ca1"' +WXXHQL: '"648b6de0-24388"' +KCADCR: '"645ee420-2601c"' +RRK8EN: '"6460d291-7516"' +WZK8XF: '"6462d959-4f3b"' +PFTMME: '"6462d8a5-1d1e7"' +CXEYFS: '"6461ee14-ad971"' +RXNL8L: '"6462d94c-25ce3"' +YEJTFV: '"64620043-6b30"' +GGBFN8: '"6417b3ec-1ecf3"' +TQKR8P: '"646429c3-2390a"' +D9UMRR: '"646429d8-2ccd2"' +MTGWEC: '"64634db5-1b14a"' +CHHWUG: '"64190532-9768"' +BALYAL: '"64657b70-16e4b"' +WLRBE3: '"6477f0b1-5ceaf"' +XZ9GLY: '"641661c3-153f2"' +QVZKDG: '"6462d8d7-58d5d"' +XWWMQL: '"6462d917-4c765"' +RSUKRU: '"616b7858-8afa"' +D8UUB3: '"64375779-15eb9"' +RDLWJ8: '"649bd471-278bd"' diff --git a/src/content/sessions/8BT9NT.yml b/src/content/sessions/8BT9NT.yml new file mode 100644 index 0000000..3508aea --- /dev/null +++ b/src/content/sessions/8BT9NT.yml @@ -0,0 +1,14 @@ +title: Rust for the Python dev +abstract:

An overview of the growing number of Rust built tools in the Python ecosystem + and how you can integrate Rust and Python yourself

+description:

Rust is a popular systems programming language that both complements + the strengths of and integrates well with Python. Increasingly Rust built tools + such as Ruff, Polars, and Pydantic V2 are becoming prominent in the Python ecosystem. + This talk with give a quick introduction to Rust for the Python developer - covering + some language concepts, learning resources, and quick examples of how you can quickly + integrate the two programming languages yourself.

+code: 8BT9NT +speakers: +- D8UUB3 +cw: +youtube_slug: diff --git a/src/content/sessions/BG9EMX.yml b/src/content/sessions/BG9EMX.yml new file mode 100644 index 0000000..0c7806d --- /dev/null +++ b/src/content/sessions/BG9EMX.yml @@ -0,0 +1,13 @@ +title: JavaScript classes for the Python Programmer +abstract:

Learn how to get the most out of JavaScript classes, exploring how their + implementation differs from Python classes, and why.

+description: "

No matter how you feel about it, in the web today Javascript is unavoidable.

\n +

ECMAScript 2015 (ES6) introduced a lot of new syntax and features, and one of\n + these was classes.

\n

However, there's a world of differences between how Python + and JavaScript\napproach this idea.

\n

Come along and learn how class construction + works, how it's implemented, and how\nyou can use it to best effect.

" +code: BG9EMX +speakers: +- VZTVRY +cw: +youtube_slug: diff --git a/src/content/sessions/BX9VRB.yml b/src/content/sessions/BX9VRB.yml new file mode 100644 index 0000000..9fd9a5f --- /dev/null +++ b/src/content/sessions/BX9VRB.yml @@ -0,0 +1,25 @@ +title: Zero or Hero? - Assessing Pygame Zero in the classroom +abstract:

Kids want to code games and I need them to learn the fundamental data + structures and how to make a user interface. Pygame Zero seems like a gift - the + UI power of pygame with a simpler format and an implied main loop. In truth there + have been ups and downs in the journey implementing Pygame Zero into the Middle + and Senior school classroom and I want to show you some of the promise and the pitfalls.

+description: "

I've just discovered that Pygame Zero is a thing. I have spent years + fighting with Pygame and Kivy and to a lesser extent AppJar; Graphical User Interfaces + are really hard. So when I found there was a clean, easy way to make games with + Python using Pygame Zero I was ecstatic. I found it really easy to read and immediately + implemented it into my classes. It didn't go exactly to plan. It turns out that + there are two ways to learn stuff - one is to trust the teacher and learn by rote + where the code should fit and the other is to break it down and synthesise it and + understand where things should go. Turns out the latter is harder than I anticipated. + \nI think that teachers and education fans will be interested to hear my story. + They can see what my dream was and how it compares with the reality. \nI have hope + that Pygame Zero is going to serve a purpose as a stepping stone between text based + Python and stuff that involves User Interface and I have ideas about how to do things + better but maybe I can help others to avoid some of the problems I faced on the + way.

" +code: BX9VRB +speakers: +- HYXK8D +cw: +youtube_slug: diff --git a/src/content/sessions/C3HYLF.yml b/src/content/sessions/C3HYLF.yml new file mode 100644 index 0000000..14504bc --- /dev/null +++ b/src/content/sessions/C3HYLF.yml @@ -0,0 +1,20 @@ +title: 'Proactive Ops: Event Driven IT Operations' +abstract:

Traditional IT operations is overwhelmingly reactive - humans respond + to incidents and tickets. There is so much noise! Alerts, tickets, audits, chat + threads. What if ops could catch the small things before they turn into big problems? + What if we could use events and serverless to remediate issues?

+description: "

Engineering teams are adopting event driven architectures with herds + of serverless microservices. Why can’t Ops play buzzword bingo too?

\n

Most + significant issues in productions start off as small problems that are overlooked + or ignored. These small problems are usually can be captured via events. Those events + can be routed to handlers than can react and remediate the issues.

\n

During + this session we will explore what “proactive ops” platform can look like. Areas + covered in this session will include capturing events from SaaS products, event + routing, building reusable composable components, and the different approaches to + deal with policy violations. By then end of session an attendee should be able to + start building their own serverless, event driven, proactive ops platform.

" +code: C3HYLF +speakers: +- EKSXKG +cw: +youtube_slug: diff --git a/src/content/sessions/D9TMCM.yml b/src/content/sessions/D9TMCM.yml new file mode 100644 index 0000000..e61d1a1 --- /dev/null +++ b/src/content/sessions/D9TMCM.yml @@ -0,0 +1,17 @@ +title: How to build a unit testing library from scratch? +abstract: "

Have you ever used Pytest? Have you ever wondered what happens when + you run pytest over your tests folder, create parametrized test cases, or use fixtures?

\n +

In this talk, we will find answers to all these by building our own testing library.\n + By the end of this talk, you will have a solid understanding of reverse engineering + and how internals of a testing library can be designed

" +description: "

This talk will explore how to build a testing library from scratch. +

\n
    \n
  1. Introduction to Pytest and its features - 5 mins
  2. \n
  3. Building + Test runners - 5 mins
  4. \n
  5. Building a parametrized test case handler - 8 mins
  6. \n +
  7. Building a fixture handler - 8 mins
  8. \n
  9. End note - 5 mins
  10. \n
\n +

By the end of this talk, you will have a solid understanding of reverse engineering + and building a testing library from scratch.

" +code: D9TMCM +speakers: +- 9SG3KG +cw: +youtube_slug: diff --git a/src/content/sessions/F3MAFZ.yml b/src/content/sessions/F3MAFZ.yml new file mode 100644 index 0000000..39f9811 --- /dev/null +++ b/src/content/sessions/F3MAFZ.yml @@ -0,0 +1,22 @@ +title: "In the Long Run We're All Dead: An Economist's Guide to Tech Debt" +abstract:

Tech debt is a familiar concept in most organisations and has been the + subject of extensive discussion regarding individual & organisational factors. + However, what’s missing is a macro-economic analysis of why tech debt exists and + how to combat it. This talk provides that analysis.

+description: '

Technical debt is a much-bemoaned aspect of nearly every engineer’s + life. How and to what extent to eliminate it has been the subject of much discussion. + Is tech debt the result of individual engineers cutting corners? Are the engineers + who write this code just incompetent? Are there organisational factors that contribute? + If so, what are they? All of these are worthy of discussion, however, there is another + factor conspicuously missing from this discussion: macroeconomics, the dismal science. + Macroeconomic factors dictate organisational behaviour and have a cascading effect + on teams and individuals within organisations. In this talk, I discuss technical + debt in the context of the work of institutional economist Hyman Minsky, contextualising + tech debt as a form of operating debt organisations take on. Minsky’s theory on + this topic provides a compelling analysis of organisations’ borrowing behaviour, + and by extension, how tech debt works.

' +code: F3MAFZ +speakers: +- FB7A7U +cw: +youtube_slug: diff --git a/src/content/sessions/FHXB3Z.yml b/src/content/sessions/FHXB3Z.yml new file mode 100644 index 0000000..dd3e1bf --- /dev/null +++ b/src/content/sessions/FHXB3Z.yml @@ -0,0 +1,22 @@ +title: Are we singing sillier? +abstract:

Everyone has heard it from someone... "Music was better in my day". As + a parent of teenagers, I'm pretty sure I've even said it. But who's right? Which + decade's pop music is linguisitcally more interesting, and is there a trend? Using + Python and some text analysis I will attempt to answer these questions and more. + By the end of the talk all will be revealed... and we can happily sing along to + some pop songs safe in the knowledge that they are linguisitcally superior.

+description: "

I will use the time to break down the process of discovering the + answer to the question \"is pop music less linguistically complex these days\". + What questions did I come up with to drive my investigation? What language processing + did I do? How does it break down by genre? This is an interesting investigation + that has lots of examples that will encourage debate in the audience and hopefully + we'll take the arguments out into the next break. \nI will use Python and Pandas + and a couple of libraries to show the process of the language analysis of the lyrics + of the top songs each year since the 50s. By the end everyone will know what the + data shows about linguistic complexity of pop lyrics and will have had some fun + along the way.

" +code: FHXB3Z +speakers: +- HYXK8D +cw: +youtube_slug: diff --git a/src/content/sessions/GPEJFD.yml b/src/content/sessions/GPEJFD.yml new file mode 100644 index 0000000..31a4265 --- /dev/null +++ b/src/content/sessions/GPEJFD.yml @@ -0,0 +1,46 @@ +title: 'Demystifying Python AsyncIO: A Real-World Approach' +abstract: "

Maybe it's just me, but I hate stupid examples. I hate reading about + OOP with animal examples as much as I hate reading about async with the client using + bare asyncio.sleep statements. Mostly because (considering you won't work for a + zoo 🤷‍♂️) these examples will never get any close to real life. I don't want to + start talking about the solution (i.e. async), I want you to feel the problem first, + I want you to run things locally from your own computer. So, in this talk, I want + then to explore async by using examples that you can run yourself and understand. + So, the plan is to learn:\n- What are sync and async processes with a real word + example\n- Where to use Sync and Async \n- Why and why not use Sync and Async\n + - Basic syntax and Usage of async in Python\n- Explore async with slow HTTP queries\n + - Explore async with slow Database queries\n- Share a real project running in production + that uses async

" +description: "

I noticed some people using the async syntax without knowing what + they were doing. First, they think async is parallel which is not true. Then they + write code that doesn't take any advantage of Python async. In other words, they + write sync code with async syntax. The goal of this talk is to point out these performance + issues and help you benefit the most from async code.

\n

🤔 When to use Python + Async

\n

Async only makes sense if you're doing IO. There's ZERO benefit in + using async to stuff like this that is CPU-bound. Your code might even get slower + by doing that due to the Event Loop. That's because Python async only optimizes + IDLE time!. IO-bound operations are related to reading/writing operations.\nA good + example would be:\n- Requesting some data from HTTP\n- Reading/Writing some json/txt + file\n- Reading data from a database

\n

👆 All these operations consist of waiting + for the data to be available.\nWhile the data is UNAVAILABLE the EVENT LOOP does + something else.\nThis is Concurrency.\nNOT Parallelism.

\n

So In this talk, + we will dive into the world of synchronous and asynchronous processes with real-world + examples that you can run on your own computer. We'll start by understanding the + difference between synchronous and asynchronous processes and where to use each + one. We'll explore the benefits and drawbacks of both sync and async processes to + help you make informed decisions in your own projects.

\n

We will then move + on to explore the basic syntax and usage of async in Python, including how to create + and run async functions. We will also discuss common pitfalls and best practices + for using async in your code.

\n

Next, we will take a deep dive into async + with slow HTTP queries and slow database queries, showing you how async can help + optimize your code and improve performance in these scenarios. We will provide real-world + examples that you can run yourself, so you can see the benefits of async firsthand.

\n +

Finally, we will share a real project running in production that uses async, + giving you a glimpse into how async can be used in a real-world scenario. By the + end of this talk, you'll have a solid understanding of async and how it can be used + to optimize your code and improve performance in a variety of scenarios.

" +code: GPEJFD +speakers: +- PZFRSS +cw: +youtube_slug: diff --git a/src/content/sessions/HJDPN9.yml b/src/content/sessions/HJDPN9.yml new file mode 100644 index 0000000..680a9b2 --- /dev/null +++ b/src/content/sessions/HJDPN9.yml @@ -0,0 +1,20 @@ +title: All the things I learnt as a junior developer (so you don't have to) +abstract: "

Being a junior developer is scary. But what should you do to make sure + your junior developer journey is productive? My talk will give you some career advice + that you can take, or pass to your juniors - through the lens of all the lessons + and mistakes I've done.

\n

(At least it'll be better than Googling the answer.)

" +description: "

Regardless from where you start - either as a newly-minted graduate + from a university, a person who finished as a bootcamp course, or self-taught - + starting out in this industry can be complex, confusing, and scary.

\n

However, + many juniors encounter the same set of common issues and pitfalls: how to level + up in this industry, how not to burn yourself out, and what should they be looking + for at a company. This talk will answer some of those common answers through all + the lessons, mistakes and regrets I made during my time as a junior developer.

\n +

This talk is for those who are starting out, knows someone who is starting out + and don't have all the answers, or just want to learn from someone's misadventures + in the tech industry.

" +code: HJDPN9 +speakers: +- TDZSSC +cw: +youtube_slug: diff --git a/src/content/sessions/K73VVW.yml b/src/content/sessions/K73VVW.yml new file mode 100644 index 0000000..6a36981 --- /dev/null +++ b/src/content/sessions/K73VVW.yml @@ -0,0 +1,13 @@ +title: The Python 3D Visualisation Landscape +abstract:

A survey of packages in the Python ecosystem for real-time 3D rendering + and data visualisation

+description:

This talk will give an overview of the ecosystem for real-time 3D + rendering packages in Python. It will talk to trade offs between higher and lower + level abstraction APIs, browser-based versus platform specific hardware rendering, + and different use cases for 3D rendering from desktop application views, Jupyter + and/or browser based views, and support for exporting 3D renders to other formats.

+code: K73VVW +speakers: +- D8UUB3 +cw: +youtube_slug: diff --git a/src/content/sessions/LYRGPG.yml b/src/content/sessions/LYRGPG.yml new file mode 100644 index 0000000..cf4e9a8 --- /dev/null +++ b/src/content/sessions/LYRGPG.yml @@ -0,0 +1,22 @@ +title: Simulating Cricket World Cup in Python +abstract: "

Cricket, with over two billion fanbases worldwide, is the second most + popular sport after soccer. Unfortunately, like other sporting events, cricket matches + were heavily affected during the Covid-19 pandemic. To compensate for the lack of + live cricket matches, the initial part of this project was done during the pandemic + to generate a fantasy T20 cricket match simulating events (runs, dots, fours, sixes, + wickets, etc.) based on the batter and bowler's career statistics.

\n

The work + has been further extended to simulate the entire Fifty Overs Cricket World Cup using + Python. As a part of the PyCon Fair Stall, I plan to share a poster detailing the + techniques used in the simulation, simulation results, and the potential application + of the work to predict the outcome of a cricket match. I also plan to live-stream + (scores only) a demo simulated cricket match, potentially the finals of the simulated + Fifty Overs Cricket World Cup.

" +description: "

The initial version of this simulation project was a part of the + poster presentation session during PyCon-US 2023. Please find the link to the poster + below.

\n

Poster: https://drive.google.com/file/d/18V94HgEttMQy1OGcPHE_3jCN31V6ydS2/view?usp=sharing\n + PyCon-2023 Listing: https://us.pycon.org/2023/schedule/posters/list/

" +code: LYRGPG +speakers: +- H3M7XF +cw: +youtube_slug: diff --git a/src/content/sessions/MHKHKK.yml b/src/content/sessions/MHKHKK.yml new file mode 100644 index 0000000..5e8a51c --- /dev/null +++ b/src/content/sessions/MHKHKK.yml @@ -0,0 +1,20 @@ +title: Diagnostics - Seeing Inside Your Application Without Logging +abstract: "

You know it as the fuel gauge in your car, the blinking lights on your + modem or the operational status page of your favourite cloud service. It's diagnostics! + A data efficient technique for seeing how well your system is running in real time.

\n +

What isn't so well known is that diagnostics can be embedded directly into your + python application. Doing it this way provides a purely on-demand and human-readable + interface of real-time system state and performance.

\n

Compared to a sequence + of log messages, diagnostics are certainly more difficult to implement. After all, + logging is essentially just some well-placed print statements, outputted to a file + or third-party logging agent.

\n

But this type of logging can be expensive, + bandwidth intensive and hard to make sense of. Have you ever had to trawl through + pages and pages of logs just to check your application is working well?

\n

In + this talk, you will learn a number of practical and pythonic techniques for serving + custom diagnostics from within your application.

" +description: '' +code: MHKHKK +speakers: +- JJFWEP +cw: +youtube_slug: diff --git a/src/content/sessions/PBBBMQ.yml b/src/content/sessions/PBBBMQ.yml new file mode 100644 index 0000000..e69de29 diff --git a/src/content/sessions/PUDUQQ.yml b/src/content/sessions/PUDUQQ.yml new file mode 100644 index 0000000..2438a0d --- /dev/null +++ b/src/content/sessions/PUDUQQ.yml @@ -0,0 +1,24 @@ +title: Maths Whimsy with Python +abstract:

The more whimsy the better. First, it's about having fun solving interesting + problems, and second it's about breaking projects down into manageable chunks and + harvesting useful results. Also Python.

+description: "

I've always enjoyed coding interesting maths and data problems, and + in the last few years I've done this many times over in the Python ecosystem. This + talk will highlight some projects, and also explore why I choose particular problems, + how I broke down the work into manageable chunks, and how I harvested useful results. + In the process, it will explore how to integrate play in your work.

\n

Project + highlights include weird gravity, atypical visualisations, solving puzzle toys, + graph processing in various domains, AI wheelie coaches, and more. I'll share the + mathematical basis, the Python libraries used and my experience with them in each + case. In sharing my approaches with the audience, I also hope to learn how I could + have solved these problems better!

\n

By reflecting on each project, I'll build + general considerations for what makes an \"interesting\" problem, strategies for + breaking down the work in order to see progress and create intermediate results, + and how to find practical applications for the outputs. I hope these considerations + will help the audience find ways to combine their own playful interests with their + work.

" +code: PUDUQQ +speakers: +- 3C7EAA +cw: +youtube_slug: diff --git a/src/content/sessions/RY9ZCY.yml b/src/content/sessions/RY9ZCY.yml new file mode 100644 index 0000000..3e4e5ce --- /dev/null +++ b/src/content/sessions/RY9ZCY.yml @@ -0,0 +1,21 @@ +title: Building 3D Trusted Data Pipelines With Dagster, Dbt, and Duckdb +abstract: "

This talk will demonstrate an example of building trusted data pipelines + with 3D packages: Dagster, Dbt, and Duckdb. First, it presents the importance of + testing data pipelines from high levels (like tables, relations, …) to low levels + (like rows and columns). It then discusses when and what we need to test. After + that, I will show how to implement these tests using different Dbt packages, including + dbt-audit-helper, dbt-utils, and dbt-expectations.

\n

Finally, a demo with + a complete ELT workflow will be presented. In this demo, Dagster is used as a data + pipeline orchestrator, and Dbt is utilized for data transformation with its related + testing packages. These transformed pipelines sit on top of Duckdb, which acts as + a small data warehouse. This demo is published in a GitHub repository, allowing + developers to clone and run the demo independently.

\n

The talk will help + data and analytics engineers build more robust tests for their data pipelines. These + trusted data pipelines could enhance the data quality and validation process, reducing + the risk of other data issues like data drift for downstream channels.

" +description: '' +code: RY9ZCY +speakers: +- BA8DVU +cw: +youtube_slug: diff --git a/src/content/sessions/WY9MES.yml b/src/content/sessions/WY9MES.yml new file mode 100644 index 0000000..ccad275 --- /dev/null +++ b/src/content/sessions/WY9MES.yml @@ -0,0 +1,37 @@ +title: Using Python and 19,200 bits/second serial links to manage antennae for the + Square Kilometre Array radio telescope in Australia +abstract:

The Australian half of the Square Kilometre Array radio telescope will + collect 7.2 Terabits/second of raw data from 131,072 antennae grouped into 512 'stations' + with 256 antennae each - but every antenna needs to be connected to a box within + a few metres of that antenna, for a DC power supply, and to convert the electrical + output to light over optical fibre before it degrades. This talk will describe those + boxes, and how they are being monitored and controlled using Python, a 40+ year + old communications protocol, and a network of 19,200 bits/second serial links.

+description: "

The Australian part of the Square Kilometre Array telescope will + have 512 stations in the Murchison region of WA, each a circle of steel mesh on + the ground with 256 two-metre tall 'Christmas Tree' antenna. Each station will also + have 24 'SMARTboxes' scattered in amongst the antennae, connected to a distribution + hub near the station. A SMARTbox needs to provide a little DC power to 10-12 antennae, + cut that power within a millisecond or so if there's a short, and convert the analogue + electrical signals from the antennae to analogue optical over fibre. It also needs + to allow remote, high-level telescope software to monitor the temperatures, voltages, + currents, etc, and switch antenna on and off.

\n

The problem is that the SKA + is so sensitive, any signal from space would be completely drowned out by the electrical + noise from a CPU, even a microcontroller, or any normal kind of communications cable + (wireless links are obviously COMPLETELY ruled out). The Power and Signal Distribution + system (PaSD) has been designed to use low-speed microcontrollers inside multiple + layers of shielding, communicating via the Modbus protocol over a custom-designed + multidrop serial bus. This multidrop bus links all 24 SMARTboxes in a station into + the same address space via 19,200 bits/second serial over the same coaxial cables + carrying 48V DC to the SMARTboxes. Python code running on a remote server can then + address each SMARTbox, manage power to each antenna, and even push new firmware + to the boxes.

\n

In this talk I will describe the PaSD system and its design + process, and how I used Python to create simulated SMARTboxes on a simulated multidrop + serial link, then used them to validate hardware and firmware prototypes over the + last few years. I'll also show live telemetry from a four-SMARTbox system that has + been running in the desert at the SKA site for the last year.

" +code: WY9MES +speakers: +- 9JGCPM +cw: +youtube_slug: diff --git a/src/pages/program/[sessionId].astro b/src/pages/program/[sessionId].astro new file mode 100644 index 0000000..25ef735 --- /dev/null +++ b/src/pages/program/[sessionId].astro @@ -0,0 +1,78 @@ +--- +import Profile from "../../components/Profile.astro" +import Base from "../../layouts/Base.astro" +import { getCollection, CollectionEntry, getEntry } from "astro:content" + +export async function getStaticPaths() { + const pages = await getCollection("sessions") + return pages.map((entry) => ({ + params: { sessionId: entry.id }, + props: { entry }, + })) +} +export type Props = { + entry: CollectionEntry<"sessions"> +} +const { entry } = Astro.props as Props +const speakers = ( + await Promise.all( + entry.data.speakers.map( + async (speakerId) => await getEntry("people", speakerId), + ), + ) +).filter(((x) => !!x) as (x: T | undefined) => x is T) +--- + + + { + /* +
+ {{ session.start.strftime('%a %B %d, %I:%M %p')}}–{{ + session.end.strftime('%I:%M %p') }} • + Back to program +
+ + + +{% endif %} + +{% if session.youtube_slug %} + +{% endif %} + +*/ + } +
+

{entry.data.title}

+ { + entry.data.cw && ( +
+ Content warning:{" "} + +
+ ) + } +
+ + {speakers.map((speaker) => )} +
+ { + /* +{% for person in session.speakers %} + {{ m.profile(person, bio=True) }} +{% endfor %} + +{% endblock %} +*/ + } + diff --git a/src/pages/program/index.astro b/src/pages/program/index.astro new file mode 100644 index 0000000..4e2ec0b --- /dev/null +++ b/src/pages/program/index.astro @@ -0,0 +1,37 @@ +--- +import ProseList from "../../components/ProseList.astro" +import Base from "../../layouts/Base.astro" +import { CollectionEntry, getCollection } from "astro:content" + +let sessions = await getCollection("sessions") +let speakers = new Map>( + (await getCollection("people")).map((entry) => [entry.id, entry]), +) +--- + + +
+

Program

+

+ Our full program is coming soon. In the meantime, here's a sneak + peek at some of the sessions you can expect to see at PyCon AU! +

+ +
+