Merge pull request #33 from torlando-tech/refactor/package-namespace
refactor: rename package from RNS.Interfaces to ble_reticulum
This commit is contained in:
commit
3b3450ab78
35 changed files with 195 additions and 83 deletions
10
.claude/commands/fix-ci.md
Normal file
10
.claude/commands/fix-ci.md
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
Check the GitHub Actions CI status and fix any failures:
|
||||
|
||||
1. Use `gh run list --limit 1` to get the latest run
|
||||
2. Use `gh run view --log` to see what failed
|
||||
3. Analyze the error logs
|
||||
4. Fix the issues in the code
|
||||
5. Run tests locally to verify
|
||||
6. Commit and push the fix
|
||||
7. Monitor the new CI run with `gh run watch`
|
||||
8. If it fails again, iterate until it passes
|
||||
8
.claude/commands/fix-issue.md
Normal file
8
.claude/commands/fix-issue.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
Please analyze and fix the GitHub issue: $ARGUMENTS. Follow these steps:
|
||||
1. Use `gh issue view` to get the issue details
|
||||
2. Understand the problem described in the issue
|
||||
3. Search the codebase for relevant files
|
||||
4. Implement the necessary changes to fix the issue
|
||||
5. Run tests to verify the fix works
|
||||
6. Create a PR with `gh pr create` with a clear description
|
||||
7. Link the PR to the issue
|
||||
2
.github/workflows/deploy.yml
vendored
2
.github/workflows/deploy.yml
vendored
|
|
@ -137,7 +137,7 @@ jobs:
|
|||
mkdir -p ~/.reticulum/interfaces || exit 1
|
||||
|
||||
echo ' [6/8] Copying interface files...'
|
||||
cp -v src/RNS/Interfaces/*.py ~/.reticulum/interfaces/ || exit 1
|
||||
cp -v src/ble_reticulum/*.py ~/.reticulum/interfaces/ || exit 1
|
||||
|
||||
echo ' [7/8] Stopping rnsd and clearing logs...'
|
||||
RNSD_BIN=\"\$HOME/.local/bin/rnsd\"
|
||||
|
|
|
|||
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
|
|
@ -155,9 +155,7 @@ jobs:
|
|||
pip install rns bleak bluezero dbus-python
|
||||
|
||||
- name: Create package structure
|
||||
run: |
|
||||
touch src/RNS/__init__.py
|
||||
touch src/RNS/Interfaces/__init__.py
|
||||
run: touch src/ble_reticulum/__init__.py
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
|
|
@ -165,7 +163,7 @@ jobs:
|
|||
--ignore=tests/test_v2_2_identity_handshake.py \
|
||||
--ignore=tests/test_v2_2_mac_sorting.py \
|
||||
--ignore=tests/test_v2_2_race_conditions.py \
|
||||
--cov=src/RNS/Interfaces \
|
||||
--cov=src/ble_reticulum \
|
||||
--cov-report=term-missing \
|
||||
--tb=short
|
||||
|
||||
|
|
|
|||
12
.github/workflows/test.yml
vendored
12
.github/workflows/test.yml
vendored
|
|
@ -80,15 +80,13 @@ jobs:
|
|||
pip install rns bleak bluezero dbus-python
|
||||
|
||||
- name: Create package structure
|
||||
run: |
|
||||
touch src/RNS/__init__.py
|
||||
touch src/RNS/Interfaces/__init__.py
|
||||
run: touch src/ble_reticulum/__init__.py
|
||||
|
||||
- name: Run unit tests
|
||||
run: |
|
||||
# Run only unit tests (fragmentation and prioritization)
|
||||
python -m pytest tests/test_fragmentation.py tests/test_prioritization.py -v \
|
||||
--cov=src/RNS/Interfaces/BLEFragmentation.py \
|
||||
--cov=src/ble_reticulum/BLEFragmentation.py \
|
||||
--cov-report=term-missing \
|
||||
--cov-report=xml:coverage-unit.xml
|
||||
continue-on-error: false
|
||||
|
|
@ -133,9 +131,7 @@ jobs:
|
|||
pip install rns bleak bluezero dbus-python
|
||||
|
||||
- name: Create package structure
|
||||
run: |
|
||||
touch src/RNS/__init__.py
|
||||
touch src/RNS/Interfaces/__init__.py
|
||||
run: touch src/ble_reticulum/__init__.py
|
||||
|
||||
- name: Run integration tests
|
||||
run: |
|
||||
|
|
@ -145,7 +141,7 @@ jobs:
|
|||
--ignore=tests/test_v2_2_identity_handshake.py \
|
||||
--ignore=tests/test_v2_2_mac_sorting.py \
|
||||
--ignore=tests/test_v2_2_race_conditions.py \
|
||||
--cov=src/RNS/Interfaces \
|
||||
--cov=src/ble_reticulum \
|
||||
--cov-report=term-missing \
|
||||
--cov-report=xml:coverage-integration.xml \
|
||||
--tb=short
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import asyncio
|
|||
# Add parent directory to path
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../src'))
|
||||
|
||||
from RNS.Interfaces.BLEFragmentation import BLEFragmenter, BLEReassembler
|
||||
from ble_reticulum.BLEFragmentation import BLEFragmenter, BLEReassembler
|
||||
|
||||
|
||||
def test_fragmentation():
|
||||
|
|
|
|||
117
install.sh
117
install.sh
|
|
@ -254,8 +254,24 @@ if command -v rnsd &> /dev/null; then
|
|||
if [ -n "$RNS_LOCATION" ]; then
|
||||
print_success "Found RNS Python package at: $RNS_LOCATION"
|
||||
|
||||
# Check if it's a pipx installation (most specific, check first)
|
||||
if [[ "$RNS_LOCATION" == *"/pipx/venvs/"* ]]; then
|
||||
# Check if it's a uv tool installation (most specific, check first)
|
||||
if [[ "$RNS_LOCATION" == *"/uv/tools/"* ]]; then
|
||||
print_info "RNS appears to be installed via uv tool"
|
||||
|
||||
# Extract uv tools path (e.g., ~/.local/share/uv/tools/rns)
|
||||
UV_RNS_PATH=$(echo "$RNS_LOCATION" | grep -oP '^.*?/uv/tools/rns')
|
||||
RNS_PYTHON="$UV_RNS_PATH/bin/python"
|
||||
|
||||
if [ ! -f "$RNS_PYTHON" ]; then
|
||||
print_error "uv Python not found at: $RNS_PYTHON"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
INSTALL_MODE="uv"
|
||||
print_success "Detected uv tool installation at: $UV_RNS_PATH"
|
||||
|
||||
# Check if it's a pipx installation
|
||||
elif [[ "$RNS_LOCATION" == *"/pipx/venvs/"* ]]; then
|
||||
print_info "RNS appears to be installed via pipx"
|
||||
|
||||
# Verify pipx command is available
|
||||
|
|
@ -308,6 +324,55 @@ if command -v rnsd &> /dev/null; then
|
|||
INSTALL_MODE="system"
|
||||
RNS_PYTHON="python3"
|
||||
fi
|
||||
else
|
||||
# rnsd exists but python3 can't import RNS
|
||||
# This happens with uv/pipx when system python3 differs from tool's python
|
||||
print_warning "rnsd found but RNS not importable by system python3"
|
||||
print_info "Checking rnsd shebang for isolated environment..."
|
||||
|
||||
RNSD_PATH=$(which rnsd)
|
||||
RNSD_SHEBANG=$(head -1 "$RNSD_PATH" 2>/dev/null)
|
||||
|
||||
if [[ "$RNSD_SHEBANG" == *"/uv/tools/rns/"* ]]; then
|
||||
# uv tool installation
|
||||
print_info "RNS appears to be installed via uv tool"
|
||||
UV_RNS_PATH=$(echo "$RNSD_SHEBANG" | grep -oP '^#!\K.*?/uv/tools/rns' || echo "$HOME/.local/share/uv/tools/rns")
|
||||
RNS_PYTHON="$UV_RNS_PATH/bin/python"
|
||||
|
||||
if [ -f "$RNS_PYTHON" ]; then
|
||||
INSTALL_MODE="uv"
|
||||
print_success "Detected uv tool installation at: $UV_RNS_PATH"
|
||||
else
|
||||
print_error "uv Python not found at: $RNS_PYTHON"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
elif [[ "$RNSD_SHEBANG" == *"/pipx/venvs/rns/"* ]]; then
|
||||
# pipx installation
|
||||
print_info "RNS appears to be installed via pipx"
|
||||
PIPX_RNS_PATH=$(echo "$RNSD_SHEBANG" | grep -oP '^#!\K.*?/pipx/venvs/rns' || echo "$HOME/.local/pipx/venvs/rns")
|
||||
RNS_PYTHON="$PIPX_RNS_PATH/bin/python3"
|
||||
|
||||
if [ -f "$RNS_PYTHON" ]; then
|
||||
INSTALL_MODE="pipx"
|
||||
print_success "Detected pipx installation at: $PIPX_RNS_PATH"
|
||||
else
|
||||
print_error "pipx Python not found at: $RNS_PYTHON"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
else
|
||||
print_error "Could not determine RNS installation type from rnsd shebang"
|
||||
print_info "Shebang: $RNSD_SHEBANG"
|
||||
echo
|
||||
echo "Please ensure RNS is properly installed and accessible to python3:"
|
||||
echo " pip install rns"
|
||||
echo " # or"
|
||||
echo " uv tool install rns"
|
||||
echo " # or"
|
||||
echo " pipx install rns"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
print_warning "Reticulum (rnsd) not found"
|
||||
|
|
@ -400,7 +465,42 @@ if [[ "$ARCH" == "armhf" ]] || [[ "$(uname -m)" =~ ^(armv6l|armv7l)$ ]]; then
|
|||
fi
|
||||
fi
|
||||
|
||||
if [ "$INSTALL_MODE" = "pipx" ]; then
|
||||
if [ "$INSTALL_MODE" = "uv" ]; then
|
||||
print_info "Installing dependencies into uv tool environment..."
|
||||
echo
|
||||
|
||||
# uv tool environments are at ~/.local/share/uv/tools/<name>
|
||||
# We install directly using the tool's pip
|
||||
DEPS=("bleak==1.1.1" "bluezero" "dbus-python")
|
||||
|
||||
for dep in "${DEPS[@]}"; do
|
||||
print_info "Installing $dep into RNS environment..."
|
||||
|
||||
if uv pip install --python "$RNS_PYTHON" "$dep" 2>/dev/null; then
|
||||
print_success "Installed $dep"
|
||||
else
|
||||
print_error "Failed to install $dep"
|
||||
echo
|
||||
echo "Try manually:"
|
||||
echo " uv pip install --python $RNS_PYTHON $dep"
|
||||
exit 1
|
||||
fi
|
||||
echo
|
||||
done
|
||||
|
||||
# Verify all modules can be imported
|
||||
print_info "Verifying dependencies..."
|
||||
if "$RNS_PYTHON" -c "import bleak, bluezero, dbus" 2>/dev/null; then
|
||||
print_success "All dependencies verified and working"
|
||||
else
|
||||
print_error "Dependency verification failed"
|
||||
echo
|
||||
echo "Test imports manually:"
|
||||
echo " $RNS_PYTHON -c 'import bleak, bluezero, dbus'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
elif [ "$INSTALL_MODE" = "pipx" ]; then
|
||||
print_info "Installing dependencies via pipx inject..."
|
||||
print_warning "dbus-python will be compiled from source (may take 2-3 minutes)"
|
||||
echo
|
||||
|
|
@ -494,9 +594,9 @@ mkdir -p "$INTERFACES_DIR"
|
|||
|
||||
# Copy interface files
|
||||
print_info "Copying BLE interface files to: $INTERFACES_DIR"
|
||||
cp src/RNS/Interfaces/BLE*.py \
|
||||
src/RNS/Interfaces/bluetooth_driver.py \
|
||||
src/RNS/Interfaces/linux_bluetooth_driver.py \
|
||||
cp src/ble_reticulum/BLE*.py \
|
||||
src/ble_reticulum/bluetooth_driver.py \
|
||||
src/ble_reticulum/linux_bluetooth_driver.py \
|
||||
"$INTERFACES_DIR/"
|
||||
|
||||
# Create __init__.py if it doesn't exist
|
||||
|
|
@ -568,7 +668,10 @@ else
|
|||
print_info "Root user already has all required Bluetooth permissions"
|
||||
elif command -v setcap &> /dev/null; then
|
||||
# Determine correct Python path based on installation mode
|
||||
if [ "$INSTALL_MODE" = "pipx" ]; then
|
||||
if [ "$INSTALL_MODE" = "uv" ]; then
|
||||
PYTHON_PATH="$UV_RNS_PATH/bin/python"
|
||||
print_info "Using uv Python: $PYTHON_PATH"
|
||||
elif [ "$INSTALL_MODE" = "pipx" ]; then
|
||||
PYTHON_PATH="$PIPX_RNS_PATH/bin/python3"
|
||||
print_info "Using pipx Python: $PYTHON_PATH"
|
||||
elif [ "$INSTALL_MODE" = "venv" ]; then
|
||||
|
|
|
|||
|
|
@ -58,11 +58,11 @@ Repository = "https://github.com/torlando-tech/ble-reticulum"
|
|||
Issues = "https://github.com/torlando-tech/ble-reticulum/issues"
|
||||
|
||||
[tool.setuptools]
|
||||
packages = ["RNS.Interfaces"]
|
||||
packages = ["ble_reticulum"]
|
||||
package-dir = {"" = "src"}
|
||||
|
||||
[tool.setuptools.package-data]
|
||||
"RNS.Interfaces" = ["*.py"]
|
||||
"ble_reticulum" = ["*.py"]
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
testpaths = ["tests"]
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ try:
|
|||
HAS_BLE_AGENT = True
|
||||
except ImportError:
|
||||
try:
|
||||
from RNS.Interfaces.BLEAgent import register_agent, unregister_agent
|
||||
from ble_reticulum.BLEAgent import register_agent, unregister_agent
|
||||
HAS_BLE_AGENT = True
|
||||
except ImportError:
|
||||
HAS_BLE_AGENT = False
|
||||
|
|
@ -67,10 +67,7 @@ except NameError:
|
|||
if _interface_dir not in sys.path:
|
||||
sys.path.insert(0, _interface_dir)
|
||||
|
||||
# Import base Interface class
|
||||
# When integrated into Reticulum, this will be:
|
||||
# from RNS.Interfaces.Interface import Interface
|
||||
# For now, we'll need to handle the import path
|
||||
# Import base Interface class from Reticulum
|
||||
try:
|
||||
from RNS.Interfaces.Interface import Interface
|
||||
except ImportError:
|
||||
|
|
@ -85,7 +82,7 @@ try:
|
|||
from BLEFragmentation import BLEFragmenter, BLEReassembler
|
||||
except ImportError:
|
||||
# Fallback for when loaded as part of RNS package
|
||||
from RNS.Interfaces.BLEFragmentation import BLEFragmenter, BLEReassembler
|
||||
from ble_reticulum.BLEFragmentation import BLEFragmenter, BLEReassembler
|
||||
|
||||
# Import GATT server for peripheral mode
|
||||
try:
|
||||
|
|
@ -93,7 +90,7 @@ try:
|
|||
HAS_GATT_SERVER = True
|
||||
except ImportError:
|
||||
try:
|
||||
from RNS.Interfaces.BLEGATTServer import BLEGATTServer
|
||||
from ble_reticulum.BLEGATTServer import BLEGATTServer
|
||||
HAS_GATT_SERVER = True
|
||||
except ImportError:
|
||||
HAS_GATT_SERVER = False
|
||||
|
|
@ -102,7 +99,7 @@ except ImportError:
|
|||
try:
|
||||
from bluetooth_driver import BLEDriverInterface, BLEDevice
|
||||
except ImportError:
|
||||
from RNS.Interfaces.bluetooth_driver import BLEDriverInterface, BLEDevice
|
||||
from ble_reticulum.bluetooth_driver import BLEDriverInterface, BLEDevice
|
||||
|
||||
# Import platform-specific driver (optional - can be overridden by subclasses)
|
||||
try:
|
||||
|
|
@ -110,7 +107,7 @@ try:
|
|||
HAS_LINUX_DRIVER = True
|
||||
except ImportError:
|
||||
try:
|
||||
from RNS.Interfaces.linux_bluetooth_driver import LinuxBluetoothDriver
|
||||
from ble_reticulum.linux_bluetooth_driver import LinuxBluetoothDriver
|
||||
HAS_LINUX_DRIVER = True
|
||||
except ImportError:
|
||||
HAS_LINUX_DRIVER = False
|
||||
|
|
@ -184,7 +184,7 @@ try:
|
|||
HAS_BLE_AGENT = True
|
||||
except ImportError:
|
||||
try:
|
||||
from RNS.Interfaces.BLEAgent import register_agent, unregister_agent
|
||||
from ble_reticulum.BLEAgent import register_agent, unregister_agent
|
||||
HAS_BLE_AGENT = True
|
||||
except ImportError:
|
||||
HAS_BLE_AGENT = False
|
||||
|
|
@ -14,7 +14,7 @@ project_root = os.path.dirname(tests_dir)
|
|||
src_dir = os.path.join(project_root, 'src')
|
||||
|
||||
# Add src/ to path for BLE interface modules
|
||||
# This allows tests to import from src/RNS/Interfaces/
|
||||
# This allows tests to import from src/ble_reticulum/
|
||||
if src_dir not in sys.path:
|
||||
sys.path.insert(0, src_dir)
|
||||
|
||||
|
|
@ -237,7 +237,7 @@ def sample_configuration():
|
|||
def sample_discovered_peers():
|
||||
"""Sample DiscoveredPeer objects for testing."""
|
||||
try:
|
||||
from RNS.Interfaces.BLEInterface import DiscoveredPeer
|
||||
from ble_reticulum.BLEInterface import DiscoveredPeer
|
||||
except ImportError:
|
||||
# Create a simple mock DiscoveredPeer for testing
|
||||
import time
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ from unittest.mock import Mock, AsyncMock, patch, MagicMock
|
|||
|
||||
# Import fragmentation for testing
|
||||
try:
|
||||
from RNS.Interfaces.BLEFragmentation import BLEFragmenter, BLEReassembler
|
||||
from ble_reticulum.BLEFragmentation import BLEFragmenter, BLEReassembler
|
||||
except ImportError:
|
||||
BLEFragmenter = None
|
||||
BLEReassembler = None
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ class TestRemoveBlueZDeviceMethod:
|
|||
@pytest.mark.asyncio
|
||||
async def test_requires_dbus(self):
|
||||
"""Test that method returns False when D-Bus is not available."""
|
||||
from RNS.Interfaces import linux_bluetooth_driver
|
||||
from ble_reticulum import linux_bluetooth_driver
|
||||
|
||||
# Mock HAS_DBUS to False
|
||||
with patch.object(linux_bluetooth_driver, 'HAS_DBUS', False):
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ class TestBREDRFallbackPrevention:
|
|||
This tests the pure logic of parameter building, which is fully
|
||||
unit-testable without D-Bus.
|
||||
"""
|
||||
from RNS.Interfaces import linux_bluetooth_driver
|
||||
from ble_reticulum import linux_bluetooth_driver
|
||||
|
||||
# Mock driver
|
||||
driver = Mock()
|
||||
|
|
@ -97,7 +97,7 @@ class TestBREDRFallbackPrevention:
|
|||
This test verifies that we handle the object path return value
|
||||
properly instead of ignoring it.
|
||||
"""
|
||||
from RNS.Interfaces import linux_bluetooth_driver
|
||||
from ble_reticulum import linux_bluetooth_driver
|
||||
|
||||
# Mock the D-Bus call to return an object path (what BlueZ actually returns)
|
||||
mock_object_path = "/org/bluez/hci0/dev_AA_BB_CC_DD_EE_FF"
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class TestConfigDirectoryResolution(unittest.TestCase):
|
|||
# Remove BLEInterface from sys.modules if it was imported
|
||||
modules_to_remove = [
|
||||
'BLEInterface',
|
||||
'RNS.Interfaces.BLEInterface'
|
||||
'ble_reticulum.BLEInterface'
|
||||
]
|
||||
for module in modules_to_remove:
|
||||
if module in sys.modules:
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ class TestDBusDisconnectMonitoring:
|
|||
@pytest.fixture
|
||||
def mock_gatt_server(self, mock_driver):
|
||||
"""Create mock GATT server with monitoring setup."""
|
||||
from RNS.Interfaces.linux_bluetooth_driver import BluezeroGATTServer
|
||||
from ble_reticulum.linux_bluetooth_driver import BluezeroGATTServer
|
||||
|
||||
server = Mock(spec=BluezeroGATTServer)
|
||||
server.driver = mock_driver
|
||||
|
|
@ -304,7 +304,7 @@ class TestDBusDisconnectMonitoring:
|
|||
|
||||
def test_error_handling_no_dbus(self, mock_gatt_server):
|
||||
"""Test that monitoring returns early when D-Bus is not available."""
|
||||
with patch('RNS.Interfaces.linux_bluetooth_driver.HAS_DBUS', False):
|
||||
with patch('ble_reticulum.linux_bluetooth_driver.HAS_DBUS', False):
|
||||
# Simulate the early return logic
|
||||
HAS_DBUS = False
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ from unittest.mock import Mock, AsyncMock, patch, MagicMock
|
|||
# conftest.py handles path setup - imports should work after that
|
||||
# Import only what we need for testing
|
||||
try:
|
||||
from RNS.Interfaces.BLEFragmentation import BLEFragmenter, BLEReassembler
|
||||
from ble_reticulum.BLEFragmentation import BLEFragmenter, BLEReassembler
|
||||
except ImportError:
|
||||
# If imports fail, tests will be skipped
|
||||
BLEFragmenter = None
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import os
|
|||
# Add parent directory to path
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../src'))
|
||||
|
||||
from RNS.Interfaces.BLEFragmentation import BLEFragmenter, BLEReassembler, HDLCFramer
|
||||
from ble_reticulum.BLEFragmentation import BLEFragmenter, BLEReassembler, HDLCFramer
|
||||
|
||||
|
||||
class TestBLEFragmenter:
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import os
|
|||
# Add src to path
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src'))
|
||||
|
||||
from RNS.Interfaces.BLEGATTServer import BLEGATTServer, BLESS_AVAILABLE
|
||||
from ble_reticulum.BLEGATTServer import BLEGATTServer, BLESS_AVAILABLE
|
||||
|
||||
|
||||
class MockInterface:
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ class TestEventDrivenDBusMonitor:
|
|||
@pytest.fixture
|
||||
def mock_gatt_server(self, mock_driver):
|
||||
"""Create mock GATT server with event-driven monitoring setup."""
|
||||
from RNS.Interfaces.linux_bluetooth_driver import BluezeroGATTServer
|
||||
from ble_reticulum.linux_bluetooth_driver import BluezeroGATTServer
|
||||
|
||||
server = Mock(spec=BluezeroGATTServer)
|
||||
server.driver = mock_driver
|
||||
|
|
@ -729,7 +729,7 @@ class TestCodeVerification:
|
|||
# Read the actual source file
|
||||
source_path = os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
'../src/RNS/Interfaces/linux_bluetooth_driver.py'
|
||||
'../src/ble_reticulum/linux_bluetooth_driver.py'
|
||||
)
|
||||
|
||||
with open(source_path, 'r') as f:
|
||||
|
|
@ -748,7 +748,7 @@ class TestCodeVerification:
|
|||
|
||||
source_path = os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
'../src/RNS/Interfaces/linux_bluetooth_driver.py'
|
||||
'../src/ble_reticulum/linux_bluetooth_driver.py'
|
||||
)
|
||||
|
||||
with open(source_path, 'r') as f:
|
||||
|
|
@ -776,7 +776,7 @@ class TestCodeVerification:
|
|||
"""Verify that stop() uses call_soon_threadsafe."""
|
||||
source_path = os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
'../src/RNS/Interfaces/linux_bluetooth_driver.py'
|
||||
'../src/ble_reticulum/linux_bluetooth_driver.py'
|
||||
)
|
||||
|
||||
with open(source_path, 'r') as f:
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ class TestComputeIdentityHash:
|
|||
# Read the actual BLEInterface.py source
|
||||
ble_interface_path = os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
'../src/RNS/Interfaces/BLEInterface.py'
|
||||
'../src/ble_reticulum/BLEInterface.py'
|
||||
)
|
||||
|
||||
with open(ble_interface_path, 'r') as f:
|
||||
|
|
|
|||
|
|
@ -23,12 +23,12 @@ def test_config_options():
|
|||
|
||||
def test_interface_has_gatt_integration():
|
||||
"""Test that BLEInterface.py uses driver abstraction for peripheral mode."""
|
||||
interface_path = os.path.join(os.path.dirname(__file__), '../src/RNS/Interfaces/BLEInterface.py')
|
||||
interface_path = os.path.join(os.path.dirname(__file__), '../src/ble_reticulum/BLEInterface.py')
|
||||
with open(interface_path, 'r') as f:
|
||||
code = f.read()
|
||||
|
||||
# Check for driver-based architecture
|
||||
assert 'from RNS.Interfaces.bluetooth_driver import BLEDriverInterface' in code or 'bluetooth_driver' in code
|
||||
assert 'from ble_reticulum.bluetooth_driver import BLEDriverInterface' in code or 'bluetooth_driver' in code
|
||||
|
||||
# Check for peripheral mode configuration
|
||||
assert 'enable_peripheral' in code
|
||||
|
|
@ -48,7 +48,7 @@ def test_interface_has_gatt_integration():
|
|||
|
||||
def test_peer_interface_has_routing():
|
||||
"""Test that BLEPeerInterface uses driver for sending."""
|
||||
interface_path = os.path.join(os.path.dirname(__file__), '../src/RNS/Interfaces/BLEInterface.py')
|
||||
interface_path = os.path.join(os.path.dirname(__file__), '../src/ble_reticulum/BLEInterface.py')
|
||||
with open(interface_path, 'r') as f:
|
||||
code = f.read()
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ def test_peer_interface_has_routing():
|
|||
|
||||
def test_gatt_server_file_exists():
|
||||
"""Test that BLEGATTServer module exists."""
|
||||
server_path = os.path.join(os.path.dirname(__file__), '../src/RNS/Interfaces/BLEGATTServer.py')
|
||||
server_path = os.path.join(os.path.dirname(__file__), '../src/ble_reticulum/BLEGATTServer.py')
|
||||
assert os.path.exists(server_path)
|
||||
|
||||
with open(server_path, 'r') as f:
|
||||
|
|
@ -80,7 +80,7 @@ def test_gatt_server_file_exists():
|
|||
def test_driver_abstraction_exists():
|
||||
"""Test that driver abstraction layer is properly implemented."""
|
||||
# Check driver interface exists
|
||||
driver_interface_path = os.path.join(os.path.dirname(__file__), '../src/RNS/Interfaces/bluetooth_driver.py')
|
||||
driver_interface_path = os.path.join(os.path.dirname(__file__), '../src/ble_reticulum/bluetooth_driver.py')
|
||||
assert os.path.exists(driver_interface_path)
|
||||
|
||||
with open(driver_interface_path, 'r') as f:
|
||||
|
|
@ -91,7 +91,7 @@ def test_driver_abstraction_exists():
|
|||
assert 'ABC' in code or 'abstractmethod' in code
|
||||
|
||||
# Check Linux driver implementation exists
|
||||
linux_driver_path = os.path.join(os.path.dirname(__file__), '../src/RNS/Interfaces/linux_bluetooth_driver.py')
|
||||
linux_driver_path = os.path.join(os.path.dirname(__file__), '../src/ble_reticulum/linux_bluetooth_driver.py')
|
||||
assert os.path.exists(linux_driver_path)
|
||||
|
||||
with open(linux_driver_path, 'r') as f:
|
||||
|
|
@ -118,7 +118,7 @@ def test_identity_based_fragmenter_keying():
|
|||
|
||||
Reference: BLE_PROTOCOL_v2.2.md §7 Identity-Based Keying
|
||||
"""
|
||||
interface_path = os.path.join(os.path.dirname(__file__), '../src/RNS/Interfaces/BLEInterface.py')
|
||||
interface_path = os.path.join(os.path.dirname(__file__), '../src/ble_reticulum/BLEInterface.py')
|
||||
with open(interface_path, 'r') as f:
|
||||
code = f.read()
|
||||
|
||||
|
|
|
|||
|
|
@ -456,7 +456,7 @@ class TestRealWorldScenario:
|
|||
Verifies that cleanup is idempotent - if both mechanisms detect the same
|
||||
disconnect, cleanup should only happen once without errors.
|
||||
"""
|
||||
from RNS.Interfaces.linux_bluetooth_driver import BluezeroGATTServer
|
||||
from ble_reticulum.linux_bluetooth_driver import BluezeroGATTServer
|
||||
|
||||
# Setup GATT server with monitoring
|
||||
server = Mock(spec=BluezeroGATTServer)
|
||||
|
|
@ -502,7 +502,7 @@ class TestRealWorldScenario:
|
|||
Simulates scenario where D-Bus signal fails or is delayed, but polling
|
||||
fallback detects and triggers cleanup within 30 seconds.
|
||||
"""
|
||||
from RNS.Interfaces.linux_bluetooth_driver import BluezeroGATTServer
|
||||
from ble_reticulum.linux_bluetooth_driver import BluezeroGATTServer
|
||||
|
||||
# Setup GATT server
|
||||
server = Mock(spec=BluezeroGATTServer)
|
||||
|
|
|
|||
|
|
@ -431,7 +431,7 @@ class TestImplementationValidation:
|
|||
|
||||
def test_discovered_peer_class_exists(self):
|
||||
"""Test that DiscoveredPeer class is in the source file"""
|
||||
interface_path = os.path.join(os.path.dirname(__file__), '../src/RNS/Interfaces/BLEInterface.py')
|
||||
interface_path = os.path.join(os.path.dirname(__file__), '../src/ble_reticulum/BLEInterface.py')
|
||||
with open(interface_path, 'r') as f:
|
||||
code = f.read()
|
||||
|
||||
|
|
@ -444,7 +444,7 @@ class TestImplementationValidation:
|
|||
|
||||
def test_prioritization_methods_exist(self):
|
||||
"""Test that prioritization methods exist in BLEInterface.py"""
|
||||
interface_path = os.path.join(os.path.dirname(__file__), '../src/RNS/Interfaces/BLEInterface.py')
|
||||
interface_path = os.path.join(os.path.dirname(__file__), '../src/ble_reticulum/BLEInterface.py')
|
||||
with open(interface_path, 'r') as f:
|
||||
code = f.read()
|
||||
|
||||
|
|
@ -458,7 +458,7 @@ class TestImplementationValidation:
|
|||
|
||||
def test_configuration_options_exist(self):
|
||||
"""Test that prioritization configuration options exist"""
|
||||
interface_path = os.path.join(os.path.dirname(__file__), '../src/RNS/Interfaces/BLEInterface.py')
|
||||
interface_path = os.path.join(os.path.dirname(__file__), '../src/ble_reticulum/BLEInterface.py')
|
||||
with open(interface_path, 'r') as f:
|
||||
code = f.read()
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ class TestScannerConnectionCoordination:
|
|||
if scanning should be paused based on connection state.
|
||||
"""
|
||||
# Import the actual driver to test real method
|
||||
from RNS.Interfaces import linux_bluetooth_driver
|
||||
from ble_reticulum import linux_bluetooth_driver
|
||||
|
||||
# Create minimal driver instance
|
||||
driver = Mock()
|
||||
|
|
@ -103,7 +103,7 @@ class TestScannerConnectionCoordination:
|
|||
This test reproduces the core bug - scanner doesn't know to pause
|
||||
when connections are active.
|
||||
"""
|
||||
from RNS.Interfaces import linux_bluetooth_driver
|
||||
from ble_reticulum import linux_bluetooth_driver
|
||||
|
||||
driver = Mock()
|
||||
driver._connecting_peers = {"AA:BB:CC:DD:EE:FF"}
|
||||
|
|
@ -126,7 +126,7 @@ class TestScannerConnectionCoordination:
|
|||
|
||||
PASSES AFTER FIX: Method correctly handles multiple connections
|
||||
"""
|
||||
from RNS.Interfaces import linux_bluetooth_driver
|
||||
from ble_reticulum import linux_bluetooth_driver
|
||||
|
||||
driver = Mock()
|
||||
driver._connecting_peers = {
|
||||
|
|
@ -156,7 +156,7 @@ class TestScannerConnectionCoordination:
|
|||
This test verifies the coordination logic is actually used in the
|
||||
scan loop. We mock BleakScanner to avoid real Bluetooth operations.
|
||||
"""
|
||||
from RNS.Interfaces import linux_bluetooth_driver
|
||||
from ble_reticulum import linux_bluetooth_driver
|
||||
|
||||
# Create mock driver
|
||||
driver = Mock()
|
||||
|
|
@ -196,7 +196,7 @@ class TestScannerConnectionCoordination:
|
|||
|
||||
PASSES AFTER FIX: Scanner starts when _connecting_peers is empty
|
||||
"""
|
||||
from RNS.Interfaces import linux_bluetooth_driver
|
||||
from ble_reticulum import linux_bluetooth_driver
|
||||
|
||||
driver = Mock()
|
||||
driver._connecting_peers = set() # No connections
|
||||
|
|
@ -231,7 +231,7 @@ class TestScannerConnectionCoordination:
|
|||
2. Connection completes -> peer removed from _connecting_peers
|
||||
3. Next scan loop iteration -> scanner resumes
|
||||
"""
|
||||
from RNS.Interfaces import linux_bluetooth_driver
|
||||
from ble_reticulum import linux_bluetooth_driver
|
||||
|
||||
driver = Mock()
|
||||
driver._connecting_peers = {"AA:BB:CC:DD:EE:FF"}
|
||||
|
|
@ -280,7 +280,7 @@ class TestScannerConnectionCoordination:
|
|||
- It correctly identifies when to pause
|
||||
- It prevents scanner.start() calls during connections
|
||||
"""
|
||||
from RNS.Interfaces import linux_bluetooth_driver
|
||||
from ble_reticulum import linux_bluetooth_driver
|
||||
|
||||
driver = Mock()
|
||||
driver._log = Mock()
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ class TestStaleConnectionPolling:
|
|||
@pytest.fixture
|
||||
def mock_gatt_server(self, mock_driver):
|
||||
"""Create mock GATT server with polling setup."""
|
||||
from RNS.Interfaces.linux_bluetooth_driver import BluezeroGATTServer
|
||||
from ble_reticulum.linux_bluetooth_driver import BluezeroGATTServer
|
||||
|
||||
server = Mock(spec=BluezeroGATTServer)
|
||||
server.driver = mock_driver
|
||||
|
|
|
|||
|
|
@ -53,11 +53,11 @@ if not hasattr(RNS, 'Identity'):
|
|||
RNS.Identity = MagicMock()
|
||||
RNS.Identity.full_hash = lambda x: (x * 2)[:16] # Simple mock
|
||||
|
||||
# Mock RNS.Interfaces.Interface (required by BLEInterface.py)
|
||||
# Mock ble_reticulum.Interface (required by BLEInterface.py)
|
||||
# First, ensure mock is in place BEFORE any imports that need it
|
||||
rns_interfaces_mock = MagicMock()
|
||||
_sys.modules['RNS.Interfaces'] = rns_interfaces_mock
|
||||
_sys.modules['RNS.Interfaces.Interface'] = MagicMock()
|
||||
_sys.modules['ble_reticulum'] = rns_interfaces_mock
|
||||
_sys.modules['ble_reticulum.Interface'] = MagicMock()
|
||||
|
||||
# Create mock Interface base class
|
||||
class MockInterface:
|
||||
|
|
@ -89,7 +89,7 @@ class MockInterface:
|
|||
return ConfigObj(configuration)
|
||||
|
||||
rns_interfaces_mock.Interface = MockInterface
|
||||
_sys.modules['RNS.Interfaces.Interface'].Interface = MockInterface
|
||||
_sys.modules['ble_reticulum.Interface'].Interface = MockInterface
|
||||
|
||||
from tests.mock_ble_driver import MockBLEDriver
|
||||
|
||||
|
|
|
|||
|
|
@ -59,9 +59,9 @@ if not hasattr(RNS, 'Identity'):
|
|||
RNS.Identity = MagicMock()
|
||||
RNS.Identity.full_hash = lambda x: (x * 2)[:16]
|
||||
|
||||
# Mock RNS.Interfaces.Interface module (the base class module, not the whole namespace)
|
||||
# Mock ble_reticulum.Interface module (the base class module, not the whole namespace)
|
||||
# We only mock the Interface.py module, allowing BLEInterface.py to be imported from src/
|
||||
if 'RNS.Interfaces.Interface' not in _sys.modules:
|
||||
if 'ble_reticulum.Interface' not in _sys.modules:
|
||||
# Create mock Interface base class
|
||||
class MockInterface:
|
||||
MODE_FULL = 1
|
||||
|
|
@ -100,13 +100,13 @@ if 'RNS.Interfaces.Interface' not in _sys.modules:
|
|||
return bool(val) if val is not None else default
|
||||
return ConfigObj(configuration)
|
||||
|
||||
# Create a mock module for RNS.Interfaces.Interface
|
||||
# Create a mock module for ble_reticulum.Interface
|
||||
interface_module = MagicMock()
|
||||
interface_module.Interface = MockInterface
|
||||
_sys.modules['RNS.Interfaces.Interface'] = interface_module
|
||||
_sys.modules['ble_reticulum.Interface'] = interface_module
|
||||
|
||||
from tests.mock_ble_driver import MockBLEDriver
|
||||
from RNS.Interfaces.BLEInterface import BLEInterface, DiscoveredPeer
|
||||
from ble_reticulum.BLEInterface import BLEInterface, DiscoveredPeer
|
||||
import time
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -64,10 +64,10 @@ if not hasattr(RNS, 'Identity'):
|
|||
RNS.Identity = MagicMock()
|
||||
RNS.Identity.full_hash = lambda x: (x * 2)[:16]
|
||||
|
||||
# Mock RNS.Interfaces.Interface (required by BLEInterface.py)
|
||||
if 'RNS.Interfaces' not in _sys.modules:
|
||||
# Mock ble_reticulum.Interface (required by BLEInterface.py)
|
||||
if 'ble_reticulum' not in _sys.modules:
|
||||
rns_interfaces_mock = MagicMock()
|
||||
_sys.modules['RNS.Interfaces'] = rns_interfaces_mock
|
||||
_sys.modules['ble_reticulum'] = rns_interfaces_mock
|
||||
|
||||
# Create mock Interface base class
|
||||
class MockInterface:
|
||||
|
|
@ -80,7 +80,7 @@ if 'RNS.Interfaces' not in _sys.modules:
|
|||
rns_interfaces_mock.Interface = MockInterface
|
||||
|
||||
from tests.mock_ble_driver import MockBLEDriver
|
||||
from RNS.Interfaces.BLEInterface import BLEInterface, DiscoveredPeer
|
||||
from ble_reticulum.BLEInterface import BLEInterface, DiscoveredPeer
|
||||
|
||||
|
||||
class MockOwner:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue