SlideShare a Scribd company logo
1 of 14
Download to read offline
Declarative Data Modeling 
in Python 
by Joshua Forman
Introducing valid_model 
It includes: 
- base class - Object 
- basic descriptors - Integer, Float, DateTime, String, ... 
- nesting descriptors - Dict, List, Set, EmbeddedObject
Most similar libraries are tightly integrated to a persistence layer: 
SQLAlchemy, Django ORM, mongokit, etc. 
Or are targeted at web forms: 
Formencode, colander, deform 
So the goal was to build a highly flexible unopinionated data modeling 
library.
Some Use Cases 
● Database data model 
● Form validation 
● Test fixtures 
● API request/response objects 
● Scrubbing and normalizing data 
● Data migration
car = { 
'make': None, 
'model': None, 
'doors': None, 
'horsepower': None, 
} 
class Car(object): 
def __init__(self, make=None, model=None, doors=None, 
horsepower=None): 
self.make = make 
self.model = model 
self.doors = doors 
self.horsepower = horsepower 
It is valid python to arbitrarily add new instance attributes in other methods, which can lead to 
headaches (and pylint complaints)
At least I know the fields ahead of time but what datatypes are these attributes? 
def horse_check(value): 
if value == 1: 
raise ValidationError('Is this powered by an actual horse?') 
elif value <= 0: 
raise ValidationError('Phantom horses?') 
return True 
class Car(Object): 
make = String(nullable=False) 
model = String() 
doors = Integer(validator=lambda x: x<=5) 
horsepower = Integer(validator=horse_check)
Nested Schemas is Easy 
class Person(Object): 
name = String(nullable=False) 
homepage = String() 
class BlogPost(Object): 
title = String(nullable=False, mutator=lambda x: x.title()) 
updated = DateTime(nullable=False, default=datetime.utcnow) 
published = DateTime() 
author = EmbeddedObject(Person) 
contributors = List(value=EmbeddedObject(Person), nullable=False) 
tags = List(value=String(nullable=False), nullable=False) 
def validate(self): 
super(BlogPost, self).validate() 
if self.published is not None and self.published > self.updated: 
raise ValidationError('a post cannot be published at a later date 
than it was updated') 
post = BlogPost(title='example post', author={'name': 'Josh'}, tags=['tag1', 'tag2']) 
>>> print post 
{'updated': datetime.datetime(2014, 10, 7, 13, 43, 1, 960174), 
'author': {'homepage': None, 'name': u'Josh'}, 
'contributors': [], 'title': u'Example Post', 'tags': [u'tag1', u'tag2'], 'published': None}
valid_model also provides something closer to strict typing 
class Car(Object): 
make = String(nullable=False) 
model = String() 
doors = Integer(validator=lambda x: x<=5) 
horsepower = Integer(validator=horse_check) 
>>> Car(doors='five') 
valid_model.exc.ValidationError: 'five' is not an int 
>>> Car(doors=10) 
valid_model.exc.ValidationError: doors 
>>> Car(horsepower=1) 
valid_model.exc.ValidationError: Is this powered by an actual horse? 
>>> Car(make=None) 
valid_model.exc.ValidationError: make is not nullable
Normalize your data when it gets set 
class HTTPAccessLog(Object): 
code = Integer(nullable=False) 
status = String(nullable=False, mutator=lambda x: x.upper()) 
timestamp = DateTime(default=datetime.utcnow) 
def validate(self): 
super(HTTPAccessLog, self).validate() 
if not self.status.startswith(unicode(self.code)): 
raise ValidationError('code and status do not match') 
>>> ping = HTTPAccessLog() 
>>> ping.code = 404 
>>> ping.status = '404 not found' 
>>> print ping 
{'status': u'404 NOT FOUND', 'timestamp': datetime.datetime(2014, 10, 7, 13, 36, 15, 217678), 
'code': 404}
Descriptors Tangent 
Python descriptors are fancy attributes. 
class SomeDescriptor(object): 
def __get__(self, instance, klass=None): 
…. 
def __set__(self, instance, value): 
…. 
def __del__(self, instance): 
…. 
class Foo(object): 
b = SomeDescriptor()
@property Descriptors 
@property is the most common 
class Foo(object): 
@property 
def a(self): 
return self._a 
@a.setter 
def a(self, value): 
self._a = value 
# Make an attribute readonly by not defining the setter. 
@property 
def readonly(self): 
return self._private_var 
#Lazily initialize or cache expensive calculations 
@property 
def expensive_func(self): 
if self._result is None: 
self._result = expensive_func() 
return self._result
Customizing Descriptors is Easy 
Extending existing descriptors works like subclassing anything else in python 
class SuperDateTime(DateTime): 
def __set__(self, instance, value): 
if isinstance(value, basestring): 
value = dateutils.parse(value) 
elif isinstance(value, (int, float)): 
value = datetime.utcfromtimestamp(value) 
super(SuperDateTime, self).__set__(instance, value) 
class Decimal(Generic): 
def __set__(self, instance, value): 
if not isinstance(value, decimal.Decimal): 
raise ValidationError('{} is not a decimal'.format(self.name)) 
super(Decimal, self).__set__(instance, value)
Simple wrappers for persistence 
An example of using MongoDB with Redis as a cache 
class PersistBlogPost(object): 
def __init__(self, mongo_collection, redis_conn): 
... 
def insert(self, post): 
self.mongo_collection.insert(post.__json__()) 
def find(self, title): 
post = self.redis_conn.get(title) 
if post: 
return pickle.loads(post) 
else: 
post = self.mongo_collection.find_one({'title': title}) 
if post: 
post = BlogPost(**post) 
self.redis_conn.set(title, pickle.dumps(post)) 
return post
Thank You 
http://github.com/outbrain/valid_model 
Joshua Forman 
jforman@outbrain.com

More Related Content

What's hot

Functions and Objects in JavaScript
Functions and Objects in JavaScript Functions and Objects in JavaScript
Functions and Objects in JavaScript Dhananjay Kumar
 
JavaScript - Chapter 6 - Basic Functions
 JavaScript - Chapter 6 - Basic Functions JavaScript - Chapter 6 - Basic Functions
JavaScript - Chapter 6 - Basic FunctionsWebStackAcademy
 
JavaScript - Chapter 8 - Objects
 JavaScript - Chapter 8 - Objects JavaScript - Chapter 8 - Objects
JavaScript - Chapter 8 - ObjectsWebStackAcademy
 
javascript objects
javascript objectsjavascript objects
javascript objectsVijay Kalyan
 
3.1 javascript objects_DOM
3.1 javascript objects_DOM3.1 javascript objects_DOM
3.1 javascript objects_DOMJalpesh Vasa
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing UpDavid Padbury
 
Ios development
Ios developmentIos development
Ios developmentelnaqah
 
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYA
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYAPYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYA
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYAMaulik Borsaniya
 
ActionScript3 collection query API proposal
ActionScript3 collection query API proposalActionScript3 collection query API proposal
ActionScript3 collection query API proposalSlavisa Pokimica
 
Basics of Object Oriented Programming in Python
Basics of Object Oriented Programming in PythonBasics of Object Oriented Programming in Python
Basics of Object Oriented Programming in PythonSujith Kumar
 
Few simple-type-tricks in scala
Few simple-type-tricks in scalaFew simple-type-tricks in scala
Few simple-type-tricks in scalaRuslan Shevchenko
 
Powerful JavaScript Tips and Best Practices
Powerful JavaScript Tips and Best PracticesPowerful JavaScript Tips and Best Practices
Powerful JavaScript Tips and Best PracticesDragos Ionita
 
Oop in-php
Oop in-phpOop in-php
Oop in-phpRajesh S
 

What's hot (20)

Functions and Objects in JavaScript
Functions and Objects in JavaScript Functions and Objects in JavaScript
Functions and Objects in JavaScript
 
JavaScript - Chapter 6 - Basic Functions
 JavaScript - Chapter 6 - Basic Functions JavaScript - Chapter 6 - Basic Functions
JavaScript - Chapter 6 - Basic Functions
 
Python programming : Classes objects
Python programming : Classes objectsPython programming : Classes objects
Python programming : Classes objects
 
JavaScript - Chapter 8 - Objects
 JavaScript - Chapter 8 - Objects JavaScript - Chapter 8 - Objects
JavaScript - Chapter 8 - Objects
 
javascript objects
javascript objectsjavascript objects
javascript objects
 
3.1 javascript objects_DOM
3.1 javascript objects_DOM3.1 javascript objects_DOM
3.1 javascript objects_DOM
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
 
Python oop class 1
Python oop   class 1Python oop   class 1
Python oop class 1
 
Csharp_Chap03
Csharp_Chap03Csharp_Chap03
Csharp_Chap03
 
Ios development
Ios developmentIos development
Ios development
 
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYA
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYAPYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYA
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYA
 
JavaScript Objects
JavaScript ObjectsJavaScript Objects
JavaScript Objects
 
ActionScript3 collection query API proposal
ActionScript3 collection query API proposalActionScript3 collection query API proposal
ActionScript3 collection query API proposal
 
Basics of Object Oriented Programming in Python
Basics of Object Oriented Programming in PythonBasics of Object Oriented Programming in Python
Basics of Object Oriented Programming in Python
 
Few simple-type-tricks in scala
Few simple-type-tricks in scalaFew simple-type-tricks in scala
Few simple-type-tricks in scala
 
Powerful JavaScript Tips and Best Practices
Powerful JavaScript Tips and Best PracticesPowerful JavaScript Tips and Best Practices
Powerful JavaScript Tips and Best Practices
 
Oop in-php
Oop in-phpOop in-php
Oop in-php
 
Parte II Objective C
Parte II   Objective CParte II   Objective C
Parte II Objective C
 
OOPs & Inheritance Notes
OOPs & Inheritance NotesOOPs & Inheritance Notes
OOPs & Inheritance Notes
 
Python advance
Python advancePython advance
Python advance
 

Similar to Declarative Data Modeling in Python

constructors.pptx
constructors.pptxconstructors.pptx
constructors.pptxEpsiba1
 
Ruby Development and MongoMapper (John Nunemaker)
Ruby Development and MongoMapper (John Nunemaker)Ruby Development and MongoMapper (John Nunemaker)
Ruby Development and MongoMapper (John Nunemaker)MongoSF
 
Python magicmethods
Python magicmethodsPython magicmethods
Python magicmethodsdreampuf
 
Oop2010 Scala Presentation Stal
Oop2010 Scala Presentation StalOop2010 Scala Presentation Stal
Oop2010 Scala Presentation StalMichael Stal
 
Object Trampoline: Why having not the object you want is what you need.
Object Trampoline: Why having not the object you want is what you need.Object Trampoline: Why having not the object you want is what you need.
Object Trampoline: Why having not the object you want is what you need.Workhorse Computing
 
11. session 11 functions and objects
11. session 11   functions and objects11. session 11   functions and objects
11. session 11 functions and objectsPhúc Đỗ
 
PofEAA and SQLAlchemy
PofEAA and SQLAlchemyPofEAA and SQLAlchemy
PofEAA and SQLAlchemyInada Naoki
 
Scalable web application architecture
Scalable web application architectureScalable web application architecture
Scalable web application architecturepostrational
 
Pyimproved again
Pyimproved againPyimproved again
Pyimproved againrik0
 
Pyconie 2012
Pyconie 2012Pyconie 2012
Pyconie 2012Yaqi Zhao
 
CoffeeScript - A Rubyist's Love Affair
CoffeeScript - A Rubyist's Love AffairCoffeeScript - A Rubyist's Love Affair
CoffeeScript - A Rubyist's Love AffairMark
 
Building a Portfolio With Custom Post Types
Building a Portfolio With Custom Post TypesBuilding a Portfolio With Custom Post Types
Building a Portfolio With Custom Post TypesAlex Blackie
 

Similar to Declarative Data Modeling in Python (20)

Oop java
Oop javaOop java
Oop java
 
constructors.pptx
constructors.pptxconstructors.pptx
constructors.pptx
 
Ruby Development and MongoMapper (John Nunemaker)
Ruby Development and MongoMapper (John Nunemaker)Ruby Development and MongoMapper (John Nunemaker)
Ruby Development and MongoMapper (John Nunemaker)
 
Python magicmethods
Python magicmethodsPython magicmethods
Python magicmethods
 
Python_Unit_2 OOPS.pptx
Python_Unit_2  OOPS.pptxPython_Unit_2  OOPS.pptx
Python_Unit_2 OOPS.pptx
 
Spsl vi unit final
Spsl vi unit finalSpsl vi unit final
Spsl vi unit final
 
Spsl v unit - final
Spsl v unit - finalSpsl v unit - final
Spsl v unit - final
 
Oop2010 Scala Presentation Stal
Oop2010 Scala Presentation StalOop2010 Scala Presentation Stal
Oop2010 Scala Presentation Stal
 
Real World MVC
Real World MVCReal World MVC
Real World MVC
 
Week3
Week3Week3
Week3
 
Object Trampoline: Why having not the object you want is what you need.
Object Trampoline: Why having not the object you want is what you need.Object Trampoline: Why having not the object you want is what you need.
Object Trampoline: Why having not the object you want is what you need.
 
Java scriptforjavadev part2a
Java scriptforjavadev part2aJava scriptforjavadev part2a
Java scriptforjavadev part2a
 
11. session 11 functions and objects
11. session 11   functions and objects11. session 11   functions and objects
11. session 11 functions and objects
 
PofEAA and SQLAlchemy
PofEAA and SQLAlchemyPofEAA and SQLAlchemy
PofEAA and SQLAlchemy
 
Scalable web application architecture
Scalable web application architectureScalable web application architecture
Scalable web application architecture
 
Pyimproved again
Pyimproved againPyimproved again
Pyimproved again
 
Pyconie 2012
Pyconie 2012Pyconie 2012
Pyconie 2012
 
CoffeeScript - A Rubyist's Love Affair
CoffeeScript - A Rubyist's Love AffairCoffeeScript - A Rubyist's Love Affair
CoffeeScript - A Rubyist's Love Affair
 
Building a Portfolio With Custom Post Types
Building a Portfolio With Custom Post TypesBuilding a Portfolio With Custom Post Types
Building a Portfolio With Custom Post Types
 
обзор Python
обзор Pythonобзор Python
обзор Python
 

Recently uploaded

WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...masabamasaba
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...chiefasafspells
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension AidPhilip Schwarz
 
WSO2Con2024 - Hello Choreo Presentation - Kanchana
WSO2Con2024 - Hello Choreo Presentation - KanchanaWSO2Con2024 - Hello Choreo Presentation - Kanchana
WSO2Con2024 - Hello Choreo Presentation - KanchanaWSO2
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...masabamasaba
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...Jittipong Loespradit
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...masabamasaba
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
WSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrainmasabamasaba
 
tonesoftg
tonesoftgtonesoftg
tonesoftglanshi9
 

Recently uploaded (20)

WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
WSO2Con2024 - Hello Choreo Presentation - Kanchana
WSO2Con2024 - Hello Choreo Presentation - KanchanaWSO2Con2024 - Hello Choreo Presentation - Kanchana
WSO2Con2024 - Hello Choreo Presentation - Kanchana
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
WSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaS
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
 

Declarative Data Modeling in Python

  • 1. Declarative Data Modeling in Python by Joshua Forman
  • 2. Introducing valid_model It includes: - base class - Object - basic descriptors - Integer, Float, DateTime, String, ... - nesting descriptors - Dict, List, Set, EmbeddedObject
  • 3. Most similar libraries are tightly integrated to a persistence layer: SQLAlchemy, Django ORM, mongokit, etc. Or are targeted at web forms: Formencode, colander, deform So the goal was to build a highly flexible unopinionated data modeling library.
  • 4. Some Use Cases ● Database data model ● Form validation ● Test fixtures ● API request/response objects ● Scrubbing and normalizing data ● Data migration
  • 5. car = { 'make': None, 'model': None, 'doors': None, 'horsepower': None, } class Car(object): def __init__(self, make=None, model=None, doors=None, horsepower=None): self.make = make self.model = model self.doors = doors self.horsepower = horsepower It is valid python to arbitrarily add new instance attributes in other methods, which can lead to headaches (and pylint complaints)
  • 6. At least I know the fields ahead of time but what datatypes are these attributes? def horse_check(value): if value == 1: raise ValidationError('Is this powered by an actual horse?') elif value <= 0: raise ValidationError('Phantom horses?') return True class Car(Object): make = String(nullable=False) model = String() doors = Integer(validator=lambda x: x<=5) horsepower = Integer(validator=horse_check)
  • 7. Nested Schemas is Easy class Person(Object): name = String(nullable=False) homepage = String() class BlogPost(Object): title = String(nullable=False, mutator=lambda x: x.title()) updated = DateTime(nullable=False, default=datetime.utcnow) published = DateTime() author = EmbeddedObject(Person) contributors = List(value=EmbeddedObject(Person), nullable=False) tags = List(value=String(nullable=False), nullable=False) def validate(self): super(BlogPost, self).validate() if self.published is not None and self.published > self.updated: raise ValidationError('a post cannot be published at a later date than it was updated') post = BlogPost(title='example post', author={'name': 'Josh'}, tags=['tag1', 'tag2']) >>> print post {'updated': datetime.datetime(2014, 10, 7, 13, 43, 1, 960174), 'author': {'homepage': None, 'name': u'Josh'}, 'contributors': [], 'title': u'Example Post', 'tags': [u'tag1', u'tag2'], 'published': None}
  • 8. valid_model also provides something closer to strict typing class Car(Object): make = String(nullable=False) model = String() doors = Integer(validator=lambda x: x<=5) horsepower = Integer(validator=horse_check) >>> Car(doors='five') valid_model.exc.ValidationError: 'five' is not an int >>> Car(doors=10) valid_model.exc.ValidationError: doors >>> Car(horsepower=1) valid_model.exc.ValidationError: Is this powered by an actual horse? >>> Car(make=None) valid_model.exc.ValidationError: make is not nullable
  • 9. Normalize your data when it gets set class HTTPAccessLog(Object): code = Integer(nullable=False) status = String(nullable=False, mutator=lambda x: x.upper()) timestamp = DateTime(default=datetime.utcnow) def validate(self): super(HTTPAccessLog, self).validate() if not self.status.startswith(unicode(self.code)): raise ValidationError('code and status do not match') >>> ping = HTTPAccessLog() >>> ping.code = 404 >>> ping.status = '404 not found' >>> print ping {'status': u'404 NOT FOUND', 'timestamp': datetime.datetime(2014, 10, 7, 13, 36, 15, 217678), 'code': 404}
  • 10. Descriptors Tangent Python descriptors are fancy attributes. class SomeDescriptor(object): def __get__(self, instance, klass=None): …. def __set__(self, instance, value): …. def __del__(self, instance): …. class Foo(object): b = SomeDescriptor()
  • 11. @property Descriptors @property is the most common class Foo(object): @property def a(self): return self._a @a.setter def a(self, value): self._a = value # Make an attribute readonly by not defining the setter. @property def readonly(self): return self._private_var #Lazily initialize or cache expensive calculations @property def expensive_func(self): if self._result is None: self._result = expensive_func() return self._result
  • 12. Customizing Descriptors is Easy Extending existing descriptors works like subclassing anything else in python class SuperDateTime(DateTime): def __set__(self, instance, value): if isinstance(value, basestring): value = dateutils.parse(value) elif isinstance(value, (int, float)): value = datetime.utcfromtimestamp(value) super(SuperDateTime, self).__set__(instance, value) class Decimal(Generic): def __set__(self, instance, value): if not isinstance(value, decimal.Decimal): raise ValidationError('{} is not a decimal'.format(self.name)) super(Decimal, self).__set__(instance, value)
  • 13. Simple wrappers for persistence An example of using MongoDB with Redis as a cache class PersistBlogPost(object): def __init__(self, mongo_collection, redis_conn): ... def insert(self, post): self.mongo_collection.insert(post.__json__()) def find(self, title): post = self.redis_conn.get(title) if post: return pickle.loads(post) else: post = self.mongo_collection.find_one({'title': title}) if post: post = BlogPost(**post) self.redis_conn.set(title, pickle.dumps(post)) return post
  • 14. Thank You http://github.com/outbrain/valid_model Joshua Forman jforman@outbrain.com