atomicshop 2.21.0__py3-none-any.whl → 2.21.1__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__ = '2.21.0'
4
+ __version__ = '2.21.1'
@@ -1,7 +1,6 @@
1
1
  from datetime import datetime
2
2
  import threading
3
3
  import queue
4
- import copy
5
4
  import socket
6
5
 
7
6
  from ..wrappers.socketw import receiver, sender, socket_client, base
@@ -182,24 +181,27 @@ def thread_worker_main(
182
181
  network_logger.info("Thread Finished. Will continue listening on the Main thread")
183
182
 
184
183
  def create_responder_response(client_message: ClientMessage) -> list[bytes]:
185
- # Since we're in response mode, we'll record the request anyway, after the responder did its job.
186
- client_message.info = "In Server Response Mode"
187
-
188
- # If it's the first cycle and the protocol is Websocket, then we'll create the HTTP Handshake
189
- # response automatically.
190
- if protocol == 'Websocket' and client_receive_count == 1:
191
- responses: list = list()
192
- responses.append(
193
- websocket_parse.create_byte_http_response(client_message.request_raw_bytes))
184
+ if client_message.action == 'service_connect':
185
+ return responder.create_connect_response(client_message)
194
186
  else:
195
- # Creating response for parsed message and printing
196
- responses: list = responder.create_response(client_message)
187
+ # Since we're in response mode, we'll record the request anyway, after the responder did its job.
188
+ # client_message.info = "In Server Response Mode"
189
+
190
+ # If it's the first cycle and the protocol is Websocket, then we'll create the HTTP Handshake
191
+ # response automatically.
192
+ if protocol == 'Websocket' and client_receive_count == 1:
193
+ responses: list = list()
194
+ responses.append(
195
+ websocket_parse.create_byte_http_response(client_message.request_raw_bytes))
196
+ else:
197
+ # Creating response for parsed message and printing
198
+ responses: list = responder.create_response(client_message)
197
199
 
198
- # Output first 100 characters of all the responses in the list.
199
- for response_raw_bytes_single in responses:
200
- responder.logger.info(f"{response_raw_bytes_single[0: 100]}...")
200
+ # Output first 100 characters of all the responses in the list.
201
+ for response_raw_bytes_single in responses:
202
+ responder.logger.info(f"{response_raw_bytes_single[0: 100]}...")
201
203
 
202
- return responses
204
+ return responses
203
205
 
204
206
  def create_client_socket(client_message: ClientMessage):
205
207
  # If there is a custom certificate for the client for this domain, then we'll use it.
@@ -303,53 +305,11 @@ def thread_worker_main(
303
305
 
304
306
  return client_message
305
307
 
306
- def responder_thread_worker():
307
- nonlocal exception_or_close_in_receiving_thread
308
-
309
- client_message: ClientMessage = client_message_first_start()
310
- try:
311
- while True:
312
- client_message = responder_queue.get()
313
- print_api(f"Got message from queue, action: [{client_message.action}]", logger=network_logger, logger_method='info')
314
-
315
- # If the message is not a ClientMessage object, then we'll break the loop, since it is the exit signal.
316
- if not isinstance(client_message, ClientMessage):
317
- return
318
-
319
- if client_message.action == 'service_connect':
320
- raw_responses: list[bytes] = responder.create_connect_response(client_message)
321
- else:
322
- raw_responses: list[bytes] = create_responder_response(client_message)
323
- print_api(f"Got responses from responder, count: [{len(raw_responses)}]", logger=network_logger, logger_method='info')
324
-
325
- is_socket_closed: bool = False
326
- for response_raw_bytes in raw_responses:
327
- client_message.reinitialize_dynamic_vars()
328
- client_message.timestamp = datetime.now()
329
- client_message.response_raw_bytes = response_raw_bytes
330
-
331
- record_and_statistics_write(client_message)
332
-
333
- error_on_send: str = sender.Sender(
334
- ssl_socket=client_socket, class_message=client_message.response_raw_bytes,
335
- logger=network_logger).send()
336
-
337
- # If there was problem with sending data, we'll break the main while loop.
338
- if error_on_send:
339
- client_message.errors.append(error_on_send)
340
- record_and_statistics_write(client_message)
341
- is_socket_closed = True
342
-
343
- if is_socket_closed:
344
- exception_or_close_in_receiving_thread = True
345
- return
346
- except Exception as exc:
347
- handle_exceptions_on_sub_connection_thread(client_message, client_exception_queue, exc)
348
-
349
308
  def receive_send_start(
350
309
  receiving_socket,
351
310
  sending_socket = None,
352
- exception_queue: queue.Queue = None
311
+ exception_queue: queue.Queue = None,
312
+ client_connection_message: ClientMessage = None
353
313
  ):
354
314
  nonlocal client_receive_count
355
315
  nonlocal server_receive_count
@@ -370,59 +330,87 @@ def thread_worker_main(
370
330
  raise ValueError(f"Unknown side of the socket: {receiving_socket}")
371
331
 
372
332
  while True:
373
- client_message.reinitialize_dynamic_vars()
333
+ # pass the socket connect to responder.
334
+ if side == 'Service' and client_connection_message:
335
+ client_message = client_connection_message
374
336
 
375
- if side == 'Client':
376
- client_receive_count += 1
377
- current_count = client_receive_count
337
+ bytes_to_send_list: list[bytes] = create_responder_response(client_message)
338
+ print_api(f"Got responses from responder, count: [{len(bytes_to_send_list)}]", logger=network_logger,
339
+ logger_method='info')
378
340
  else:
379
- server_receive_count += 1
380
- current_count = server_receive_count
341
+ client_message.reinitialize_dynamic_vars()
381
342
 
382
- network_logger.info(
383
- f"Initializing Receiver for {side} cycle: {str(current_count)}")
343
+ if side == 'Client':
344
+ client_receive_count += 1
345
+ current_count = client_receive_count
346
+ else:
347
+ server_receive_count += 1
348
+ current_count = server_receive_count
384
349
 
385
- # Getting message from the client over the socket using specific class.
386
- received_raw_data, is_socket_closed, error_message = receiver.Receiver(
387
- ssl_socket=receiving_socket, logger=network_logger).receive()
350
+ network_logger.info(
351
+ f"Initializing Receiver for {side} cycle: {str(current_count)}")
388
352
 
389
- # Getting current time of message received, either from client or service.
390
- client_message.timestamp = datetime.now()
353
+ # Getting message from the client over the socket using specific class.
354
+ received_raw_data, is_socket_closed, error_message = receiver.Receiver(
355
+ ssl_socket=receiving_socket, logger=network_logger).receive()
391
356
 
392
- # In case of client socket, we'll process the raw data specifically for the client.
393
- if side == 'Client':
394
- process_client_raw_data(received_raw_data, error_message, client_message)
395
- client_message.action = 'client_receive'
396
- # In case of service socket, we'll process the raw data specifically for the service.
397
- else:
398
- process_server_raw_data(received_raw_data, error_message, client_message)
399
- client_message.action = 'service_receive'
357
+ # Getting current time of message received, either from client or service.
358
+ client_message.timestamp = datetime.now()
400
359
 
401
- # If there was an exception in the service thread, then receiving empty bytes doesn't mean that
402
- # the socket was closed by the other side, it means that the service thread closed the socket.
403
- if (received_raw_data == b'' or error_message) and exception_or_close_in_receiving_thread:
404
- print_api("Both sockets are closed, breaking the loop", logger=network_logger,
405
- logger_method='info')
406
- return
360
+ # In case of client socket, we'll process the raw data specifically for the client.
361
+ if side == 'Client':
362
+ process_client_raw_data(received_raw_data, error_message, client_message)
363
+ client_message.action = 'client_receive'
364
+ # In case of service socket, we'll process the raw data specifically for the service.
365
+ else:
366
+ process_server_raw_data(received_raw_data, error_message, client_message)
367
+ client_message.action = 'service_receive'
368
+
369
+ # If there was an exception in the service thread, then receiving empty bytes doesn't mean that
370
+ # the socket was closed by the other side, it means that the service thread closed the socket.
371
+ if (received_raw_data == b'' or error_message) and exception_or_close_in_receiving_thread:
372
+ print_api("Both sockets are closed, breaking the loop", logger=network_logger,
373
+ logger_method='info')
374
+ return
407
375
 
408
- # We will record only if there was no closing signal, because if there was, it means that we initiated
409
- # the close on the opposite socket.
410
- record_and_statistics_write(client_message)
376
+ # We will record only if there was no closing signal, because if there was, it means that we initiated
377
+ # the close on the opposite socket.
378
+ record_and_statistics_write(client_message)
379
+
380
+ # Now send it to requester/responder.
381
+ if side == 'Client':
382
+ # Send to requester.
383
+ bytes_to_send_list: list[bytes] = [client_message.request_raw_bytes]
384
+ else:
385
+ bytes_to_send_list: list[bytes] = create_responder_response(client_message)
386
+ print_api(f"Got responses from responder, count: [{len(bytes_to_send_list)}]",
387
+ logger=network_logger,
388
+ logger_method='info')
389
+
390
+ if is_socket_closed:
391
+ exception_or_close_in_receiving_thread = True
392
+ finish_thread()
393
+ return
411
394
 
412
- if is_socket_closed:
413
- exception_or_close_in_receiving_thread = True
414
- finish_thread()
415
- return
395
+ # If nothing was passed from the responder, and the client message is the connection message, then we'll skip to the next iteration.
396
+ if not bytes_to_send_list and client_connection_message:
397
+ client_connection_message = None
398
+ continue
416
399
 
417
- # If we're in offline mode, execute responder.
418
- if config_static.MainConfig.offline:
419
- responder_queue.put(copy.deepcopy(client_message))
420
- else:
421
- # if side == 'Client':
422
- # raise NotImplementedError
400
+ is_socket_closed: bool = False
401
+ for bytes_to_send_single in bytes_to_send_list:
423
402
  client_message.reinitialize_dynamic_vars()
403
+ client_message.timestamp = datetime.now()
404
+
405
+ if side == 'Client':
406
+ client_message.request_raw_bytes = bytes_to_send_single
407
+ else:
408
+ client_message.response_raw_bytes = bytes_to_send_single
409
+
410
+ record_and_statistics_write(client_message)
411
+
424
412
  error_on_send: str = sender.Sender(
425
- ssl_socket=sending_socket, class_message=received_raw_data,
413
+ ssl_socket=sending_socket, class_message=bytes_to_send_single,
426
414
  logger=network_logger).send()
427
415
 
428
416
  if error_on_send:
@@ -439,9 +427,11 @@ def thread_worker_main(
439
427
  # If the socket was closed on message receive, then we'll break the loop only after send.
440
428
  if is_socket_closed or error_on_send:
441
429
  exception_or_close_in_receiving_thread = True
442
- responder_queue.put('exit')
443
430
  finish_thread()
444
431
  return
432
+
433
+ # For next iteration to start in case this iteration was responsible to process connection message, we need to set it to None.
434
+ client_connection_message = None
445
435
  except Exception as exc:
446
436
  # If the sockets were already closed, then there is nothing to do here besides log.
447
437
  # if (isinstance(exc, OSError) and exc.errno == 10038 and
@@ -470,7 +460,6 @@ def thread_worker_main(
470
460
  # record_and_statistics_write(client_message)
471
461
 
472
462
  finish_thread()
473
- responder_queue.put('exit')
474
463
  exception_queue.put(exc)
475
464
 
476
465
  def handle_exceptions_on_main_connection_thread(
@@ -522,14 +511,13 @@ def thread_worker_main(
522
511
  reference_module=reference_module
523
512
  )
524
513
  parser = found_domain_module.parser_class_object
525
- responder = found_domain_module.responder_class_object
526
- recorder_no_init = found_domain_module.recorder_class_object
527
- recorder = recorder_no_init(record_path=config_static.LogRec.recordings_path)
514
+ responder = found_domain_module.responder_class_object()
515
+ recorder = found_domain_module.recorder_class_object(record_path=config_static.LogRec.recordings_path)
528
516
 
529
517
  network_logger.info(f"Assigned Modules for [{server_name}]: "
530
518
  f"{parser.__name__}, "
531
- f"{responder.__name__}, "
532
- f"{recorder_no_init.__name__}")
519
+ f"{responder.__class__.__name__}, "
520
+ f"{recorder.__class__.__name__}")
533
521
 
534
522
 
535
523
  # Initializing the client message object with current thread's data.
@@ -537,8 +525,6 @@ def thread_worker_main(
537
525
  client_message_connection: ClientMessage = ClientMessage()
538
526
  # This is needed to indicate if there was an exception or socket was closed in any of the receiving thread.
539
527
  exception_or_close_in_receiving_thread: bool = False
540
- # Responder queue for ClientMessage objects.
541
- responder_queue: queue.Queue = queue.Queue()
542
528
  # Queue for http request URI paths.
543
529
  http_path_queue: queue.Queue = queue.Queue()
544
530
 
@@ -558,15 +544,6 @@ def thread_worker_main(
558
544
  network_logger.info(f"Thread Created - Client [{client_ip}:{source_port}] | "
559
545
  f"Destination service: [{server_name}:{destination_port}]")
560
546
 
561
- # If we're in offline mode, we'll start the responder thread.
562
- if config_static.MainConfig.offline:
563
- responder_thread: threading.Thread = threading.Thread(
564
- target=responder_thread_worker, name=f"Thread-{thread_id}-Responder", daemon=True)
565
- responder_thread.start()
566
- else:
567
- # noinspection PyTypeChecker
568
- responder_thread = None
569
-
570
547
  service_client = None
571
548
  client_receive_count: int = 0
572
549
  server_receive_count: int = 0
@@ -576,58 +553,48 @@ def thread_worker_main(
576
553
  # noinspection PyTypeChecker
577
554
  connection_error: str = None
578
555
  service_socket_instance = None
579
- if not config_static.MainConfig.offline:
580
- # If "service_client" object is not defined, we'll define it.
581
- # If it's defined, then there's still active "ssl_socket" with connection to the service domain.
582
- if not service_client:
583
- service_client = create_client_socket(client_message_connection)
584
- service_socket_instance, connection_error = service_client.service_connection()
585
- # Now we'll update the server IP with the IP of the service.
586
- server_ip = service_socket_instance.getpeername()[0]
587
- client_message_connection.server_ip = server_ip
588
- else:
589
- client_message_connection.timestamp = datetime.now()
590
- client_message_connection.action = 'service_connect'
591
- client_message_connection.info = 'Server Response Mode'
592
- responder_queue.put(copy.deepcopy(client_message_connection))
593
-
594
- if connection_error:
595
- client_message_connection.timestamp = datetime.now()
596
- client_message_connection.errors.append(connection_error)
597
- client_message_connection.action = 'service_connect'
598
- record_and_statistics_write(client_message_connection)
556
+ client_message_connection.action = 'service_connect'
557
+ client_message_connection.timestamp = datetime.now()
558
+
559
+ if config_static.MainConfig.offline:
560
+ client_message_connection.info = 'Offline Mode'
599
561
  else:
562
+ service_client = create_client_socket(client_message_connection)
563
+ service_socket_instance, connection_error = service_client.service_connection()
564
+ # Now we'll update the server IP with the IP of the service.
565
+ server_ip = service_socket_instance.getpeername()[0]
566
+ client_message_connection.server_ip = server_ip
567
+
568
+ if connection_error:
569
+ client_message_connection.errors.append(connection_error)
570
+ record_and_statistics_write(client_message_connection)
571
+
572
+ if not connection_error:
600
573
  client_exception_queue: queue.Queue = queue.Queue()
601
574
  client_thread = threading.Thread(
602
- target=receive_send_start, args=(client_socket, service_socket_instance, client_exception_queue),
575
+ target=receive_send_start,
576
+ args=(client_socket, service_socket_instance, client_exception_queue, None),
603
577
  name=f"Thread-{thread_id}-Client")
604
578
  client_thread.daemon = True
605
579
  client_thread.start()
606
580
 
607
- if not config_static.MainConfig.offline:
608
- service_exception_queue: queue.Queue = queue.Queue()
609
- service_thread = threading.Thread(
610
- target=receive_send_start, args=(service_socket_instance, client_socket, service_exception_queue),
611
- name=f"Thread-{thread_id}-Service")
612
- service_thread.daemon = True
613
- service_thread.start()
581
+ service_exception_queue: queue.Queue = queue.Queue()
582
+ service_thread = threading.Thread(
583
+ target=receive_send_start,
584
+ args=(service_socket_instance, client_socket, service_exception_queue, client_message_connection),
585
+ name=f"Thread-{thread_id}-Service")
586
+ service_thread.daemon = True
587
+ service_thread.start()
614
588
 
615
589
  client_thread.join()
616
- if config_static.MainConfig.offline:
617
- responder_thread.join()
618
- else:
619
- service_thread.join()
590
+ service_thread.join()
620
591
 
621
592
  # If there was an exception in any of the threads, then we'll raise it here.
622
593
  if not client_exception_queue.empty():
623
594
  raise client_exception_queue.get()
624
- if not config_static.MainConfig.offline:
625
- if not service_exception_queue.empty():
626
- raise service_exception_queue.get()
595
+ if not service_exception_queue.empty():
596
+ raise service_exception_queue.get()
627
597
 
628
598
  finish_thread()
629
599
  except Exception as e:
630
- if not client_message_connection.timestamp:
631
- client_message_connection.timestamp = datetime.now()
632
-
633
600
  handle_exceptions_on_main_connection_thread(e, client_message_connection)
@@ -110,48 +110,49 @@ class ResponderParent:
110
110
  headers: dict,
111
111
  body: bytes
112
112
  ) -> bytes:
113
+ # noinspection GrazieInspection
113
114
  """
114
- Create genuine response from input parameters.
115
- ---------------
116
- The response is built from:
117
- HTTP-Version HTTP-Status HTTP-Status-String\r\n
118
- Headers1: Value\r\n
119
- Headers2: Value\r\n
120
- \r\n # This is meant to end the headers' section
121
- Body\r\n\r\n # In most cases Body is ended with '\r\n\r\n'
122
- ---------------
123
- Example for 200 response:
124
- HTTP/1.1 200 OK\r\n
125
- Cache-Control: max-age=86400\r\n
126
- Content-Type: application/json; charset=utf-8\r\n
127
- \r\n
128
- {"id":1,"name":"something"}
129
- ---------------
130
- The final response will look like oneline string:
131
- HTTP/1.1 200 OK\r\nCache-Control: max-age=86400\r\n
132
- Content-Type: application/json; charset=utf-8\r\n\r\n{"id":1,"name":"something"}
133
- ---------------
134
- You can create response as:
135
-
136
- ...HTTP/1.1 200 OK
137
- header1: value
138
- header2: value
139
-
140
- {data: value}...
141
-
142
- Change 3 dots ("...") to 3 double quotes before "HTTP" and after "value}".
143
- This way there will be "\n" added automatically after each line.
144
- While, the HTTP Client does the parsing of the text and not raw data, most probably it will be parsed well,
145
- but genuine responses from HTTP sources come with "\r\n" at the end of the line, so better use these for
146
- better compatibility.
147
- ---------------
148
-
149
- :param http_version: HTTP Version of Response in HTTP Status line.
150
- :param status_code: HTTP Status Code of Response in HTTP Status line.
151
- :param headers: HTTP Headers of Response.
152
- :param body: HTTP body data of Response, bytes.
153
- :return: bytes of the response.
154
- """
115
+ Create genuine response from input parameters.
116
+ ---------------
117
+ The response is built from:
118
+ HTTP-Version HTTP-Status HTTP-Status-String\r\n
119
+ Headers1: Value\r\n
120
+ Headers2: Value\r\n
121
+ \r\n # This is meant to end the headers' section
122
+ Body\r\n\r\n # In most cases Body is ended with '\r\n\r\n'
123
+ ---------------
124
+ Example for 200 response:
125
+ HTTP/1.1 200 OK\r\n
126
+ Cache-Control: max-age=86400\r\n
127
+ Content-Type: application/json; charset=utf-8\r\n
128
+ \r\n
129
+ {"id":1,"name":"something"}
130
+ ---------------
131
+ The final response will look like oneline string:
132
+ HTTP/1.1 200 OK\r\nCache-Control: max-age=86400\r\n
133
+ Content-Type: application/json; charset=utf-8\r\n\r\n{"id":1,"name":"something"}
134
+ ---------------
135
+ You can create response as:
136
+
137
+ ...HTTP/1.1 200 OK
138
+ header1: value
139
+ header2: value
140
+
141
+ {data: value}...
142
+
143
+ Change 3 dots ("...") to 3 double quotes before "HTTP" and after "value}".
144
+ This way there will be "\n" added automatically after each line.
145
+ While, the HTTP Client does the parsing of the text and not raw data, most probably it will be parsed well,
146
+ but genuine responses from HTTP sources come with "\r\n" at the end of the line, so better use these for
147
+ better compatibility.
148
+ ---------------
149
+
150
+ :param http_version: HTTP Version of Response in HTTP Status line.
151
+ :param status_code: HTTP Status Code of Response in HTTP Status line.
152
+ :param headers: HTTP Headers of Response.
153
+ :param body: HTTP body data of Response, bytes.
154
+ :return: bytes of the response.
155
+ """
155
156
 
156
157
  try:
157
158
  # Building full status string line and the "\r\n" to the end of the status line
@@ -201,6 +202,5 @@ class ResponderParent:
201
202
  def create_response(self, class_client_message: ClientMessage):
202
203
  """ This function should be overridden in the child class. """
203
204
 
204
- _ = class_client_message
205
- response_bytes_list: list[bytes] = list()
205
+ response_bytes_list: list[bytes] = [class_client_message.response_raw_bytes]
206
206
  return response_bytes_list
@@ -23,49 +23,49 @@ class ResponderGeneral(ResponderParent):
23
23
 
24
24
  self.logger = create_custom_logger()
25
25
 
26
- def create_response(self, class_client_message: ClientMessage):
27
- # noinspection GrazieInspection
28
- """
29
- Function to create Response based on ClientMessage and its Request.
30
-
31
- :param class_client_message: contains request and other parameters to help creating response.
32
- :return: list of responses in bytes.
33
- -----------------------------------
34
-
35
- # Example of creating list of bytes using 'build_byte_response' function:
36
- result_list: list[bytes] = list()
37
- result_list.append(
38
- self.build_byte_response(
39
- http_version=class_client_message.request_raw_decoded.request_version,
40
- status_code=200,
41
- headers=response_headers,
42
- body=b''
43
- )
44
- )
45
-
46
- return result_list
47
- -----------------------------------
48
- # Example of extracting variables from URL PATH based on custom PATH TEMPLATE:
49
- # (more examples in 'self.extract_variables_from_path_template' function description)
50
- template_path: str = "/hithere/<variable1>/else/<variable2>/tested/"
51
- path_variables: dict = extract_variables_from_path_template(
52
- path=class_client_message.request_raw_decoded.path,
53
- template_path=template_path
54
- )
55
- -----------------------------------
56
- # Example of extracting value from URL PATH parameters after question mark:
57
- parameter_value = extract_value_from_path_parameter(
58
- path=class_client_message.request_raw_decoded.path,
59
- parameter='test_id'
60
- )
61
- """
62
-
63
- # byte_response: bytes = b''
64
- # self.logger.info(f"Response: {byte_response}")
65
-
66
- response_bytes_list: list[bytes] = list()
67
- # response_bytes_list.append(byte_response)
68
- return response_bytes_list
26
+ # def create_response(self, class_client_message: ClientMessage):
27
+ # # noinspection GrazieInspection
28
+ # """
29
+ # Function to create Response based on ClientMessage and its Request.
30
+ #
31
+ # :param class_client_message: contains request and other parameters to help creating response.
32
+ # :return: list of responses in bytes.
33
+ # -----------------------------------
34
+ #
35
+ # # Example of creating list of bytes using 'build_byte_response' function:
36
+ # result_list: list[bytes] = list()
37
+ # result_list.append(
38
+ # self.build_byte_response(
39
+ # http_version=class_client_message.request_raw_decoded.request_version,
40
+ # status_code=200,
41
+ # headers=response_headers,
42
+ # body=b''
43
+ # )
44
+ # )
45
+ #
46
+ # return result_list
47
+ # -----------------------------------
48
+ # # Example of extracting variables from URL PATH based on custom PATH TEMPLATE:
49
+ # # (more examples in 'self.extract_variables_from_path_template' function description)
50
+ # template_path: str = "/hithere/<variable1>/else/<variable2>/tested/"
51
+ # path_variables: dict = extract_variables_from_path_template(
52
+ # path=class_client_message.request_raw_decoded.path,
53
+ # template_path=template_path
54
+ # )
55
+ # -----------------------------------
56
+ # # Example of extracting value from URL PATH parameters after question mark:
57
+ # parameter_value = extract_value_from_path_parameter(
58
+ # path=class_client_message.request_raw_decoded.path,
59
+ # parameter='test_id'
60
+ # )
61
+ # """
62
+ #
63
+ # # byte_response: bytes = b''
64
+ # # self.logger.info(f"Response: {byte_response}")
65
+ #
66
+ # response_bytes_list: list[bytes] = list()
67
+ # # response_bytes_list.append(byte_response)
68
+ # return response_bytes_list
69
69
 
70
70
  # def create_connect_response(self, class_client_message: ClientMessage):
71
71
  # """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: atomicshop
3
- Version: 2.21.0
3
+ Version: 2.21.1
4
4
  Summary: Atomic functions and classes to make developer life easier
5
5
  Author: Denis Kras
6
6
  License: MIT License
@@ -1,4 +1,4 @@
1
- atomicshop/__init__.py,sha256=dzUSfXNEa44LuoH_pJBGkKq3_it8IWZOVMP3pec9RfI,123
1
+ atomicshop/__init__.py,sha256=FYQ8-qAL9PVUMgBs-HklwbCpRvP--eHNx3_VzcTLtVM,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
@@ -135,7 +135,7 @@ atomicshop/file_io/xmls.py,sha256=zh3SuK-dNaFq2NDNhx6ivcf4GYCfGM8M10PcEwDSpxk,21
135
135
  atomicshop/mitm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
136
136
  atomicshop/mitm/config_static.py,sha256=dQH9AJFnwuO8qNVmoN4f3OrllIHlUvC5tkCGAPteK_U,8066
137
137
  atomicshop/mitm/config_toml_editor.py,sha256=2p1CMcktWRR_NW-SmyDwylu63ad5e0-w1QPMa8ZLDBw,1635
138
- atomicshop/mitm/connection_thread_worker.py,sha256=oOJmX4CwHynX8ZFvJVDo2Dtp9Jzw54IXF7Y_lKhU3fw,29418
138
+ atomicshop/mitm/connection_thread_worker.py,sha256=IZtcdW9ZZrtgL-dawt_o56emGCrzWtbd8fUAwgKX9NU,27972
139
139
  atomicshop/mitm/import_config.py,sha256=Aj_q3GEovZgN_ig15PWi-LhkuEG0CjDSwakhJg4xp2U,17575
140
140
  atomicshop/mitm/initialize_engines.py,sha256=ygxTtfpjlSErF-tKS3rYCyA1X4WT0GyQCZNbtzjPngk,7339
141
141
  atomicshop/mitm/message.py,sha256=CDhhm4BTuZE7oNZCjvIZ4BuPOW4MuIzQLOg91hJaxDI,3065
@@ -149,11 +149,11 @@ atomicshop/mitm/engines/create_module_template_main_example.py,sha256=LeQ44Rp2Gi
149
149
  atomicshop/mitm/engines/__parent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
150
150
  atomicshop/mitm/engines/__parent/parser___parent.py,sha256=HHaCXhScl3OlPjz6eUxsDpJaZyk6BNuDMc9xCkeo2Ws,661
151
151
  atomicshop/mitm/engines/__parent/recorder___parent.py,sha256=JbbcpV6j4odvREmvcXQlzKr5_hwLiEHhF0O414PlTes,6010
152
- atomicshop/mitm/engines/__parent/responder___parent.py,sha256=yEgR33CkAd1b9jyH5E8I4E16upqjlcK3WLo3BFHdjyk,9157
152
+ atomicshop/mitm/engines/__parent/responder___parent.py,sha256=mtiS_6ej9nxT9UhAQR4ftMqnqL-j_kO3u8KEaoEaI9k,9495
153
153
  atomicshop/mitm/engines/__reference_general/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
154
154
  atomicshop/mitm/engines/__reference_general/parser___reference_general.py,sha256=57MEPZMAjTO6xBDZ-yt6lgGJyqRrP0Do5Gk_cgCiPns,2998
155
155
  atomicshop/mitm/engines/__reference_general/recorder___reference_general.py,sha256=El2_YHLoHUCiKfkAmGlXxtFpmSjsUFdsb8I1MvSAFaM,653
156
- atomicshop/mitm/engines/__reference_general/responder___reference_general.py,sha256=eg8dMLXUDJ-0muUqoYM9MrGAXwy_0PTZyB-Apa-QDuE,9553
156
+ atomicshop/mitm/engines/__reference_general/responder___reference_general.py,sha256=zVMmON1sy6HH-A35uZZuAURBMfKS5X9ivkPVjPl-sCw,9654
157
157
  atomicshop/mitm/statistic_analyzer_helper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
158
158
  atomicshop/mitm/statistic_analyzer_helper/analyzer_helper.py,sha256=pk6L1t1ea1kvlBoR9QEJptOmaX-mumhwLsP2GCKukbk,5920
159
159
  atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py,sha256=UnnY_FSTiXEfZ8SkDKU2s2qpgPYu1oOT99ghmY-zzas,19992
@@ -330,8 +330,8 @@ atomicshop/wrappers/socketw/statistics_csv.py,sha256=WcNyaqEZ82S5-f3kzqi1nllNT2N
330
330
  atomicshop/wrappers/winregw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
331
331
  atomicshop/wrappers/winregw/winreg_installed_software.py,sha256=Qzmyktvob1qp6Tjk2DjLfAqr_yXV0sgWzdMW_9kwNjY,2345
332
332
  atomicshop/wrappers/winregw/winreg_network.py,sha256=AENV88H1qDidrcpyM9OwEZxX5svfi-Jb4N6FkS1xtqA,8851
333
- atomicshop-2.21.0.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
334
- atomicshop-2.21.0.dist-info/METADATA,sha256=8GW1okaXLnfFSef6IQvmFU2XOva4xdMcMPLEiLg5eDA,10630
335
- atomicshop-2.21.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
336
- atomicshop-2.21.0.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
337
- atomicshop-2.21.0.dist-info/RECORD,,
333
+ atomicshop-2.21.1.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
334
+ atomicshop-2.21.1.dist-info/METADATA,sha256=xGsV5SmY4zYzw1ns7OPlC7zX0NkYGx2ZQh0fpVUyHvQ,10630
335
+ atomicshop-2.21.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
336
+ atomicshop-2.21.1.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
337
+ atomicshop-2.21.1.dist-info/RECORD,,