1- Let's start by defining some schema classes .
1+ Let's start by defining some schemas .
22
33``` python
44import typesystem
55
6- class Artist (typesystem .Schema ):
7- name = typesystem.String(max_length = 100 )
6+ artist_schema = typesystem.Schema(
7+ fields = {
8+ " name" : typesystem.String(max_length = 100 )
9+ }
10+ )
811
9- class Album (typesystem .Schema ):
10- title = typesystem.String(max_length = 100 )
11- release_date = typesystem.Date()
12- artist = typesystem.Reference(Artist)
12+ definitions = typesystem.Definitions()
13+ definitions[" Artist" ] = artist_schema
14+
15+ album_schema = typesystem.Schema(
16+ fields = {
17+ " title" : typesystem.String(max_length = 100 ),
18+ " release_date" : typesystem.Date(),
19+ " artist" : typesystem.Reference(" Artist" , definitions = definitions)
20+ }
21+ )
1322```
1423
1524We've got some incoming user data that we'd like to validate against our schema.
@@ -25,18 +34,18 @@ data = {
2534We can validate the data against a Schema by using ` .validate(data) ` .
2635
2736``` python
28- album = Album .validate(data)
37+ album = album_schema .validate(data)
2938```
3039
31- If validation succeeds, this will return an ` Album ` instance .
40+ If validation succeeds, this will return an ` dict ` .
3241
3342If validation fails, a ` ValidationError ` will be raised.
3443
3544Alternatively we can use ` .validate_or_error(data) ` , which will return a
3645two-tuple of ` (value, error) ` . Either one of ` value ` or ` error ` will be ` None ` .
3746
3847``` python
39- album, error = Album .validate_or_error(data)
48+ album, error = album_schema .validate_or_error(data)
4049if error:
4150 ...
4251else :
@@ -53,7 +62,7 @@ invalid_data = {
5362 ' release_date' : ' 2018.09.14' ,
5463 ' artist' : {' name' : ' x' * 1000 }
5564}
56- album, error = Album .validate_or_error(invalid_data)
65+ album, error = album_schema .validate_or_error(invalid_data)
5766
5867print (dict (error))
5968# {'release_date': 'Must be a valid date format.', 'artist': {'name': 'Must have no more than 100 characters.'}}
@@ -65,7 +74,7 @@ If you want more precise information about exactly what error messages exist,
6574you can access each individual message with ` error.messages() ` :
6675
6776``` python
68- album, error = Album .validate_or_error(invalid_data)
77+ album, error = album_schema .validate_or_error(invalid_data)
6978
7079for message in error.messages():
7180 print (f ' { message.index!r } , { message.code!r } , { message.text!r } ) ' )
@@ -75,79 +84,46 @@ for message in error.messages():
7584
7685## Working with schema instances
7786
78- Schema instances are returned by calls to ` .validate() ` .
87+ Python dictionaries are returned by calls to ` .validate() ` .
7988
8089``` python
8190data = {
8291 ' title' : ' Double Negative' ,
8392 ' release_date' : ' 2018-09-14' ,
8493 ' artist' : {' name' : ' Low' }
8594}
86- album = Album.validate(data)
87- print (album)
88- # Album(title='Double Negative', release_date=datetime.date(2018, 9, 14), artist=Artist(name='Low'))
89- ```
90-
91- Attributes on schemas return native python data types.
92-
93- ``` python
94- print (type (album.release_date))
95- # <class 'datetime.date'>
96- ```
95+ album = album_schema.validate(data)
9796
98- Schema instances present a dict-like interface, allowing them to be easily serialized.
99-
100- ``` python
101- print (dict (album))
97+ print (album)
10298# {'title': 'Double Negative', 'release_date': '2018-09-14', 'artist': {'name': 'Low'}}
10399```
104100
105- Index lookup on schema instances returns serialized datatypes.
101+ You can also ` serialize ` data using the schema instance:
106102
107103``` python
108- print ( type (album[ ' release_date ' ]) )
109- # <class 'str'>
104+ artist = artist_schema.serialize({ ' name ' : ' Low ' } )
105+ album = album_schema.serialize({ ' title ' : ' Double Negative ' , ' artist ' : artist})
110106```
111107
112- You can also instantiate schema instances directly.
108+ If ` serialize ` directly, validation is not done and data returned may be sparsely populated.
109+ Any unused attributes without a default will not be returned.
113110
114111``` python
115- artist = Artist(name = ' Low' )
116- album = Album(title = ' Double Negative' , release_date = ' 2018-09-14' , artist = artist)
117- ```
118-
119- When instantiating with keyword arguments, each keyword argument will be validated.
120-
121- If instantiated directly, schema instances may be sparsely populated. Any unused
122- attributes without a default will not be set on the instance.
112+ artist = artist_schema.serialize({' name' : ' Low' })
113+ album = album_schema.serialize({' title' : ' Double Negative' , ' artist' : artist})
123114
124- ``` python
125- artist = Artist(name = ' Low' )
126- album = Album(title = ' Double Negative' , artist = artist)
127115print (album)
128- # Album(title='Double Negative', artist=Artist(name='Low')) [sparse]
129- album.release_date
130- # AttributeError: 'Album' object has no attribute 'release_date'
131- print (dict (album))
132- {' title' : ' Double Negative' , ' artist' : {' name' : ' Low' }}
116+ # {'title': 'Double Negative', 'artist': {'name': 'Low'}} [sparse]
117+
118+ album[' release_date' ]
119+ # KetError: 'release_date'
133120```
134121
135- Sparsely populated instances can be useful for cases of loading data from database,
122+ Sparsely serialized data can be useful for cases of loading data from database,
136123when you do not need to retrieve all the fields, or for cases of loading nested
137124data where no database join has been made, and only the primary key of the relationship
138125is known.
139126
140- You can also instantiate a schema from an object instance or dictionary.
141-
142- ``` python
143- new_album = Album(album)
144- ```
145-
146- Note that data validation is not applied when instantiating a schema instance
147- directly from an instance or dictionary. This should be used when creating
148- instances against a data source that is already known to be validated, such as
149- when loading existing instances from a database.
150-
151127## Using strict validation
152128
153129By default, additional properties in the incoming user data is ignored.
@@ -162,19 +138,10 @@ data = {
162138```
163139
164140After validating against the schema, the ` num_tracks ` property is not present
165- on the ` album ` instance .
141+ in the returned data .
166142
167143``` python
168- album = Album.validate(data)
169- album.num_tracks
170- # AttributeError: 'Album' object has no attribute 'num_tracks'
171- ```
172-
173- If you use strict validation, additional properties becomes an error instead.
174-
175- ``` python
176- album, error = Album.validate_or_error(data, strict = True )
177-
178- print (dict (error))
179- # {'num_tracks': 'Invalid property name.'}
144+ album = album_schema.validate(data)
145+ album[' num_tracks]
146+ # KeyError: 'num_tracks'
180147```
0 commit comments