Skip to content

Commit

Permalink
fix: Base64Bytes compatibility with all supported pydantic versions
Browse files Browse the repository at this point in the history
  • Loading branch information
azmeuk committed Dec 2, 2024
1 parent bcf08ef commit 34f3b37
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 4 deletions.
11 changes: 11 additions & 0 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
Changelog
=========

[0.2.10] - 2024-12-02
---------------------

Changed
^^^^^^^
- The ``schema`` attribute is annotated with :attr:`~scim2_models.Required.true`.

Fixed
^^^^^
- ``Base64Bytes`` compatibility between pydantic 2.10+ and <2.10

[0.2.9] - 2024-12-02
--------------------

Expand Down
2 changes: 1 addition & 1 deletion scim2_models/rfc7643/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from typing import Union
from typing import get_origin

from pydantic import Base64Bytes
from pydantic import Field
from pydantic import create_model
from pydantic import field_validator
Expand All @@ -30,6 +29,7 @@
from ..base import URIReference
from ..base import is_complex_attribute
from ..constants import RESERVED_WORDS
from ..utils import Base64Bytes
from ..utils import normalize_attribute_name
from .resource import Extension
from .resource import Resource
Expand Down
2 changes: 1 addition & 1 deletion scim2_models/rfc7643/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from typing import Optional
from typing import Union

from pydantic import Base64Bytes
from pydantic import EmailStr
from pydantic import Field

Expand All @@ -17,6 +16,7 @@
from ..base import Required
from ..base import Returned
from ..base import Uniqueness
from ..utils import Base64Bytes
from .resource import Resource


Expand Down
57 changes: 57 additions & 0 deletions scim2_models/utils.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import base64
import re
from typing import Annotated
from typing import Literal
from typing import Optional
from typing import Union

from pydantic import EncodedBytes
from pydantic import EncoderProtocol
from pydantic.alias_generators import to_snake
from pydantic_core import PydanticCustomError

try:
from types import UnionType # type: ignore
Expand All @@ -17,6 +23,57 @@ def int_to_str(status: Optional[int]) -> Optional[str]:
return None if status is None else str(status)


# Copied from Pydantic 2.10 repository
class Base64Encoder(EncoderProtocol): # pragma: no cover
"""Standard (non-URL-safe) Base64 encoder."""

@classmethod
def decode(cls, data: bytes) -> bytes:
"""Decode the data from base64 encoded bytes to original bytes data.
Args:
data: The data to decode.
Returns:
The decoded data.
"""
try:
return base64.b64decode(data)
except ValueError as e:
raise PydanticCustomError(
"base64_decode", "Base64 decoding error: '{error}'", {"error": str(e)}
) from e

@classmethod
def encode(cls, value: bytes) -> bytes:
"""Encode the data from bytes to a base64 encoded bytes.
Args:
value: The data to encode.
Returns:
The encoded data.
"""
return base64.b64encode(value)

@classmethod
def get_json_format(cls) -> Literal["base64"]:
"""Get the JSON format for the encoded data.
Returns:
The JSON format for the encoded data.
"""
return "base64"


# Compatibility with Pydantic <2.10
# https://pydantic.dev/articles/pydantic-v2-10-release#use-b64decode-and-b64encode-for-base64bytes-and-base64str-types
Base64Bytes = Annotated[bytes, EncodedBytes(encoder=Base64Encoder)]


def to_camel(string: str) -> str:
"""Transform strings to camelCase.
Expand Down
3 changes: 1 addition & 2 deletions tests/test_dynamic_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
from typing import Literal
from typing import Union

from pydantic import Base64Bytes

from scim2_models.base import CaseExact
from scim2_models.base import ComplexAttribute
from scim2_models.base import ExternalReference
Expand All @@ -18,6 +16,7 @@
from scim2_models.rfc7643.resource import Resource
from scim2_models.rfc7643.schema import Attribute
from scim2_models.rfc7643.schema import Schema
from scim2_models.utils import Base64Bytes


def test_make_group_model_from_schema(load_sample):
Expand Down

0 comments on commit 34f3b37

Please sign in to comment.