atomicshop 2.11.47__py3-none-any.whl → 3.10.5__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.
- atomicshop/__init__.py +1 -1
- atomicshop/{addons/mains → a_mains}/FACT/update_extract.py +3 -2
- atomicshop/a_mains/addons/process_list/compile.cmd +7 -0
- atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.dll +0 -0
- atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.exp +0 -0
- atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.lib +0 -0
- atomicshop/{addons → a_mains/addons}/process_list/process_list.cpp +8 -1
- atomicshop/a_mains/dns_gateway_setting.py +11 -0
- atomicshop/a_mains/get_local_tcp_ports.py +85 -0
- atomicshop/a_mains/github_wrapper.py +11 -0
- atomicshop/a_mains/install_ca_certificate.py +172 -0
- atomicshop/{addons/mains → a_mains}/msi_unpacker.py +3 -1
- atomicshop/a_mains/process_from_port.py +119 -0
- atomicshop/a_mains/set_default_dns_gateway.py +90 -0
- atomicshop/a_mains/update_config_toml.py +38 -0
- atomicshop/appointment_management.py +5 -3
- atomicshop/basics/ansi_escape_codes.py +3 -1
- atomicshop/basics/argparse_template.py +2 -0
- atomicshop/basics/booleans.py +27 -30
- atomicshop/basics/bytes_arrays.py +43 -0
- atomicshop/basics/classes.py +149 -1
- atomicshop/basics/dicts.py +12 -0
- atomicshop/basics/enums.py +2 -2
- atomicshop/basics/exceptions.py +5 -1
- atomicshop/basics/list_of_classes.py +29 -0
- atomicshop/basics/list_of_dicts.py +69 -5
- atomicshop/basics/lists.py +14 -0
- atomicshop/basics/multiprocesses.py +374 -50
- atomicshop/basics/package_module.py +10 -0
- atomicshop/basics/strings.py +160 -7
- atomicshop/basics/threads.py +14 -0
- atomicshop/basics/tracebacks.py +13 -4
- atomicshop/certificates.py +153 -52
- atomicshop/config_init.py +12 -7
- atomicshop/console_user_response.py +7 -14
- atomicshop/consoles.py +9 -0
- atomicshop/datetimes.py +98 -0
- atomicshop/diff_check.py +340 -40
- atomicshop/dns.py +128 -12
- atomicshop/etws/_pywintrace_fix.py +17 -0
- atomicshop/etws/const.py +38 -0
- atomicshop/etws/providers.py +21 -0
- atomicshop/etws/sessions.py +43 -0
- atomicshop/etws/trace.py +168 -0
- atomicshop/etws/traces/trace_dns.py +162 -0
- atomicshop/etws/traces/trace_sysmon_process_creation.py +126 -0
- atomicshop/etws/traces/trace_tcp.py +130 -0
- atomicshop/file_io/csvs.py +222 -24
- atomicshop/file_io/docxs.py +35 -18
- atomicshop/file_io/file_io.py +35 -19
- atomicshop/file_io/jsons.py +49 -0
- atomicshop/file_io/tomls.py +139 -0
- atomicshop/filesystem.py +864 -293
- atomicshop/get_process_list.py +133 -0
- atomicshop/{process_name_cmd.py → get_process_name_cmd_dll.py} +52 -19
- atomicshop/http_parse.py +149 -93
- atomicshop/ip_addresses.py +6 -1
- atomicshop/mitm/centered_settings.py +132 -0
- atomicshop/mitm/config_static.py +207 -0
- atomicshop/mitm/config_toml_editor.py +55 -0
- atomicshop/mitm/connection_thread_worker.py +875 -357
- atomicshop/mitm/engines/__parent/parser___parent.py +4 -17
- atomicshop/mitm/engines/__parent/recorder___parent.py +108 -51
- atomicshop/mitm/engines/__parent/requester___parent.py +116 -0
- atomicshop/mitm/engines/__parent/responder___parent.py +75 -114
- atomicshop/mitm/engines/__reference_general/parser___reference_general.py +10 -7
- atomicshop/mitm/engines/__reference_general/recorder___reference_general.py +5 -5
- atomicshop/mitm/engines/__reference_general/requester___reference_general.py +47 -0
- atomicshop/mitm/engines/__reference_general/responder___reference_general.py +95 -13
- atomicshop/mitm/engines/create_module_template.py +58 -14
- atomicshop/mitm/import_config.py +359 -139
- atomicshop/mitm/initialize_engines.py +160 -74
- atomicshop/mitm/message.py +64 -23
- atomicshop/mitm/mitm_main.py +892 -0
- atomicshop/mitm/recs_files.py +183 -0
- atomicshop/mitm/shared_functions.py +4 -10
- atomicshop/mitm/ssh_tester.py +82 -0
- atomicshop/mitm/statistic_analyzer.py +257 -166
- atomicshop/mitm/statistic_analyzer_helper/analyzer_helper.py +136 -0
- atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py +525 -0
- atomicshop/monitor/change_monitor.py +96 -120
- atomicshop/monitor/checks/dns.py +139 -70
- atomicshop/monitor/checks/file.py +77 -0
- atomicshop/monitor/checks/network.py +81 -77
- atomicshop/monitor/checks/process_running.py +33 -34
- atomicshop/monitor/checks/url.py +94 -0
- atomicshop/networks.py +671 -0
- atomicshop/on_exit.py +205 -0
- atomicshop/package_mains_processor.py +84 -0
- atomicshop/permissions/permissions.py +22 -0
- atomicshop/permissions/ubuntu_permissions.py +239 -0
- atomicshop/permissions/win_permissions.py +33 -0
- atomicshop/print_api.py +24 -41
- atomicshop/process.py +63 -17
- atomicshop/process_poller/__init__.py +0 -0
- atomicshop/process_poller/pollers/__init__.py +0 -0
- atomicshop/process_poller/pollers/psutil_pywin32wmi_dll.py +95 -0
- atomicshop/process_poller/process_pool.py +207 -0
- atomicshop/process_poller/simple_process_pool.py +311 -0
- atomicshop/process_poller/tracer_base.py +45 -0
- atomicshop/process_poller/tracers/__init__.py +0 -0
- atomicshop/process_poller/tracers/event_log.py +46 -0
- atomicshop/process_poller/tracers/sysmon_etw.py +68 -0
- atomicshop/python_file_patcher.py +1 -1
- atomicshop/python_functions.py +27 -75
- atomicshop/question_answer_engine.py +2 -2
- atomicshop/scheduling.py +24 -5
- atomicshop/sound.py +4 -2
- atomicshop/speech_recognize.py +8 -0
- atomicshop/ssh_remote.py +158 -172
- atomicshop/startup/__init__.py +0 -0
- atomicshop/startup/win/__init__.py +0 -0
- atomicshop/startup/win/startup_folder.py +53 -0
- atomicshop/startup/win/task_scheduler.py +119 -0
- atomicshop/system_resource_monitor.py +61 -46
- atomicshop/system_resources.py +8 -8
- atomicshop/tempfiles.py +1 -2
- atomicshop/timer.py +30 -11
- atomicshop/urls.py +41 -0
- atomicshop/venvs.py +28 -0
- atomicshop/versioning.py +27 -0
- atomicshop/web.py +110 -25
- atomicshop/web_apis/__init__.py +0 -0
- atomicshop/web_apis/google_custom_search.py +44 -0
- atomicshop/web_apis/google_llm.py +188 -0
- atomicshop/websocket_parse.py +450 -0
- atomicshop/wrappers/certauthw/certauth.py +1 -0
- atomicshop/wrappers/cryptographyw.py +29 -8
- atomicshop/wrappers/ctyping/etw_winapi/__init__.py +0 -0
- atomicshop/wrappers/ctyping/etw_winapi/const.py +335 -0
- atomicshop/wrappers/ctyping/etw_winapi/etw_functions.py +393 -0
- atomicshop/wrappers/ctyping/file_details_winapi.py +67 -0
- atomicshop/wrappers/ctyping/msi_windows_installer/cabs.py +2 -1
- atomicshop/wrappers/ctyping/msi_windows_installer/extract_msi_main.py +13 -9
- atomicshop/wrappers/ctyping/msi_windows_installer/tables.py +35 -0
- atomicshop/wrappers/ctyping/setup_device.py +466 -0
- atomicshop/wrappers/ctyping/win_console.py +39 -0
- atomicshop/wrappers/dockerw/dockerw.py +113 -2
- atomicshop/wrappers/elasticsearchw/config_basic.py +0 -12
- atomicshop/wrappers/elasticsearchw/elastic_infra.py +75 -0
- atomicshop/wrappers/elasticsearchw/elasticsearchw.py +2 -20
- atomicshop/wrappers/factw/get_file_data.py +12 -5
- atomicshop/wrappers/factw/install/install_after_restart.py +89 -5
- atomicshop/wrappers/factw/install/pre_install_and_install_before_restart.py +20 -14
- atomicshop/wrappers/factw/postgresql/firmware.py +4 -6
- atomicshop/wrappers/githubw.py +583 -51
- atomicshop/wrappers/loggingw/consts.py +49 -0
- atomicshop/wrappers/loggingw/filters.py +102 -0
- atomicshop/wrappers/loggingw/formatters.py +58 -71
- atomicshop/wrappers/loggingw/handlers.py +459 -40
- atomicshop/wrappers/loggingw/loggers.py +19 -0
- atomicshop/wrappers/loggingw/loggingw.py +1010 -178
- atomicshop/wrappers/loggingw/reading.py +344 -19
- atomicshop/wrappers/mongodbw/__init__.py +0 -0
- atomicshop/wrappers/mongodbw/mongo_infra.py +31 -0
- atomicshop/wrappers/mongodbw/mongodbw.py +1432 -0
- atomicshop/wrappers/netshw.py +271 -0
- atomicshop/wrappers/playwrightw/engine.py +34 -19
- atomicshop/wrappers/playwrightw/infra.py +5 -0
- atomicshop/wrappers/playwrightw/javascript.py +7 -3
- atomicshop/wrappers/playwrightw/keyboard.py +14 -0
- atomicshop/wrappers/playwrightw/scenarios.py +172 -5
- atomicshop/wrappers/playwrightw/waits.py +9 -7
- atomicshop/wrappers/powershell_networking.py +80 -0
- atomicshop/wrappers/psutilw/processes.py +81 -0
- atomicshop/wrappers/psutilw/psutil_networks.py +85 -0
- atomicshop/wrappers/psutilw/psutilw.py +9 -0
- atomicshop/wrappers/pyopensslw.py +9 -2
- atomicshop/wrappers/pywin32w/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/cert_store.py +116 -0
- atomicshop/wrappers/pywin32w/console.py +34 -0
- atomicshop/wrappers/pywin32w/win_event_log/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/win_event_log/fetch.py +174 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribe.py +212 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_create.py +57 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_terminate.py +49 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/schannel_logging.py +97 -0
- atomicshop/wrappers/pywin32w/winshell.py +19 -0
- atomicshop/wrappers/pywin32w/wmis/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/wmis/msft_netipaddress.py +113 -0
- atomicshop/wrappers/pywin32w/wmis/win32_networkadapterconfiguration.py +259 -0
- atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py +112 -0
- atomicshop/wrappers/pywin32w/wmis/wmi_helpers.py +236 -0
- atomicshop/wrappers/socketw/accepter.py +21 -7
- atomicshop/wrappers/socketw/certificator.py +216 -150
- atomicshop/wrappers/socketw/creator.py +190 -50
- atomicshop/wrappers/socketw/dns_server.py +500 -173
- atomicshop/wrappers/socketw/exception_wrapper.py +45 -52
- atomicshop/wrappers/socketw/process_getter.py +86 -0
- atomicshop/wrappers/socketw/receiver.py +144 -102
- atomicshop/wrappers/socketw/sender.py +65 -35
- atomicshop/wrappers/socketw/sni.py +334 -165
- atomicshop/wrappers/socketw/socket_base.py +134 -0
- atomicshop/wrappers/socketw/socket_client.py +137 -95
- atomicshop/wrappers/socketw/socket_server_tester.py +14 -9
- atomicshop/wrappers/socketw/socket_wrapper.py +717 -116
- atomicshop/wrappers/socketw/ssl_base.py +15 -14
- atomicshop/wrappers/socketw/statistics_csv.py +148 -17
- atomicshop/wrappers/sysmonw.py +157 -0
- atomicshop/wrappers/ubuntu_terminal.py +65 -26
- atomicshop/wrappers/win_auditw.py +189 -0
- atomicshop/wrappers/winregw/__init__.py +0 -0
- atomicshop/wrappers/winregw/winreg_installed_software.py +58 -0
- atomicshop/wrappers/winregw/winreg_network.py +232 -0
- {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/METADATA +31 -49
- atomicshop-3.10.5.dist-info/RECORD +306 -0
- {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/WHEEL +1 -1
- atomicshop/_basics_temp.py +0 -101
- atomicshop/addons/a_setup_scripts/install_psycopg2_ubuntu.sh +0 -3
- atomicshop/addons/a_setup_scripts/install_pywintrace_0.3.cmd +0 -2
- atomicshop/addons/mains/install_docker_rootless_ubuntu.py +0 -11
- atomicshop/addons/mains/install_docker_ubuntu_main_sudo.py +0 -11
- atomicshop/addons/mains/install_elastic_search_and_kibana_ubuntu.py +0 -10
- atomicshop/addons/mains/install_wsl_ubuntu_lts_admin.py +0 -9
- atomicshop/addons/package_setup/CreateWheel.cmd +0 -7
- atomicshop/addons/package_setup/Setup in Edit mode.cmd +0 -6
- atomicshop/addons/package_setup/Setup.cmd +0 -7
- atomicshop/addons/process_list/compile.cmd +0 -2
- atomicshop/addons/process_list/compiled/Win10x64/process_list.dll +0 -0
- atomicshop/addons/process_list/compiled/Win10x64/process_list.exp +0 -0
- atomicshop/addons/process_list/compiled/Win10x64/process_list.lib +0 -0
- atomicshop/archiver/_search_in_zip.py +0 -189
- atomicshop/archiver/archiver.py +0 -34
- atomicshop/archiver/search_in_archive.py +0 -250
- atomicshop/archiver/sevenz_app_w.py +0 -86
- atomicshop/archiver/sevenzs.py +0 -44
- atomicshop/archiver/zips.py +0 -293
- atomicshop/etw/dns_trace.py +0 -118
- atomicshop/etw/etw.py +0 -61
- atomicshop/file_types.py +0 -24
- atomicshop/mitm/engines/create_module_template_example.py +0 -13
- atomicshop/mitm/initialize_mitm_server.py +0 -240
- atomicshop/monitor/checks/hash.py +0 -44
- atomicshop/monitor/checks/hash_checks/file.py +0 -55
- atomicshop/monitor/checks/hash_checks/url.py +0 -62
- atomicshop/pbtkmultifile_argparse.py +0 -88
- atomicshop/permissions.py +0 -110
- atomicshop/process_poller.py +0 -237
- atomicshop/script_as_string_processor.py +0 -38
- atomicshop/ssh_scripts/process_from_ipv4.py +0 -37
- atomicshop/ssh_scripts/process_from_port.py +0 -27
- atomicshop/wrappers/_process_wrapper_curl.py +0 -27
- atomicshop/wrappers/_process_wrapper_tar.py +0 -21
- atomicshop/wrappers/dockerw/install_docker.py +0 -209
- atomicshop/wrappers/elasticsearchw/infrastructure.py +0 -265
- atomicshop/wrappers/elasticsearchw/install_elastic.py +0 -232
- atomicshop/wrappers/ffmpegw.py +0 -125
- atomicshop/wrappers/loggingw/checks.py +0 -20
- atomicshop/wrappers/nodejsw/install_nodejs.py +0 -139
- atomicshop/wrappers/process_wrapper_pbtk.py +0 -16
- atomicshop/wrappers/socketw/base.py +0 -59
- atomicshop/wrappers/socketw/get_process.py +0 -107
- atomicshop/wrappers/wslw.py +0 -191
- atomicshop-2.11.47.dist-info/RECORD +0 -251
- /atomicshop/{addons/mains → a_mains}/FACT/factw_fact_extractor_docker_image_main_sudo.py +0 -0
- /atomicshop/{addons → a_mains/addons}/PlayWrightCodegen.cmd +0 -0
- /atomicshop/{addons → a_mains/addons}/ScriptExecution.cmd +0 -0
- /atomicshop/{addons/mains → a_mains/addons}/inits/init_to_import_all_modules.py +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/ReadMe.txt +0 -0
- /atomicshop/{addons/mains → a_mains}/search_for_hyperlinks_in_docx.py +0 -0
- /atomicshop/{archiver → etws}/__init__.py +0 -0
- /atomicshop/{etw → etws/traces}/__init__.py +0 -0
- /atomicshop/{monitor/checks/hash_checks → mitm/statistic_analyzer_helper}/__init__.py +0 -0
- /atomicshop/{wrappers/nodejsw → permissions}/__init__.py +0 -0
- /atomicshop/wrappers/pywin32w/{wmi_win32process.py → wmis/win32process.py} +0 -0
- {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info/licenses}/LICENSE.txt +0 -0
- {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
DEFAULT_ROTATING_SUFFIXES_FROM_WHEN: dict = {
|
|
2
|
+
'midnight': '%Y-%m-%d',
|
|
3
|
+
'S': '%Y-%m-%d_%H-%M-%S',
|
|
4
|
+
'M': '%Y-%m-%d_%H-%M',
|
|
5
|
+
'H': '%Y-%m-%d_%H',
|
|
6
|
+
'D': '%Y-%m-%d',
|
|
7
|
+
'W0': '%Y-%m-%d',
|
|
8
|
+
'W1': '%Y-%m-%d',
|
|
9
|
+
'W2': '%Y-%m-%d',
|
|
10
|
+
'W3': '%Y-%m-%d',
|
|
11
|
+
'W4': '%Y-%m-%d',
|
|
12
|
+
'W5': '%Y-%m-%d',
|
|
13
|
+
'W6': '%Y-%m-%d'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
DEFAULT_STREAM_FORMATTER: str = "%(asctime)s | %(levelname)s | %(threadName)s | %(name)s | %(message)s"
|
|
18
|
+
DEFAULT_MESSAGE_FORMATTER: str = "%(message)s"
|
|
19
|
+
|
|
20
|
+
FORMAT_ELEMENT_TO_HEADER: dict = {
|
|
21
|
+
'asctime': 'Event Time [Y-M-D H:M:S]',
|
|
22
|
+
'created': 'Created',
|
|
23
|
+
'filename': "ModuleFileName ",
|
|
24
|
+
'funcName': 'Function',
|
|
25
|
+
'levelname': 'Log Level',
|
|
26
|
+
'levelno': 'Level Number',
|
|
27
|
+
'lineno': 'Line ',
|
|
28
|
+
'module': 'Module',
|
|
29
|
+
'msecs': '[MS.mS]',
|
|
30
|
+
'message': 'Message',
|
|
31
|
+
'name': 'Logger Name ',
|
|
32
|
+
'pathname': 'Path',
|
|
33
|
+
'process': 'Process',
|
|
34
|
+
'processName': 'Process Name',
|
|
35
|
+
'relativeCreated': 'Relative Created',
|
|
36
|
+
'thread': 'Thread',
|
|
37
|
+
'threadName': 'Thread Name'
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
DEFAULT_FORMATTER_TXT_FILE: str = \
|
|
41
|
+
"{asctime} | " \
|
|
42
|
+
"{levelname:<" + f"{len(FORMAT_ELEMENT_TO_HEADER['levelname'])}" + "s} | " \
|
|
43
|
+
"{name:<" + f"{len(FORMAT_ELEMENT_TO_HEADER['name'])}" + "s} | " \
|
|
44
|
+
"{filename:<" + f"{len(FORMAT_ELEMENT_TO_HEADER['filename'])}" + "s} : " \
|
|
45
|
+
"{lineno:<" + f"{len(FORMAT_ELEMENT_TO_HEADER['lineno'])}" + "d} | " \
|
|
46
|
+
"{threadName} | {message}"
|
|
47
|
+
|
|
48
|
+
DEFAULT_FORMATTER_CSV_FILE: str = \
|
|
49
|
+
'\"{asctime}\",{levelname},{name},{filename},{lineno},{threadName},\"{message}\"'
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import threading
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
from ...basics import ansi_escape_codes
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class HeaderFilter(logging.Filter):
|
|
10
|
+
"""
|
|
11
|
+
A logging.Filter that writes a header to a log file if the file is empty (
|
|
12
|
+
i.e., no log records have been written, i.e.2, on file rotation).
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
# noinspection PyPep8Naming
|
|
16
|
+
def __init__(self, header, baseFilename):
|
|
17
|
+
super().__init__()
|
|
18
|
+
self.header = header
|
|
19
|
+
self.baseFilename = baseFilename
|
|
20
|
+
self._write_header_if_needed()
|
|
21
|
+
|
|
22
|
+
def _write_header_if_needed(self):
|
|
23
|
+
if not os.path.exists(self.baseFilename) or os.path.getsize(self.baseFilename) == 0:
|
|
24
|
+
self._write_header()
|
|
25
|
+
|
|
26
|
+
def _write_header(self):
|
|
27
|
+
if self.header:
|
|
28
|
+
with open(self.baseFilename, 'a') as f:
|
|
29
|
+
f.write(self.header + '\n')
|
|
30
|
+
|
|
31
|
+
def filter(self, record):
|
|
32
|
+
self._write_header_if_needed()
|
|
33
|
+
return True
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ThreadColorLogFilter(logging.Filter):
|
|
37
|
+
"""
|
|
38
|
+
A logging.Filter that adds color to log records based on the thread that emitted the log record.
|
|
39
|
+
"""
|
|
40
|
+
def __init__(self, color: str, thread_id):
|
|
41
|
+
super().__init__()
|
|
42
|
+
self.color = color
|
|
43
|
+
self.thread_id = thread_id
|
|
44
|
+
|
|
45
|
+
def filter(self, record):
|
|
46
|
+
if threading.get_ident() == self.thread_id:
|
|
47
|
+
record.msg = (
|
|
48
|
+
ansi_escape_codes.get_colors_basic_dict(self.color) + record.msg +
|
|
49
|
+
ansi_escape_codes.ColorsBasic.END)
|
|
50
|
+
return True
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
"""
|
|
54
|
+
A logging.Filter in Python's logging module is an object that provides a way to perform fine-grained
|
|
55
|
+
filtering of log records.
|
|
56
|
+
It allows you to control which log records are passed through and which are filtered out,
|
|
57
|
+
based on specific criteria you define.
|
|
58
|
+
|
|
59
|
+
Basic Concepts of logging.Filter
|
|
60
|
+
Purpose: Filters are used to allow or deny log records from being processed further.
|
|
61
|
+
This can be based on various criteria, such as the level of the log record, the source logger, or custom attributes.
|
|
62
|
+
Implementation: Filters are typically subclasses of logging.Filter,
|
|
63
|
+
but they can also be any callable that accepts a log record and returns a boolean value.
|
|
64
|
+
|
|
65
|
+
How logging.Filter Works
|
|
66
|
+
When a log record is emitted, it is passed through any filters attached to the logger or the handler.
|
|
67
|
+
If the filter returns True, the log record is processed. If the filter returns False, the log record is ignored.
|
|
68
|
+
|
|
69
|
+
Example of logging.Filter
|
|
70
|
+
Here’s a simple example to demonstrate the use of logging.Filter:
|
|
71
|
+
|
|
72
|
+
Create a Filter: Subclass logging.Filter and override the filter method.
|
|
73
|
+
import logging
|
|
74
|
+
|
|
75
|
+
class MyFilter(logging.Filter):
|
|
76
|
+
def filter(self, record):
|
|
77
|
+
# Example: Allow only log records with a level of WARNING or higher
|
|
78
|
+
return record.levelno >= logging.WARNING
|
|
79
|
+
|
|
80
|
+
Attach the Filter to a Handler or Logger:
|
|
81
|
+
# Create a logger
|
|
82
|
+
logger = logging.getLogger('my_logger')
|
|
83
|
+
logger.setLevel(logging.DEBUG)
|
|
84
|
+
|
|
85
|
+
# Create a console handler
|
|
86
|
+
console_handler = logging.StreamHandler()
|
|
87
|
+
|
|
88
|
+
# Create an instance of the custom filter
|
|
89
|
+
my_filter = MyFilter()
|
|
90
|
+
|
|
91
|
+
# Add the filter to the handler
|
|
92
|
+
console_handler.addFilter(my_filter)
|
|
93
|
+
|
|
94
|
+
# Add the handler to the logger
|
|
95
|
+
logger.addHandler(console_handler)
|
|
96
|
+
|
|
97
|
+
# Log some messages
|
|
98
|
+
logger.debug('This is a debug message') # Will be filtered out
|
|
99
|
+
logger.info('This is an info message') # Will be filtered out
|
|
100
|
+
logger.warning('This is a warning message') # Will be displayed
|
|
101
|
+
logger.error('This is an error message') # Will be displayed
|
|
102
|
+
"""
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
from . import consts
|
|
2
5
|
|
|
3
6
|
|
|
4
7
|
# Log formatter, means how the log will look inside the file
|
|
@@ -8,63 +11,33 @@ import logging
|
|
|
8
11
|
|
|
9
12
|
# ".40" truncating the string to only 40 characters. Example: %(message).250s
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
#
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
#
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
#
|
|
33
|
-
|
|
34
|
-
#
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
FORMAT_ELEMENT_TO_HEADER: dict = {
|
|
39
|
-
'asctime': 'Event Time [Y-M-D H:M:S]',
|
|
40
|
-
'created': 'Created',
|
|
41
|
-
'filename': "ModuleFileName ",
|
|
42
|
-
'funcName': 'Function',
|
|
43
|
-
'levelname': 'Log Level',
|
|
44
|
-
'levelno': 'Level Number',
|
|
45
|
-
'lineno': 'Line ',
|
|
46
|
-
'module': 'Module',
|
|
47
|
-
'msecs': '[MS.mS]',
|
|
48
|
-
'message': 'Message',
|
|
49
|
-
'name': 'Logger Name ',
|
|
50
|
-
'pathname': 'Path',
|
|
51
|
-
'process': 'Process',
|
|
52
|
-
'processName': 'Process Name',
|
|
53
|
-
'relativeCreated': 'Relative Created',
|
|
54
|
-
'thread': 'Thread',
|
|
55
|
-
'threadName': 'Thread Name'
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
DEFAULT_FORMATTER_TXT_FILE: str = \
|
|
59
|
-
"{asctime},{msecs:013.9f} | " \
|
|
60
|
-
"{levelname:<" + f"{len(FORMAT_ELEMENT_TO_HEADER['levelname'])}" + "s} | " \
|
|
61
|
-
"{name:<" + f"{len(FORMAT_ELEMENT_TO_HEADER['name'])}" + "s} | " \
|
|
62
|
-
"{filename:<" + f"{len(FORMAT_ELEMENT_TO_HEADER['filename'])}" + "s} : " \
|
|
63
|
-
"{lineno:<" + f"{len(FORMAT_ELEMENT_TO_HEADER['lineno'])}" + "d} | " \
|
|
64
|
-
"{threadName} | {message}"
|
|
65
|
-
|
|
66
|
-
DEFAULT_FORMATTER_CSV_FILE: str = \
|
|
67
|
-
'\"{asctime}.{msecs:010.6f}\",{levelname},{name},{filename},{lineno},{threadName},\"{message}\"'
|
|
14
|
+
|
|
15
|
+
class NanosecondsFormatter(logging.Formatter):
|
|
16
|
+
def __init__(self, fmt=None, datefmt=None, style='%', use_nanoseconds=False):
|
|
17
|
+
super().__init__(fmt, datefmt, style)
|
|
18
|
+
self.use_nanoseconds = use_nanoseconds
|
|
19
|
+
|
|
20
|
+
def formatTime(self, record, datefmt=None):
|
|
21
|
+
ct = self.converter(record.created)
|
|
22
|
+
|
|
23
|
+
if datefmt:
|
|
24
|
+
# Remove unsupported %f from datefmt if present
|
|
25
|
+
if '%f' in datefmt:
|
|
26
|
+
datefmt = datefmt.replace('%f', '')
|
|
27
|
+
self.use_nanoseconds = True
|
|
28
|
+
else:
|
|
29
|
+
# Default time format if datefmt is not provided
|
|
30
|
+
datefmt = '%Y-%m-%d %H:%M:%S'
|
|
31
|
+
|
|
32
|
+
s = time.strftime(datefmt, ct)
|
|
33
|
+
|
|
34
|
+
if self.use_nanoseconds:
|
|
35
|
+
# Calculate nanoseconds from the fractional part of the timestamp
|
|
36
|
+
nanoseconds = f'{record.created:.9f}'.split('.')[1]
|
|
37
|
+
# Return the formatted string with nanoseconds appended
|
|
38
|
+
return f'{s}.{nanoseconds}'
|
|
39
|
+
else:
|
|
40
|
+
return s
|
|
68
41
|
|
|
69
42
|
|
|
70
43
|
class FormatterProcessor:
|
|
@@ -144,13 +117,17 @@ class FormatterProcessor:
|
|
|
144
117
|
# Iterate through all the elements and get the header list.
|
|
145
118
|
header_dict: dict = dict()
|
|
146
119
|
for element in self.list_of_elements:
|
|
147
|
-
header_dict.update({element: FORMAT_ELEMENT_TO_HEADER[element]})
|
|
120
|
+
header_dict.update({element: consts.FORMAT_ELEMENT_TO_HEADER[element]})
|
|
148
121
|
|
|
149
122
|
return header_dict
|
|
150
123
|
|
|
151
124
|
|
|
152
125
|
def get_logging_formatter_from_string(
|
|
153
|
-
formatter: str,
|
|
126
|
+
formatter: str,
|
|
127
|
+
style=None,
|
|
128
|
+
datefmt=None,
|
|
129
|
+
use_nanoseconds: bool = False
|
|
130
|
+
) -> logging.Formatter:
|
|
154
131
|
"""
|
|
155
132
|
Function to get the logging formatter from the string.
|
|
156
133
|
|
|
@@ -160,12 +137,12 @@ def get_logging_formatter_from_string(
|
|
|
160
137
|
'%': will use the '%' style.
|
|
161
138
|
'{': will use the '{' style.
|
|
162
139
|
:param datefmt: string, date format of 'asctime' element. Default is None.
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
140
|
+
We use custom formatter that can process the date format with nanoseconds:
|
|
141
|
+
'%Y-%m-%d %H:%M:%S.%f' -> '2021-01-01 00:00:00.000000000'
|
|
142
|
+
:param use_nanoseconds: bool, if set to True, the formatter will use nanoseconds instead of milliseconds.
|
|
143
|
+
This will print 'asctime' in the following format: '2021-01-01 00:00:00.000000000', instead of
|
|
144
|
+
'2021-01-01 00:00:00.000'.
|
|
145
|
+
|
|
169
146
|
:return: logging.Formatter, formatter.
|
|
170
147
|
"""
|
|
171
148
|
|
|
@@ -173,10 +150,20 @@ def get_logging_formatter_from_string(
|
|
|
173
150
|
if not style:
|
|
174
151
|
style = FormatterProcessor(formatter).get_style()['style']
|
|
175
152
|
|
|
176
|
-
# The regular 'datefmt' is '%Y-%m-%d,%H:%M:%S:%f'. If we want to use it with milliseconds 'msecs' element,
|
|
177
|
-
# we need to disable the duplicate milliseconds.
|
|
178
|
-
if disable_duplicate_ms:
|
|
179
|
-
datefmt = '%Y-%m-%d,%H:%M:%S'
|
|
180
|
-
|
|
181
153
|
# Create the logging formatter.
|
|
182
|
-
|
|
154
|
+
if use_nanoseconds or '%f' in datefmt:
|
|
155
|
+
return NanosecondsFormatter(formatter, style=style, datefmt=datefmt, use_nanoseconds=use_nanoseconds)
|
|
156
|
+
else:
|
|
157
|
+
return logging.Formatter(formatter, style=style, datefmt=datefmt)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def get_formatter_string(formatter) -> str:
|
|
161
|
+
"""
|
|
162
|
+
Function to get the formatter string from the 'logging.Formatter'.
|
|
163
|
+
|
|
164
|
+
:param formatter: logging.Formatter, formatter to convert to string.
|
|
165
|
+
:return: str, formatter string.
|
|
166
|
+
"""
|
|
167
|
+
|
|
168
|
+
# noinspection PyProtectedMember
|
|
169
|
+
return formatter._fmt
|