PyFunceble-dev 4.2.7__py3-none-any.whl → 4.2.10__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 (51) hide show
  1. PyFunceble/checker/availability/base.py +8 -8
  2. PyFunceble/checker/availability/domain.py +0 -1
  3. PyFunceble/checker/availability/extras/base.py +1 -2
  4. PyFunceble/checker/availability/extras/rules.py +1 -1
  5. PyFunceble/checker/availability/ip.py +0 -1
  6. PyFunceble/checker/availability/url.py +0 -1
  7. PyFunceble/checker/reputation/base.py +0 -1
  8. PyFunceble/checker/reputation/domain.py +0 -1
  9. PyFunceble/checker/reputation/ip.py +0 -1
  10. PyFunceble/checker/reputation/url.py +0 -1
  11. PyFunceble/checker/syntax/second_lvl_domain.py +6 -2
  12. PyFunceble/checker/syntax/status.py +1 -0
  13. PyFunceble/checker/syntax/subdomain.py +3 -1
  14. PyFunceble/checker/syntax/url.py +0 -1
  15. PyFunceble/cli/credential_loader.py +3 -3
  16. PyFunceble/cli/entry_points/pyfunceble/cli.py +72 -6
  17. PyFunceble/cli/file_preloader.py +3 -3
  18. PyFunceble/cli/migrators/base.py +0 -1
  19. PyFunceble/cli/processes/workers/base.py +15 -6
  20. PyFunceble/cli/processes/workers/producer.py +5 -0
  21. PyFunceble/cli/scripts/production.py +3 -4
  22. PyFunceble/cli/storage.py +5 -3
  23. PyFunceble/cli/system/launcher.py +47 -1
  24. PyFunceble/cli/utils/testing.py +1 -3
  25. PyFunceble/config/loader.py +10 -0
  26. PyFunceble/data/alembic/mysql/versions/35c79626ecb9_fix_some_columns.py +1 -0
  27. PyFunceble/data/alembic/mysql/versions/3a4c55a9320d_add_continue_table.py +1 -0
  28. PyFunceble/data/alembic/mysql/versions/3d6f4a33cdb2_add_inactive_table.py +1 -0
  29. PyFunceble/data/alembic/mysql/versions/45713fea8097_deletion_uneeded_columns_from_whois_.py +1 -0
  30. PyFunceble/data/alembic/mysql/versions/459a0d7b8f09_add_idna_subject_column_into_whois.py +1 -0
  31. PyFunceble/data/alembic/mysql/versions/6f4729deaf03_delete_inactive_source_column.py +1 -0
  32. PyFunceble/data/alembic/mysql/versions/7bcf7fa64ba1_rename_created_to_created_at_and.py +1 -0
  33. PyFunceble/data/alembic/mysql/versions/83ada95132bf_delete_the_file_table.py +1 -0
  34. PyFunceble/data/alembic/mysql/versions/912bbcb77a6c_add_registrar_column.py +1 -0
  35. PyFunceble/data/alembic/mysql/versions/95dc17ddd729_introduction_of_the_session_id_column.py +1 -0
  36. PyFunceble/data/alembic/mysql/versions/ade87195b0a0_base.py +1 -0
  37. PyFunceble/data/alembic/mysql/versions/bef7bcaac3f2_make_id_a_bigint.py +1 -0
  38. PyFunceble/data/alembic/mysql/versions/d8893cd406db_allow_whois_record_to_be_empty_null.py +1 -0
  39. PyFunceble/data/alembic/mysql/versions/e04e8301d1a2_deletion_of_the_mined_table.py +1 -0
  40. PyFunceble/data/alembic/postgresql/versions/a32ac5d66eee_initial_version.py +1 -0
  41. PyFunceble/data/infrastructure/.PyFunceble_production.yaml +3 -0
  42. PyFunceble/query/collection.py +207 -11
  43. PyFunceble/query/requests/adapter/https.py +6 -6
  44. PyFunceble/query/whois/converter/digit2digits.py +1 -0
  45. PyFunceble/storage.py +4 -2
  46. {PyFunceble_dev-4.2.7.dist-info → PyFunceble_dev-4.2.10.dist-info}/METADATA +42 -42
  47. {PyFunceble_dev-4.2.7.dist-info → PyFunceble_dev-4.2.10.dist-info}/RECORD +51 -51
  48. {PyFunceble_dev-4.2.7.dist-info → PyFunceble_dev-4.2.10.dist-info}/WHEEL +1 -1
  49. {PyFunceble_dev-4.2.7.dist-info → PyFunceble_dev-4.2.10.dist-info}/LICENSE +0 -0
  50. {PyFunceble_dev-4.2.7.dist-info → PyFunceble_dev-4.2.10.dist-info}/entry_points.txt +0 -0
  51. {PyFunceble_dev-4.2.7.dist-info → PyFunceble_dev-4.2.10.dist-info}/top_level.txt +0 -0
@@ -76,7 +76,6 @@ from PyFunceble.checker.syntax.domain import DomainSyntaxChecker
76
76
  from PyFunceble.checker.syntax.ip import IPSyntaxChecker
77
77
  from PyFunceble.checker.syntax.url import URLSyntaxChecker
78
78
  from PyFunceble.converter.url2netloc import Url2Netloc
79
- from PyFunceble.helpers.regex import RegexHelper
80
79
  from PyFunceble.query.dns.query_tool import DNSQueryTool
81
80
  from PyFunceble.query.http_status_code import HTTPStatusCode
82
81
  from PyFunceble.query.netinfo.address import AddressInfo
@@ -919,12 +918,7 @@ class AvailabilityCheckerBase(CheckerBase):
919
918
  if from_domain_test and self.status.url_syntax:
920
919
  return self
921
920
 
922
- if not self.status.url_syntax and not RegexHelper("[^a-z0-9._]").match(
923
- self.idna_subject, return_match=False
924
- ):
925
- # The regex is there because while testing for domain, sometime we
926
- # may see something like mailto:xxx@yyy.de
927
-
921
+ if not self.status.url_syntax and not self.idna_subject.startswith("http"):
928
922
  self.http_status_code_query_tool.set_subject(
929
923
  f"http://{self.idna_subject}:80"
930
924
  )
@@ -1049,7 +1043,13 @@ class AvailabilityCheckerBase(CheckerBase):
1049
1043
  self.collection_query_tool.preferred_status_origin == "latest"
1050
1044
  and data["status"]["availability"]["latest"]
1051
1045
  ):
1052
- self.status.status = data["status"]["availability"]["latest"]["status"]
1046
+ try:
1047
+ # legacy
1048
+ self.status.status = data["status"]["availability"]["latest"][
1049
+ "status"
1050
+ ]
1051
+ except KeyError:
1052
+ self.status.status = data["status"]["availability"]["latest"]
1053
1053
  self.status.status_source = "COLLECTION"
1054
1054
  elif (
1055
1055
  self.collection_query_tool.preferred_status_origin == "recommended"
@@ -50,7 +50,6 @@ License:
50
50
  limitations under the License.
51
51
  """
52
52
 
53
-
54
53
  import PyFunceble.facility
55
54
  import PyFunceble.factory
56
55
  import PyFunceble.storage
@@ -50,7 +50,6 @@ License:
50
50
  limitations under the License.
51
51
  """
52
52
 
53
-
54
53
  import functools
55
54
  import socket
56
55
  from typing import Callable, Dict, List, Optional, Union
@@ -423,7 +422,7 @@ class ExtraRuleHandlerBase:
423
422
  of the given one.
424
423
  """
425
424
 
426
- if not isinstance(status_code, (list, tuple)):
425
+ if not isinstance(status_code, (list, tuple, set)):
427
426
  status_code = [status_code]
428
427
 
429
428
  if any(self.status.http_status_code == x for x in status_code):
@@ -78,7 +78,7 @@ class ExtraRulesHandler(ExtraRuleHandlerBase):
78
78
  def __init__(self, status: Optional[AvailabilityCheckerStatus] = None) -> None:
79
79
  self.regex_active2inactive = {
80
80
  r"\.000webhostapp\.com": [
81
- (self.switch_to_down_if_status_code, 410),
81
+ (self.switch_to_down_if_status_code, {410, 424}),
82
82
  ],
83
83
  r"\.24\.eu$": [(self.switch_to_down_if_status_code, 503)],
84
84
  r"\.altervista\.org$": [(self.switch_to_down_if_status_code, 403)],
@@ -50,7 +50,6 @@ License:
50
50
  limitations under the License.
51
51
  """
52
52
 
53
-
54
53
  import PyFunceble.facility
55
54
  import PyFunceble.factory
56
55
  import PyFunceble.storage
@@ -50,7 +50,6 @@ License:
50
50
  limitations under the License.
51
51
  """
52
52
 
53
-
54
53
  import PyFunceble.facility
55
54
  import PyFunceble.factory
56
55
  import PyFunceble.storage
@@ -50,7 +50,6 @@ License:
50
50
  limitations under the License.
51
51
  """
52
52
 
53
-
54
53
  from typing import List, Optional
55
54
 
56
55
  from sqlalchemy.orm import Session
@@ -50,7 +50,6 @@ License:
50
50
  limitations under the License.
51
51
  """
52
52
 
53
-
54
53
  from typing import List, Optional
55
54
 
56
55
  from PyFunceble.checker.reputation.base import ReputationCheckerBase
@@ -50,7 +50,6 @@ License:
50
50
  limitations under the License.
51
51
  """
52
52
 
53
-
54
53
  from typing import List, Optional
55
54
 
56
55
  from PyFunceble.checker.reputation.base import ReputationCheckerBase
@@ -50,7 +50,6 @@ License:
50
50
  limitations under the License.
51
51
  """
52
52
 
53
-
54
53
  from typing import List, Optional
55
54
 
56
55
  from PyFunceble.checker.reputation.base import ReputationCheckerBase
@@ -65,8 +65,12 @@ class SecondLvlDomainSyntaxChecker(DomainSyntaxCheckerBase):
65
65
  """
66
66
 
67
67
  # pylint: disable=line-too-long
68
- REGEX_VALID_DOMAIN: str = r"^(?=.{0,253}$)(([a-z0-9][a-z0-9-]{0,61}[a-z0-9]|[a-z0-9])\.)+((?=.*[^0-9])([a-z0-9][a-z0-9-]{0,61}[a-z0-9](?:\.)?|[a-z0-9](?:\.)?))$"
69
- REGEX_VALID_RELAXED_DOMAIN: str = r"^(?=.{0,253}$)(([a-z0-9][a-z0-9_-]{0,61}[a-z0-9_-]|[a-z0-9])\.)+((?=.*[^0-9])([a-z0-9][a-z0-9-]{0,61}[a-z0-9](?:\.)?|[a-z0-9](?:\.)?))$"
68
+ REGEX_VALID_DOMAIN: str = (
69
+ r"^(?=.{0,253}$)(([a-z0-9][a-z0-9-]{0,61}[a-z0-9]|[a-z0-9])\.)+((?=.*[^0-9])([a-z0-9][a-z0-9-]{0,61}[a-z0-9](?:\.)?|[a-z0-9](?:\.)?))$"
70
+ )
71
+ REGEX_VALID_RELAXED_DOMAIN: str = (
72
+ r"^(?=.{0,253}$)(([a-z0-9][a-z0-9_-]{0,61}[a-z0-9_-]|[a-z0-9])\.)+((?=.*[^0-9])([a-z0-9][a-z0-9-]{0,61}[a-z0-9](?:\.)?|[a-z0-9](?:\.)?))$"
73
+ )
70
74
 
71
75
  last_point_index: Optional[int] = None
72
76
  """
@@ -50,6 +50,7 @@ License:
50
50
  See the License for the specific language governing permissions and
51
51
  limitations under the License.
52
52
  """
53
+
53
54
  import dataclasses
54
55
  from typing import Optional
55
56
 
@@ -63,7 +63,9 @@ class SubDomainSyntaxChecker(DomainSyntaxCheckerBase):
63
63
  """
64
64
 
65
65
  # pylint: disable=line-too-long
66
- REGEX_VALID_SUBDOMAIN: str = r"^(?=.{0,253}$)(([a-z0-9_][a-z0-9-_]{0,61}[a-z0-9_-]|[a-z0-9])\.)+((?=.*)([a-z0-9][a-z0-9-]{0,61}[a-z0-9](?:\.)?|[a-z0-9](?:\.)?))$"
66
+ REGEX_VALID_SUBDOMAIN: str = (
67
+ r"^(?=.{0,253}$)(([a-z0-9_][a-z0-9-_]{0,61}[a-z0-9_-]|[a-z0-9])\.)+((?=.*)([a-z0-9][a-z0-9-]{0,61}[a-z0-9](?:\.)?|[a-z0-9](?:\.)?))$"
68
+ )
67
69
 
68
70
  @DomainSyntaxCheckerBase.ensure_subject_is_given
69
71
  def is_valid(self) -> bool:
@@ -50,7 +50,6 @@ License:
50
50
  limitations under the License.
51
51
  """
52
52
 
53
-
54
53
  import urllib.parse
55
54
  from typing import Optional
56
55
 
@@ -266,9 +266,9 @@ class CredentialLoader:
266
266
  # We directly share the credential object into the DBSession object.
267
267
  # This will let us use the DBSession without having to think about
268
268
  # any other headache.
269
- self.credential = (
270
- PyFunceble.cli.factory.DBSession.credential
271
- ) = self.DB_TYPE2OBJ[self.db_type]()
269
+ self.credential = PyFunceble.cli.factory.DBSession.credential = (
270
+ self.DB_TYPE2OBJ[self.db_type]()
271
+ )
272
272
 
273
273
  env_var_helper = EnvironmentVariableHelper(
274
274
  env_file_path=self.credential.get_dot_env_file()
@@ -69,7 +69,9 @@ from PyFunceble.cli.system.launcher import SystemLauncher
69
69
  from PyFunceble.helpers.regex import RegexHelper
70
70
 
71
71
 
72
- def get_configured_value(entry: str, *, negate=False) -> Any:
72
+ def get_configured_value(
73
+ entry: str, *, negate: bool = False, value_only: bool = False
74
+ ) -> Any:
73
75
  """
74
76
  Provides the currently configured value.
75
77
 
@@ -81,6 +83,9 @@ def get_configured_value(entry: str, *, negate=False) -> Any:
81
83
  :param negate:
82
84
  Allows us to negate the result from the configuration.
83
85
 
86
+ :param value_only:
87
+ Whether we should only return the value or the full message.
88
+
84
89
  :raise ValueError:
85
90
  When the given :code:`entry` is not found.
86
91
  """
@@ -102,10 +107,14 @@ def get_configured_value(entry: str, *, negate=False) -> Any:
102
107
  result = not result
103
108
 
104
109
  return (
105
- f"\n{colorama.Fore.YELLOW}{colorama.Style.BRIGHT}"
106
- f"Configured value: {colorama.Fore.BLUE}"
107
- f"{result!r}"
108
- f"{colorama.Style.RESET_ALL}"
110
+ (
111
+ f"\n{colorama.Fore.YELLOW}{colorama.Style.BRIGHT}"
112
+ f"Configured value: {colorama.Fore.BLUE}"
113
+ f"{result!r}"
114
+ f"{colorama.Style.RESET_ALL}"
115
+ )
116
+ if not value_only
117
+ else result
109
118
  )
110
119
 
111
120
 
@@ -122,6 +131,12 @@ def add_arguments_to_parser(
122
131
  if "dest" in opt_args:
123
132
  opt_args["dest"] = opt_args["dest"].replace(".", "__")
124
133
 
134
+ for index, value in enumerate(pos_args):
135
+ if value.startswith("-") and "." not in value:
136
+ continue
137
+
138
+ pos_args[index] = value.replace(".", "__")
139
+
125
140
  parser.add_argument(*pos_args, **opt_args)
126
141
 
127
142
 
@@ -1184,6 +1199,42 @@ def get_default_group_data() -> List[Tuple[List[str], dict]]:
1184
1199
  ]
1185
1200
 
1186
1201
 
1202
+ def platform_parser(
1203
+ parser: Union[argparse.ArgumentParser, argparse._SubParsersAction]
1204
+ ) -> None:
1205
+ """
1206
+ Adds the platform group to the given parser.
1207
+ """
1208
+
1209
+ platform = parser.add_parser(
1210
+ "platform",
1211
+ add_help=False,
1212
+ epilog=PyFunceble.cli.storage.STD_EPILOG,
1213
+ )
1214
+
1215
+ args = [
1216
+ (
1217
+ ["cli_testing.testing_mode.platform_contribution"],
1218
+ {
1219
+ "default": get_configured_value(
1220
+ "cli_testing.testing_mode.platform_contribution", value_only=True
1221
+ ),
1222
+ "action": "store_%s"
1223
+ % str(
1224
+ not get_configured_value(
1225
+ "cli_testing.testing_mode.platform_contribution",
1226
+ value_only=True,
1227
+ )
1228
+ ).lower(),
1229
+ "help": argparse.SUPPRESS,
1230
+ },
1231
+ )
1232
+ ]
1233
+
1234
+ add_arguments_to_parser(platform, args)
1235
+ add_arguments_to_parser(platform, get_default_group_data())
1236
+
1237
+
1187
1238
  def ask_authorization_to_merge_config(missing_key: Optional[str] = None) -> bool:
1188
1239
  """
1189
1240
  Asks the end-user for the authorization to merge the upstream
@@ -1292,6 +1343,8 @@ def tool() -> None:
1292
1343
 
1293
1344
  # pylint: disable=possibly-unused-variable
1294
1345
 
1346
+ command_sub = parser.add_subparsers(dest="command", help=argparse.SUPPRESS)
1347
+
1295
1348
  shtab.add_argument_to(
1296
1349
  parser,
1297
1350
  option_string=["--show-completion"],
@@ -1321,6 +1374,8 @@ def tool() -> None:
1321
1374
  get_ci_group_data,
1322
1375
  ]
1323
1376
 
1377
+ parse_funcs = [platform_parser]
1378
+
1324
1379
  for func in funcs:
1325
1380
  parser_name = func.__name__.replace("get_", "").replace("_data", "")
1326
1381
 
@@ -1348,10 +1403,21 @@ def tool() -> None:
1348
1403
  )
1349
1404
  sys.exit(1)
1350
1405
 
1406
+ for func in parse_funcs:
1407
+ func(command_sub)
1408
+
1351
1409
  add_arguments_to_parser(parser, get_default_group_data())
1352
1410
 
1353
1411
  args = parser.parse_args()
1354
1412
 
1355
- if any(getattr(args, x) for x in ["domains", "urls", "files", "url_files"]):
1413
+ if any(
1414
+ getattr(args, x)
1415
+ for x in [
1416
+ "domains",
1417
+ "urls",
1418
+ "files",
1419
+ "url_files",
1420
+ ]
1421
+ ) or bool(args.command):
1356
1422
  SystemIntegrator(args).start()
1357
1423
  SystemLauncher(args).start()
@@ -481,9 +481,9 @@ class FilePreloader:
481
481
  raise exception
482
482
 
483
483
  if not broken:
484
- self.__description[self.__matching_index][
485
- "previous_hash"
486
- ] = self.__description[self.__matching_index]["hash"]
484
+ self.__description[self.__matching_index]["previous_hash"] = (
485
+ self.__description[self.__matching_index]["hash"]
486
+ )
487
487
 
488
488
  self.__save_description()
489
489
 
@@ -50,7 +50,6 @@ License:
50
50
  limitations under the License.
51
51
  """
52
52
 
53
-
54
53
  from typing import Optional
55
54
 
56
55
  from sqlalchemy.orm import Session
@@ -115,9 +115,9 @@ class WorkerBase(multiprocessing.Process):
115
115
  self.input_queue = self._params["input_queue"] = input_queue
116
116
  self.output_queue = self._params["output_queue"] = output_queue
117
117
 
118
- self.continuous_integration = self._params[
119
- "continuous_integration"
120
- ] = continuous_integration
118
+ self.continuous_integration = self._params["continuous_integration"] = (
119
+ continuous_integration
120
+ )
121
121
 
122
122
  self.global_exit_event = self._params["global_exit_event"] = global_exit_event
123
123
  self.exit_it = multiprocessing.Event()
@@ -318,8 +318,10 @@ class WorkerBase(multiprocessing.Process):
318
318
 
319
319
  try:
320
320
  worker_name, destination_worker, consumed = self.input_queue.get()
321
- except EOFError:
322
- PyFunceble.facility.Logger.info("Got EOFError. Stopping worker.")
321
+ except (EOFError, KeyboardInterrupt):
322
+ PyFunceble.facility.Logger.info(
323
+ "Got EOFError/KeyboardInterrupt. Stopping worker."
324
+ )
323
325
  self.global_exit_event.set()
324
326
  break
325
327
 
@@ -370,7 +372,14 @@ class WorkerBase(multiprocessing.Process):
370
372
  self.share_waiting_message(apply_breakoff=wait_for_stop)
371
373
  continue
372
374
 
373
- result = self.target(consumed)
375
+ try:
376
+ result = self.target(consumed)
377
+ except (EOFError, KeyboardInterrupt):
378
+ PyFunceble.facility.Logger.info(
379
+ "Got EOFError/KeyboardInterrupt. Stopping worker."
380
+ )
381
+ self.global_exit_event.set()
382
+ break
374
383
 
375
384
  if result is not None:
376
385
  self.add_to_output_queue(result)
@@ -399,6 +399,11 @@ class ProducerWorker(WorkerBase):
399
399
  )
400
400
  return None
401
401
 
402
+ if test_dataset["type"] == "platform-contribution":
403
+ self.collection_query_tool.deliver_contract(
404
+ test_dataset["contract"], test_result
405
+ )
406
+
402
407
  if (
403
408
  PyFunceble.storage.CONFIGURATION.collection.push
404
409
  and test_result.status_source != "COLLECTION"
@@ -50,7 +50,6 @@ License:
50
50
  limitations under the License.
51
51
  """
52
52
 
53
-
54
53
  import copy
55
54
  import functools
56
55
  import os
@@ -516,9 +515,9 @@ class ProductionPrep:
516
515
  if to_append not in self.version_file_content["deprecated"]:
517
516
  self.version_file_content["deprecated"].append(to_append)
518
517
 
519
- self.version_file_content[
520
- "current_version"
521
- ] = PyFunceble.storage.PROJECT_VERSION
518
+ self.version_file_content["current_version"] = (
519
+ PyFunceble.storage.PROJECT_VERSION
520
+ )
522
521
 
523
522
  self.dict_helper.set_subject(self.version_file_content).to_yaml_file(
524
523
  self.VERSION_FILE_PATH
PyFunceble/cli/storage.py CHANGED
@@ -253,9 +253,11 @@ UNIVERSAL_OUTPUTS: dict = {
253
253
  }
254
254
 
255
255
  OUTPUTS: Optional[Box] = Box(
256
- Merge(UNIX_OUTPUTS).into(UNIVERSAL_OUTPUTS)
257
- if PlatformUtility.is_unix()
258
- else Merge(WIN_OUTPUTS).into(UNIVERSAL_OUTPUTS),
256
+ (
257
+ Merge(UNIX_OUTPUTS).into(UNIVERSAL_OUTPUTS)
258
+ if PlatformUtility.is_unix()
259
+ else Merge(WIN_OUTPUTS).into(UNIVERSAL_OUTPUTS)
260
+ ),
259
261
  frozen_box=True,
260
262
  )
261
263
 
@@ -119,6 +119,7 @@ from PyFunceble.dataset.inactive.base import InactiveDatasetBase
119
119
  from PyFunceble.helpers.directory import DirectoryHelper
120
120
  from PyFunceble.helpers.download import DownloadHelper
121
121
  from PyFunceble.helpers.file import FileHelper
122
+ from PyFunceble.query.collection import CollectionQueryTool
122
123
 
123
124
 
124
125
  class SystemLauncher(SystemBase):
@@ -222,7 +223,7 @@ class SystemLauncher(SystemBase):
222
223
  )
223
224
  self.producer_process_manager = ChancyProducerProcessesManager(
224
225
  self.manager,
225
- max_worker=1,
226
+ max_worker=PyFunceble.storage.CONFIGURATION.cli_testing.max_workers,
226
227
  continuous_integration=self.continuous_integration,
227
228
  input_queue=self.tester_process_manager.output_queue[0],
228
229
  daemon=True,
@@ -406,6 +407,21 @@ class SystemLauncher(SystemBase):
406
407
  "Added to the protocol:\n%r", to_append
407
408
  )
408
409
 
410
+ # pylint: disable=line-too-long
411
+ if (
412
+ PyFunceble.storage.CONFIGURATION.cli_testing.testing_mode.platform_contribution
413
+ ):
414
+ self.testing_protocol.append(
415
+ {
416
+ "type": "platform-contribution",
417
+ "subject_type": "any",
418
+ "destination": None,
419
+ "checker_type": None,
420
+ "output_dir": None,
421
+ "session_id": None,
422
+ }
423
+ )
424
+
409
425
  def ci_stop_in_the_middle_if_time_exceeded(self) -> "SystemLauncher":
410
426
  """
411
427
  Stops our processes as soon as the time is exceeded.
@@ -648,7 +664,37 @@ class SystemLauncher(SystemBase):
648
664
  )
649
665
  elif protocol["type"] == "file":
650
666
  handle_file(protocol)
667
+ elif protocol["type"] == "platform-contribution":
668
+ query_tool = CollectionQueryTool()
669
+
670
+ while True:
671
+ for next_contract in next(
672
+ query_tool.pull_contract(
673
+ PyFunceble.storage.CONFIGURATION.cli_testing.max_workers
674
+ )
675
+ ):
676
+ if (
677
+ "subject" not in next_contract
678
+ or not next_contract["subject"]
679
+ ):
680
+ continue
651
681
 
682
+ protocol_data = copy.deepcopy(protocol)
683
+
684
+ protocol_data["checker_type"] = next_contract[
685
+ "checker_type"
686
+ ].upper()
687
+ protocol_data["subject_type"] = next_contract["subject_type"]
688
+ protocol_data["subject"] = protocol_data["idna_subject"] = (
689
+ next_contract["subject"]["subject"]
690
+ )
691
+ protocol_data["contract"] = copy.deepcopy(next_contract)
692
+
693
+ self.tester_process_manager.add_to_input_queue(
694
+ protocol_data, worker_name="main"
695
+ )
696
+
697
+ self.ci_stop_in_the_middle_if_time_exceeded()
652
698
  return self
653
699
 
654
700
  def generate_waiting_files(self) -> "SystemLauncher":
@@ -232,9 +232,7 @@ def get_subjects_from_line(
232
232
  if cidr2subject is None:
233
233
  cidr2subject = CIDR2Subject()
234
234
 
235
- adblock_inputline2subject.aggressive = (
236
- wildcard2subject.aggressive
237
- ) = (
235
+ adblock_inputline2subject.aggressive = wildcard2subject.aggressive = (
238
236
  rpz_inputline2subject.aggressive
239
237
  ) = inputline2subject.aggressive = url2netloc.aggressive = bool(
240
238
  PyFunceble.storage.CONFIGURATION.cli_decoding.aggressive
@@ -172,6 +172,16 @@ class ConfigLoader:
172
172
  # If timeout is set to a negative digit, switch to the default one.
173
173
  config["lookup"]["timeout"] = 5
174
174
 
175
+ if (
176
+ "cli_testing" in config
177
+ and "testing_mode" in config["cli_testing"]
178
+ and "platform_contribution" in config["cli_testing"]["testing_mode"]
179
+ and config["cli_testing"]["testing_mode"]["platform_contribution"]
180
+ ):
181
+ # If we are under a special testing mode. We shouldn't generate
182
+ # any files
183
+ config["cli_testing"]["file_generation"]["no_file"] = True
184
+
175
185
  return config
176
186
 
177
187
  @staticmethod
@@ -5,6 +5,7 @@ Revises: ade87195b0a0
5
5
  Create Date: 2020-08-21 11:42:07.044762
6
6
 
7
7
  """
8
+
8
9
  from alembic import op
9
10
  from sqlalchemy.exc import OperationalError
10
11
 
@@ -5,6 +5,7 @@ Revises: 3d6f4a33cdb2
5
5
  Create Date: 2020-12-13 22:52:56.968513
6
6
 
7
7
  """
8
+
8
9
  import sqlalchemy as sa
9
10
  from alembic import op
10
11
 
@@ -5,6 +5,7 @@ Revises: 7bcf7fa64ba1
5
5
  Create Date: 2020-12-13 19:45:41.893657
6
6
 
7
7
  """
8
+
8
9
  import sqlalchemy as sa
9
10
  from alembic import op
10
11
 
@@ -5,6 +5,7 @@ Revises: e04e8301d1a2
5
5
  Create Date: 2020-12-07 12:36:04.818466
6
6
 
7
7
  """
8
+
8
9
  import sqlalchemy as sa
9
10
  from alembic import op
10
11
  from sqlalchemy.dialects import mysql
@@ -5,6 +5,7 @@ Revises: 45713fea8097
5
5
  Create Date: 2020-12-07 12:37:52.018637
6
6
 
7
7
  """
8
+
8
9
  import sqlalchemy as sa
9
10
  from alembic import op
10
11
 
@@ -5,6 +5,7 @@ Revises: 95dc17ddd729
5
5
  Create Date: 2021-02-13 12:21:00.493002
6
6
 
7
7
  """
8
+
8
9
  import sqlalchemy as sa
9
10
  from alembic import op
10
11
  from sqlalchemy.dialects import mysql
@@ -5,6 +5,7 @@ Revises: 83ada95132bf
5
5
  Create Date: 2020-12-08 17:34:59.349943
6
6
 
7
7
  """
8
+
8
9
  import sqlalchemy as sa
9
10
  from alembic import op
10
11
  from sqlalchemy.dialects import mysql
@@ -5,6 +5,7 @@ Revises: 459a0d7b8f09
5
5
  Create Date: 2020-12-07 12:49:48.797794
6
6
 
7
7
  """
8
+
8
9
  import sqlalchemy as sa
9
10
  from alembic import op
10
11
  from sqlalchemy.dialects import mysql
@@ -5,6 +5,7 @@ Revises: 6f4729deaf03
5
5
  Create Date: 2021-12-04 23:52:11.861732
6
6
 
7
7
  """
8
+
8
9
  import sqlalchemy as sa
9
10
  from alembic import op
10
11
 
@@ -5,6 +5,7 @@ Revises: bef7bcaac3f2
5
5
  Create Date: 2020-12-23 02:26:21.647125
6
6
 
7
7
  """
8
+
8
9
  import sqlalchemy as sa
9
10
  from alembic import op
10
11
 
@@ -5,6 +5,7 @@ Revises:
5
5
  Create Date: 2020-08-15 20:12:26.768419
6
6
 
7
7
  """
8
+
8
9
  import sqlalchemy as sa
9
10
  from alembic import op
10
11
 
@@ -5,6 +5,7 @@ Revises: 3a4c55a9320d
5
5
  Create Date: 2020-12-16 19:09:41.212679
6
6
 
7
7
  """
8
+
8
9
  import sqlalchemy as sa
9
10
  from alembic import op
10
11
  from sqlalchemy.dialects import mysql