@@ -36,9 +36,13 @@ class ApiClient:
3636 __DEFAULT_URL = 'https://bhexpress.cl'
3737 __DEFAULT_VERSION = 'v1'
3838
39- def __init__ (self , token = None , url = None , version = None , raise_for_status = True ):
39+ def __init__ (self , token = None , url = None , version = None , raise_for_status = True ):
40+ '''
41+ Constructor para inicializar el Cliente de la API de BHExpress.
42+ '''
4043 self .token = self .__validate_token (token )
4144 self .url = self .__validate_url (url )
45+ self .rut = self .__validate_rut ()
4246 self .headers = self .__generate_headers ()
4347 self .version = version or self .__DEFAULT_VERSION
4448 self .raise_for_status = raise_for_status
@@ -68,6 +72,20 @@ def __validate_url(self, url):
6872 '''
6973 return str (url ).strip () if url else getenv ('BHEXPRESS_API_URL' , self .__DEFAULT_URL ).strip ()
7074
75+ def __validate_rut (self ):
76+ '''
77+ Valida y retorna el RUT del Emisor de BHEs a utilizar.
78+
79+ :param str rut: RUT a validar.
80+ :return: RUT validado.
81+ :rtype: str
82+ :raises ApiException: Si el RUT no es válido o está ausente.
83+ '''
84+ rut = getenv ('BHEXPRESS_EMISOR_RUT' , '' )
85+ if rut == '' :
86+ raise ApiException ('Se debe configurar la variable de entorno: BHEXPRESS_EMISOR_RUT.' )
87+ return str (rut ).strip ()
88+
7189 def __generate_headers (self ):
7290 '''
7391 Genera y retorna las cabeceras por defecto para las solicitudes.
@@ -78,11 +96,12 @@ def __generate_headers(self):
7896 return {
7997 'User-Agent' : 'BHExpress: Cliente de API en Python.' ,
8098 'Accept' : 'application/json' ,
81- 'Content-Type' : 'application/json' , # Faltaba ESTA línea de código...
82- 'Authorization' : 'Token ' + self .token
99+ 'Content-Type' : 'application/json' ,
100+ 'Authorization' : 'Token %(token)s' % {'token' : self .token },
101+ 'X-Bhexpress-Emisor' : self .rut
83102 }
84103
85- def get (self , resource , headers = None ):
104+ def get (self , resource , headers = None ):
86105 '''
87106 Realiza una solicitud GET a la API.
88107
@@ -91,9 +110,9 @@ def get(self, resource, headers=None):
91110 :return: Respuesta de la solicitud.
92111 :rtype: requests.Response
93112 '''
94- return self .__request ('GET' , resource , headers = headers )
113+ return self .__request ('GET' , resource , headers = headers )
95114
96- def delete (self , resource , headers = None ):
115+ def delete (self , resource , headers = None ):
97116 '''
98117 Realiza una solicitud DELETE a la API.
99118
@@ -102,9 +121,9 @@ def delete(self, resource, headers=None):
102121 :return: Respuesta de la solicitud.
103122 :rtype: requests.Response
104123 '''
105- return self .__request ('DELETE' , resource , headers = headers )
124+ return self .__request ('DELETE' , resource , headers = headers )
106125
107- def post (self , resource , data = None , headers = None ):
126+ def post (self , resource , data = None , headers = None ):
108127 '''
109128 Realiza una solicitud POST a la API.
110129
@@ -114,9 +133,9 @@ def post(self, resource, data=None, headers=None):
114133 :return: Respuesta de la solicitud.
115134 :rtype: requests.Response
116135 '''
117- return self .__request ('POST' , resource , data , headers )
136+ return self .__request ('POST' , resource , data = data , headers = headers )
118137
119- def put (self , resource , data = None , headers = None ):
138+ def put (self , resource , data = None , headers = None ):
120139 '''
121140 Realiza una solicitud PUT a la API.
122141
@@ -126,9 +145,9 @@ def put(self, resource, data=None, headers=None):
126145 :return: Respuesta de la solicitud.
127146 :rtype: requests.Response
128147 '''
129- return self .__request ('PUT' , resource , data , headers )
148+ return self .__request ('PUT' , resource , data = data , headers = headers )
130149
131- def __request (self , method , resource , data = None , headers = None ):
150+ def __request (self , method , resource , data = None , headers = None ):
132151 '''
133152 Método privado para realizar solicitudes HTTP.
134153
@@ -140,21 +159,21 @@ def __request(self, method, resource, data=None, headers=None):
140159 :rtype: requests.Response
141160 :raises ApiException: Si el método HTTP no es soportado o si hay un error de conexión.
142161 '''
143- api_path = f '/api/{ self .version } { resource } '
162+ api_path = '/api/%(version)s%(resource)s' % { 'version' : self .version , ' resource' : resource }
144163 full_url = urllib .parse .urljoin (self .url + '/' , api_path .lstrip ('/' ))
145164 headers = headers or {}
146165 headers = {** self .headers , ** headers }
147166 if data and not isinstance (data , str ):
148167 data = json .dumps (data )
149168 try :
150- response = requests .request (method , full_url , data = data , headers = headers )
169+ response = requests .request (method , full_url , data = data , headers = headers )
151170 return self .__check_and_return_response (response )
152171 except requests .exceptions .ConnectionError as error :
153- raise ApiException (f 'Error de conexión: { error } ' )
172+ raise ApiException ('Error de conexión: %(error)s' % { ' error' : error } )
154173 except requests .exceptions .Timeout as error :
155- raise ApiException (f 'Error de timeout: { error } ' )
174+ raise ApiException ('Error de timeout: %(error)s' % { ' error' : error } )
156175 except requests .exceptions .RequestException as error :
157- raise ApiException (f 'Error en la solicitud: { error } ' )
176+ raise ApiException ('Error en la solicitud: %(error)s' % { ' error' : error } )
158177
159178 def __check_and_return_response (self , response ):
160179 '''
@@ -173,20 +192,23 @@ def __check_and_return_response(self, response):
173192 error = response .json ()
174193 message = error .get ('message' , '' ) or error .get ('exception' , '' ) or 'Error desconocido.'
175194 except json .decoder .JSONDecodeError :
176- message = f 'Error al decodificar los datos en JSON: { response .text } '
177- raise ApiException (f 'Error HTTP: { message } ' )
195+ message = 'Error al decodificar los datos en JSON: %(response)s' % { ' response' : response .text }
196+ raise ApiException ('Error HTTP: %(message)s' % { ' message' : message } )
178197 return response
179198
180199class ApiException (Exception ):
181200 '''
182201 Excepción personalizada para errores en el cliente de la API.
183-
184- :param str message: Mensaje de error.
185- :param int code: Código de error (opcional).
186- :param dict params: Parámetros adicionales del error (opcional).
187202 '''
188203
189- def __init__ (self , message , code = None , params = None ):
204+ def __init__ (self , message , code = None , params = None ):
205+ '''
206+ Constructor para la creación de manejo de errores.
207+
208+ :param str message: Mensaje de error.
209+ :param int code: Código de error (opcional).
210+ :param dict params: Parámetros adicionales del error (opcional).
211+ '''
190212 self .message = message
191213 self .code = code
192214 self .params = params
@@ -207,9 +229,9 @@ def __str__(self):
207229 :return: Una cadena que representa el error de una manera clara y concisa.
208230 '''
209231 if self .code is not None :
210- return f '[BHExpress] Error { self .code } : { self .message } '
232+ return '[BHExpress] Error %(code)s: %(message)s' % { 'code' : self .code , 'message' : self .message }
211233 else :
212- return f '[BHExpress] { self .message } '
234+ return '[BHExpress] %(message)s' % { 'message' : self .message }
213235
214236class ApiBase (ABC ):
215237 '''
@@ -221,6 +243,6 @@ class ApiBase(ABC):
221243 :param bool api_raise_for_status: Si se debe lanzar una excepción automáticamente para respuestas de error HTTP. Por defecto es True.
222244 '''
223245
224- def __init__ (self , api_token = None , api_url = None , api_version = None , api_raise_for_status = True ):
246+ def __init__ (self , api_token = None , api_url = None , api_version = None , api_raise_for_status = True ):
225247 self .client = ApiClient (api_token , api_url , api_version , api_raise_for_status )
226248
0 commit comments