Skip to content

Commit 83f76d4

Browse files
[PATCH] apply more changes from review (- WIP #184 -)
### ChangeLog: Changes in file .circleci/config.yml: jobs: Changes in file docs/FAQ.md: # FAQ Changes in file docs/USAGE.md: ## Basic Library Usage ## CLI Usage Changes in file docs/conf.py: Unknown Changes Changes in file tests/check_pip: EXIT_CODE=1 Changes in file tests/context.py: def _should_get_package_version_WHEN_valid(self): Changes in file tests/test_build.py: Unknown Changes Changes in file tests/test_exceptions.py: Unknown Changes Changes in file tests/test_hear_cleanup.py: class HearCleanupTestSuite(context.BasicUsageTestSuite): def test_cleanup_on_exit(self): Changes in file tests/test_hear_data_processing.py: Unknown Changes Changes in file tests/test_hear_keyboard_interrupt.py: Unknown Changes Changes in file tests/test_hear_server_activate.py: Unknown Changes
1 parent c907a4e commit 83f76d4

File tree

12 files changed

+132
-73
lines changed

12 files changed

+132
-73
lines changed

.circleci/config.yml

Lines changed: 26 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
11
---
22
version: 2.1
3+
commands:
4+
cleanup:
5+
steps:
6+
- run:
7+
shell: /bin/bash
8+
name: "Cleanup"
9+
command: |
10+
make clean
11+
when: always
12+
13+
parameters:
14+
python-version:
15+
type: string
16+
default: "3.12"
17+
318
jobs:
419
build:
520
docker:
6-
- image: cimg/python:3.10
7-
- image: cimg/python:3.11
8-
- image: cimg/python:3.12
21+
- image: cimg/python:<< pipeline.parameters.python-version >>
922
resource_class: medium
1023
environment:
1124
CI: cicleci
@@ -39,9 +52,7 @@ jobs:
3952

4053
test:
4154
docker:
42-
- image: cimg/python:3.10
43-
- image: cimg/python:3.11
44-
- image: cimg/python:3.12
55+
- image: cimg/python:<< pipeline.parameters.python-version >>
4556
parallelism: 2
4657
resource_class: medium
4758
environment:
@@ -60,36 +71,18 @@ jobs:
6071
command: |
6172
python3 -m pip install --upgrade --user -r ./tests/requirements.txt || : ;
6273
when: on_success
63-
- run:
64-
shell: /bin/bash
65-
name: "clean up for test"
66-
command: |
67-
make clean
68-
when: always
74+
- cleanup
6975
- run:
7076
shell: /bin/bash
7177
name: "Unit Tests"
7278
command: |
7379
make test
7480
when: on_success
75-
- run:
76-
shell: /bin/bash
77-
name: "clean up from test"
78-
command: |
79-
make clean
80-
when: always
81-
- run:
82-
shell: /bin/bash
83-
name: "clean up from FAIL"
84-
command: |
85-
make clean
86-
when: on_fail
81+
- cleanup
8782

8883
pytest:
8984
docker:
90-
- image: cimg/python:3.10
91-
- image: cimg/python:3.11
92-
- image: cimg/python:3.12
85+
- image: cimg/python:<< pipeline.parameters.python-version >>
9386
parallelism: 2
9487
resource_class: medium
9588
environment:
@@ -116,12 +109,7 @@ jobs:
116109
command: |
117110
python3 -m pip install --upgrade --user -r ./tests/requirements.txt || : ;
118111
when: on_success
119-
- run:
120-
shell: /bin/bash
121-
name: "clean up for pytest"
122-
command: |
123-
make clean
124-
when: always
112+
- cleanup
125113
- run:
126114
shell: /bin/bash
127115
name: "pytest Unit Tests"
@@ -134,22 +122,11 @@ jobs:
134122
- store_artifacts:
135123
path: test-reports
136124
when: on_success
137-
- run:
138-
shell: /bin/bash
139-
name: "clean up from pytest"
140-
command: |
141-
make clean
142-
when: always
143-
- run:
144-
shell: /bin/bash
145-
name: "clean up from FAIL"
146-
command: |
147-
make clean
148-
when: on_fail
125+
- cleanup
149126

150127
lint:
151128
docker:
152-
- image: cimg/python:3.11
129+
- image: cimg/python:<< pipeline.parameters.python-version >>
153130
resource_class: medium
154131
environment:
155132
CI: cicleci
@@ -169,25 +146,17 @@ jobs:
169146
name: "install test-reqs attempt"
170147
command: |
171148
python3 -m pip install --user -r ./tests/requirements.txt || : ;
172-
- run:
173-
shell: /bin/bash
174-
name: "clean up for test"
175-
command: |
176-
make clean
149+
- cleanup
177150
- run:
178151
shell: /bin/bash
179152
name: "check code style and spelling"
180153
command: |
181154
make test-style || python3 -m flake8 --verbose --count --config=.flake8.ini
182-
- run:
183-
shell: /bin/bash
184-
name: "clean up when done"
185-
command: |
186-
make clean
155+
- cleanup
187156

188157
workflows:
189158
version: 2
190-
workflow:
159+
test-matrix:
191160
jobs:
192161
- build
193162
- test:

docs/FAQ.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
```{toctree}
66
:maxdepth: 3
77
8-
[Code of Conduct](https://github.com/reactive-firewall/multicast/.github/CODE_OF_CONDUCT.md)
9-
[Contributing](https://github.com/reactive-firewall/multicast/.github/CONTRIBUTING.md)
8+
[Code of Conduct](https://github.com/reactive-firewall/multicast/blob/master/.github/CODE_OF_CONDUCT.md)
9+
[Contributing](https://github.com/reactive-firewall/multicast/blob/master/.github/CONTRIBUTING.md)
1010
```
1111

1212
### How do I get this running?

docs/USAGE.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ from multiprocessing import Process
1212

1313
# set up some stuff
1414
_fixture_PORT_arg = int(59595)
15+
# Valid multicast addresses range from 224.0.0.0 to 239.255.255.255
1516
_fixture_mcast_GRP_arg = """224.0.0.1""" # only use dotted notation for multicast group addresses
1617
_fixture_host_BIND_arg = """224.0.0.1""" # only use dotted notation for multicast group addresses
1718
_fixture_host_IFACE_arg = None # Initial value representing no specific interface
@@ -100,7 +101,13 @@ I begin with it.
100101
CLI should work like so:
101102

102103
```plain
103-
multicast [-h|--help] [--use-std] [--daemon] (SAY|RECV|HEAR) [-h|--help] [--port PORT] [--iface IFACE] [--pipe|-m MESSAGE|--message MESSAGE] [--group BIND_GROUP] [--groups [JOIN_MCAST_GROUPS ...]]
104+
multicast [-h|--help] [--use-std] [--daemon] (SAY|RECV|HEAR)
105+
[-h|--help]
106+
[--port PORT]
107+
[--iface IFACE]
108+
[-m MESSAGE|--message MESSAGE]
109+
[--group BIND_GROUP]
110+
[--groups [JOIN_MCAST_GROUPS ...]]
104111
```
105112

106113
The commands are `SAY`, `RECV`, and `HEAR` for the CLI and are analogous to `send` listen/accept
@@ -110,7 +117,8 @@ and echo functions of a 1-to-1 connection.
110117

111118
The `SAY` command is used to send data messages via multicast datagrams.
112119

113-
* Note: the `--message` flag is expected with the `SAY` command, otherwise it behaves like `NOOP`.
120+
* Note: the `--message` flag is expected with the `SAY` command;
121+
if not provided, it behaves like `NOOP`.
114122
* Note: the `--daemon` flag has no effect on the `SAY` command.
115123

116124
### `RECV`

docs/conf.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import sys
1717
import os
18+
from urllib.parse import quote
1819

1920
# Define the branch reference for linkcode_resolve
2021
DOCS_BUILD_REF: str = os.environ.get("DOCS_BUILD_REF", "stable")
@@ -385,12 +386,16 @@
385386

386387

387388
def linkcode_resolve(domain, info):
388-
if domain != "py" or not info["module"]:
389+
if not isinstance(domain, str) or domain != "py":
390+
return None
391+
if not isinstance(info, dict) or "module" not in info or not info["module"]:
392+
return None
393+
if not isinstance(info["module"], str):
389394
return None
390395
filename = info["module"].replace(".", "/")
391396
theResult = f"{linkcode_url_prefix}/blob/{DOCS_BUILD_REF}/{filename}.py"
392397
if "/multicast.py" in theResult:
393398
theResult = theResult.replace("/multicast.py", "/multicast/__init__.py")
394399
if "/tests.py" in theResult:
395400
theResult = theResult.replace("/tests.py", "/tests/__init__.py")
396-
return theResult
401+
return quote(theResult, safe=":/-._")

tests/check_pip

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ EXIT_CODE=1
153153
# Results:
154154
# returns -- once cleanup has been done on a best-effort case.
155155
function cleanup() {
156-
rm -f ${LOCK_FILE} 2>/dev/null || : ; wait ;
156+
rm -f "${LOCK_FILE}" 2>/dev/null || : ; wait ;
157157
# unset when done
158158
unset LOCK_FILE 2>/dev/null || : ;
159159
hash -d shlock 2>/dev/null || : ;

tests/context.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -940,10 +940,10 @@ def _should_get_package_version_WHEN_valid(self):
940940
This helper method imports the package and extracts the __version__ attribute.
941941
942942
Returns:
943-
version -- The version string of the package.
944-
943+
packaging.version.Version -- A validated version object from the __version__ attrbute.
945944
Raises:
946-
AssertionError -- If the version string cannot be retrieved.
945+
AssertionError -- If the version string is invalid or cannot be retrieved.
946+
ImportError -- If the multicast package cannot be imported.
947947
948948
"""
949949
try:
@@ -957,6 +957,10 @@ def _should_get_package_version_WHEN_valid(self):
957957
parsed_version = version.parse(_raw_version_fixture)
958958
self.assertIsNotNone(parsed_version, """Version is not valid.""")
959959
self.assertIsInstance(parsed_version, version.Version, """Version is not valid.""")
960+
self.assertTrue(
961+
len(parsed_version.release) >= 2,
962+
"""Version must have at least major.minor components."""
963+
)
960964
return parsed_version
961965
except ImportError:
962966
self.fail("""Failed to import the multicast package to retrieve version.""")

tests/test_build.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,17 @@ class TestPEP517Build(BasicUsageTestSuite):
4343
__module__ = """tests.test_build"""
4444

4545
def test_build_with_pep517(self):
46-
"""Test building the package using PEP 517 standards."""
46+
"""
47+
Test building the package using PEP 517 standards.
48+
49+
This test verifies:
50+
1. Clean build environment setup
51+
2. Successful package build (both sdist and wheel)
52+
3. Presence of expected distribution files
53+
54+
References:
55+
- PEP 517: https://peps.python.org/pep-0517/
56+
"""
4757
# Arguments need to clean
4858
build_arguments = [
4959
str("{} -m coverage run").format(sys.executable),

tests/test_exceptions.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,42 @@
3737

3838

3939
class ExceptionsTestSuite(BasicUsageTestSuite):
40+
"""
41+
Test suite for validating the behavior of exception classes in the multicast package.
42+
43+
This suite focuses on testing the CommandExecutionError class, verifying its
44+
initialization with different arguments and proper error propagation.
45+
"""
4046

4147
__module__ = """tests.test_exceptions"""
4248

4349
__name__ = """tests.test_exceptions.ExceptionsTestSuite"""
4450

4551
def test_command_execution_error_with_args(self):
52+
"""
53+
Test CommandExecutionError initialization with custom message and exit code.
54+
55+
Verifies that both the message and exit code are correctly assigned when
56+
explicitly provided during initialization.
57+
"""
4658
error = multicast.exceptions.CommandExecutionError("Test error", 42)
4759
self.assertEqual(error.message, "Test error")
4860
self.assertEqual(error.exit_code, 42)
4961

5062
def test_command_execution_error_default_exit_code(self):
63+
"""Test CommandExecutionError initialization with default exit code.
64+
65+
Verifies that the exit code defaults to 1 when only a message is provided.
66+
"""
5167
error = multicast.exceptions.CommandExecutionError("Test error")
5268
self.assertEqual(error.exit_code, 1)
5369

5470
def test_command_execution_error_with_cause(self):
71+
"""Test CommandExecutionError initialization with a cause.
72+
73+
Verifies that the error properly chains exceptions when initialized with a
74+
cause, maintaining both the cause reference and custom attributes.
75+
"""
5576
test_cause = RuntimeError("test")
5677
self.assertIsNotNone(test_cause)
5778
error = multicast.exceptions.CommandExecutionError(test_cause, "Test with cause", 77)

tests/test_hear_cleanup.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,28 @@ class HearCleanupTestSuite(context.BasicUsageTestSuite):
5151

5252
__name__ = """tests.test_hear_cleanup.HearCleanupTestSuite"""
5353

54+
# Class-level constants
55+
QUICK_JOIN_TIMEOUT = 1 # Quick check for process termination
56+
ERROR_JOIN_TIMEOUT = 3 # Timeout when handling errors
57+
FINAL_JOIN_TIMEOUT = 15 # Final wait for process cleanup
58+
5459
def test_cleanup_on_exit(self):
55-
"""Tests the special hear and stop test"""
60+
"""Test proper cleanup of McastHEAR when receiving STOP message.
61+
62+
Prerequisites:
63+
- Available test port (self._the_test_port)
64+
- Multicast group 224.0.0.1 accessible
65+
66+
Expected behavior:
67+
1. Start McastHEAR process in daemon mode
68+
2. Send "STOP Test" message
69+
3. Verify process terminates cleanly
70+
4. Ensure all resources are released
71+
72+
Success criteria:
73+
- Process exits with code 0
74+
- No lingering processes or sockets
75+
"""
5676
theResult = False
5777
fail_fixture = str("""STOP --> HEAR == error""")
5878
_fixture_port_num = self._the_test_port
@@ -77,15 +97,15 @@ def test_cleanup_on_exit(self):
7797
self.assertIsNotNone(sender)
7898
while p.is_alive():
7999
sender(group="224.0.0.1", port=_fixture_port_num, ttl=1, data="STOP Test")
80-
p.join(1)
100+
p.join(self.QUICK_JOIN_TIMEOUT)
81101
self.assertFalse(p.is_alive())
82102
except Exception as _cause:
83-
p.join(3)
103+
p.join(self.ERROR_JOIN_TIMEOUT)
84104
if p.is_alive():
85105
p.terminate()
86106
p.close()
87107
raise unittest.SkipTest(fail_fixture) from _cause
88-
p.join(15)
108+
p.join(self.FINAL_JOIN_TIMEOUT)
89109
self.assertIsNotNone(p.exitcode)
90110
self.assertEqual(int(p.exitcode), int(0))
91111
theResult = (int(p.exitcode) <= int(0))

tests/test_hear_data_processing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
try:
2424
try:
2525
import context
26-
except Exception as _: # pragma: no branch
26+
except ImportError as _: # pragma: no branch
2727
del _ # skipcq - cleanup any error vars early
2828
from . import context
2929
if context.__name__ is None:

0 commit comments

Comments
 (0)