1+ import warnings
2+
13from sqlalchemy import select
24from sqlalchemy .schema import Column
35
@@ -46,6 +48,9 @@ def __getattr__(self, item):
4648 return getattr (self .query , item )
4749
4850
51+ _none = object ()
52+
53+
4954class ModelLoader (Loader ):
5055 def __init__ (self , model , * column_names , ** extras ):
5156 self .model = model
@@ -57,12 +62,20 @@ def __init__(self, model, *column_names, **extras):
5762 self .extras = dict ((key , self .get (value ))
5863 for key , value in extras .items ())
5964 self .on_clause = None
60-
61- def _do_load (self , row ):
65+ self ._none_as_none = None
66+
67+ def _do_load (self , row , * , none_as_none = None ):
68+ if none_as_none is None :
69+ none_as_none = self ._none_as_none
70+ if none_as_none is None :
71+ warnings .warn (
72+ 'The none_as_none feature will be enabled by default in 0.8' ,
73+ DeprecationWarning )
74+ values = dict ((c .name , row [c ]) for c in self .columns if c in row )
75+ if none_as_none and all ((v is None ) for v in values .values ()):
76+ return None
6277 rv = self .model ()
63- for c in self .columns :
64- if c in row :
65- rv .__values__ [c .name ] = row [c ]
78+ rv .__values__ .update (values )
6679 return rv
6780
6881 def do_load (self , row , context ):
@@ -72,22 +85,23 @@ def do_load(self, row, context):
7285 context = {}
7386 ctx = context .setdefault (self ._distinct , {})
7487 key = tuple (row [col ] for col in self ._distinct )
75- if key == (None ,) * len (key ):
76- return None , None
77- rv = ctx .get (key )
78- if rv is None :
79- rv = self ._do_load (row )
88+ rv = ctx .get (key , _none )
89+ if rv is _none :
90+ rv = self ._do_load (row , none_as_none = True )
8091 ctx [key ] = rv
8192 else :
8293 distinct = False
8394 else :
8495 rv = self ._do_load (row )
8596
86- for key , value in self .extras .items ():
87- value , distinct_ = value .do_load (row , context )
88- if distinct_ is not None :
89- setattr (rv , key , value )
90- return rv , distinct
97+ if rv is None :
98+ return None , None
99+ else :
100+ for key , value in self .extras .items ():
101+ value , distinct_ = value .do_load (row , context )
102+ if distinct_ is not None :
103+ setattr (rv , key , value )
104+ return rv , distinct
91105
92106 def get_columns (self ):
93107 yield from self .columns
@@ -118,6 +132,14 @@ def distinct(self, *columns):
118132 self ._distinct = columns
119133 return self
120134
135+ def none_as_none (self , enabled = True ):
136+ if not enabled :
137+ warnings .warn (
138+ 'The none_as_none feature will be always enabled in 0.9' ,
139+ PendingDeprecationWarning )
140+ self ._none_as_none = enabled
141+ return self
142+
121143
122144class AliasLoader (ModelLoader ):
123145 def __init__ (self , alias , * column_names , ** extras ):
0 commit comments