Add linting

This commit is contained in:
Jake Howard 2022-06-12 15:17:28 +01:00
parent b997350283
commit e2d5101a56
Signed by: jake
GPG key ID: 57AFB45680EDD477
13 changed files with 104 additions and 31 deletions

View file

@ -40,14 +40,28 @@ pip:
- ./env/ - ./env/
expire_in: 30 mins expire_in: 30 mins
just:
stage: build
before_script:
- apt-get update && apt-get install -y curl
script:
- curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to $CI_PROJECT_DIR/.just-bin
artifacts:
name: 'pip-$CI_JOB_ID'
paths:
- $CI_PROJECT_DIR/.just-bin
expire_in: 30 mins
.python_test_template: &python_test_template .python_test_template: &python_test_template
stage: test stage: test
dependencies: dependencies:
- pip - pip
- collect_static - collect_static
- static - static
- just
before_script: before_script:
- source env/bin/activate - source env/bin/activate
- mv $CI_PROJECT_DIR/.just-bin/just /usr/local/bin/just
variables: variables:
SECRET_KEY: super-secret SECRET_KEY: super-secret
@ -57,9 +71,11 @@ collect_static:
dependencies: dependencies:
- pip - pip
- static - static
- just
needs: needs:
- pip - pip
- static - static
- just
script: script:
- ./manage.py collectstatic --noinput -v2 --clear - ./manage.py collectstatic --noinput -v2 --clear
artifacts: artifacts:
@ -80,3 +96,8 @@ django_checks:
script: script:
- ./manage.py check - ./manage.py check
- ./manage.py makemigrations --check --noinput - ./manage.py makemigrations --check --noinput
python_lint:
<<: *python_test_template
script:
- just lint

View file

@ -1,3 +1,7 @@
-r requirements.txt -r requirements.txt
honcho==1.1.0 honcho==1.1.0
django-stubs[compatible-mypy]==1.11.0
flake8==4.0.1
isort==5.10.1
black==22.3.0

View file

@ -21,5 +21,18 @@ install:
@manage +ARGS: @manage +ARGS:
./manage.py {{ ARGS }} ./manage.py {{ ARGS }}
@pip +ARGS:
pip {{ ARGS }}
test *ARGS: test *ARGS:
./manage.py test {{ ARGS }} ./manage.py test {{ ARGS }}
format:
black website
isort website
lint:
black --check website
isort --check website
flake8 website
mypy website

23
setup.cfg Normal file
View file

@ -0,0 +1,23 @@
[mypy]
no_implicit_optional = True
warn_unused_ignores = True
strict_optional = True
check_untyped_defs = True
ignore_missing_imports = True
disallow_untyped_calls = True
disallow_untyped_defs = True
disallow_incomplete_defs = True
plugins = mypy_django_plugin.main
[mypy.plugins.django-stubs]
django_settings_module = "website.settings"
[isort]
multi_line_output=3
include_trailing_comma=True
force_grid_wrap=0
use_parentheses=True
line_length=88
[flake8]
extend_ignore=E128,E501

View file

@ -1,5 +1,3 @@
from django.db import models
from wagtail.models import Page from wagtail.models import Page
@ -9,5 +7,5 @@ class BasePage(Page):
@classmethod @classmethod
@property @property
def body_class(cls): def body_class(cls) -> str:
return "page-" + cls._meta.db_table.replace("_", "-") return "page-" + cls._meta.db_table.replace("_", "-")

View file

@ -1,12 +1,17 @@
from django.test import SimpleTestCase from django.test import SimpleTestCase
from .utils import get_page_models
from .models import BasePage from .models import BasePage
from .utils import get_page_models
class BasePageTestCase(SimpleTestCase): class BasePageTestCase(SimpleTestCase):
def test_unique_body_classes(self): def test_unique_body_classes(self) -> None:
body_classes = [page.body_class for page in get_page_models()] body_classes = [page.body_class for page in get_page_models()]
self.assertEqual(len(body_classes), len(set(body_classes))) self.assertEqual(len(body_classes), len(set(body_classes)))
def test_pages_inherit_base_page(self): def test_pages_inherit_base_page(self) -> None:
for page_model in get_page_models(): for page_model in get_page_models():
self.assertTrue(issubclass(page_model, BasePage), f"{page_model} does not inherit from {BasePage}.") self.assertTrue(
issubclass(page_model, BasePage),
f"{page_model} does not inherit from {BasePage}.",
)

View file

@ -1,6 +1,10 @@
from wagtail.models import get_page_models as get_wagtail_page_models, Page from typing import Type
def get_page_models(): from wagtail.models import Page
from wagtail.models import get_page_models as get_wagtail_page_models
def get_page_models() -> list[Type[Page]]:
page_models = get_wagtail_page_models().copy() page_models = get_wagtail_page_models().copy()
page_models.remove(Page) page_models.remove(Page)
return page_models return page_models

View file

@ -1,8 +1,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.db import migrations from django.db import migrations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
def create_homepage(apps, schema_editor): def create_homepage(
apps: migrations.state.StateApps, schema_editor: BaseDatabaseSchemaEditor
) -> None:
# Get models # Get models
ContentType = apps.get_model("contenttypes.ContentType") ContentType = apps.get_model("contenttypes.ContentType")
Page = apps.get_model("wagtailcore.Page") Page = apps.get_model("wagtailcore.Page")
@ -34,7 +37,9 @@ def create_homepage(apps, schema_editor):
Site.objects.create(hostname="localhost", root_page=homepage, is_default_site=True) Site.objects.create(hostname="localhost", root_page=homepage, is_default_site=True)
def remove_homepage(apps, schema_editor): def remove_homepage(
apps: migrations.state.StateApps, schema_editor: BaseDatabaseSchemaEditor
) -> None:
# Get models # Get models
ContentType = apps.get_model("contenttypes.ContentType") ContentType = apps.get_model("contenttypes.ContentType")
HomePage = apps.get_model("home.HomePage") HomePage = apps.get_model("home.HomePage")

View file

@ -1,4 +1,5 @@
from website.common.models import BasePage from website.common.models import BasePage
class HomePage(BasePage): class HomePage(BasePage):
pass pass

View file

@ -1,11 +1,15 @@
from django.test import TestCase from django.test import TestCase
from .models import HomePage from .models import HomePage
class HomePageTestCase(TestCase): class HomePageTestCase(TestCase):
page: HomePage
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls) -> None:
cls.page = HomePage.objects.get() cls.page = HomePage.objects.get()
def test_accessible(self): def test_accessible(self) -> None:
response = self.client.get(self.page.url) response = self.client.get(self.page.url)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)

View file

@ -1,11 +1,11 @@
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
from django.http.request import HttpRequest
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from wagtail.models import Page from wagtail.models import Page
from wagtail.search.models import Query from wagtail.search.models import Query
def search(request): def search(request: HttpRequest) -> TemplateResponse:
search_query = request.GET.get("query", None) search_query = request.GET.get("query", None)
page = request.GET.get("page", 1) page = request.GET.get("page", 1)

View file

@ -1,19 +1,17 @@
from pathlib import Path from pathlib import Path
import environ import environ
BASE_DIR = Path(__file__).parent.parent BASE_DIR = Path(__file__).parent.parent
env = environ.Env( env = environ.Env(DEBUG=(bool, False), BASE_HOSTNAME=(str, "example.com"))
DEBUG=(bool, False),
BASE_HOSTNAME=(str, "example.com")
)
# Read local secrets # Read local secrets
environ.Env.read_env(BASE_DIR / '.env') environ.Env.read_env(BASE_DIR / ".env")
DEBUG = env('DEBUG') DEBUG = env("DEBUG")
SECRET_KEY = env('SECRET_KEY') SECRET_KEY = env("SECRET_KEY")
ALLOWED_HOSTS = ["*"] ALLOWED_HOSTS = ["*"]
@ -80,9 +78,7 @@ TEMPLATES = [
WSGI_APPLICATION = "website.wsgi.application" WSGI_APPLICATION = "website.wsgi.application"
DATABASES = { DATABASES = {"default": env.db(default=f"sqlite:///{BASE_DIR}/db.sqlite3")}
'default': env.db(default=f"sqlite:///{BASE_DIR}/db.sqlite3")
}
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/4.0/topics/i18n/ # https://docs.djangoproject.com/en/4.0/topics/i18n/
@ -132,5 +128,5 @@ WAGTAILSEARCH_BACKENDS = {
} }
} }
BASE_HOSTNAME = env('BASE_HOSTNAME') BASE_HOSTNAME = env("BASE_HOSTNAME")
WAGTAILADMIN_BASE_URL = f"https://{BASE_HOSTNAME}" WAGTAILADMIN_BASE_URL = f"https://{BASE_HOSTNAME}"

View file

@ -1,9 +1,8 @@
from django.conf import settings from django.conf import settings
from django.urls import include, path
from django.contrib import admin from django.contrib import admin
from django.urls import include, path
from wagtail.admin import urls as wagtailadmin_urls
from wagtail import urls as wagtail_urls from wagtail import urls as wagtail_urls
from wagtail.admin import urls as wagtailadmin_urls
from wagtail.documents import urls as wagtaildocs_urls from wagtail.documents import urls as wagtaildocs_urls
from website.search import views as search_views from website.search import views as search_views