Coverage for fingerprint_server_sdk/configuration.py: 78%

137 statements  

« prev     ^ index     » next       coverage.py v7.14.3, created at 2026-07-14 10:45 +0000

1""" 

2Server API 

3Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. 

4Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. 

5The API also supports collection of Automation Intelligence for requests to your server in edge, pre-origin, or middleware contexts. 

6 

7The version of the OpenAPI document: 4 

8Contact: support@fingerprint.com 

9Generated by OpenAPI Generator (https://openapi-generator.tech) 

10 

11Do not edit the class manually. 

12""" # noqa: E501 

13 

14import copy 

15import http.client as httplib 

16import logging 

17import multiprocessing 

18import sys 

19from enum import Enum 

20from logging import FileHandler 

21from typing import Any, ClassVar, Literal, Optional, TypedDict, Union 

22 

23from typing_extensions import Self 

24 

25from fingerprint_server_sdk import __version__ 

26 

27JSON_SCHEMA_VALIDATION_KEYWORDS = { 

28 'multipleOf', 

29 'maximum', 

30 'exclusiveMaximum', 

31 'minimum', 

32 'exclusiveMinimum', 

33 'maxLength', 

34 'minLength', 

35 'pattern', 

36 'maxItems', 

37 'minItems', 

38} 

39 

40ServerVariablesT = dict[str, str] 

41 

42BearerFormatAuthSetting = TypedDict( 

43 'BearerFormatAuthSetting', 

44 { 

45 'type': Literal['bearer'], 

46 'in': Literal['header'], 

47 'format': Literal['JWT'], 

48 'key': Literal['Authorization'], 

49 'value': str, 

50 }, 

51) 

52 

53 

54class AuthSettings(TypedDict, total=False): 

55 bearerAuth: BearerFormatAuthSetting 

56 

57 

58class Region(Enum): 

59 US = 'us' 

60 EU = 'eu' 

61 AP = 'ap' 

62 

63 

64class Configuration: 

65 """This class contains various settings of the API client. 

66 

67 :param api_key: Required API key. 

68 :param region: Region. 

69 :param host: Optional base url. If this provided, region will not be used. 

70 :param ssl_ca_cert: str - the path to a file of concatenated CA certificates 

71 in PEM format. 

72 :param retries: Number of retries for API requests. 

73 :param ca_cert_data: verify the peer using concatenated CA certificate data 

74 in PEM (str) or DER (bytes) format. 

75 :param default_query_params: default additional query parameters. 

76 """ 

77 

78 _default: ClassVar[Optional[Self]] = None 

79 

80 def __init__( 

81 self, 

82 api_key: str, 

83 region: Region = Region.US, 

84 host: Optional[str] = None, 

85 ssl_ca_cert: Optional[str] = None, 

86 retries: Optional[int] = None, 

87 ca_cert_data: Optional[Union[str, bytes]] = None, 

88 default_query_params: Optional[list[tuple[str, str]]] = None, 

89 *, 

90 debug: Optional[bool] = None, 

91 ) -> None: 

92 """Constructor""" 

93 if host: 

94 self._base_path = host 

95 else: 

96 self._base_path = self.get_host(region) 

97 

98 self.api_key = api_key 

99 

100 self.logger = {} 

101 """Logging Settings 

102 """ 

103 self.logger['package_logger'] = logging.getLogger('fingerprint_server_sdk') 

104 self.logger['urllib3_logger'] = logging.getLogger('urllib3') 

105 self.logger_format = '%(asctime)s %(levelname)s %(message)s' 

106 """Log format 

107 """ 

108 self.logger_stream_handler = None 

109 """Log stream handler 

110 """ 

111 self.logger_file_handler: Optional[FileHandler] = None 

112 """Log file handler 

113 """ 

114 self.logger_file = None 

115 """Debug file location 

116 """ 

117 if debug is not None: 

118 self.debug = debug 

119 else: 

120 self.__debug = False 

121 """Debug switch 

122 """ 

123 

124 self.verify_ssl = True 

125 """SSL/TLS verification 

126 Set this to false to skip verifying SSL certificate when calling API 

127 from https server. 

128 """ 

129 self.ssl_ca_cert = ssl_ca_cert 

130 """Set this to customize the certificate file to verify the peer. 

131 """ 

132 self.ca_cert_data = ca_cert_data 

133 """Set this to verify the peer using PEM (str) or DER (bytes) 

134 certificate data. 

135 """ 

136 self.cert_file = None 

137 """client certificate file 

138 """ 

139 self.key_file = None 

140 """client key file 

141 """ 

142 self.assert_hostname = None 

143 """Set this to True/False to enable/disable SSL hostname verification. 

144 """ 

145 self.tls_server_name = None 

146 """SSL/TLS Server Name Indication (SNI) 

147 Set this to the SNI value expected by the server. 

148 """ 

149 

150 self.connection_pool_maxsize = multiprocessing.cpu_count() * 5 

151 """urllib3 connection pool's maximum number of connections saved 

152 per pool. urllib3 uses 1 connection as default value, but this is 

153 not the best value when you are making a lot of possibly parallel 

154 requests to the same host, which is often the case here. 

155 cpu_count * 5 is used as default value to increase performance. 

156 """ 

157 

158 self.proxy: Optional[str] = None 

159 """Proxy URL 

160 """ 

161 self.proxy_headers = None 

162 """Proxy headers 

163 """ 

164 self.safe_chars_for_path_param = '' 

165 """Safe chars for path_param 

166 """ 

167 self.retries = retries 

168 """Adding retries to override urllib3 default value 3 

169 """ 

170 # Enable client side validation 

171 self.client_side_validation = True 

172 

173 self.socket_options = None 

174 """Options to pass down to the underlying urllib3 socket 

175 """ 

176 

177 self.datetime_format = '%Y-%m-%dT%H:%M:%S.%f%z' 

178 """datetime format 

179 """ 

180 

181 self.date_format = '%Y-%m-%d' 

182 """date format 

183 """ 

184 

185 self.default_query_params: list[tuple[str, str]] = ( 

186 default_query_params 

187 if default_query_params 

188 else [('ii', f'fingerprint-pro-server-python-sdk/{__version__}')] 

189 ) 

190 

191 def __deepcopy__(self, memo: dict[int, Any]) -> Self: 

192 cls = self.__class__ 

193 result = cls.__new__(cls) 

194 memo[id(self)] = result 

195 for k, v in self.__dict__.items(): 

196 if k not in ('logger', 'logger_file_handler'): 

197 setattr(result, k, copy.deepcopy(v, memo)) 

198 # shallow copy of loggers 

199 result.logger = copy.copy(self.logger) 

200 # use setters to configure loggers 

201 result.logger_file = self.logger_file 

202 result.debug = self.debug 

203 return result 

204 

205 def __setattr__(self, name: str, value: Any) -> None: 

206 object.__setattr__(self, name, value) 

207 

208 @classmethod 

209 def set_default(cls, default: Optional[Self]) -> None: 

210 """Set default instance of configuration. 

211 

212 It stores default configuration, which can be 

213 returned by get_default_copy method. 

214 

215 :param default: object of Configuration 

216 """ 

217 cls._default = default 

218 

219 @property 

220 def logger_file(self) -> Optional[str]: 

221 """The logger file. 

222 

223 If the logger_file is None, then add stream handler and remove file 

224 handler. Otherwise, add file handler and remove stream handler. 

225 

226 :type: str 

227 """ 

228 return self.__logger_file 

229 

230 @logger_file.setter 

231 def logger_file(self, value: Optional[str]) -> None: 

232 """The logger file. 

233 

234 If the logger_file is None, then add stream handler and remove file 

235 handler. Otherwise, add file handler and remove stream handler. 

236 

237 :param value: The logger_file path. 

238 :type: str 

239 """ 

240 self.__logger_file = value 

241 if self.__logger_file: 

242 # If set logging file, 

243 # then add file handler and remove stream handler. 

244 self.logger_file_handler = logging.FileHandler(self.__logger_file) 

245 self.logger_file_handler.setFormatter(self.logger_formatter) 

246 for _, logger in self.logger.items(): 

247 logger.addHandler(self.logger_file_handler) 

248 

249 @property 

250 def debug(self) -> bool: 

251 """Debug status 

252 

253 :type: bool 

254 """ 

255 return self.__debug 

256 

257 @debug.setter 

258 def debug(self, value: bool) -> None: 

259 """Debug status 

260 

261 :param value: The debug status, True or False. 

262 :type: bool 

263 """ 

264 self.__debug = value 

265 if self.__debug: 

266 # if debug status is True, turn on debug logging 

267 for _, logger in self.logger.items(): 

268 logger.setLevel(logging.DEBUG) 

269 # turn on httplib debug 

270 httplib.HTTPConnection.debuglevel = 1 

271 else: 

272 # if debug status is False, turn off debug logging, 

273 # setting log level to default `logging.WARNING` 

274 for _, logger in self.logger.items(): 

275 logger.setLevel(logging.WARNING) 

276 # turn off httplib debug 

277 httplib.HTTPConnection.debuglevel = 0 

278 

279 @property 

280 def logger_format(self) -> str: 

281 """The logger format. 

282 

283 The logger_formatter will be updated when sets logger_format. 

284 

285 :type: str 

286 """ 

287 return self.__logger_format 

288 

289 @logger_format.setter 

290 def logger_format(self, value: str) -> None: 

291 """The logger format. 

292 

293 The logger_formatter will be updated when sets logger_format. 

294 

295 :param value: The format string. 

296 :type: str 

297 """ 

298 self.__logger_format = value 

299 self.logger_formatter = logging.Formatter(self.__logger_format) 

300 

301 def auth_settings(self) -> AuthSettings: 

302 """Gets Auth Settings dict for api client. 

303 

304 :return: The Auth Settings information dict. 

305 """ 

306 auth: AuthSettings = {} 

307 bearerAuth: BearerFormatAuthSetting = { 

308 'type': 'bearer', 

309 'in': 'header', 

310 'format': 'JWT', 

311 'key': 'Authorization', 

312 'value': 'Bearer ' + self.api_key, 

313 } 

314 

315 auth['bearerAuth'] = bearerAuth 

316 return auth 

317 

318 def to_debug_report(self) -> str: 

319 """Gets the essential information for debugging. 

320 

321 :return: The report for debugging. 

322 """ 

323 return ( 

324 'Python SDK Debug Report:\n' 

325 f'OS: {sys.platform}\n' 

326 f'Python Version: {sys.version}\n' 

327 'Version of the API: 4\n' 

328 'SDK Package Version: 9.4.0' 

329 ) 

330 

331 @staticmethod 

332 def get_host(region: Region) -> str: 

333 return { 

334 Region.US: 'https://api.fpjs.io/v4', 

335 Region.EU: 'https://eu.api.fpjs.io/v4', 

336 Region.AP: 'https://ap.api.fpjs.io/v4', 

337 }.get(region, 'https://api.fpjs.io/v4') 

338 

339 @property 

340 def host(self) -> str: 

341 """Return generated host.""" 

342 return self._base_path 

343 

344 @host.setter 

345 def host(self, value: str) -> None: 

346 """Fix base path.""" 

347 self._base_path = value