diff --git a/.github/workflows/check_links.yml b/.github/workflows/check_links.yml index 5adb14c..a71d649 100644 --- a/.github/workflows/check_links.yml +++ b/.github/workflows/check_links.yml @@ -14,12 +14,12 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@v6 - name: Build documentation - run: uv run sphinx-build -nWaE docs build + run: uv run pyvec-docs build - name: Link Checker id: lychee uses: lycheeverse/lychee-action@v2 with: - args: _build + args: build fail: false - name: Create Issue From File if: steps.lychee.outputs.exit_code != 0 diff --git a/.github/workflows/generate.yml b/.github/workflows/generate.yml new file mode 100644 index 0000000..c0398b4 --- /dev/null +++ b/.github/workflows/generate.yml @@ -0,0 +1,31 @@ +name: Generate +on: + push: + branches: + - master + schedule: + - cron: "0 4 * * *" +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install uv + uses: astral-sh/setup-uv@v6 + - name: Generate grants + run: uv run pyvec-docs gen-grants + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Generate boards + run: uv run pyvec-docs gen-boards + - name: Generate Twemoji + run: uv run pyvec-docs gen-twemoji + - name: Create PR + uses: peter-evans/create-pull-request@v7 + with: + token: ${{ secrets.GITHUB_TOKEN }} + add-paths: docs + commit-message: "update generated files" + branch: automation/generate + title: "Automated update of generated pages and other files" + body: "For details, see [the docs](https://docs.pyvec.org/contributing.html#generovani-stranek-a-souboru) :book:" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a9c31c8..63a15bb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,6 +10,6 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@v6 - name: Test - run: uv run pytest + run: uv run pyvec-docs test - name: Build documentation - run: uv run sphinx-build -nWaE docs build + run: uv run pyvec-docs build diff --git a/.github/workflows/update_pages.yml b/.github/workflows/update_pages.yml deleted file mode 100644 index f21b319..0000000 --- a/.github/workflows/update_pages.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Update Pages -on: - push: - branches: - - master - schedule: - - cron: "0 4 * * *" -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Install uv - uses: astral-sh/setup-uv@v6 - - name: Generate the list of grants - run: uv run python scripts/generate_grants.py > ./docs/operations/grants.rst - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Generate the list of boards - run: uv run python scripts/generate_boards.py > ./docs/operations/boards.rst - - name: Create PR - uses: peter-evans/create-pull-request@v7 - with: - token: ${{ secrets.GITHUB_TOKEN }} - add-paths: | - ./docs/operations/grants.rst - ./docs/operations/boards.rst - commit-message: "update pages (generated)" - branch: automation/pages - title: "Automated update of pages (grants, boards)" - body: > - Automated update of some pages, namely the lists of grants and boards :robot: - For details, see [the docs](https://docs.pyvec.org/contributing.html) :book: diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 1afb482..74057af 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -21,7 +21,7 @@ Když toho upravujete víc, nebo máte zálusk na nějaké složitější kejkle Běžná práce ----------- -#. Ve virtuálním prostředí spusťte projekt: ``uv run sphinx-autobuild docs build`` +#. Ve virtuálním prostředí spusťte projekt: ``uv run pyvec-docs build`` #. Otevřete si v prohlížeči ``_ #. V editoru upravujete texty a v prohlížeči si kontrolujete výsledek #. Projekt zastavíte v terminálu pomocí :kbd:`Ctrl+C` @@ -90,28 +90,15 @@ Na repozitáři je zapojená `GitHub Action `_, konkrétně workflow ``generate.yml``. Tyto skripty se spouští jednou denně a generují soubory, které se pak posílají jako pull requesty do repozitáře, pokud vytvoří nějaké změny. -* se pomocí `GitHub Actions `_ jednou denně spustí, -* vygeneruje soubor ``operations/boards.rst`` ze `souboru boards.toml `_ a ze šablony ``operations/boards.rst``, -* commitne a pushne jej přes Git do repozitáře. +- Generuje se ``docs/operations/boards.rst`` ze `souboru boards.toml `_ a ze šablony ``operations/boards.rst``. +- Generuje se ``docs/operations/grants.rst`` z dat na `pyvec/money `_ a ze šablony ``operations/grants.rst``. +- Generuje se ``docs/_static/twemoji.min.js``, abychom Twemoji měli lokálně a nemuseli se spoléhat na CDN. -Výsledná stránka je pouze informační, kanonickým zdrojem pravdy jsou v tomto případě státní registry. - -.. _generate_grants: - -Skript na generování zápisů hlasování o grantech ------------------------------------------------- - -V adresáři ``scripts`` je skript ``generate_grants.py``, který: - -* se pomocí `GitHub Actions `_ jednou denně spustí, -* vygeneruje soubor ``operations/grants.rst`` z dat na `pyvec/money `_ a ze šablony ``operations/grants.rst``, -* commitne a pushne jej přes Git do repozitáře. - -Hlasování o grantech probíhá :ref:`pomocí reakcí ` na GitHub Issues a tento skript hlasování archivuje sem do dokumentace pro účely jednoduššího vyhledávání, zálohy, kdyby se s `pyvec/money `_ něco stalo, a pro nějakou historickou evidenci. Kanonickým zdrojem pravdy ale zůstává hlasování přímo na GitHub Issues, toto je jen automatizovaný přepis. Skript započítává pouze hlasy od členů výboru (podle `souboru boards.toml `_). +Kód pro generování je v ``src/pyvec_docs/cli.py``. Skripty jde pouštět např. ``uv run pyvec-docs gen-boards``. diff --git a/docs/_static/twemoji.min.js b/docs/_static/twemoji.min.js new file mode 100644 index 0000000..457e46c --- /dev/null +++ b/docs/_static/twemoji.min.js @@ -0,0 +1,5 @@ +/*! Copyright Twitter Inc. and other contributors. Licensed under MIT */ + +/* :-) */ + +var twemoji=function(){"use strict";var twemoji={base:"https://cdn.jsdelivr.net/gh/jdecked/twemoji@16.0.1/assets/",ext:".png",size:"72x72",className:"emoji",convert:{fromCodePoint:fromCodePoint,toCodePoint:toCodePoint},onerror:function onerror(){if(this.parentNode){this.parentNode.replaceChild(createText(this.alt,false),this)}},parse:parse,replace:replace,test:test},escaper={"&":"&","<":"<",">":">","'":"'",'"':"""},re=/(?:\ud83d\udc68\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83e\uddd1\ud83c[\udffc-\udfff]|\ud83e\uddd1\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83e\uddd1\ud83c[\udffb\udffd-\udfff]|\ud83e\uddd1\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83e\uddd1\ud83c[\udffb\udffc\udffe\udfff]|\ud83e\uddd1\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83e\uddd1\ud83c[\udffb-\udffd\udfff]|\ud83e\uddd1\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83e\uddd1\ud83c[\udffb-\udffe]|\ud83d\udc68\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffc-\udfff]|\ud83d\udc68\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffd-\udfff]|\ud83d\udc68\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc68\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffd\udfff]|\ud83d\udc68\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffe]|\ud83d\udc69\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffc-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffc-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffd-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb\udffd-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc69\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc69\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffd\udfff]|\ud83d\udc69\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb-\udffd\udfff]|\ud83d\udc69\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffe]|\ud83d\udc69\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb-\udffe]|\ud83e\uddd1\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83e\uddd1\ud83c[\udffc-\udfff]|\ud83e\uddd1\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83e\uddd1\ud83c[\udffb\udffd-\udfff]|\ud83e\uddd1\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83e\uddd1\ud83c[\udffb\udffc\udffe\udfff]|\ud83e\uddd1\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83e\uddd1\ud83c[\udffb-\udffd\udfff]|\ud83e\uddd1\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83e\uddd1\ud83c[\udffb-\udffe]|\ud83e\uddd1\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68|\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d[\udc68\udc69]|\ud83e\udef1\ud83c\udffb\u200d\ud83e\udef2\ud83c[\udffc-\udfff]|\ud83e\udef1\ud83c\udffc\u200d\ud83e\udef2\ud83c[\udffb\udffd-\udfff]|\ud83e\udef1\ud83c\udffd\u200d\ud83e\udef2\ud83c[\udffb\udffc\udffe\udfff]|\ud83e\udef1\ud83c\udffe\u200d\ud83e\udef2\ud83c[\udffb-\udffd\udfff]|\ud83e\udef1\ud83c\udfff\u200d\ud83e\udef2\ud83c[\udffb-\udffe]|\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc68|\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d[\udc68\udc69]|\ud83e\uddd1\u200d\ud83e\udd1d\u200d\ud83e\uddd1|\ud83d\udc6b\ud83c[\udffb-\udfff]|\ud83d\udc6c\ud83c[\udffb-\udfff]|\ud83d\udc6d\ud83c[\udffb-\udfff]|\ud83d\udc8f\ud83c[\udffb-\udfff]|\ud83d\udc91\ud83c[\udffb-\udfff]|\ud83e\udd1d\ud83c[\udffb-\udfff]|\ud83d[\udc6b-\udc6d\udc8f\udc91]|\ud83e\udd1d)|(?:\ud83d[\udc68\udc69]|\ud83e\uddd1)(?:\ud83c[\udffb-\udfff])?\u200d(?:\u2695\ufe0f|\u2696\ufe0f|\u2708\ufe0f|\ud83c[\udf3e\udf73\udf7c\udf84\udf93\udfa4\udfa8\udfeb\udfed]|\ud83d[\udcbb\udcbc\udd27\udd2c\ude80\ude92]|\ud83e[\uddaf-\uddb3\uddbc\uddbd])(?:\u200d\u27a1\ufe0f)?|(?:\ud83c[\udfcb\udfcc]|\ud83d[\udd74\udd75]|\u26f9)((?:\ud83c[\udffb-\udfff]|\ufe0f)\u200d[\u2640\u2642]\ufe0f(?:\u200d\u27a1\ufe0f)?)|(?:\ud83c[\udfc3\udfc4\udfca]|\ud83d[\udc6e\udc70\udc71\udc73\udc77\udc81\udc82\udc86\udc87\ude45-\ude47\ude4b\ude4d\ude4e\udea3\udeb4-\udeb6]|\ud83e[\udd26\udd35\udd37-\udd39\udd3d\udd3e\uddb8\uddb9\uddcd-\uddcf\uddd4\uddd6-\udddd])(?:\ud83c[\udffb-\udfff])?\u200d[\u2640\u2642]\ufe0f(?:\u200d\u27a1\ufe0f)?|(?:\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83e\uddd1\u200d\ud83e\uddd1\u200d\ud83e\uddd2\u200d\ud83e\uddd2|\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83e\uddd1\u200d\ud83e\uddd1\u200d\ud83e\uddd2|\ud83e\uddd1\u200d\ud83e\uddd2\u200d\ud83e\uddd2|\ud83c\udff3\ufe0f\u200d\u26a7\ufe0f|\ud83c\udff3\ufe0f\u200d\ud83c\udf08|\ud83d\ude36\u200d\ud83c\udf2b\ufe0f|\u26d3\ufe0f\u200d\ud83d\udca5|\u2764\ufe0f\u200d\ud83d\udd25|\u2764\ufe0f\u200d\ud83e\ude79|\ud83c\udf44\u200d\ud83d\udfeb|\ud83c\udf4b\u200d\ud83d\udfe9|\ud83c\udff4\u200d\u2620\ufe0f|\ud83d\udc15\u200d\ud83e\uddba|\ud83d\udc26\u200d\ud83d\udd25|\ud83d\udc3b\u200d\u2744\ufe0f|\ud83d\udc41\u200d\ud83d\udde8|\ud83d\udc68\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83d\udc6f\u200d\u2640\ufe0f|\ud83d\udc6f\u200d\u2642\ufe0f|\ud83d\ude2e\u200d\ud83d\udca8|\ud83d\ude35\u200d\ud83d\udcab|\ud83d\ude42\u200d\u2194\ufe0f|\ud83d\ude42\u200d\u2195\ufe0f|\ud83e\udd3c\u200d\u2640\ufe0f|\ud83e\udd3c\u200d\u2642\ufe0f|\ud83e\uddd1\u200d\ud83e\uddd2|\ud83e\uddde\u200d\u2640\ufe0f|\ud83e\uddde\u200d\u2642\ufe0f|\ud83e\udddf\u200d\u2640\ufe0f|\ud83e\udddf\u200d\u2642\ufe0f|\ud83d\udc08\u200d\u2b1b|\ud83d\udc26\u200d\u2b1b)|[#*0-9]\ufe0f?\u20e3|(?:[©®\u2122\u265f]\ufe0f)|(?:\ud83c[\udc04\udd70\udd71\udd7e\udd7f\ude02\ude1a\ude2f\ude37\udf21\udf24-\udf2c\udf36\udf7d\udf96\udf97\udf99-\udf9b\udf9e\udf9f\udfcd\udfce\udfd4-\udfdf\udff3\udff5\udff7]|\ud83d[\udc3f\udc41\udcfd\udd49\udd4a\udd6f\udd70\udd73\udd76-\udd79\udd87\udd8a-\udd8d\udda5\udda8\uddb1\uddb2\uddbc\uddc2-\uddc4\uddd1-\uddd3\udddc-\uddde\udde1\udde3\udde8\uddef\uddf3\uddfa\udecb\udecd-\udecf\udee0-\udee5\udee9\udef0\udef3]|[\u203c\u2049\u2139\u2194-\u2199\u21a9\u21aa\u231a\u231b\u2328\u23cf\u23ed-\u23ef\u23f1\u23f2\u23f8-\u23fa\u24c2\u25aa\u25ab\u25b6\u25c0\u25fb-\u25fe\u2600-\u2604\u260e\u2611\u2614\u2615\u2618\u2620\u2622\u2623\u2626\u262a\u262e\u262f\u2638-\u263a\u2640\u2642\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267b\u267f\u2692-\u2697\u2699\u269b\u269c\u26a0\u26a1\u26a7\u26aa\u26ab\u26b0\u26b1\u26bd\u26be\u26c4\u26c5\u26c8\u26cf\u26d1\u26d3\u26d4\u26e9\u26ea\u26f0-\u26f5\u26f8\u26fa\u26fd\u2702\u2708\u2709\u270f\u2712\u2714\u2716\u271d\u2721\u2733\u2734\u2744\u2747\u2757\u2763\u2764\u27a1\u2934\u2935\u2b05-\u2b07\u2b1b\u2b1c\u2b50\u2b55\u3030\u303d\u3297\u3299])(?:\ufe0f|(?!\ufe0e))|(?:(?:\ud83c[\udfcb\udfcc]|\ud83d[\udd74\udd75\udd90]|\ud83e\udef0|[\u261d\u26f7\u26f9\u270c\u270d])(?:\ufe0f|(?!\ufe0e))|(?:\ud83c\udfc3|\ud83d\udeb6|\ud83e\uddce)(?:\ud83c[\udffb-\udfff])?(?:\u200d\u27a1\ufe0f)?|(?:\ud83c[\udf85\udfc2\udfc4\udfc7\udfca]|\ud83d[\udc42\udc43\udc46-\udc50\udc66-\udc69\udc6e\udc70-\udc78\udc7c\udc81-\udc83\udc85-\udc87\udcaa\udd7a\udd95\udd96\ude45-\ude47\ude4b-\ude4f\udea3\udeb4\udeb5\udec0\udecc]|\ud83e[\udd0c\udd0f\udd18-\udd1c\udd1e\udd1f\udd26\udd30-\udd39\udd3d\udd3e\udd77\uddb5\uddb6\uddb8\uddb9\uddbb\uddcd\uddcf\uddd1-\udddd\udec3-\udec5\udef1-\udef8]|[\u270a\u270b]))(?:\ud83c[\udffb-\udfff])?|(?:\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f|\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc73\udb40\udc63\udb40\udc74\udb40\udc7f|\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f|\ud83c\udde6\ud83c[\udde8-\uddec\uddee\uddf1\uddf2\uddf4\uddf6-\uddfa\uddfc\uddfd\uddff]|\ud83c\udde7\ud83c[\udde6\udde7\udde9-\uddef\uddf1-\uddf4\uddf6-\uddf9\uddfb\uddfc\uddfe\uddff]|\ud83c\udde8\ud83c[\udde6\udde8\udde9\uddeb-\uddee\uddf0-\uddf7\uddfa-\uddff]|\ud83c\udde9\ud83c[\uddea\uddec\uddef\uddf0\uddf2\uddf4\uddff]|\ud83c\uddea\ud83c[\udde6\udde8\uddea\uddec\udded\uddf7-\uddfa]|\ud83c\uddeb\ud83c[\uddee-\uddf0\uddf2\uddf4\uddf7]|\ud83c\uddec\ud83c[\udde6\udde7\udde9-\uddee\uddf1-\uddf3\uddf5-\uddfa\uddfc\uddfe]|\ud83c\udded\ud83c[\uddf0\uddf2\uddf3\uddf7\uddf9\uddfa]|\ud83c\uddee\ud83c[\udde8-\uddea\uddf1-\uddf4\uddf6-\uddf9]|\ud83c\uddef\ud83c[\uddea\uddf2\uddf4\uddf5]|\ud83c\uddf0\ud83c[\uddea\uddec-\uddee\uddf2\uddf3\uddf5\uddf7\uddfc\uddfe\uddff]|\ud83c\uddf1\ud83c[\udde6-\udde8\uddee\uddf0\uddf7-\uddfb\uddfe]|\ud83c\uddf2\ud83c[\udde6\udde8-\udded\uddf0-\uddff]|\ud83c\uddf3\ud83c[\udde6\udde8\uddea-\uddec\uddee\uddf1\uddf4\uddf5\uddf7\uddfa\uddff]|\ud83c\uddf4\ud83c\uddf2|\ud83c\uddf5\ud83c[\udde6\uddea-\udded\uddf0-\uddf3\uddf7-\uddf9\uddfc\uddfe]|\ud83c\uddf6\ud83c\udde6|\ud83c\uddf7\ud83c[\uddea\uddf4\uddf8\uddfa\uddfc]|\ud83c\uddf8\ud83c[\udde6-\uddea\uddec-\uddf4\uddf7-\uddf9\uddfb\uddfd-\uddff]|\ud83c\uddf9\ud83c[\udde6\udde8\udde9\uddeb-\udded\uddef-\uddf4\uddf7\uddf9\uddfb\uddfc\uddff]|\ud83c\uddfa\ud83c[\udde6\uddec\uddf2\uddf3\uddf8\uddfe\uddff]|\ud83c\uddfb\ud83c[\udde6\udde8\uddea\uddec\uddee\uddf3\uddfa]|\ud83c\uddfc\ud83c[\uddeb\uddf8]|\ud83c\uddfd\ud83c\uddf0|\ud83c\uddfe\ud83c[\uddea\uddf9]|\ud83c\uddff\ud83c[\udde6\uddf2\uddfc]|\ud83c[\udccf\udd8e\udd91-\udd9a\udde6-\uddff\ude01\ude32-\ude36\ude38-\ude3a\ude50\ude51\udf00-\udf20\udf2d-\udf35\udf37-\udf7c\udf7e-\udf84\udf86-\udf93\udfa0-\udfc1\udfc5\udfc6\udfc8\udfc9\udfcf-\udfd3\udfe0-\udff0\udff4\udff8-\udfff]|\ud83d[\udc00-\udc3e\udc40\udc44\udc45\udc51-\udc65\udc6a\udc6f\udc79-\udc7b\udc7d-\udc80\udc84\udc88-\udc8e\udc90\udc92-\udca9\udcab-\udcfc\udcff-\udd3d\udd4b-\udd4e\udd50-\udd67\udda4\uddfb-\ude44\ude48-\ude4a\ude80-\udea2\udea4-\udeb3\udeb7-\udebf\udec1-\udec5\uded0-\uded2\uded5-\uded7\udedc-\udedf\udeeb\udeec\udef4-\udefc\udfe0-\udfeb\udff0]|\ud83e[\udd0d\udd0e\udd10-\udd17\udd20-\udd25\udd27-\udd2f\udd3a\udd3c\udd3f-\udd45\udd47-\udd76\udd78-\uddb4\uddb7\uddba\uddbc-\uddcc\uddd0\uddde-\uddff\ude70-\ude7c\ude80-\ude89\ude8f-\udec2\udec6\udece-\udedc\udedf-\udee9]|[\u23e9-\u23ec\u23f0\u23f3\u267e\u26ce\u2705\u2728\u274c\u274e\u2753-\u2755\u2795-\u2797\u27b0\u27bf\ue50a])|\ufe0f/g,UFE0Fg=/\uFE0F/g,U200D=String.fromCharCode(8205),rescaper=/[&<>'"]/g,shouldntBeParsed=/^(?:iframe|noframes|noscript|script|select|style|textarea)$/,fromCharCode=String.fromCharCode;return twemoji;function createText(text,clean){return document.createTextNode(clean?text.replace(UFE0Fg,""):text)}function escapeHTML(s){return s.replace(rescaper,replacer)}function defaultImageSrcGenerator(icon,options){return"".concat(options.base,options.size,"/",icon,options.ext)}function grabAllTextNodes(node,allText){var childNodes=node.childNodes,length=childNodes.length,subnode,nodeType;while(length--){subnode=childNodes[length];nodeType=subnode.nodeType;if(nodeType===3){allText.push(subnode)}else if(nodeType===1&&!("ownerSVGElement"in subnode)&&!shouldntBeParsed.test(subnode.nodeName.toLowerCase())){grabAllTextNodes(subnode,allText)}}return allText}function grabTheRightIcon(rawText){return toCodePoint(rawText.indexOf(U200D)<0?rawText.replace(UFE0Fg,""):rawText)}function parseNode(node,options){var allText=grabAllTextNodes(node,[]),length=allText.length,attrib,attrname,modified,fragment,subnode,text,match,i,index,img,rawText,iconId,src;while(length--){modified=false;fragment=document.createDocumentFragment();subnode=allText[length];text=subnode.nodeValue;i=0;while(match=re.exec(text)){index=match.index;if(index!==i){fragment.appendChild(createText(text.slice(i,index),true))}rawText=match[0];iconId=grabTheRightIcon(rawText);i=index+rawText.length;src=options.callback(iconId,options);if(iconId&&src){img=new Image;img.onerror=options.onerror;img.setAttribute("draggable","false");attrib=options.attributes(rawText,iconId);for(attrname in attrib){if(attrib.hasOwnProperty(attrname)&&attrname.indexOf("on")!==0&&!img.hasAttribute(attrname)){img.setAttribute(attrname,attrib[attrname])}}img.className=options.className;img.alt=rawText;img.src=src;modified=true;fragment.appendChild(img)}if(!img)fragment.appendChild(createText(rawText,false));img=null}if(modified){if(i")}return ret})}function replacer(m){return escaper[m]}function returnNull(){return null}function toSizeSquaredAsset(value){return typeof value==="number"?value+"x"+value:value}function fromCodePoint(codepoint){var code=typeof codepoint==="string"?parseInt(codepoint,16):codepoint;if(code<65536){return fromCharCode(code)}code-=65536;return fromCharCode(55296+(code>>10),56320+(code&1023))}function parse(what,how){if(!how||typeof how==="function"){how={callback:how}}return(typeof what==="string"?parseString:parseNode)(what,{callback:how.callback||defaultImageSrcGenerator,attributes:typeof how.attributes==="function"?how.attributes:returnNull,base:typeof how.base==="string"?how.base:twemoji.base,ext:how.ext||twemoji.ext,size:how.folder||toSizeSquaredAsset(how.size||twemoji.size),className:how.className||twemoji.className,onerror:how.onerror||twemoji.onerror})}function replace(text,callback){return String(text).replace(re,callback)}function test(text){re.lastIndex=0;var result=re.test(text);re.lastIndex=0;return result}function toCodePoint(unicodeSurrogates,sep){var r=[],c=0,p=0,i=0;while(i`. Kanonickým zdrojem pravdy je `výpis na justice.cz `_. Historii výborů si pro vlastní potřeby zaznamenáváme do `souboru boards.toml `_ a z něj se generuje i tato stránka. -Kdyby něco nesedělo, ověřte `historii zdrojáku této stránky `_ a funkčnost :ref:`přepisů `. +Kdyby něco nesedělo, ověřte `historii zdrojáku této stránky `_ a funkčnost :ref:`přepisů `. .. Soubor docs/operations/boards.rst je generován skriptem scripts/generate_boards.py ze šablony docs/operations/boards.rst.jinja. Neupravovat ručně! @@ -14,11 +14,11 @@ Výbor od 9.4.2022 .. csv-table:: :header: "Jméno", "GitHub", "Funkce" - Barbora Drbohlavová, `@baradrb `_, |:crown:| - Anežka Müller, `@anezkamll `_, - Jan Javorek, `@honzajavorek `_, - Jakub Vysoký, `@kvbik `_, - Jan Čermák, `@sairon `_, |:moneybag:| + Barbora Drbohlavová, `@baradrb `_, |:crown:| + Anežka Müller, `@anezkamll `_, + Jan Javorek, `@honzajavorek `_, + Jakub Vysoký, `@kvbik `_, + Jan Čermák, `@sairon `_, |:moneybag:| Výbor od 8.4.2019 ------------------------------------------------- @@ -26,11 +26,11 @@ Výbor od 8.4.2019 .. csv-table:: :header: "Jméno", "GitHub", "Funkce" - Martin Bílek, `@martinbilek `_, |:crown:| |:moneybag:| - Aleš Zoulek, `@aleszoulek `_, - Jan Javorek, `@honzajavorek `_, - Jakub Vysoký, `@kvbik `_, - Jiří Bartoň, `@whiskybar `_, + Martin Bílek, `@martinbilek `_, |:crown:| |:moneybag:| + Aleš Zoulek, `@aleszoulek `_, + Jan Javorek, `@honzajavorek `_, + Jakub Vysoký, `@kvbik `_, + Jiří Bartoň, `@whiskybar `_, Výbor od 27.3.2012 ------------------------------------------------- @@ -38,11 +38,11 @@ Výbor od 27.3.2012 .. csv-table:: :header: "Jméno", "GitHub", "Funkce" - Martin Bílek, `@martinbilek `_, |:crown:| |:moneybag:| - Aleš Zoulek, `@aleszoulek `_, - Robin Gottfried, `@czervenka `_, - Jan Král, `@honzakral `_, - Jakub Vysoký, `@kvbik `_, - Jiří Bartoň, `@whiskybar `_, - Vítězslav Pliska, `@whit `_, + Martin Bílek, `@martinbilek `_, |:crown:| |:moneybag:| + Aleš Zoulek, `@aleszoulek `_, + Robin Gottfried, `@czervenka `_, + Jan Král, `@honzakral `_, + Jakub Vysoký, `@kvbik `_, + Jiří Bartoň, `@whiskybar `_, + Vítězslav Pliska, `@whit `_, diff --git a/docs/operations/boards.rst.jinja b/docs/operations/boards.rst.jinja index 9d7697a..6916e72 100644 --- a/docs/operations/boards.rst.jinja +++ b/docs/operations/boards.rst.jinja @@ -1,11 +1,15 @@ Výbory spolku ============= -Historie složení :term:`výboru `. Kanonickým zdrojem pravdy je `výpis na justice.cz `_. Historii výborů si pro vlastní potřeby zaznamenáváme do `souboru boards.toml `_ a z něj se generuje i tato stránka. +Historii :term:`výborů ` si pro vlastní potřeby zaznamenáváme do `souboru boards.toml `_ a z něj se generuje i tato stránka. Kdyby něco nesedělo, ověřte `historii zdrojáku této stránky `_ a funkčnost :ref:`přepisů `. + +Kanonickým zdrojem pravdy je ale `výpis na justice.cz `_. + + + +.. Soubor docs/operations/boards.rst je generován, NEUPRAVOVAT RUČNĚ! -Kdyby něco nesedělo, ověřte `historii zdrojáku této stránky `_ a funkčnost :ref:`přepisů `. -.. Soubor docs/operations/boards.rst je generován skriptem scripts/generate_boards.py ze šablony docs/operations/boards.rst.jinja. Neupravovat ručně! {% for board in boards %} Výbor od {{ board.start_on.strftime("%-d.%-m.%Y") }} diff --git a/docs/operations/grants.rst b/docs/operations/grants.rst index 9f5e5ba..4171dfa 100644 --- a/docs/operations/grants.rst +++ b/docs/operations/grants.rst @@ -1,7 +1,7 @@ Elektronická hlasování o grantech ================================= -Od roku 2020 o grantech :term:`výbor ` hlasuje prostřednictvím repozitáře `pyvec/money `_. Zde je strojový přepis proběhlých hlasování. Kanonickým zdrojem pravdy je hlasování přímo na GitHub Issues. Kdyby něco nesedělo, ověřte `historii zdrojáku této stránky `_ a funkčnost :ref:`přepisů `. +Od roku 2020 o grantech :term:`výbor ` hlasuje prostřednictvím repozitáře `pyvec/money `_. Zde je strojový přepis proběhlých hlasování. Kanonickým zdrojem pravdy je hlasování přímo na GitHub Issues. Kdyby něco nesedělo, ověřte `historii zdrojáku této stránky `_ a funkčnost :ref:`přepisů `. .. Soubor docs/operations/grants.rst je generován skriptem scripts/generate_grants.py ze šablony docs/operations/grants.rst.jinja. Neupravovat ručně! @@ -339,7 +339,7 @@ Dne 25. 7. 2023 požádal uživatel `@clytaemnestra `_ o Karolina Surma - PyLadies **Kolik potřebujete? (aspoň odhad nebo rozmezí)** - ~6800 Kč + ~6800 Kč *detailně* hlavička: 6.24 Kč / ks = 2496 Kč @@ -403,7 +403,7 @@ Dne 27. 2. 2023 požádal uživatel `@Zuzanita `_ o .. code-block:: text **Kdo jste?** - Organizátoři PyLadies - podává Zuzana Pokorná za všechny + Organizátoři PyLadies - podává Zuzana Pokorná za všechny **Kolik potřebujete? (aspoň odhad nebo rozmezí)** 25 000 Kč z toho bude část vrácena z příspěvků jednotlivců na trička @@ -613,7 +613,7 @@ Dne 16. 12. 2020 požádal uživatel `@kvbik `_ o gran **Kdo jste?** - Jakub Vysoky, clen Pyvec, spolu organizator prazskeho Pyva + Jakub Vysoky, clen Pyvec, spolu organizator prazskeho Pyva **Kolik potřebujete? (aspoň odhad nebo rozmezí)** @@ -621,7 +621,7 @@ Dne 16. 12. 2020 požádal uživatel `@kvbik `_ o gran **Na jakou věc to je?** - Letni edice Python komunitniho Sprintu ve Msenych-laznich v srpen 2020. + Letni edice Python komunitniho Sprintu ve Msenych-laznich v srpen 2020. **Proč? (čemu prospějeme, proč je to dobrý nápad, jaký to bude mít dopad?)** @@ -651,13 +651,13 @@ Dne 26. 2. 2020 požádal uživatel `@radusaaa `_ o PyLadies Praha **Kolik potřebujete? (aspoň odhad nebo rozmezí)** - 500,- Kč za oba běhy + 500,- Kč za oba běhy **Na jakou věc to je?** - kancelářské potřeby - - drobné odměny do soutěží + - drobné odměny do soutěží **Proč? (čemu prospějeme, proč je to dobrý nápad, jaký to bude mít dopad?)** Organizujeme dva běhy začátečnických kurzů viz https://pyladies.cz/praha/. Součástí kurzů jsou i dva sobotní celodenní pyworkingy a závěrečný hackathon. diff --git a/docs/operations/grants.rst.jinja b/docs/operations/grants.rst.jinja index a2c938b..d84bb22 100644 --- a/docs/operations/grants.rst.jinja +++ b/docs/operations/grants.rst.jinja @@ -1,9 +1,17 @@ Elektronická hlasování o grantech ================================= -Od roku 2020 o grantech :term:`výbor ` hlasuje prostřednictvím repozitáře `pyvec/money `_. Zde je strojový přepis proběhlých hlasování. Kanonickým zdrojem pravdy je hlasování přímo na GitHub Issues. Kdyby něco nesedělo, ověřte `historii zdrojáku této stránky `_ a funkčnost :ref:`přepisů `. +Od roku 2020 o grantech :term:`výbor ` hlasuje prostřednictvím repozitáře `pyvec/money `_. + +Hlasování o grantech probíhá :ref:`pomocí reakcí ` na GitHub Issues. Hlasování se automaticky archivují sem do dokumentace pro účely jednoduššího vyhledávání, zálohy, kdyby se s `pyvec/money `_ něco stalo, a pro nějakou historickou evidenci. Kanonickým zdrojem pravdy ale zůstává hlasování přímo na GitHub Issues, toto je jen přepis. Skript započítává pouze hlasy od členů výboru (podle `souboru boards.toml `_). + +Kdyby něco nesedělo, ověřte `historii zdrojáku této stránky `_ a funkčnost :ref:`přepisů `. + + + +.. Soubor docs/operations/grants.rst je generován, NEUPRAVOVAT RUČNĚ! + -.. Soubor docs/operations/grants.rst je generován skriptem scripts/generate_grants.py ze šablony docs/operations/grants.rst.jinja. Neupravovat ručně! {% for grant in grants %} {{ grant.voted_at.day }}. {{ grant.voted_at.month }}. {{ grant.voted_at.year }} - elektronické hlasování výboru diff --git a/pyproject.toml b/pyproject.toml index 2ba89ec..0e453fc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,6 +3,7 @@ name = "pyvec-docs" version = "0" requires-python = "==3.12.*" dependencies = [ + "click==8.1.8", "jinja2==3.1.6", "myst-parser==4.0.1", "pydantic==2.11.4", @@ -12,6 +13,9 @@ dependencies = [ "sphinxemoji==0.3.1", ] +[project.scripts] +pyvec-docs = "pyvec_docs.cli:main" + [dependency-groups] dev = [ "pytest-ruff==0.4.1", diff --git a/scripts/generate_boards.py b/scripts/generate_boards.py deleted file mode 100644 index adbfb59..0000000 --- a/scripts/generate_boards.py +++ /dev/null @@ -1,14 +0,0 @@ -from pathlib import Path - -from jinja2 import Template - -from pyvec_docs.board import load_boards - - -CONTENT_PATH = Path(__file__).parent.parent / "docs" - - -if __name__ == "__main__": - tpl_path = CONTENT_PATH / "operations" / "boards.rst.jinja" - tpl = Template(tpl_path.read_text()) - print(tpl.render(boards=load_boards())) diff --git a/scripts/generate_grants.py b/scripts/generate_grants.py deleted file mode 100644 index a4dde59..0000000 --- a/scripts/generate_grants.py +++ /dev/null @@ -1,80 +0,0 @@ -import os -from operator import itemgetter -from pathlib import Path - -import requests -from jinja2 import Template - -from pyvec_docs.board import load_boards -from pyvec_docs.grants import get_lock_date, get_votes, remove_comments, to_date - - -GITHUB_TOKEN = os.getenv("GITHUB_TOKEN") -GITHUB_API_HEADERS = { - "Accept": "application/vnd.github.squirrel-girl-preview", - "Authorization": f"token {GITHUB_TOKEN}", -} -GITHUB_API_URL = "https://api.github.com/repos/pyvec/money/issues" -CONTENT_PATH = Path(__file__).parent.parent / "docs" - - -if __name__ == "__main__": - boards = load_boards() - - res = requests.get( - GITHUB_API_URL, - headers=GITHUB_API_HEADERS, - params={"per_page": 100, "state": "closed"}, - ) - res.raise_for_status() - - grants = [] - for issue in res.json(): - labels = [label["name"] for label in issue["labels"]] - if "approved" not in labels and "rejected" not in labels: - # skip unlabeled, e.g. https://github.com/pyvec/money/issues/1 - continue - - if issue["locked"]: - res = requests.get( - issue["events_url"], - headers=GITHUB_API_HEADERS, - params={"per_page": 100}, - ) - res.raise_for_status() - - if res.headers.get("link"): - raise NotImplementedError( - f"The number of events of issue #{issue['number']} " - "is paginated and this code isn't yet designed " - "to handle this!" - ) - else: - voted_at = get_lock_date(res.json()) - else: - voted_at = to_date(issue["closed_at"]) - - res = requests.get(issue["reactions"]["url"], headers=GITHUB_API_HEADERS) - res.raise_for_status() - votes = list(get_votes(res.json(), voted_at, boards)) - - grants.append( - { - "title": issue["title"], - "description": remove_comments(issue["body"]), - "url": issue["html_url"], - "user": { - "username": issue["user"]["login"], - "url": issue["user"]["html_url"], - }, - "is_approved": "approved" in labels, - "filed_at": to_date(issue["created_at"]), - "voted_at": voted_at, - "votes": votes, - } - ) - grants = sorted(grants, key=itemgetter("voted_at"), reverse=True) - - tpl_path = CONTENT_PATH / "operations" / "grants.rst.jinja" - tpl = Template(tpl_path.read_text()) - print(tpl.render(grants=grants)) diff --git a/src/pyvec_docs/board.py b/src/pyvec_docs/boards.py similarity index 100% rename from src/pyvec_docs/board.py rename to src/pyvec_docs/boards.py diff --git a/src/pyvec_docs/cli.py b/src/pyvec_docs/cli.py new file mode 100644 index 0000000..19b07ff --- /dev/null +++ b/src/pyvec_docs/cli.py @@ -0,0 +1,169 @@ +import subprocess +import sys +from operator import itemgetter +from pathlib import Path + +import click +import requests +from jinja2 import Template + +from pyvec_docs.boards import load_boards +from pyvec_docs.grants import get_lock_date, get_votes, remove_comments, to_date + + +@click.group() +def main() -> None: + pass + + +@main.command() +def test() -> None: + try: + subprocess.run(["pytest"], check=True) + except subprocess.CalledProcessError: + sys.exit(1) + + +@main.command() +def build() -> None: + try: + subprocess.run(["sphinx-build", "-nWaE", "docs", "build"], check=True) + except subprocess.CalledProcessError: + sys.exit(1) + + +@main.command() +def watch() -> None: + try: + subprocess.run(["sphinx-autobuild", "-nWaE", "docs", "build"], check=True) + except subprocess.CalledProcessError: + sys.exit(1) + + +@main.command() +@click.option( + "--template", + "template_path", + type=click.Path(exists=True, path_type=Path), + default="docs/operations/grants.rst.jinja", +) +@click.option( + "--output", + "output_path", + type=click.Path(path_type=Path), + default="docs/operations/grants.rst", +) +@click.option( + "--github-url", type=str, default="https://api.github.com/repos/pyvec/money/issues" +) +@click.option("--github-token", type=str, envvar="GITHUB_TOKEN") +def gen_grants( + template_path: Path, + output_path: Path, + github_url: str, + github_token: str, +) -> None: + github_headers = { + "Accept": "application/vnd.github.squirrel-girl-preview", + "Authorization": f"token {github_token}", + } + res = requests.get( + github_url, + headers=github_headers, + params={"per_page": 100, "state": "closed"}, + ) + res.raise_for_status() + issues = res.json() + + boards = load_boards() + grants = [] + with click.progressbar(issues, label="Processing issues") as progress: + for issue in progress: + labels = [label["name"] for label in issue["labels"]] + if "approved" not in labels and "rejected" not in labels: + # skip unlabeled, e.g. https://github.com/pyvec/money/issues/1 + continue + + if issue["locked"]: + res = requests.get( + issue["events_url"], + headers=github_headers, + params={"per_page": 100}, + ) + res.raise_for_status() + + if res.headers.get("link"): + raise NotImplementedError( + f"The number of events of issue #{issue['number']} " + "is paginated and the code isn't yet designed " + "to handle this!" + ) + else: + voted_at = get_lock_date(res.json()) + else: + voted_at = to_date(issue["closed_at"]) + + res = requests.get(issue["reactions"]["url"], headers=github_headers) + res.raise_for_status() + votes = list(get_votes(res.json(), voted_at, boards)) + + grants.append( + { + "title": issue["title"], + "description": remove_comments(issue["body"]), + "url": issue["html_url"], + "user": { + "username": issue["user"]["login"], + "url": issue["user"]["html_url"], + }, + "is_approved": "approved" in labels, + "filed_at": to_date(issue["created_at"]), + "voted_at": voted_at, + "votes": votes, + } + ) + grants = sorted(grants, key=itemgetter("voted_at"), reverse=True) + + tpl = Template(template_path.read_text()) + output_path.write_text(tpl.render(grants=grants)) + + +@main.command() +@click.option( + "--template", + "template_path", + type=click.Path(exists=True, path_type=Path), + default="docs/operations/boards.rst.jinja", +) +@click.option( + "--output", + "output_path", + type=click.Path(path_type=Path), + default="docs/operations/boards.rst", +) +def gen_boards( + template_path: Path, + output_path: Path, +) -> None: + boards = load_boards() + tpl = Template(template_path.read_text()) + output_path.write_text(tpl.render(boards=boards)) + + +@main.command() +@click.option( + "--source-url", + type=str, + default="https://cdn.jsdelivr.net/npm/@twemoji/api@latest/dist/twemoji.min.js", +) +@click.option( + "--output", + "output_path", + type=click.Path(path_type=Path), + default="docs/_static/twemoji.min.js", +) +def gen_twemoji(source_url: str, output_path: Path) -> None: + """Download the latest version of twemoji.min.js from CDN of https://github.com/jdecked/twemoji/""" + res = requests.get(source_url) + res.raise_for_status() + output_path.write_bytes(res.content) diff --git a/src/pyvec_docs/ext/board_dates.py b/src/pyvec_docs/ext/board_dates.py index 49cde48..7fa25d9 100644 --- a/src/pyvec_docs/ext/board_dates.py +++ b/src/pyvec_docs/ext/board_dates.py @@ -4,7 +4,7 @@ from sphinx.application import Sphinx from sphinx.config import Config -from pyvec_docs.board import BOARDS_MANDATE_LENGTH, load_boards +from pyvec_docs.boards import BOARDS_MANDATE_LENGTH, load_boards def board_dates(app: Sphinx, config: Config): diff --git a/src/pyvec_docs/ext/slack.py b/src/pyvec_docs/ext/slack.py index 9d837b6..983f997 100644 --- a/src/pyvec_docs/ext/slack.py +++ b/src/pyvec_docs/ext/slack.py @@ -9,7 +9,7 @@ from docutils import nodes -from pyvec_docs.board import load_boards +from pyvec_docs.boards import load_boards # https://docutils.readthedocs.io/en/sphinx-docs/howto/rst-roles.html diff --git a/src/pyvec_docs/grants.py b/src/pyvec_docs/grants.py index 640b625..458dc3c 100644 --- a/src/pyvec_docs/grants.py +++ b/src/pyvec_docs/grants.py @@ -1,7 +1,7 @@ import re from datetime import date -from pyvec_docs.board import Board +from pyvec_docs.boards import Board REACTIONS_MAPPING = {"+1": "ano", "-1": "ne", "eyes": "zdržel(a) se"} diff --git a/tests/test_scripts_generate_grants.py b/tests/test_scripts_generate_grants.py index 3194671..1c3d4f3 100644 --- a/tests/test_scripts_generate_grants.py +++ b/tests/test_scripts_generate_grants.py @@ -2,7 +2,7 @@ import pytest -from pyvec_docs.board import Board +from pyvec_docs.boards import Board from pyvec_docs.grants import ( get_board_member_name, get_votes, diff --git a/uv.lock b/uv.lock index 1f910d5..0a95271 100644 --- a/uv.lock +++ b/uv.lock @@ -320,6 +320,7 @@ name = "pyvec-docs" version = "0" source = { editable = "." } dependencies = [ + { name = "click" }, { name = "jinja2" }, { name = "myst-parser" }, { name = "pydantic" }, @@ -338,6 +339,7 @@ dev = [ [package.metadata] requires-dist = [ + { name = "click", specifier = "==8.1.8" }, { name = "jinja2", specifier = "==3.1.6" }, { name = "myst-parser", specifier = "==4.0.1" }, { name = "pydantic", specifier = "==2.11.4" },