Skip to content

Commit 2c9460e

Browse files
committed
0.0.4 - test fixes, denest fix, conversions
1 parent e2540d5 commit 2c9460e

File tree

2 files changed

+103
-28
lines changed

2 files changed

+103
-28
lines changed

src/quickbase_json/qb_response.py

Lines changed: 64 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import datetime
2+
from functools import wraps
23

34

45
class Bcolors:
@@ -13,10 +14,20 @@ class Bcolors:
1314
UNDERLINE = '\033[4m'
1415

1516

17+
def operation(method):
18+
@wraps(method)
19+
def wrapper(self, *args, **kwargs):
20+
self.operations.append(method.__name__)
21+
return method(self, *args, **kwargs)
22+
23+
return wrapper
24+
25+
1626
class QBResponse(dict):
27+
1728
def __init__(self, response_type, **kwargs):
1829
self.response_type = response_type
19-
self.transformations = {}
30+
self.operations = []
2031
# potential to load sample data for testing
2132
if kwargs.get('sample_data'):
2233
self.update(kwargs.get('sample_data'))
@@ -84,6 +95,7 @@ def prd(self, data):
8495
"""
8596
print("\033[91m", 'Relevant Data:\n\n', data, '\n', "\033[0m")
8697

98+
@operation
8799
def denest(self):
88100
"""
89101
Denests data, i.e. if in {'key': {'value': actual_value}} format. -> {'key': actual_value}
@@ -102,8 +114,16 @@ def denest(self):
102114
new_records.update({record: new_record_value})
103115

104116
self.update({'data': new_records})
117+
118+
if type(data) is list:
119+
for d in data:
120+
for k, v in d.items():
121+
d.update({k: v.get('value')})
122+
123+
print('++++', self.data)
105124
return self
106125

126+
@operation
107127
def orient(self, orient, **kwargs):
108128
"""
109129
Orients the data, given orientation argument.
@@ -125,7 +145,10 @@ def orient(self, orient, **kwargs):
125145
records = {}
126146
try:
127147
for i in self.get('data'):
128-
key = i.pop(selector).get('value') if self.get('data') else i.pop(selector)
148+
if 'denest' in self.operations:
149+
key = i.pop(selector)
150+
else:
151+
key = i.pop(selector).get('value')
129152
records.update({key: i})
130153
except KeyError as e:
131154
print('KeyError:', e, 'Attempting to use Record ID#')
@@ -182,41 +205,55 @@ def transform(self, transformation, **kwargs):
182205
records.append(record)
183206
self.update({'data': records})
184207

185-
if transformation == 'datetime':
186-
"""Finds columns that are of type datetime and converts them into python datetime objects"""
187-
# transform fids into labels
208+
if transformation == 'intround':
209+
"""Rounds numbers and transforms them to ints"""
188210

189211
data = self.get('data')
190212
fields = self.get('fields')
191213

192214
for field in fields:
193-
if field.get('type') == 'date time':
194-
if type(self.get('data') == list):
195-
for row in data:
196-
dt_field = row.get(str(field.get('id')))
197-
if dt_field.get('value') is None:
198-
str_dt = dt_field
199-
dt = datetime.datetime.strptime(str_dt, '%Y-%m-%dT%H:%M:%S.%fZ')
200-
row.update({str(field.get('id')): dt})
201-
else:
202-
str_dt = dt_field.get('value')
203-
dt = datetime.datetime.strptime(str_dt, '%Y-%m-%dT%H:%M:%S.%fZ')
204-
row.update({str(field.get('id')): {'value': dt}})
215+
if field.get('type') == 'numeric':
205216

206-
if field.get('type') == 'date':
207217
if type(self.get('data') == list):
208218
for row in data:
209-
dt_field = row.get(str(field.get('id')))
210-
if dt_field.get('value') is None:
211-
str_dt = dt_field
212-
dt = datetime.datetime.strptime(str_dt, kwargs.get('datestring'))
213-
row.update({str(field.get('id')): dt})
219+
numeric_field = row.get(str(field.get('id')))
220+
if numeric_field.get('value') is None:
221+
row.update({str(field.get('id')): int(round(numeric_field))})
214222
else:
215-
str_dt = dt_field.get('value')
216-
dt = datetime.datetime.strptime(str_dt, kwargs.get('datestring'))
217-
row.update({str(field.get('id')): {'value': dt}})
223+
numeric_field = numeric_field.get('value')
224+
row.update({str(field.get('id')): {'value': int(round(numeric_field))}})
218225

219-
if transformation == 'intround':
226+
return self
227+
228+
def convert_type(self, field_type, **kwargs):
229+
"""
230+
Converts data of certain field types to standard python objects
231+
:param field_type:
232+
:param kwargs:
233+
:return:
234+
"""
235+
236+
def c_datetime():
237+
238+
for f in self.get('fields'):
239+
fid = str(f.get('id'))
240+
if f.get('type') == 'date time':
241+
242+
if 'denest' in self.operations:
243+
for d in self.get('data'):
244+
print('>>>>>>>>', self.operations, d)
245+
d.update({fid: datetime.datetime.strptime(d.get(fid), '%Y-%m-%dT%H:%M:%S.%fZ')})
246+
else:
247+
for d in self.get('data'):
248+
print('>>>>>>>>', fid, d.get(fid), d)
249+
d.update({fid: {'value': datetime.datetime.strptime(d.get(fid).get('value'), '%Y-%m-%dT%H:%M:%S.%fZ')}})
250+
251+
252+
253+
if field_type == 'datetime':
254+
c_datetime()
255+
256+
if field_type == 'intround':
220257
"""Rounds numbers and transforms them to ints"""
221258

222259
data = self.get('data')

tests/test_response.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
import datetime
2+
13
import pytest
24

35
# test where
46
from src.quickbase_json.qb_response import QBResponse
57
from src.quickbase_json.helpers import Where, IncorrectParameters
68
from tests import sample_data
9+
from copy import deepcopy
710

811

912
# test loading in data
@@ -16,4 +19,39 @@ def test_load(data, expected):
1619

1720
# test getting info, basic tests, does not test formatting
1821
def test_get_info():
19-
assert "{'6': {'value': 'Andre Harris'}, '7': {'value': 10}, '8': {'value': '2019-12-18T08:00:00.000Z'}}" in QBResponse('records', sample_data=sample_data.record_data).info(prt=False)
22+
assert "{'6': {'value': 'Andre Harris'}, '7': {'value': 10}, '8': {'value': '2019-12-18T08:00:00.000Z'}}" in QBResponse(
23+
'records', sample_data=sample_data.record_data.copy()).info(prt=False)
24+
25+
26+
# test getting info, basic tests, does not test formatting
27+
def test_denest():
28+
res = QBResponse('records', sample_data=deepcopy(sample_data.record_data))
29+
res.denest()
30+
assert res.data() == [{'8': '2019-12-18T08:00:00.000Z', '6': 'Andre Harris', '7': 10}]
31+
32+
33+
# test datetime convert
34+
def test_convert_datetime():
35+
# test datetime convert w/o denest
36+
res = QBResponse('records', sample_data=deepcopy(sample_data.record_data))
37+
res.convert_type('datetime')
38+
dt_test = res.data()[0].get('8').get('value')
39+
40+
# test datetime convert w/ denest
41+
res2 = QBResponse('records', sample_data=deepcopy(sample_data.record_data))
42+
res2.denest()
43+
res2.convert_type('datetime')
44+
dt_test2 = res2.data()[0].get('8')
45+
46+
# make sure both are datetime
47+
assert isinstance(dt_test, datetime.datetime)
48+
assert isinstance(dt_test2, datetime.datetime)
49+
50+
51+
def test_operations():
52+
res = QBResponse('records', sample_data=sample_data.record_data)
53+
assert res.operations == []
54+
res.denest()
55+
assert res.operations == ['denest']
56+
res.orient('records', key=6)
57+
assert res.operations == ['denest', 'orient']

0 commit comments

Comments
 (0)