chore: add pre-commit

This commit is contained in:
Luke Tainton 2024-08-04 19:02:10 +01:00
parent ed973162b6
commit 14d7cecc55
12 changed files with 107 additions and 31 deletions

View File

@ -1,3 +1,3 @@
[coverage:run] [coverage:run]
relative_files = True relative_files = True
branch = True branch = True

2
.github/CODEOWNERS vendored
View File

@ -1 +1 @@
* @luketainton * @luketainton

40
.github/renovate.json vendored
View File

@ -1,26 +1,42 @@
{ {
"extends": ["config:base"],
"platformCommit": true,
"dependencyDashboardAutoclose": true,
"assignAutomerge": true, "assignAutomerge": true,
"assigneesFromCodeOwners": true, "assigneesFromCodeOwners": true,
"rebaseWhen": "behind-base-branch", "dependencyDashboardAutoclose": true,
"rollbackPrs": true, "extends": [
"labels": ["dependencies"], "config:base"
],
"labels": [
"dependencies"
],
"packageRules": [ "packageRules": [
{ {
"matchPackagePatterns": ["black", "pylint"], "labels": [
"labels": ["linting"] "linting"
],
"matchPackagePatterns": [
"black",
"pylint"
]
}, },
{ {
"matchPackagePatterns": ["coverage", "pytest"], "labels": [
"labels": ["unit-tests"] "unit-tests"
],
"matchPackagePatterns": [
"coverage",
"pytest"
]
} }
], ],
"platformCommit": true,
"rebaseWhen": "behind-base-branch",
"rollbackPrs": true,
"vulnerabilityAlerts": { "vulnerabilityAlerts": {
"enabled": true,
"labels": ["security"],
"commitMessagePrefix": "[SECURITY] ", "commitMessagePrefix": "[SECURITY] ",
"enabled": true,
"labels": [
"security"
],
"prCreation": "immediate" "prCreation": "immediate"
} }
} }

60
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,60 @@
fail_fast: false
minimum_pre_commit_version: 3.8.0
default_install_hook_types: [pre-commit, commit-msg]
default_language_version:
python: python3.11
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: mixed-line-ending
- id: end-of-file-fixer
- id: requirements-txt-fixer
- id: check-yaml
- id: check-added-large-files
- id: check-ast
- id: check-docstring-first
- id: check-json
- id: check-merge-conflict
- id: check-toml
- id: check-xml
- id: detect-private-key
- id: no-commit-to-branch
- id: requirements-txt-fixer
- id: name-tests-test
args: [--pytest-test-first]
- id: pretty-format-json
args: [--autofix]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.5.6
hooks:
- id: ruff-format # Run the formatter.
- id: ruff # Run the linter.
args: [--fix]
# - repo: https://github.com/pycqa/isort
# rev: 5.13.2
# hooks:
# - id: isort
- repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.10.0
hooks:
- id: python-use-type-annotations
- repo: https://github.com/asottile/pyupgrade
rev: v3.17.0
hooks:
- id: pyupgrade
- repo: https://github.com/compilerla/conventional-pre-commit
rev: v3.4.0
hooks:
- id: conventional-pre-commit
stages: [commit-msg]

View File

@ -5,6 +5,7 @@ import os
class Config: class Config:
"""Configuration module.""" """Configuration module."""
def __init__(self) -> None: def __init__(self) -> None:
"""Configuration module.""" """Configuration module."""
self.__environment: str = os.environ.get("APP_LIFECYCLE", "DEV").upper() self.__environment: str = os.environ.get("APP_LIFECYCLE", "DEV").upper()

View File

@ -1,6 +1,5 @@
import requests import requests
CHAR_REPLACEMENTS: list = [ CHAR_REPLACEMENTS: list = [
["_", "__"], ["_", "__"],
["-", "--"], ["-", "--"],
@ -56,5 +55,7 @@ def generate_api_url(template: str, top_str: str, btm_str: str) -> str:
top_str = format_meme_string(top_str) top_str = format_meme_string(top_str)
btm_str = format_meme_string(btm_str) btm_str = format_meme_string(btm_str)
url: str = f"https://api.memegen.link/images/{tmpl_name}/{top_str}/{btm_str}.{tmpl_ext}" url: str = (
f"https://api.memegen.link/images/{tmpl_name}/{top_str}/{btm_str}.{tmpl_ext}"
)
return url return url

View File

@ -2,13 +2,11 @@
import sentry_sdk import sentry_sdk
from sentry_sdk.integrations.stdlib import StdlibIntegration from sentry_sdk.integrations.stdlib import StdlibIntegration
from webex_bot.webex_bot import WebexBot from webex_bot.webex_bot import WebexBot
from app import close, meme from app import close, meme
from app.config import config from app.config import config
if config.sentry_enabled: if config.sentry_enabled:
apm = sentry_sdk.init( apm = sentry_sdk.init(
dsn=config.sentry_dsn, dsn=config.sentry_dsn,
@ -16,7 +14,7 @@ if config.sentry_enabled:
environment=config.environment, environment=config.environment,
release=config.version, release=config.version,
integrations=[StdlibIntegration()], integrations=[StdlibIntegration()],
spotlight=True spotlight=True,
) )

View File

@ -2,25 +2,25 @@ from webex_bot.models.command import Command
from webex_bot.models.response import Response, response_from_adaptive_card from webex_bot.models.response import Response, response_from_adaptive_card
from webexteamssdk.models.cards import ( from webexteamssdk.models.cards import (
AdaptiveCard, AdaptiveCard,
Choice,
Choices,
Column, Column,
ColumnSet, ColumnSet,
FontSize, FontSize,
FontWeight, FontWeight,
Text, Text,
TextBlock, TextBlock,
Choice,
Choices,
) )
from webexteamssdk.models.cards.actions import Submit, OpenUrl from webexteamssdk.models.cards.actions import OpenUrl, Submit
from app import img from app import img
TEMPLATES = img.get_templates() TEMPLATES = img.get_templates()
class MakeMemeCommand(Command): class MakeMemeCommand(Command):
"""Class for initial Webex interactive card.""" """Class for initial Webex interactive card."""
def __init__(self) -> None: def __init__(self) -> None:
super().__init__( super().__init__(
command_keyword="/meme", command_keyword="/meme",
@ -69,7 +69,8 @@ class MakeMemeCommand(Command):
id="meme_type", id="meme_type",
isMultiSelect=False, isMultiSelect=False,
choices=[ choices=[
Choice(title=x["name"], value=x["choiceval"]) for x in TEMPLATES Choice(title=x["name"], value=x["choiceval"])
for x in TEMPLATES
], ],
), ),
Text(id="text_top", placeholder="Top Text", maxLength=100), Text(id="text_top", placeholder="Top Text", maxLength=100),
@ -100,6 +101,7 @@ class MakeMemeCommand(Command):
class MakeMemeCallback(Command): class MakeMemeCallback(Command):
"""Class to process user data and return meme.""" """Class to process user data and return meme."""
def __init__(self) -> None: def __init__(self) -> None:
super().__init__( super().__init__(
card_callback_keyword="make_meme_callback_rbamzfyx", card_callback_keyword="make_meme_callback_rbamzfyx",

View File

@ -19,7 +19,6 @@ pathspec==0.12.1
platformdirs==4.2.2 platformdirs==4.2.2
pluggy==1.5.0 pluggy==1.5.0
pre-commit==3.8.0 pre-commit==3.8.0
pylint-exit==1.2.0
pylint==3.2.6 pylint==3.2.6
pylint-exit==1.2.0 pylint-exit==1.2.0
pytest==8.3.2 pytest==8.3.2

View File

@ -8,4 +8,4 @@ sonar.python.pylint.reportPaths=lintreport.txt
sonar.python.xunit.reportPath=testresults.xml sonar.python.xunit.reportPath=testresults.xml
sonar.sources=app sonar.sources=app
sonar.tests=tests sonar.tests=tests
sonar.exclusions=,.github/**,.gitignore,CODEOWNERS,CHANGELOG.md,LICENSE.md,README.md,renovate.json,requirements-dev.txt,requirements.txt sonar.exclusions=,.github/**,.gitignore,CODEOWNERS,CHANGELOG.md,LICENSE.md,README.md,renovate.json,requirements-dev.txt,requirements.txt

View File

@ -2,12 +2,11 @@
import os import os
vars: dict = { vars: dict = {
"APP_VERSION": "dev", "APP_VERSION": "dev",
"WEBEX_API_KEY": "testing", "WEBEX_API_KEY": "testing",
"SENTRY_ENABLED": "false", "SENTRY_ENABLED": "false",
"SENTRY_DSN": "http://localhost" "SENTRY_DSN": "http://localhost",
} }
@ -15,7 +14,7 @@ for var, value in vars.items():
os.environ[var] = value os.environ[var] = value
# needs to be imported AFTER environment variables are set # needs to be imported AFTER environment variables are set
from app.config import config # pragma: no cover from app.config import config # pragma: no cover # noqa: E402
def test_config() -> None: def test_config() -> None:

View File

@ -30,7 +30,7 @@ def test_error_false() -> None:
callback.text_bottom = "TEST" callback.text_bottom = "TEST"
result: Response = callback.execute(None, None, {"target": {"globalId": "TEST"}}) result: Response = callback.execute(None, None, {"target": {"globalId": "TEST"}})
assert ( assert (
isinstance(result, Response) \ isinstance(result, Response)
and result.roomId == "TEST" \ and result.roomId == "TEST"
and result.files[0] == callback.meme_filename and result.files[0] == callback.meme_filename
) )