MyPy, Pylint

This commit is contained in:
DarkCat09 2023-05-30 14:47:06 +04:00
parent ca8816a77d
commit 73fc57a105
4 changed files with 226 additions and 15 deletions

2
.gitignore vendored
View file

@ -2,5 +2,7 @@
.vscode .vscode
__pycache__ __pycache__
.mypy_cache
venv venv
.env .env

41
main.py
View file

@ -1,3 +1,5 @@
#!/usr/bin/env python3
import json import json
import hashlib import hashlib
@ -8,11 +10,11 @@ import requests
from pydantic import BaseSettings from pydantic import BaseSettings
from aiogram import Bot from aiogram import Bot # type: ignore
from aiogram.dispatcher import Dispatcher from aiogram.dispatcher import Dispatcher # type: ignore
from aiogram.utils import executor from aiogram.utils import executor # type: ignore
from aiogram.types import InlineQuery from aiogram.types import InlineQuery # type: ignore
from aiogram.types import InlineQueryResultArticle from aiogram.types import InlineQueryResultArticle
from aiogram.types import InputTextMessageContent from aiogram.types import InputTextMessageContent
@ -22,9 +24,11 @@ DDG_URL = 'https://duckduckgo.com/js/spice/currency'
COINAPI_URL = 'https://rest.coinapi.io/v1/exchangerate' COINAPI_URL = 'https://rest.coinapi.io/v1/exchangerate'
# --- # ---
# Config from .env # Config from .env
class Settings(BaseSettings): class Settings(BaseSettings):
debug: bool debug: bool
timeout: int = 2
coinapi_key: str coinapi_key: str
telegram_token: str telegram_token: str
@ -32,9 +36,11 @@ class Settings(BaseSettings):
env_file = '.env' env_file = '.env'
env_file_encoding = 'utf-8' env_file_encoding = 'utf-8'
settings = Settings()
settings = Settings() # type: ignore
# --- # ---
# Logging # Logging
log = logging.getLogger('shirino') log = logging.getLogger('shirino')
handler = logging.StreamHandler() handler = logging.StreamHandler()
@ -48,28 +54,29 @@ if settings.debug:
log.setLevel(logging.DEBUG) log.setLevel(logging.DEBUG)
# --- # ---
bot = Bot(token=settings.telegram_token) bot = Bot(token=settings.telegram_token)
dp = Dispatcher(bot) dp = Dispatcher(bot)
class CurrencyConverter: class CurrencyConverter:
def __init__(self) -> None: def __init__(self) -> None:
self.amount = 1.0 self.amount = 1.0
self.conv_amount = 0.0 self.conv_amount = 0.0
self.from_currency = '' self.from_currency = ''
self.conv_currency = '' self.conv_currency = ''
def convert(self) -> None: def convert(self) -> None:
"""Currency conversion""" """Currency conversion"""
if not self.ddgapi(): if not self.ddgapi():
self.coinapi() self.coinapi()
def ddgapi(self) -> bool: def ddgapi(self) -> bool:
"""Get data from DuckDuckGo's currency API """Get data from DuckDuckGo's currency API
Returns: Returns:
`False` if the currency does not exist, `False` if the currency does not exist,
`True` on successful conversion `True` on successful conversion
@ -77,16 +84,19 @@ class CurrencyConverter:
# API request # API request
resp = requests.get( resp = requests.get(
f'{DDG_URL}/{self.amount}/{self.from_currency}' (
f'/{self.conv_currency}' f'{DDG_URL}/{self.amount}/{self.from_currency}'
f'/{self.conv_currency}'
),
timeout=settings.timeout,
) )
log.debug(resp.text) log.debug(resp.text)
# Parsing JSON data # Parsing JSON data
data: Dict[str, Any] = json.loads( data: Dict[str, Any] = json.loads(
resp.text \ resp.text
.replace('ddg_spice_currency(', '') \ .replace('ddg_spice_currency(', '')
.replace(');', '') .replace(');', '')
) )
@ -104,7 +114,7 @@ class CurrencyConverter:
log.debug(conv) log.debug(conv)
return True return True
def coinapi(self) -> None: def coinapi(self) -> None:
"""Get data from CoinAPI (for cryptocurrencies)""" """Get data from CoinAPI (for cryptocurrencies)"""
@ -116,6 +126,7 @@ class CurrencyConverter:
headers={ headers={
'X-CoinAPI-Key': settings.coinapi_key, 'X-CoinAPI-Key': settings.coinapi_key,
}, },
timeout=settings.timeout,
) )
data: Dict[str, Any] = resp.json() data: Dict[str, Any] = resp.json()

5
mypy.ini Normal file
View file

@ -0,0 +1,5 @@
[mypy]
check_untyped_defs = True
warn_return_any = True
warn_unreachable = True
show_error_codes = True

193
pylintrc Normal file
View file

@ -0,0 +1,193 @@
[MAIN]
analyse-fallback-blocks=no
clear-cache-post-run=no
extension-pkg-allow-list=
extension-pkg-whitelist=
fail-on=
fail-under=10
ignore=CVS
ignore-paths=
ignore-patterns=^\.#
ignored-modules=
jobs=4
limit-inference-results=100
load-plugins=
persistent=yes
py-version=3.10
recursive=no
suggestion-mode=yes
unsafe-load-any-extension=no
[BASIC]
argument-naming-style=snake_case
attr-naming-style=snake_case
bad-names=foo,
bar,
baz,
toto,
tutu,
tata
bad-names-rgxs=
class-attribute-naming-style=any
class-const-naming-style=UPPER_CASE
class-naming-style=PascalCase
const-naming-style=UPPER_CASE
docstring-min-length=-1
function-naming-style=snake_case
good-names=i,
j,
k,
ex,
Run,
_
good-names-rgxs=
include-naming-hint=no
inlinevar-naming-style=any
method-naming-style=snake_case
module-naming-style=snake_case
name-group=
no-docstring-rgx=^_
property-classes=abc.abstractproperty
variable-naming-style=snake_case
[CLASSES]
check-protected-access-in-special-methods=no
defining-attr-methods=__init__,
__new__,
setUp,
__post_init__
exclude-protected=_asdict,
_fields,
_replace,
_source,
_make
valid-classmethod-first-arg=cls
valid-metaclass-classmethod-first-arg=mcs
[DESIGN]
exclude-too-few-public-methods=
ignored-parents=
max-args=5
max-attributes=7
max-bool-expr=5
max-branches=12
max-locals=15
max-parents=7
max-public-methods=20
max-returns=6
max-statements=50
min-public-methods=0
[EXCEPTIONS]
overgeneral-exceptions=builtins.BaseException,builtins.Exception
[FORMAT]
expected-line-ending-format=
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
indent-after-paren=4
indent-string=' '
max-line-length=100
max-module-lines=1000
single-line-class-stmt=no
single-line-if-stmt=no
[IMPORTS]
allow-any-import-level=
allow-reexport-from-package=no
allow-wildcard-with-all=no
deprecated-modules=
ext-import-graph=
import-graph=
int-import-graph=
known-standard-library=
known-third-party=enchant
preferred-modules=
[LOGGING]
logging-format-style=old
logging-modules=logging
[MESSAGES CONTROL]
confidence=HIGH,
CONTROL_FLOW,
INFERENCE,
INFERENCE_FAILURE,
UNDEFINED
disable=raw-checker-failed,
bad-inline-option,
locally-disabled,
file-ignored,
suppressed-message,
useless-suppression,
deprecated-pragma,
use-symbolic-message-instead,
missing-module-docstring,
missing-class-docstring,
missing-function-docstring,
broad-exception-caught
enable=c-extension-no-member
[METHOD_ARGS]
timeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests.api.options,requests.api.patch,requests.api.post,requests.api.put,requests.api.request
[MISCELLANEOUS]
notes=FIXME,
XXX,
TODO
notes-rgx=
[REFACTORING]
max-nested-blocks=5
never-returning-functions=sys.exit,argparse.parse_error
[REPORTS]
evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10))
msg-template=
reports=no
score=yes
[SIMILARITIES]
ignore-comments=yes
ignore-docstrings=yes
ignore-imports=yes
ignore-signatures=yes
min-similarity-lines=4
[SPELLING]
max-spelling-suggestions=4
spelling-dict=
spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:
spelling-ignore-words=
spelling-private-dict-file=
spelling-store-unknown-words=no
[STRING]
check-quote-consistency=no
check-str-concat-over-line-jumps=no
[TYPECHECK]
contextmanager-decorators=contextlib.contextmanager
generated-members=
ignore-none=yes
ignore-on-opaque-inference=yes
ignored-checks-for-mixins=no-member,
not-async-context-manager,
not-context-manager,
attribute-defined-outside-init
ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace
missing-member-hint=yes
missing-member-hint-distance=1
missing-member-max-choices=1
mixin-class-rgx=.*[Mm]ixin
signature-mutators=
[VARIABLES]
additional-builtins=
allow-global-unused-variables=yes
allowed-redefined-builtins=
callbacks=cb_,
_cb
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
ignored-argument-names=_.*|^ignored_|^unused_
init-import=no
redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io