PyFunceble-dev 4.3.0a5__py3-none-any.whl → 4.3.0a10__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. PyFunceble/checker/availability/base.py +0 -1
  2. PyFunceble/checker/availability/domain.py +0 -1
  3. PyFunceble/checker/availability/extras/base.py +18 -18
  4. PyFunceble/checker/availability/extras/etoxic.py +0 -1
  5. PyFunceble/checker/availability/extras/parked.py +1 -2
  6. PyFunceble/checker/availability/extras/rules.py +64 -5
  7. PyFunceble/checker/availability/extras/subject_switch.py +1 -1
  8. PyFunceble/checker/availability/ip.py +0 -1
  9. PyFunceble/checker/availability/url.py +0 -1
  10. PyFunceble/checker/reputation/base.py +0 -1
  11. PyFunceble/cli/processes/migrator.py +0 -1
  12. PyFunceble/cli/processes/workers/base.py +5 -3
  13. PyFunceble/cli/processes/workers/dir_files_sorter.py +0 -1
  14. PyFunceble/cli/processes/workers/file_sorter.py +0 -1
  15. PyFunceble/cli/processes/workers/file_sorter_base.py +0 -1
  16. PyFunceble/cli/processes/workers/migrator.py +0 -1
  17. PyFunceble/cli/processes/workers/miner.py +7 -9
  18. PyFunceble/cli/processes/workers/tester.py +2 -6
  19. PyFunceble/cli/scripts/iana.py +11 -1
  20. PyFunceble/cli/scripts/public_suffix.py +14 -1
  21. PyFunceble/cli/system/launcher.py +27 -14
  22. PyFunceble/cli/utils/version.py +27 -15
  23. PyFunceble/config/loader.py +43 -12
  24. PyFunceble/downloader/base.py +13 -3
  25. PyFunceble/helpers/download.py +147 -20
  26. PyFunceble/helpers/hash.py +10 -18
  27. PyFunceble/query/dns/nameserver.py +12 -6
  28. PyFunceble/query/dns/query_tool.py +3 -1
  29. PyFunceble/query/http_status_code.py +9 -7
  30. PyFunceble/query/platform.py +7 -8
  31. PyFunceble/query/requests/adapter/base.py +36 -4
  32. PyFunceble/query/requests/adapter/http.py +2 -3
  33. PyFunceble/query/requests/adapter/https.py +2 -2
  34. PyFunceble/query/requests/requester.py +70 -41
  35. PyFunceble/storage.py +1 -4
  36. {PyFunceble_dev-4.3.0a5.dist-info → PyFunceble_dev-4.3.0a10.dist-info}/METADATA +173 -68
  37. {PyFunceble_dev-4.3.0a5.dist-info → PyFunceble_dev-4.3.0a10.dist-info}/RECORD +41 -41
  38. {PyFunceble_dev-4.3.0a5.dist-info → PyFunceble_dev-4.3.0a10.dist-info}/WHEEL +1 -1
  39. {PyFunceble_dev-4.3.0a5.dist-info → PyFunceble_dev-4.3.0a10.dist-info}/LICENSE +0 -0
  40. {PyFunceble_dev-4.3.0a5.dist-info → PyFunceble_dev-4.3.0a10.dist-info}/entry_points.txt +0 -0
  41. {PyFunceble_dev-4.3.0a5.dist-info → PyFunceble_dev-4.3.0a10.dist-info}/top_level.txt +0 -0
@@ -66,6 +66,7 @@ from yaml.error import MarkedYAMLError
66
66
  import PyFunceble.cli.storage
67
67
  import PyFunceble.storage
68
68
  from PyFunceble.config.compare import ConfigComparison
69
+ from PyFunceble.dataset.user_agent import UserAgentDataset
69
70
  from PyFunceble.downloader.iana import IANADownloader
70
71
  from PyFunceble.downloader.public_suffix import PublicSuffixDownloader
71
72
  from PyFunceble.downloader.user_agents import UserAgentsDownloader
@@ -438,19 +439,20 @@ class ConfigLoader:
438
439
  else:
439
440
  destination = dest
440
441
 
441
- DownloadHelper(src).download_text(destination=destination)
442
-
443
- if not self.is_already_loaded():
444
- self.install_missing_infrastructure_files()
445
- self.download_dynamic_infrastructure_files()
446
- download_remote_config(
447
- self.remote_config_location, self.path_to_remote_config
448
- )
449
- download_remote_config(self.path_to_config)
442
+ DownloadHelper(
443
+ src,
444
+ certificate_validation=(
445
+ PyFunceble.storage.CONFIGURATION.verify_ssl_certificate
446
+ if PyFunceble.storage.CONFIGURATION
447
+ else True
448
+ ),
449
+ own_proxy_handler=True,
450
+ proxies=config["proxies"],
451
+ ).download_text(destination=destination)
450
452
 
451
453
  try:
452
454
  config = self.dict_helper.from_yaml_file(self.path_to_config)
453
- except MarkedYAMLError:
455
+ except (MarkedYAMLError, FileNotFoundError):
454
456
  self.file_helper.set_path(self.path_to_default_config).copy(
455
457
  self.path_to_config
456
458
  )
@@ -474,6 +476,32 @@ class ConfigLoader:
474
476
 
475
477
  self.dict_helper.set_subject(config).to_yaml_file(self.path_to_config)
476
478
 
479
+ if self.file_helper.set_path(self.path_to_overwrite_config).exists():
480
+ # Early load of the overwrite configuration to allow usage of defined
481
+ # proxy settings.
482
+ overwrite_data = self.dict_helper.from_yaml_file(
483
+ self.path_to_overwrite_config
484
+ )
485
+
486
+ if isinstance(overwrite_data, dict):
487
+ config = Merge(overwrite_data).into(config)
488
+ else: # pragma: no cover ## Just make it visible to end-user.
489
+ self.file_helper.write("")
490
+
491
+ # Now we preset the storage to enforce the usage of the configuration
492
+ # in any downloads.
493
+ PyFunceble.storage.CONFIGURATION = Box(
494
+ config,
495
+ )
496
+
497
+ if not self.is_already_loaded():
498
+ self.install_missing_infrastructure_files()
499
+ self.download_dynamic_infrastructure_files()
500
+ download_remote_config(
501
+ self.remote_config_location, self.path_to_remote_config
502
+ )
503
+ download_remote_config(self.path_to_config)
504
+
477
505
  if (
478
506
  self.path_to_remote_config
479
507
  and self.file_helper.set_path(self.path_to_remote_config).exists()
@@ -484,14 +512,14 @@ class ConfigLoader:
484
512
  config = Merge(remote_data).into(config)
485
513
 
486
514
  if self.file_helper.set_path(self.path_to_overwrite_config).exists():
515
+ # Load the overwrite configuration again to ensure that user defined
516
+ # settings are always applied - last one wins.
487
517
  overwrite_data = self.dict_helper.from_yaml_file(
488
518
  self.path_to_overwrite_config
489
519
  )
490
520
 
491
521
  if isinstance(overwrite_data, dict):
492
522
  config = Merge(overwrite_data).into(config)
493
- else: # pragma: no cover ## Just make it visible to end-user.
494
- self.file_helper.write("")
495
523
 
496
524
  return config
497
525
 
@@ -562,6 +590,9 @@ class ConfigLoader:
562
590
  if "proxy" in config and config["proxy"]:
563
591
  PyFunceble.storage.PROXY = Box(config["proxy"])
564
592
 
593
+ # Early load user agents to allow usage of defined user agents.
594
+ UserAgentDataset().get_latest()
595
+
565
596
  return self
566
597
 
567
598
  def destroy(self, keep_custom: bool = False) -> "ConfigLoader":
@@ -107,6 +107,7 @@ class DownloaderBase:
107
107
  _config_dir: Optional[str] = None
108
108
  _destination: Optional[str] = None
109
109
  _download_link: Optional[str] = None
110
+ _download_helper: Optional[DownloadHelper] = None
110
111
 
111
112
  dict_helper: Optional[DictHelper] = None
112
113
 
@@ -130,6 +131,17 @@ class DownloaderBase:
130
131
  if self.DEFAULT_FILENAME is not None:
131
132
  self.destination = os.path.join(self.config_dir, self.DEFAULT_FILENAME)
132
133
 
134
+ self._download_helper = DownloadHelper(
135
+ self.download_link,
136
+ own_proxy_handler=True,
137
+ proxies=PyFunceble.storage.PROXY,
138
+ certificate_validation=(
139
+ PyFunceble.storage.CONFIGURATION.verify_ssl_certificate
140
+ if PyFunceble.storage.CONFIGURATION
141
+ else True
142
+ ),
143
+ )
144
+
133
145
  @property
134
146
  def authorized(self) -> bool:
135
147
  """
@@ -343,8 +355,6 @@ class DownloaderBase:
343
355
  if not hasattr(self, "download_link") or not self.download_link:
344
356
  raise PyFunceble.downloader.exceptions.NoDownloadLinkGiven()
345
357
 
346
- if DownloadHelper(self.download_link).download_text(
347
- destination=self.destination
348
- ):
358
+ if self._download_helper.download_text(destination=self.destination):
349
359
  self.set_current_downtime()
350
360
  self.save_all_downtimes()
@@ -65,13 +65,29 @@ class DownloadHelper:
65
65
  Simplification of the downloads.
66
66
 
67
67
  :param str url:
68
- :param int retry:
68
+ :param int retries:
69
69
  The number of time we have to retry before raising an exception.
70
+ :param bool certificate_validation:
71
+ The state of the certificate validation.
72
+ :param bool own_proxy_handler:
73
+ Whether we should use our own proxy handler or not.
74
+ :param dict proxies:
75
+ The proxy to use.
76
+
77
+ When :code:`own_proxy_handler` is set to :code:`True`, the proxies
78
+ are expected to come from the global configuration.
79
+ Otherwise, the proxies are expected to be a dictionary as defined
80
+ by the requests library.
70
81
  """
71
82
 
72
83
  _url: Optional[str] = None
73
84
  _certificate_validation: bool = True
74
85
  _retries: int = 3
86
+ _proxies: Optional[dict] = None
87
+
88
+ _session = None
89
+ _own_proxy_handler: Optional[bool] = True
90
+ _proxies: Optional[dict] = None
75
91
 
76
92
  def __init__(
77
93
  self,
@@ -79,15 +95,42 @@ class DownloadHelper:
79
95
  *,
80
96
  certificate_validation: bool = True,
81
97
  retries: int = 3,
98
+ own_proxy_handler: Optional[bool] = True,
99
+ proxies: Optional[dict] = None,
82
100
  ) -> None:
83
- if url:
101
+ if url is not None:
84
102
  self.url = url
85
103
 
86
- if certificate_validation:
87
- self.certificate_validation = certificate_validation
104
+ if proxies is not None:
105
+ self.proxies = proxies
88
106
 
89
- if retries:
90
- self.retries = retries
107
+ self.retries = retries
108
+ self.certificate_validation = bool(certificate_validation)
109
+ self.own_proxy_handler = own_proxy_handler
110
+
111
+ @property
112
+ def session(self) -> requests.Session:
113
+ """
114
+ Provides the current state of the :code:`_session` attribute.
115
+ """
116
+
117
+ if not self._session:
118
+ if self.own_proxy_handler:
119
+ # pylint: disable=import-outside-toplevel
120
+ from PyFunceble.query.requests.requester import Requester
121
+
122
+ self._session = Requester(proxy_pattern=self.proxies)
123
+ else:
124
+ self._session = requests.Session()
125
+ self._session.proxies = self.proxies
126
+
127
+ retries = Retry(total=self.retries, backoff_factor=3)
128
+ adapter = HTTPAdapter(max_retries=retries)
129
+
130
+ self._session.mount("http://", adapter)
131
+ self._session.mount("https://", adapter)
132
+
133
+ return self._session
91
134
 
92
135
  @property
93
136
  def url(self) -> Optional[str]:
@@ -208,7 +251,103 @@ class DownloadHelper:
208
251
 
209
252
  return self
210
253
 
211
- def download_text(self, *, destination: Optional[str] = None) -> str:
254
+ @property
255
+ def own_proxy_handler(self) -> Optional[bool]:
256
+ """
257
+ Provides the current state of the :code:`own_proxy_handler` attribute.
258
+ """
259
+
260
+ return self._own_proxy_handler
261
+
262
+ @own_proxy_handler.setter
263
+ def own_proxy_handler(self, value: bool) -> None:
264
+ """
265
+ Sets the state of the own proxy handler.
266
+
267
+ :param value:
268
+ The value to set.
269
+
270
+ :raise TypeError:
271
+ When :code:`value` is not a :py:class:`bool`.
272
+ """
273
+
274
+ if not isinstance(value, bool):
275
+ raise TypeError(f"<value> should be {bool}, {type(value)} given.")
276
+
277
+ self._own_proxy_handler = value
278
+
279
+ if value:
280
+ # We force the recreation of the session.
281
+ self._session = None
282
+
283
+ def set_own_proxy_handler(self, value: bool) -> "DownloadHelper":
284
+ """
285
+ Sets the state of the own proxy handler.
286
+
287
+ :param value:
288
+ The value to set.
289
+ """
290
+
291
+ self.own_proxy_handler = value
292
+
293
+ return self
294
+
295
+ @property
296
+ def proxies(self) -> Optional[dict]:
297
+ """
298
+ Provides the current state of the :code:`_proxies` attribute.
299
+ """
300
+
301
+ return self._proxies
302
+
303
+ @proxies.setter
304
+ def proxies(self, value: Optional[dict]) -> None:
305
+ """
306
+ Sets the proxy to use.
307
+
308
+ :param value:
309
+ The proxy to use.
310
+
311
+ When :code:`own_proxy_handler` is set to :code:`True`, the proxies
312
+ are expected to come from the global configuration.
313
+ Otherwise, the proxies are expected to be a dictionary as defined
314
+ by the requests library.
315
+
316
+ :raise TypeError:
317
+ When :code:`value` is not a :py:class:`dict`.
318
+ """
319
+
320
+ if not isinstance(value, dict):
321
+ raise TypeError(f"<value> should be {dict}, {type(value)} given.")
322
+
323
+ self._proxies = value
324
+
325
+ if value:
326
+ # We force the recreation of the session.
327
+ self._session = None
328
+
329
+ def set_proxies(self, value: Optional[dict]) -> "DownloadHelper":
330
+ """
331
+ Sets the proxy to use.
332
+
333
+ :param value:
334
+ The proxy to use.
335
+
336
+ When :code:`own_proxy_handler` is set to :code:`True`, the proxies
337
+ are expected to come from the global configuration.
338
+ Otherwise, the proxies are expected to be a dictionary as defined
339
+ by the requests library.
340
+ """
341
+
342
+ self.proxies = value
343
+
344
+ return self
345
+
346
+ def download_text(
347
+ self,
348
+ *,
349
+ destination: Optional[str] = None,
350
+ ) -> str:
212
351
  """
213
352
  Download the body of the set url.
214
353
 
@@ -224,15 +363,7 @@ class DownloadHelper:
224
363
  :raise UnableToDownload: When could not unable to download the URL.
225
364
  """
226
365
 
227
- session = requests.Session()
228
-
229
- retries = Retry(total=self.retries, backoff_factor=3)
230
- adapter = HTTPAdapter(max_retries=retries)
231
-
232
- session.mount("http://", adapter)
233
- session.mount("https://", adapter)
234
-
235
- req = session.get(self.url, verify=self.certificate_validation)
366
+ req = self.session.get(self.url, verify=self.certificate_validation)
236
367
 
237
368
  if req.status_code == 200:
238
369
  response = req.text
@@ -240,12 +371,8 @@ class DownloadHelper:
240
371
  if destination and isinstance(destination, str):
241
372
  FileHelper(destination).write(req.text, overwrite=True)
242
373
 
243
- adapter.close()
244
- req.close()
245
374
  return response
246
375
 
247
- adapter.close()
248
- session.close()
249
376
  raise PyFunceble.helpers.exceptions.UnableToDownload(
250
377
  f"{req.url} (retries: {self.retries} | status code: {req.status_code})"
251
378
  )
@@ -50,11 +50,9 @@ License:
50
50
  limitations under the License.
51
51
  """
52
52
 
53
+ import hashlib
53
54
  from typing import Optional, Union
54
55
 
55
- from cryptography.hazmat.backends import default_backend
56
- from cryptography.hazmat.primitives import hashes
57
-
58
56
  from PyFunceble.helpers.file import FileHelper
59
57
 
60
58
 
@@ -68,7 +66,7 @@ class HashHelper:
68
66
  :raise ValueError: When the given algo is not known.
69
67
  """
70
68
 
71
- _algo: str = "SHA512_224"
69
+ _algo: str = "sha512_224"
72
70
 
73
71
  def __init__(self, algo: Optional[str] = None):
74
72
  if algo is not None:
@@ -97,11 +95,12 @@ class HashHelper:
97
95
  if not isinstance(value, str):
98
96
  raise TypeError(f"<value> should be {str}, {type(value)} given.")
99
97
 
100
- value = value.upper()
98
+ value = value.lower()
101
99
 
102
- if not hasattr(hashes, value):
100
+ if value not in hashlib.algorithms_available:
103
101
  raise ValueError(
104
- f"<value> ({value!r}) in an unknown algorithm ({self.algo!r})."
102
+ f"<value> ({value!r}) in an unknown algorithm "
103
+ f"({hashlib.algorithms_available})."
105
104
  )
106
105
 
107
106
  self._algo = value
@@ -118,13 +117,6 @@ class HashHelper:
118
117
 
119
118
  return self
120
119
 
121
- def __get_hash(self) -> hashes.Hash:
122
- """
123
- Provides the Hash to use.
124
- """
125
-
126
- return hashes.Hash(getattr(hashes, self.algo)(), backend=default_backend())
127
-
128
120
  def hash_file(self, file_path: str) -> str:
129
121
  """
130
122
  Hashes the content of the given file.
@@ -135,7 +127,7 @@ class HashHelper:
135
127
 
136
128
  block_size = 4096
137
129
 
138
- digest = self.__get_hash()
130
+ digest = hashlib.new(self.algo)
139
131
 
140
132
  with FileHelper(file_path).open("rb") as file_stream:
141
133
  block = file_stream.read(block_size)
@@ -144,7 +136,7 @@ class HashHelper:
144
136
  digest.update(block)
145
137
  block = file_stream.read(block_size)
146
138
 
147
- return digest.finalize().hex()
139
+ return digest.hexdigest()
148
140
 
149
141
  def hash_data(self, data: Union[str, bytes]) -> str:
150
142
  """
@@ -163,7 +155,7 @@ class HashHelper:
163
155
  if isinstance(data, str):
164
156
  data = data.encode()
165
157
 
166
- digest = self.__get_hash()
158
+ digest = hashlib.new(self.algo)
167
159
  digest.update(data)
168
160
 
169
- return digest.finalize().hex()
161
+ return digest.hexdigest()
@@ -50,6 +50,7 @@ License:
50
50
  limitations under the License.
51
51
  """
52
52
 
53
+ import ipaddress
53
54
  from typing import List, Optional, Tuple
54
55
 
55
56
  import dns.exception
@@ -79,15 +80,19 @@ class Nameservers:
79
80
 
80
81
  protocol: Optional[str] = None
81
82
 
82
- domain_syntax_checker: DomainSyntaxChecker = DomainSyntaxChecker()
83
- url_syntax_checker: URLSyntaxChecker = URLSyntaxChecker()
84
- url2netloc: Url2Netloc = Url2Netloc()
83
+ domain_syntax_checker: Optional[DomainSyntaxChecker] = None
84
+ url_syntax_checker: Optional[URLSyntaxChecker] = None
85
+ url2netloc: Optional[Url2Netloc] = None
85
86
 
86
87
  def __init__(
87
88
  self, nameserver: Optional[List[str]] = None, protocol: str = "TCP"
88
89
  ) -> None:
89
90
  self.protocol = protocol
90
91
 
92
+ self.domain_syntax_checker = DomainSyntaxChecker()
93
+ self.url_syntax_checker = URLSyntaxChecker()
94
+ self.url2netloc = Url2Netloc()
95
+
91
96
  if nameserver is not None:
92
97
  self.set_nameservers(nameserver)
93
98
 
@@ -141,7 +146,10 @@ class Nameservers:
141
146
 
142
147
  result = []
143
148
 
144
- if cls.domain_syntax_checker.set_subject(nameserver).is_valid():
149
+ try:
150
+ _ = ipaddress.ip_address(nameserver)
151
+ result.append(nameserver)
152
+ except ValueError:
145
153
  try:
146
154
  result.extend(
147
155
  [
@@ -161,8 +169,6 @@ class Nameservers:
161
169
  )
162
170
  except dns.exception.DNSException:
163
171
  pass
164
- else:
165
- result.append(nameserver)
166
172
 
167
173
  PyFunceble.facility.Logger.debug(
168
174
  "IP from nameserver (%r):\n%r", nameserver, result
@@ -96,7 +96,7 @@ class DNSQueryTool:
96
96
  x.name: x.value for x in dns.rdatatype.RdataType
97
97
  }
98
98
 
99
- nameservers: Nameservers = Nameservers()
99
+ nameservers: Optional[Nameservers] = None
100
100
  _query_record_type: int = dns.rdatatype.RdataType.ANY
101
101
 
102
102
  _subject: Optional[str] = None
@@ -120,6 +120,8 @@ class DNSQueryTool:
120
120
  trust_server: Optional[bool] = None,
121
121
  delay: Optional[bool] = None,
122
122
  ) -> None:
123
+ self.nameservers = Nameservers()
124
+
123
125
  if nameservers is not None:
124
126
  self.nameservers.set_nameservers(nameservers)
125
127
  else: # pragma: no cover ## I'm not playing with system resolver.
@@ -55,9 +55,9 @@ import socket
55
55
  from typing import Optional, Union
56
56
 
57
57
  import PyFunceble.facility
58
- import PyFunceble.factory
59
58
  import PyFunceble.storage
60
59
  from PyFunceble.converter.url2netloc import Url2Netloc
60
+ from PyFunceble.query.requests.requester import Requester
61
61
 
62
62
 
63
63
  class HTTPStatusCode:
@@ -75,6 +75,7 @@ class HTTPStatusCode:
75
75
  _verify_certificate: bool = True
76
76
  _allow_redirects: bool = False
77
77
  _url2netloc: Optional[Url2Netloc] = None
78
+ requester: Optional[Requester] = None
78
79
 
79
80
  def __init__(
80
81
  self,
@@ -103,6 +104,7 @@ class HTTPStatusCode:
103
104
  self.allow_redirects = self.STD_ALLOW_REDIRECTS
104
105
 
105
106
  self._url2netloc = Url2Netloc()
107
+ self.requester = Requester(config=PyFunceble.storage.CONFIGURATION)
106
108
 
107
109
  def ensure_subject_is_given(func): # pylint: disable=no-self-argument
108
110
  """
@@ -334,7 +336,7 @@ class HTTPStatusCode:
334
336
  """ # pylint: disable=line-too-long
335
337
 
336
338
  try:
337
- req = PyFunceble.factory.Requester.get(
339
+ req = self.requester.get(
338
340
  self.subject,
339
341
  timeout=self.timeout,
340
342
  verify=self.verify_certificate,
@@ -363,12 +365,12 @@ class HTTPStatusCode:
363
365
 
364
366
  return req.status_code
365
367
  except (
366
- PyFunceble.factory.Requester.exceptions.RequestException,
367
- PyFunceble.factory.Requester.exceptions.InvalidSchema,
368
- PyFunceble.factory.Requester.exceptions.InvalidURL,
369
- PyFunceble.factory.Requester.exceptions.MissingSchema,
368
+ self.requester.exceptions.RequestException,
369
+ self.requester.exceptions.InvalidSchema,
370
+ self.requester.exceptions.InvalidURL,
371
+ self.requester.exceptions.MissingSchema,
370
372
  socket.timeout,
371
- PyFunceble.factory.Requester.urllib3_exceptions.InvalidHeader,
373
+ self.requester.urllib3_exceptions.InvalidHeader,
372
374
  ):
373
375
  pass
374
376
 
@@ -702,9 +702,7 @@ class PlatformQueryTool:
702
702
  "shuffle": True,
703
703
  }
704
704
 
705
- if "none" in self.checker_priority:
706
- params["shuffle"] = True
707
- else:
705
+ if "none" not in self.checker_priority:
708
706
  params["checker_type_priority"] = ",".join(self.checker_priority)
709
707
 
710
708
  if "none" not in self.checker_exclude:
@@ -717,9 +715,9 @@ class PlatformQueryTool:
717
715
  timeout=self.timeout * 10,
718
716
  )
719
717
 
720
- response_json = response.json()
721
-
722
718
  if response.status_code == 200:
719
+ response_json = response.json()
720
+
723
721
  PyFunceble.facility.Logger.debug(
724
722
  "Successfully pulled next %r contracts. Response: %r", response_json
725
723
  )
@@ -772,9 +770,9 @@ class PlatformQueryTool:
772
770
  timeout=self.timeout * 10,
773
771
  )
774
772
 
775
- response_json = response.json()
773
+ if response.status_code in (202, 200):
774
+ response_json = response.json()
776
775
 
777
- if response.status_code == 200:
778
776
  PyFunceble.facility.Logger.debug(
779
777
  "Successfully delivered contract: %r. Response: %r",
780
778
  contract_data,
@@ -786,6 +784,7 @@ class PlatformQueryTool:
786
784
  )
787
785
 
788
786
  return response_json
787
+ response_json = {}
789
788
  except (requests.RequestException, json.decoder.JSONDecodeError):
790
789
  response_json = {}
791
790
 
@@ -796,7 +795,7 @@ class PlatformQueryTool:
796
795
  "Finished to deliver contract: %r", contract_data
797
796
  )
798
797
 
799
- return None
798
+ return response_json
800
799
 
801
800
  @ensure_modern_api
802
801
  def push(
@@ -50,12 +50,13 @@ License:
50
50
  limitations under the License.
51
51
  """
52
52
 
53
+ import secrets
53
54
  from typing import Optional
54
55
 
55
56
  import requests.adapters
57
+ import requests.exceptions
56
58
  import requests.models
57
59
 
58
- import PyFunceble.storage
59
60
  from PyFunceble.checker.syntax.ip import IPSyntaxChecker
60
61
  from PyFunceble.query.dns.query_tool import DNSQueryTool
61
62
 
@@ -66,10 +67,15 @@ class RequestAdapterBase(requests.adapters.HTTPAdapter):
66
67
  adapter.
67
68
  """
68
69
 
70
+ NOT_RESOLVED_STD_HOSTNAME: str = (
71
+ f"{secrets.token_hex(12)}.mock-resolver.pyfunceble.com"
72
+ )
73
+
69
74
  resolving_cache: dict = {}
70
75
  resolving_use_cache: bool = False
71
76
  timeout: float = 5.0
72
77
  proxy_pattern: dict = {}
78
+ ssl_context: Optional[dict] = None
73
79
 
74
80
  def __init__(self, *args, **kwargs):
75
81
  if "timeout" in kwargs:
@@ -93,6 +99,10 @@ class RequestAdapterBase(requests.adapters.HTTPAdapter):
93
99
  else:
94
100
  self.proxy_pattern = {}
95
101
 
102
+ if "ssl_context" in kwargs:
103
+ self.ssl_context = kwargs["ssl_context"]
104
+ del kwargs["ssl_context"]
105
+
96
106
  super().__init__(*args, **kwargs)
97
107
 
98
108
  @staticmethod
@@ -102,9 +112,7 @@ class RequestAdapterBase(requests.adapters.HTTPAdapter):
102
112
  given domain.
103
113
  """
104
114
 
105
- raise PyFunceble.factory.Requester.exceptions.ConnectionError(
106
- "Could not resolve."
107
- )
115
+ raise requests.exceptions.ConnectionError("Could not resolve.")
108
116
 
109
117
  @staticmethod
110
118
  def extract_extension(subject: str) -> Optional[str]:
@@ -286,3 +294,27 @@ class RequestAdapterBase(requests.adapters.HTTPAdapter):
286
294
  return self.resolve_with_cache(hostname)
287
295
  return self.resolve_without_cache(hostname)
288
296
  return None
297
+
298
+ def init_poolmanager(self, connections, maxsize, block=False, **pool_kwargs):
299
+ """
300
+ Overwrite the upstream :code:`init_poolmanager` method to ensure that we
301
+ use our own ssl context - when given.
302
+ """
303
+
304
+ _ = pool_kwargs.pop("ssl_context", None)
305
+
306
+ return super().init_poolmanager(
307
+ connections, maxsize, block, ssl_context=self.ssl_context, **pool_kwargs
308
+ )
309
+
310
+ def proxy_manager_for(self, proxy, **proxy_kwargs):
311
+ """
312
+ Overwrite the upstream :code:`proxy_manager_for` method to ensure that we
313
+ use our own ssl context - when given.
314
+ """
315
+
316
+ _ = proxy_kwargs.pop("ssl_context", None)
317
+
318
+ return super().proxy_manager_for(
319
+ proxy, ssl_context=self.ssl_context, **proxy_kwargs
320
+ )