feat: bye travis, hi gh actn, hndl empty resp, tip in readme
This commit is contained in:
parent
ec7c2a0b9c
commit
88979b6b3c
28
.github/testing.yml
vendored
Normal file
28
.github/testing.yml
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
name: WakaReadme
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
pull_request:
|
||||||
|
branches: [master]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up Python 3.10
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: "3.10"
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python - --version 1.1.13
|
||||||
|
echo "##vso[task.setvariable variable=PATH]${PATH}:$HOME/.poetry/bin"
|
||||||
|
source $HOME/.poetry/env"
|
||||||
|
poetry install
|
||||||
|
- name: Run unit tests
|
||||||
|
run: |
|
||||||
|
poetry run python -m unittest discover
|
10
.travis.yml
10
.travis.yml
@ -1,10 +0,0 @@
|
|||||||
dist: focal
|
|
||||||
language: python
|
|
||||||
python: '3.10.2'
|
|
||||||
install:
|
|
||||||
- curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python - --version 1.1.13
|
|
||||||
- echo "##vso[task.setvariable variable=PATH]${PATH}:$HOME/.poetry/bin"
|
|
||||||
- source $HOME/.poetry/env
|
|
||||||
- poetry install
|
|
||||||
script:
|
|
||||||
- poetry run python -m unittest discover
|
|
@ -6,8 +6,8 @@ First off, thanks! You can contribute to the repo via the following steps.
|
|||||||
2. Install poetry with: `curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python - --version 1.1.13`
|
2. Install poetry with: `curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python - --version 1.1.13`
|
||||||
3. Open a terminal in the cloned folder and create a virtual environment using: `poetry shell` and install dependencies with `poetry install`
|
3. Open a terminal in the cloned folder and create a virtual environment using: `poetry shell` and install dependencies with `poetry install`
|
||||||
4. You can put the environment variable in a local `.env` file
|
4. You can put the environment variable in a local `.env` file
|
||||||
5. Test the program `python -m unittest discover`
|
5. Test the program `python -m unittest discover`. Read [main.py:L289](main.py#L289) before step 6.
|
||||||
6. Finally run the program with `python -m main`
|
6. Finally run it in development mode with `python -m main --dev`.
|
||||||
|
|
||||||
## Resources
|
## Resources
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ WORKDIR /src
|
|||||||
# RUN curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -
|
# RUN curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -
|
||||||
RUN pip install pipx
|
RUN pip install pipx
|
||||||
RUN pipx install "poetry==$POETRY_VERSION"
|
RUN pipx install "poetry==$POETRY_VERSION"
|
||||||
|
RUN pipx ensurepath
|
||||||
|
|
||||||
# install dependencies
|
# install dependencies
|
||||||
COPY pyproject.toml poetry.lock /src/
|
COPY pyproject.toml poetry.lock /src/
|
||||||
@ -28,4 +29,4 @@ RUN poetry install --no-dev --no-root --no-interaction --no-ansi
|
|||||||
|
|
||||||
# copy and run program
|
# copy and run program
|
||||||
COPY main.py /src/
|
COPY main.py /src/
|
||||||
RUN python /src/main.py
|
CMD [ "python", "/src/main.py" ]
|
||||||
|
@ -235,7 +235,9 @@ jobs:
|
|||||||
Other ██▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 05.87 %
|
Other ██▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 05.87 %
|
||||||
```
|
```
|
||||||
|
|
||||||
> You can find all the options in [action.yml](action.yml) and an example workflow [here](https://github.com/athul/athul/blob/master/.github/workflows/update-readme.yml).
|
> You can find all the options in [action.yml](action.yml) and a sample workflow [here](https://github.com/athul/athul/blob/master/.github/workflows/update-readme.yml).
|
||||||
|
>
|
||||||
|
> Tip 💡: Add `on: workflow_dispatch:` to enable manual runs. [See](https://github.com/joe733/joe733/blob/master/.github/workflows/waka.yml#L4).
|
||||||
|
|
||||||
## Why only the language stats and not other data from the API?
|
## Why only the language stats and not other data from the API?
|
||||||
|
|
||||||
|
54
main.py
54
main.py
@ -2,7 +2,7 @@
|
|||||||
WakaReadme : WakaTime progress visualizer
|
WakaReadme : WakaTime progress visualizer
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
Wakatime Weekly Metrics on your Profile Readme.
|
Wakatime Metrics on your Profile Readme.
|
||||||
|
|
||||||
Title:
|
Title:
|
||||||
------
|
------
|
||||||
@ -48,6 +48,10 @@ from github import GithubException, Github
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=logging-fstring-interpolation
|
||||||
|
|
||||||
|
################### data ###################
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class WakaConstants:
|
class WakaConstants:
|
||||||
"""
|
"""
|
||||||
@ -124,6 +128,8 @@ class WakaInput:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
################### logic ###################
|
||||||
|
|
||||||
def make_title(dawn: str, dusk: str, /) -> str:
|
def make_title(dawn: str, dusk: str, /) -> str:
|
||||||
"""
|
"""
|
||||||
WakaReadme Title
|
WakaReadme Title
|
||||||
@ -140,7 +146,7 @@ def make_title(dawn: str, dusk: str, /) -> str:
|
|||||||
start_date = datetime.strptime(dawn, api_dfm).strftime(msg_dfm)
|
start_date = datetime.strptime(dawn, api_dfm).strftime(msg_dfm)
|
||||||
end_date = datetime.strptime(dusk, api_dfm).strftime(msg_dfm)
|
end_date = datetime.strptime(dusk, api_dfm).strftime(msg_dfm)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
logger.critical(err)
|
logger.error(err)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
logger.debug('Title was made')
|
logger.debug('Title was made')
|
||||||
return f'From: {start_date} - To: {end_date}'
|
return f'From: {start_date} - To: {end_date}'
|
||||||
@ -156,7 +162,6 @@ def make_graph(
|
|||||||
|
|
||||||
Makes time graph from the API's data.
|
Makes time graph from the API's data.
|
||||||
"""
|
"""
|
||||||
# pylint: disable=logging-fstring-interpolation
|
|
||||||
logger.debug(f'Generating graph for {lg_nm or "..."}')
|
logger.debug(f'Generating graph for {lg_nm or "..."}')
|
||||||
markers: int = len(block_style) - 1
|
markers: int = len(block_style) - 1
|
||||||
proportion: float = percent / 100 * gr_len
|
proportion: float = percent / 100 * gr_len
|
||||||
@ -182,8 +187,8 @@ def prep_content(stats: dict | None, /) -> str:
|
|||||||
|
|
||||||
# Check if any data exists
|
# Check if any data exists
|
||||||
if not (lang_info := stats.get('languages')):
|
if not (lang_info := stats.get('languages')):
|
||||||
logger.debug('The data seems to be empty. Please wait for a day')
|
logger.debug('The data seems to be empty, please wait for a day')
|
||||||
contents += 'No activity tracked this week'
|
contents += 'No activity tracked'
|
||||||
return contents
|
return contents
|
||||||
|
|
||||||
# make title
|
# make title
|
||||||
@ -201,6 +206,7 @@ def prep_content(stats: dict | None, /) -> str:
|
|||||||
pad_len = len(
|
pad_len = len(
|
||||||
max((str(l.get('name')) for l in lang_info), key=len)
|
max((str(l.get('name')) for l in lang_info), key=len)
|
||||||
# comment if it feels way computationally expensive
|
# comment if it feels way computationally expensive
|
||||||
|
# and then don't for get to set pad_len to say 13 :)
|
||||||
)
|
)
|
||||||
for idx, lang in enumerate(lang_info):
|
for idx, lang in enumerate(lang_info):
|
||||||
lang_name: str = lang.get('name')
|
lang_name: str = lang.get('name')
|
||||||
@ -231,24 +237,32 @@ def fetch_stats() -> Any:
|
|||||||
|
|
||||||
Retruns statistics as JSON string
|
Retruns statistics as JSON string
|
||||||
"""
|
"""
|
||||||
|
tries, statistic = 3, {}
|
||||||
logger.debug('Fetching WakaTime statistics')
|
logger.debug('Fetching WakaTime statistics')
|
||||||
encoded_key: str = str(b64encode(bytes(wk_i.waka_key, 'utf-8')), 'utf-8')
|
encoded_key: str = str(b64encode(bytes(wk_i.waka_key, 'utf-8')), 'utf-8')
|
||||||
try:
|
|
||||||
stat_data = requests.get(
|
with requests.Session() as rqs:
|
||||||
|
# why session? read @
|
||||||
|
# https://docs.python-requests.org/en/latest/user/advanced/#session-objects
|
||||||
|
while tries > 0:
|
||||||
|
resp = rqs.get(
|
||||||
url=f'{wk_i.api_base_url.rstrip("/")}/v1/users/current/stats/{wk_i.time_range}',
|
url=f'{wk_i.api_base_url.rstrip("/")}/v1/users/current/stats/{wk_i.time_range}',
|
||||||
headers={'Authorization': f'Basic {encoded_key}'}
|
headers={'Authorization': f'Basic {encoded_key}'}
|
||||||
).json()
|
)
|
||||||
except requests.RequestException as rq_exp:
|
logger.debug(
|
||||||
logger.critical(rq_exp)
|
f'API response at trial #{4 - tries}: {resp.status_code} {resp.reason}'
|
||||||
sys.exit(1)
|
)
|
||||||
|
if resp.status_code == 200 and (statistic := resp.json()):
|
||||||
|
logger.debug('Fetched WakaTime statistics')
|
||||||
|
break
|
||||||
|
logger.debug('Retrying ...')
|
||||||
|
tries -= 1
|
||||||
|
|
||||||
# would this be a little too restrictive?
|
if err := (statistic.get('error') or statistic.get('errors')):
|
||||||
if err := (stat_data.get('error') or stat_data.get('errors')):
|
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
logger.debug('Fetched WakaTime statistics')
|
return statistic.get('data')
|
||||||
return stat_data.get('data')
|
|
||||||
|
|
||||||
|
|
||||||
def churn(old_readme: str, /) -> str | None:
|
def churn(old_readme: str, /) -> str | None:
|
||||||
@ -258,8 +272,12 @@ def churn(old_readme: str, /) -> str | None:
|
|||||||
|
|
||||||
Composes WakaTime stats within markdown code snippet
|
Composes WakaTime stats within markdown code snippet
|
||||||
"""
|
"""
|
||||||
|
try:
|
||||||
if not (waka_stats := fetch_stats()):
|
if not (waka_stats := fetch_stats()):
|
||||||
logger.error('Unable to fetch data')
|
logger.error('Unable to fetch data, please rerun workflow')
|
||||||
|
sys.exit(1)
|
||||||
|
except requests.RequestException as rq_exp:
|
||||||
|
logger.critical(rq_exp)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
generated_content = prep_content(waka_stats)
|
generated_content = prep_content(waka_stats)
|
||||||
print('\n', generated_content, '\n', sep='')
|
print('\n', generated_content, '\n', sep='')
|
||||||
@ -269,7 +287,7 @@ def churn(old_readme: str, /) -> str | None:
|
|||||||
string=old_readme
|
string=old_readme
|
||||||
)
|
)
|
||||||
# return None # un-comment when testing with --dev
|
# return None # un-comment when testing with --dev
|
||||||
# to avoid writing back to Github
|
# to avoid accidentally writing back to Github
|
||||||
return None if new_readme == old_readme else new_readme
|
return None if new_readme == old_readme else new_readme
|
||||||
|
|
||||||
|
|
||||||
@ -294,6 +312,8 @@ def genesis() -> None:
|
|||||||
logger.info('No changes were made')
|
logger.info('No changes were made')
|
||||||
|
|
||||||
|
|
||||||
|
################### driver ###################
|
||||||
|
|
||||||
# configure logger
|
# configure logger
|
||||||
logger.getLogger('urllib3').setLevel(logger.WARNING)
|
logger.getLogger('urllib3').setLevel(logger.WARNING)
|
||||||
logger.getLogger('github.Requester').setLevel(logger.WARNING)
|
logger.getLogger('github.Requester').setLevel(logger.WARNING)
|
||||||
|
@ -31,7 +31,7 @@ class TestData:
|
|||||||
def populate(self) -> None:
|
def populate(self) -> None:
|
||||||
"""Populate Test Data"""
|
"""Populate Test Data"""
|
||||||
# for future tests
|
# for future tests
|
||||||
# with open(file='tests/template.json', mode='rt', encoding='utf-8') as wkf:
|
# with open(file='tests/sample_data.json', mode='rt', encoding='utf-8') as wkf:
|
||||||
# self.waka_json = loads(wkf.read())
|
# self.waka_json = loads(wkf.read())
|
||||||
|
|
||||||
self.bar_percent = (
|
self.bar_percent = (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user