PyFunceble-dev 4.2.28a1__py3-none-any.whl → 4.3.0a1__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.
- PyFunceble/cli/entry_points/pyfunceble/cli.py +22 -0
- PyFunceble/cli/filesystem/dir_structure/base.py +1 -2
- PyFunceble/cli/migrators/base.py +47 -1
- PyFunceble/cli/migrators/csv_file/inactive_source_delete.py +1 -1
- PyFunceble/cli/migrators/csv_file/whois_registrar_add.py +1 -1
- PyFunceble/cli/migrators/file_cleanup/hashes_file.py +1 -1
- PyFunceble/cli/migrators/file_cleanup/mining_file.py +1 -1
- PyFunceble/cli/migrators/file_cleanup/production_config_file.py +1 -1
- PyFunceble/cli/migrators/json2csv/inactive.py +1 -1
- PyFunceble/cli/migrators/json2csv/whois.py +1 -1
- PyFunceble/cli/scripts/production.py +67 -26
- PyFunceble/cli/system/integrator.py +51 -14
- PyFunceble/cli/system/launcher.py +17 -6
- PyFunceble/config/loader.py +146 -22
- PyFunceble/database/credential/base.py +46 -3
- PyFunceble/dataset/base.py +3 -3
- PyFunceble/dataset/csv_base.py +3 -1
- PyFunceble/dataset/db_base.py +44 -0
- PyFunceble/dataset/iana.py +3 -6
- PyFunceble/dataset/inactive/csv.py +4 -2
- PyFunceble/dataset/ipv4_reputation.py +5 -9
- PyFunceble/dataset/public_suffix.py +4 -8
- PyFunceble/dataset/user_agent.py +4 -7
- PyFunceble/dataset/whois/csv.py +1 -1
- PyFunceble/downloader/base.py +64 -5
- PyFunceble/downloader/iana.py +4 -11
- PyFunceble/downloader/ipv4_reputation.py +2 -11
- PyFunceble/downloader/public_suffix.py +5 -11
- PyFunceble/downloader/user_agents.py +5 -11
- PyFunceble/query/whois/query_tool.py +1 -0
- PyFunceble/storage.py +2 -19
- {PyFunceble_dev-4.2.28a1.dist-info → PyFunceble_dev-4.3.0a1.dist-info}/METADATA +67 -67
- {PyFunceble_dev-4.2.28a1.dist-info → PyFunceble_dev-4.3.0a1.dist-info}/RECORD +37 -37
- {PyFunceble_dev-4.2.28a1.dist-info → PyFunceble_dev-4.3.0a1.dist-info}/LICENSE +0 -0
- {PyFunceble_dev-4.2.28a1.dist-info → PyFunceble_dev-4.3.0a1.dist-info}/WHEEL +0 -0
- {PyFunceble_dev-4.2.28a1.dist-info → PyFunceble_dev-4.3.0a1.dist-info}/entry_points.txt +0 -0
- {PyFunceble_dev-4.2.28a1.dist-info → PyFunceble_dev-4.3.0a1.dist-info}/top_level.txt +0 -0
PyFunceble/config/loader.py
CHANGED
@@ -60,6 +60,7 @@ except ImportError: # pragma: no cover ## Retro compatibility
|
|
60
60
|
import importlib_resources as package_resources
|
61
61
|
|
62
62
|
from box import Box
|
63
|
+
from dotenv import load_dotenv
|
63
64
|
from yaml.error import MarkedYAMLError
|
64
65
|
|
65
66
|
import PyFunceble.cli.storage
|
@@ -69,6 +70,7 @@ from PyFunceble.downloader.iana import IANADownloader
|
|
69
70
|
from PyFunceble.downloader.public_suffix import PublicSuffixDownloader
|
70
71
|
from PyFunceble.downloader.user_agents import UserAgentsDownloader
|
71
72
|
from PyFunceble.helpers.dict import DictHelper
|
73
|
+
from PyFunceble.helpers.download import DownloadHelper
|
72
74
|
from PyFunceble.helpers.environment_variable import EnvironmentVariableHelper
|
73
75
|
from PyFunceble.helpers.file import FileHelper
|
74
76
|
from PyFunceble.helpers.merge import Merge
|
@@ -86,31 +88,42 @@ class ConfigLoader:
|
|
86
88
|
:code:`PYFUNCEBLE_AUTO_CONFIGURATION` environment variable.
|
87
89
|
"""
|
88
90
|
|
89
|
-
|
91
|
+
_path_to_config: Optional[str] = None
|
92
|
+
_remote_config_location: Optional[str] = None
|
90
93
|
path_to_default_config: Optional[str] = None
|
91
94
|
path_to_overwrite_config: Optional[str] = None
|
92
95
|
|
93
96
|
_custom_config: dict = {}
|
94
97
|
_merge_upstream: bool = False
|
98
|
+
_config_dir: Optional[str] = None
|
95
99
|
|
96
100
|
file_helper: FileHelper = FileHelper()
|
97
101
|
dict_helper: DictHelper = DictHelper()
|
98
102
|
|
99
|
-
def __init__(
|
103
|
+
def __init__(
|
104
|
+
self, merge_upstream: Optional[bool] = None, *, config_dir: Optional[str] = None
|
105
|
+
) -> None:
|
100
106
|
with package_resources.path(
|
101
107
|
"PyFunceble.data.infrastructure",
|
102
108
|
PyFunceble.storage.DISTRIBUTED_CONFIGURATION_FILENAME,
|
103
109
|
) as file_path:
|
104
110
|
self.path_to_default_config = str(file_path)
|
105
111
|
|
112
|
+
if config_dir is not None:
|
113
|
+
self.config_dir = config_dir
|
114
|
+
else:
|
115
|
+
self.config_dir = PyFunceble.storage.CONFIG_DIRECTORY
|
116
|
+
|
106
117
|
self.path_to_config = os.path.join(
|
107
|
-
|
118
|
+
self.config_dir,
|
108
119
|
PyFunceble.storage.CONFIGURATION_FILENAME,
|
109
120
|
)
|
110
121
|
|
122
|
+
self.path_to_remote_config = None
|
123
|
+
|
111
124
|
self.path_to_overwrite_config = os.path.join(
|
112
|
-
|
113
|
-
PyFunceble.
|
125
|
+
self.config_dir,
|
126
|
+
".PyFunceble.overwrite.yaml",
|
114
127
|
)
|
115
128
|
|
116
129
|
if merge_upstream is not None:
|
@@ -132,7 +145,7 @@ class ConfigLoader:
|
|
132
145
|
result = func(self, *args, **kwargs) # pylint: disable=not-callable
|
133
146
|
|
134
147
|
if self.is_already_loaded():
|
135
|
-
self.
|
148
|
+
self.reload(keep_custom=True)
|
136
149
|
|
137
150
|
return result
|
138
151
|
|
@@ -200,6 +213,44 @@ class ConfigLoader:
|
|
200
213
|
|
201
214
|
return bool(PyFunceble.storage.CONFIGURATION)
|
202
215
|
|
216
|
+
@property
|
217
|
+
def config_dir(self) -> Optional[str]:
|
218
|
+
"""
|
219
|
+
Provides the current state of the :code:`_config_dir` attribute.
|
220
|
+
"""
|
221
|
+
|
222
|
+
return self._config_dir
|
223
|
+
|
224
|
+
@config_dir.setter
|
225
|
+
@reload_config
|
226
|
+
def config_dir(self, value: str) -> None:
|
227
|
+
"""
|
228
|
+
Sets the configuration directory.
|
229
|
+
|
230
|
+
:param value:
|
231
|
+
The value to set.
|
232
|
+
|
233
|
+
:raise TypeError:
|
234
|
+
When value is not a :py:class:`str`.
|
235
|
+
"""
|
236
|
+
|
237
|
+
if not isinstance(value, str):
|
238
|
+
raise TypeError(f"<value> should be {str}, {type(value)} given.")
|
239
|
+
|
240
|
+
self._config_dir = value
|
241
|
+
|
242
|
+
def set_config_dir(self, value: str) -> "ConfigLoader":
|
243
|
+
"""
|
244
|
+
Sets the configuration directory.
|
245
|
+
|
246
|
+
:param value:
|
247
|
+
The value to set.
|
248
|
+
"""
|
249
|
+
|
250
|
+
self.config_dir = value
|
251
|
+
|
252
|
+
return self
|
253
|
+
|
203
254
|
@property
|
204
255
|
def custom_config(self) -> dict:
|
205
256
|
"""
|
@@ -274,23 +325,44 @@ class ConfigLoader:
|
|
274
325
|
|
275
326
|
return self
|
276
327
|
|
277
|
-
|
278
|
-
|
279
|
-
) -> bool: # pragma: no cover ## Existance checker already tested.
|
328
|
+
@property
|
329
|
+
def remote_config_location(self) -> Optional[str]:
|
280
330
|
"""
|
281
|
-
|
331
|
+
Provides the current state of the :code:`_remote_config_location` attribute.
|
282
332
|
"""
|
283
333
|
|
284
|
-
return
|
334
|
+
return self._remote_config_location
|
285
335
|
|
286
|
-
|
287
|
-
|
288
|
-
) -> bool: # pragma: no cover ## Existance checker already tested.
|
336
|
+
@remote_config_location.setter
|
337
|
+
def remote_config_location(self, value: Optional[str]) -> None:
|
289
338
|
"""
|
290
|
-
|
339
|
+
Updates the value of :code:`_remote_config_location` attribute.
|
340
|
+
|
341
|
+
:raise TypeError:
|
342
|
+
When :code:`value` is not a :py:class:`str`.
|
291
343
|
"""
|
292
344
|
|
293
|
-
|
345
|
+
if value is not None and not isinstance(value, str):
|
346
|
+
raise TypeError(f"<value> should be {str}, {type(value)} given.")
|
347
|
+
|
348
|
+
if not value.startswith("http") and not value.startswith("https"):
|
349
|
+
self.path_to_remote_config = os.path.realpath(value)
|
350
|
+
else:
|
351
|
+
self.path_to_remote_config = os.path.join(
|
352
|
+
self.config_dir,
|
353
|
+
".PyFunceble.remote.yaml",
|
354
|
+
)
|
355
|
+
|
356
|
+
self._remote_config_location = value
|
357
|
+
|
358
|
+
def set_remote_config_location(self, value: Optional[str]) -> "ConfigLoader":
|
359
|
+
"""
|
360
|
+
Updates the value of :code:`_remote_config_location` attribute.
|
361
|
+
"""
|
362
|
+
|
363
|
+
self.remote_config_location = value
|
364
|
+
|
365
|
+
return self
|
294
366
|
|
295
367
|
def install_missing_infrastructure_files(
|
296
368
|
self,
|
@@ -347,9 +419,34 @@ class ConfigLoader:
|
|
347
419
|
|
348
420
|
return config and "days_between_inactive_db_clean" in config
|
349
421
|
|
422
|
+
def download_remote_config(src: str, dest: str = None) -> None:
|
423
|
+
"""
|
424
|
+
Downloads the remote configuration.
|
425
|
+
|
426
|
+
:param src:
|
427
|
+
The source to download from.
|
428
|
+
:param dest:
|
429
|
+
The destination to download
|
430
|
+
"""
|
431
|
+
|
432
|
+
if src and (src.startswith("http") or src.startswith("https")):
|
433
|
+
if dest is None:
|
434
|
+
destination = os.path.join(
|
435
|
+
self.config_dir,
|
436
|
+
os.path.basename(dest),
|
437
|
+
)
|
438
|
+
else:
|
439
|
+
destination = dest
|
440
|
+
|
441
|
+
DownloadHelper(src).download_text(destination=destination)
|
442
|
+
|
350
443
|
if not self.is_already_loaded():
|
351
444
|
self.install_missing_infrastructure_files()
|
352
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)
|
353
450
|
|
354
451
|
try:
|
355
452
|
config = self.dict_helper.from_yaml_file(self.path_to_config)
|
@@ -377,15 +474,22 @@ class ConfigLoader:
|
|
377
474
|
|
378
475
|
self.dict_helper.set_subject(config).to_yaml_file(self.path_to_config)
|
379
476
|
|
477
|
+
if (
|
478
|
+
self.path_to_remote_config
|
479
|
+
and self.file_helper.set_path(self.path_to_remote_config).exists()
|
480
|
+
):
|
481
|
+
remote_data = self.dict_helper.from_yaml_file(self.path_to_remote_config)
|
482
|
+
|
483
|
+
if isinstance(remote_data, dict):
|
484
|
+
config = Merge(remote_data).into(config)
|
485
|
+
|
380
486
|
if self.file_helper.set_path(self.path_to_overwrite_config).exists():
|
381
487
|
overwrite_data = self.dict_helper.from_yaml_file(
|
382
488
|
self.path_to_overwrite_config
|
383
489
|
)
|
384
490
|
|
385
491
|
if isinstance(overwrite_data, dict):
|
386
|
-
config = Merge(
|
387
|
-
self.dict_helper.from_yaml_file(self.path_to_overwrite_config)
|
388
|
-
).into(config)
|
492
|
+
config = Merge(overwrite_data).into(config)
|
389
493
|
else: # pragma: no cover ## Just make it visible to end-user.
|
390
494
|
self.file_helper.write("")
|
391
495
|
|
@@ -415,11 +519,26 @@ class ConfigLoader:
|
|
415
519
|
|
416
520
|
return PyFunceble.storage.FLATTEN_CONFIGURATION[entry]
|
417
521
|
|
522
|
+
def reload(self, keep_custom: bool = False) -> "ConfigLoader":
|
523
|
+
"""
|
524
|
+
Reloads the configuration.
|
525
|
+
|
526
|
+
:param bool keep_custom:
|
527
|
+
If set to :code:`True`, we keep the custom configuration, otherwise
|
528
|
+
we delete it.
|
529
|
+
"""
|
530
|
+
|
531
|
+
self.destroy(keep_custom=keep_custom)
|
532
|
+
self.start()
|
533
|
+
|
418
534
|
def start(self) -> "ConfigLoader":
|
419
535
|
"""
|
420
536
|
Starts the loading processIs.
|
421
537
|
"""
|
422
538
|
|
539
|
+
load_dotenv(os.path.join(self.config_dir, ".env"))
|
540
|
+
load_dotenv(os.path.join(self.config_dir, PyFunceble.storage.ENV_FILENAME))
|
541
|
+
|
423
542
|
config = self.get_config_file_content()
|
424
543
|
|
425
544
|
if self.custom_config:
|
@@ -445,9 +564,13 @@ class ConfigLoader:
|
|
445
564
|
|
446
565
|
return self
|
447
566
|
|
448
|
-
def destroy(self) -> "ConfigLoader":
|
567
|
+
def destroy(self, keep_custom: bool = False) -> "ConfigLoader":
|
449
568
|
"""
|
450
569
|
Destroys everything loaded.
|
570
|
+
|
571
|
+
:param bool keep_custom:
|
572
|
+
If set to :code:`True`, we keep the custom configuration, otherwise
|
573
|
+
we delete it.
|
451
574
|
"""
|
452
575
|
|
453
576
|
try:
|
@@ -462,7 +585,8 @@ class ConfigLoader:
|
|
462
585
|
except (AttributeError, TypeError): # pragma: no cover ## Safety.
|
463
586
|
pass
|
464
587
|
|
465
|
-
|
466
|
-
|
588
|
+
if not keep_custom:
|
589
|
+
# This is not a mistake.
|
590
|
+
self._custom_config = {}
|
467
591
|
|
468
592
|
return self
|
@@ -100,6 +100,8 @@ class CredentialBase:
|
|
100
100
|
_password: Optional[str] = None
|
101
101
|
_charset: Optional[str] = None
|
102
102
|
|
103
|
+
_config_dir: Optional[str] = None
|
104
|
+
|
103
105
|
def __init__(
|
104
106
|
self,
|
105
107
|
*,
|
@@ -109,6 +111,7 @@ class CredentialBase:
|
|
109
111
|
username: Optional[str] = None,
|
110
112
|
password: Optional[str] = None,
|
111
113
|
charset: Optional[str] = None,
|
114
|
+
config_dir: Optional[str] = None,
|
112
115
|
) -> None:
|
113
116
|
if host is not None:
|
114
117
|
self.host = host
|
@@ -140,11 +143,14 @@ class CredentialBase:
|
|
140
143
|
else:
|
141
144
|
self.charset = self.STD_CHARSET
|
142
145
|
|
146
|
+
if config_dir is not None:
|
147
|
+
self.config_dir = config_dir
|
148
|
+
else:
|
149
|
+
self.config_dir = PyFunceble.storage.CONFIG_DIRECTORY
|
150
|
+
|
143
151
|
self.dotenv_locations = [
|
144
152
|
os.path.realpath(PyFunceble.storage.ENV_FILENAME),
|
145
|
-
os.path.join(
|
146
|
-
PyFunceble.storage.CONFIG_DIRECTORY, PyFunceble.storage.ENV_FILENAME
|
147
|
-
),
|
153
|
+
os.path.join(self.config_dir, PyFunceble.storage.ENV_FILENAME),
|
148
154
|
]
|
149
155
|
|
150
156
|
def ensure_protocol_is_given(func): # pylint: disable=no-self-argument
|
@@ -165,6 +171,43 @@ class CredentialBase:
|
|
165
171
|
|
166
172
|
return wrapper
|
167
173
|
|
174
|
+
@property
|
175
|
+
def config_dir(self) -> Optional[str]:
|
176
|
+
"""
|
177
|
+
Provides the current state of the :code:`_config_dir` attribute.
|
178
|
+
"""
|
179
|
+
|
180
|
+
return self._config_dir
|
181
|
+
|
182
|
+
@config_dir.setter
|
183
|
+
def config_dir(self, value: str) -> None:
|
184
|
+
"""
|
185
|
+
Sets the configuration directory.
|
186
|
+
|
187
|
+
:param value:
|
188
|
+
The value to set.
|
189
|
+
|
190
|
+
:raise TypeError:
|
191
|
+
When value is not a :py:class:`str`.
|
192
|
+
"""
|
193
|
+
|
194
|
+
if not isinstance(value, str):
|
195
|
+
raise TypeError(f"<value> should be {str}, {type(value)} given.")
|
196
|
+
|
197
|
+
self._config_dir = value
|
198
|
+
|
199
|
+
def set_config_dir(self, value: str) -> "CredentialBase":
|
200
|
+
"""
|
201
|
+
Sets the configuration directory.
|
202
|
+
|
203
|
+
:param value:
|
204
|
+
The value to set.
|
205
|
+
"""
|
206
|
+
|
207
|
+
self.config_dir = value
|
208
|
+
|
209
|
+
return self
|
210
|
+
|
168
211
|
@property
|
169
212
|
def host(self) -> Optional[str]:
|
170
213
|
"""
|
PyFunceble/dataset/base.py
CHANGED
@@ -65,7 +65,7 @@ class DatasetBase:
|
|
65
65
|
"""
|
66
66
|
|
67
67
|
STORAGE_INDEX: Optional[str] = None
|
68
|
-
|
68
|
+
downloader: Optional[DownloaderBase] = None
|
69
69
|
|
70
70
|
source_file: Optional[str] = None
|
71
71
|
|
@@ -129,9 +129,9 @@ class DatasetBase:
|
|
129
129
|
file_helper = FileHelper(self.source_file)
|
130
130
|
|
131
131
|
if not file_helper.exists() and bool(
|
132
|
-
self.
|
132
|
+
self.downloader
|
133
133
|
): # pragma: no cover ## This is just a safety endpoint.
|
134
|
-
self.
|
134
|
+
self.downloader.start()
|
135
135
|
|
136
136
|
if not file_helper.exists():
|
137
137
|
raise FileNotFoundError(file_helper.path)
|
PyFunceble/dataset/csv_base.py
CHANGED
@@ -208,7 +208,9 @@ class CSVDatasetBase(DBDatasetBase):
|
|
208
208
|
for row in reader:
|
209
209
|
if "tested_at" in row:
|
210
210
|
try:
|
211
|
-
row["tested_at"] = datetime.fromisoformat(
|
211
|
+
row["tested_at"] = datetime.fromisoformat(
|
212
|
+
row["tested_at"]
|
213
|
+
).astimezone(timezone.utc)
|
212
214
|
except (TypeError, ValueError):
|
213
215
|
row["tested_at"] = datetime.now(timezone.utc) - timedelta(
|
214
216
|
days=365
|
PyFunceble/dataset/db_base.py
CHANGED
@@ -53,6 +53,7 @@ License:
|
|
53
53
|
import functools
|
54
54
|
from typing import Any, Generator, List, Optional
|
55
55
|
|
56
|
+
import PyFunceble.storage
|
56
57
|
from PyFunceble.dataset.base import DatasetBase
|
57
58
|
|
58
59
|
|
@@ -77,7 +78,13 @@ class DBDatasetBase(DatasetBase):
|
|
77
78
|
*,
|
78
79
|
authorized: Optional[bool] = None,
|
79
80
|
remove_unneeded_fields: Optional[bool] = None,
|
81
|
+
config_dir: Optional[str] = None,
|
80
82
|
) -> None:
|
83
|
+
if config_dir is not None:
|
84
|
+
self.config_dir = config_dir
|
85
|
+
else:
|
86
|
+
self.config_dir = PyFunceble.storage.CONFIG_DIRECTORY
|
87
|
+
|
81
88
|
if authorized is not None:
|
82
89
|
self.set_authorized(authorized)
|
83
90
|
|
@@ -108,6 +115,43 @@ class DBDatasetBase(DatasetBase):
|
|
108
115
|
|
109
116
|
return inner_metdhod
|
110
117
|
|
118
|
+
@property
|
119
|
+
def config_dir(self) -> Optional[str]:
|
120
|
+
"""
|
121
|
+
Provides the current state of the :code:`_config_dir` attribute.
|
122
|
+
"""
|
123
|
+
|
124
|
+
return self._config_dir
|
125
|
+
|
126
|
+
@config_dir.setter
|
127
|
+
def config_dir(self, value: str) -> None:
|
128
|
+
"""
|
129
|
+
Sets the configuration directory.
|
130
|
+
|
131
|
+
:param value:
|
132
|
+
The value to set.
|
133
|
+
|
134
|
+
:raise TypeError:
|
135
|
+
When value is not a :py:class:`str`.
|
136
|
+
"""
|
137
|
+
|
138
|
+
if not isinstance(value, str):
|
139
|
+
raise TypeError(f"<value> should be {str}, {type(value)} given.")
|
140
|
+
|
141
|
+
self._config_dir = value
|
142
|
+
|
143
|
+
def set_config_dir(self, value: str) -> "DBDatasetBase":
|
144
|
+
"""
|
145
|
+
Sets the configuration directory.
|
146
|
+
|
147
|
+
:param value:
|
148
|
+
The value to set.
|
149
|
+
"""
|
150
|
+
|
151
|
+
self.config_dir = value
|
152
|
+
|
153
|
+
return self
|
154
|
+
|
111
155
|
@property
|
112
156
|
def authorized(self) -> Optional[bool]:
|
113
157
|
"""
|
PyFunceble/dataset/iana.py
CHANGED
@@ -50,10 +50,8 @@ License:
|
|
50
50
|
limitations under the License.
|
51
51
|
"""
|
52
52
|
|
53
|
-
import os
|
54
53
|
from typing import Any, Optional
|
55
54
|
|
56
|
-
import PyFunceble.storage
|
57
55
|
from PyFunceble.dataset.base import DatasetBase
|
58
56
|
from PyFunceble.downloader.iana import IANADownloader
|
59
57
|
|
@@ -64,12 +62,11 @@ class IanaDataset(DatasetBase):
|
|
64
62
|
"""
|
65
63
|
|
66
64
|
STORAGE_INDEX: str = "IANA"
|
67
|
-
|
65
|
+
downloader: Optional[IANADownloader] = None
|
68
66
|
|
69
67
|
def __init__(self) -> None:
|
70
|
-
self.
|
71
|
-
|
72
|
-
)
|
68
|
+
self.downloader = IANADownloader()
|
69
|
+
self.source_file = self.downloader.destination
|
73
70
|
|
74
71
|
def __contains__(self, value: Any) -> bool:
|
75
72
|
if value.startswith("."):
|
@@ -68,7 +68,7 @@ class CSVInactiveDataset(CSVDatasetBase, InactiveDatasetBase):
|
|
68
68
|
|
69
69
|
def __post_init__(self) -> None:
|
70
70
|
self.source_file = os.path.join(
|
71
|
-
|
71
|
+
self.config_dir, PyFunceble.cli.storage.INACTIVE_DB_FILE
|
72
72
|
)
|
73
73
|
|
74
74
|
return super().__post_init__()
|
@@ -84,7 +84,9 @@ class CSVInactiveDataset(CSVDatasetBase, InactiveDatasetBase):
|
|
84
84
|
):
|
85
85
|
if not isinstance(dataset["tested_at"], datetime):
|
86
86
|
try:
|
87
|
-
date_of_inclusion = datetime.fromisoformat(
|
87
|
+
date_of_inclusion = datetime.fromisoformat(
|
88
|
+
dataset["tested_at"]
|
89
|
+
).astimezone(timezone.utc)
|
88
90
|
except (TypeError, ValueError):
|
89
91
|
date_of_inclusion = datetime.now(timezone.utc) - timedelta(days=365)
|
90
92
|
else:
|
@@ -50,10 +50,8 @@ License:
|
|
50
50
|
limitations under the License.
|
51
51
|
"""
|
52
52
|
|
53
|
-
import os
|
54
53
|
from typing import Any, Optional
|
55
54
|
|
56
|
-
import PyFunceble.storage
|
57
55
|
from PyFunceble.dataset.base import DatasetBase
|
58
56
|
from PyFunceble.downloader.ipv4_reputation import IPV4ReputationDownloader
|
59
57
|
from PyFunceble.helpers.file import FileHelper
|
@@ -65,13 +63,11 @@ class IPV4ReputationDataset(DatasetBase):
|
|
65
63
|
"""
|
66
64
|
|
67
65
|
STORAGE_INDEX: Optional[str] = None
|
68
|
-
|
66
|
+
downloader: Optional[IPV4ReputationDownloader] = None
|
69
67
|
|
70
68
|
def __init__(self) -> None:
|
71
|
-
self.
|
72
|
-
|
73
|
-
PyFunceble.storage.IPV4_REPUTATION_FILENAME,
|
74
|
-
)
|
69
|
+
self.downloader = IPV4ReputationDownloader()
|
70
|
+
self.source_file = self.downloader.destination
|
75
71
|
|
76
72
|
def __contains__(self, value: Any) -> bool:
|
77
73
|
with self.get_content() as file_stream:
|
@@ -95,9 +91,9 @@ class IPV4ReputationDataset(DatasetBase):
|
|
95
91
|
|
96
92
|
file_helper = FileHelper(self.source_file)
|
97
93
|
|
98
|
-
if not file_helper.exists() and bool(self.
|
94
|
+
if not file_helper.exists() and bool(self.downloader): # pragma: no cover
|
99
95
|
## pragma reason: Safety.
|
100
|
-
self.
|
96
|
+
self.downloader.start()
|
101
97
|
|
102
98
|
if not file_helper.exists():
|
103
99
|
raise FileNotFoundError(file_helper.path)
|
@@ -50,10 +50,8 @@ License:
|
|
50
50
|
limitations under the License.
|
51
51
|
"""
|
52
52
|
|
53
|
-
import
|
54
|
-
from typing import Any, List
|
53
|
+
from typing import Any, List, Optional
|
55
54
|
|
56
|
-
import PyFunceble.storage
|
57
55
|
from PyFunceble.dataset.base import DatasetBase
|
58
56
|
from PyFunceble.downloader.public_suffix import PublicSuffixDownloader
|
59
57
|
|
@@ -64,13 +62,11 @@ class PublicSuffixDataset(DatasetBase):
|
|
64
62
|
"""
|
65
63
|
|
66
64
|
STORAGE_INDEX: str = "PUBLIC_SUFFIX"
|
67
|
-
|
65
|
+
downloader: Optional[PublicSuffixDownloader] = None
|
68
66
|
|
69
67
|
def __init__(self) -> None:
|
70
|
-
self.
|
71
|
-
|
72
|
-
PyFunceble.storage.PUBLIC_SUFFIX_DUMP_FILENAME,
|
73
|
-
)
|
68
|
+
self.downloader = PublicSuffixDownloader()
|
69
|
+
self.source_file = self.downloader.destination
|
74
70
|
|
75
71
|
def __contains__(self, value: Any) -> bool:
|
76
72
|
if value.startswith("."):
|
PyFunceble/dataset/user_agent.py
CHANGED
@@ -50,9 +50,8 @@ License:
|
|
50
50
|
limitations under the License.
|
51
51
|
"""
|
52
52
|
|
53
|
-
import os
|
54
53
|
import secrets
|
55
|
-
from typing import Any
|
54
|
+
from typing import Any, Optional
|
56
55
|
from warnings import warn
|
57
56
|
|
58
57
|
import PyFunceble.storage
|
@@ -66,16 +65,14 @@ class UserAgentDataset(DatasetBase):
|
|
66
65
|
"""
|
67
66
|
|
68
67
|
STORAGE_INDEX: str = "USER_AGENTS"
|
69
|
-
|
68
|
+
downloader: Optional[UserAgentsDownloader] = None
|
70
69
|
|
71
70
|
preferred_browser: str = "chrome"
|
72
71
|
preferred_platform: str = "linux"
|
73
72
|
|
74
73
|
def __init__(self) -> None:
|
75
|
-
self.
|
76
|
-
|
77
|
-
PyFunceble.storage.USER_AGENT_FILENAME,
|
78
|
-
)
|
74
|
+
self.downloader = UserAgentsDownloader()
|
75
|
+
self.source_file = self.downloader.destination
|
79
76
|
|
80
77
|
def __contains__(self, value: Any) -> bool:
|
81
78
|
content = self.get_content()
|
PyFunceble/dataset/whois/csv.py
CHANGED
@@ -67,7 +67,7 @@ class CSVWhoisDataset(CSVDatasetBase, WhoisDatasetBase):
|
|
67
67
|
|
68
68
|
def __post_init__(self) -> None:
|
69
69
|
self.source_file = os.path.join(
|
70
|
-
|
70
|
+
self.config_dir, PyFunceble.cli.storage.WHOIS_DB_FILE
|
71
71
|
)
|
72
72
|
|
73
73
|
return super().__post_init__()
|