Compare commits

...

58 Commits

Author SHA1 Message Date
c1b28d7f43 Merge branch 'master' of https://git.mamahaha.work/sangge/waka-readme 2024-01-22 00:43:51 +08:00
512d27739c temp change 2024-01-22 00:43:24 +08:00
ad3a3b38e6 update dockerfile 2024-01-20 00:43:13 +08:00
1d9eeae447 Merge pull request 'dev-gitea' (#3) from dev-gitea into master
Reviewed-on: #3
2024-01-18 23:04:08 +08:00
c0345cb5d9 Merge branch 'dev-gitea' of https://git.mamahaha.work/sangge/waka-readme into dev-gitea 2024-01-18 23:03:17 +08:00
632b13121d update some readme 2024-01-18 22:59:49 +08:00
e9ab3581aa Merge pull request 'remove requirements.txt' (#2) from dev-gitea into master
Reviewed-on: #2
2024-01-18 22:44:26 +08:00
8b0ab3bd76 Merge branch 'master' into dev-gitea 2024-01-18 22:43:30 +08:00
7a6d95d436 remove requirements.txt 2024-01-18 22:42:21 +08:00
fd26197e70 Merge pull request 'use pyproject.toml to control deps' (#1) from dev-gitea into master
Reviewed-on: #1
2024-01-18 22:40:43 +08:00
99b6b3f887 remove dev file 2024-01-18 22:35:01 +08:00
c2f0b9de48 use pyproject.toml to control deps 2024-01-18 22:29:09 +08:00
95c7f84451 use slim image 2024-01-16 00:19:01 +08:00
d1558ad6db update readme 2024-01-15 23:46:39 +08:00
76d3c7249a update gitea url 2024-01-15 21:17:44 +08:00
450ba61d22 Merge branch 'master' of https://git.mamahaha.work/sangge/waka-readme 2024-01-15 21:06:50 +08:00
3d3239a2e3 use 3.11 2024-01-15 21:06:17 +08:00
830c76c07a update requirement 2024-01-15 21:01:33 +08:00
6125862010 mute useless ci 2024-01-15 20:53:58 +08:00
b88da2af7d update requirements
Some checks failed
WakaReadme CI / UnitTests (push) Failing after 13s
2024-01-15 20:52:49 +08:00
b55e75a74d update container
Some checks failed
WakaReadme CI / UnitTests (push) Failing after 13s
2024-01-15 20:38:23 +08:00
3bc9d82ee4 feat: update action 2024-01-15 20:36:55 +08:00
980f869999 finish dev version
Some checks failed
WakaReadme CI / UnitTests (push) Failing after 26s
2024-01-15 20:02:19 +08:00
108a90abce test: update
Some checks failed
WakaReadme CI / UnitTests (push) Failing after 19s
2024-01-15 02:38:12 +08:00
Jovial Joe Jayarson
5dc349128a
Merge pull request #152 from yozachar/workshop
chore: monthly updates for Dec'23
2023-12-25 13:06:38 +05:30
Jovial Joe Jayarson
d2e7ba7208 chore: monthly updates for Dec'23 2023-12-24 22:17:15 +05:30
Jovial Joe Jayarson
2dd14d3fd8
Merge pull request #149 from yozachar/workshop
chore: monthly updates for Nov'23
2023-11-09 08:44:27 +05:30
Jovial Joe Jayarson
e644272268 chore: monthly updates for Nov'23 2023-11-08 11:48:30 +05:30
Jovial Joe Jayarson
2aab71918a
Merge pull request #148 from yozachar/workshop
chore: monthly updates for Oct'23; bump version
2023-10-23 09:48:07 +05:30
Jovial Joe Jayarson
3f2f9d748e chore: monthly updates for Oct'23; bump version 2023-10-21 08:12:29 +05:30
Andrew Hong
54c3312012
feat: adds flag IGNORE_LANGUAGES (#146)
- feat: adds flag `IGNORE_LANGUAGES`  (#146)

---------

Co-authored-by: Jovial Joe Jayarson <jovial7joe@hotmail.com>
2023-10-21 07:58:43 +05:30
Jovial Joe Jayarson
dd576f44c6
Merge pull request #144 from joe733/workshop
chore: monthly updates for Sep'23; bump version
2023-09-19 16:23:00 +05:30
Jovial Joe Jayarson
b2363ac606 chore: monthly updates for Sep'23; bump version
- fix: 0 discovered test in container
- uses containerfile for testing
- update dependencies, bump version
2023-09-17 15:55:22 +05:30
Jovial Joe Jayarson
519a95b477
Merge pull request #143 from joe733/workshop
chore: monthly updates for Aug'23; bump version
2023-08-18 08:36:43 +05:30
Jovial Joe Jayarson
ac8e6017f5 chore: monthly updates for Aug'23; bump version
- revised readme, better theming support, improved wording where needed
- granular config for ruff linter & pyright type checker, re-format code
- update dependencies, bump version
2023-08-17 11:59:26 +05:30
Jovial Joe Jayarson
ba3aa17f4e
Merge pull request #138 from joe733/workshop
patch: work around pip's secure-install bug; bump version
2023-07-20 06:01:27 +05:30
Jovial Joe Jayarson
9630bc0a2b patch: work around pip's secure-install bug; bump version
- upstream issue: https://github.com/pypa/pip/issues/9644
- runs tests within a container, uses the same `dockerfile`
- ignores `pdm.lock`, removes `requirement.txt`
- update manual contribution steps
- bumps project version

**Related Items**

_Issues_

- Closes #137
2023-07-19 18:12:28 +05:30
Jovial Joe Jayarson
78ac94ef4f
Merge pull request #135 from joe733/workshop
feat: flags to tweak commit info; bump version
2023-07-19 08:43:50 +05:30
Jovial Joe Jayarson
a3e45eb050 feat: flags to tweak commit info; bump version
- flags are now available to modify commit information
- adds these flags to `dockerfile` & `action.yml`
- fixes a few typos
- improves `Readme.md`
- updates secondary dependencies
- bumps project version

**Related Items**

_Issues_

- Closes #103
- Closes #104
- Closes #125
2023-07-18 14:01:38 +05:30
Jovial Joe Jayarson
7d29cf150e fix: license format from choosealicense.com 2023-07-18 13:31:35 +05:30
Jovial Joe Jayarson
cefd952b71
Merge pull request #134 from joe733/workshop
chore: monthly updates for July'23
2023-07-18 06:30:40 +05:30
Jovial Joe Jayarson
77ba5f6a96 chore: monthly updates for July'23
- migrate to `pdm` from `poetry`
- update dependencies
- improvises `dockerfile` (drops `containerfile`)
- only `python` & `pip` are required in ci/cd
- adds `compose.yml`
- simplifies local & containerized development
2023-07-17 08:30:12 +05:30
Jovial Joe Jayarson
c34fb893a6
Merge pull request #131 from joe733/workshop
maint: monthly updates for June '23
2023-06-14 17:30:31 +05:30
Jovial Joe Jayarson
1fc26a4121 feat: update dependencies; bump version 2023-06-14 14:13:38 +05:30
Jovial Joe Jayarson
82c9408d6d maint: follows google pydocstyle 2023-06-13 19:40:52 +05:30
Jovial Joe Jayarson
9bee9ba11b maint: migrate to black formatting 2023-06-13 19:17:26 +05:30
Jovial Joe Jayarson
b42a071671
Merge pull request #129 from athul/dependabot/pip/cryptography-41.0.0
chore(deps): bump cryptography from 40.0.2 to 41.0.0
2023-06-03 05:39:40 +05:30
dependabot[bot]
e8541dbe4e
chore(deps): bump cryptography from 40.0.2 to 41.0.0
Bumps [cryptography](https://github.com/pyca/cryptography) from 40.0.2 to 41.0.0.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/40.0.2...41.0.0)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-02 20:31:09 +00:00
Jisan
da0f4f1847
feat: Add language syntax support for color code (#128)
- feat: text highlight
- fix: wrong env, typo
2023-06-02 11:17:41 +05:30
Jovial Joe Jayarson
d26ed33e7a
Merge pull request #124 from athul/dependabot/pip/requests-2.31.0
chore(deps): bump requests from 2.29.0 to 2.31.0
2023-05-23 12:31:51 +05:30
dependabot[bot]
a50019231d
chore(deps): bump requests from 2.29.0 to 2.31.0
Bumps [requests](https://github.com/psf/requests) from 2.29.0 to 2.31.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.29.0...v2.31.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-23 06:51:25 +00:00
Jovial Joe Jayarson
080a8c9b63
Merge pull request #122 from joe733/workshop
fix: adds granularity to show more languages
2023-05-05 16:07:45 +05:30
Jovial Joe Jayarson
fbc9196645 fix: adds granularity to show more languages
- adds option `STOP_AT_OTHER` to stop retrieval at lang marked `Other`
- updates dependencies
- makes dev dependencies optional
- bumps project version
- updates readme

**Related Items**

*Issues*

- Closes #121
2023-05-04 17:15:14 +05:30
Jovial Joe Jayarson
59f35b046b
Merge pull request #120 from joe733/workshop
feat: bumped version to 0.1.9
2023-03-25 12:52:13 +05:30
Jovial Joe Jayarson
60fa45f3f0 feat: bumped version to 0.1.9
- updates dependencies
- prefer type inference with function return
- fix typos / minor improvements
- ignore all ``*.env` files
- bumped package version to 0.1.9
2023-03-25 10:05:49 +05:30
Jovial Joe Jayarson
60fe3b9f48
Merge pull request #119 from joe733/workshop
fix: adds check to find placeholder in old readme
2023-02-28 12:36:09 +05:30
Jovial Joe Jayarson
29dba6dd79 fix: adds check to find placeholder in old readme 2023-02-27 12:36:25 +05:30
Jovial Joe Jayarson
ac0bb21462 feat: bump version, update deps 2023-02-09 07:25:07 +05:30
16 changed files with 852 additions and 1443 deletions

28
.env.template Executable file
View File

@ -0,0 +1,28 @@
# Do NOT edit this file, make
# a copy and rename as `.env`
INPUT_GH_TOKEN=
INPUT_WAKATIME_API_KEY=
# meta
INPUT_API_BASE_URL=
INPUT_REPOSITORY=
# content
INPUT_SHOW_TITLE=
INPUT_SECTION_NAME=
INPUT_BLOCKS=
INPUT_CODE_LANG=
INPUT_TIME_RANGE=
INPUT_LANG_COUNT=
INPUT_SHOW_TIME=
INPUT_SHOW_TOTAL=
INPUT_SHOW_MASKED_TIME=
INPUT_STOP_AT_OTHER=
INPUT_IGNORED_LANGUAGES=
# commit
INPUT_COMMIT_MESSAGE=
INPUT_TARGET_BRANCH=
INPUT_TARGET_PATH=
INPUT_COMMITTER_NAME=
INPUT_COMMITTER_EMAIL=
INPUT_AUTHOR_NAME=
INPUT_AUTHOR_EMAIL=

View File

@ -1,26 +1,24 @@
name: UnitTests
name: WakaReadme CI
on:
push:
branches: [master]
branches: [main]
pull_request:
branches: [master]
branches: [main]
workflow_dispatch:
jobs:
build:
UnitTests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.11
uses: actions/setup-python@v4
with:
python-version: "3.11"
- name: Install dependencies
- name: Build docker image
run: |
curl -sSL https://install.python-poetry.org | python -
export PATH="$HOME/.poetry/bin:${PATH}"
poetry install
- name: Run unit tests
run: |
poetry run python -m unittest discover
# Clear existing cache
docker builder prune --force
# Build and run container (executes unit tests)
docker compose -p waka-readme -f ./compose.yml up --no-color --pull always --build --force-recreate
# Cleanup
docker compose -p waka-readme -f ./compose.yml down --rmi all

23
.gitignore vendored
View File

@ -85,21 +85,29 @@ ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
poetry.lock
# pdm
# Similar to poetry.lock, it is generally recommended to include pdm.lock in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
# However, this project does not rely on pdm for production.
pdm.lock
.pdm-python
.pdm-build
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
@ -112,7 +120,8 @@ celerybeat.pid
*.sage.py
# Environments
.env
*.env
env.sh
.venv
env/
venv/
@ -154,5 +163,9 @@ cython_debug/
# VSCode
.vscode/
# asdf
# asdf/rtx
.tool-versions
.rtx.toml
# ruff
.ruff_cache

View File

@ -1,142 +1,66 @@
# Contributing
![python_ver](https://img.shields.io/badge/python-%5E3.10-blue.svg)
![python_ver](https://img.shields.io/badge/Python-%3E%3D3.12-blue.svg)
> First off, thank you! Please follow along.
**You need to _fork_ this repository and _clone_ it, onto your system.**
**You need to _`fork`_ this repository & _`clone`_ it onto your system.** Inside the cloned folder, create a `.env` file with the following contents (without `# comments`):
## Using Docker/Podman (recommended)
```ini
INPUT_GH_TOKEN=EXAMPLE_GITHUB_PAT # required (for development)
INPUT_WAKATIME_API_KEY=EXAMPLE-WAKATIME-API-KEY # required
INPUT_API_BASE_URL=https://wakatime.com/api # required
INPUT_REPOSITORY=GITHUB_USERNAME/REPOSITORY_NAME # required
INPUT_COMMIT_MESSAGE=Updated WakaReadme graph with new metrics
INPUT_SHOW_TITLE=true
INPUT_SECTION_NAME=waka
INPUT_BLOCKS=->
INPUT_SHOW_TIME=true
INPUT_SHOW_TOTAL=true
INPUT_TIME_RANGE=last_7_days
INPUT_SHOW_MASKED_TIME=false
INPUT_LANG_COUNT=0
INPUT_STOP_AT_OTHER=true
INPUT_IGNORED_LANGUAGES=
```
> Assumes you've already installed & configured latest version of [docker](https://www.docker.com/) or [podman](https://podman.io/).
**NEVER commit this `.env` file!**
## Using containers (recommended)
> Assumes that you already have latest version of either [`podman`](https://podman.io/) or [`docker`](https://www.docker.com/) (with [`compose`](https://docs.docker.com/compose/)) installed & configured.
>
> Replace `docker` with `podman` everywhere, if you're using the latter.
> Replace `podman` with `docker` everywhere, if you're using the latter.
1. **Inside the cloned folder**, run:
```console
$ git archive -o 'waka-readme.tar.gz' HEAD
$ docker build . -f containerfile -t 'waka-readme:dev'
```
to build an image. (Image is identified as `<name>:<tag>`)
2. Then create containers and use them as dev environments.
- Temporary:
```console
$ docker run --rm -it --name 'WakaReadmeDev' 'waka-readme:dev' bash
```
- or Persistent
```console
$ docker run --detach --name 'WakaReadmeDev' 'waka-readme:dev'
```
where `WakaReadmeDev` is the docker container name. Then execute `bash` in the container:
```console
$ docker exec -it 'WakaReadmeDev' bash
```
3. For development, you can attach code editor of your choice to this container.
4. Export environnement variables with edits, as required:
```console
// inside container, create a file `.env`
# micro .env
```
paste (`Ctrl+Shift+V`) the following contents:
```env
INPUT_GH_TOKEN='<GITHUB TOKEN>'
INPUT_WAKATIME_API_KEY='<WAKATIME API KEY>'
INPUT_API_BASE_URL='https://wakatime.com/api'
INPUT_REPOSITORY='<REPOSITORY SLUG>'
INPUT_COMMIT_MESSAGE='<COMMIT MESSAGE>'
INPUT_SHOW_TITLE='True'
INPUT_SECTION_NAME='waka'
INPUT_BLOCKS='->'
INPUT_SHOW_TIME='True'
INPUT_SHOW_TOTAL='True'
INPUT_TIME_RANGE='last_7_days'
INPUT_SHOW_MASKED_TIME='True'
```
and execute program with:
```console
# poetry shell
# set -a && . ./.env && set +a # optional
(venv)# python -m main --dev
(venv)# python -m unittest discover # run tests
```
5. Later, to remove stop and remove the container:
```console
// exit container
# exit
$ docker container stop 'WakaReadmeDev'
$ docker container rm 'WakaReadmeDev'
```
```sh
# Build and watch logs
$ podman-compose -p waka-readme -f ./docker-compose.yml up
# Cleanup
$ podman-compose -p waka-readme -f ./docker-compose.yml down
```
---
> **NOTE** With VSCode on Windows
>
> Add these to `.vscode/settings.json`
>
> ```json
> {
> "terminal.integrated.commandsToSkipShell": [
> "-workbench.action.quickOpenView"
> ]
> }
> ```
>
> To quit the `micro` editor from the vscode terminal.
## Using virtual environments
---
> Assumes you've already installed & configured latest version of [python](https://www.python.org/).
## Manual
1. Inside the cloned folder run the following commands to install dependencies
> Assumes you've already installed & configured latest version of [python](https://www.python.org/) and [poetry](https://python-poetry.org/).
1. Inside the cloned folder run:
```console
$ poetry shell
(venv)$ poetry install
```sh
$ python -m venv .venv
$ . ./.venv/bin/activate
$ python -m pip install .
# ... install decencies ...
```
to create and activate a virtual environnement and install dependencies.
to activate virtual environment & install dependencies.
2. Put environment variables in a `.env` file
2. To test or execute the program in development, run:
```env
INPUT_GH_TOKEN='<GITHUB TOKEN>'
INPUT_WAKATIME_API_KEY='<WAKATIME API KEY>'
INPUT_API_BASE_URL='https://wakatime.com/api'
INPUT_REPOSITORY='<REPOSITORY SLUG>'
INPUT_COMMIT_MESSAGE='<COMMIT MESSAGE>'
INPUT_SHOW_TITLE='True'
INPUT_SECTION_NAME='waka'
INPUT_BLOCKS='->'
INPUT_SHOW_TIME='True'
INPUT_SHOW_TOTAL='True'
INPUT_TIME_RANGE='last_7_days'
INPUT_SHOW_MASKED_TIME='True'
```sh
(.venv)$ python -m unittest discover # run tests
(.venv)$ python -m main --dev # execute program in dev mode
```
3. Execute program in development mode with:
```console
$ set -a && . ./.env && set +a # optional
(venv)$ python -m main --dev
(venv)$ python -m unittest discover # run tests
```
> You can use any other virtual environment & dependency manager as well.

25
LICENSE
View File

@ -1,20 +1,21 @@
# The MIT License (MIT)
MIT License
Copyright (c) 2020 ATHUL CYRIAC AJAY
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

168
README.md
View File

@ -1,22 +1,16 @@
<center>
# Dev Metrics in Readme
![waka-readme](https://socialify.git.ci/athul/waka-readme/image?description=1&forks=1&name=1&pulls=1&stargazers=1&theme=Light)
fork from [waka-readme](https://github/athul/waka-readme)
edit for Gitea use.
</center>
# Dev Metrics in Readme [![Unit Tests](https://github.com/athul/waka-readme/actions/workflows/testing.yml/badge.svg?branch=master)](https://github.com/athul/waka-readme/actions/workflows/testing.yml) ![Python Version](https://img.shields.io/badge/python-v3.11-blue)
[WakaTime](https://wakatime.com) weekly metrics on your profile readme.
![Project Preview](https://user-images.githubusercontent.com/8397274/87243943-e6b45c00-c457-11ea-94c9-2aa0bf241be8.png)
:speech_balloon: **Forum** | [GitHub discussions][gh_discuss]
[WakaTime](https://wakatime.com) coding metrics on your profile readme.
## New to WakaTime?
> Nope? Skip to [prep work](#prep-work).
> Nope? Skip to [#Prep work](#prep-work).
WakaTime gives you an idea of the time you spent on coding. This helps you boost your productivity and competitive edge.
WakaTime gives you an idea of the time you spent on coding.
This helps you boost your productivity and competitive edge (aka _flex_ :muscle:).
1. Head over to <https://wakatime.com/> and create an account.
2. After logging in get your WakaTime API Key from <https://wakatime.com/api-key/>.
@ -24,11 +18,11 @@ WakaTime gives you an idea of the time you spent on coding. This helps you boost
4. Paste in your API key to start telemetry.
:information_source: **Info** | You can read [WakaTime help][waka_help] to know more about configurations.
Alternatively, you can also fetch data from WakaTime compatible services like [Wakapi][wakapi] or [Hakatime][hakatime].
Alternatively, you can fetch data from WakaTime compatible services such as [Wakapi][wakapi] or [Hakatime][hakatime].
## Prep Work
A GitHub repository and a `README.md` file is required. We'll be making use of readme in the [profile repository][profile_readme]\*.
A Gitea repository and a `README.md` file is required. We'll be making use of readme in the [profile repository][profile_readme].
- Save the `README.md` file after copy-pasting the following special comments. Your dev-metics will show up in between.
@ -37,60 +31,78 @@ A GitHub repository and a `README.md` file is required. We'll be making use of r
<!--END_SECTION:waka-->
```
"`waka`" can be replaced by any alphanumeric string with the `SECTION_NAME` environment variable. See the [#tweaks](#tweaks) section for more.
`<!--START_SECTION: -->` and `<!--END_SECTION: -->` are placeholders and must be retained as is. Whereas "`waka`" can be replaced by any alphanumeric string. See [#Tweaks](#tweaks) section for more.
- Navigate to your repo's `Settings > Secrets` and add a new secret _named_ `WAKATIME_API_KEY` with your API key as it's _value_.
- Navigate to your repo's `Settings`:
- Go to `Secrets` (at `https://your_gitea_url/username/.profile/settings/actions/secrets` by replacing the `USERNAME` with your own username) and add a new secret "_Named_" `WAKATIME_API_KEY` with your API key as it's "_Secret_".
> Or use the url <https://github.com/USERNAME/USERNAME/settings/secrets/actions/new> by replacing the `USERNAME` with your own username.
>
> ![new_secrets_actions][new_secrets_actions]
- If you're not using [profile repository][profile_readme], add another secret _named_ `GH_TOKEN` and insert your [GitHub token][gh_access_token]\* in place of _value_.
- Create a new workflow file (`waka-readme.yml`) inside `.github/workflows/` folder of your repository. You can create it from a template using the _actions tab_ of your repository too.
- Clear any existing contents, add the following lines and save the file.
- Create a new workflow file named `waka-readme.yml` inside `.gitea/workflows/` folder of your profile repository.
- Clear all existing contents, add following lines and save the file.
```yml
name: Waka Readme
on:
workflow_dispatch: # for manual workflow trigger
# for manual workflow trigger
workflow_dispatch:
schedule:
- cron: "0 0 * * *" # runs at every 12AM UTC
# runs at 12 AM UTC (5:30 AM IST)
- cron: "0 0 * * *"
jobs:
update-readme:
name: WakaReadme DevMetrics
runs-on: ubuntu-latest
steps:
- uses: athul/waka-readme@master
- uses: https://git.mamahaha.work/sangge/waka-readme@master # this action name
with:
WAKATIME_API_KEY: ${{ secrets.WAKATIME_API_KEY }}
# following flags are required, only if this is not on
# profile readme, remove the leading `#` to use them
#GH_TOKEN: ${{ secrets.GH_TOKEN }}
#REPOSITORY: <gh_username/gh_username>
```
Refer [#Example](#example) section for a full blown workflow file.
## Tweaks
There are many flags that you can tweak to suit your taste!
There are many flags that you can modify as you see fit.
| Flag | Default | Options | Meaning |
| ------------------ | -------------------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `API_BASE_URL` | `https://wakatime.com/api` | `https://wakatime.com/api`, `https://wakapi.dev/api`, `https://hakatime.mtx-dev.xyz/api` | Integration with WakaTime compatible services like [Wakapi][wakapi] & [Hakatime][hakatime] are possible |
| `REPOSITORY` | `<gh_username>/<gh_username>` | `<gh_username>/<repo_name>` | Waka-readme stats will appear on the provided repository |
| `SECTION_NAME` | `waka` | Any alphanumeric string | The generator will look for this section to fill up the readme. |
| `COMMIT_MESSAGE` | `Updated waka-readme graph with new metrics` | Any string | Messaged used when committing updated stats |
| `SHOW_TITLE` | `false` | `false`, `true` | Add title to waka-readme stats blob |
| `BLOCKS` | `░▒▓█` | `░▒▓█`, `⣀⣄⣤⣦⣶⣷⣿`, `-#`, you can be creative! | Ascii art used to build stats graph |
| `TIME_RANGE` | `last_7_days` | `last_7_days`, `last_30_days`, `last_6_months`, `last_year`, `all_time` | String representing a dispensation from which stats are aggregated |
| `SHOW_TIME` | `true` | `false`, `true` | Displays the amount of time spent for each language |
| `SHOW_TOTAL` | `false` | `false`, `true` | Show total coding time |
| `SHOW_MASKED_TIME` | `false` | `false`, `true` | Adds total coding time including unclassified languages (overrides: `SHOW_TOTAL`) |
| `LANG_COUNT` | `5` | Any reasonable number | Number of languages to be displayed |
### Meta Tweaks
# Example
| Environment flag | Options (`Default`, `Other`, ...) | Description |
| ---------------- | ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `API_BASE_URL` | `https://wakatime.com/api`, `https://wakapi.dev/api`, `https://hakatime.mtx-dev.xyz/api` | Use WakaTime compatible services like [Wakapi][wakapi] & [Hakatime][hakatime] |
| `REPOSITORY` | `<gh_username>/<gh_username>`, `<gh_username>/<repo_name>` | Waka-readme stats will appear on the provided repository |
### Content Tweaks
| Environment flag | Options (`Default`, `Other`, ...) | Description |
| ------------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| `SHOW_TITLE` | `false`, `true` | Add title to waka-readme stats blob |
| `SECTION_NAME` | `waka`, any alphanumeric string | The generator will look for section name to fill up the readme. |
| `BLOCKS` | `░▒▓█`, `⣀⣄⣤⣦⣶⣷⣿`, `-#`, `=>`, you can be creative | Ascii art used to build stats graph |
| `CODE_LANG` | `txt`, `python` `ruby` `json` , you can use other languages also | Language syntax based highlighted text |
| `TIME_RANGE` | `last_7_days`, `last_30_days`, `last_6_months`, `last_year`, `all_time` | String representing a dispensation from which stats are aggregated |
| `LANG_COUNT` | `5`, any plausible number | Number of languages to be displayed |
| `SHOW_TIME` | `true`, `false` | Displays the amount of time spent for each language |
| `SHOW_TOTAL` | `false`, `true` | Show total coding time |
| `SHOW_MASKED_TIME` | `false`, `true` | Adds total coding time including unclassified languages (overrides: `SHOW_TOTAL`) |
| `STOP_AT_OTHER` | `false`, `true` | Stop when language marked as `Other` is retrieved (overrides: `LANG_COUNT`) |
| `IGNORED_LANGUAGES` | <code> </code>, `Binary YAML JSON TOML` | Hide languages from your stats |
### Commit Tweaks
| Environment flag | Options (`Default`, `Other`, ...) |
| ----------------- | -------------------------------------------------------------------- |
| `COMMIT_MESSAGE` | `Updated waka-readme graph with new metrics`, any reasonable message |
| `TARGET_BRANCH` | `NOT_SET`, target branch name |
| `TARGET_PATH` | `NOT_SET`, `/path/to/target/file` |
| `COMMITTER_NAME` | `NOT_SET`, committer name |
| `COMMITTER_EMAIL` | `NOT_SET`, committer email |
| `AUTHOR_NAME` | `NOT_SET`, author name |
| `AUTHOR_EMAIL` | `NOT_SET`, author email |
The first option is the _default_ value of the _flag_, subsequent options are valid values available for the _flag_.
## Example
**`waka-readme.yml`**
@ -98,9 +110,10 @@ There are many flags that you can tweak to suit your taste!
name: Waka Readme
on:
# for manual workflow trigger
workflow_dispatch:
schedule:
# Runs at 12am UTC
# runs at 12 AM UTC (5:30 AM IST)
- cron: "0 0 * * *"
jobs:
@ -108,20 +121,42 @@ jobs:
name: WakaReadme DevMetrics
runs-on: ubuntu-latest
steps:
- uses: athul/waka-readme@master
# this action name
- uses: https://git.mamahaha.work/sangge/waka-readme@master # do NOT replace with anything else
with:
WAKATIME_API_KEY: ${{ secrets.WAKATIME_API_KEY }}
SHOW_TITLE: true
BLOCKS: ->
TIME_RANGE: all_time
SHOW_TIME: true
SHOW_MASKED_TIME: true
LANG_COUNT: 10
GH_TOKEN: ${{ secrets.GH_TOKEN }} # optional if on profile readme
WAKATIME_API_KEY: ${{ secrets.WAKATIME_API_KEY }} # required
### meta
API_BASE_URL: https://wakatime.com/api # optional
REPOSITORY: YOUR_GITEA_USERNAME/YOUR_REPOSITORY_NAME # optional
### content
SHOW_TITLE: true # optional
SECTION_NAME: waka # optional
BLOCKS: -> # optional
CODE_LANG: rust # optional
TIME_RANGE: all_time # optional
LANG_COUNT: 10 # optional
SHOW_TIME: true # optional
SHOW_TOTAL: true # optional
SHOW_MASKED_TIME: false # optional
STOP_AT_OTHER: true # optional
IGNORED_LANGUAGES: YAML JSON TOML # optional
### commit
COMMIT_MESSAGE: Updated waka-readme graph with new metrics # optional
TARGET_BRANCH: master # optional
TARGET_PATH: README.md # optional
COMMITTER_NAME: GitHubActionBot # optional
COMMITTER_EMAIL: action-bot@github.com # optional
AUTHOR_NAME: YOUR_NAME # optional
AUTHOR_EMAIL: YOUR@EMAIL.com # optional
# you can populate email-id with secretes instead
```
**`README.md`**
_Rendered `markdown`:_
```md
<!-- prettier-ignore-start -->
```rust
From: 10 July 2020 - To: 06 August 2022
Total Time: 1,464 hrs 54 mins
@ -134,20 +169,23 @@ Nim 64 hrs 31 mins >------------------------ 04.11 %
Other 47 hrs 58 mins >------------------------ 03.05 %
```
<!-- prettier-ignore-end -->
## Notes
- Flags `REPOSITORY` and `GH_TOKEN` are required ONLY if, you are NOT using [profile readme][profile_readme].
- If you are using `GH_TOKEN`, make sure set the [fine grained token](https://github.com/settings/tokens?type=beta) scope to repository contents with `read-and-write` access. See [#141 (comment)](https://github.com/athul/waka-readme/issues/141#issuecomment-1679831949).
- `WAKATIME_API_KEY` is a **required** secret. All other environment variables are optional.
- The above example does NOT show proper default values, refer [#Tweaks](#tweaks) for the same.
- `IGNORED_LANGUAGES` is suggested for [.NET](https://dotnet.microsoft.com) users, as WakaTime assumes you're working with `Binary`, while debugging.
## Why only the language stats (and not other data) from the API?
I am a fan of minimal designs and the profile readme is a great way to show off your skills and interests. The WakaTime API, gets us a **lot of data** about a person's **coding activity including the editors and Operating Systems you used and the projects you worked on**. Some of these projects maybe secretive and should not be shown out to the public. Using up more data via the Wakatime API will clutter the profile readme and hinder your chances on displaying what you provide **value to the community** like the pinned Repositories. I believe that **Coding Stats is nerdiest of all** since you can tell the community that you are **_exercising these languages or learning a new language_**, this will also show that you spend some amount of time to learn and exercise your development skills. That's what matters in the end :heart:
---
<sup>\*</sup>`REPOSITORY` flag and `GH_TOKEN` secret are required you're not using profile readme.
[//]: #(Links)
[wakapi]: https://wakapi.dev
[hakatime]: https://github.com/mujx/hakatime
[waka_plugins]: https://wakatime.com/plugins
[waka_help]: https://wakatime.com/help/editors
[profile_readme]: https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/managing-your-profile-readme
[new_secrets_actions]: https://user-images.githubusercontent.com/52720626/151221742-bc37d139-2bb3-4554-b27c-46b107d1f408.png
[gh_access_token]: https://docs.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token
[gh_discuss]: https://github.com/athul/waka-readme/discussions

View File

@ -1,73 +1,101 @@
name: "Waka - Readme"
author: Athul Cyriac Ajay
description: "Add a Wakatime Coding Activity graph in your Readme"
author: "Athul Cyriac Ajay"
description: "WakaTime coding activity graph in your profile readme"
inputs:
GH_TOKEN:
GITEA_TOKEN:
description: "GitHub access token with Repo scope"
default: ${{ github.token }}
required: true
WAKATIME_API_KEY:
description: "Your Wakatime/Wakapi/Hakatime API Key"
required: true
# meta tweaks
API_BASE_URL:
description: "Alternative API base URL when using a third-party WakaTime-ish backend"
default: "https://wakatime.com/api"
required: false
REPOSITORY:
description: "Your GitHub repository"
default: ${{ github.repository }}
required: false
COMMIT_MESSAGE:
description: "Add a commit message of your choice"
default: "Updated waka-readme graph with new metrics"
required: false
# content tweaks
SHOW_TITLE:
description: "Displays the week number and days in Readme as title"
default: "false"
required: false
SECTION_NAME:
description: "Section name for data to appear in readme"
required: false
default: "waka"
BLOCKS:
description: "Add the progress blocks of your choice"
default: "░▒▓█"
required: false
CODE_LANG:
description: "Add syntax formatter for generated code"
default: "txt"
required: false
TIME_RANGE:
description: "Time range of the queried statistics"
default: "last_7_days"
required: false
LANG_COUNT:
description: "Maximum number of languages to be shown"
default: "5"
required: false
SHOW_TIME:
description: "Displays the amount of time spent for each language"
default: "true"
required: false
SHOW_TOTAL:
description: "Displays total coding time"
default: "false"
required: false
SHOW_MASKED_TIME:
description: "Displays total coding time including unclassified languages"
default: "false"
required: false
STOP_AT_OTHER:
description: "Stop data retrieval when language marked 'Other' is reached"
default: "false"
required: false
IGNORED_LANGUAGES:
description: "Ignore space separated, listed languages"
default: ""
required: false
# commit tweaks
COMMIT_MESSAGE:
description: "Add a commit message of your choice"
default: "Updated waka-readme graph with new metrics"
required: false
TARGET_BRANCH:
description: "Target branch"
default: "NOT_SET"
required: false
TARGET_PATH:
description: "Target file path"
default: "NOT_SET"
required: false
COMMITTER_NAME:
description: "Committer name"
default: "NOT_SET"
required: false
COMMITTER_EMAIL:
description: "Committer email"
default: "NOT_SET"
required: false
AUTHOR_NAME:
description: "Author name"
default: "NOT_SET"
required: false
AUTHOR_EMAIL:
description: "Author email"
default: "NOT_SET"
required: false
runs:
using: "docker"

10
compose.yml Normal file
View File

@ -0,0 +1,10 @@
# for CI testing
services:
waka-readme:
env_file:
- .env.template
build:
context: .
dockerfile: containerfile
image: waka-readme:testing
container_name: WakaReadmeTesting

View File

@ -1,28 +1,51 @@
FROM python:slim-bullseye
FROM docker.io/python:3-slim
WORKDIR /root/waka-readme/
ENV INPUT_GITEA_TOKEN \
INPUT_WAKATIME_API_KEY \
# meta
INPUT_API_BASE_URL \
INPUT_REPOSITORY \
# content
INPUT_SHOW_TITLE \
INPUT_SECTION_NAME \
INPUT_BLOCKS \
INPUT_CODE_LANG \
INPUT_TIME_RANGE \
INPUT_LANG_COUNT \
INPUT_SHOW_TIME \
INPUT_SHOW_TOTAL \
INPUT_SHOW_MASKED_TIME \
INPUT_STOP_AT_OTHER \
INPUT_IGNORED_LANGUAGES \
# commit
INPUT_COMMIT_MESSAGE \
INPUT_TARGET_BRANCH \
INPUT_TARGET_PATH \
INPUT_COMMITTER_NAME \
INPUT_COMMITTER_EMAIL \
INPUT_AUTHOR_NAME \
INPUT_AUTHOR_EMAIL
ENV PYTHONFAULTHANDLER=1 \
ENV PATH="${PATH}:/root/.local/bin" \
# python
PYTHONFAULTHANDLER=1 \
PYTHONUNBUFFERED=1 \
PYTHONHASHSEED=random \
PYTHONDONTWRITEBYTECODE=1 \
# pip:
PIP_NO_CACHE_DIR=off \
PIP_DISABLE_PIP_VERSION_CHECK=on \
PIP_DEFAULT_TIMEOUT=100 \
# poetry:
# POETRY_VERSION=1.1.14 \
POETRY_NO_INTERACTION=1 \
POETRY_CACHE_DIR=/var/cache/pypoetry \
PATH=${PATH}:/root/.local/bin
# pip
PIP_DISABLE_PIP_VERSION_CHECK=1 \
PIP_NO_CACHE_DIR=1 \
PIP_DEFAULT_TIMEOUT=100
# import project
ADD waka-readme.tar.gz .
# copy project files
COPY --chown=root:root pyproject.toml main.py /app/
# install poetry & dependencies
RUN apt-get update && apt-get install --no-install-recommends -y curl git micro \
&& curl -sSL https://install.python-poetry.org | python - \
&& poetry install --no-root --no-ansi
# install dependencies
RUN python -m pip install /app/ -i https://pypi.tuna.tsinghua.edu.cn/simple
# copy and run program
CMD [ "sleep", "infinity" ]
# copy tests
COPY --chown=root:root tests /app/tests/
# run tests
CMD python -m unittest discover /app/

9
docker-compose.yml Normal file
View File

@ -0,0 +1,9 @@
services:
waka-readme:
env_file:
- .env
build:
context: .
dockerfile: dockerfile
image: waka-readme:dev
container_name: WakaReadmeDev

View File

@ -1,26 +1,48 @@
FROM python:slim-bullseye
FROM docker.io/python:3-slim
ENV PYTHONFAULTHANDLER=1 \
ENV INPUT_GH_TOKEN \
INPUT_WAKATIME_API_KEY \
# meta
INPUT_API_BASE_URL \
INPUT_REPOSITORY \
# content
INPUT_SHOW_TITLE \
INPUT_SECTION_NAME \
INPUT_BLOCKS \
INPUT_CODE_LANG \
INPUT_TIME_RANGE \
INPUT_LANG_COUNT \
INPUT_SHOW_TIME \
INPUT_SHOW_TOTAL \
INPUT_SHOW_MASKED_TIME \
INPUT_STOP_AT_OTHER \
INPUT_IGNORED_LANGUAGES \
# commit
INPUT_COMMIT_MESSAGE \
INPUT_TARGET_BRANCH \
INPUT_TARGET_PATH \
INPUT_COMMITTER_NAME \
INPUT_COMMITTER_EMAIL \
INPUT_AUTHOR_NAME \
INPUT_AUTHOR_EMAIL
ENV PATH="${PATH}:/root/.local/bin" \
# python
PYTHONFAULTHANDLER=1 \
PYTHONUNBUFFERED=1 \
PYTHONHASHSEED=random \
PYTHONDONTWRITEBYTECODE=1 \
# pip:
PIP_NO_CACHE_DIR=off \
PIP_DISABLE_PIP_VERSION_CHECK=on \
PIP_DEFAULT_TIMEOUT=100 \
# poetry:
# POETRY_VERSION=1.1.14 \
POETRY_NO_INTERACTION=1 \
POETRY_CACHE_DIR=/var/cache/pypoetry \
PATH=${PATH}:/root/.local/bin
# pip
PIP_DISABLE_PIP_VERSION_CHECK=1 \
PIP_NO_CACHE_DIR=1 \
PIP_DEFAULT_TIMEOUT=100
# copy project files
COPY pyproject.toml poetry.lock main.py /
COPY --chown=root:root pyproject.toml main.py /app/
# install poetry & dependencies
RUN apt-get update && apt-get install --no-install-recommends -y curl \
&& curl -sSL https://install.python-poetry.org | python - \
&& poetry install --no-root --no-ansi --only main
# install dependencies
RUN python -m pip install /app/ -i https://pypi.tuna.tsinghua.edu.cn/simple
# copy and run program
CMD [ "poetry", "run", "python", "/main.py" ]
# execute program
CMD python /app/main.py

546
main.py
View File

@ -1,25 +1,20 @@
"""
WakaReadme : WakaTime progress visualizer
=========================================
"""WakaReadme : WakaTime progress visualizer.
Wakatime Metrics on your Profile Readme.
Title:
------
```txt
From: 15 February, 2022 - To: 22 February, 2022
````
Byline:
-------
```txt
Total: 34 hrs 43 mins
```
Body:
-----
```txt
Python 27 hrs 29 mins 77.83 %
@ -29,60 +24,59 @@ TOML 1 hr 48 mins ⣿⣤⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀
Other 35 mins 01.68 %
```
#### Contents = Title + Byline + Body
Contents := Title + Byline + Body
"""
# standard
from base64 import b64encode, b64decode
from dataclasses import dataclass
from random import SystemRandom
from datetime import datetime
from base64 import b64encode
from functools import partial
import logging as logger
import os
from random import SystemRandom
import re
import sys
from time import sleep
from typing import Any
import sys
import re
import os
# external
# # requests
from requests.exceptions import RequestException
from requests import get as rq_get
# # github
from github import GithubException, Github
# # faker
from faker import Faker
# pylint: disable = logging-fstring-interpolation
# from github import ContentFile, Github, GithubException, InputGitAuthor, Repository
import gitea
from requests import get as rq_get
from requests.exceptions import RequestException
################### setup ###################
print()
# hush existing loggers
# pylint: disable = no-member # see: https://stackoverflow.com/q/20965287
for lgr_name in logger.root.manager.loggerDict:
# to disable log propagation completely set '.propagate = False'
logger.getLogger(lgr_name).setLevel(logger.WARNING)
# pylint: enable = no-member
# somehow github.Requester gets missed out from loggerDict
logger.getLogger('github.Requester').setLevel(logger.WARNING)
logger.getLogger("github.Requester").setLevel(logger.WARNING)
# configure logger
logger.basicConfig(
datefmt='%Y-%m-%d %H:%M:%S',
format='[%(asctime)s] ln. %(lineno)-3d %(levelname)-8s %(message)s',
level=logger.DEBUG
datefmt="%Y-%m-%d %H:%M:%S",
format="[%(asctime)s] ln. %(lineno)-3d %(levelname)-8s %(message)s",
level=logger.DEBUG,
)
try:
if len(sys.argv) == 2 and sys.argv[1] == '--dev':
if len(sys.argv) == 2 and sys.argv[1] == "--dev":
# get env-vars from .env file for development
from dotenv import load_dotenv
# comment this out to disable colored logging
from loguru import logger
logger.debug("loguru loaded")
# load from .env before class def gets parsed
load_dotenv()
logger.debug("dotenv loaded")
waka_key: str | None = os.getenv("INPUT_WAKATIME_API_KEY")
except ImportError as im_err:
logger.warning(im_err)
@ -90,32 +84,39 @@ except ImportError as im_err:
################### lib-func ###################
def strtobool(val: str | bool) -> bool:
"""
strtobool
---------
def strtobool(val: str | bool):
"""Strtobool.
PEP 632 https://www.python.org/dev/peps/pep-0632/ is depreciating distutils.
This is from the official source code with slight modifications.
Converts a string representation of truth to True or False.
Converts a string representation of truth to `True` or `False`.
- True values are `'y', 'yes', 't', 'true', 'on', and '1'`
- False values are `'n', 'no', 'f', 'false', 'off', and '0'`
- Raises `ValueError` if `val` is anything else.
Args:
val:
Value to be converted to bool.
Returns:
(Literal[True]):
If `val` is any of 'y', 'yes', 't', 'true', 'on', or '1'.
(Literal[False]):
If `val` is any of 'n', 'no', 'f', 'false', 'off', and '0'.
Raises:
ValueError: If `val` is anything else.
"""
if isinstance(val, bool):
return val
val = val.lower()
if val in {'y', 'yes', 't', 'true', 'on', '1'}:
if val in {"y", "yes", "t", "true", "on", "1"}:
return True
if val in {'n', 'no', 'f', 'false', 'off', '0'}:
if val in {"n", "no", "f", "false", "off", "0"}:
return False
raise ValueError(f'invalid truth value for {val}')
raise ValueError(f"invalid truth value for {val}")
################### data ###################
@ -123,54 +124,61 @@ def strtobool(val: str | bool) -> bool:
@dataclass(slots=True)
class WakaInput:
"""
WakaReadme Input Env Variables
------------------------------
"""
"""WakaReadme Input Env Variables."""
# constants
prefix_length: int = 16
graph_length: int = 25
# mapped environment variables
# # required
gh_token: str | None = os.getenv('INPUT_GH_TOKEN')
waka_key: str | None = os.getenv('INPUT_WAKATIME_API_KEY')
api_base_url: str | None = os.getenv(
'INPUT_API_BASE_URL', 'https://wakatime.com/api'
)
repository: str | None = os.getenv('INPUT_REPOSITORY')
gitea_token: str | None = os.getenv("INPUT_GITEA_TOKEN")
gitea_url: str | None = os.getenv("GITHUB_SERVER_URL", "https://gitea.com")
waka_key: str | None = os.getenv("INPUT_WAKATIME_API_KEY")
api_base_url: str | None = os.getenv("INPUT_API_BASE_URL", "https://wakatime.com/api")
repository: str | None = os.getenv("INPUT_REPOSITORY", ".profile")
# # depends
commit_message: str = os.getenv(
'INPUT_COMMIT_MESSAGE', 'Updated WakaReadme graph with new metrics'
"INPUT_COMMIT_MESSAGE", "Updated WakaReadme graph with new metrics"
)
_section_name: str = os.getenv('INPUT_SECTION_NAME', 'waka')
start_comment: str = f'<!--START_SECTION:{_section_name}-->'
end_comment: str = f'<!--END_SECTION:{_section_name}-->'
waka_block_pattern: str = f'{start_comment}[\\s\\S]+{end_comment}'
code_lang: str = os.getenv("INPUT_CODE_LANG", "txt")
_section_name: str = os.getenv("INPUT_SECTION_NAME", "waka")
start_comment: str = f"<!--START_SECTION:{_section_name}-->"
end_comment: str = f"<!--END_SECTION:{_section_name}-->"
waka_block_pattern: str = f"{start_comment}[\\s\\S]+{end_comment}"
# # optional
show_title: str | bool = os.getenv('INPUT_SHOW_TITLE') or False
block_style: str = os.getenv('INPUT_BLOCKS', '░▒▓█')
time_range: str = os.getenv('INPUT_TIME_RANGE', 'last_7_days')
show_time: str | bool = os.getenv('INPUT_SHOW_TIME') or False
show_total_time: str | bool = os.getenv('INPUT_SHOW_TOTAL') or False
show_masked_time: str | bool = os.getenv('INPUT_SHOW_MASKED_TIME') or False
language_count: str | int = os.getenv('INPUT_LANG_COUNT') or 5
show_title: str | bool = os.getenv("INPUT_SHOW_TITLE") or False
block_style: str = os.getenv("INPUT_BLOCKS", "░▒▓█")
time_range: str = os.getenv("INPUT_TIME_RANGE", "last_7_days")
show_time: str | bool = os.getenv("INPUT_SHOW_TIME") or False
show_total_time: str | bool = os.getenv("INPUT_SHOW_TOTAL") or False
show_masked_time: str | bool = os.getenv("INPUT_SHOW_MASKED_TIME") or False
language_count: str | int = os.getenv("INPUT_LANG_COUNT") or 5
stop_at_other: str | bool = os.getenv("INPUT_STOP_AT_OTHER") or False
ignored_languages: str = os.getenv("INPUT_IGNORED_LANGUAGES", "")
# # optional meta
target_branch: str = os.getenv("INPUT_TARGET_BRANCH", "NOT_SET")
target_path: str = os.getenv("INPUT_TARGET_PATH", "NOT_SET")
committer_name: str = os.getenv("INPUT_COMMITTER_NAME", "NOT_SET")
committer_email: str = os.getenv("INPUT_COMMITTER_EMAIL", "NOT_SET")
author_name: str = os.getenv("INPUT_AUTHOR_NAME", "NOT_SET")
author_email: str = os.getenv("INPUT_AUTHOR_EMAIL", "NOT_SET")
def validate_input(self) -> bool:
"""
Validate Input Env Variables
----------------------------
"""
logger.debug('Validating input variables')
if not self.gh_token or not self.waka_key or not self.api_base_url or not self.repository:
logger.error('Invalid inputs')
logger.info('Refer https://github.com/athul/waka-readme')
def validate_input(self):
"""Validate Input Env Variables."""
logger.debug("Validating input variables")
if (
not self.gitea_token
or not self.waka_key
or not self.api_base_url
or not self.repository
):
logger.error("Invalid inputs")
logger.info("Refer https://github.com/athul/waka-readme")
return False
if len(self.commit_message) < 1:
logger.error(
'Commit message length must be greater than 1 character long'
)
logger.error("Commit message length must be greater than 1 character long")
return False
try:
@ -178,275 +186,373 @@ class WakaInput:
self.show_time = strtobool(self.show_time)
self.show_total_time = strtobool(self.show_total_time)
self.show_masked_time = strtobool(self.show_masked_time)
self.stop_at_other = strtobool(self.stop_at_other)
except (ValueError, AttributeError) as err:
logger.error(err)
return False
if not self._section_name.isalnum():
logger.warning('Section name must be in any of [[a-z][A-Z][0-9]]')
logger.debug('Using default section name: waka')
self._section_name = 'waka'
self.start_comment = f'<!--START_SECTION:{self._section_name}-->'
self.end_comment = f'<!--END_SECTION:{self._section_name}-->'
self.waka_block_pattern = f'{self.start_comment}[\\s\\S]+{self.end_comment}'
logger.warning("Section name must be in any of [[a-z][A-Z][0-9]]")
logger.debug("Using default section name: waka")
self._section_name = "waka"
self.start_comment = f"<!--START_SECTION:{self._section_name}-->"
self.end_comment = f"<!--END_SECTION:{self._section_name}-->"
self.waka_block_pattern = f"{self.start_comment}[\\s\\S]+{self.end_comment}"
if len(self.block_style) < 2:
logger.warning('Graph block must be longer than 2 characters')
logger.debug('Using default blocks: ░▒▓█')
self.block_style = '░▒▓█'
logger.warning("Graph block must be longer than 2 characters")
logger.debug("Using default blocks: ░▒▓█")
self.block_style = "░▒▓█"
if self.time_range not in {
'last_7_days', 'last_30_days', 'last_6_months', 'last_year', 'all_time'
}: # 'all_time' is un-documented, should it be used?
logger.warning('Invalid time range')
logger.debug('Using default time range: last_7_days')
self.time_range = 'last_7_days'
"last_7_days",
"last_30_days",
"last_6_months",
"last_year",
"all_time",
}: # "all_time" is un-documented, should it be used?
logger.warning("Invalid time range")
logger.debug("Using default time range: last_7_days")
self.time_range = "last_7_days"
if not str(self.language_count).isnumeric():
logger.warning('Invalid language count')
logger.debug('Using default language count: 5')
try:
self.language_count = int(self.language_count)
if self.language_count < -1:
raise ValueError
except ValueError:
logger.warning("Invalid language count")
logger.debug("Using default language count: 5")
self.language_count = 5
logger.debug('Input validation complete\n')
for option in (
"target_branch",
"target_path",
"committer_name",
"committer_email",
"author_name",
"author_email",
):
if not getattr(self, option):
logger.warning(f"Improper '{option}' configuration")
logger.debug(f"Using default '{option}'")
setattr(self, option, "NOT_SET")
logger.debug("Input validation complete\n")
return True
################### logic ###################
def make_title(dawn: str | None, dusk: str | None, /) -> str:
"""
WakaReadme Title
----------------
def make_title(dawn: str | None, dusk: str | None, /):
"""WakaReadme Title.
Makes title for WakaReadme.
"""
logger.debug('Making title')
logger.debug("Making title")
if not dawn or not dusk:
logger.error('Cannot find start/end date\n')
logger.error("Cannot find start/end date\n")
sys.exit(1)
api_dfm, msg_dfm = '%Y-%m-%dT%H:%M:%SZ', '%d %B %Y'
api_dfm, msg_dfm = "%Y-%m-%dT%H:%M:%SZ", "%d %B %Y"
try:
start_date = datetime.strptime(dawn, api_dfm).strftime(msg_dfm)
end_date = datetime.strptime(dusk, api_dfm).strftime(msg_dfm)
except ValueError as err:
logger.error(f'{err}\n')
logger.error(f"{err}\n")
sys.exit(1)
logger.debug('Title was made\n')
return f'From: {start_date} - To: {end_date}'
logger.debug("Title was made\n")
return f"From: {start_date} - To: {end_date}"
def make_graph(block_style: str, percent: float, gr_len: int, lg_nm: str = '', /) -> str:
"""
WakaReadme Graph
----------------
def make_graph(block_style: str, percent: float, gr_len: int, lg_nm: str = "", /):
"""WakaReadme Graph.
Makes time graph from the API's data.
"""
logger.debug(f'Generating graph for "{lg_nm or "..."}"')
logger.debug(f"Generating graph for '{lg_nm or '...'}'")
markers = len(block_style) - 1
proportion = percent / 100 * gr_len
graph_bar = block_style[-1] * int(proportion + 0.5 / markers)
remainder_block = int(
(proportion - len(graph_bar)) * markers + 0.5
)
graph_bar += block_style[remainder_block] if remainder_block > 0 else ''
remainder_block = int((proportion - len(graph_bar)) * markers + 0.5)
graph_bar += block_style[remainder_block] if remainder_block > 0 else ""
graph_bar += block_style[0] * (gr_len - len(graph_bar))
logger.debug(f'"{lg_nm or "..."}" graph generated')
logger.debug(f"'{lg_nm or '...'}' graph generated")
return graph_bar
def prep_content(stats: dict[str, Any], language_count: int = 5, /) -> str:
"""
WakaReadme Prepare Markdown
---------------------------
def prep_content(stats: dict[str, Any], /):
"""WakaReadme Prepare Markdown.
Prepared markdown content from the fetched statistics
Prepared markdown content from the fetched statistics.
```
"""
logger.debug('Making contents')
contents = ''
logger.debug("Making contents")
contents = ""
# make title
if wk_i.show_title:
contents += make_title(stats.get('start'), stats.get('end')) + '\n\n'
contents += make_title(stats.get("start"), stats.get("end")) + "\n\n"
# make byline
if wk_i.show_masked_time and (
total_time := stats.get('human_readable_total_including_other_language')
total_time := stats.get("human_readable_total_including_other_language")
):
# overrides 'human_readable_total'
contents += f'Total Time: {total_time}\n\n'
elif wk_i.show_total_time and (
total_time := stats.get('human_readable_total')
):
contents += f'Total Time: {total_time}\n\n'
# overrides "human_readable_total"
contents += f"Total Time: {total_time}\n\n"
elif wk_i.show_total_time and (total_time := stats.get("human_readable_total")):
contents += f"Total Time: {total_time}\n\n"
lang_info: list[dict[str, int | float | str]] | None = []
# Check if any language data exists
if not (lang_info := stats.get('languages')):
logger.debug('The API data seems to be empty, please wait for a day')
contents += 'No activity tracked'
return contents
if not (lang_info := stats.get("languages")):
logger.debug("The API data seems to be empty, please wait for a day")
contents += "No activity tracked"
return contents.rstrip("\n")
# make lang content
pad_len = len(
# comment if it feels way computationally expensive
max((str(lng['name']) for lng in lang_info), key=len)
# and then don't for get to set pad_len to say 13 :)
max((str(lng["name"]) for lng in lang_info), key=len)
# and then do not for get to set `pad_len` to say 13 :)
)
language_count, stop_at_other = int(wk_i.language_count), bool(wk_i.stop_at_other)
if language_count == 0 and not wk_i.stop_at_other:
logger.debug(
"Set INPUT_LANG_COUNT to -1 to retrieve all language"
+ " or specify a positive number (ie. above 0)"
)
return contents.rstrip("\n")
ignored_languages = set[str](igl.lower() for igl in wk_i.ignored_languages.strip().split())
for idx, lang in enumerate(lang_info):
lang_name = str(lang['name'])
# >>> add languages to filter here <<<
# if lang_name in {...}: continue
lang_time = str(lang['text']) if wk_i.show_time else ''
lang_ratio = float(lang['percent'])
lang_bar = make_graph(
wk_i.block_style, lang_ratio, wk_i.graph_length, lang_name
)
lang_name = str(lang["name"])
if ignored_languages and lang_name.lower() in ignored_languages:
continue
lang_time = str(lang["text"]) if wk_i.show_time else ""
lang_ratio = float(lang["percent"])
lang_bar = make_graph(wk_i.block_style, lang_ratio, wk_i.graph_length, lang_name)
contents += (
f'{lang_name.ljust(pad_len)} ' +
f'{lang_time: <16}{lang_bar} ' +
f'{lang_ratio:.2f}'.zfill(5) + ' %\n'
f"{lang_name.ljust(pad_len)} "
+ f"{lang_time: <16}{lang_bar} "
+ f"{lang_ratio:.2f}".zfill(5)
+ " %\n"
)
if idx >= language_count or lang_name == 'Other':
if language_count == -1:
continue
if stop_at_other and (lang_name == "Other"):
break
if idx + 1 >= language_count > 0: # idx starts at 0
break
logger.debug('Contents were made\n')
return contents.rstrip('\n')
logger.debug("Contents were made\n")
return contents.rstrip("\n")
def fetch_stats() -> dict[str, Any] | None:
"""
WakaReadme Fetch Stats
----------------------
def fetch_stats():
"""WakaReadme Fetch Stats.
Returns statistics as JSON string
Returns statistics as JSON string.
"""
attempts = 4
statistic: dict[str, dict[str, Any]] = {}
encoded_key = str(
b64encode(bytes(str(wk_i.waka_key), 'utf-8')), 'utf-8'
)
logger.debug(
f'Pulling WakaTime stats from {" ".join(wk_i.time_range.split("_"))}'
)
encoded_key = str(b64encode(bytes(str(wk_i.waka_key), "utf-8")), "utf-8")
logger.debug(f"Pulling WakaTime stats from {' '.join(wk_i.time_range.split('_'))}")
while attempts > 0:
resp_message, fake_ua = '', cryptogenic.choice(
[str(fake.user_agent()) for _ in range(5)]
)
resp_message, fake_ua = "", cryptogenic.choice([str(fake.user_agent()) for _ in range(5)])
# making a request
if (resp := rq_get(
url=f'{str(wk_i.api_base_url).rstrip("/")}/v1/users/current/stats/{wk_i.time_range}',
if (
resp := rq_get(
url=f"{str(wk_i.api_base_url).rstrip('/')}/v1/users/current/stats/{wk_i.time_range}",
headers={
'Authorization': f'Basic {encoded_key}',
'User-Agent': fake_ua,
"Authorization": f"Basic {encoded_key}",
"User-Agent": fake_ua,
},
timeout=30 * (5 - attempts)
)).status_code != 200:
resp_message += f'{conn_info}' if (
conn_info := resp.json().get('message')
) else ''
timeout=(30.0 * (5 - attempts)),
)
).status_code != 200:
resp_message += f"{conn_info}" if (conn_info := resp.json().get("message")) else ""
logger.debug(
f'API response #{5 - attempts}: {resp.status_code}{resp.reason}{resp_message}'
f"API response #{5 - attempts}: {resp.status_code}" + f" {resp.reason}{resp_message}"
)
if resp.status_code == 200 and (statistic := resp.json()):
logger.debug('Fetched WakaTime statistics')
logger.debug("Fetched WakaTime statistics")
break
logger.debug(f'Retrying in {30 * (5 - attempts )}s ...')
logger.debug(f"Retrying in {30 * (5 - attempts )}s ...")
sleep(30 * (5 - attempts))
attempts -= 1
if err := (statistic.get('error') or statistic.get('errors')):
logger.error(f'{err}\n')
if err := (statistic.get("error") or statistic.get("errors")):
logger.error(f"{err}\n")
sys.exit(1)
print()
return statistic.get('data')
return statistic.get("data")
def churn(old_readme: str, /) -> str | None:
def churn(old_readme: str, /):
"""WakaReadme Churn.
Composes WakaTime stats within markdown code snippet.
"""
WakaReadme Churn
----------------
Composes WakaTime stats within markdown code snippet
"""
# getting content
# check if placeholder pattern exists in readme
if not re.findall(wk_i.waka_block_pattern, old_readme):
logger.warning(f"Cannot find `{wk_i.waka_block_pattern}` pattern in readme")
return None
# getting contents
if not (waka_stats := fetch_stats()):
logger.error('Unable to fetch data, please rerun workflow\n')
logger.error("Unable to fetch data, please rerun workflow\n")
sys.exit(1)
# processing content
# preparing contents
try:
generated_content = prep_content(waka_stats, int(wk_i.language_count))
generated_content = prep_content(waka_stats)
except (AttributeError, KeyError, ValueError) as err:
logger.error(f'Unable to read API data | {err}\n')
logger.error(f"Unable to read API data | {err}\n")
sys.exit(1)
print(generated_content, '\n', sep='')
print(generated_content, "\n", sep="")
# substituting old contents
new_readme = re.sub(
pattern=wk_i.waka_block_pattern,
repl=f'{wk_i.start_comment}\n\n```text\n{generated_content}\n```\n\n{wk_i.end_comment}',
string=old_readme
repl=f"{wk_i.start_comment}\n\n```{wk_i.code_lang}\n{generated_content}\n```\n\n{wk_i.end_comment}",
string=old_readme,
)
if len(sys.argv) == 2 and sys.argv[1] == '--dev':
logger.debug('Detected run in `dev` mode.')
logger.debug(new_readme)
if len(sys.argv) == 2 and sys.argv[1] == "--dev":
logger.debug("Detected run in `dev` mode.")
# to avoid accidentally writing back to Github
# when developing and testing WakaReadme
# when developing or testing waka-readme
return None
return None if new_readme == old_readme else new_readme
def genesis() -> None:
"""Run Program"""
logger.debug('Connecting to GitHub')
gh_connect = Github(wk_i.gh_token)
# since a validator is being used casting to string here is okay
gh_repo = gh_connect.get_repo(str(wk_i.repository))
readme_file = gh_repo.get_readme()
logger.debug('Decoding readme contents\n')
readme_contents = str(readme_file.decoded_content, encoding='utf-8')
if new_content := churn(readme_contents):
logger.debug('WakaReadme stats has changed')
gh_repo.update_file(
path=readme_file.path,
message=wk_i.commit_message,
content=new_content,
sha=readme_file.sha
# def qualify_target(gitea_repo: Repository.Repository):
def qualify_target(gitea_repo: gitea.Repository, gitea_connect: gitea.Gitea):
"""Qualify target repository defaults."""
@dataclass
class TargetRepository:
# this: ContentFile.ContentFile
this: gitea.Content
path: str
commit_message: str
sha: str
branch: str
# committer: InputGitAuthor | None
# author: InputGitAuthor | None
committer: None
author: None
gitea_branch = gitea_repo.get_branches()[0].name
# if wk_i.target_branch != "NOT_SET":
# gitea_branch = gitea_repo.get_branch(wk_i.target_branch)
readme_content = gitea.Content(gitea_connect)
readme_content.path = "README.md"
readme_content.type = gitea.Content.FILE
target = gitea_repo.get_file_content(readme_content) # base64 encoded
# target = gitea_repo.get_readme()
# if wk_i.target_path != "NOT_SET":
# target = gitea_repo.get_contents(
# path=wk_i.target_path,
# ref=gitea_branch if isinstance(gitea_branch, str) else gitea_branch.commit.sha,
# )
if isinstance(target, list):
raise RuntimeError("Cannot handle multiple files.")
committer, author = None, None
# if wk_i.committer_name != "NOT_SET" and wk_i.committer_email != "NOT_SET":
# committer = InputGitAuthor(name=wk_i.committer_name, email=wk_i.committer_email)
# if wk_i.author_name != "NOT_SET" and wk_i.author_email != "NOT_SET":
# author = InputGitAuthor(name=wk_i.author_name, email=wk_i.author_email)
sha = ""
return TargetRepository(
this=target,
path="README.md",
commit_message=wk_i.commit_message,
sha=sha,
branch=gitea_branch if isinstance(gitea_branch, str) else gitea_branch.name,
committer=committer,
author=author,
)
logger.info('Stats updated successfully')
def genesis():
"""Run Program."""
logger.debug("Connecting to Gitea")
gitea_connect = gitea.Gitea(wk_i.gitea_url, wk_i.gitea_token)
logger.debug("logged into gitea\n")
# since a validator is being used earlier, casting
# `wk_i.ENV_VARIABLE` to a string here, is okay
# gitea_repo = gitea_connect.get_repo(str(wk_i.repository))
owner = "sangge"
repo_name = ".profile"
gitea_repo = gitea.Repository.request(gitea_connect, owner, repo_name)
if len(sys.argv) == 2 and sys.argv[1] == "--dev":
logger.debug("Detected run in `dev` mode.,fetched repo \n")
target = qualify_target(gitea_repo, gitea_connect)
logger.debug("Decoding readme contents\n")
readme_contents = str(b64decode(target.this), encoding="utf-8")
if not (new_content := churn(readme_contents)):
logger.info("WakaReadme was not updated")
return
logger.info('WakaReadme was not updated')
logger.debug("WakaReadme stats has changed")
# update_metric = partial(
# gitea_repo.update_file,
# path=target.path,
# message=target.commit_message,
# content=new_content,
# sha=target.sha,
# branch=target.branch,
# )
# if target.committer:
# update_metric = partial(update_metric, committer=target.committer)
# if target.author:
# update_metric = partial(update_metric, author=target.author)
# update_metric()
b64_new_content = b64encode(bytes(new_content, "utf-8"))
repo_content = gitea_repo.get_git_content()
readmes = [c for c in repo_content if c.name == "README.md"]
str_new_content = b64_new_content.decode("utf-8")
gitea_repo.change_file(readmes[0].name, readmes[0].sha, str_new_content)
logger.info("Stats updated successfully")
return
################### driver ###################
if __name__ == '__main__':
if __name__ == "__main__":
# faker data preparation
fake = Faker()
Faker.seed(0)
cryptogenic = SystemRandom()
# initial waka-readme setup
logger.debug('Initialize WakaReadme')
logger.debug("Initialize WakaReadme")
wk_i = WakaInput()
if not wk_i.validate_input():
logger.error('Environment variables are misconfigured\n')
logger.error("Environment variables are misconfigured\n")
sys.exit(1)
# run
try:
genesis()
except KeyboardInterrupt:
print()
logger.error('Interrupt signal received\n')
print("\r", end=" ")
logger.error("Interrupt signal received\n")
sys.exit(1)
except (GithubException, RequestException) as rq_exp:
logger.critical(f'{rq_exp}\n')
except RuntimeError as err:
logger.error(f"{type(err).__name__}: {err}\n")
sys.exit(1)
print('\nThanks for using WakaReadme!\n')
# except (GithubException, RequestException) as rq_exp:
# logger.critical(f"{rq_exp}\n")
# sys.exit(1)
print("\nThanks for using WakaReadme!\n")

846
poetry.lock generated
View File

@ -1,846 +0,0 @@
# This file is automatically @generated by Poetry and should not be changed by hand.
[[package]]
name = "astroid"
version = "2.14.1"
description = "An abstract syntax tree for Python with inference support."
category = "dev"
optional = false
python-versions = ">=3.7.2"
files = [
{file = "astroid-2.14.1-py3-none-any.whl", hash = "sha256:23c718921acab5f08cbbbe9293967f1f8fec40c336d19cd75dc12a9ea31d2eb2"},
{file = "astroid-2.14.1.tar.gz", hash = "sha256:bd1aa4f9915c98e8aaebcd4e71930154d4e8c9aaf05d35ac0a63d1956091ae3f"},
]
[package.dependencies]
lazy-object-proxy = ">=1.4.0"
wrapt = {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}
[[package]]
name = "autopep8"
version = "2.0.1"
description = "A tool that automatically formats Python code to conform to the PEP 8 style guide"
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
{file = "autopep8-2.0.1-py2.py3-none-any.whl", hash = "sha256:be5bc98c33515b67475420b7b1feafc8d32c1a69862498eda4983b45bffd2687"},
{file = "autopep8-2.0.1.tar.gz", hash = "sha256:d27a8929d8dcd21c0f4b3859d2d07c6c25273727b98afc984c039df0f0d86566"},
]
[package.dependencies]
pycodestyle = ">=2.10.0"
[[package]]
name = "bandit"
version = "1.7.4"
description = "Security oriented static analyser for python code."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "bandit-1.7.4-py3-none-any.whl", hash = "sha256:412d3f259dab4077d0e7f0c11f50f650cc7d10db905d98f6520a95a18049658a"},
{file = "bandit-1.7.4.tar.gz", hash = "sha256:2d63a8c573417bae338962d4b9b06fbc6080f74ecd955a092849e1e65c717bd2"},
]
[package.dependencies]
colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""}
GitPython = ">=1.0.1"
PyYAML = ">=5.3.1"
stevedore = ">=1.20.0"
[package.extras]
test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "toml"]
toml = ["toml"]
yaml = ["PyYAML"]
[[package]]
name = "certifi"
version = "2022.12.7"
description = "Python package for providing Mozilla's CA Bundle."
category = "main"
optional = false
python-versions = ">=3.6"
files = [
{file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"},
{file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"},
]
[[package]]
name = "cffi"
version = "1.15.1"
description = "Foreign Function Interface for Python calling C code."
category = "main"
optional = false
python-versions = "*"
files = [
{file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"},
{file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"},
{file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"},
{file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"},
{file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"},
{file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"},
{file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"},
{file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"},
{file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"},
{file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"},
{file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"},
{file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"},
{file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"},
{file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"},
{file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"},
{file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"},
{file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"},
{file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"},
{file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"},
{file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"},
{file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"},
{file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"},
{file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"},
{file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"},
{file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"},
{file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"},
{file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"},
{file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"},
{file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"},
{file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"},
{file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"},
{file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"},
{file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"},
{file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"},
{file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"},
{file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"},
{file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"},
{file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"},
{file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"},
{file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"},
{file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"},
{file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"},
{file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"},
{file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"},
{file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"},
{file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"},
{file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"},
{file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"},
{file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"},
{file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"},
{file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"},
{file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"},
{file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"},
{file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"},
{file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"},
{file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"},
{file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"},
{file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"},
{file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"},
{file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"},
{file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"},
{file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"},
{file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"},
{file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"},
]
[package.dependencies]
pycparser = "*"
[[package]]
name = "charset-normalizer"
version = "3.0.1"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
category = "main"
optional = false
python-versions = "*"
files = [
{file = "charset-normalizer-3.0.1.tar.gz", hash = "sha256:ebea339af930f8ca5d7a699b921106c6e29c617fe9606fa7baa043c1cdae326f"},
{file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88600c72ef7587fe1708fd242b385b6ed4b8904976d5da0893e31df8b3480cb6"},
{file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c75ffc45f25324e68ab238cb4b5c0a38cd1c3d7f1fb1f72b5541de469e2247db"},
{file = "charset_normalizer-3.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db72b07027db150f468fbada4d85b3b2729a3db39178abf5c543b784c1254539"},
{file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62595ab75873d50d57323a91dd03e6966eb79c41fa834b7a1661ed043b2d404d"},
{file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff6f3db31555657f3163b15a6b7c6938d08df7adbfc9dd13d9d19edad678f1e8"},
{file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:772b87914ff1152b92a197ef4ea40efe27a378606c39446ded52c8f80f79702e"},
{file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70990b9c51340e4044cfc394a81f614f3f90d41397104d226f21e66de668730d"},
{file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:292d5e8ba896bbfd6334b096e34bffb56161c81408d6d036a7dfa6929cff8783"},
{file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2edb64ee7bf1ed524a1da60cdcd2e1f6e2b4f66ef7c077680739f1641f62f555"},
{file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:31a9ddf4718d10ae04d9b18801bd776693487cbb57d74cc3458a7673f6f34639"},
{file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:44ba614de5361b3e5278e1241fda3dc1838deed864b50a10d7ce92983797fa76"},
{file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:12db3b2c533c23ab812c2b25934f60383361f8a376ae272665f8e48b88e8e1c6"},
{file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c512accbd6ff0270939b9ac214b84fb5ada5f0409c44298361b2f5e13f9aed9e"},
{file = "charset_normalizer-3.0.1-cp310-cp310-win32.whl", hash = "sha256:502218f52498a36d6bf5ea77081844017bf7982cdbe521ad85e64cabee1b608b"},
{file = "charset_normalizer-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:601f36512f9e28f029d9481bdaf8e89e5148ac5d89cffd3b05cd533eeb423b59"},
{file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0298eafff88c99982a4cf66ba2efa1128e4ddaca0b05eec4c456bbc7db691d8d"},
{file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a8d0fc946c784ff7f7c3742310cc8a57c5c6dc31631269876a88b809dbeff3d3"},
{file = "charset_normalizer-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:87701167f2a5c930b403e9756fab1d31d4d4da52856143b609e30a1ce7160f3c"},
{file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14e76c0f23218b8f46c4d87018ca2e441535aed3632ca134b10239dfb6dadd6b"},
{file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c0a590235ccd933d9892c627dec5bc7511ce6ad6c1011fdf5b11363022746c1"},
{file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c7fe7afa480e3e82eed58e0ca89f751cd14d767638e2550c77a92a9e749c317"},
{file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79909e27e8e4fcc9db4addea88aa63f6423ebb171db091fb4373e3312cb6d603"},
{file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ac7b6a045b814cf0c47f3623d21ebd88b3e8cf216a14790b455ea7ff0135d18"},
{file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:72966d1b297c741541ca8cf1223ff262a6febe52481af742036a0b296e35fa5a"},
{file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f9d0c5c045a3ca9bedfc35dca8526798eb91a07aa7a2c0fee134c6c6f321cbd7"},
{file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5995f0164fa7df59db4746112fec3f49c461dd6b31b841873443bdb077c13cfc"},
{file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4a8fcf28c05c1f6d7e177a9a46a1c52798bfe2ad80681d275b10dcf317deaf0b"},
{file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:761e8904c07ad053d285670f36dd94e1b6ab7f16ce62b9805c475b7aa1cffde6"},
{file = "charset_normalizer-3.0.1-cp311-cp311-win32.whl", hash = "sha256:71140351489970dfe5e60fc621ada3e0f41104a5eddaca47a7acb3c1b851d6d3"},
{file = "charset_normalizer-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:9ab77acb98eba3fd2a85cd160851816bfce6871d944d885febf012713f06659c"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:84c3990934bae40ea69a82034912ffe5a62c60bbf6ec5bc9691419641d7d5c9a"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74292fc76c905c0ef095fe11e188a32ebd03bc38f3f3e9bcb85e4e6db177b7ea"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c95a03c79bbe30eec3ec2b7f076074f4281526724c8685a42872974ef4d36b72"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c39b0e3eac288fedc2b43055cfc2ca7a60362d0e5e87a637beac5d801ef478"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df2c707231459e8a4028eabcd3cfc827befd635b3ef72eada84ab13b52e1574d"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93ad6d87ac18e2a90b0fe89df7c65263b9a99a0eb98f0a3d2e079f12a0735837"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:59e5686dd847347e55dffcc191a96622f016bc0ad89105e24c14e0d6305acbc6"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:cd6056167405314a4dc3c173943f11249fa0f1b204f8b51ed4bde1a9cd1834dc"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:083c8d17153ecb403e5e1eb76a7ef4babfc2c48d58899c98fcaa04833e7a2f9a"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:f5057856d21e7586765171eac8b9fc3f7d44ef39425f85dbcccb13b3ebea806c"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:7eb33a30d75562222b64f569c642ff3dc6689e09adda43a082208397f016c39a"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-win32.whl", hash = "sha256:95dea361dd73757c6f1c0a1480ac499952c16ac83f7f5f4f84f0658a01b8ef41"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:eaa379fcd227ca235d04152ca6704c7cb55564116f8bc52545ff357628e10602"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3e45867f1f2ab0711d60c6c71746ac53537f1684baa699f4f668d4c6f6ce8e14"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cadaeaba78750d58d3cc6ac4d1fd867da6fc73c88156b7a3212a3cd4819d679d"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:911d8a40b2bef5b8bbae2e36a0b103f142ac53557ab421dc16ac4aafee6f53dc"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:503e65837c71b875ecdd733877d852adbc465bd82c768a067badd953bf1bc5a3"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a60332922359f920193b1d4826953c507a877b523b2395ad7bc716ddd386d866"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16a8663d6e281208d78806dbe14ee9903715361cf81f6d4309944e4d1e59ac5b"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a16418ecf1329f71df119e8a65f3aa68004a3f9383821edcb20f0702934d8087"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9d9153257a3f70d5f69edf2325357251ed20f772b12e593f3b3377b5f78e7ef8"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:02a51034802cbf38db3f89c66fb5d2ec57e6fe7ef2f4a44d070a593c3688667b"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:2e396d70bc4ef5325b72b593a72c8979999aa52fb8bcf03f701c1b03e1166918"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:11b53acf2411c3b09e6af37e4b9005cba376c872503c8f28218c7243582df45d"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-win32.whl", hash = "sha256:0bf2dae5291758b6f84cf923bfaa285632816007db0330002fa1de38bfcb7154"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:2c03cc56021a4bd59be889c2b9257dae13bf55041a3372d3295416f86b295fb5"},
{file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:024e606be3ed92216e2b6952ed859d86b4cfa52cd5bc5f050e7dc28f9b43ec42"},
{file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4b0d02d7102dd0f997580b51edc4cebcf2ab6397a7edf89f1c73b586c614272c"},
{file = "charset_normalizer-3.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:358a7c4cb8ba9b46c453b1dd8d9e431452d5249072e4f56cfda3149f6ab1405e"},
{file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81d6741ab457d14fdedc215516665050f3822d3e56508921cc7239f8c8e66a58"},
{file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8b8af03d2e37866d023ad0ddea594edefc31e827fee64f8de5611a1dbc373174"},
{file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9cf4e8ad252f7c38dd1f676b46514f92dc0ebeb0db5552f5f403509705e24753"},
{file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e696f0dd336161fca9adbb846875d40752e6eba585843c768935ba5c9960722b"},
{file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c22d3fe05ce11d3671297dc8973267daa0f938b93ec716e12e0f6dee81591dc1"},
{file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:109487860ef6a328f3eec66f2bf78b0b72400280d8f8ea05f69c51644ba6521a"},
{file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:37f8febc8ec50c14f3ec9637505f28e58d4f66752207ea177c1d67df25da5aed"},
{file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f97e83fa6c25693c7a35de154681fcc257c1c41b38beb0304b9c4d2d9e164479"},
{file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a152f5f33d64a6be73f1d30c9cc82dfc73cec6477ec268e7c6e4c7d23c2d2291"},
{file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:39049da0ffb96c8cbb65cbf5c5f3ca3168990adf3551bd1dee10c48fce8ae820"},
{file = "charset_normalizer-3.0.1-cp38-cp38-win32.whl", hash = "sha256:4457ea6774b5611f4bed5eaa5df55f70abde42364d498c5134b7ef4c6958e20e"},
{file = "charset_normalizer-3.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:e62164b50f84e20601c1ff8eb55620d2ad25fb81b59e3cd776a1902527a788af"},
{file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8eade758719add78ec36dc13201483f8e9b5d940329285edcd5f70c0a9edbd7f"},
{file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8499ca8f4502af841f68135133d8258f7b32a53a1d594aa98cc52013fff55678"},
{file = "charset_normalizer-3.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3fc1c4a2ffd64890aebdb3f97e1278b0cc72579a08ca4de8cd2c04799a3a22be"},
{file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00d3ffdaafe92a5dc603cb9bd5111aaa36dfa187c8285c543be562e61b755f6b"},
{file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2ac1b08635a8cd4e0cbeaf6f5e922085908d48eb05d44c5ae9eabab148512ca"},
{file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6f45710b4459401609ebebdbcfb34515da4fc2aa886f95107f556ac69a9147e"},
{file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ae1de54a77dc0d6d5fcf623290af4266412a7c4be0b1ff7444394f03f5c54e3"},
{file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b590df687e3c5ee0deef9fc8c547d81986d9a1b56073d82de008744452d6541"},
{file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab5de034a886f616a5668aa5d098af2b5385ed70142090e2a31bcbd0af0fdb3d"},
{file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9cb3032517f1627cc012dbc80a8ec976ae76d93ea2b5feaa9d2a5b8882597579"},
{file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:608862a7bf6957f2333fc54ab4399e405baad0163dc9f8d99cb236816db169d4"},
{file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0f438ae3532723fb6ead77e7c604be7c8374094ef4ee2c5e03a3a17f1fca256c"},
{file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:356541bf4381fa35856dafa6a965916e54bed415ad8a24ee6de6e37deccf2786"},
{file = "charset_normalizer-3.0.1-cp39-cp39-win32.whl", hash = "sha256:39cf9ed17fe3b1bc81f33c9ceb6ce67683ee7526e65fde1447c772afc54a1bb8"},
{file = "charset_normalizer-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:0a11e971ed097d24c534c037d298ad32c6ce81a45736d31e0ff0ad37ab437d59"},
{file = "charset_normalizer-3.0.1-py3-none-any.whl", hash = "sha256:7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24"},
]
[[package]]
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
category = "dev"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
files = [
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
]
[[package]]
name = "deprecated"
version = "1.2.13"
description = "Python @deprecated decorator to deprecate old python classes, functions or methods."
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
{file = "Deprecated-1.2.13-py2.py3-none-any.whl", hash = "sha256:64756e3e14c8c5eea9795d93c524551432a0be75629f8f29e67ab8caf076c76d"},
{file = "Deprecated-1.2.13.tar.gz", hash = "sha256:43ac5335da90c31c24ba028af536a91d41d53f9e6901ddb021bcc572ce44e38d"},
]
[package.dependencies]
wrapt = ">=1.10,<2"
[package.extras]
dev = ["PyTest", "PyTest (<5)", "PyTest-Cov", "PyTest-Cov (<2.6)", "bump2version (<1)", "configparser (<5)", "importlib-metadata (<3)", "importlib-resources (<4)", "sphinx (<2)", "sphinxcontrib-websupport (<2)", "tox", "zipp (<2)"]
[[package]]
name = "dill"
version = "0.3.6"
description = "serialize all of python"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"},
{file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"},
]
[package.extras]
graph = ["objgraph (>=1.7.2)"]
[[package]]
name = "faker"
version = "16.6.1"
description = "Faker is a Python package that generates fake data for you."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "Faker-16.6.1-py3-none-any.whl", hash = "sha256:2375d0bbaf405dc4f1cbc771485a78ad952c776798e5c228eef3e7b337f78868"},
{file = "Faker-16.6.1.tar.gz", hash = "sha256:b76e5d2405470e3d38d37d1bfaa9d9bbf171bdf41c814f5bbd8117b121f6bccb"},
]
[package.dependencies]
python-dateutil = ">=2.4"
[[package]]
name = "gitdb"
version = "4.0.10"
description = "Git Object Database"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "gitdb-4.0.10-py3-none-any.whl", hash = "sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7"},
{file = "gitdb-4.0.10.tar.gz", hash = "sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a"},
]
[package.dependencies]
smmap = ">=3.0.1,<6"
[[package]]
name = "gitpython"
version = "3.1.30"
description = "GitPython is a python library used to interact with Git repositories"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "GitPython-3.1.30-py3-none-any.whl", hash = "sha256:cd455b0000615c60e286208ba540271af9fe531fa6a87cc590a7298785ab2882"},
{file = "GitPython-3.1.30.tar.gz", hash = "sha256:769c2d83e13f5d938b7688479da374c4e3d49f71549aaf462b646db9602ea6f8"},
]
[package.dependencies]
gitdb = ">=4.0.1,<5"
[[package]]
name = "idna"
version = "3.4"
description = "Internationalized Domain Names in Applications (IDNA)"
category = "main"
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 = "isort"
version = "5.12.0"
description = "A Python utility / library to sort Python imports."
category = "dev"
optional = false
python-versions = ">=3.8.0"
files = [
{file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"},
{file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"},
]
[package.extras]
colors = ["colorama (>=0.4.3)"]
pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"]
plugins = ["setuptools"]
requirements-deprecated-finder = ["pip-api", "pipreqs"]
[[package]]
name = "lazy-object-proxy"
version = "1.9.0"
description = "A fast and thorough lazy object proxy."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"},
{file = "lazy_object_proxy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7"},
{file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4"},
{file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd"},
{file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701"},
{file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46"},
{file = "lazy_object_proxy-1.9.0-cp310-cp310-win32.whl", hash = "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455"},
{file = "lazy_object_proxy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e"},
{file = "lazy_object_proxy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07"},
{file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a"},
{file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"},
{file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4"},
{file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9"},
{file = "lazy_object_proxy-1.9.0-cp311-cp311-win32.whl", hash = "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586"},
{file = "lazy_object_proxy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb"},
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e"},
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8"},
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2"},
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8"},
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda"},
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734"},
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671"},
{file = "lazy_object_proxy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63"},
{file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171"},
{file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be"},
{file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30"},
{file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11"},
{file = "lazy_object_proxy-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82"},
{file = "lazy_object_proxy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b"},
{file = "lazy_object_proxy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b"},
{file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4"},
{file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006"},
{file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494"},
{file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382"},
{file = "lazy_object_proxy-1.9.0-cp39-cp39-win32.whl", hash = "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821"},
{file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"},
]
[[package]]
name = "loguru"
version = "0.6.0"
description = "Python logging made (stupidly) simple"
category = "dev"
optional = false
python-versions = ">=3.5"
files = [
{file = "loguru-0.6.0-py3-none-any.whl", hash = "sha256:4e2414d534a2ab57573365b3e6d0234dfb1d84b68b7f3b948e6fb743860a77c3"},
{file = "loguru-0.6.0.tar.gz", hash = "sha256:066bd06758d0a513e9836fd9c6b5a75bfb3fd36841f4b996bc60b547a309d41c"},
]
[package.dependencies]
colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""}
win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""}
[package.extras]
dev = ["Sphinx (>=4.1.1)", "black (>=19.10b0)", "colorama (>=0.3.4)", "docutils (==0.16)", "flake8 (>=3.7.7)", "isort (>=5.1.1)", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "sphinx-autobuild (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "tox (>=3.9.0)"]
[[package]]
name = "mccabe"
version = "0.7.0"
description = "McCabe checker, plugin for flake8"
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
{file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"},
{file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"},
]
[[package]]
name = "pbr"
version = "5.11.1"
description = "Python Build Reasonableness"
category = "dev"
optional = false
python-versions = ">=2.6"
files = [
{file = "pbr-5.11.1-py2.py3-none-any.whl", hash = "sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b"},
{file = "pbr-5.11.1.tar.gz", hash = "sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3"},
]
[[package]]
name = "platformdirs"
version = "2.6.2"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "platformdirs-2.6.2-py3-none-any.whl", hash = "sha256:83c8f6d04389165de7c9b6f0c682439697887bca0aa2f1c87ef1826be3584490"},
{file = "platformdirs-2.6.2.tar.gz", hash = "sha256:e1fea1fe471b9ff8332e229df3cb7de4f53eeea4998d3b6bfff542115e998bd2"},
]
[package.extras]
docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"]
test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
[[package]]
name = "pycodestyle"
version = "2.10.0"
description = "Python style guide checker"
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
{file = "pycodestyle-2.10.0-py2.py3-none-any.whl", hash = "sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610"},
{file = "pycodestyle-2.10.0.tar.gz", hash = "sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053"},
]
[[package]]
name = "pycparser"
version = "2.21"
description = "C parser in Python"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
{file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
{file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
]
[[package]]
name = "pygithub"
version = "1.57"
description = "Use the full Github API v3"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "PyGithub-1.57-py3-none-any.whl", hash = "sha256:5822febeac2391f1306c55a99af2bc8f86c8bf82ded000030cd02c18f31b731f"},
{file = "PyGithub-1.57.tar.gz", hash = "sha256:c273f252b278fb81f1769505cc6921bdb6791e1cebd6ac850cc97dad13c31ff3"},
]
[package.dependencies]
deprecated = "*"
pyjwt = ">=2.4.0"
pynacl = ">=1.4.0"
requests = ">=2.14.0"
[package.extras]
integrations = ["cryptography"]
[[package]]
name = "pyjwt"
version = "2.6.0"
description = "JSON Web Token implementation in Python"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "PyJWT-2.6.0-py3-none-any.whl", hash = "sha256:d83c3d892a77bbb74d3e1a2cfa90afaadb60945205d1095d9221f04466f64c14"},
{file = "PyJWT-2.6.0.tar.gz", hash = "sha256:69285c7e31fc44f68a1feb309e948e0df53259d579295e6cfe2b1792329f05fd"},
]
[package.extras]
crypto = ["cryptography (>=3.4.0)"]
dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"]
docs = ["sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"]
tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"]
[[package]]
name = "pylint"
version = "2.16.1"
description = "python code static checker"
category = "dev"
optional = false
python-versions = ">=3.7.2"
files = [
{file = "pylint-2.16.1-py3-none-any.whl", hash = "sha256:bad9d7c36037f6043a1e848a43004dfd5ea5ceb05815d713ba56ca4503a9fe37"},
{file = "pylint-2.16.1.tar.gz", hash = "sha256:ffe7fa536bb38ba35006a7c8a6d2efbfdd3d95bbf21199cad31f76b1c50aaf30"},
]
[package.dependencies]
astroid = ">=2.14.1,<=2.16.0-dev0"
colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
dill = {version = ">=0.3.6", markers = "python_version >= \"3.11\""}
isort = ">=4.2.5,<6"
mccabe = ">=0.6,<0.8"
platformdirs = ">=2.2.0"
tomlkit = ">=0.10.1"
[package.extras]
spelling = ["pyenchant (>=3.2,<4.0)"]
testutils = ["gitpython (>3)"]
[[package]]
name = "pynacl"
version = "1.5.0"
description = "Python binding to the Networking and Cryptography (NaCl) library"
category = "main"
optional = false
python-versions = ">=3.6"
files = [
{file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"},
{file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"},
{file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"},
{file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"},
{file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"},
{file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"},
{file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"},
{file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"},
{file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"},
{file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"},
]
[package.dependencies]
cffi = ">=1.4.1"
[package.extras]
docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"]
tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"]
[[package]]
name = "python-dateutil"
version = "2.8.2"
description = "Extensions to the standard Python datetime module"
category = "main"
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 = "python-dotenv"
version = "0.21.1"
description = "Read key-value pairs from a .env file and set them as environment variables"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "python-dotenv-0.21.1.tar.gz", hash = "sha256:1c93de8f636cde3ce377292818d0e440b6e45a82f215c3744979151fa8151c49"},
{file = "python_dotenv-0.21.1-py3-none-any.whl", hash = "sha256:41e12e0318bebc859fcc4d97d4db8d20ad21721a6aa5047dd59f090391cb549a"},
]
[package.extras]
cli = ["click (>=5.0)"]
[[package]]
name = "pyyaml"
version = "6.0"
description = "YAML parser and emitter for Python"
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
{file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
{file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"},
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"},
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"},
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"},
{file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"},
{file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"},
{file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"},
{file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"},
{file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"},
{file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"},
{file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"},
{file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"},
{file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"},
{file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"},
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"},
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"},
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"},
{file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"},
{file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"},
{file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"},
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"},
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"},
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"},
{file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"},
{file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"},
{file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"},
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"},
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"},
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"},
{file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"},
{file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"},
{file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"},
{file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"},
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"},
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"},
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"},
{file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"},
{file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
{file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
]
[[package]]
name = "requests"
version = "2.28.2"
description = "Python HTTP for Humans."
category = "main"
optional = false
python-versions = ">=3.7, <4"
files = [
{file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"},
{file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"},
]
[package.dependencies]
certifi = ">=2017.4.17"
charset-normalizer = ">=2,<4"
idna = ">=2.5,<4"
urllib3 = ">=1.21.1,<1.27"
[package.extras]
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
name = "six"
version = "1.16.0"
description = "Python 2 and 3 compatibility utilities"
category = "main"
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 = "smmap"
version = "5.0.0"
description = "A pure Python implementation of a sliding window memory map manager"
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
{file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"},
{file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"},
]
[[package]]
name = "stevedore"
version = "4.1.1"
description = "Manage dynamic plugins for Python applications"
category = "dev"
optional = false
python-versions = ">=3.8"
files = [
{file = "stevedore-4.1.1-py3-none-any.whl", hash = "sha256:aa6436565c069b2946fe4ebff07f5041e0c8bf18c7376dd29edf80cf7d524e4e"},
{file = "stevedore-4.1.1.tar.gz", hash = "sha256:7f8aeb6e3f90f96832c301bff21a7eb5eefbe894c88c506483d355565d88cc1a"},
]
[package.dependencies]
pbr = ">=2.0.0,<2.1.0 || >2.1.0"
[[package]]
name = "tomlkit"
version = "0.11.6"
description = "Style preserving TOML library"
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
{file = "tomlkit-0.11.6-py3-none-any.whl", hash = "sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b"},
{file = "tomlkit-0.11.6.tar.gz", hash = "sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73"},
]
[[package]]
name = "urllib3"
version = "1.26.14"
description = "HTTP library with thread-safe connection pooling, file post, and more."
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
files = [
{file = "urllib3-1.26.14-py2.py3-none-any.whl", hash = "sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1"},
{file = "urllib3-1.26.14.tar.gz", hash = "sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72"},
]
[package.extras]
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[[package]]
name = "win32-setctime"
version = "1.1.0"
description = "A small Python utility to set file creation time on Windows"
category = "dev"
optional = false
python-versions = ">=3.5"
files = [
{file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"},
{file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"},
]
[package.extras]
dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"]
[[package]]
name = "wrapt"
version = "1.14.1"
description = "Module for decorators, wrappers and monkey patching."
category = "main"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
files = [
{file = "wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"},
{file = "wrapt-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef"},
{file = "wrapt-1.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28"},
{file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59"},
{file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87"},
{file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1"},
{file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b"},
{file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462"},
{file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1"},
{file = "wrapt-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320"},
{file = "wrapt-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2"},
{file = "wrapt-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4"},
{file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069"},
{file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310"},
{file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f"},
{file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656"},
{file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"},
{file = "wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"},
{file = "wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"},
{file = "wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"},
{file = "wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"},
{file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"},
{file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d"},
{file = "wrapt-1.14.1-cp35-cp35m-win32.whl", hash = "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7"},
{file = "wrapt-1.14.1-cp35-cp35m-win_amd64.whl", hash = "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00"},
{file = "wrapt-1.14.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4"},
{file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1"},
{file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1"},
{file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff"},
{file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d"},
{file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1"},
{file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569"},
{file = "wrapt-1.14.1-cp36-cp36m-win32.whl", hash = "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed"},
{file = "wrapt-1.14.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471"},
{file = "wrapt-1.14.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248"},
{file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68"},
{file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d"},
{file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77"},
{file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7"},
{file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015"},
{file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a"},
{file = "wrapt-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853"},
{file = "wrapt-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c"},
{file = "wrapt-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456"},
{file = "wrapt-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f"},
{file = "wrapt-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc"},
{file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1"},
{file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"},
{file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b"},
{file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0"},
{file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57"},
{file = "wrapt-1.14.1-cp38-cp38-win32.whl", hash = "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5"},
{file = "wrapt-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d"},
{file = "wrapt-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383"},
{file = "wrapt-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7"},
{file = "wrapt-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86"},
{file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735"},
{file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b"},
{file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3"},
{file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3"},
{file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe"},
{file = "wrapt-1.14.1-cp39-cp39-win32.whl", hash = "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5"},
{file = "wrapt-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb"},
{file = "wrapt-1.14.1.tar.gz", hash = "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d"},
]
[metadata]
lock-version = "2.0"
python-versions = "^3.11"
content-hash = "7d511f3d3dfb9c88c331ee83af83fde3d9dfe029f7ed2382fc63522127cf351c"

View File

@ -1,25 +1,86 @@
[tool.poetry]
####################
# Metadata #
####################
[project]
name = "waka-readme"
version = "0.1.7"
description = "Wakatime Weekly Metrics on your Profile Readme"
authors = ["Athul Cyriac Ajay <athul8720@gmail.com>"]
license = "MIT"
version = "0.3.0"
description = "Wakatime Weekly Metrics on your Profile Readme."
authors = [{ name = "Athul Cyriac Ajay", email = "athul8720@gmail.com" }]
license = { text = "MIT" }
readme = "README.md"
#packages = [{include = "waka_readme"}]
keywords = ["readme", "profile-page", "wakatime"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Programming Language :: Python",
"Typing :: Typed",
]
requires-python = ">=3.12"
dependencies = ["faker>=21.0.0", "pygithub>=2.1.1", "requests>=2.31.0", "py-gitea>=0.2.6"]
[tool.poetry.dependencies]
python = "^3.11"
faker = "^16.6.1"
requests = "^2.28.2"
pygithub = "^1.57"
[project.urls]
Homepage = "https://github.com/athul/waka-readme"
Documentation = "https://github.com/athul/waka-readme#readme"
Repository = "https://github.com/athul/waka-readme"
Changelog = "https://github.com/athul/waka-readme/commits/master"
[tool.poetry.group.dev.dependencies]
autopep8 = "^2.0.1"
pylint = "^2.16.1"
python-dotenv = "^0.21.1"
loguru = "^0.6.0"
bandit = "^1.7.4"
#############################
# Optional Dependencies #
#############################
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[project.optional-dependencies]
extra = ["loguru>=0.7.2", "python-dotenv>=1.0.0"]
#############################
# Development Dependencies #
#############################
[tool.pdm.dev-dependencies]
tooling = ["bandit>=1.7.6", "black>=23.12.1", "ruff>=0.1.9", "pyright>=1.1.342"]
####################
# Configurations #
####################
[tool.bandit]
exclude_dirs = [".github", "tests", ".venv", ".vscode"]
[tool.black]
line-length = 100
target-version = ["py312"]
[tool.pyright]
exclude = ["**/__pycache__", ".venv/"]
pythonVersion = "3.12"
pythonPlatform = "All"
typeCheckingMode = "strict"
[tool.ruff]
select = [
# Pyflakes
"F",
# pycodestyle
"W",
"E",
# mccabe
# C90
# isort
"I",
# pep8-naming
"N",
# pydocstyle
"D",
]
line-length = 100
target-version = "py312"
extend-exclude = ["**/__pycache__"]
[tool.ruff.isort]
# case-sensitive = true
combine-as-imports = true
force-sort-within-sections = true
force-wrap-aliases = true
relative-imports-order = "closest-to-furthest"
[tool.ruff.pydocstyle]
convention = "google"

View File

@ -1,6 +1,4 @@
"""
Initialize test module
"""
"""Initialize test module."""
# standard
import logging

View File

@ -1,21 +1,20 @@
"""
Tests for the main.py
"""
"""Unit Tests."""
# standard
from importlib import import_module
from dataclasses import dataclass # , field
from importlib import import_module
from itertools import product
import os
import sys
import unittest
# from pathlib import Path
# from inspect import cleandoc
# from typing import Any
# from json import load
import unittest
import sys
import os
try:
prime = import_module('main')
prime = import_module("main")
# works when running as
# python -m unittest discover
except ImportError as err:
@ -25,7 +24,8 @@ except ImportError as err:
@dataclass
class TestData:
"""Test Data"""
"""Test Data."""
# for future tests
# waka_json: dict[str, dict[str, Any]] = field(
# default_factory=lambda: {}
@ -33,25 +33,24 @@ class TestData:
bar_percent: tuple[int | float, ...] | None = None
graph_blocks: tuple[str, ...] | None = None
waka_graphs: tuple[list[str], ...] | None = None
dummy_readme: str = ''
dummy_readme: str = ""
def populate(self) -> None:
"""Populate Test Data"""
"""Populate Test Data."""
# for future tests
# with open(
# file=Path(__file__).parent / 'sample_data.json',
# encoding='utf-8',
# mode='rt',
# file=Path(__file__).parent / "sample_data.json",
# encoding="utf-8",
# mode="rt",
# ) as wkf:
# self.waka_json = load(wkf)
self.bar_percent = (
0, 100, 49.999, 50, 25, 75, 3.14, 9.901, 87.334, 87.333, 4.666, 4.667
)
self.bar_percent = (0, 100, 49.999, 50, 25, 75, 3.14, 9.901, 87.334, 87.333, 4.666, 4.667)
self.graph_blocks = ("░▒▓█", "⚪⚫", "⓪①②③④⑤⑥⑦⑧⑨⑩")
self.waka_graphs = ([
self.waka_graphs = (
[
"░░░░░░░░░░░░░░░░░░░░░░░░░",
"█████████████████████████",
"████████████▒░░░░░░░░░░░░",
@ -63,7 +62,7 @@ class TestData:
"██████████████████████░░░",
"█████████████████████▓░░░",
"█░░░░░░░░░░░░░░░░░░░░░░░░",
"█▒░░░░░░░░░░░░░░░░░░░░░░░"
"█▒░░░░░░░░░░░░░░░░░░░░░░░",
],
[
"⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪",
@ -77,7 +76,7 @@ class TestData:
"⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚪⚪⚪",
"⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚫⚪⚪⚪",
"⚫⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪",
"⚫⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪"
"⚫⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪",
],
[
"⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪",
@ -91,8 +90,9 @@ class TestData:
"⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑧⓪⓪⓪",
"⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑩⑧⓪⓪⓪",
"⑩②⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪",
"⑩②⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪"
])
"⑩②⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪",
],
)
# self.dummy_readme = cleandoc("""
# My Test Readme Start
@ -103,47 +103,43 @@ class TestData:
class TestMain(unittest.TestCase):
"""Testing Main Module"""
"""Testing Main Module."""
def test_make_graph(self) -> None:
"""Test graph maker"""
"""Test graph maker."""
if not tds.graph_blocks or not tds.waka_graphs or not tds.bar_percent:
raise AssertionError('Data population failed')
raise AssertionError("Data population failed")
for (idx, grb), (jdy, bpc) in product(
enumerate(tds.graph_blocks), enumerate(tds.bar_percent)
):
self.assertEqual(
prime.make_graph(grb, bpc, 25),
tds.waka_graphs[idx][jdy]
)
self.assertEqual(prime.make_graph(grb, bpc, 25), tds.waka_graphs[idx][jdy])
def test_make_title(self) -> None:
"""Test title maker"""
"""Test title maker."""
self.assertRegex(
prime.make_title('2022-01-11T23:18:19Z', '2021-12-09T10:22:06Z'),
r'From: \d{2} \w{3,9} \d{4} - To: \d{2} \w{3,9} \d{4}'
prime.make_title("2022-01-11T23:18:19Z", "2021-12-09T10:22:06Z"),
r"From: \d{2} \w{3,9} \d{4} - To: \d{2} \w{3,9} \d{4}",
)
def test_strtobool(self) -> None:
"""Test string to bool"""
self.assertTrue(prime.strtobool('Yes'))
self.assertFalse(prime.strtobool('nO'))
"""Test string to bool."""
self.assertTrue(prime.strtobool("Yes"))
self.assertFalse(prime.strtobool("nO"))
self.assertTrue(prime.strtobool(True))
self.assertRaises(AttributeError, prime.strtobool, None)
self.assertRaises(ValueError, prime.strtobool, 'yo!')
self.assertRaises(ValueError, prime.strtobool, "yo!")
self.assertRaises(AttributeError, prime.strtobool, 20.5)
tds = TestData()
tds.populate()
if __name__ == '__main__':
if __name__ == "__main__":
try:
sys.path.insert(0, os.path.abspath(
os.path.join(os.path.dirname(__file__), '..')
))
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
import main as prime
# works when running as
# python tests/test_main.py
except ImportError as im_er: