maint: migrate to black formatting

This commit is contained in:
Jovial Joe Jayarson 2023-06-13 19:17:26 +05:30
parent b42a071671
commit 9bee9ba11b
3 changed files with 201 additions and 220 deletions

1
.gitignore vendored
View File

@ -113,6 +113,7 @@ celerybeat.pid
# Environments # Environments
*.env *.env
env.sh
.venv .venv
env/ env/
venv/ venv/

290
main.py
View File

@ -45,42 +45,36 @@ import re
import os import os
# external # external
# # requests
from requests.exceptions import RequestException from requests.exceptions import RequestException
from requests import get as rq_get from requests import get as rq_get
# # github
from github import GithubException, Github from github import GithubException, Github
# # faker
from faker import Faker from faker import Faker
# pylint: disable = logging-fstring-interpolation
################### setup ################### ################### setup ###################
print() print()
# hush existing loggers # hush existing loggers
# pylint: disable = no-member # see: https://stackoverflow.com/q/20965287
for lgr_name in logger.root.manager.loggerDict: for lgr_name in logger.root.manager.loggerDict:
# to disable log propagation completely set '.propagate = False' # to disable log propagation completely set '.propagate = False'
logger.getLogger(lgr_name).setLevel(logger.WARNING) logger.getLogger(lgr_name).setLevel(logger.WARNING)
# pylint: enable = no-member
# somehow github.Requester gets missed out from loggerDict # somehow github.Requester gets missed out from loggerDict
logger.getLogger('github.Requester').setLevel(logger.WARNING) logger.getLogger("github.Requester").setLevel(logger.WARNING)
# configure logger # configure logger
logger.basicConfig( logger.basicConfig(
datefmt='%Y-%m-%d %H:%M:%S', datefmt="%Y-%m-%d %H:%M:%S",
format='[%(asctime)s] ln. %(lineno)-3d %(levelname)-8s %(message)s', format="[%(asctime)s] ln. %(lineno)-3d %(levelname)-8s %(message)s",
level=logger.DEBUG level=logger.DEBUG,
) )
try: 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 # get env-vars from .env file for development
from dotenv import load_dotenv from dotenv import load_dotenv
# comment this out to disable colored logging # comment this out to disable colored logging
from loguru import logger from loguru import logger
# load from .env before class def gets parsed # load from .env before class def gets parsed
load_dotenv() load_dotenv()
except ImportError as im_err: except ImportError as im_err:
@ -109,13 +103,13 @@ def strtobool(val: str | bool):
val = val.lower() val = val.lower()
if val in {'y', 'yes', 't', 'true', 'on', '1'}: if val in {"y", "yes", "t", "true", "on", "1"}:
return True return True
if val in {'n', 'no', 'f', 'false', 'off', '0'}: if val in {"n", "no", "f", "false", "off", "0"}:
return False return False
raise ValueError(f'invalid truth value for {val}') raise ValueError(f"invalid truth value for {val}")
################### data ################### ################### data ###################
@ -127,52 +121,49 @@ class WakaInput:
WakaReadme Input Env Variables WakaReadme Input Env Variables
------------------------------ ------------------------------
""" """
# constants # constants
prefix_length: int = 16 prefix_length: int = 16
graph_length: int = 25 graph_length: int = 25
# mapped environment variables # mapped environment variables
# # required # # required
gh_token: str | None = os.getenv('INPUT_GH_TOKEN') gh_token: str | None = os.getenv("INPUT_GH_TOKEN")
waka_key: str | None = os.getenv('INPUT_WAKATIME_API_KEY') waka_key: str | None = os.getenv("INPUT_WAKATIME_API_KEY")
api_base_url: str | None = os.getenv( api_base_url: str | None = os.getenv("INPUT_API_BASE_URL", "https://wakatime.com/api")
'INPUT_API_BASE_URL', 'https://wakatime.com/api' repository: str | None = os.getenv("INPUT_REPOSITORY")
)
repository: str | None = os.getenv('INPUT_REPOSITORY')
# # depends # # depends
commit_message: str = os.getenv( commit_message: str = os.getenv(
'INPUT_COMMIT_MESSAGE', 'Updated WakaReadme graph with new metrics' "INPUT_COMMIT_MESSAGE", "Updated WakaReadme graph with new metrics"
) )
code_lang: str = os.getenv('INPUT_CODE_LANG', 'txt') code_lang: str = os.getenv("INPUT_CODE_LANG", "txt")
_section_name: str = os.getenv('INPUT_SECTION_NAME', 'waka') _section_name: str = os.getenv("INPUT_SECTION_NAME", "waka")
start_comment: str = f'<!--START_SECTION:{_section_name}-->' start_comment: str = f"<!--START_SECTION:{_section_name}-->"
end_comment: str = f'<!--END_SECTION:{_section_name}-->' end_comment: str = f"<!--END_SECTION:{_section_name}-->"
waka_block_pattern: str = f'{start_comment}[\\s\\S]+{end_comment}' waka_block_pattern: str = f"{start_comment}[\\s\\S]+{end_comment}"
# # optional # # optional
show_title: str | bool = os.getenv('INPUT_SHOW_TITLE') or False show_title: str | bool = os.getenv("INPUT_SHOW_TITLE") or False
block_style: str = os.getenv('INPUT_BLOCKS', '░▒▓█') block_style: str = os.getenv("INPUT_BLOCKS", "░▒▓█")
time_range: str = os.getenv('INPUT_TIME_RANGE', 'last_7_days') time_range: str = os.getenv("INPUT_TIME_RANGE", "last_7_days")
show_time: str | bool = os.getenv('INPUT_SHOW_TIME') or False show_time: str | bool = os.getenv("INPUT_SHOW_TIME") or False
show_total_time: str | bool = os.getenv('INPUT_SHOW_TOTAL') 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 show_masked_time: str | bool = os.getenv("INPUT_SHOW_MASKED_TIME") or False
language_count: str | int = os.getenv('INPUT_LANG_COUNT') or 5 language_count: str | int = os.getenv("INPUT_LANG_COUNT") or 5
stop_at_other: str | bool = os.getenv('INPUT_STOP_AT_OTHER') or False stop_at_other: str | bool = os.getenv("INPUT_STOP_AT_OTHER") or False
def validate_input(self): def validate_input(self):
""" """
Validate Input Env Variables Validate Input Env Variables
---------------------------- ----------------------------
""" """
logger.debug('Validating input 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: 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.error("Invalid inputs")
logger.info('Refer https://github.com/athul/waka-readme') logger.info("Refer https://github.com/athul/waka-readme")
return False return False
if len(self.commit_message) < 1: if len(self.commit_message) < 1:
logger.error( logger.error("Commit message length must be greater than 1 character long")
'Commit message length must be greater than 1 character long'
)
return False return False
try: try:
@ -186,35 +177,39 @@ class WakaInput:
return False return False
if not self._section_name.isalnum(): if not self._section_name.isalnum():
logger.warning('Section name must be in any of [[a-z][A-Z][0-9]]') logger.warning("Section name must be in any of [[a-z][A-Z][0-9]]")
logger.debug('Using default section name: waka') logger.debug("Using default section name: waka")
self._section_name = 'waka' self._section_name = "waka"
self.start_comment = f'<!--START_SECTION:{self._section_name}-->' self.start_comment = f"<!--START_SECTION:{self._section_name}-->"
self.end_comment = f'<!--END_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}' self.waka_block_pattern = f"{self.start_comment}[\\s\\S]+{self.end_comment}"
if len(self.block_style) < 2: if len(self.block_style) < 2:
logger.warning('Graph block must be longer than 2 characters') logger.warning("Graph block must be longer than 2 characters")
logger.debug('Using default blocks: ░▒▓█') logger.debug("Using default blocks: ░▒▓█")
self.block_style = '░▒▓█' self.block_style = "░▒▓█"
if self.time_range not in { if self.time_range not in {
'last_7_days', 'last_30_days', 'last_6_months', 'last_year', 'all_time' "last_7_days",
}: # 'all_time' is un-documented, should it be used? "last_30_days",
logger.warning('Invalid time range') "last_6_months",
logger.debug('Using default time range: last_7_days') "last_year",
self.time_range = 'last_7_days' "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"
try: try:
self.language_count = int(self.language_count) self.language_count = int(self.language_count)
if self.language_count < -1: if self.language_count < -1:
raise ValueError raise ValueError
except ValueError: except ValueError:
logger.warning('Invalid language count') logger.warning("Invalid language count")
logger.debug('Using default language count: 5') logger.debug("Using default language count: 5")
self.language_count = 5 self.language_count = 5
logger.debug('Input validation complete\n') logger.debug("Input validation complete\n")
return True return True
@ -228,40 +223,38 @@ def make_title(dawn: str | None, dusk: str | None, /):
Makes title for WakaReadme. Makes title for WakaReadme.
""" """
logger.debug('Making title') logger.debug("Making title")
if not dawn or not dusk: 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) 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: try:
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.error(f'{err}\n') logger.error(f"{err}\n")
sys.exit(1) sys.exit(1)
logger.debug('Title was made\n') logger.debug("Title was made\n")
return f'From: {start_date} - To: {end_date}' return f"From: {start_date} - To: {end_date}"
def make_graph(block_style: str, percent: float, gr_len: int, lg_nm: str = '', /): def make_graph(block_style: str, percent: float, gr_len: int, lg_nm: str = "", /):
""" """
WakaReadme Graph WakaReadme Graph
---------------- ----------------
Makes time graph from the API's data. 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 markers = len(block_style) - 1
proportion = percent / 100 * gr_len proportion = percent / 100 * gr_len
graph_bar = block_style[-1] * int(proportion + 0.5 / markers) graph_bar = block_style[-1] * int(proportion + 0.5 / markers)
remainder_block = int( remainder_block = int((proportion - len(graph_bar)) * markers + 0.5)
(proportion - len(graph_bar)) * markers + 0.5 graph_bar += block_style[remainder_block] if remainder_block > 0 else ""
)
graph_bar += block_style[remainder_block] if remainder_block > 0 else ''
graph_bar += block_style[0] * (gr_len - len(graph_bar)) 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 return graph_bar
@ -273,68 +266,65 @@ def prep_content(stats: dict[str, Any], language_count: int = 5, stop_at_other:
Prepared markdown content from the fetched statistics. Prepared markdown content from the fetched statistics.
``` ```
""" """
logger.debug('Making contents') logger.debug("Making contents")
contents = '' contents = ""
# make title # make title
if wk_i.show_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 # make byline
if wk_i.show_masked_time and ( 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' # overrides "human_readable_total"
contents += f'Total Time: {total_time}\n\n' contents += f"Total Time: {total_time}\n\n"
elif wk_i.show_total_time and ( elif wk_i.show_total_time and (total_time := stats.get("human_readable_total")):
total_time := stats.get('human_readable_total') contents += f"Total Time: {total_time}\n\n"
):
contents += f'Total Time: {total_time}\n\n'
lang_info: list[dict[str, int | float | str]] | None = [] lang_info: list[dict[str, int | float | str]] | None = []
# Check if any language data exists # Check if any language data exists
if not (lang_info := stats.get('languages')): if not (lang_info := stats.get("languages")):
logger.debug('The API data seems to be empty, please wait for a day') logger.debug("The API data seems to be empty, please wait for a day")
contents += 'No activity tracked' contents += "No activity tracked"
return contents.rstrip('\n') return contents.rstrip("\n")
# make lang content # make lang content
pad_len = len( pad_len = len(
# comment if it feels way computationally expensive # comment if it feels way computationally expensive
max((str(lng['name']) for lng in lang_info), key=len) max((str(lng["name"]) for lng in lang_info), key=len)
# and then don't for get to set pad_len to say 13 :) # and then don't for get to set pad_len to say 13 :)
) )
if language_count == 0 and not stop_at_other: if language_count == 0 and not stop_at_other:
logger.debug( logger.debug(
'Set INPUT_LANG_COUNT to -1 to retrieve all language' "Set INPUT_LANG_COUNT to -1 to retrieve all language"
+ ' or specify a positive number (ie. above 0)' + " or specify a positive number (ie. above 0)"
) )
return contents.rstrip('\n') return contents.rstrip("\n")
for idx, lang in enumerate(lang_info): for idx, lang in enumerate(lang_info):
lang_name = str(lang['name']) lang_name = str(lang["name"])
# >>> add languages to filter here <<< # >>> add languages to filter here <<<
# if lang_name in {...}: continue # if lang_name in {...}: continue
lang_time = str(lang['text']) if wk_i.show_time else '' lang_time = str(lang["text"]) if wk_i.show_time else ""
lang_ratio = float(lang['percent']) lang_ratio = float(lang["percent"])
lang_bar = make_graph( lang_bar = make_graph(wk_i.block_style, lang_ratio, wk_i.graph_length, lang_name)
wk_i.block_style, lang_ratio, wk_i.graph_length, lang_name
)
contents += ( contents += (
f'{lang_name.ljust(pad_len)} ' + f"{lang_name.ljust(pad_len)} "
f'{lang_time: <16}{lang_bar} ' + + f"{lang_time: <16}{lang_bar} "
f'{lang_ratio:.2f}'.zfill(5) + ' %\n' + f"{lang_ratio:.2f}".zfill(5)
+ " %\n"
) )
if language_count == -1: if language_count == -1:
continue continue
if stop_at_other and (lang_name == 'Other'): if stop_at_other and (lang_name == "Other"):
break break
if idx+1 >= language_count > 0: # idx starts at 0 if idx + 1 >= language_count > 0: # idx starts at 0
break break
logger.debug('Contents were made\n') logger.debug("Contents were made\n")
return contents.rstrip('\n') return contents.rstrip("\n")
def fetch_stats(): def fetch_stats():
@ -346,44 +336,38 @@ def fetch_stats():
""" """
attempts = 4 attempts = 4
statistic: dict[str, dict[str, Any]] = {} statistic: dict[str, dict[str, Any]] = {}
encoded_key = str( encoded_key = str(b64encode(bytes(str(wk_i.waka_key), "utf-8")), "utf-8")
b64encode(bytes(str(wk_i.waka_key), 'utf-8')), 'utf-8' logger.debug(f"Pulling WakaTime stats from {' '.join(wk_i.time_range.split('_'))}")
)
logger.debug(
f'Pulling WakaTime stats from {" ".join(wk_i.time_range.split("_"))}'
)
while attempts > 0: while attempts > 0:
resp_message, fake_ua = '', cryptogenic.choice( resp_message, fake_ua = "", cryptogenic.choice([str(fake.user_agent()) for _ in range(5)])
[str(fake.user_agent()) for _ in range(5)]
)
# making a request # making a request
if (resp := rq_get( if (
url=f'{str(wk_i.api_base_url).rstrip("/")}/v1/users/current/stats/{wk_i.time_range}', resp := rq_get(
headers={ url=f"{str(wk_i.api_base_url).rstrip('/')}/v1/users/current/stats/{wk_i.time_range}",
'Authorization': f'Basic {encoded_key}', headers={
'User-Agent': fake_ua, "Authorization": f"Basic {encoded_key}",
}, "User-Agent": fake_ua,
timeout=30 * (5 - attempts) },
)).status_code != 200: timeout=(30.0 * (5 - attempts)),
resp_message += f'{conn_info}' if ( )
conn_info := resp.json().get('message') ).status_code != 200:
) else '' resp_message += f"{conn_info}" if (conn_info := resp.json().get("message")) else ""
logger.debug( 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()): if resp.status_code == 200 and (statistic := resp.json()):
logger.debug('Fetched WakaTime statistics') logger.debug("Fetched WakaTime statistics")
break break
logger.debug(f'Retrying in {30 * (5 - attempts )}s ...') logger.debug(f"Retrying in {30 * (5 - attempts )}s ...")
sleep(30 * (5 - attempts)) sleep(30 * (5 - attempts))
attempts -= 1 attempts -= 1
if err := (statistic.get('error') or statistic.get('errors')): if err := (statistic.get("error") or statistic.get("errors")):
logger.error(f'{err}\n') logger.error(f"{err}\n")
sys.exit(1) sys.exit(1)
print() print()
return statistic.get('data') return statistic.get("data")
def churn(old_readme: str, /): def churn(old_readme: str, /):
@ -395,31 +379,29 @@ def churn(old_readme: str, /):
""" """
# check if placeholder pattern exists in readme # check if placeholder pattern exists in readme
if not re.findall(wk_i.waka_block_pattern, old_readme): if not re.findall(wk_i.waka_block_pattern, old_readme):
logger.warning( logger.warning(f"Can't find `{wk_i.waka_block_pattern}` pattern in readme")
f'Can\'t find `{wk_i.waka_block_pattern}` pattern in readme'
)
return None return None
# getting contents # getting contents
if not (waka_stats := fetch_stats()): 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) sys.exit(1)
# preparing contents # preparing contents
try: try:
generated_content = prep_content(waka_stats, int( generated_content = prep_content(
wk_i.language_count), bool(wk_i.stop_at_other) waka_stats, int(wk_i.language_count), bool(wk_i.stop_at_other)
) )
except (AttributeError, KeyError, ValueError) as err: 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) sys.exit(1)
print(generated_content, '\n', sep='') print(generated_content, "\n", sep="")
# substituting old contents # substituting old contents
new_readme = re.sub( new_readme = re.sub(
pattern=wk_i.waka_block_pattern, pattern=wk_i.waka_block_pattern,
repl=f'{wk_i.start_comment}\n\n```{wk_i.code_lang}\n{generated_content}\n```\n\n{wk_i.end_comment}', 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 string=old_readme,
) )
if len(sys.argv) == 2 and sys.argv[1] == '--dev': if len(sys.argv) == 2 and sys.argv[1] == "--dev":
logger.debug('Detected run in `dev` mode.') logger.debug("Detected run in `dev` mode.")
# to avoid accidentally writing back to Github # to avoid accidentally writing back to Github
# when developing and testing WakaReadme # when developing and testing WakaReadme
return None return None
@ -432,41 +414,41 @@ def genesis():
Run Program Run Program
----------- -----------
""" """
logger.debug('Connecting to GitHub') logger.debug("Connecting to GitHub")
gh_connect = Github(wk_i.gh_token) gh_connect = Github(wk_i.gh_token)
# since a validator is being used casting to string here is okay # since a validator is being used casting to string here is okay
gh_repo = gh_connect.get_repo(str(wk_i.repository)) gh_repo = gh_connect.get_repo(str(wk_i.repository))
readme_file = gh_repo.get_readme() readme_file = gh_repo.get_readme()
logger.debug('Decoding readme contents\n') logger.debug("Decoding readme contents\n")
readme_contents = str(readme_file.decoded_content, encoding='utf-8') readme_contents = str(readme_file.decoded_content, encoding="utf-8")
if new_content := churn(readme_contents): if new_content := churn(readme_contents):
logger.debug('WakaReadme stats has changed') logger.debug("WakaReadme stats has changed")
gh_repo.update_file( gh_repo.update_file(
path=readme_file.path, path=readme_file.path,
message=wk_i.commit_message, message=wk_i.commit_message,
content=new_content, content=new_content,
sha=readme_file.sha sha=readme_file.sha,
) )
logger.info('Stats updated successfully') logger.info("Stats updated successfully")
return return
logger.info('WakaReadme was not updated') logger.info("WakaReadme was not updated")
################### driver ################### ################### driver ###################
if __name__ == '__main__': if __name__ == "__main__":
# faker data preparation # faker data preparation
fake = Faker() fake = Faker()
Faker.seed(0) Faker.seed(0)
cryptogenic = SystemRandom() cryptogenic = SystemRandom()
# initial waka-readme setup # initial waka-readme setup
logger.debug('Initialize WakaReadme') logger.debug("Initialize WakaReadme")
wk_i = WakaInput() wk_i = WakaInput()
if not wk_i.validate_input(): if not wk_i.validate_input():
logger.error('Environment variables are misconfigured\n') logger.error("Environment variables are misconfigured\n")
sys.exit(1) sys.exit(1)
# run # run
@ -474,9 +456,9 @@ if __name__ == '__main__':
genesis() genesis()
except KeyboardInterrupt: except KeyboardInterrupt:
print() print()
logger.error('Interrupt signal received\n') logger.error("Interrupt signal received\n")
sys.exit(1) sys.exit(1)
except (GithubException, RequestException) as rq_exp: except (GithubException, RequestException) as rq_exp:
logger.critical(f'{rq_exp}\n') logger.critical(f"{rq_exp}\n")
sys.exit(1) sys.exit(1)
print('\nThanks for using WakaReadme!\n') print("\nThanks for using WakaReadme!\n")

View File

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