Skip to content

Commit

Permalink
🐛 Fix: classroom assignment schema fields (#146)
Browse files Browse the repository at this point in the history
  • Loading branch information
yanyongyu authored Oct 5, 2024
1 parent 270b57c commit 70aadfa
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 40 deletions.
4 changes: 2 additions & 2 deletions codegen/parser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ def add_schema(ref: httpx.URL, schema: "SchemaData"):
_schemas.get()[ref] = schema


from .utils import merge_dict
from .models import parse_models
from .utils import merge_inplace
from .webhooks import parse_webhook
from .endpoints import parse_endpoint
from .utils import sanitize as sanitize
Expand All @@ -53,7 +53,7 @@ def parse_openapi_spec(source: "Source", override: "Override") -> OpenAPIData:
# apply schema overrides first to make sure json pointer is correct
for path, new_schema in override.schema_overrides.items():
ref = str(httpx.URL(fragment=path))
merge_dict(source.resolve_ref(ref).data, new_schema)
merge_inplace(source.resolve_ref(ref).data, new_schema)

_ot = _override_config.set(override)
_st = _schemas.set({})
Expand Down
38 changes: 32 additions & 6 deletions codegen/parser/utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import re
import builtins
from keyword import iskeyword
from typing import TYPE_CHECKING, TypeVar
from typing import TYPE_CHECKING, Any, TypeVar

import openapi_pydantic as oas
from pydantic import TypeAdapter
Expand All @@ -24,6 +24,8 @@
}

UNSET_KEY = "<unset>"
ADD_KEY = "<add>"
REMOVE_KEY = "<remove>"


def sanitize(value: str) -> str:
Expand Down Expand Up @@ -103,16 +105,40 @@ def build_prop_name(name: str) -> str:
def merge_dict(old: dict, new: dict):
# make change inplace to make json point correct
for key, value in new.items():
# remove a field
if value == UNSET_KEY:
if key not in old:
raise ValueError(f"Key {key} not found in {old}")
del old[key]
else:
old[key] = (
merge_dict(old[key], value)
if isinstance(value, dict) and isinstance(old[key], dict)
else value
)
if key not in old:
old[key] = value
else:
try:
merge_inplace(old[key], value)
except TypeError:
old[key] = value


def merge_list(old: list, new: list | dict):
if isinstance(new, list):
old.clear()
old.extend(new)
else:
if REMOVE_KEY in new:
for item in new[REMOVE_KEY]:
old.remove(item)
if ADD_KEY in new:
old.extend(new[ADD_KEY])


def merge_inplace(old: Any, new: Any):
if isinstance(old, dict) and isinstance(new, dict):
merge_dict(old, new)
elif isinstance(old, list) and isinstance(new, list | dict):
merge_list(old, new)
else:
raise TypeError(f"Cannot merge type {type(old)} with {type(new)}")


def schema_from_source(source: "Source") -> oas.Schema:
Expand Down
4 changes: 3 additions & 1 deletion docs/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ Please make sure you have activated the virtual environment.

If you encounter an schema error, you can patch the schema by modifying the `pyproject.toml` file.

In the `[tool.codegen.overrides.schema_overrides]` section, you can modify the schema using json pointer. The value will override the original schema. Specially, if the value is `<unset>`, the original one will be removed.
In the `[tool.codegen.overrides.schema_overrides]` section, you can modify the schema using json pointer. The value will override the original schema.

Specially, if the json pointer points to a dictionary, you can use special value `<unset>` to remove the key from the dictionary. If the json pointer points to a array, you can use a list value to replace the original array. Or you can use a dict with key `<add>` and `<remove>` to add or remove items from the array.

Please add a comment to explain the reason for the patch if you want to submit a PR.

Expand Down
11 changes: 7 additions & 4 deletions githubkit/versions/ghec_v2022_11_28/models/group_0025.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,20 @@ class SimpleClassroomAssignment(GitHubModel):
max_members: Missing[Union[int, None]] = Field(
default=UNSET, description="The maximum allowable members per team."
)
editor: str = Field(description="The selected editor for the assignment.")
editor: Union[str, None] = Field(
description="The selected editor for the assignment."
)
accepted: int = Field(
description="The number of students that have accepted the assignment."
)
submitted: int = Field(
description="The number of students that have submitted the assignment."
submitted: Missing[int] = Field(
default=UNSET,
description="The number of students that have submitted the assignment.",
)
passing: int = Field(
description="The number of students that have passed the assignment."
)
language: str = Field(
language: Union[str, None] = Field(
description="The programming language used in the assignment."
)
deadline: Union[datetime, None] = Field(
Expand Down
6 changes: 3 additions & 3 deletions githubkit/versions/ghec_v2022_11_28/types/group_0025.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ class SimpleClassroomAssignmentType(TypedDict):
feedback_pull_requests_enabled: bool
max_teams: NotRequired[Union[int, None]]
max_members: NotRequired[Union[int, None]]
editor: str
editor: Union[str, None]
accepted: int
submitted: int
submitted: NotRequired[int]
passing: int
language: str
language: Union[str, None]
deadline: Union[datetime, None]
classroom: SimpleClassroomType

Expand Down
11 changes: 7 additions & 4 deletions githubkit/versions/v2022_11_28/models/group_0025.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,20 @@ class SimpleClassroomAssignment(GitHubModel):
max_members: Missing[Union[int, None]] = Field(
default=UNSET, description="The maximum allowable members per team."
)
editor: str = Field(description="The selected editor for the assignment.")
editor: Union[str, None] = Field(
description="The selected editor for the assignment."
)
accepted: int = Field(
description="The number of students that have accepted the assignment."
)
submitted: int = Field(
description="The number of students that have submitted the assignment."
submitted: Missing[int] = Field(
default=UNSET,
description="The number of students that have submitted the assignment.",
)
passing: int = Field(
description="The number of students that have passed the assignment."
)
language: str = Field(
language: Union[str, None] = Field(
description="The programming language used in the assignment."
)
deadline: Union[datetime, None] = Field(
Expand Down
6 changes: 3 additions & 3 deletions githubkit/versions/v2022_11_28/types/group_0025.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ class SimpleClassroomAssignmentType(TypedDict):
feedback_pull_requests_enabled: bool
max_teams: NotRequired[Union[int, None]]
max_members: NotRequired[Union[int, None]]
editor: str
editor: Union[str, None]
accepted: int
submitted: int
submitted: NotRequired[int]
passing: int
language: str
language: Union[str, None]
deadline: Union[datetime, None]
classroom: SimpleClassroomType

Expand Down
34 changes: 17 additions & 17 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -361,25 +361,29 @@ source = "https://raw.githubusercontent.com/github/rest-api-description/main/des
# https://docs.github.com/search-github/getting-started-with-searching-on-github/understanding-the-search-syntax#query-for-dates
"/components/parameters/created/schema" = { format = "<unset>" }

# https://github.com/yanyongyu/githubkit/issues/144
"/components/schemas/simple-classroom-assignment/properties/editor" = { type = [
"string",
"null",
] }
"/components/schemas/simple-classroom-assignment/properties/language" = { type = [
"string",
"null",
] }
"/components/schemas/simple-classroom-assignment/required" = { "<remove>" = [
"submitted",
] }

# Webhook schema overrides
# webhook check run action is required
"/components/schemas/webhook-check-run-completed" = { required = [
"/components/schemas/webhook-check-run-completed/required" = { "<add>" = [
"action",
"check_run",
"repository",
"sender",
] }
"/components/schemas/webhook-check-run-created" = { required = [
"/components/schemas/webhook-check-run-created/required" = { "<add>" = [
"action",
"check_run",
"repository",
"sender",
] }
"/components/schemas/webhook-check-run-rerequested" = { required = [
"/components/schemas/webhook-check-run-rerequested/required" = { "<add>" = [
"action",
"check_run",
"repository",
"sender",
] }

# webhook github app events enum schema is not always up to date
Expand Down Expand Up @@ -414,12 +418,8 @@ source = "https://raw.githubusercontent.com/github/rest-api-description/main/des
"action",
] }
# webhook secret scanning alert location action is required
"/components/schemas/webhook-secret-scanning-alert-location-created" = { required = [
"/components/schemas/webhook-secret-scanning-alert-location-created/required" = { "<add>" = [
"action",
"location",
"alert",
"repository",
"sender",
] }

# webhook fork topics can be null
Expand Down

0 comments on commit 70aadfa

Please sign in to comment.