atomicshop 3.3.15__py3-none-any.whl → 3.3.17__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.

Potentially problematic release.


This version of atomicshop might be problematic. Click here for more details.

atomicshop/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  """Atomic Basic functions and classes to make developer life easier"""
2
2
 
3
3
  __author__ = "Den Kras"
4
- __version__ = '3.3.15'
4
+ __version__ = '3.3.17'
@@ -116,7 +116,15 @@ def import_engines_configs(print_kwargs: dict) -> int:
116
116
  return result_code
117
117
 
118
118
  # Assigning all the engines domains to all time domains, that will be responsible for adding new domains.
119
- config_static.Certificates.domains_all_times = list(domains_engine_list_full)
119
+ domains_all_times_with_ports: list[str] = list(domains_engine_list_full)
120
+
121
+ domains_all_times: list[str] = list()
122
+ for domain_and_port in domains_all_times_with_ports:
123
+ domain: str = domain_and_port.split(':')[0]
124
+ if domain not in domains_engine_list_full:
125
+ domains_all_times.append(domain)
126
+
127
+ config_static.Certificates.domains_all_times = domains_all_times
120
128
 
121
129
  config_static.ENGINES_LIST = engines_list
122
130
  config_static.REFERENCE_MODULE = reference_module
@@ -20,6 +20,14 @@ from .connection_thread_worker import thread_worker_main
20
20
  from . import config_static, recs_files
21
21
 
22
22
 
23
+ # If you have 'pip-system-certs' package installed, this section overrides this behavior, since it injects
24
+ # the ssl default behavior, which we don't need when using ssl and sockets.
25
+ import ssl, importlib
26
+ if getattr(ssl.SSLContext.wrap_socket, "__module__", "").startswith("pip._vendor.truststore"):
27
+ # Truststore injection is active; restore stdlib ssl
28
+ importlib.reload(ssl)
29
+
30
+
23
31
  class NetworkSettings:
24
32
  """
25
33
  Class to store network settings.
@@ -162,7 +170,7 @@ def startup_output(system_logger, script_version: str):
162
170
  f"Default server certificate usage enabled, if no SNI available: "
163
171
  f"{config_static.MainConfig.default_server_certificate_filepath}")
164
172
 
165
- if config_static.Certificates.sni_server_certificates_cache_directory:
173
+ if config_static.Certificates.sni_create_server_certificate_for_each_domain:
166
174
  system_logger.info(
167
175
  f"SNI function certificates creation enabled. Certificates cache: "
168
176
  f"{config_static.Certificates.sni_server_certificates_cache_directory}")
atomicshop/ssh_remote.py CHANGED
@@ -129,32 +129,9 @@ class SSHRemote:
129
129
  # with description of
130
130
  # Server 'address_goes_here' not found in known_hosts
131
131
  self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
132
- try:
133
- # Executing SSH connection to client.
134
- self.ssh_client.connect(self.ip_address, username=self.username, password=self.password, timeout=60)
135
- # When port 22 is unreachable on the client.
136
- except paramiko.ssh_exception.NoValidConnectionsError as e:
137
- error = str(e)
138
- # Logging the error also. Since the process name isn't critical, we'll continue script execution.
139
- print_api(error, logger=self.logger, logger_method='error', traceback_string=True)
140
- pass
141
- except paramiko.ssh_exception.SSHException as e:
142
- error = str(e)
143
- # Logging the error also. Since the process name isn't critical, we'll continue script execution.
144
- print_api(error, logger=self.logger, logger_method='error', traceback_string=True)
145
- pass
146
- except ConnectionResetError:
147
- # Returning the error.
148
- error = "An existing connection was forcibly closed by the remote host."
149
- # Logging the error also. Since the process name isn't critical, we'll continue script execution.
150
- print_api(error, logger=self.logger, logger_method='error', traceback_string=True)
151
- pass
152
- except TimeoutError:
153
- # Returning the error.
154
- error = "Connection timed out."
155
- # Logging the error also. Since the process name isn't critical, we'll continue script execution.
156
- print_api(error, logger=self.logger, logger_method='error', traceback_string=True)
157
- pass
132
+
133
+ # Executing SSH connection to client.
134
+ self.ssh_client.connect(self.ip_address, username=self.username, password=self.password, timeout=60)
158
135
 
159
136
  return error
160
137
 
@@ -14,7 +14,7 @@ DEFAULT_ROTATING_SUFFIXES_FROM_WHEN: dict = {
14
14
  }
15
15
 
16
16
 
17
- DEFAULT_STREAM_FORMATTER: str = "%(levelname)s | %(threadName)s | %(name)s | %(message)s"
17
+ DEFAULT_STREAM_FORMATTER: str = "%(asctime)s | %(levelname)s | %(threadName)s | %(name)s | %(message)s"
18
18
  DEFAULT_MESSAGE_FORMATTER: str = "%(message)s"
19
19
 
20
20
  FORMAT_ELEMENT_TO_HEADER: dict = {
@@ -2,7 +2,7 @@ import logging
2
2
  import os
3
3
  from logging import Logger
4
4
  from logging.handlers import QueueListener
5
- from typing import Literal, Union
5
+ from typing import Literal, Union, Callable
6
6
  import datetime
7
7
  import contextlib
8
8
  import threading
@@ -54,7 +54,7 @@ def create_logger(
54
54
  formatter_filehandler_use_nanoseconds: bool = True,
55
55
  filehandler_rotate_at_rollover_time: bool = True,
56
56
  filehandler_rotation_date_format: str = None,
57
- filehandler_rotation_callback_namer_function: callable = None,
57
+ filehandler_rotation_callback_namer_function: Callable = None,
58
58
  filehandler_rotation_use_default_namer_function: bool = True,
59
59
  when: str = "midnight",
60
60
  interval: int = 1,
@@ -646,7 +646,7 @@ def start_queue_listener_in_multiprocessing(
646
646
  formatter_filehandler_use_nanoseconds: bool = True,
647
647
  filehandler_rotate_at_rollover_time: bool = True,
648
648
  filehandler_rotation_date_format: str = None,
649
- filehandler_rotation_callback_namer_function: callable = None,
649
+ filehandler_rotation_callback_namer_function: Callable = None,
650
650
  filehandler_rotation_use_default_namer_function: bool = True,
651
651
  when: str = "midnight",
652
652
  interval: int = 1,
@@ -25,20 +25,36 @@ def add_reusable_address_option(socket_instance):
25
25
  socket_instance.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
26
26
 
27
27
 
28
- def create_ssl_context_for_server() -> ssl.SSLContext:
28
+ def create_ssl_context_for_server(allow_legacy=False) -> ssl.SSLContext:
29
29
  # Creating context with SSL certificate and the private key before the socket
30
30
  # https://docs.python.org/3/library/ssl.html
31
31
  # Creating context for SSL wrapper, specifying "PROTOCOL_TLS_SERVER" will pick the best TLS version protocol for
32
32
  # the server.
33
33
 
34
- ssl_context: ssl.SSLContext = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
34
+ # ssl_context: ssl.SSLContext = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
35
35
 
36
36
  # # Enforce the use of TLS 1.2 only (disable TLS 1.0, TLS 1.1, and TLS 1.3)
37
37
  # ssl_context.options |= ssl.OP_NO_TLSv1 # Disable TLS 1.0
38
38
  # ssl_context.options |= ssl.OP_NO_TLSv1_1 # Disable TLS 1.1
39
39
  # ssl_context.options |= ssl.OP_NO_TLSv1_3 # Disable TLS 1.3
40
40
 
41
- # return ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
41
+ # Correct factory for servers
42
+ ssl_context: ssl.SSLContext = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
43
+
44
+ # Modern default; relax only if you must
45
+ ssl_context.minimum_version = ssl.TLSVersion.TLSv1_2
46
+
47
+ # Don't verify client certificates.
48
+ ssl_context.verify_mode = ssl.CERT_NONE
49
+ ssl_context.check_hostname = False
50
+
51
+ # If you must support old clients that only offer TLS_RSA_* suites under OpenSSL 3:
52
+ if allow_legacy:
53
+ # This enables RSA key exchange and other legacy bits at security level 1
54
+ ssl_context.set_ciphers('DEFAULT:@SECLEVEL=1')
55
+ # If you truly have TLS 1.0/1.1 clients, uncomment the next line (not recommended):
56
+ ssl_context.minimum_version = ssl.TLSVersion.TLSv1
57
+
42
58
  return ssl_context
43
59
 
44
60
 
@@ -138,9 +154,44 @@ def load_certificate_and_key_into_server_ssl_context(
138
154
  print_api(message, error_type=True, logger_method="critical", **print_kwargs)
139
155
 
140
156
 
141
- def create_server_ssl_context___load_certificate_and_key(certificate_file_path: str, key_file_path) -> ssl.SSLContext:
157
+ def copy_server_ctx_settings(src: ssl.SSLContext, dst: ssl.SSLContext) -> None:
158
+ # Versions & options
159
+ try: dst.minimum_version = src.minimum_version
160
+ except Exception: pass
161
+ try: dst.maximum_version = src.maximum_version
162
+ except Exception: pass
163
+ try: dst.options = src.options
164
+ except Exception: pass
165
+
166
+ # Verification knobs (server usually CERT_NONE unless you do mTLS)
167
+ try: dst.verify_mode = src.verify_mode
168
+ except Exception: pass
169
+ try: dst.check_hostname = src.check_hostname
170
+ except Exception: pass
171
+
172
+ # Cipher policy – replicate current enabled list
173
+ try:
174
+ cipher_names = ':'.join(c['name'] for c in src.get_ciphers())
175
+ if cipher_names:
176
+ dst.set_ciphers(cipher_names)
177
+ except Exception:
178
+ pass
179
+
180
+ # (ALPN/curves/etc. don’t have public getters; set them the same way you set them on src, if applicable)
181
+
182
+
183
+ def create_server_ssl_context___load_certificate_and_key(
184
+ certificate_file_path: str,
185
+ key_file_path: str | None,
186
+ inherit_from: ssl.SSLContext | None = None
187
+ ) -> ssl.SSLContext:
142
188
  # Create and set ssl context for server.
143
- ssl_context: ssl.SSLContext = create_ssl_context_for_server()
189
+ ssl_context: ssl.SSLContext = create_ssl_context_for_server(True)
190
+
191
+ # If you replaced contexts during SNI, copy policy from the old one
192
+ if inherit_from is not None:
193
+ copy_server_ctx_settings(inherit_from, ssl_context)
194
+
144
195
  # Load certificate into context.
145
196
  load_certificate_and_key_into_server_ssl_context(ssl_context, certificate_file_path, key_file_path)
146
197
  # Return ssl context only.
@@ -75,18 +75,25 @@ def connection_exception_decorator(function_name):
75
75
  pass
76
76
  pass
77
77
  except ssl.SSLError as exception_object:
78
- # Getting the exact reason of "ssl.SSLError"
79
- if exception_object.reason == "HTTP_REQUEST":
80
- message = f"Socket Accept: HTTP Request on SSL Socket: " \
81
- f"{base.get_source_destination(kwargs['socket_object'])}"
82
- wrapper_handle_connection_exceptions.message = message
83
- print_api(message, logger_method='error', traceback_string=True, oneline=True, **kwargs['print_kwargs'])
84
- elif exception_object.reason == "TSV1_ALERT_UNKNOWN_CA":
85
- message = f"Socket Accept: Check CA certificate on the client " \
86
- f"{base.get_source_destination(kwargs['socket_object'])}"
87
- wrapper_handle_connection_exceptions.message = message
88
- print_api(message, logger_method='error', traceback_string=True, oneline=True, **kwargs['print_kwargs'])
89
- else:
78
+ excepted: bool = False
79
+ if getattr(exception_object, "reason", None):
80
+ # Getting the exact reason of "ssl.SSLError"
81
+ if exception_object.reason == "HTTP_REQUEST":
82
+ message = f"Socket Accept: HTTP Request on SSL Socket: " \
83
+ f"{base.get_source_destination(kwargs['socket_object'])}"
84
+ wrapper_handle_connection_exceptions.message = message
85
+ print_api(message, logger_method='error', traceback_string=True, oneline=True, **kwargs['print_kwargs'])
86
+
87
+ excepted = True
88
+ elif exception_object.reason == "TSV1_ALERT_UNKNOWN_CA":
89
+ message = f"Socket Accept: Check CA certificate on the client " \
90
+ f"{base.get_source_destination(kwargs['socket_object'])}"
91
+ wrapper_handle_connection_exceptions.message = message
92
+ print_api(message, logger_method='error', traceback_string=True, oneline=True, **kwargs['print_kwargs'])
93
+
94
+ excepted = True
95
+
96
+ if not excepted:
90
97
  # Not all requests have the server name passed through Client Hello.
91
98
  # If it is not passed an error of undefined variable will be raised.
92
99
  # So, we'll check if the variable as a string is in the "locals()" variable pool.
@@ -102,21 +109,19 @@ def connection_exception_decorator(function_name):
102
109
  f"Socket Accept: {domain_from_dns_server}:{port}: {message}"
103
110
  wrapper_handle_connection_exceptions.message = message
104
111
  print_api(message, logger_method='error', oneline=True, **kwargs['print_kwargs'])
105
- pass
112
+
106
113
  except FileNotFoundError:
107
114
  message = "'SSLSocket.accept()' crashed: 'FileNotFoundError'. Some problem with SSL during Handshake - " \
108
115
  "Could be certificate, client, or server."
109
116
  message = f"Socket Accept: {domain_from_dns_server}:{port}: {message}"
110
117
  wrapper_handle_connection_exceptions.message = message
111
118
  print_api(message, logger_method='error', traceback_string=True, oneline=True, **kwargs['print_kwargs'])
112
- pass
113
119
  except Exception as e:
114
120
  _ = e
115
121
  message = "Undocumented exception on accept."
116
122
  message = f"Socket Accept: {domain_from_dns_server}:{port}: {message}"
117
123
  wrapper_handle_connection_exceptions.message = message
118
124
  print_api(message, logger_method='error', traceback_string=True, oneline=True, **kwargs['print_kwargs'])
119
- pass
120
125
 
121
126
  wrapper_handle_connection_exceptions.message = None
122
127
  return wrapper_handle_connection_exceptions
@@ -82,7 +82,7 @@ class SNISetup:
82
82
  ):
83
83
 
84
84
  # Create SSL Socket to wrap the raw socket with.
85
- ssl_context: ssl.SSLContext = creator.create_ssl_context_for_server()
85
+ ssl_context: ssl.SSLContext = creator.create_ssl_context_for_server(True)
86
86
 
87
87
  self.certificator_instance = certificator.Certificator(
88
88
  ca_certificate_name=self.ca_certificate_name,
@@ -149,7 +149,8 @@ class SNISetup:
149
149
  # The function is actually called at "accept()" method of the "ssl.SSLSocket"
150
150
  # This needs to be set only once on the listening socket
151
151
  if self.sni_custom_callback_function:
152
- ssl_context.sni_callback = self.sni_custom_callback_function
152
+ # ssl_context.sni_callback = self.sni_custom_callback_function
153
+ ssl_context.set_servername_callback(self.sni_custom_callback_function)
153
154
 
154
155
  if self.sni_use_default_callback_function:
155
156
  sni_handler_instance = SNIHandler(
@@ -320,8 +321,13 @@ class SNIHandler:
320
321
  # Since new default certificate was created we need to create new SSLContext and add the certificate.
321
322
  # You need to build new context and exchange the context that being inherited from the main socket,
322
323
  # or else the context will receive previous certificate each time.
323
- self.sni_received_parameters.ssl_socket.context = \
324
- creator.create_server_ssl_context___load_certificate_and_key(default_server_certificate_path, None)
324
+ self.sni_received_parameters.ssl_socket.context = (
325
+ creator.create_server_ssl_context___load_certificate_and_key(
326
+ default_server_certificate_path,
327
+ None,
328
+ inherit_from=self.sni_received_parameters.ssl_socket.context
329
+ )
330
+ )
325
331
  else:
326
332
  message = f"Couldn't create / overwrite Default Server Certificate: {default_server_certificate_path}"
327
333
  raise SNIDefaultCertificateCreationError(message)
@@ -378,7 +378,8 @@ class SocketWrapper:
378
378
 
379
379
  os.makedirs(self.sni_server_certificates_cache_directory, exist_ok=True)
380
380
  print_api("Removed cached server certificates.", logger=self.logger)
381
-
381
+ else:
382
+ os.makedirs(self.sni_server_certificates_cache_directory, exist_ok=True)
382
383
 
383
384
  if self.install_ca_certificate_to_root_store:
384
385
  if not self.ca_certificate_filepath:
@@ -613,6 +614,12 @@ class SocketWrapper:
613
614
  print_kwargs={'logger': self.logger}
614
615
  )
615
616
 
617
+ if ssl_client_socket:
618
+ # Handshake is done at this point, so version/cipher are available
619
+ self.logger.info(
620
+ f"TLS version={ssl_client_socket.version()} cipher={ssl_client_socket.cipher()}"
621
+ )
622
+
616
623
  if accept_error_message:
617
624
  # Write statistics after wrap is there was an error.
618
625
  self.statistics_writer.write_accept_error(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: atomicshop
3
- Version: 3.3.15
3
+ Version: 3.3.17
4
4
  Summary: Atomic functions and classes to make developer life easier
5
5
  Author: Denis Kras
6
6
  License-Expression: MIT
@@ -1,4 +1,4 @@
1
- atomicshop/__init__.py,sha256=6WgqHKNGGFHXE26Xw2aXZupzRTfmkTbM2lmvzAjmQcc,123
1
+ atomicshop/__init__.py,sha256=Dpoh5myDY76x-yt8GnffOAHw--mjow5KnNkH5ARBuyc,123
2
2
  atomicshop/_basics_temp.py,sha256=6cu2dd6r2dLrd1BRNcVDKTHlsHs_26Gpw8QS6v32lQ0,3699
3
3
  atomicshop/_create_pdf_demo.py,sha256=Yi-PGZuMg0RKvQmLqVeLIZYadqEZwUm-4A9JxBl_vYA,3713
4
4
  atomicshop/_patch_import.py,sha256=ENp55sKVJ0e6-4lBvZnpz9PQCt3Otbur7F6aXDlyje4,6334
@@ -37,7 +37,7 @@ atomicshop/scheduling.py,sha256=MvF20M6uU0Kh_CQn2ERxMTLvvF-ToBrdMhXNrKxYFj8,4682
37
37
  atomicshop/script_as_string_processor.py,sha256=uAIWwhHE-eP2FniuwBqEiM6VzyQX96uwdE3aA31rIm8,1883
38
38
  atomicshop/sound.py,sha256=tHiQQbFBk7EYN3pAfGNcxfF9oNsoYnZgu9z9iq8hxQE,24352
39
39
  atomicshop/speech_recognize.py,sha256=55-dIjgkpF93mvJnJuxSFuft5H5eRvGNlUj9BeIOZxk,5903
40
- atomicshop/ssh_remote.py,sha256=Mxixqs2-xGy1bhbcP0LKqjxKTNPz1Gmzz8PzO8aLB4c,17345
40
+ atomicshop/ssh_remote.py,sha256=-Xr8VMRJ2WpxdEG8HT2kFKKsb9GhSVVOJvUm948h1PE,15917
41
41
  atomicshop/sys_functions.py,sha256=MTBxRve5bh58SPvhX3gMiGqHlSBuI_rdNN1NnnBBWqI,906
42
42
  atomicshop/system_resource_monitor.py,sha256=yHdBU4mAVqoVS0Nn_SM_H42i4PgsgXDaXaMxfnL5CgA,14588
43
43
  atomicshop/system_resources.py,sha256=iKUvVSaXR47inmr3cTYsgNfclT38dRia2oupnlhIpK4,9290
@@ -128,10 +128,10 @@ atomicshop/mitm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
128
128
  atomicshop/mitm/config_static.py,sha256=KzO8DjZjRHfkQMYSIGTkW4jLNPzMR8visTqs1H6ZQ-U,8926
129
129
  atomicshop/mitm/config_toml_editor.py,sha256=2p1CMcktWRR_NW-SmyDwylu63ad5e0-w1QPMa8ZLDBw,1635
130
130
  atomicshop/mitm/connection_thread_worker.py,sha256=p-93_zdq3HzWpR7NF-gIq0JvvX0L8jz3_TSD3tBhV4o,33255
131
- atomicshop/mitm/import_config.py,sha256=6fPiV_3v2ym1LgiLlbGoiIPaB6pfRNM9UBXmRnP-pMQ,18560
131
+ atomicshop/mitm/import_config.py,sha256=7aLfKqflc3ZnzKc2_Y4T0eenzQpKG94M0r-PaVwF99M,18881
132
132
  atomicshop/mitm/initialize_engines.py,sha256=qzz5jzh_lKC03bI1w5ebngVXo1K-RV3poAyW-nObyqo,11042
133
133
  atomicshop/mitm/message.py,sha256=CDhhm4BTuZE7oNZCjvIZ4BuPOW4MuIzQLOg91hJaxDI,3065
134
- atomicshop/mitm/mitm_main.py,sha256=ucmdCr2p1F4c18DE8qJG3uG3FkkVLWdMEIWevN5BNKE,38967
134
+ atomicshop/mitm/mitm_main.py,sha256=u9q4BYIhScw9W9M7AS4h217gKQXkuppOFxvprEBVPGE,39366
135
135
  atomicshop/mitm/recs_files.py,sha256=tv8XFhYZMkBv4DauvpiAdPgvSo0Bcm1CghnmwO7dx8M,5018
136
136
  atomicshop/mitm/shared_functions.py,sha256=0lzeyINd44sVEfFbahJxQmz6KAMWbYrW5ou3UYfItvw,1777
137
137
  atomicshop/mitm/statistic_analyzer.py,sha256=D7DzpgqZN303jS8hfXn5HKq1edbTil7CpJr85bk9ERA,28489
@@ -252,12 +252,12 @@ atomicshop/wrappers/factw/rest/firmware.py,sha256=FezneouU1lUO9uZ6_8ZQNxr4MDlFIo
252
252
  atomicshop/wrappers/factw/rest/router.py,sha256=fdGok5ESBxcZHIBgM93l4yTPRGoeooQNsrPWIETieGk,710
253
253
  atomicshop/wrappers/factw/rest/statistics.py,sha256=vznwzKP1gEF7uXz3HsuV66BU9wrp73N_eFqpFpye9Qw,653
254
254
  atomicshop/wrappers/factw/rest/status.py,sha256=4O3xS1poafwyUiLDkhyx4oMMe4PBwABuRPpOMnMKgIU,641
255
- atomicshop/wrappers/loggingw/consts.py,sha256=JWiUJEydjhwatBxtIJsGTmDUSTLbmIRidtR6qRLMaIY,1608
255
+ atomicshop/wrappers/loggingw/consts.py,sha256=SK-DhONhwSeSJg5wbLAMGFTH6EDyh4_kyAeTrLedWwE,1622
256
256
  atomicshop/wrappers/loggingw/filters.py,sha256=48UVhJHemCS0agXmQP8dHvAHM8r9DFphJ1TNEBP3Dlg,3545
257
257
  atomicshop/wrappers/loggingw/formatters.py,sha256=ZY12IokVY1G_Wzn2Zlv9qjK-e8CtIK6yUgUfPHvH2BU,5802
258
258
  atomicshop/wrappers/loggingw/handlers.py,sha256=9JoleL96N85e6lEtD92YmKMwupHHON_YbV2ajeOBJ-8,21965
259
259
  atomicshop/wrappers/loggingw/loggers.py,sha256=mmM__XR3W4QC82wbsDRG_M4_0JYGGEP0Qn0WCOSp-go,2910
260
- atomicshop/wrappers/loggingw/loggingw.py,sha256=Cp_9IsiloPYpp9uzEQtUX-jCfcgGe4B2nFBle8x4wqQ,43582
260
+ atomicshop/wrappers/loggingw/loggingw.py,sha256=na7JhWyYIhCcvqDp1omiY2o23RMYN22JsWzFr9fOo6Y,43592
261
261
  atomicshop/wrappers/loggingw/reading.py,sha256=3uM7xc4Q_CBDkWgu6YGv_n5-9cCGrYXEd7qhc_Zk2EI,18068
262
262
  atomicshop/wrappers/mongodbw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
263
263
  atomicshop/wrappers/mongodbw/mongo_infra.py,sha256=vEXKy1Mi6LZ7QNEtRb8d-5xT5PYFhXbeEfFsXfsgpYo,918
@@ -301,23 +301,23 @@ atomicshop/wrappers/socketw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
301
301
  atomicshop/wrappers/socketw/accepter.py,sha256=4I9ORugRDvwaqSzm_gWSjZnRwQGY8hDTlCdsYHwH_ZE,2377
302
302
  atomicshop/wrappers/socketw/base.py,sha256=EcosGkD8VzgBY3GeIHDSG29ThQfXwg3-GQPmBTAqTdw,3048
303
303
  atomicshop/wrappers/socketw/certificator.py,sha256=mtWPJ_ew3OSwt0-1W4jaoco1VIY4NRCrMv3mDUxb_Cc,12418
304
- atomicshop/wrappers/socketw/creator.py,sha256=LLqPEI00pDN1HxHo_QVVuNmrmjmjhIBNMsgpZd3wS_4,13969
304
+ atomicshop/wrappers/socketw/creator.py,sha256=8cRX8mfU36rDCZ6eUPqPw1_GVX6inr4x4LEuWoV-esE,15866
305
305
  atomicshop/wrappers/socketw/dns_server.py,sha256=GOYMvHvS6Fx7s-DRygGqO7_o8_Qt9on3HmKxgOSznRE,55956
306
- atomicshop/wrappers/socketw/exception_wrapper.py,sha256=qW_1CKyPgGlsIt7_jusKkMV4A4hih4bX324u0PLnoO8,7382
306
+ atomicshop/wrappers/socketw/exception_wrapper.py,sha256=_p98OdOaKYSMqJ23pHLXBUA7NkbVmpgqcSJAdWr6wwc,7560
307
307
  atomicshop/wrappers/socketw/get_process.py,sha256=aJC-_qFUv3NgWCSUzDI72E4z8_-VTZE9NVZ0CwUoNlM,5698
308
308
  atomicshop/wrappers/socketw/receiver.py,sha256=9B3MvcDqr4C3x2fsnjG5SQognd1wRqsBgikxZa0wXG8,8243
309
309
  atomicshop/wrappers/socketw/sender.py,sha256=aX_K8l_rHjd5AWb8bi5mt8-YTkMYVRDB6DnPqK_XDUE,4754
310
- atomicshop/wrappers/socketw/sni.py,sha256=wsouhMreR3AmigW-3iZDvRsnhBS4S01a6SGGYFtBIvA,17907
310
+ atomicshop/wrappers/socketw/sni.py,sha256=uj6KKYKmSrzXcKBhVLaHQhYn1wNfIUpdnmcvn21V9iE,18176
311
311
  atomicshop/wrappers/socketw/socket_client.py,sha256=WWIiCxUX9irN9aWzJ6-1xrXNB_iv_diq3ha1yrWsNGU,22671
312
312
  atomicshop/wrappers/socketw/socket_server_tester.py,sha256=Qobmh4XV8ZxLUaw-eW4ESKAbeSLecCKn2OWFzMhadk0,6420
313
- atomicshop/wrappers/socketw/socket_wrapper.py,sha256=VZe27EQhExaiLQ0FEW4ePJhNSwPMyPzgcl6oljMSbGg,41185
313
+ atomicshop/wrappers/socketw/socket_wrapper.py,sha256=8tRoccWvnDNXaK2iYsT68RyxHHjILdPjw2R7SxPC6go,41621
314
314
  atomicshop/wrappers/socketw/ssl_base.py,sha256=62-hPm7zla1rh3m_WvDnXqKH-sDUTdiRptD8STCkgdk,2313
315
315
  atomicshop/wrappers/socketw/statistics_csv.py,sha256=_gA8bMX6Sw_UCXKi2y9wNAwlqifgExgDGfQIa9pFxQA,5543
316
316
  atomicshop/wrappers/winregw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
317
317
  atomicshop/wrappers/winregw/winreg_installed_software.py,sha256=Qzmyktvob1qp6Tjk2DjLfAqr_yXV0sgWzdMW_9kwNjY,2345
318
318
  atomicshop/wrappers/winregw/winreg_network.py,sha256=ih0BVNwByLvf9F_Lac4EdmDYYJA3PzMvmG0PieDZrsE,9905
319
- atomicshop-3.3.15.dist-info/licenses/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
320
- atomicshop-3.3.15.dist-info/METADATA,sha256=Mcn63amszsRHA31Jh2PiUb2TH3jwolN_trPIqZUGwr8,9345
321
- atomicshop-3.3.15.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
322
- atomicshop-3.3.15.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
323
- atomicshop-3.3.15.dist-info/RECORD,,
319
+ atomicshop-3.3.17.dist-info/licenses/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
320
+ atomicshop-3.3.17.dist-info/METADATA,sha256=rJmcAVoJKVxK4eEyafjPZ2rCdQDLlyHewEpgEiYM9eQ,9345
321
+ atomicshop-3.3.17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
322
+ atomicshop-3.3.17.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
323
+ atomicshop-3.3.17.dist-info/RECORD,,