Skip to content

Commit 73bacf8

Browse files
[FEATURE] Initial implementation of module logging for debugging (- WIP #233 -)
Changes in file .coveragerc: * updated related config Changes in file multicast/__init__.py: * added debug signposts via logging module Changes in file multicast/env.py: * added debug signposts via logging module Changes in file multicast/exceptions.py: * added debug signposts via logging module Changes in file multicast/hear.py: * added debug signposts via logging module * related work Changes in file multicast/recv.py: * added debug signposts via logging module Changes in file multicast/send.py: * added debug signposts via logging module * related work Changes in file multicast/skt.py: * added debug signpost via logging module Changes in file requirements.txt: * mention of loggin builtin Changes in file tests/__init__.py: * added debug signposts via logging module Changes in file tests/context.py: * related work Changes in file tests/run_selective.py: * related work def main() -> None:
1 parent 9219f69 commit 73bacf8

File tree

12 files changed

+321
-42
lines changed

12 files changed

+321
-42
lines changed

.coveragerc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ exclude_lines =
3434
if __name__ in u"__main__":
3535
if __name__ .. .__main__.:
3636
if __sys_path__ not in sys.path:
37+
if __debug__
3738
os.abort()
3839
exit
3940

@@ -52,6 +53,7 @@ partial_branches =
5253
if __name__ in u'__main__':
5354
if __name__ in u"__main__":
5455
if __name__ in '__main__':
56+
if __debug__
5557
if __sys_path__ not in sys.path:
5658
# don't complain about sys.modules
5759
sys.modules

multicast/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import socket
2323
import struct
2424
import abc
25+
import logging
2526

2627
# skipcq
2728
__all__ = [
@@ -404,6 +405,10 @@
404405
405406
"""
406407

408+
if logging.__name__ is not None: # pragma: no branch
409+
logging.getLogger(__module__).addHandler(logging.NullHandler())
410+
logging.getLogger(__module__).debug(f"Loading {__module__}")
411+
407412
if sys.__name__ is None:
408413
raise ModuleNotFoundError(
409414
"FAIL: we could not import sys. We're like in the matrix! ABORT."
@@ -418,6 +423,7 @@
418423
if socket.__name__ is None:
419424
raise ModuleNotFoundError("FAIL: we could not import socket. ABORT.") from None
420425
else: # pragma: no branch
426+
logging.getLogger(__module__).debug(f"Setting default packet timeout to {_MCAST_DEFAULT_TTL}")
421427
socket.setdefaulttimeout(int(_MCAST_DEFAULT_TTL))
422428

423429
if struct.__name__ is None:
@@ -460,6 +466,7 @@
460466
if _config is None:
461467
raise ImportError("FAIL: we could not import environment. ABORT.") from None
462468
else:
469+
logging.getLogger(__module__).debug("Configuring overrides and defaults.")
463470
_MCAST_DEFAULT_PORT = _config["port"]
464471
_MCAST_DEFAULT_GROUP = _config["group"]
465472
_MCAST_DEFAULT_TTL = _config["ttl"]
@@ -468,6 +475,11 @@
468475
_MCAST_DEFAULT_BIND_IP = _config["bind_addr"]
469476
global _MCAST_DEFAULT_GROUPS # skipcq: PYL-W0604
470477
_MCAST_DEFAULT_GROUPS = _config["groups"]
478+
if __debug__: # pragma: no branch
479+
logging.getLogger(__module__).info("Overrides and defaults are configured.")
480+
logging.getLogger(__module__).debug("Defaults:")
481+
for key, value in _config.items():
482+
logging.getLogger(__module__).debug(f"\t{key}={str(value)}")
471483

472484
del _config # skipcq - cleanup any bootstrap/setup leaks early
473485

@@ -543,6 +555,7 @@ def buildArgs(cls, calling_parser_group):
543555
544556
"""
545557
if calling_parser_group is None: # pragma: no branch
558+
logging.getLogger(__module__).debug(f"Building {__name__} arguments.")
546559
calling_parser_group = argparse.ArgumentParser(
547560
prog=str(cls.__name__ if cls.__proc__ is None else cls.__proc__),
548561
description=cls.__prologue__,

multicast/env.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
try:
8989
import os
9090
import warnings
91+
from . import logging # skipcq: PLY-C0414
9192
from . import socket # skipcq: PYL-C0414
9293
import ipaddress
9394
except Exception as err:
@@ -98,6 +99,11 @@
9899
raise baton from err
99100

100101

102+
module_logger = logging.getLogger(__module__)
103+
module_logger.debug(f"loading {__module__}")
104+
module_logger.debug(f"Initializing {__package__} environment.")
105+
106+
101107
def validate_buffer_size(size: int) -> bool:
102108
"""
103109
Validate if the buffer size is a positive integer.
@@ -334,26 +340,31 @@ def load_buffer_size() -> int:
334340
"""
335341
# Import globals that we'll potentially update
336342
from multicast import _MCAST_DEFAULT_BUFFER_SIZE
343+
module_logger.debug("Looking for MULTICAST_BUFFER_SIZE in environment.")
337344
try:
338345
buffer_size = int(os.getenv(
339346
"MULTICAST_BUFFER_SIZE",
340347
_MCAST_DEFAULT_BUFFER_SIZE # skipcq: PYL-W1508
341348
))
349+
module_logger.debug("Done.")
342350
except ValueError:
343351
warnings.warn(
344352
f"Invalid MULTICAST_BUFFER_SIZE value, using default {_MCAST_DEFAULT_BUFFER_SIZE}",
345353
stacklevel=2
346354
)
347355
buffer_size = _MCAST_DEFAULT_BUFFER_SIZE # skipcq: PYL-W1508
348-
# Validate and potentially update port
356+
# Validate and potentially update buffer-size
357+
module_logger.debug("Validating MULTICAST_BUFFER_SIZE.")
349358
if validate_buffer_size(buffer_size):
350359
globals()["_MCAST_DEFAULT_BUFFER_SIZE"] = buffer_size
360+
module_logger.debug("Valid.")
351361
else:
352362
warnings.warn(
353363
f"Invalid MULTICAST_BUFFER_SIZE {buffer_size}, using default {_MCAST_DEFAULT_BUFFER_SIZE}",
354364
stacklevel=2
355365
)
356366
buffer_size = _MCAST_DEFAULT_BUFFER_SIZE
367+
module_logger.debug(f"Loaded {buffer_size} as internal multicast buffer size.")
357368
return buffer_size
358369

359370

@@ -435,22 +446,27 @@ def load_port() -> int:
435446
"""
436447
# Import globals that we'll potentially update
437448
from multicast import _MCAST_DEFAULT_PORT
449+
module_logger.debug("Looking for MULTICAST_PORT in environment.")
438450
try:
439451
port = int(os.getenv("MULTICAST_PORT", _MCAST_DEFAULT_PORT))
452+
module_logger.debug("Done.")
440453
except ValueError:
441454
warnings.warn(
442455
f"Invalid MULTICAST_PORT value, using default {_MCAST_DEFAULT_PORT}", stacklevel=2
443456
)
444457
port = _MCAST_DEFAULT_PORT
445458
# Validate and potentially update port
459+
module_logger.debug("Validating MULTICAST_PORT.")
446460
if validate_port(port):
447461
globals()["_MCAST_DEFAULT_PORT"] = port
462+
module_logger.debug("Valid.")
448463
else:
449464
warnings.warn(
450465
f"Port {port} is outside valid range (49152-65535), using default {_MCAST_DEFAULT_PORT}",
451466
stacklevel=2
452467
)
453468
port = _MCAST_DEFAULT_PORT
469+
module_logger.debug(f"Loaded {port} as default multicast port.")
454470
return port
455471

456472

@@ -555,15 +571,19 @@ def load_group() -> ipaddress.IPv4Address:
555571
"""
556572
# Import globals that we'll potentially update
557573
from multicast import _MCAST_DEFAULT_GROUP
574+
module_logger.debug("Looking for any MULTICAST_GROUP in environment.")
558575
group = os.getenv("MULTICAST_GROUP", _MCAST_DEFAULT_GROUP)
559576
# Validate and potentially update group
577+
module_logger.debug("Validating either MULTICAST_GROUP or default.")
560578
if validate_multicast_address(group):
561579
globals()["_MCAST_DEFAULT_GROUP"] = group
580+
module_logger.debug("Valid.")
562581
else:
563582
warnings.warn(
564583
f"Invalid multicast group {group}, using default {_MCAST_DEFAULT_GROUP}", stacklevel=2
565584
)
566585
group = _MCAST_DEFAULT_GROUP
586+
module_logger.debug(f"Loaded {group} as default multicast group.")
567587
return ipaddress.IPv4Address(group)
568588

569589

@@ -638,24 +658,31 @@ def load_TTL() -> int:
638658
"""
639659
# Import globals that we'll potentially update
640660
from multicast import _MCAST_DEFAULT_TTL
661+
module_logger.debug("Looking for MULTICAST_TTL in environment.")
641662
try:
642663
ttl = int(os.getenv("MULTICAST_TTL", _MCAST_DEFAULT_TTL))
664+
module_logger.debug("Done.")
643665
except ValueError:
644666
warnings.warn(
645667
f"Invalid MULTICAST_TTL value, using default {_MCAST_DEFAULT_TTL}", stacklevel=2
646668
)
647669
ttl = _MCAST_DEFAULT_TTL
648670
# Validate and potentially update TTL
671+
module_logger.debug("Validating MULTICAST_TTL.")
649672
if validate_ttl(ttl):
650673
globals()["_MCAST_DEFAULT_TTL"] = ttl
674+
module_logger.debug("Valid.")
651675
else:
652676
warnings.warn(
653677
f"TTL {ttl} is outside valid range (1-126), using default {_MCAST_DEFAULT_TTL}",
654678
stacklevel=2
655679
)
656680
ttl = _MCAST_DEFAULT_TTL
681+
module_logger.debug(f"Loaded {ttl} as default multicast time-to-live.")
657682
# Update socket default timeout
683+
module_logger.debug("Update socket default timeout.")
658684
socket.setdefaulttimeout(int(ttl))
685+
module_logger.debug("Updated.")
659686
return ttl
660687

661688

@@ -857,13 +884,19 @@ def load_config() -> dict:
857884
858885
"""
859886
# Load values from environment with defaults
887+
module_logger.info("Loading multicast overrides from environment.")
860888
port = load_port()
861889
group = load_group()
862890
ttl = load_TTL()
863891
buffer_size = load_buffer_size()
892+
module_logger.debug("Looking for MULTICAST_GROUPS in environment.")
864893
groups_str = os.getenv("MULTICAST_GROUPS", "")
894+
module_logger.debug("Done.")
895+
module_logger.debug("Looking for MULTICAST_BIND_ADDR in environment.")
865896
bind_addr = os.getenv("MULTICAST_BIND_ADDR", str(group)) # skipcq: PYL-W1508
897+
module_logger.debug("Done.")
866898
# Process and validate groups
899+
module_logger.debug("Processing and validating groups.")
867900
groups = set()
868901
if groups_str:
869902
for addr in groups_str.split():
@@ -875,9 +908,14 @@ def load_config() -> dict:
875908
)
876909
# Always include the primary group
877910
groups.add(str(group))
911+
module_logger.debug("Processed groups.")
878912
# Include bind_addr if it's a valid multicast address
913+
module_logger.debug("Processing and validating bind-address.")
879914
if validate_multicast_address(bind_addr):
915+
module_logger.debug("Adding multicast bind-address to groups.")
880916
groups.add(str(bind_addr))
917+
module_logger.debug("Processed bind-address.")
918+
module_logger.debug("Overrides and defaults are ready to configure.")
881919
return {
882920
"port": port,
883921
"group": str(group),

multicast/exceptions.py

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,8 @@
193193
"""
194194

195195
try:
196-
from . import sys # skipcq: PYL-C0414
197196
from . import argparse # skipcq: PYL-C0414
197+
from . import logging # skipcq: PYL-C0414
198198
import functools
199199
except Exception as err:
200200
baton = ImportError(err, str("[CWE-758] Module failed completely."))
@@ -204,6 +204,11 @@
204204
raise baton from err
205205

206206

207+
module_logger = logging.getLogger(__module__)
208+
module_logger.debug(f"loading {__module__}")
209+
module_logger.debug(f"Initializing {__package__} exceptions.")
210+
211+
207212
class CommandExecutionError(RuntimeError):
208213
"""
209214
Exception raised when a command execution fails.
@@ -433,8 +438,11 @@ def __init__(self, *args, **kwargs) -> None:
433438
self.exit_code = 143 # Use SIGTERM exit code for graceful shutdown
434439

435440

441+
module_logger.debug("Initialized exceptions.")
442+
module_logger.debug("Initializing error message strings.")
436443
# Error message constants
437444
EXIT_CODE_RANGE_ERROR = "Exit code must be an integer between 0 and 255"
445+
module_logger.debug("Initialized message strings.")
438446

439447

440448
def validate_exit_code(code) -> None:
@@ -509,8 +517,13 @@ def validate_exit_code(code) -> None:
509517
>>> success
510518
True
511519
"""
520+
module_logger.info("Validating possible exit code.")
512521
if not isinstance(code, int) or code < 0 or code > 255:
513522
raise ValueError(EXIT_CODE_RANGE_ERROR)
523+
module_logger.info("Validated possible exit code.")
524+
525+
526+
module_logger.debug("Initializing CEP-8 EXIT_CODES")
514527

515528

516529
EXIT_CODES = {
@@ -555,6 +568,7 @@ def validate_exit_code(code) -> None:
555568
556569
Usage Example:
557570
```python
571+
import sys
558572
from multicast.exceptions import EXIT_CODES
559573
from multicast.exceptions import get_exit_code_from_exception
560574
@@ -621,6 +635,9 @@ def validate_exit_code(code) -> None:
621635
"""
622636

623637

638+
module_logger.debug("Initialized EXIT_CODES.")
639+
640+
624641
def get_exit_code_from_exception(exc: BaseException) -> int:
625642
"""
626643
Retrieve the exit code associated with a specific exception.
@@ -733,25 +750,28 @@ def exit_on_exception(func: callable):
733750

734751
@functools.wraps(func)
735752
def wrapper(*args, **kwargs):
753+
_func_logger = module_logger
736754
try:
755+
_func_logger = logging.getLogger(func.__name__)
737756
return func(*args, **kwargs)
738757
except SystemExit as exc:
739758
# Handle SystemExit exceptions, possibly from argparse
740759
exit_code = exc.code if isinstance(exc.code, int) else 2
741-
if (sys.stderr.isatty()):
742-
print(f"{EXIT_CODES[exit_code][1]}: {exc}", file=sys.stderr)
760+
_func_logger.warning(f"{EXIT_CODES[exit_code][1]}: {exc}")
743761
raise SystemExit(exit_code) from exc
744762
# otherwise sys.exit(exit_code)
745763
except BaseException as err:
746764
exit_code = get_exit_code_from_exception(err)
747-
if (sys.stderr.isatty()):
748-
print(f"{EXIT_CODES[exit_code][1]}: {err}", file=sys.stderr)
765+
_func_logger.warning(f"{EXIT_CODES[exit_code][1]}: {err}")
749766
raise SystemExit(exit_code) from err
750767
# otherwise sys.exit(exit_code)
751768

752769
return wrapper
753770

754771

772+
module_logger.debug(f"loaded {__module__}")
773+
774+
755775
# skipcq
756776
__all__ = [
757777
"""__package__""",

0 commit comments

Comments
 (0)