Skip to content

Commit

Permalink
Merge pull request #26 from akx/pydantic-2
Browse files Browse the repository at this point in the history
Upgrade to Pydantic 2.x
  • Loading branch information
rambo authored Feb 3, 2025
2 parents 8e38e4c + 8deb0b3 commit 0706aaa
Show file tree
Hide file tree
Showing 9 changed files with 224 additions and 100 deletions.
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 1.9.1
current_version = 2.0.0
commit = False
tag = False

Expand Down
231 changes: 180 additions & 51 deletions poetry.lock

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "libpvarki"
version = "1.9.1"
version = "2.0.0"
description = "Common helpers like standard logging init"
authors = ["Eero af Heurlin <eero.afheurlin@iki.fi>"]
homepage = "https://github.com/pvarki/python-libpvarki/"
Expand Down Expand Up @@ -59,8 +59,7 @@ branch = true
python = "^3.8"
ecs-logging = "^2.0"
fastapi = ">0.89,<1.0" # caret behaviour on 0.x is to lock to 0.x.*
# FIXME: Migrate to v2, see https://docs.pydantic.dev/2.3/migration/#basesettings-has-moved-to-pydantic-settings
pydantic= ">=1.10,<2.0"
pydantic= ">=2.0,<3.0"
cryptography = ">=41.0"
libadvian = "^1.4"
aiohttp = ">=3.10.2,<4.0"
Expand Down
2 changes: 1 addition & 1 deletion src/libpvarki/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
""" Common helpers like standard logging init """
__version__ = "1.9.1" # NOTE Use `bump2version --config-file patch` to bump versions correctly
__version__ = "2.0.0" # NOTE Use `bump2version --config-file patch` to bump versions correctly
16 changes: 7 additions & 9 deletions src/libpvarki/schemas/generic.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
"""Generic schemas"""
from typing import Optional

from pydantic import Field, Extra
from pydantic.main import BaseModel # pylint: disable=E0611 # false positive
from pydantic import Field, BaseModel, ConfigDict


class OperationResultResponse(BaseModel): # pylint: disable=too-few-public-methods
Expand All @@ -16,14 +15,13 @@ class OperationResultResponse(BaseModel): # pylint: disable=too-few-public-meth
json_schema_extra={"nullable": True},
)

class Config: # pylint: disable=too-few-public-methods
"""Example values for schema"""

extra = Extra.forbid
schema_extra = {
model_config = ConfigDict(
extra="forbid",
json_schema_extra={
"examples": [
{"success": True},
{"success": False, "error": "Things went wrong"},
{"success": True, "extra": "Tell the user they're awesome"},
]
}
],
},
)
55 changes: 25 additions & 30 deletions src/libpvarki/schemas/product.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
"""Pydantic schemas for product integration APIs"""
from typing import Optional

from pydantic import Field, Extra
from pydantic.main import BaseModel # pylint: disable=E0611 # false positive
from pydantic import Field, BaseModel, ConfigDict

# pylint: disable=too-few-public-methods
from .generic import OperationResultResponse # pylint: disable=W0611 # For backwards compatibility
Expand All @@ -15,19 +14,18 @@ class UserCRUDRequest(BaseModel):
callsign: str = Field(description="Callsign of the user")
x509cert: str = Field(description="Certificate encoded with CFSSL conventions (newlines escaped)")

class Config: # pylint: disable=too-few-public-methods
"""Example values for schema"""

extra = Extra.forbid
schema_extra = {
model_config = ConfigDict(
extra="forbid",
json_schema_extra={
"examples": [
{
"uuid": "3ede23ae-eff2-4aa8-b7ef-7fac68c39988",
"callsign": "ROTTA01a",
"x509cert": "-----BEGIN CERTIFICATE-----\\nMIIEwjCC...\\n-----END CERTIFICATE-----\\n",
},
]
}
],
},
)


# FIXME: The spec for these will be changed
Expand All @@ -41,19 +39,18 @@ class UserInstructionFragment(BaseModel):
json_schema_extra={"nullable": True},
)

class Config: # pylint: disable=too-few-public-methods
"""Example values for schema"""

extra = Extra.forbid
schema_extra = {
model_config = ConfigDict(
extra="forbid",
json_schema_extra={
"examples": [
{"html": "<p>Hello World!</p>"},
{
"html": """<p class="hello">Hello World!</p>""",
"inject_css": "http://example.com/mystyle.css",
},
]
}
],
},
)


class ReadyRequest(BaseModel): # pylint: disable=too-few-public-methods
Expand All @@ -63,19 +60,18 @@ class ReadyRequest(BaseModel): # pylint: disable=too-few-public-methods
apiurl: str = Field(description="Product API URL")
url: str = Field(description="Product UI URL")

class Config: # pylint: disable=too-few-public-methods
"""Example values for schema"""

extra = Extra.forbid
schema_extra = {
model_config = ConfigDict(
extra="forbid",
json_schema_extra={
"examples": [
{
"product": "tak",
"apiurl": "https://tak.sleepy-sloth.pvarki.fi:4625/",
"url": "https://tak.sleepy-sloth.pvarki.fi:8443/",
},
]
}
],
},
)


class ProductHealthCheckResponse(BaseModel):
Expand All @@ -86,13 +82,12 @@ class ProductHealthCheckResponse(BaseModel):
healthy: bool = Field(description="Everything is good, ready to serve")
extra: Optional[str] = Field(description="Extra information", default=None, json_schema_extra={"nullable": True})

class Config: # pylint: disable=too-few-public-methods
"""Example values for schema"""

extra = Extra.forbid
schema_extra = {
model_config = ConfigDict(
extra="forbid",
json_schema_extra={
"examples": [
{"healthy": True},
{"healthy": False, "extra": "Things went wrong"},
]
}
],
},
)
5 changes: 4 additions & 1 deletion tests/schemas/test_generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@
def test_result() -> None:
"""Test constructing OperationResultResponse"""
res = OperationResultResponse(success=True)
assert res.dict()["success"]
assert res.model_dump()["success"]


def test_result_extra() -> None:
"""Test that extra field forbid works"""
with pytest.raises(ValidationError):
OperationResultResponse(success=True, nosuchfield="Trololooo") # type: ignore[call-arg]

with pytest.raises(ValidationError):
OperationResultResponse.model_validate({"success": True, "nosuchfield": "Trololooo"})
6 changes: 3 additions & 3 deletions tests/schemas/test_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
def test_fragment() -> None:
"""Test constructing UserInstructionFragment"""
res = UserInstructionFragment(html="<p>Hello world!</p>")
assert res.dict()["html"]
assert res.model_dump()["html"]


def test_crud() -> None:
"""Test constructing UserCRUDRequest"""
res = UserCRUDRequest(callsign="KISSA23a", uuid="not really an uuid", x509cert="not really a cert")
assert res.dict()["callsign"] == "KISSA23a"
assert res.model_dump()["callsign"] == "KISSA23a"


def test_health() -> None:
"""Test constructing ProductHealthCheckResponse"""
res = ProductHealthCheckResponse(healthy=True)
assert res.dict()["healthy"] is True
assert res.model_dump()["healthy"] is True
2 changes: 1 addition & 1 deletion tests/test_libpvarki.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

def test_version() -> None:
"""Make sure version matches expected"""
assert __version__ == "1.9.1"
assert __version__ == "2.0.0"

0 comments on commit 0706aaa

Please sign in to comment.