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

Config: inherit all pydantic models from a common base class #11857

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
37 changes: 24 additions & 13 deletions readthedocs/config/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,28 @@
but we aren't using it yet, and instead we are doing the validation
in a separate step.
"""

from typing import Literal

from pydantic import BaseModel
from pydantic import BaseModel, ConfigDict


class Parent(BaseModel):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't name it Parent but something with a more explicit meaning. Maybe something like BaseConfigKey.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be BaseModel too, and import pydantic's BaseModel with a different name

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to re-use a name that already exists if we can use a new one more explicit 😉

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, BaseModel it's what we want, so what about ParentModel?

"""Base class for all the models."""

model_config = ConfigDict(
# Don't allow extra fields in the models.
# It will raise an error if there are extra fields.
extra="forbid",
)


class BuildTool(BaseModel):
class BuildTool(Parent):
version: str
full_version: str


class BuildJobsBuildTypes(BaseModel):
class BuildJobsBuildTypes(Parent):
"""Object used for `build.jobs.build` key."""

html: list[str] | None = None
Expand All @@ -27,7 +38,7 @@ class BuildJobsBuildTypes(BaseModel):
htmlzip: list[str] | None = None


class BuildJobs(BaseModel):
class BuildJobs(Parent):
"""Object used for `build.jobs` key."""

pre_checkout: list[str] = []
Expand All @@ -46,52 +57,52 @@ class BuildJobs(BaseModel):


# TODO: rename this class to `Build`
class BuildWithOs(BaseModel):
class BuildWithOs(Parent):
os: str
tools: dict[str, BuildTool]
jobs: BuildJobs = BuildJobs()
apt_packages: list[str] = []
commands: list[str] = []


class PythonInstallRequirements(BaseModel):
class PythonInstallRequirements(Parent):
requirements: str


class PythonInstall(BaseModel):
class PythonInstall(Parent):
path: str
method: Literal["pip", "setuptools"] = "pip"
extra_requirements: list[str] = []


class Python(BaseModel):
class Python(Parent):
install: list[PythonInstall | PythonInstallRequirements] = []


class Conda(BaseModel):
class Conda(Parent):
environment: str


class Sphinx(BaseModel):
class Sphinx(Parent):
configuration: str | None
# NOTE: This is how we save the object in the DB,
# the actual options for users are "html", "htmldir", "singlehtml".
builder: Literal["sphinx", "sphinx_htmldir", "sphinx_singlehtml"] = "sphinx"
fail_on_warning: bool = False


class Mkdocs(BaseModel):
class Mkdocs(Parent):
configuration: str | None
fail_on_warning: bool = False


class Submodules(BaseModel):
class Submodules(Parent):
include: list[str] | Literal["all"] = []
exclude: list[str] | Literal["all"] = []
recursive: bool = False


class Search(BaseModel):
class Search(Parent):
ranking: dict[str, int] = {}
ignore: list[str] = [
"search.html",
Expand Down