@@ -58,6 +58,7 @@ def _record_from_json(value, field):
5858def _string_from_json (value , _ ):
5959 return value
6060
61+
6162_CELLDATA_FROM_JSON = {
6263 'INTEGER' : _int_from_json ,
6364 'FLOAT' : _float_from_json ,
@@ -81,3 +82,73 @@ def _rows_from_json(rows, schema):
8182 row_data .append (converter (cell ['v' ], field ))
8283 rows_data .append (tuple (row_data ))
8384 return rows_data
85+
86+
87+ class _ConfigurationProperty (object ):
88+ """Base property implementation.
89+
90+ Values will be stored on a `_configuration` helper attribute of the
91+ property's job instance.
92+
93+ :type name: string
94+ :param name: name of the property
95+ """
96+
97+ def __init__ (self , name ):
98+ self .name = name
99+ self ._backing_name = '_%s' % (self .name ,)
100+
101+ def __get__ (self , instance , owner ):
102+ """Descriptor protocal: accesstor"""
103+ if instance is None :
104+ return self
105+ return getattr (instance ._configuration , self ._backing_name )
106+
107+ def _validate (self , value ):
108+ """Subclasses override to impose validation policy."""
109+ pass
110+
111+ def __set__ (self , instance , value ):
112+ """Descriptor protocal: mutator"""
113+ self ._validate (value )
114+ setattr (instance ._configuration , self ._backing_name , value )
115+
116+ def __delete__ (self , instance ):
117+ """Descriptor protocal: deleter"""
118+ delattr (instance ._configuration , self ._backing_name )
119+
120+
121+ class _TypedProperty (_ConfigurationProperty ):
122+ """Property implementation: validates based on value type.
123+
124+ :type name: string
125+ :param name: name of the property
126+
127+ :type property_type: type or sequence of types
128+ :param property_type: type to be validated
129+ """
130+ def __init__ (self , name , property_type ):
131+ super (_TypedProperty , self ).__init__ (name )
132+ self .property_type = property_type
133+
134+ def _validate (self , value ):
135+ if not isinstance (value , self .property_type ):
136+ raise ValueError ('Required type: %s' % (self .property_type ,))
137+
138+
139+ class _EnumProperty (_ConfigurationProperty ):
140+ """Psedo-enumeration class.
141+
142+ Subclasses must define ``ALLOWED`` as a class-level constant: it must
143+ be a sequence of strings.
144+
145+ :type name: string
146+ :param name: name of the property
147+ """
148+ def _validate (self , value ):
149+ """Check that ``value`` is one of the allowed values.
150+
151+ :raises: ValueError if value is not allowed.
152+ """
153+ if value not in self .ALLOWED :
154+ raise ValueError ('Pass one of: %s' ', ' .join (self .ALLOWED ))
0 commit comments