Skip to content

Commit

Permalink
Add testing for Pydantic 1/2 (#42)
Browse files Browse the repository at this point in the history
* Add testing for Pydantic 1/2

* Clean up for pydantic cross-compatibility

* Update tox.ini

* Update tests.yml

* set environment for building docs

---------

Co-authored-by: Owen Lynch <[email protected]>
  • Loading branch information
cthoyt and olynch authored Nov 14, 2023
1 parent 53b161d commit 45e5b2e
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 20 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11"]
python-version: ["3.11"]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -60,6 +60,7 @@ jobs:
matrix:
os: [ubuntu-latest]
python-version: ["3.9", "3.10", "3.11"]
pydantic: [ "1", "2" ]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -69,7 +70,7 @@ jobs:
- name: Install dependencies
run: pip install tox
- name: Test with pytest and generate coverage file
run: tox run -e py
run: tox run -e py-pydantic${{ matrix.pydantic }}
- name: Upload coverage report to codecov
uses: codecov/codecov-action@v3
if: success()
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ keywords =

[options]
install_requires =
pydantic<2.0
pydantic

# Random options
zip_safe = false
Expand Down
39 changes: 26 additions & 13 deletions src/acsets/acsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,12 @@ class Ob(HashableBaseModel):
"""

name: str = Field(..., description="The name of the object")
title: Optional[str] = Field(description="The human-readable label for the object")
description: Optional[str] = Field(description="A long-form description of the object")
title: Optional[str] = Field(
default=None, description="The human-readable label for the object"
)
description: Optional[str] = Field(
default=None, description="A long-form description of the object"
)

class Config:
"""pydantic config"""
Expand All @@ -52,11 +56,15 @@ class Hom(HashableBaseModel):
and `Hom("tgt", E, V)`.
"""

name: str = Field(description="The name of the morphism.")
dom: str = Field(title="domain", description="The object of the domain.")
codom: str = Field(title="codomain", description="The object of the codomain.")
title: Optional[str] = Field(description="The human-readable label for the morphism")
description: Optional[str] = Field(description="A long-form description of the morphism")
name: str = Field(..., description="The name of the morphism.")
dom: str = Field(..., title="domain", description="The object of the domain.")
codom: str = Field(..., title="codomain", description="The object of the codomain.")
title: Optional[str] = Field(
default=None, description="The human-readable label for the morphism"
)
description: Optional[str] = Field(
default=None, description="A long-form description of the morphism"
)

@validator("dom", pre=True)
def dom_string(cls, ob: Union[str, Ob]):
Expand Down Expand Up @@ -110,9 +118,10 @@ class AttrType(HashableBaseModel):
transition, for instance, has a tuple of strings as its name.
"""

name: str = Field(description="The name of the attribute type.")
name: str = Field(..., description="The name of the attribute type.")
ty: type = Field(
description="The type assigned to the attribute type. Use a string referring to the Python type"
...,
description="The type assigned to the attribute type. Use a string referring to the Python type",
)
title: Optional[str] = None
description: Optional[str] = None
Expand Down Expand Up @@ -140,9 +149,9 @@ class Attr(HashableBaseModel):
which is the attribute that stores the name of a species in a Petri net.
"""

name: str = Field(title="name", description="The name of the attribute.")
dom: str = Field(title="domain", description="The object in the domain.")
codom: str = Field(title="codomain", description="The attribute type in the codomain")
name: str = Field(..., title="name", description="The name of the attribute.")
dom: str = Field(..., title="domain", description="The object in the domain.")
codom: str = Field(..., title="codomain", description="The attribute type in the codomain")
title: Optional[str] = None
description: Optional[str] = None

Expand Down Expand Up @@ -279,7 +288,11 @@ def valtype(self, prop: Property):
Returns:
The Property value type
"""
return int if isinstance(prop, Hom) else next(at for at in self.schema.AttrType if at.name == prop.codom).ty
return (
int
if isinstance(prop, Hom)
else next(at for at in self.schema.AttrType if at.name == prop.codom).ty
)

def valid_value(self, prop: Property, val):
"""Verify if a given value is valid for a given property
Expand Down
3 changes: 2 additions & 1 deletion src/acsets/schemas/catlab_to_jsonschema.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""This script turns all the catlab schemata into json schemata"""

from pathlib import Path

from acsets import (
CATLAB_SCHEMAS_DIRECTORY,
ACSet,
Expand All @@ -9,8 +10,8 @@
CatlabSchema,
Hom,
Ob,
petris,
Schema,
petris,
)

HERE = Path(__file__).parent.resolve()
Expand Down
3 changes: 2 additions & 1 deletion tests/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import unittest

import jsonschema
from acsets.schemas import EXAMPLES, CATLAB, JSONSCHEMA

from acsets.schemas import CATLAB, EXAMPLES, JSONSCHEMA


class TestExamples(unittest.TestCase):
Expand Down
6 changes: 6 additions & 0 deletions tests/test_petri.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@

"""Test serialization."""

import importlib
import os
import tempfile
import unittest

from acsets import ACSet, Attr, AttrType, Hom, Ob, mira, petris

PYDANTIC_1 = importlib.metadata.version("pydantic").startswith("1.")


class TestSerialization(unittest.TestCase):
"""A test case for testing serialization."""
Expand Down Expand Up @@ -55,6 +58,9 @@ def test_ob(self):
self.assertIsInstance(hom1.dom, str)
self.assertIsInstance(hom1.codom, str)

@unittest.skipUnless(
PYDANTIC_1, reason="This functionality can not be made cross-compatible AFAIK"
)
def test_write_schema(self):
"""Test writing the schema does not error."""
with tempfile.TemporaryDirectory() as directory:
Expand Down
11 changes: 9 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ envlist =
docstr-coverage
docs-test
# the actual tests
py
py-pydantic1
py-pydantic2
# always keep coverage-report last
# coverage-report

Expand All @@ -34,6 +35,9 @@ commands =
coverage run -p -m pytest --durations=20 {posargs:tests}
coverage combine
coverage xml
deps =
pydantic1: pydantic<2.0
pydantic2: pydantic>=2.0
extras =
# See the [options.extras_require] entry in setup.cfg for "tests"
tests
Expand Down Expand Up @@ -80,7 +84,7 @@ description = Check that the MANIFEST.in is written properly and give feedback o
skip_install = true
deps =
darglint
flake8
flake8<5.0.0
flake8-black
flake8-bandit
flake8-bugbear
Expand Down Expand Up @@ -137,6 +141,9 @@ commands =
[testenv:docs-test]
description = Test building the documentation in an isolated environment.
changedir = docs
setenv =
LC_ALL = C.UTF-8
LANG = C.UTF-8
extras =
{[testenv:docs]extras}
commands =
Expand Down

0 comments on commit 45e5b2e

Please sign in to comment.