1
+ import warnings
2
+
1
3
from sqlalchemy import select
2
4
from sqlalchemy .schema import Column
3
5
@@ -46,6 +48,9 @@ def __getattr__(self, item):
46
48
return getattr (self .query , item )
47
49
48
50
51
+ _none = object ()
52
+
53
+
49
54
class ModelLoader (Loader ):
50
55
def __init__ (self , model , * column_names , ** extras ):
51
56
self .model = model
@@ -57,12 +62,20 @@ def __init__(self, model, *column_names, **extras):
57
62
self .extras = dict ((key , self .get (value ))
58
63
for key , value in extras .items ())
59
64
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
62
77
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 )
66
79
return rv
67
80
68
81
def do_load (self , row , context ):
@@ -72,22 +85,23 @@ def do_load(self, row, context):
72
85
context = {}
73
86
ctx = context .setdefault (self ._distinct , {})
74
87
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 )
80
91
ctx [key ] = rv
81
92
else :
82
93
distinct = False
83
94
else :
84
95
rv = self ._do_load (row )
85
96
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
91
105
92
106
def get_columns (self ):
93
107
yield from self .columns
@@ -118,6 +132,14 @@ def distinct(self, *columns):
118
132
self ._distinct = columns
119
133
return self
120
134
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
+
121
143
122
144
class AliasLoader (ModelLoader ):
123
145
def __init__ (self , alias , * column_names , ** extras ):
0 commit comments