Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce pre-commit and ruff #89

Merged
merged 2 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,18 @@ jobs:
strategy:
matrix:
lint-command:
- bandit -r . -x ./tests
- black --check --diff .
- flake8 .
- isort --check-only --diff .
- pydocstyle .
- ruff check --output-format=github .
- djlint emark --reformat
steps:
- uses: actions/checkout@v4
- run: sudo apt install -y gettext
- uses: actions/setup-python@v5
with:
python-version: "3.x"
cache: 'pip'
cache-dependency-path: 'linter-requirements.txt'
- run: python -m pip install -r linter-requirements.txt
cache-dependency-path: 'pyproject.toml'
- run: python -m pip install -e .[lint]
- run: ${{ matrix.lint-command }}

pytest:
Expand Down
37 changes: 37 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: check-merge-conflict
- id: check-yaml
- id: debug-statements
- id: end-of-file-fixer
- id: name-tests-test
args: ['--pytest-test-first']
- id: no-commit-to-branch
args: [--branch, main]
- id: detect-private-key
- repo: local
hooks:
- id: ruff
name: ruff
language: system
entry: ruff check
types: [python]
args: [--fix, --exit-non-zero-on-fix]

- id: black
name: black
language: system
entry: black
types: [python]

- id: djlint
name: djlint
language: system
entry: djlint
types: [ html ]
args: [ --reformat, --profile, "django" ]
7 changes: 3 additions & 4 deletions emark/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def send_messages(self, email_messages):


class TrackingEmailBackendMixin:
"""Add tracking framework to an email backend."""
"""Add a tracking framework to an email backend."""

def send_messages(self, email_messages):
self._messages_sent = []
Expand Down Expand Up @@ -83,7 +83,7 @@ def write_message(self, message):
msg.get_charset().get_output_charset() if msg.get_charset() else "utf-8"
)
msg_data = msg_data.decode(charset)
self.stream.write("%s\n" % msg_data)
self.stream.write(f"{msg_data}\n")
self.stream.write("-" * 79)
self.stream.write("\n")
if payload_count > 1:
Expand Down Expand Up @@ -119,8 +119,7 @@ def write_message(self, message):


class TrackingSMTPEmailBackend(TrackingEmailBackendMixin, _SMTPEmailBackend):
"""
Like the SMTP email backend but with click and open tracking.
"""Like the SMTP email backend but with click and open tracking.

Furthermore, all emails are sent to a single email address.
If multiple to, cc, or bcc addresses are specified, a separate
Expand Down
10 changes: 4 additions & 6 deletions emark/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@


class MarkdownEmail(EmailMultiAlternatives):
"""
Multipart email message that renders both plaintext and HTML from markdown.
"""Multipart email message that renders both plaintext and HTML from markdown.

This is a full class:`EmailMultiAlternatives` subclass with additional support
to send emails directly to a users. It also requires an explicit language
Expand Down Expand Up @@ -102,7 +101,7 @@ def message(self):
def get_utm_campaign_name(cls):
"""Return the UTM campaign name for this email."""
return "_".join(
(m.group(0) for m in CLS_NAME_TO_CAMPAIGN_RE.finditer(cls.__qualname__))
m.group(0) for m in CLS_NAME_TO_CAMPAIGN_RE.finditer(cls.__qualname__)
).upper()

def update_url_params(self, url, **params):
Expand Down Expand Up @@ -192,8 +191,7 @@ def get_subject(self, **context):
return self.subject % context

def get_preheader(self):
"""
Return the email's preheader.
"""Return the email's preheader.

A brief text that recipients will see in their inbox before opening the email
along with the subject. Unless explicitly set, the preheader will be the first
Expand All @@ -217,7 +215,7 @@ def get_html(self, markdown_string, context):
"markdown.extensions.extra",
],
)
context["markdown_string"] = mark_safe(html_message) # nosec
context["markdown_string"] = mark_safe(html_message) # noqa: S308

template = loader.get_template(self.base_html_template)
rendered_html = template.render(context)
Expand Down
3 changes: 1 addition & 2 deletions emark/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@

@dataclasses.dataclass
class Node:
"""
Simple HTML node that can be extracted into plain text.
"""Simple HTML node that can be extracted into plain text.

Nodes have a parent and children link to create a tree structure.
Plain text extraction is done by recursively traversing the tree.
Expand Down
6 changes: 0 additions & 6 deletions linter-requirements.txt

This file was deleted.

40 changes: 31 additions & 9 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ test = [
"pytest-django",
"model_bakery",
]
lint = [
"black==24.8.0",
"pre-commit==3.8.0",
"ruff==0.5.6",
"djlint==1.34.1",
]

[project.urls]
Project-URL = "https://github.com/voiio/emark"
Expand All @@ -69,16 +75,32 @@ omit = ["emark/buildapi.py"]
[tool.coverage.report]
show_missing = true

[tool.isort]
atomic = true
line_length = 88
known_first_party = "emark, tests"
include_trailing_comma = true
default_section = "THIRDPARTY"
combine_as_imports = true
[tool.ruff]
src = ["emark", "tests"]

[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"S", # flake8-bandit
"D", # pydocstyle
"UP", # pyupgrade
"B", # flake8-bugbear
"C", # flake8-comprehensions
]

ignore = ["B904", "D1", "E501", "S101"]

[tool.ruff.lint.isort]
combine-as-imports = true
split-on-trailing-comma = true
section-order = ["future", "standard-library", "third-party", "first-party", "local-folder"]
force-wrap-aliases = true

[tool.pydocstyle]
add_ignore = "D1"
[tool.ruff.lint.pydocstyle]
convention = "google"

[tool.djlint]
profile="django"
Expand Down
1 change: 0 additions & 1 deletion tests/test_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import pytest
from django.core.mail import EmailMessage, EmailMultiAlternatives

from emark import backends
from emark.models import Send

Expand Down
5 changes: 2 additions & 3 deletions tests/test_message.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import copy
from pathlib import Path

import emark.message
import pytest
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.test.html import parse_html
from model_bakery import baker

import emark.message

BASE_DIR = Path(__file__).resolve().parent.parent


Expand Down Expand Up @@ -250,7 +249,7 @@ def test_get_preheader__missing(self):
language="en-US",
context={"donut_name": "HoneyNuts", "donut_type": "Honey"},
)
msg.get_preheader() == ""
assert msg.get_preheader() == ""
amureki marked this conversation as resolved.
Show resolved Hide resolved

def test_get_preheader(self):
email_message = MarkdownEmailTestWithPreheader(
Expand Down
3 changes: 1 addition & 2 deletions tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
import pytest
from django.urls import reverse
from django.utils.http import urlencode
from model_bakery import baker

from emark import models
from model_bakery import baker


class TestEmailDetailView:
Expand Down
7 changes: 4 additions & 3 deletions tests/testapp/settings.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""
Django settings for testapp project.
"""Django settings for testapp project.

Generated by 'django-admin startproject' using Django 4.0.4.

Expand All @@ -20,7 +19,9 @@
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "django-insecure-4787+%emei)bk2ue$5^0(5_i3+fz-0^87v)myt+8y__n$-o4@l"
SECRET_KEY = (
"django-insecure-4787+%emei)bk2ue$5^0(5_i3+fz-0^87v)myt+8y__n$-o4@l" # noqa: S105
)

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
Expand Down
Loading