Skip to content

Commit 593bf91

Browse files
[FEATURE] Part 2 of 2 implementing initial prototype buffer ENV validation (- WIP #264 -)
Changes in file multicast/__init__.py: * new global `_MCAST_DEFAULT_BUFFER_SIZE` which can be overriden by the environment variable 'MULTICAST_BUFFER_SIZE' if set. Changes in file multicast/env.py: * load_config * related work * validate_buffer_size * implemented new validation function * load_buffer_size * implemented new helper function
1 parent 0dbfbc8 commit 593bf91

File tree

2 files changed

+97
-22
lines changed

2 files changed

+97
-22
lines changed

multicast/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
"""EXIT_CODES""",
5353
"""EXCEPTION_EXIT_CODES""",
5454
"""_BLANK""",
55+
"""_MCAST_DEFAULT_BUFFER_SIZE""", # added in version 2.0.6
5556
"""_MCAST_DEFAULT_PORT""",
5657
"""_MCAST_DEFAULT_GROUP""",
5758
"""_MCAST_DEFAULT_TTL""",
@@ -156,6 +157,7 @@
156157
157158
Attributes:
158159
__version__ (str): The version of this package.
160+
_MCAST_DEFAULT_BUFFER_SIZE (int): Default buffer size for multicast communication (1316).
159161
_MCAST_DEFAULT_PORT (int): Default port for multicast communication (59259).
160162
_MCAST_DEFAULT_GROUP (str): Default multicast group address ('224.0.0.1').
161163
_MCAST_DEFAULT_TTL (int): Default TTL for multicast packets (1).
@@ -221,7 +223,7 @@
221223

222224
_MCAST_DEFAULT_BUFFER_SIZE = 1316
223225
"""
224-
Arbitrary bugger size to use by default, though any value below 1500 would probably work well.
226+
Arbitrary bugger size to use by default, though any value below 65507 should work.
225227
226228
Minimal Testing:
227229
@@ -456,11 +458,11 @@
456458
_MCAST_DEFAULT_PORT = _config["port"]
457459
_MCAST_DEFAULT_GROUP = _config["group"]
458460
_MCAST_DEFAULT_TTL = _config["ttl"]
461+
_MCAST_DEFAULT_BUFFER_SIZE = _config["buffer_size"]
459462
global _MCAST_DEFAULT_BIND_IP # skipcq: PYL-W0604
460463
_MCAST_DEFAULT_BIND_IP = _config["bind_addr"]
461464
global _MCAST_DEFAULT_GROUPS # skipcq: PYL-W0604
462465
_MCAST_DEFAULT_GROUPS = _config["groups"]
463-
_MCAST_DEFAULT_BUFFER_SIZE = _config["buffer_size"]
464466

465467
del _config # skipcq - cleanup any bootstrap/setup leaks early
466468

multicast/env.py

Lines changed: 93 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -106,29 +106,34 @@ def validate_buffer_size(size: int) -> bool:
106106
size (int) -- The buffer size to validate.
107107
108108
Returns:
109-
bool: True if the buffer size is valid (> 0), False otherwise.
109+
bool: True if the buffer size is valid ( > 0), False otherwise.
110110
111111
Raises:
112112
ValueError: If the size cannot be converted to an integer.
113113
114114
Minimum Acceptance Testing:
115-
>>> validate_buffer_size(1316)
115+
>>> validate_buffer_size(1316) # Default value
116116
True
117-
>>> validate_buffer_size(1)
117+
>>> validate_buffer_size(1) # Minimum valid value
118118
True
119-
>>> validate_buffer_size(0)
119+
>>> validate_buffer_size(0) # Zero is invalid
120120
False
121-
>>> validate_buffer_size(-1)
121+
>>> validate_buffer_size(-1) # Negative is invalid
122122
False
123+
>>> validate_buffer_size(65527) # Maximum UDP payload size 65,535-8 - RFC 791 & RFC 768
124+
True
125+
>>> validate_buffer_size("1316") # String that can be converted
126+
True
123127
>>> try:
124128
... validate_buffer_size('invalid')
125129
... except ValueError:
126130
... print('ValueError raised')
127131
ValueError raised
132+
128133
"""
129134
try:
130135
size_num = int(size)
131-
return size_num > 0
136+
return 0 < size_num <= 65527
132137
except (ValueError, TypeError) as err:
133138
raise ValueError(f"Invalid buffer size value: {size}. Must be a positive integer.") from err
134139

@@ -237,7 +242,7 @@ def validate_ttl(ttl: int) -> bool:
237242
) from err
238243

239244

240-
def load_buffer() -> int:
245+
def load_buffer_size() -> int:
241246
"""
242247
Load and validate the multicast buffer size from environment variable.
243248
@@ -253,27 +258,95 @@ def load_buffer() -> int:
253258
Raises:
254259
ImportError: If the multicast module cannot be imported.
255260
256-
[WIP - DRAFT]
261+
Load buffer size from environment variables.
262+
263+
This function attempts to load the buffer size from the MULTICAST_BUFFER_SIZE
264+
environment variable. If the value is valid, it returns the buffer size.
265+
Invalid values trigger warnings and fall back to the default.
266+
267+
Returns:
268+
int: The validated buffer size, or the default value if not set/invalid.
269+
270+
Environment:
271+
MULTICAST_BUFFER_SIZE -- The buffer size in bytes.
272+
273+
Raises:
274+
ImportError: If the multicast module cannot be imported.
275+
276+
Minimum Acceptance Testing:
277+
>>> import os
278+
>>> from multicast import _MCAST_DEFAULT_BUFFER_SIZE
279+
>>> original_buffer = _MCAST_DEFAULT_BUFFER_SIZE
280+
281+
>>> # Test with valid environment variable
282+
>>> os.environ["MULTICAST_BUFFER_SIZE"] = "2048"
283+
>>> buffer_size = load_buffer_size()
284+
>>> buffer_size
285+
2048
286+
>>> _MCAST_DEFAULT_BUFFER_SIZE != 2048 # Global should not be updated by this function
287+
True
288+
289+
>>> # Test with invalid (negative) environment variable
290+
>>> os.environ["MULTICAST_BUFFER_SIZE"] = "-100"
291+
>>> import warnings
292+
>>> with warnings.catch_warnings(record=True) as w:
293+
... warnings.simplefilter("always")
294+
... buffer_size = load_buffer_size()
295+
... len(w) == 1 # One warning was issued
296+
True
297+
>>> buffer_size == 1316 # Falls back to default
298+
True
299+
300+
>>> # Test with invalid (zero) environment variable
301+
>>> os.environ["MULTICAST_BUFFER_SIZE"] = "0"
302+
>>> with warnings.catch_warnings(record=True) as w:
303+
... warnings.simplefilter("always")
304+
... buffer_size = load_buffer_size()
305+
... len(w) == 1 # One warning was issued
306+
True
307+
>>> buffer_size == 1316 # Falls back to default
308+
True
309+
310+
>>> # Test with invalid (non-integer) environment variable
311+
>>> os.environ["MULTICAST_BUFFER_SIZE"] = 'not_an_integer'
312+
>>> with warnings.catch_warnings(record=True) as w:
313+
... warnings.simplefilter("always")
314+
... buffer_size = load_buffer_size()
315+
... len(w) == 1 # One warning was issued
316+
True
317+
>>> buffer_size == 1316 # Falls back to default
318+
True
319+
320+
>>> # Test with no environment variable
321+
>>> if "MULTICAST_BUFFER_SIZE" in os.environ: os.environ.pop("MULTICAST_BUFFER_SIZE")
322+
'not_an_integer'
323+
>>> buffer_size = load_buffer_size()
324+
>>> buffer_size == 1316 # Uses default
325+
True
326+
327+
# Cleanup
328+
>>> globals()['_MCAST_DEFAULT_BUFFER_SIZE'] = original_buffer
257329
258330
"""
259331
# Import globals that we'll potentially update
260332
from multicast import _MCAST_DEFAULT_BUFFER_SIZE
261333
try:
262-
buffer_size = int(
263-
os.getenv("MULTICAST_BUFFER_SIZE", _MCAST_DEFAULT_BUFFER_SIZE) # skipcq: PYL-W1508
264-
)
334+
buffer_size = int(os.getenv(
335+
"MULTICAST_BUFFER_SIZE",
336+
_MCAST_DEFAULT_BUFFER_SIZE # skipcq: PYL-W1508
337+
))
265338
except ValueError:
266339
warnings.warn(
267-
"Invalid MULTICAST_BUFFER_SIZE value, using default 1316",
340+
f"Invalid MULTICAST_BUFFER_SIZE value, using default {_MCAST_DEFAULT_BUFFER_SIZE}",
268341
stacklevel=2
269342
)
270-
buffer_size = _MCAST_DEFAULT_BUFFER_SIZE
343+
buffer_size = _MCAST_DEFAULT_BUFFER_SIZE # skipcq: PYL-W1508
271344
# Validate and potentially update port
272345
if validate_buffer_size(buffer_size):
273346
globals()["_MCAST_DEFAULT_BUFFER_SIZE"] = buffer_size
274347
else:
275348
warnings.warn(
276-
f"Invalid MULTICAST_BUFFER_SIZE {buffer_size}, using default 1316",
349+
f"Invalid MULTICAST_BUFFER_SIZE {buffer_size}, using default {_MCAST_DEFAULT_BUFFER_SIZE}",
277350
stacklevel=2
278351
)
279352
buffer_size = _MCAST_DEFAULT_BUFFER_SIZE
@@ -749,10 +822,10 @@ def load_config() -> dict:
749822
>>> with warnings.catch_warnings(record=True) as w:
750823
... warnings.simplefilter("always")
751824
... config = load_config()
752-
... len(w) == 0 # expected failure - Warning was NOT issued
825+
... len(w) == 1 # expected failure - Warning was issued
826+
True
827+
>>> config['buffer_size'] == _MCAST_DEFAULT_BUFFER_SIZE # Falls back to default
753828
True
754-
>>> config['buffer_size'] # Undefined or Falls-back to default
755-
1316
756829
757830
# Cleanup
758831
>>> os.environ.pop('MULTICAST_BUFFER_SIZE', None)
@@ -767,9 +840,8 @@ def load_config() -> dict:
767840
... config = load_config()
768841
... except ValueError:
769842
... print('ValueError raised')
770-
ValueError raised
771843
>>> config is None
772-
True
844+
False
773845
774846
# Cleanup
775847
>>> os.environ.pop('MULTICAST_BUFFER_SIZE', None)
@@ -781,9 +853,9 @@ def load_config() -> dict:
781853
port = load_port()
782854
group = load_group()
783855
ttl = load_TTL()
856+
buffer_size = load_buffer_size()
784857
groups_str = os.getenv("MULTICAST_GROUPS", "")
785858
bind_addr = os.getenv("MULTICAST_BIND_ADDR", group) # skipcq: PYL-W1508
786-
buffer_size = load_buffer()
787859
# Process and validate groups
788860
groups = set()
789861
if groups_str:
@@ -815,6 +887,7 @@ def load_config() -> dict:
815887
"""__module__""",
816888
"""__name__""",
817889
"""__doc__""", # skipcq: PYL-E0603
890+
"""validate_buffer_size""",
818891
"""validate_port""",
819892
"""validate_multicast_address""",
820893
"""validate_ttl""",

0 commit comments

Comments
 (0)