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

[Issue #3730] Fix parsing issueType bug #3731

Merged
merged 3 commits into from
Jan 31, 2025
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
39 changes: 30 additions & 9 deletions analytics/src/analytics/integrations/github/validation.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,30 @@
"""Pydantic schemas for validating GitHub API responses."""

# pylint: disable=no-self-argument
# mypy: disable-error-code="literal-required"
# This mypy disable is needed so we can use constants for field aliases

from datetime import datetime, timedelta

from pydantic import BaseModel, Field, computed_field, model_validator

# Declare constants for the fields that need to be aliased from the GitHub data
# so that we only have to change these values in one place.
#
# We need to declare them at the module-level instead of class-level
# because pydantic throws an error when using class level constants.

# Issue content aliases
ISSUE_TYPE = "issueType"
CLOSED_AT = "closedAt"
CREATED_AT = "createdAt"
PARENT = "parent"
# Iteration aliases
ITERATION_ID = "iterationId"
START_DATE = "startDate"
# Single select aliases
OPTION_ID = "optionId"


def safe_default_factory(data: dict, keys_to_replace: list[str]) -> dict:
"""
Expand Down Expand Up @@ -40,19 +60,20 @@ class IssueType(BaseModel):
class IssueContent(BaseModel):
"""Schema for core issue metadata."""

# The fields that we're parsing from the raw GitHub output
title: str
url: str
closed: bool
created_at: str = Field(alias="createdAt")
closed_at: str | None = Field(alias="closedAt", default=None)
issue_type: IssueType = Field(alias="type", default_factory=IssueType)
created_at: str = Field(alias=CREATED_AT)
closed_at: str | None = Field(alias=CLOSED_AT, default=None)
issue_type: IssueType = Field(alias=ISSUE_TYPE, default_factory=IssueType)
parent: IssueParent = Field(default_factory=IssueParent)

@model_validator(mode="before")
def replace_none_with_defaults(cls, values) -> dict: # noqa: ANN001, N805
"""Replace None with default_factory instances."""
"""Replace keys that are set to None with default_factory instances."""
# Replace None with default_factory instances
return safe_default_factory(values, ["type", "parent"])
return safe_default_factory(values, [ISSUE_TYPE, PARENT])


# #############################################
Expand All @@ -63,9 +84,9 @@ def replace_none_with_defaults(cls, values) -> dict: # noqa: ANN001, N805
class IterationValue(BaseModel):
"""Schema for iteration field values like Sprint or Quad."""

iteration_id: str | None = Field(alias="iterationId", default=None)
iteration_id: str | None = Field(alias=ITERATION_ID, default=None)
title: str | None = None
start_date: str | None = Field(alias="startDate", default=None)
start_date: str | None = Field(alias=START_DATE, default=None)
duration: int | None = None

@computed_field
Expand All @@ -82,7 +103,7 @@ def end_date(self) -> str | None:
class SingleSelectValue(BaseModel):
"""Schema for single select field values like Status or Pillar."""

option_id: str | None = Field(alias="optionId", default=None)
option_id: str | None = Field(alias=OPTION_ID, default=None)
name: str | None = None


Expand Down Expand Up @@ -112,7 +133,7 @@ class ProjectItem(BaseModel):

@model_validator(mode="before")
def replace_none_with_defaults(cls, values) -> dict: # noqa: ANN001, N805
"""Replace None with default_factory instances."""
"""Replace keys that are set to None with default_factory instances."""
return safe_default_factory(
values,
["sprint", "points", "quad", "pillar", "status"],
Expand Down
2 changes: 1 addition & 1 deletion analytics/tests/integrations/github/test_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"title": "Test Parent",
"url": "https://github.com/test/repo/issues/2",
},
"type": {
"issueType": {
widal001 marked this conversation as resolved.
Show resolved Hide resolved
"name": "Bug",
},
}
Expand Down