diff --git a/src/lumina/database/models.py b/src/lumina/database/models.py index 28c68ae..bebb861 100644 --- a/src/lumina/database/models.py +++ b/src/lumina/database/models.py @@ -22,22 +22,22 @@ class BaseDynamoModel(BaseModel): class MemberConsent(BaseModel, DynamoExportMixin): - consent_news: datetime.datetime | None - consent_network: datetime.datetime | None - consent_members: datetime.datetime | None - consent_students: datetime.datetime | None + consent_news: datetime.datetime | None = None + consent_network: datetime.datetime | None = None + consent_members: datetime.datetime | None = None + consent_students: datetime.datetime | None = None class MemberModel(BaseDynamoModel, DynamoExportMixin): - sk = table.SK_PROFILE + sk: str = table.SK_PROFILE name: str email: EmailStr - phone: str | None - year_of_graduation: int | None - created_at: datetime.datetime | None - email_verified_at: datetime.datetime | None - consent: MemberConsent | None - anonymous_ids: list[UUID] | None + phone: str | None = None + year_of_graduation: int | None = None + created_at: datetime.datetime | None = None + email_verified_at: datetime.datetime | None = None + consent: MemberConsent | None = None + anonymous_ids: list[UUID] | None = None @property def id(self) -> str: @@ -61,8 +61,8 @@ class SubmitterModel(BaseModel, DynamoExportMixin): id: str verified: bool name: str - year_of_graduation: int | None - email: EmailStr | None + year_of_graduation: int | None = None + email: EmailStr | None = None class GitHubIssueState(Enum): @@ -77,7 +77,7 @@ class GitHubIssueModel(BaseModel, DynamoExportMixin): title: str created_at: datetime.datetime updated_at: datetime.datetime - closed_at: datetime.datetime | None + closed_at: datetime.datetime | None = None comments: int @@ -87,8 +87,8 @@ class SubmissionModel(BaseDynamoModel, DynamoExportMixin): target_type: str target_name: str created_at: datetime.datetime - subject: str | None - message: str | None + subject: str | None = None + message: str | None = None submitter: SubmitterModel github_issue: GitHubIssueModel diff --git a/src/lumina/database/table.py b/src/lumina/database/table.py index 28468f0..c60892f 100644 --- a/src/lumina/database/table.py +++ b/src/lumina/database/table.py @@ -75,4 +75,5 @@ def create_tables(): "Projection": {"ProjectionType": "ALL"}, }, ], + BillingMode="PAY_PER_REQUEST", ) diff --git a/src/lumina/schema/auth.py b/src/lumina/schema/auth.py index 61fd38c..ebb2953 100644 --- a/src/lumina/schema/auth.py +++ b/src/lumina/schema/auth.py @@ -9,5 +9,5 @@ class AuthCheckRequiredResponse(LuminaModel): class AuthCheckOptionalResponse(LuminaModel): - id: str | None - expires_at: datetime.datetime | None + id: str | None = None + expires_at: datetime.datetime | None = None diff --git a/src/lumina/schema/base.py b/src/lumina/schema/base.py index a0dfd2b..f75da77 100644 --- a/src/lumina/schema/base.py +++ b/src/lumina/schema/base.py @@ -1,5 +1,5 @@ import humps -from pydantic import BaseModel +from pydantic import BaseModel, ConfigDict def to_camel(string): @@ -7,6 +7,4 @@ def to_camel(string): class LuminaModel(BaseModel): - class Config: - alias_generator = to_camel - allow_population_by_field_name = True + model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True) diff --git a/src/lumina/schema/github.py b/src/lumina/schema/github.py index b11f1fb..a0e5ffe 100644 --- a/src/lumina/schema/github.py +++ b/src/lumina/schema/github.py @@ -7,11 +7,11 @@ class GitHubIssue(BaseModel): number: int state: GitHubIssueState - state_reason: str | None + state_reason: str | None = None title: str created_at: datetime.datetime updated_at: datetime.datetime - closed_at: datetime.datetime | None + closed_at: datetime.datetime | None = None comments: int @@ -26,5 +26,5 @@ class GitHubRepository(BaseModel): class GitHubWebhook(BaseModel): action: str - issue: GitHubIssue | None + issue: GitHubIssue | None = None repository: GitHubRepository diff --git a/src/lumina/schema/health.py b/src/lumina/schema/health.py index 5ec6060..a143de6 100644 --- a/src/lumina/schema/health.py +++ b/src/lumina/schema/health.py @@ -7,7 +7,7 @@ class HealthCheckCondition(LuminaModel): ok: bool = Field(description="Whether the condition is ok") timestamp: datetime.datetime = Field(description="When the last check ran") - message: str | None = Field(description="Details of fault if any") + message: str | None = Field(description="Details of fault if any", default=None) class HealthCheckResponse(LuminaModel): diff --git a/src/lumina/schema/submissions.py b/src/lumina/schema/submissions.py index 342131b..4752da6 100644 --- a/src/lumina/schema/submissions.py +++ b/src/lumina/schema/submissions.py @@ -24,8 +24,8 @@ class SubmitterRequest(LuminaModel): id: UUID = FIELD_SUBMITTER_ID name: str = FIELD_SUBMITTER_NAME - year_of_graduation: int | None = Field(example=1999) - email: EmailStr | None = Field(example="fred@bloggs.com") + year_of_graduation: int | None = Field(example=1999, default=None) + email: EmailStr | None = Field(example="fred@bloggs.com", default=None) def to_model(self) -> SubmitterModel: return SubmitterModel( @@ -49,6 +49,7 @@ class BaseSubmissionRequest(LuminaModel): submitter: SubmitterRequest | None = Field( description="The submitter of the submission if, and only if, the submission " "is anonymous. If the user is logged in this field should be omitted.", + default=None, ) @@ -59,6 +60,7 @@ class BaseSubmissionRequest(LuminaModel): title="Target ID", description="The ID of the target", example="00_01/romeo_and_juliet", + default=None, ) FIELD_TARGET_NAME = Field( title="Target Name", @@ -71,7 +73,7 @@ class BaseSubmissionRequest(LuminaModel): example="https://history.newtheatre.org.uk/00_01/romeo_and_juliet", ) FIELD_SUBJECT = Field( - description="The subject of the submission", example="The lighting" + description="The subject of the submission", example="The lighting", default=None ) FIELD_MESSAGE = Field( title="Message", @@ -135,7 +137,7 @@ class GitHubIssueResponse(LuminaModel): title: str created_at: datetime.datetime updated_at: datetime.datetime - closed_at: datetime.datetime | None + closed_at: datetime.datetime | None = None comments: int diff --git a/tests/unit/lumina/database/test_operations.py b/tests/unit/lumina/database/test_operations.py index 758bb1f..fd7585f 100644 --- a/tests/unit/lumina/database/test_operations.py +++ b/tests/unit/lumina/database/test_operations.py @@ -17,7 +17,7 @@ @pytest.fixture(scope="function", autouse=True) def create_tables(): - with moto.mock_dynamodb2(): + with moto.mock_dynamodb(): table.create_tables() yield diff --git a/tests/unit/lumina/database/test_table.py b/tests/unit/lumina/database/test_table.py index 2eb0b3d..b96295c 100644 --- a/tests/unit/lumina/database/test_table.py +++ b/tests/unit/lumina/database/test_table.py @@ -2,7 +2,7 @@ from lumina.database import connection, table -@moto.mock_dynamodb2 +@moto.mock_dynamodb def test_create_tables(): table.create_tables() tables = list(connection.get_dynamo_db().tables.all()) diff --git a/tests/unit/lumina/endpoints/test_member.py b/tests/unit/lumina/endpoints/test_member.py index 012638f..2832a8d 100644 --- a/tests/unit/lumina/endpoints/test_member.py +++ b/tests/unit/lumina/endpoints/test_member.py @@ -160,9 +160,12 @@ def test_invalid_email(self): assert response.json() == { "detail": [ { + "ctx": {"reason": "There must be something after the @-sign."}, + "input": "test@", "loc": ["body", "email"], - "msg": "value is not a valid email address", - "type": "value_error.email", + "msg": "value is not a valid email address: There must be " + "something after the @-sign.", + "type": "value_error", } ] } diff --git a/tests/unit/lumina/endpoints/test_submissions.py b/tests/unit/lumina/endpoints/test_submissions.py index 748bd9c..2443a89 100644 --- a/tests/unit/lumina/endpoints/test_submissions.py +++ b/tests/unit/lumina/endpoints/test_submissions.py @@ -99,11 +99,11 @@ def test_with_submissions(self): "githubIssue": { "closedAt": None, "comments": 1, - "createdAt": "2020-01-01T00:00:00+00:00", + "createdAt": "2020-01-01T00:00:00Z", "number": 1, "state": "open", "title": "A title", - "updatedAt": "2020-01-01T00:00:00+00:00", + "updatedAt": "2020-01-01T00:00:00Z", "url": "https://github.com/newtheatre/lumina-test/issues/2", }, } @@ -182,9 +182,18 @@ def test_require_uuid_submitter_id_if_not_authed(self): assert response.json() == { "detail": [ { + "ctx": { + "error": "invalid character: expected an optional prefix " + "of `urn:uuid:` followed by [0-9a-fA-F-], found " + "`r` at 2" + }, + "input": "fred_bloggs", "loc": ["body", "submitter", "id"], - "msg": "value is not a valid uuid", - "type": "type_error.uuid", + "msg": "Input should be a valid UUID, invalid character: expected " + "an optional prefix of `urn:uuid:` followed by " + "[0-9a-fA-F-], found `r` at 2", + "type": "uuid_parsing", + "url": "https://errors.pydantic.dev/2.1/v/uuid_parsing", } ] } @@ -267,11 +276,11 @@ def test_success_not_authed(self): "githubIssue": { "closedAt": None, "comments": 0, - "createdAt": "2020-01-01T00:00:00+00:00", + "createdAt": "2020-01-01T00:00:00Z", "number": 123, "state": "open", "title": "Test issue", - "updatedAt": "2020-01-01T00:00:00+00:00", + "updatedAt": "2020-01-01T00:00:00Z", "url": "https://github.com/newtheatre/lumina-test/issues/123", }, } @@ -317,11 +326,11 @@ def test_success_authed(self, auth_fred_bloggs): "githubIssue": { "closedAt": None, "comments": 0, - "createdAt": "2020-01-01T00:00:00+00:00", + "createdAt": "2020-01-01T00:00:00Z", "number": 123, "state": "open", "title": "Test issue", - "updatedAt": "2020-01-01T00:00:00+00:00", + "updatedAt": "2020-01-01T00:00:00Z", "url": "https://github.com/newtheatre/lumina-test/issues/123", }, }