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

Add pydantic 2 compatibility layer #321

Merged
merged 9 commits into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
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
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ jobs:
run: pipx run check-manifest

test:
name: ${{ matrix.platform }} (${{ matrix.python-version }})
name: ${{ matrix.platform }} (${{ matrix.python-version }}) ${{ matrix.pydantic }}
runs-on: ${{ matrix.platform }}
strategy:
fail-fast: false
matrix:
python-version: [3.8, 3.9, "3.10", "3.11"]
platform: [ubuntu-latest, macos-latest, windows-latest]
pydantic: ["pydantic<2", "pydantic>2"]

steps:
- uses: actions/checkout@v4
Expand All @@ -42,6 +43,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install "${{ matrix.pydantic }}"
pip install -e .[json,docs,testing]

- name: Test Main docs build
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ dependencies = [
"appdirs",
"build>=1",
"psygnal>=0.3.0",
"pydantic<2",
"pydantic",
"tomli-w",
"tomli; python_version < '3.11'",
"rich",
Expand Down
2 changes: 1 addition & 1 deletion src/npe2/_dynamic_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
overload,
)

from pydantic import BaseModel, ValidationError
from npe2._pydantic_compat import BaseModel, ValidationError

from ._plugin_manager import PluginManager
from .manifest.contributions import (
Expand Down
54 changes: 54 additions & 0 deletions src/npe2/_pydantic_compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
try:
# pydantic v2
from pydantic.v1 import (
BaseModel,
Extra,
Field,
PrivateAttr,
ValidationError,
color,
conlist,
constr,
root_validator,
validator,
)
from pydantic.v1.error_wrappers import ErrorWrapper
from pydantic.v1.fields import SHAPE_LIST
from pydantic.v1.generics import GenericModel
from pydantic.v1.main import ModelMetaclass
except ImportError:
# pydantic v2
from pydantic import (
BaseModel,
Extra,
Field,
PrivateAttr,
ValidationError,
color,
conlist,
constr,
root_validator,
validator,
)
from pydantic.error_wrappers import ErrorWrapper
from pydantic.fields import SHAPE_LIST
from pydantic.generics import GenericModel
from pydantic.main import ModelMetaclass


__all__ = (
"BaseModel",
"Extra",
"Field",
"ValidationError",
"root_validator",
"validator",
"PrivateAttr",
"color",
"conlist",
"constr",
"ModelMetaclass",
"ErrorWrapper",
"GenericModel",
"SHAPE_LIST",
)
2 changes: 1 addition & 1 deletion src/npe2/implements.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from inspect import Parameter, Signature
from typing import Any, Callable, List, Sequence, Type, TypeVar

from pydantic import BaseModel
from npe2._pydantic_compat import BaseModel

from .manifest import contributions

Expand Down
2 changes: 1 addition & 1 deletion src/npe2/implements.pyi
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Any, Callable, TypeVar

from pydantic import BaseModel as BaseModel
from npe2._pydantic_compat import BaseModel as BaseModel

from .manifest import PluginManifest as PluginManifest
from .manifest import contributions as contributions
Expand Down
3 changes: 2 additions & 1 deletion src/npe2/manifest/_bases.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
from typing import Callable, Dict, Optional, Union

import yaml
from pydantic import BaseModel, PrivateAttr

from npe2._pydantic_compat import BaseModel, PrivateAttr


class ImportExportModel(BaseModel):
Expand Down
10 changes: 8 additions & 2 deletions src/npe2/manifest/_package_metadata.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
from importlib import metadata
from typing import Dict, List, Literal, Optional, Union

from pydantic import BaseModel, Extra, Field, constr, root_validator
from pydantic.fields import SHAPE_LIST
from npe2._pydantic_compat import (
SHAPE_LIST,
BaseModel,
Extra,
Field,
constr,
root_validator,
)

# https://packaging.python.org/specifications/core-metadata/

Expand Down
3 changes: 1 addition & 2 deletions src/npe2/manifest/contributions/_commands.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from typing import TYPE_CHECKING, Any, Optional, Union

from pydantic import BaseModel, Extra, Field, validator

from npe2._pydantic_compat import BaseModel, Extra, Field, validator
from npe2.manifest import _validators
from npe2.types import PythonName

Expand Down
2 changes: 1 addition & 1 deletion src/npe2/manifest/contributions/_configuration.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Any, Dict, List, Literal, Optional, Union

from pydantic import BaseModel, Field, conlist, root_validator, validator
from npe2._pydantic_compat import BaseModel, Field, conlist, root_validator, validator

from ._json_schema import (
Draft07JsonSchema,
Expand Down
2 changes: 1 addition & 1 deletion src/npe2/manifest/contributions/_contributions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Dict, List, Optional

from pydantic import BaseModel, Field, validator
from npe2._pydantic_compat import BaseModel, Field, validator

from ._commands import CommandContribution
from ._configuration import ConfigurationContribution
Expand Down
2 changes: 1 addition & 1 deletion src/npe2/manifest/contributions/_icon.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Optional

from pydantic import BaseModel
from npe2._pydantic_compat import BaseModel


class Icon(BaseModel):
Expand Down
9 changes: 8 additions & 1 deletion src/npe2/manifest/contributions/_json_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@

from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional, Type, Union

from pydantic import BaseModel, Field, PrivateAttr, conlist, root_validator, validator
from npe2._pydantic_compat import (
BaseModel,
Field,
PrivateAttr,
conlist,
root_validator,
validator,
)

if TYPE_CHECKING:
from jsonschema.exceptions import ValidationError
Expand Down
3 changes: 1 addition & 2 deletions src/npe2/manifest/contributions/_keybindings.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from typing import Optional

from pydantic.fields import Field

from npe2._pydantic_compat import Field
from npe2.manifest.utils import Executable


Expand Down
3 changes: 1 addition & 2 deletions src/npe2/manifest/contributions/_menus.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from typing import Optional, Union

from pydantic import BaseModel, Field

from npe2._pydantic_compat import BaseModel, Field
from npe2.manifest.utils import Executable


Expand Down
3 changes: 1 addition & 2 deletions src/npe2/manifest/contributions/_readers.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from functools import wraps
from typing import List, Optional

from pydantic import Extra, Field

from npe2._pydantic_compat import Extra, Field
from npe2.manifest.utils import Executable, v2_to_v1
from npe2.types import ReaderFunction

Expand Down
4 changes: 1 addition & 3 deletions src/npe2/manifest/contributions/_sample_data.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, List, Optional, Union

from pydantic.fields import Field
from pydantic.generics import GenericModel

from npe2._pydantic_compat import Field, GenericModel
from npe2.manifest.utils import Executable
from npe2.types import LayerData

Expand Down
3 changes: 1 addition & 2 deletions src/npe2/manifest/contributions/_submenu.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from typing import Optional, Union

from pydantic import BaseModel
from pydantic.fields import Field
from npe2._pydantic_compat import BaseModel, Field

from ._icon import Icon

Expand Down
3 changes: 1 addition & 2 deletions src/npe2/manifest/contributions/_themes.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import sys
from typing import Literal, Optional, Union

from pydantic import BaseModel, color
from pydantic.fields import Field
from npe2._pydantic_compat import BaseModel, Field, color


# pydantic doesn't implement color equality?
Expand Down
3 changes: 1 addition & 2 deletions src/npe2/manifest/contributions/_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

from typing import TYPE_CHECKING, Callable, Optional

from pydantic import Extra, Field

from npe2._pydantic_compat import Extra, Field
from npe2.manifest.utils import Executable
from npe2.types import Widget

Expand Down
3 changes: 1 addition & 2 deletions src/npe2/manifest/contributions/_writers.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from enum import Enum
from typing import List, Tuple

from pydantic import BaseModel, Extra, Field, validator

from npe2._pydantic_compat import BaseModel, Extra, Field, validator
from npe2.manifest.utils import Executable


Expand Down
17 changes: 11 additions & 6 deletions src/npe2/manifest/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@
from pathlib import Path
from typing import Iterator, List, Literal, NamedTuple, Optional, Sequence, Union

from pydantic import Extra, Field, ValidationError, root_validator, validator
from pydantic.error_wrappers import ErrorWrapper
from pydantic.main import BaseModel, ModelMetaclass

from npe2._pydantic_compat import (
BaseModel,
ErrorWrapper,
Extra,
Field,
ModelMetaclass,
ValidationError,
root_validator,
validator,
)
from npe2.types import PythonName

from . import _validators
Expand Down Expand Up @@ -438,9 +444,8 @@ def _from_package_or_name(
If the name does not resolve to either a distribution name or a filename.

"""
from pydantic import ValidationError

from npe2 import PluginManifest
from npe2._pydantic_compat import ValidationError

try:
return PluginManifest.from_file(package_or_filename)
Expand Down
4 changes: 1 addition & 3 deletions src/npe2/manifest/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@
Union,
)

from pydantic import PrivateAttr
from pydantic.generics import GenericModel

from npe2._pydantic_compat import GenericModel, PrivateAttr
from npe2.types import PythonName

if TYPE_CHECKING:
Expand Down
2 changes: 1 addition & 1 deletion tests/test_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
from unittest.mock import patch

import pytest
from pydantic import ValidationError

from npe2 import PluginManifest
from npe2._pydantic_compat import ValidationError
from npe2.manifest import PackageMetadata
from npe2.manifest.schema import ENTRY_POINT

Expand Down
2 changes: 1 addition & 1 deletion tests/test_validations.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import json

import pytest
from pydantic import ValidationError

from npe2 import PluginManifest
from npe2._pydantic_compat import ValidationError
from npe2.manifest import _validators

# the docstrings here are used to assert the validation error that is printed.
Expand Down