Skip to content
This repository was archived by the owner on Aug 19, 2025. It is now read-only.

Commit 84a657b

Browse files
Schema as plain instances, not classes
1 parent 013007f commit 84a657b

11 files changed

Lines changed: 543 additions & 831 deletions

tests/test_base.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
11
import typesystem
22

33

4-
class Example(typesystem.Schema):
5-
a = typesystem.String(max_length=10)
6-
b = typesystem.Integer(maximum=5)
4+
example = typesystem.Schema(fields={
5+
"a": typesystem.String(max_length=10),
6+
"b": typesystem.Integer(maximum=5),
7+
})
78

89

910
def test_validation_result_repr():
10-
result = Example.validate_or_error({"a": "a", "b": 1})
11-
assert repr(result) == "ValidationResult(value=Example(a='a', b=1))"
11+
result = example.validate_or_error({"a": "a", "b": 1})
12+
assert repr(result) == "ValidationResult(value={'a': 'a', 'b': 1})"
1213

13-
result = Example.validate_or_error({"a": "a"})
14+
result = example.validate_or_error({"a": "a"})
1415
assert (
1516
repr(result)
1617
== "ValidationResult(error=ValidationError([Message(text='This field is required.', code='required', index=['b'])]))"
1718
)
1819

1920

2021
def test_validation_error_repr():
21-
result = Example.validate_or_error({"a": "a"})
22+
result = example.validate_or_error({"a": "a"})
2223
assert (
2324
repr(result.error)
2425
== "ValidationError([Message(text='This field is required.', code='required', index=['b'])])"
@@ -32,15 +33,15 @@ def test_validation_error_repr():
3233

3334

3435
def test_validation_error_str():
35-
result = Example.validate_or_error({"a": "a"})
36+
result = example.validate_or_error({"a": "a"})
3637
assert str(result.error) == "{'b': 'This field is required.'}"
3738

3839
result = typesystem.String(max_length=10).validate_or_error("a" * 100)
3940
assert str(result.error) == "Must have no more than 10 characters."
4041

4142

4243
def test_validation_message_repr():
43-
result = Example.validate_or_error({"a": "a"})
44+
result = example.validate_or_error({"a": "a"})
4445
message = result.error.messages()[0]
4546
assert (
4647
repr(message)

tests/test_definitions.py

Lines changed: 92 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -4,122 +4,104 @@
44

55

66
def test_reference():
7-
definitions = typesystem.SchemaDefinitions()
7+
definitions = typesystem.Definitions()
88

9-
class Album(typesystem.Schema, definitions=definitions):
10-
title = typesystem.String(max_length=100)
11-
release_date = typesystem.Date()
12-
artist = typesystem.Reference("Artist")
9+
album = typesystem.Schema(fields={
10+
"title": typesystem.String(max_length=100),
11+
"release_date": typesystem.Date(),
12+
"artist": typesystem.Reference("Artist", definitions=definitions),
13+
})
1314

14-
class Artist(typesystem.Schema, definitions=definitions):
15-
name = typesystem.String(max_length=100)
15+
artist = typesystem.Schema(fields={
16+
"name": typesystem.String(max_length=100)
17+
})
1618

17-
album = Album.validate(
19+
definitions['Artist'] = artist
20+
21+
value = album.validate(
1822
{
1923
"title": "Double Negative",
2024
"release_date": "2018-09-14",
2125
"artist": {"name": "Low"},
2226
}
2327
)
24-
assert album == Album(
25-
title="Double Negative",
26-
release_date=datetime.date(2018, 9, 14),
27-
artist=Artist(name="Low"),
28-
)
29-
30-
# Identical class names in alternate definitions should not clash.
31-
definitions = typesystem.SchemaDefinitions()
32-
33-
class Album(typesystem.Schema, definitions=definitions):
34-
renamed_title = typesystem.String(max_length=100)
35-
renamed_release_date = typesystem.Date()
36-
renamed_artist = typesystem.Reference("Artist")
37-
38-
class Artist(typesystem.Schema, definitions=definitions):
39-
renamed_name = typesystem.String(max_length=100)
40-
41-
album = Album.validate(
42-
{
43-
"renamed_title": "Double Negative",
44-
"renamed_release_date": "2018-09-14",
45-
"renamed_artist": {"renamed_name": "Low"},
46-
}
47-
)
48-
assert album == Album(
49-
renamed_title="Double Negative",
50-
renamed_release_date=datetime.date(2018, 9, 14),
51-
renamed_artist=Artist(renamed_name="Low"),
52-
)
53-
54-
55-
def test_definitions_as_mapping():
56-
"""
57-
Ensure that definitions support a mapping interface.
58-
"""
59-
definitions = typesystem.SchemaDefinitions()
60-
61-
class Album(typesystem.Schema, definitions=definitions):
62-
title = typesystem.String(max_length=100)
63-
release_date = typesystem.Date()
64-
artist = typesystem.Reference("Artist")
65-
66-
class Artist(typesystem.Schema, definitions=definitions):
67-
name = typesystem.String(max_length=100)
68-
69-
assert definitions["Album"] == Album
70-
assert definitions["Artist"] == Artist
71-
assert dict(definitions) == {"Album": Album, "Artist": Artist}
72-
assert len(definitions) == 2
73-
del definitions["Artist"]
74-
75-
76-
def test_string_references():
77-
definitions = typesystem.SchemaDefinitions()
78-
79-
class ExampleA(typesystem.Schema, definitions=definitions):
80-
field_on_a = typesystem.Integer()
81-
example_b = typesystem.Reference("ExampleB")
82-
83-
class ExampleB(typesystem.Schema, definitions=definitions):
84-
field_on_b = typesystem.Integer()
85-
86-
value = ExampleA.validate({"field_on_a": "123", "example_b": {"field_on_b": "456"}})
87-
assert value == ExampleA(field_on_a=123, example_b=ExampleB(field_on_b=456))
88-
89-
class ExampleC(typesystem.Schema, definitions=definitions):
90-
field_on_c = typesystem.Integer()
91-
example_d = typesystem.Array(items=typesystem.Reference("ExampleD"))
92-
93-
class ExampleD(typesystem.Schema, definitions=definitions):
94-
field_on_d = typesystem.Integer()
95-
96-
value = ExampleC.validate(
97-
{"field_on_c": "123", "example_d": [{"field_on_d": "456"}]}
98-
)
99-
assert value == ExampleC(field_on_c=123, example_d=[ExampleD(field_on_d=456)])
100-
101-
class ExampleE(typesystem.Schema, definitions=definitions):
102-
field_on_e = typesystem.Integer()
103-
example_f = typesystem.Array(items=[typesystem.Reference("ExampleF")])
104-
105-
class ExampleF(typesystem.Schema, definitions=definitions):
106-
field_on_f = typesystem.Integer()
107-
108-
value = ExampleE.validate(
109-
{"field_on_e": "123", "example_f": [{"field_on_f": "456"}]}
110-
)
111-
assert value == ExampleE(field_on_e=123, example_f=[ExampleF(field_on_f=456)])
112-
113-
class ExampleG(typesystem.Schema, definitions=definitions):
114-
field_on_g = typesystem.Integer()
115-
example_h = typesystem.Object(
116-
properties={"h": typesystem.Reference("ExampleH")}
117-
)
118-
119-
class ExampleH(typesystem.Schema, definitions=definitions):
120-
field_on_h = typesystem.Integer()
121-
122-
value = ExampleG.validate(
123-
{"field_on_g": "123", "example_h": {"h": {"field_on_h": "456"}}}
124-
)
125-
assert value == ExampleG(field_on_g=123, example_h={"h": ExampleH(field_on_h=456)})
28+
assert value == {
29+
"title": "Double Negative",
30+
"release_date": datetime.date(2018, 9, 14),
31+
"artist": {
32+
"name": "Low"
33+
},
34+
}
35+
36+
37+
# def test_definitions_as_mapping():
38+
# """
39+
# Ensure that definitions support a mapping interface.
40+
# """
41+
# definitions = typesystem.SchemaDefinitions()
42+
#
43+
# class Album(typesystem.Schema, definitions=definitions):
44+
# title = typesystem.String(max_length=100)
45+
# release_date = typesystem.Date()
46+
# artist = typesystem.Reference("Artist")
47+
#
48+
# class Artist(typesystem.Schema, definitions=definitions):
49+
# name = typesystem.String(max_length=100)
50+
#
51+
# assert definitions["Album"] == Album
52+
# assert definitions["Artist"] == Artist
53+
# assert dict(definitions) == {"Album": Album, "Artist": Artist}
54+
# assert len(definitions) == 2
55+
# del definitions["Artist"]
56+
#
57+
#
58+
# def test_string_references():
59+
# definitions = typesystem.SchemaDefinitions()
60+
#
61+
# class ExampleA(typesystem.Schema, definitions=definitions):
62+
# field_on_a = typesystem.Integer()
63+
# example_b = typesystem.Reference("ExampleB")
64+
#
65+
# class ExampleB(typesystem.Schema, definitions=definitions):
66+
# field_on_b = typesystem.Integer()
67+
#
68+
# value = ExampleA.validate({"field_on_a": "123", "example_b": {"field_on_b": "456"}})
69+
# assert value == ExampleA(field_on_a=123, example_b=ExampleB(field_on_b=456))
70+
#
71+
# class ExampleC(typesystem.Schema, definitions=definitions):
72+
# field_on_c = typesystem.Integer()
73+
# example_d = typesystem.Array(items=typesystem.Reference("ExampleD"))
74+
#
75+
# class ExampleD(typesystem.Schema, definitions=definitions):
76+
# field_on_d = typesystem.Integer()
77+
#
78+
# value = ExampleC.validate(
79+
# {"field_on_c": "123", "example_d": [{"field_on_d": "456"}]}
80+
# )
81+
# assert value == ExampleC(field_on_c=123, example_d=[ExampleD(field_on_d=456)])
82+
#
83+
# class ExampleE(typesystem.Schema, definitions=definitions):
84+
# field_on_e = typesystem.Integer()
85+
# example_f = typesystem.Array(items=[typesystem.Reference("ExampleF")])
86+
#
87+
# class ExampleF(typesystem.Schema, definitions=definitions):
88+
# field_on_f = typesystem.Integer()
89+
#
90+
# value = ExampleE.validate(
91+
# {"field_on_e": "123", "example_f": [{"field_on_f": "456"}]}
92+
# )
93+
# assert value == ExampleE(field_on_e=123, example_f=[ExampleF(field_on_f=456)])
94+
#
95+
# class ExampleG(typesystem.Schema, definitions=definitions):
96+
# field_on_g = typesystem.Integer()
97+
# example_h = typesystem.Object(
98+
# properties={"h": typesystem.Reference("ExampleH")}
99+
# )
100+
#
101+
# class ExampleH(typesystem.Schema, definitions=definitions):
102+
# field_on_h = typesystem.Integer()
103+
#
104+
# value = ExampleG.validate(
105+
# {"field_on_g": "123", "example_h": {"h": {"field_on_h": "456"}}}
106+
# )
107+
# assert value == ExampleG(field_on_g=123, example_h={"h": ExampleH(field_on_h=456)})

tests/test_forms.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@
33
import typesystem
44

55

6-
class Contact(typesystem.Schema):
7-
a = typesystem.Boolean()
8-
b = typesystem.String(max_length=10)
9-
c = typesystem.Text()
10-
d = typesystem.Choice(choices=[("abc", "Abc"), ("def", "Def"), ("ghi", "Ghi")])
6+
contact = typesystem.Schema(fields={
7+
"a": typesystem.Boolean(),
8+
"b": typesystem.String(max_length=10),
9+
"c": typesystem.Text(),
10+
"d": typesystem.Choice(choices=[("abc", "Abc"), ("def", "Def"), ("ghi", "Ghi")]),
11+
})
1112

1213

1314
forms = typesystem.Jinja2Forms(package="typesystem")
1415

1516

1617
def test_form_rendering():
17-
form = forms.create_form(Contact)
18+
form = forms.create_form(contact)
1819

1920
html = str(form)
2021

@@ -25,17 +26,18 @@ def test_form_rendering():
2526

2627

2728
def test_password_rendering():
28-
class PasswordForm(typesystem.Schema):
29-
password = typesystem.String(format="password")
29+
password_schema = typesystem.Schema({
30+
"password": typesystem.String(format="password")
31+
})
3032

31-
form = forms.create_form(PasswordForm)
33+
form = forms.create_form(password_schema)
3234
form.validate(data={"password": "secret"})
3335
html = str(form)
3436
assert "secret" not in html
3537

3638

3739
def test_form_html():
38-
form = forms.create_form(Contact)
40+
form = forms.create_form(contact)
3941

4042
markup = form.__html__()
4143

tests/test_json_schema.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,20 +116,21 @@ def test_to_from_json_schema(schema, data, is_valid, description):
116116

117117

118118
def test_schema_to_json_schema():
119-
class BookingSchema(typesystem.Schema):
120-
start_date = typesystem.Date(title="Start date")
121-
end_date = typesystem.Date(title="End date")
122-
room = typesystem.Choice(
119+
booking_schema = typesystem.Schema({
120+
"start_date": typesystem.Date(title="Start date"),
121+
"end_date": typesystem.Date(title="End date"),
122+
"room": typesystem.Choice(
123123
title="Room type",
124124
choices=[
125125
("double", "Double room"),
126126
("twin", "Twin room"),
127127
("single", "Single room"),
128128
],
129-
)
130-
include_breakfast = typesystem.Boolean(title="Include breakfast", default=False)
129+
),
130+
"include_breakfast": typesystem.Boolean(title="Include breakfast", default=False)
131+
})
131132

132-
schema = to_json_schema(BookingSchema)
133+
schema = to_json_schema(booking_schema)
133134

134135
assert schema == {
135136
"type": "object",

0 commit comments

Comments
 (0)