Skip to content

Commit

Permalink
Merge main again
Browse files Browse the repository at this point in the history
  • Loading branch information
faucomte97 committed Apr 16, 2024
2 parents 510c110 + 01d9452 commit 359f6dd
Show file tree
Hide file tree
Showing 20 changed files with 100 additions and 62 deletions.
49 changes: 11 additions & 38 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,54 +10,29 @@ on:
- ".*"
workflow_dispatch:

env:
PYTHON_VERSION: 3.8

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: [3.8]
steps:
- name: 🛫 Checkout
uses: actions/checkout@v3

- name: 🐍 Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: 🛠 Install Dependencies
run: |
python -m pip install --upgrade pip
python -m pip install pipenv
pipenv install --dev
- name: 🔎 Check Code Format
run: if ! pipenv run black --check .; then exit 1; fi

- name: 🔎 Check Migrations
run: pipenv run python manage.py makemigrations --check --dry-run

# TODO: assert code coverage target.
- name: 🧪 Test Code Units
run: pipenv run pytest -n auto
uses: ocadotechnology/codeforlife-workspace/.github/workflows/test-python-code.yaml@main
with:
# Cannot be set with an env var. Value must match in the release job.
python-version: 3.8

release:
concurrency: release
runs-on: ubuntu-latest
needs: [test]
if: github.ref_name == 'main'
env:
# Value must match in the test job.
PYTHON_VERSION: 3.8
steps:
- name: 🛫 Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
token: ${{ secrets.CFL_BOT_GITHUB_TOKEN }}
fetch-depth: 0

- name: 🐍 Set up Python
- name: 🐍 Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
Expand All @@ -67,10 +42,8 @@ jobs:
python -m pip install --upgrade pip
python -m pip install python-semantic-release~=7.33
- name: ⚙️ Configure Git
run: |
git config --local user.name cfl-bot
git config --local user.email [email protected]
- name: 🤖 Set up cfl-bot as Git User
uses: ocadotechnology/codeforlife-workspace/.github/actions/git/setup-bot@main

- name: 🚀 Publish Semantic Release
env:
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

<!--next-version-placeholder-->

## v0.16.2 (2024-04-16)

### Fix

* Polish mypy ([#110](https://github.com/ocadotechnology/codeforlife-package-python/issues/110)) ([`bcbe98f`](https://github.com/ocadotechnology/codeforlife-package-python/commit/bcbe98f6209c493de1837f12ab32761478778004))

## v0.16.1 (2024-04-15)

### Fix
Expand Down
4 changes: 2 additions & 2 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion codeforlife/models/signals/pre_save.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ def get_previous_value(field: str):
return None

else:
previous_instance = instance.__class__.objects.get(pk=instance.pk)
objects = instance.__class__.objects # type: ignore[attr-defined]
previous_instance = objects.get(pk=instance.pk)

def get_previous_value(field: str):
return getattr(previous_instance, field)
Expand Down
4 changes: 2 additions & 2 deletions codeforlife/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
ModelListSerializerTestCase,
ModelSerializerTestCase,
)
from .model_view_set import ModelViewSetTestCase
from .test import TestCase
from .model_view_set import ModelViewSetClient, ModelViewSetTestCase
from .test import Client, TestCase
4 changes: 3 additions & 1 deletion codeforlife/tests/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,9 @@ def _login_user_type(self, user_type: t.Type[LoginUser], **credentials):
otp = user.totp.at(now)
with patch.object(timezone, "now", return_value=now):
assert super().login(
request=self.request_factory.post(user=user),
request=self.request_factory.post(
user=t.cast(RequestUser, user)
),
otp=otp,
), f'Failed to login with OTP "{otp}" at {now}.'

Expand Down
6 changes: 4 additions & 2 deletions codeforlife/tests/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import typing as t
from unittest.case import _AssertRaisesContext

from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Model
from django.db.utils import IntegrityError

Expand Down Expand Up @@ -76,8 +77,9 @@ def assert_does_not_exist(self, model_or_pk: t.Union[AnyModel, t.Any]):
"""

model_class = self.get_model_class()
with self.assertRaises(model_class.DoesNotExist):
with self.assertRaises(ObjectDoesNotExist):
if isinstance(model_or_pk, Model):
model_or_pk.refresh_from_db()
else:
model_class.objects.get(pk=model_or_pk)
objects = model_class.objects # type: ignore[attr-defined]
objects.get(pk=model_or_pk)
26 changes: 18 additions & 8 deletions codeforlife/tests/model_view_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import typing as t
from datetime import datetime

from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Model
from django.db.models.query import QuerySet
from django.urls import reverse
Expand All @@ -19,7 +20,7 @@
from ..serializers import BaseSerializer
from ..types import DataDict, JsonDict, KwArgs
from ..user.models import AnyUser as RequestUser
from ..user.models import User
from ..user.models import Class, Student, User
from ..views import ModelViewSet
from .api import APIClient, APITestCase

Expand Down Expand Up @@ -681,8 +682,13 @@ def assert_serialized_model_equals_json_model(
"""
# Get the logged-in user.
try:
user = User.objects.get(session=self.client.session.session_key)
except User.DoesNotExist:
user = t.cast(
RequestUser,
self.get_request_user_class().objects.get(
session=self.client.session.session_key
),
)
except ObjectDoesNotExist:
user = None # NOTE: no user has logged in.

# Create an instance of the model view set and serializer.
Expand Down Expand Up @@ -844,7 +850,9 @@ def get_another_school_user(
school = (
user.teacher.school
if user.teacher
else user.student.class_field.teacher.school
else t.cast(
Class, t.cast(Student, user.student).class_field
).teacher.school
)
assert school

Expand Down Expand Up @@ -882,12 +890,14 @@ def get_another_school_user(
)
# Else, both users are students.
else:
klass = t.cast(
Class, t.cast(Student, user.student).class_field
)

assert (
user.student.class_field
== other_user.student.class_field
klass == other_user.student.class_field
if same_class
else user.student.class_field
!= other_user.student.class_field
else klass != other_user.student.class_field
)
else:
assert school != other_school
Expand Down
28 changes: 28 additions & 0 deletions codeforlife/tests/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,40 @@
Created on 10/04/2024 at 13:03:00(+01:00).
"""

import typing as t
from unittest.case import _AssertRaisesContext

from django.core.exceptions import ValidationError
from django.http import HttpResponse
from django.test import Client as _Client
from django.test import TestCase as _TestCase


class Client(_Client):
"""A Django client with type hints."""

def generic(self, *args, **kwargs):
return t.cast(HttpResponse, super().generic(*args, **kwargs))

def get(self, *args, **kwargs):
return t.cast(HttpResponse, super().get(*args, **kwargs))

def post(self, *args, **kwargs):
return t.cast(HttpResponse, super().post(*args, **kwargs))

def put(self, *args, **kwargs):
return t.cast(HttpResponse, super().put(*args, **kwargs))

def patch(self, *args, **kwargs):
return t.cast(HttpResponse, super().patch(*args, **kwargs))

def delete(self, *args, **kwargs):
return t.cast(HttpResponse, super().delete(*args, **kwargs))

def options(self, *args, **kwargs):
return t.cast(HttpResponse, super().options(*args, **kwargs))


class TestCase(_TestCase):
"""Base test case for all tests to inherit."""

Expand Down
6 changes: 4 additions & 2 deletions codeforlife/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
Created on 12/04/2024 at 14:42:20(+01:00).
"""

import typing as t

from django.contrib import admin
from django.contrib.auth.views import LogoutView
from django.http import HttpResponse
from django.shortcuts import render
from django.urls import include, path, re_path
from django.urls import URLPattern, URLResolver, include, path, re_path
from rest_framework import status

from .settings import SERVICE_IS_ROOT, SERVICE_NAME
Expand All @@ -31,7 +33,7 @@ def service_urlpatterns(
"""

# Specific url patterns.
urlpatterns = [
urlpatterns: t.List[t.Union[URLResolver, URLPattern]] = [
path(
"admin/",
admin.site.urls,
Expand Down
7 changes: 6 additions & 1 deletion codeforlife/user/auth/backends/user_id_and_login_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@

import typing as t

from common.helpers.generators import get_hashed_login_id
# isort: off
from common.helpers.generators import ( # type: ignore[import-untyped]
get_hashed_login_id,
)

# isort: on

from ....request import HttpRequest
from ...models import Student, StudentUser
Expand Down
2 changes: 1 addition & 1 deletion codeforlife/user/auth/password_validators/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
Created on 30/01/2024 at 12:28:00(+00:00).
"""

from .student import StudentPasswordValidator
from .independent import IndependentPasswordValidator
from .student import StudentPasswordValidator
from .teacher import TeacherPasswordValidator
4 changes: 3 additions & 1 deletion codeforlife/user/filters/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
Created on 03/04/2024 at 16:37:44(+01:00).
"""

from django_filters import rest_framework as filters
from django_filters import ( # type: ignore[import-untyped] # isort: skip
rest_framework as filters,
)

from ..models import User

Expand Down
2 changes: 1 addition & 1 deletion codeforlife/user/models/klass.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
"""

# pylint: disable-next=unused-import
from common.models import Class
from common.models import Class # type: ignore[import-untyped]
2 changes: 1 addition & 1 deletion codeforlife/user/models/school.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
"""

# pylint: disable-next=unused-import
from common.models import School
from common.models import School # type: ignore[import-untyped]
2 changes: 2 additions & 0 deletions codeforlife/user/models/student.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# TODO: remove this in new system
# mypy: disable-error-code="import-untyped"
"""
© Ocado Group
Created on 14/02/2024 at 17:16:44(+00:00).
Expand Down
2 changes: 2 additions & 0 deletions codeforlife/user/models/teacher.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# TODO: remove this in new system
# mypy: disable-error-code="import-untyped"
"""
© Ocado Group
Created on 05/02/2024 at 09:49:56(+00:00).
Expand Down
2 changes: 2 additions & 0 deletions codeforlife/user/models/user.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# TODO: remove this in new system
# mypy: disable-error-code="import-untyped"
"""
© Ocado Group
Created on 05/02/2024 at 09:50:04(+00:00).
Expand Down
2 changes: 1 addition & 1 deletion codeforlife/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@

# Do NOT set manually!
# This is auto-updated by python-semantic-release in the pipeline.
__version__ = "0.16.1"
__version__ = "0.16.2"
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ def parse_requirements(packages: t.Dict[str, t.Dict[str, t.Any]]):
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/ocadotechnology/codeforlife-package-python",
# TODO: exclude test files
packages=find_packages(exclude=["tests", "tests.*"]),
include_package_data=True,
data_files=[get_data_files(DATA_DIR), get_data_files(USER_FIXTURES_DIR)],
Expand Down

0 comments on commit 359f6dd

Please sign in to comment.