1- test_data = {
2- "data" : [
3- {
4- "6" : {
5- "value" : "Andre Harris"
6- },
7- "7" : {
8- "value" : 10
9- },
10- "8" : {
11- "value" : "2019-12-18T08:00:00.000Z"
12- }
13- }
14- ],
15- "fields" : [
16- {
17- "id" : 6 ,
18- "label" : "Full Name" ,
19- "type" : "text"
20- },
21- {
22- "id" : 7 ,
23- "label" : "Amount" ,
24- "type" : "numeric"
25- },
26- {
27- "id" : 8 ,
28- "label" : "Date time" ,
29- "type" : "date time"
30- }
31- ],
32- "metadata" : {
33- "totalRecords" : 10 ,
34- "numRecords" : 1 ,
35- "numFields" : 3 ,
36- "skip" : 0
37- }
38- }
1+ import datetime
2+
3+
4+ class bcolors :
5+ HEADER = '\033 [95m'
6+ OKBLUE = '\033 [94m'
7+ OKCYAN = '\033 [96m'
8+ OKGREEN = '\033 [92m'
9+ WARNING = '\033 [93m'
10+ FAIL = '\033 [91m'
11+ ENDC = '\033 [0m'
12+ BOLD = '\033 [1m'
13+ UNDERLINE = '\033 [4m'
3914
4015
4116class QBResponse (dict ):
42- def __init__ (self , response_type ):
17+ def __init__ (self , response_type , ** kwargs ):
4318 self .response_type = response_type
19+ self .transformations = {}
20+ # potential to load sample data for testing
21+ if kwargs .get ('sample_data' ):
22+ self .update (kwargs .get ('sample_data' ))
4423 super ().__init__ ()
4524
25+ def info (self ):
26+ """
27+ Prints information about the response.
28+ """
29+ if self .response_type == 'records' :
30+
31+ print (f'{ bcolors .OKBLUE } Sample Data:\n ' )
32+ try :
33+ print ('\t ' , self .get ('data' )[0 ], '\n ' )
34+ except KeyError as e :
35+ print ('\t ' , self .get ('data' ), '\n ' )
36+ print (bcolors .ENDC )
37+ print (f'{ bcolors .OKGREEN } Fields:\n ' )
38+
39+ fields_info = []
40+ for field in self .get ('fields' ):
41+ field_info = []
42+ # build field info
43+ for k , v in field .items ():
44+ field_info .append (f'{ k } : { v } ' )
45+ fields_info .append (field_info )
46+
47+ # print field info
48+ for fi in fields_info :
49+ print ('\t ' , '{:<16s} {:<32s} {:<16s}' .format (fi [0 ], fi [1 ], fi [2 ]))
50+ print (bcolors .ENDC )
51+
52+ print (f'\n { bcolors .OKCYAN } Metadata:\n ' )
53+ for k , v in self .get ('metadata' ).items ():
54+ print ('\t {:<16s} {:<16s}' .format (k , str (v )))
55+ print (bcolors .ENDC )
56+
57+ def fields (self , prop ):
58+ """
59+ Gets fields, given property, i.e. label, id or type
60+ :param prop: property of field
61+ :return: list of fields
62+ """
63+ return [i .get (prop ) for i in self .get ('fields' )]
64+
65+ def data (self ):
66+ return self .get ('data' )
67+
68+ def prd (self , data ):
69+ """
70+ Print relevant data, simple print function.
71+ :param data: data to print
72+ """
73+ print ("\033 [91m" , 'Relevant Data:\n \n ' , data , '\n ' , "\033 [0m" )
74+
4675 def denest (self ):
47- denested_list = []
48- for record in self .get ('data' ):
49- denested = {}
50- for k , v in record .items ():
51- denested .update ({k : v .get ('value' )})
52- denested_list .append (denested )
53- self .update ({'data' : denested_list })
76+ """
77+ Denests data, i.e. if in {'key': {'value': actual_value}} format. -> {'key': actual_value}
78+ :return: QBResponse
79+ """
80+ data = self .get ('data' )
81+ # ugly handling for now, need to fix
82+ if type (data ) is dict :
83+ new_records = {}
84+ for record , record_value in data .items ():
85+ new_record_value = {}
86+ for k , v in record_value .items ():
87+ new_record = {}
88+ new_record .update ({k : v .get ('value' )})
89+ new_record_value .update (new_record )
90+ new_records .update ({record : new_record_value })
91+
92+ self .update ({'data' : new_records })
5493 return self
5594
5695 def orient (self , orient , ** kwargs ):
57-
96+ """
97+ Orients the data, given orientation argument.
98+ :param orient: type of orientation, 'records' is the only orientation for now.
99+ :param kwargs: 'records' argument needs 'key' argument, to determine key for records.
100+ :return: QBResponse
101+ """
58102 if orient == 'records' :
59103 if not kwargs .get ('key' ):
60104 raise ValueError ('Missing required "key" argument for records orientation' )
@@ -67,10 +111,23 @@ def orient(self, orient, **kwargs):
67111
68112 # loop data list, create dict
69113 records = {}
70- for i in self .get ('data' ):
71- print (i )
72- key = i .pop (selector ).get ('value' ) if self .get ('data' ) else i .pop (selector )
73- records .update ({key : i })
114+ try :
115+ for i in self .get ('data' ):
116+ key = i .pop (selector ).get ('value' ) if self .get ('data' ) else i .pop (selector )
117+ records .update ({key : i })
118+ except KeyError as e :
119+ print ('KeyError:' , e , 'Attempting to use Record ID#' )
120+ self .prd (self .get ('data' )[0 ])
121+
122+ # attempt to find selector in fields
123+ for i in self .get ('fields' ):
124+ if i .get ('id' ) == int (selector ):
125+ selector = i .get ('label' )
126+ break
127+
128+ for i in self .get ('data' ):
129+ key = i .pop (selector )
130+ records .update ({key : i })
74131
75132 # set data to records
76133 self .update ({'data' : records })
@@ -84,6 +141,11 @@ def currency(self, currency_type):
84141 return self
85142
86143 def transform (self , transformation ):
144+ """
145+ Transforms the data, given a transformation argument.
146+ :param transformation: type of transformation.
147+ :return: QBResponse
148+ """
87149 if transformation == 'labels' :
88150
89151 # transform fids into labels
@@ -92,61 +154,60 @@ def transform(self, transformation):
92154 'Try transforming the data before applying additional methods.' )
93155
94156 data = self .get ('data' )
95- print (data )
96157 fields = self .get ('fields' )
97158
98159 fields_dict = {i ['id' ]: i for i in fields }
99160
161+ # replace record id numbers with record labels
100162 records = []
101163 for idx , d in enumerate (data ):
102164 record = {}
103- print ('data' , d )
104165 for k , v in d .items ():
105166 record .update ({
106167 fields_dict [int (k )].get ('label' ): v if v .get ('value' ) is None else v .get ('value' )
107168 })
108- records .append (record )
109- print (k , v )
110169
170+ records .append (record )
111171 self .update ({'data' : records })
112172
113- return self
173+ if transformation == 'datetime' :
174+ """Finds columns that are of type datetime and converts them into python datetime objects"""
175+ # transform fids into labels
176+
177+ data = self .get ('data' )
178+ fields = self .get ('fields' )
114179
180+ for field in fields :
181+ if field .get ('type' ) == 'date time' :
115182
116- qbr = QBResponse ('records' )
117- qbr .update (test_data )
118- qbr .transform ('labels' ).orient ('records' , key = 6 )
119-
120- print (qbr )
121-
122- # # handle transform
123- # if kwargs.get('transform'):
124- # # labels
125- # if kwargs.get('transform') == 'labels':
126- #
127- # # transform fids into labels
128- # data = json_data.get('data')
129- # fields = json_data.get('fields')
130- #
131- # fields_dict = {i['id']: i for i in fields}
132- # print(fields_dict)
133- #
134- # records = []
135- # for idx, d in enumerate(data):
136- # record = {}
137- # print('data', d)
138- # for k, v in d.items():
139- # record.update({
140- # fields_dict[int(k)].get('label'): v if kwargs.get('denested') else v.get('value')
141- # })
142- # records.append(record)
143- # print(k, v)
144- #
145- # json_data.update({'data': records})
146- #
147-
148- #
149- # # handle data orientation
150- # if kwargs.get('orient'):
151- # if kwargs.get('orient') == 'records':
152- #
183+ if type (self .get ('data' ) == list ):
184+ for row in data :
185+ dt_field = row .get (str (field .get ('id' )))
186+ if dt_field .get ('value' ) is None :
187+ str_dt = dt_field
188+ dt = datetime .datetime .strptime (str_dt , '%Y-%m-%dT%H:%M:%S.%fZ' )
189+ row .update ({str (field .get ('id' )): dt })
190+ else :
191+ str_dt = dt_field .get ('value' )
192+ dt = datetime .datetime .strptime (str_dt , '%Y-%m-%dT%H:%M:%S.%fZ' )
193+ row .update ({str (field .get ('id' )): {'value' : dt }})
194+
195+ if transformation == 'intround' :
196+ """Rounds numbers and transforms them to ints"""
197+
198+ data = self .get ('data' )
199+ fields = self .get ('fields' )
200+
201+ for field in fields :
202+ if field .get ('type' ) == 'numeric' :
203+
204+ if type (self .get ('data' ) == list ):
205+ for row in data :
206+ numeric_field = row .get (str (field .get ('id' )))
207+ if numeric_field .get ('value' ) is None :
208+ row .update ({str (field .get ('id' )): int (round (numeric_field ))})
209+ else :
210+ numeric_field = numeric_field .get ('value' )
211+ row .update ({str (field .get ('id' )): {'value' : int (round (numeric_field ))}})
212+
213+ return self
0 commit comments