1
- from pynamodb .constants import (
2
- AND , BETWEEN , BINARY_SHORT , IN , NUMBER_SHORT , OR , SHORT_ATTR_TYPES , STRING_SHORT
3
- )
4
- from pynamodb .expressions .util import get_value_placeholder , substitute_names
1
+ from pynamodb .constants import AND , BETWEEN , IN , OR
5
2
from six .moves import range
6
3
7
4
@@ -12,38 +9,19 @@ def size(path):
12
9
13
10
14
11
class Condition (object ):
15
- format_string = '{path} {operator} {0} '
12
+ format_string = ''
16
13
17
- def __init__ (self , path , operator , * values ):
18
- self .path = path
14
+ def __init__ (self , operator , * values ):
19
15
self .operator = operator
20
16
self .values = values
21
17
22
18
# http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html#DDB-Query-request-KeyConditionExpression
23
19
def is_valid_range_key_condition (self , path ):
24
- return str ( self .path ) == path and self . operator in ['=' , '<' , '<=' , '>' , '>=' , BETWEEN , 'begins_with' ]
20
+ return self .operator in ['=' , '<' , '<=' , '>' , '>=' , BETWEEN , 'begins_with' ] and str ( self . values [ 0 ]) == path
25
21
26
22
def serialize (self , placeholder_names , expression_attribute_values ):
27
- path = self ._get_path (self .path , placeholder_names )
28
- values = self ._get_values (placeholder_names , expression_attribute_values )
29
- return self .format_string .format (* values , path = path , operator = self .operator )
30
-
31
- def _get_path (self , path , placeholder_names ):
32
- from pynamodb .expressions .operand import Path , Size
33
- if isinstance (path , Path ):
34
- return substitute_names (path .path , placeholder_names )
35
- elif isinstance (path , Size ):
36
- return "size ({0})" .format (self ._get_path (path .path , placeholder_names ))
37
- else :
38
- return path
39
-
40
- def _get_values (self , placeholder_names , expression_attribute_values ):
41
- return [
42
- value .serialize (placeholder_names , expression_attribute_values )
43
- if isinstance (value , Condition )
44
- else get_value_placeholder (value , expression_attribute_values )
45
- for value in self .values
46
- ]
23
+ values = [value .serialize (placeholder_names , expression_attribute_values ) for value in self .values ]
24
+ return self .format_string .format (* values , operator = self .operator )
47
25
48
26
def __and__ (self , other ):
49
27
if not isinstance (other , Condition ):
@@ -61,8 +39,8 @@ def __invert__(self):
61
39
return Not (self )
62
40
63
41
def __repr__ (self ):
64
- values = [repr (value ) if isinstance ( value , Condition ) else list ( value . items ())[ 0 ][ 1 ] for value in self .values ]
65
- return self .format_string .format (* values , path = self . path , operator = self .operator )
42
+ values = [str (value ) for value in self .values ]
43
+ return self .format_string .format (* values , operator = self .operator )
66
44
67
45
def __nonzero__ (self ):
68
46
# Prevent users from accidentally comparing the condition object instead of the attribute instance
@@ -73,77 +51,80 @@ def __bool__(self):
73
51
raise TypeError ("unsupported operand type(s) for bool: {0}" .format (self .__class__ .__name__ ))
74
52
75
53
54
+ class Comparison (Condition ):
55
+ format_string = '{0} {operator} {1}'
56
+
57
+ def __init__ (self , operator , lhs , rhs ):
58
+ if operator not in ['=' , '<>' , '<' , '<=' , '>' , '>=' ]:
59
+ raise ValueError ("{0} is not a valid comparison operator: {0}" .format (operator ))
60
+ super (Comparison , self ).__init__ (operator , lhs , rhs )
61
+
62
+
76
63
class Between (Condition ):
77
- format_string = '{path } {operator} {0 } AND {1 }'
64
+ format_string = '{0 } {operator} {1 } AND {2 }'
78
65
79
66
def __init__ (self , path , lower , upper ):
80
- super (Between , self ).__init__ (path , BETWEEN , lower , upper )
67
+ super (Between , self ).__init__ (BETWEEN , path , lower , upper )
81
68
82
69
83
70
class In (Condition ):
84
71
def __init__ (self , path , * values ):
85
- super (In , self ).__init__ (path , IN , * values )
86
- list_format = ', ' .join ('{' + str (i ) + '}' for i in range (len (values )))
87
- self .format_string = '{path } {operator} (' + list_format + ')'
72
+ super (In , self ).__init__ (IN , path , * values )
73
+ list_format = ', ' .join ('{' + str (i + 1 ) + '}' for i in range (len (values )))
74
+ self .format_string = '{0 } {operator} (' + list_format + ')'
88
75
89
76
90
77
class Exists (Condition ):
91
- format_string = '{operator} ({path })'
78
+ format_string = '{operator} ({0 })'
92
79
93
80
def __init__ (self , path ):
94
- super (Exists , self ).__init__ (path , 'attribute_exists' )
81
+ super (Exists , self ).__init__ ('attribute_exists' , path )
95
82
96
83
97
84
class NotExists (Condition ):
98
- format_string = '{operator} ({path })'
85
+ format_string = '{operator} ({0 })'
99
86
100
87
def __init__ (self , path ):
101
- super (NotExists , self ).__init__ (path , 'attribute_not_exists' )
88
+ super (NotExists , self ).__init__ ('attribute_not_exists' , path )
102
89
103
90
104
91
class IsType (Condition ):
105
- format_string = '{operator} ({path }, {0 })'
92
+ format_string = '{operator} ({0 }, {1 })'
106
93
107
94
def __init__ (self , path , attr_type ):
108
- if attr_type not in SHORT_ATTR_TYPES :
109
- raise ValueError ("{0} is not a valid attribute type. Must be one of {1}" .format (
110
- attr_type , SHORT_ATTR_TYPES ))
111
- super (IsType , self ).__init__ (path , 'attribute_type' , {STRING_SHORT : attr_type })
95
+ super (IsType , self ).__init__ ('attribute_type' , path , attr_type )
112
96
113
97
114
98
class BeginsWith (Condition ):
115
- format_string = '{operator} ({path }, {0 })'
99
+ format_string = '{operator} ({0 }, {1 })'
116
100
117
101
def __init__ (self , path , prefix ):
118
- super (BeginsWith , self ).__init__ (path , 'begins_with' , prefix )
102
+ super (BeginsWith , self ).__init__ ('begins_with' , path , prefix )
119
103
120
104
121
105
class Contains (Condition ):
122
- format_string = '{operator} ({path }, {0 })'
106
+ format_string = '{operator} ({0 }, {1 })'
123
107
124
- def __init__ (self , path , item ):
125
- (attr_type , value ), = item .items ()
126
- if attr_type not in [BINARY_SHORT , NUMBER_SHORT , STRING_SHORT ]:
127
- raise ValueError ("{0} must be a string, number, or binary element" .format (value ))
128
- super (Contains , self ).__init__ (path , 'contains' , item )
108
+ def __init__ (self , path , operand ):
109
+ super (Contains , self ).__init__ ('contains' , path , operand )
129
110
130
111
131
112
class And (Condition ):
132
113
format_string = '({0} {operator} {1})'
133
114
134
115
def __init__ (self , condition1 , condition2 ):
135
- super (And , self ).__init__ (None , AND , condition1 , condition2 )
116
+ super (And , self ).__init__ (AND , condition1 , condition2 )
136
117
137
118
138
119
class Or (Condition ):
139
120
format_string = '({0} {operator} {1})'
140
121
141
122
def __init__ (self , condition1 , condition2 ):
142
- super (Or , self ).__init__ (None , OR , condition1 , condition2 )
123
+ super (Or , self ).__init__ (OR , condition1 , condition2 )
143
124
144
125
145
126
class Not (Condition ):
146
127
format_string = '({operator} {0})'
147
128
148
129
def __init__ (self , condition ):
149
- super (Not , self ).__init__ (None , 'NOT' , condition )
130
+ super (Not , self ).__init__ ('NOT' , condition )
0 commit comments