From 703c5377e10526d275c5f2ad96abe60c08c2a79c Mon Sep 17 00:00:00 2001 From: StevanFreeborn Date: Fri, 15 Apr 2022 14:44:27 -0500 Subject: [PATCH] more work --- Enums.py | 1 + Models.py | 61 +++++ OnspringClient.py | 350 ++++++++++++++++++++---- UrlHelper.py | 25 +- __pycache__/ApiResponse.cpython-310.pyc | Bin 0 -> 504 bytes __pycache__/Enums.cpython-310.pyc | Bin 0 -> 372 bytes __pycache__/Models.cpython-310.pyc | Bin 0 -> 3177 bytes __pycache__/UrlHelper.cpython-310.pyc | Bin 649 -> 1041 bytes python.gitignore | 160 +++++++++++ 9 files changed, 549 insertions(+), 48 deletions(-) create mode 100644 Enums.py create mode 100644 Models.py create mode 100644 __pycache__/ApiResponse.cpython-310.pyc create mode 100644 __pycache__/Enums.cpython-310.pyc create mode 100644 __pycache__/Models.cpython-310.pyc create mode 100644 python.gitignore diff --git a/Enums.py b/Enums.py new file mode 100644 index 0000000..2151f26 --- /dev/null +++ b/Enums.py @@ -0,0 +1 @@ +from enum import Enum \ No newline at end of file diff --git a/Models.py b/Models.py new file mode 100644 index 0000000..c9a2eb7 --- /dev/null +++ b/Models.py @@ -0,0 +1,61 @@ +class ApiResponse: + def __init__(self, statusCode=None, data=None, message=None): + self.statusCode = statusCode + self.isSuccessful = int(statusCode) < 400 + self.data = data + self.message = message + +class PagingRequest: + def __init__(self, pageNumber, pageSize): + self.pageNumber = pageNumber + self.pageSize = pageSize + +class App: + def __init__(self, href, id, name): + self.href = href + self.id = id + self.name = name + +class GetAppsResponse: + def __init__(self, pageNumber, pageSize, totalPages, totalRecords, apps: list[App]): + self.pageNumber = pageNumber + self.pageSize = pageSize + self.totalPages = totalPages + self.totalRecords = totalRecords + self.apps = apps + +class GetAppByIdResponse: + def __init__(self, app: App): + self.app = app + +class GetAppsByIdsResponse: + def __init__(self, count, apps: list[App]): + self.count = count + self.apps = apps + +class Field: + def __init__(self, id, appId, name, type, status, isRequired, isUnique): + self.id = id + self.appId = appId + self.name = name + self.type = type + self.status = status + self.isRequired = isRequired + self.isUnique = isUnique + +class GetFieldByIdResponse: + def __init__(self, field: Field): + self.field = field + +class GetFieldsByIdsResponse: + def __init__(self, count, fields: list[Field]): + self.count = count + self.fields = fields + +class GetFieldsByAppIdResponse: + def __init__(self, pageNumber, pageSize, totalPages, totalRecords, fields: list[Field]): + self.pageNumber = pageNumber + self.pageSize = pageSize + self.totalPages = totalPages + self.totalRecords = totalRecords + self.fields = fields \ No newline at end of file diff --git a/OnspringClient.py b/OnspringClient.py index b38d77a..c09954b 100644 --- a/OnspringClient.py +++ b/OnspringClient.py @@ -1,6 +1,9 @@ +from dataclasses import fields import requests import json from UrlHelper import * +from Models import * + class OnspringClient: def __init__(self, url, key): @@ -9,83 +12,336 @@ class OnspringClient: 'x-apikey': key, 'x-api-version': '2' } - - # verify connectivity + + # connectivity methods def canConnect(self): - + endpoint = GetPingEndpoint(self.baseUrl) - response = requests.request('GET', endpoint, headers=self.headers) + response = requests.request( + 'GET', + endpoint, + headers=self.headers) return response.status_code == 200 - # apps + # app methods + + def GetApps(self, pagingRequest=PagingRequest(1, 50)): - def GetApps(self, pageNumber=1, pageSize=50): - endpoint = GetAppsEndpoint(self.baseUrl) - params={ - 'PageNumber': pageNumber, - 'PageSize': pageSize - } + params = pagingRequest.__dict__ - response = requests.request('GET', endpoint, headers=self.headers, params=params) + response = requests.request( + 'GET', + endpoint, + headers=self.headers, + params=params) - if(response.status_code == 400): - return {'Message': 'Invalid paging information.'} - - if(response.status_code == 401): - return {'Message': 'Unauthorized request.'} + if response.status_code == 400: + return ApiResponse( + response.status_code, + message='Invalid paging information') - return response.json() + if response.status_code == 401: + return ApiResponse( + response.status_code, + message='Unauthorized request') + + responseJson = response.json() + + apps = [] + + for item in responseJson['items']: + app = App( + item['href'], + item['id'], + item['name']) + + apps.append(app) + + data = GetAppsResponse( + responseJson['pageNumber'], + responseJson['pageSize'], + responseJson['totalPages'], + responseJson['totalRecords'], + apps) + + return ApiResponse( + response.status_code, + data) + + def GetAppById(self, appId: int): - def GetAppById(self, appId): - endpoint = GetAppByIdEndpoint(self.baseUrl, appId) - response = requests.request('GET', endpoint, headers=self.headers) + response = requests.request( + 'GET', + endpoint, + headers=self.headers) - if(response.status_code == 401): - return {'Message': 'Unauthorized request.'} - - if(response.status_code == 403): - return {'Message': 'Client does not have read access to the app.'} - - if(response.status_code == 404): - return {'Message': 'App could not be found.'} + if response.status_code == 401: + return ApiResponse( + response.status_code, + message='Unauthorized request' + ) - return response.json() + if response.status_code == 403: + return ApiResponse( + response.status_code, + message='Client does not have read access to the app' + ) - def GetAppByIds(self, appIds): + if response.status_code == 404: + return ApiResponse( + response.status_code, + message='App could not be found' + ) + responseJson = response.json() + + app = App( + responseJson['href'], + responseJson['id'], + responseJson['name']) + + data = GetAppByIdResponse(app) + + return ApiResponse( + response.status_code, + data + ) + + def GetAppByIds(self, appIds: list): + endpoint = GetAppByIdsEndpoint(self.baseUrl) - self.headers["Content-Type"] = "application/json" + self.headers['Content-Type'] = 'application/json' + + # make sure appIds can be serialized to json string + if not isinstance(appIds, (list, tuple)): + return ApiResponse( + 400, + message='App ids should be of type list or tuple') + + appIds = json.dumps(appIds) + + response = requests.request( + 'POST', + endpoint, + headers=self.headers, + data=appIds) + + if response.status_code == 401: + return ApiResponse( + response.status_code, + message='Unauthorized request' + ) + + if response.status_code == 403: + return ApiResponse( + response.status_code, + message='Client does not have read access to the app' + ) + + responseJson = response.json() + + apps = [] + + for item in responseJson['items']: + app = App( + item['href'], + item['id'], + item['name']) + + apps.append(app) + + data = GetAppsByIdsResponse( + responseJson['count'], + apps + ) + + return ApiResponse( + response.status_code, + data + ) + + # field methods + + def GetFieldById(self, fieldId: int): + + endpoint = GetFieldByIdEndpoint(self.baseUrl, fieldId) + + response = requests.request( + 'GET', + endpoint, + headers=self.headers) + + if response.status_code == 401: + return ApiResponse( + response.status_code, + message='Unauthorized request' + ) + + if response.status_code == 403: + return ApiResponse( + response.status_code, + message='Client does not have read access to the field' + ) + + if response.status_code == 404: + return ApiResponse( + response.status_code, + message='Field could not be found' + ) - if(not isinstance(appIds, (list, tuple))): - return {'Message': 'App ids should be of type list or tuple.'} - - data = json.dumps(appIds) + jsonResponse = response.json() - response = requests.request("POST", endpoint, headers=self.headers, data=data) + field = Field( + jsonResponse['id'], + jsonResponse['appId'], + jsonResponse['name'], + jsonResponse['type'], + jsonResponse['status'], + jsonResponse['isRequired'], + jsonResponse['isUnique'], + ) - if(response.status_code == 401): - return {'Message': 'Unauthorized request.'} - - if(response.status_code == 403): - return {'Message': 'Client does not have read access to the app.'} + data = GetFieldByIdResponse(field) - return response.json() + return ApiResponse( + response.status_code, + data + ) + def GetFieldsByIds(self, fieldIds: list): + + endpoint = GetFieldsByIdsEndpoint(self.baseUrl) + + self.headers['Content-Type'] = 'application/json' + + # make sure fieldIds can be serialized to json string + if not isinstance(fieldIds, (list, tuple)): + return ApiResponse( + 400, + message='Field ids should be of type list or tuple') + + fieldIds = json.dumps(fieldIds) + + response = requests.request( + 'POST', + endpoint, + headers=self.headers, + data=fieldIds) + + if response.status_code == 401: + return ApiResponse( + response.status_code, + message='Unauthorized request' + ) + + if response.status_code == 403: + return ApiResponse( + response.status_code, + message='Client does not have read access to the field(s)' + ) + + if response.status_code == 404: + return ApiResponse( + response.status_code, + message='Field(s) could not be found' + ) + + responseJson = response.json() + + fields = [] + + for item in responseJson['items']: + field = Field( + item['id'], + item['appId'], + item['name'], + item['type'], + item['status'], + item['isRequired'], + item['isUnique']) + + fields.append(field) + + data = GetFieldsByIdsResponse( + responseJson['count'], + fields + ) + + return ApiResponse( + response.status_code, + data + ) + + def GetFieldsByAppId(self, appId: int, pagingRequest=PagingRequest(1, 50)): + + endpoint = GetFieldsByAppIdEndpoint(self.baseUrl, appId) + + params = pagingRequest.__dict__ + + response = requests.request( + 'GET', + endpoint, + headers=self.headers, + params=params) + + if response.status_code == 400: + return ApiResponse( + response.status_code, + message='Invalid paging information') + + if response.status_code == 401: + return ApiResponse( + response.status_code, + message='Unauthorized request') + + responseJson = response.json() + + fields = [] + + for item in responseJson['items']: + field = Field( + item['id'], + item['appId'], + item['name'], + item['type'], + item['status'], + item['isRequired'], + item['isUnique']) + + fields.append(field) + + data = GetFieldsByAppIdResponse( + responseJson['pageNumber'], + responseJson['pageSize'], + responseJson['totalPages'], + responseJson['totalRecords'], + fields) + + return ApiResponse( + response.status_code, + data) + + # file methods + + # list methods + + # record methods + + # report methods - url = 'https://api.onspring.com' apiKey = '61642d8c686f9e8747e42af8/52cae9a9-4c49-48b6-a3fe-10a48d46ac69' -onspringClient = OnspringClient(url,apiKey) +onspringClient = OnspringClient(url, apiKey) -data = (8,) +response = onspringClient.GetFieldsByAppId(8) -print(onspringClient.GetAppByIds(data)) \ No newline at end of file +print() diff --git a/UrlHelper.py b/UrlHelper.py index 0cc8b18..8955ee3 100644 --- a/UrlHelper.py +++ b/UrlHelper.py @@ -1,6 +1,10 @@ +# connectivity endpoints + def GetPingEndpoint(baseUrl): return f'{baseUrl}/Ping' +# app endpoints + def GetAppsEndpoint(baseUrl): return f'{baseUrl}/Apps' @@ -8,4 +12,23 @@ def GetAppByIdEndpoint(baseUrl, appId): return f'{baseUrl}/Apps/id/{appId}' def GetAppByIdsEndpoint(baseUrl): - return f'{baseUrl}/Apps/batch-get' \ No newline at end of file + return f'{baseUrl}/Apps/batch-get' + +# field endpoints + +def GetFieldByIdEndpoint(baseUrl, fieldId): + return f'{baseUrl}/Fields/id/{fieldId}' + +def GetFieldsByIdsEndpoint(baseUrl): + return f'{baseUrl}/Fields/batch-get' + +def GetFieldsByAppIdEndpoint(baseUrl, appId): + return f'{baseUrl}/Fields/appId/{appId}' + +# file endpoints + +# list endpoints + +# record endpoints + +# report endpoints \ No newline at end of file diff --git a/__pycache__/ApiResponse.cpython-310.pyc b/__pycache__/ApiResponse.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a694d6419281a6b051a1f916a4bc8dd529cfb043 GIT binary patch literal 504 zcmY*U!AiqG5S`tvHPrS}Jd4*J>QxYtN)O(O*o%b160=)fO|x-#qf~NhKfvGc?BC=h z_!m7n(^7~7@6FC+=FN-k^*VsD`MH1i#{5e~GXxeRgzqEWfC9zVh!u}P@hJ>Miv54V zu^J)#F_MOuDTujZimxFSO5jebKDsW-e>Bm;-`rs|eN?i++hq!C}v`ka&{k+TuqHcMe%^lrvbnFXU z8`I`Iy_ikyJiI4PpWZtAtkd9U=&x`le;g)-85Ya%Wb;|W`dP88BPmU8f|MlbNvqA; ztj|7yDHQtICYtT`6D7B-?#)5$bG>HRzCf__ILpEu;v#Y}=U( WcDXT4P8_Y&(dF*Q)pn0;_Tdi<0dHOa literal 0 HcmV?d00001 diff --git a/__pycache__/Enums.cpython-310.pyc b/__pycache__/Enums.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f86659e3be901f249a5f108c89aca933030619b9 GIT binary patch literal 372 zcmYjNy-ve05I)B)L?zw&09`W_i4`H#1+kT?Wk69RD~$~lC9$y+Rh{8kka#7pOnn7d zxJ!}fN%#3a`@27z(P#*0A3qQ41)g6-j!ht$q5BDf0>vt*S;iRLf{GM>2gNme<5{G{ z3ev$IRgkhEZknzxi5we4GDG)c1PvKefQc;QD$0c7SU`kisl7Fg*Y`WC9cAnZ=IJ2B zQZ_}cr3^zUYooe~;zY{VuBiTAPVd$)x@>*m%VPTpj<)OJ`=Y$eSLU(Z7EVtV&h)Yz zJ6X4Bo~DJ}Ozp0HHcd{m`*XW<9FxiY2|^5l#jL-Zr#uLaDi=|ClKeM1L}z#x;;X}y N*R+ABuS{SZ{Q`q>QJDY$ literal 0 HcmV?d00001 diff --git a/__pycache__/Models.cpython-310.pyc b/__pycache__/Models.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..79541e0b26e8984f024361cb67813191da9b9b87 GIT binary patch literal 3177 zcma)8+in|07~ZoT$8nlNLrW=5TTTlkKsgE_lv0VR7nmv$7g&)jcW0e0IJPsh7E0v1 z_5pgyE96ahhPmYte8&~vH|zB}v7L6L`90sx?mz$k{fBXHWu;V=E>Kx40WAS}KozkJv<&0} zRmBR>3Qz!46RSY0Kqa7SVhv~ws0_3&Hh?yOmc-_P6<&{E)rB#!cMFeWt6>YP;lMIl zYByYA<11e;KkO&_vFi7_Dy~P~lm@OH%tx5&J&2(_w3=3G5A7GWu>Z7xoS_5h4qZr3 zSkUOylUKGy%@vil(t&!^6R~!aZrZ3O>R=E>u~O|pM|+}`wsh$juyquNp7vDSX-l3c zd9?H)&Mk>hSpPkUzCS$ZwbQ>^GTweFdw;}Hst#duUnbq7omM~D>7S<0d)>oda9l_2 z_D^-W*-W}g+H6v#DnkTz%?|8}eYQE}^ltuI=+^7?bC2J3TgP#;sVmLqaZe07TvwaT zlR>MK?Z_o)GnP#Wo*?16#i{5**{a#*$xLi$(jMk$6Jin@TR1N*M8*Y=o?dy{I)Zci z@yQ@oX~b~mgKMf_Xhzo{ve1}dAj}8Wxm^z(UFn0_`r!CkEOnXdgXAm@T^ZmDxlXY` zL54G7T%d29Bf4Pd+PYxLgs{3~!AyN_6d4_>*xc z@wB5R>m0f(*Z94wz2`D+YbO!fW1vDWbM-Ck${Q3nDdzag^A%|cvIMEZkT>y@CaqBC zbqb;x9~rAX%+b3LMW|yp_HJ5j$CRVj@P%i}arJSW;%t?dr1n}s5lzbn*OTDi1DNGx z=$WeY^Qz4F@r#)2O4>_X9mF+Ox@y+@anzGS$#D$TeIgD+=TumZeGL6`_M@q z#;mN{l1~=0BFPH+^X51>bbgX=CcF`IHXmH)-b?nHESVhbN4-He&GKd3Q$FGLq6FFI zCbQ)1_Pmn||K(l2SyXA!RzAjtNy7VlgJ{M}n!3l`aZB-kPU4P;*o^YQb?%Yc1-QC^ zh5^dRAC@44BIYI2P_&O^c_K_-(O!Dmk9Ck;d%BW<)RRFXW1-85`mLLwkB8+fM@%!? z!O>Yqq7m{liq9#&peXz|9hDuKVO8`iFR^i%)r^l*1Tsmd6chx0iVa@nS-&EhA&~Lj z<12h`oF+#9g(C6WhE~#;53X}s<%a-SqS*3Ftn=dFddjkiYsUGHuxXNG=DfnU+2WuV zi(AG6>>7GQzDBgz<8fhZAw7)+>OyJg!1%1*s5+!6g|Bg3e&0?W%yZw+Vrt{g{KE?Z zW;&<5N6)Ti;VZmC-{pM@qSvy(-kr068>wiJl3p#mk>qWjVD96o`$iV`hvDRk`-S`S zDEf}iw;|5%F0!m3Nq%!tOHl#eVuLedf~$I1F@Ms`UzDuXvYVPFYI;n@t)Y+1N%MJ8 jo)g`={6qG4@kjFykm0OZwNlNm1+{X`!*8YLt^5B2`CKKC literal 0 HcmV?d00001 diff --git a/__pycache__/UrlHelper.cpython-310.pyc b/__pycache__/UrlHelper.cpython-310.pyc index 5dfcd4526b35490b29595c98a809a27fcbd0ab29..bc902cabb1ec752fe9106591d9c6281f28bf8485 100644 GIT binary patch delta 457 zcmeBVoyftL&&$ij00b__Ba?ENCi2NJ+Dz0|l}X`jVTfW$;Y#5K(yS>wDZD_MErllw$qN6#XKQ3QeXW79e$tJq;x8nF1Ds z5Ue0^5%<&*uokCE&lK0Zl!E-syb@ucOc5`TU@8)r_(_#r5Mt`&Ka8sNVlWNGARWap zEn*-oV226Xhli`YOM l4iLcuBEW$s0AhjMR3tPxoJmaxB*?+U!OFo5gg}yq8325GSjhkY delta 136 zcmbQp(aFk}&&$ij00c3!Ba);UC-TWKs!Y^YWeH}`g&jGpaIbPF~Asz{?KQRm=n=_!x`0CZA(coy^Z