Skip to content

Commit

Permalink
Add support for Pydantic v2
Browse files Browse the repository at this point in the history
Close #15
  • Loading branch information
fcurella committed Jun 25, 2024
1 parent ffc4503 commit 78e4f1b
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 8 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10"]
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
pydantic-version: ["<2", ">=2"]

steps:
- uses: actions/checkout@v3
Expand All @@ -39,6 +40,7 @@ jobs:
run: |
python -m pip install --upgrade pip
python -m pip install -e .
python -m pip install pydantic${{ matrix.pydantic-version }}
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Test
run: |
Expand All @@ -48,7 +50,7 @@ jobs:
env:
COVERALLS_PARALLEL: true
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COVERALLS_FLAG_NAME: run-${{ matrix.python-version }}
COVERALLS_FLAG_NAME: run-${{ matrix.python-version }}-${{ matrix.pydantic-version }}

finish:
needs: [test]
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ lint:
check-manifest

test:
python -m pytest
python -m pytest --pdb

release:
check-manifest
Expand Down
33 changes: 29 additions & 4 deletions datauri/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import textwrap
from base64 import b64decode as decode64
from base64 import b64encode as encode64
from typing import Any, Dict, Optional, Tuple, TypeVar, Union
from typing import Any, Dict, MutableMapping, Optional, Tuple, TypeVar, Union

if sys.version_info >= (3, 11):
from typing import Self
Expand Down Expand Up @@ -160,15 +160,40 @@ def __get_validators__(cls):
yield cls.validate

@classmethod
def validate(cls, v: str) -> Self:
if not isinstance(v, str):
def __get_pydantic_core_schema__(cls, source_type: Any, handler: Any) -> Any:
from pydantic_core import core_schema

return core_schema.no_info_after_validator_function(cls, handler(str))

@classmethod
def validate(
cls,
value: str,
values: Optional[MutableMapping[str, Any]] = None,
config: Any = None,
field: Any = None,
**kwargs: Any,
) -> Self:
if not isinstance(value, str):
raise TypeError("string required")

m = cls(v)
m = cls(value)
if not m.is_valid:
raise ValueError("invalid data-uri format")
return m

@classmethod
def __get_pydantic_json_schema__(
cls, core_schema: MutableMapping[str, Any], handler: Any
) -> Any:
core_schema.update(
pattern=DATA_URI_REGEX,
examples=[
"data:text/plain;charset=utf-8;base64,VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cu"
],
)
return core_schema

@classmethod
def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None:
# __modify_schema__ should mutate the dict it receives in place,
Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
pytest
coveralls
pydantic<2.0
flake8
isort
check-manifest
Expand Down
19 changes: 19 additions & 0 deletions tests/test_pydantic.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
pydantic = pytest.importorskip("pydantic")


@pytest.mark.skipif(pydantic.__version__.rsplit(".", 3)[0] > "1", reason="pydantic v2")
def test_pydantic():
class Model(pydantic.BaseModel):
content: DataURI
Expand All @@ -18,3 +19,21 @@ class Model(pydantic.BaseModel):
'aGUgbGF6eSBkb2cu"}'
)
assert instance.dict() == {"content": DataURI(t)}


@pytest.mark.skipif(
pydantic.__version__.rsplit(".", 3)[0] < "2", reason="pydantic v2 required"
)
def test_pydantic_v2():
class Model(pydantic.BaseModel):
content: DataURI

t = "data:text/plain;charset=utf-8;base64,VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cu"
instance = Model(content=t)
assert isinstance(instance.content, DataURI)
assert (
instance.model_dump_json()
== '{"content":"data:text/plain;charset=utf-8;base64,VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0'
'aGUgbGF6eSBkb2cu"}'
)
assert instance.model_dump() == {"content": DataURI(t)}

0 comments on commit 78e4f1b

Please sign in to comment.