1+ from __future__ import annotations
2+
13from abc import ABC
24from dataclasses import dataclass
35
4- from conSys4Py import APIResourceTypes , APITerms
6+ from pydantic import BaseModel , Field
7+
8+ from conSys4Py import APIResourceTypes , APITerms , EncodingSchema
59from conSys4Py .con_sys_api import ConnectedSystemAPIRequest
610
711
@@ -73,30 +77,35 @@ def resource_type_to_endpoint(res_type: APIResourceTypes, parent_type: APIResour
7377@dataclass
7478class APIHelper (ABC ):
7579 server_url = None
76- api_endpoint = "/api"
80+ api_root = "/api"
7781 username = None
7882 password = None
7983 user_auth = False
8084
8185 def create_resource (self , res_type : APIResourceTypes , json_data : any , parent_res_id : str = None ,
82- from_collection : bool = False ):
86+ from_collection : bool = False , url_endpoint : str = None ):
8387 """
8488 Creates a resource of the given type with the given data, will attempt to create a sub-resource if parent_res_id
8589 is provided.
8690 :param res_type:
8791 :param json_data:
8892 :param parent_res_id:
8993 :param from_collection:
94+ :param url_endpoint: If given, will override the default URL construction. Should contain the endpoint past the API root.
9095 :return:
9196 """
92- url = self .resource_url_resolver (res_type , None , parent_res_id , from_collection )
97+
98+ if url_endpoint is None :
99+ url = self .resource_url_resolver (res_type , None , parent_res_id , from_collection )
100+ else :
101+ url = f'{ self .server_url } /{ self .api_root } /{ url_endpoint } '
93102 api_request = ConnectedSystemAPIRequest (url = url , request_method = 'POST' , auth = self .get_helper_auth (),
94103 body = json_data )
95104 return api_request .make_request ()
96105
97106 def retrieve_resource (self , res_type : APIResourceTypes , res_id : str , parent_res_id : str = None ,
98107 from_collection : bool = False ,
99- collection_id : str = None ):
108+ collection_id : str = None , url_endpoint : str = None ):
100109 """
101110 Retrieves a resource or list of resources if no res_id is provided, will attempt to retrieve a sub-resource if
102111 parent_res_id is provided.
@@ -105,14 +114,18 @@ def retrieve_resource(self, res_type: APIResourceTypes, res_id: str, parent_res_
105114 :param parent_res_id:
106115 :param from_collection:
107116 :param collection_id:
117+ :param url_endpoint: If given, will override the default URL construction. Should contain the endpoint past the API root.
108118 :return:
109119 """
110- url = self .resource_url_resolver (res_type , res_id , parent_res_id , from_collection )
120+ if url_endpoint is None :
121+ url = self .resource_url_resolver (res_type , None , parent_res_id , from_collection )
122+ else :
123+ url = f'{ self .server_url } /{ self .api_root } /{ url_endpoint } '
111124 api_request = ConnectedSystemAPIRequest (url = url , request_method = 'GET' , auth = self .get_helper_auth ())
112125 return api_request .make_request ()
113126
114127 def update_resource (self , res_type : APIResourceTypes , res_id : str , json_data : any , parent_res_id : str = None ,
115- from_collection : bool = False ):
128+ from_collection : bool = False , url_endpoint : str = None ):
116129 """
117130 Updates a resource of the given type by its id, if necessary, will attempt to update a sub-resource if
118131 parent_res_id is provided.
@@ -121,31 +134,48 @@ def update_resource(self, res_type: APIResourceTypes, res_id: str, json_data: an
121134 :param json_data:
122135 :param parent_res_id:
123136 :param from_collection:
137+ :param url_endpoint: If given, will override the default URL construction. Should contain the endpoint past the API root.
124138 :return:
125139 """
126- url = self .resource_url_resolver (res_type , None , parent_res_id , from_collection )
140+ if url_endpoint is None :
141+ url = self .resource_url_resolver (res_type , None , parent_res_id , from_collection )
142+ else :
143+ url = f'{ self .server_url } /{ self .api_root } /{ url_endpoint } '
127144 api_request = ConnectedSystemAPIRequest (url = url , request_method = 'PUT' , auth = self .get_helper_auth (),
128145 body = json_data )
129146 return api_request .make_request ()
130147
131148 def delete_resource (self , res_type : APIResourceTypes , res_id : str , parent_res_id : str = None ,
132- from_collection : bool = False ):
149+ from_collection : bool = False , url_endpoint : str = None ):
133150 """
134151 Deletes a resource of the given type by its id, if necessary, will attempt to delete a sub-resource if
135152 parent_res_id is provided.
136153 :param res_type:
137154 :param res_id:
138155 :param parent_res_id:
139156 :param from_collection:
157+ :param url_endpoint: If given, will override the default URL construction. Should contain the endpoint past the API root.
140158 :return:
141159 """
142- url = self .resource_url_resolver (res_type , res_id , parent_res_id , from_collection )
160+ if url_endpoint is None :
161+ url = self .resource_url_resolver (res_type , None , parent_res_id , from_collection )
162+ else :
163+ url = f'{ self .server_url } /{ self .api_root } /{ url_endpoint } '
143164 api_request = ConnectedSystemAPIRequest (url = url , request_method = 'DELETE' , auth = self .get_helper_auth ())
144165 return api_request .make_request ()
145166
146167 # Helpers
147168 def resource_url_resolver (self , res_type : APIResourceTypes , res_id : str = None , parent_res_id : str = None ,
148169 from_collection : bool = False ):
170+ """
171+ Helper to generate a URL endpoint for a given resource type and id by matching the resource type to an
172+ appropriate parent endpoint and inserting the resource ids as necessary.
173+ :param res_type:
174+ :param res_id:
175+ :param parent_res_id:
176+ :param from_collection:
177+ :return:
178+ """
149179 if res_type is None :
150180 raise ValueError ('Resource type must contain a valid APIResourceType' )
151181 if res_type is APIResourceTypes .COLLECTION and from_collection :
@@ -160,8 +190,16 @@ def resource_url_resolver(self, res_type: APIResourceTypes, res_id: str = None,
160190 return self .construct_url (parent_type , res_id , res_type , parent_res_id )
161191
162192 def construct_url (self , parent_type , res_id , res_type , parent_res_id ):
193+ """
194+ Constructs an API endpoint url from the given parameters
195+ :param parent_type:
196+ :param res_id:
197+ :param res_type:
198+ :param parent_res_id:
199+ :return:
200+ """
163201 # TODO: Test for less common cases to ensure that the URL is being constructed correctly
164- base_url = f'{ self .server_url } /{ self .api_endpoint } '
202+ base_url = f'{ self .server_url } /{ self .api_root } '
165203 resource_endpoint = resource_type_to_endpoint (res_type , parent_type )
166204 url = f'{ base_url } /{ resource_endpoint } '
167205
@@ -178,3 +216,32 @@ def get_helper_auth(self):
178216 if self .user_auth :
179217 return self .username , self .password
180218 return None
219+
220+
221+ @dataclass (kw_only = True )
222+ class ResponseParserHelper :
223+ default_object_reps : DefaultObjectRepresentations
224+
225+
226+ class DefaultObjectRepresentations (BaseModel ):
227+ """
228+ Intended to be used as a way to determine which formats should be used when serializing and deserializing objects.
229+ Should work in tandem with planned Serializer/Deserializer classes.
230+ """
231+ # Part 1
232+ collections : str = Field (EncodingSchema .JSON .value )
233+ deployments : str = Field (EncodingSchema . GEO_JSON .value )
234+ procedures : str = Field (EncodingSchema .GEO_JSON .value )
235+ properties : str = Field (EncodingSchema .SML_JSON .value )
236+ sampling_features : str = Field (EncodingSchema .GEO_JSON .value )
237+ systems : str = Field (EncodingSchema .GEO_JSON .value )
238+ # Part 2
239+ datastreams : str = Field (EncodingSchema .JSON .value )
240+ observations : str = Field (EncodingSchema .JSON .value )
241+ control_channels : str = Field (EncodingSchema .JSON .value )
242+ commands : str = Field (EncodingSchema .JSON .value )
243+ system_events : str = Field (EncodingSchema .OM_JSON .value )
244+ system_history : str = Field (EncodingSchema .GEO_JSON .value )
245+ # TODO: validate schemas for each resource to amke sure they are allowed per the spec
246+
247+
0 commit comments