Skip to content

Commit

Permalink
Migrate remaining schemas to pydantic 2 (#333)
Browse files Browse the repository at this point in the history
* Migrate collection config and links to pydantic 2.

* Migrate docs schemas to pydantic 2.

* Remove _pydantic_compat module.

* Add changelog fragment.

* Rewrite location type name removal.

* Add missing __future__ import.

* Use t.Literal instead of pattern if possible.

* Avoid conflict between remove_example and normalize_sample validators by combining them.

* Make default object creation more efficient.

Co-authored-by: Maxwell G <[email protected]>

* Use strings.ascii_uppercase.

* Remove wrong comments.

* Lint.

* Use default constructor instead of `model_validate({})`.

Co-authored-by: Maxwell G <[email protected]>

* Bump antsibull-core requirement to 3.2.0.

---------

Co-authored-by: Maxwell G <[email protected]>
  • Loading branch information
felixfontein and gotmax23 authored Sep 23, 2024
1 parent 4a45097 commit f866406
Show file tree
Hide file tree
Showing 68 changed files with 2,492 additions and 2,418 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/antsibull-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
- '3.12'
antsibull_core_ref:
- main
- '3.1.0'
- '3.2.0'
antsibull_docs_parser_ref:
- main
antsibull_changelog_ref:
Expand Down
2 changes: 1 addition & 1 deletion changelogs/fragments/330-antsibull-core-pydantic.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
minor_changes:
- "This project now depends on antsibull-core >= 3.1.0 and pydantic 2 (https://github.com/ansible-community/antsibull-docs/pull/330)."
- "This project now depends on antsibull-core >= 3.2.0 and pydantic 2 (https://github.com/ansible-community/antsibull-docs/pull/330)."
- "When rendering the Ansible docsite with the ``stable`` and ``devel`` subcommands, information on deprecated collections is shown
(https://github.com/ansible-community/ansible-build-data/pull/450, https://github.com/ansible-community/antsibull-docs/pull/330)."
6 changes: 6 additions & 0 deletions changelogs/fragments/332-pydantic-2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
minor_changes:
- "Migrated all models to Pydantic 2. This is mostly transparent, except that validation error messages slightly change, and that
some validation is more strict. For example, if a boolean is used instead of a string, say in a description, this now results
in an error instead of a silent coercion. Numbers are still accepted for strings (for example ``version_added`` with float values
like ``2.14``)
(https://github.com/ansible-community/antsibull-docs/pull/331, https://github.com/ansible-community/antsibull-core/pull/333)."
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ requires-python = ">=3.9"
dependencies = [
"ansible-pygments",
"antsibull-changelog >= 0.24.0",
"antsibull-core >= 3.1.0, < 4.0.0",
"antsibull-core >= 3.2.0, < 4.0.0",
"antsibull-docs-parser >= 1.1.0, < 2.0.0",
"antsibull-fileutils >= 1.0.0, < 2.0.0",
"asyncio-pool",
Expand Down
43 changes: 0 additions & 43 deletions src/antsibull_docs/_pydantic_compat.py

This file was deleted.

30 changes: 11 additions & 19 deletions src/antsibull_docs/collection_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
from collections.abc import Mapping

import asyncio_pool # type: ignore[import]
import pydantic as p
from antsibull_core import app_context
from antsibull_core.logging import log
from antsibull_core.pydantic import forbid_extras, get_formatted_error_messages
from antsibull_fileutils.yaml import load_yaml_file

from antsibull_docs._pydantic_compat import v1

from .schemas.collection_config import CollectionConfig

mlog = log.fields(mod=__name__)
Expand All @@ -27,7 +27,7 @@


def get_ansible_core_config() -> CollectionConfig:
return CollectionConfig.parse_obj(_ANSIBLE_CORE_CONFIG)
return CollectionConfig.model_validate(_ANSIBLE_CORE_CONFIG)


async def load_collection_config(
Expand All @@ -50,10 +50,10 @@ async def load_collection_config(
config_path = os.path.join(collection_path, "docs", "docsite", "config.yml")
if os.path.isfile(config_path):
try:
return CollectionConfig.parse_obj(load_yaml_file(config_path))
except v1.ValidationError:
return CollectionConfig.model_validate(load_yaml_file(config_path))
except p.ValidationError:
pass
return CollectionConfig.parse_obj({})
return CollectionConfig()
finally:
flog.debug("Leave")

Expand Down Expand Up @@ -99,8 +99,7 @@ def lint_collection_config(collection_path: str) -> list[tuple[str, int, int, st

result: list[tuple[str, int, int, str]] = []

for cls in (CollectionConfig,):
cls.__config__.extra = v1.Extra.forbid # type: ignore[attr-defined]
forbid_extras(CollectionConfig)

try:
config_path = os.path.join(collection_path, "docs", "docsite", "config.yml")
Expand All @@ -109,17 +108,10 @@ def lint_collection_config(collection_path: str) -> list[tuple[str, int, int, st

config_data = load_yaml_file(config_path)
try:
CollectionConfig.parse_obj(config_data)
except v1.ValidationError as exc:
for error in exc.errors():
result.append(
(
config_path,
0,
0,
v1.error_wrappers.display_errors([error]).replace("\n ", ":"),
)
)
CollectionConfig.model_validate(config_data)
except p.ValidationError as exc:
for message in get_formatted_error_messages(exc):
result.append((config_path, 0, 0, message))

return result
finally:
Expand Down
50 changes: 22 additions & 28 deletions src/antsibull_docs/collection_links.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
from collections.abc import Mapping

import asyncio_pool # type: ignore[import]
import pydantic as p
from antsibull_core import app_context
from antsibull_core.logging import log
from antsibull_core.pydantic import forbid_extras, get_formatted_error_messages
from antsibull_fileutils.yaml import load_yaml_file

from antsibull_docs._pydantic_compat import v1

from .schemas.collection_links import (
CollectionEditOnGitHub,
CollectionLinks,
Expand Down Expand Up @@ -99,7 +99,7 @@ def extract(
if data.get(other_key) == url:
return
if isinstance(url, str):
result.append(Link.parse_obj({"description": desc, "url": url}))
result.append(Link.model_validate({"description": desc, "url": url}))

# extract('documentation', 'Documentation')
extract("issues", "Issue Tracker")
Expand Down Expand Up @@ -130,9 +130,9 @@ def load(
else:
ld = {}
try:
result = CollectionLinks.parse_obj(ld)
except v1.ValidationError:
result = CollectionLinks.parse_obj({})
result = CollectionLinks.model_validate(ld)
except p.ValidationError:
result = CollectionLinks()

# Parse MANIFEST or galaxy data
issue_tracker = None
Expand Down Expand Up @@ -170,7 +170,7 @@ async def load_collection_links(
flog.debug("Enter")

if collection_name == "ansible.builtin":
return CollectionLinks.parse_obj(_ANSIBLE_CORE_METADATA)
return CollectionLinks.model_validate(_ANSIBLE_CORE_METADATA)

try:
# Load links data
Expand Down Expand Up @@ -274,16 +274,17 @@ def lint_collection_links(collection_path: str) -> list[tuple[str, int, int, str

result: list[tuple[str, int, int, str]] = []

for cls in (
CollectionEditOnGitHub,
Link,
IRCChannel,
MatrixRoom,
MailingList,
Communication,
CollectionLinks,
):
cls.__config__.extra = v1.Extra.forbid # type: ignore[attr-defined]
forbid_extras(
[
CollectionEditOnGitHub,
Link,
IRCChannel,
MatrixRoom,
MailingList,
Communication,
CollectionLinks,
]
)

try:
index_path = os.path.join(collection_path, "docs", "docsite", "links.yml")
Expand All @@ -297,18 +298,11 @@ def lint_collection_links(collection_path: str) -> list[tuple[str, int, int, str
(index_path, 0, 0, f"The key '{forbidden_key}' must not be used")
)
try:
parsed_data = CollectionLinks.parse_obj(links_data)
parsed_data = CollectionLinks.model_validate(links_data)
_check_default_values(parsed_data, index_path, result)
except v1.ValidationError as exc:
for error in exc.errors():
result.append(
(
index_path,
0,
0,
v1.error_wrappers.display_errors([error]).replace("\n ", ":"),
)
)
except p.ValidationError as exc:
for message in get_formatted_error_messages(exc):
result.append((index_path, 0, 0, message))

return result
finally:
Expand Down
2 changes: 1 addition & 1 deletion src/antsibull_docs/docs_parsing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,4 @@ def __repr__(self):

@classmethod
def empty(cls, path="."):
return cls(path=path, docs_config=CollectionConfig.parse_obj({}), version=None)
return cls(path=path, docs_config=CollectionConfig(), version=None)
Loading

0 comments on commit f866406

Please sign in to comment.