BE: linting fixes 2

Signed-off-by: jokob-sk <jokob.sk@gmail.com>
This commit is contained in:
jokob-sk
2025-11-22 20:43:36 +11:00
parent 5c14b34a8b
commit ebeb7a07af
63 changed files with 124 additions and 113 deletions

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import sys import sys

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
# Just a testing library plugin for development purposes # Just a testing library plugin for development purposes
import os import os
import sys import sys

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import json import json
import subprocess import subprocess

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import sys import sys
import re import re

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import json import json
import os import os

View File

@@ -1,5 +1,5 @@
# !/usr/bin/env python #!/usr/bin/env python
import json import json
import os import os

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python3 #!/usr/bin/env python3
import conf import conf
from const import confFileName, logPath from const import confFileName, logPath
from pytz import timezone from pytz import timezone

View File

@@ -1,5 +1,5 @@
# !/usr/bin/env python #!/usr/bin/env python
import json import json
import os import os

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import subprocess import subprocess
import os import os

View File

@@ -1,5 +1,5 @@
# !/usr/bin/env python #!/usr/bin/env python
import json import json
import subprocess import subprocess

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import time import time
import argparse import argparse

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import sys import sys

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python3 #!/usr/bin/env python3
import os import os
import sys import sys
import socket import socket

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import argparse import argparse

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import sys import sys

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import argparse import argparse

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
from __future__ import unicode_literals from __future__ import unicode_literals
import argparse import argparse

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
# Based on the work of https://github.com/leiweibau/Pi.Alert # Based on the work of https://github.com/leiweibau/Pi.Alert
import subprocess import subprocess

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import sys import sys
import subprocess import subprocess

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import sys import sys

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
# test script by running: # test script by running:
# tbc # tbc

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import time import time

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import sys import sys

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import sys import sys

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import sys import sys

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import sys import sys

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import sys import sys

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import sys import sys

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
# test script by running: # test script by running:
# tbc # tbc

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import argparse import argparse

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
# test script by running: # test script by running:
# tbc # tbc

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
__author__ = "ffsb" __author__ = "ffsb"
__version__ = "0.1" # initial __version__ = "0.1" # initial
__version__ = "0.2" # added logic to retry omada api call once as it seems to sometimes fail for some reasons, and error handling logic... __version__ = "0.2" # added logic to retry omada api call once as it seems to sometimes fail for some reasons, and error handling logic...
@@ -134,7 +134,7 @@ def callomada(myargs):
omada_output = "" omada_output = ""
retries = 2 retries = 2
while omada_output == "" and retries > 1: while omada_output == "" and retries > 0:
retries = retries - 1 retries = retries - 1
try: try:
mf = io.StringIO() mf = io.StringIO()
@@ -183,51 +183,71 @@ def add_uplink(
sadevices_linksbymac, sadevices_linksbymac,
port_byswitchmac_byclientmac, port_byswitchmac_byclientmac,
): ):
# Ensure switch_mac exists in device_data_bymac # Ensure switch exists
if switch_mac not in device_data_bymac: if switch_mac not in device_data_bymac:
mylog("none", [f"[{pluginName}] switch_mac '{switch_mac}' not found in device_data_bymac"]) mylog("none", [f"[{pluginName}] switch_mac '{switch_mac}' not found in device_data_bymac"])
return return
# Ensure SWITCH_AP key exists in the dictionary dev_switch = device_data_bymac[switch_mac]
if SWITCH_AP not in device_data_bymac[switch_mac]:
mylog("none", [f"[{pluginName}] Missing key '{SWITCH_AP}' in device_data_bymac[{switch_mac}]"]) # Ensure list is long enough to contain SWITCH_AP index
if len(dev_switch) <= SWITCH_AP:
mylog("none", [f"[{pluginName}] SWITCH_AP index {SWITCH_AP} missing in record for {switch_mac}"])
return return
# Check if uplink should be added # Add uplink only if empty
if device_data_bymac[switch_mac][SWITCH_AP] in [None, "null"]: if dev_switch[SWITCH_AP] in (None, "null"):
device_data_bymac[switch_mac][SWITCH_AP] = uplink_mac dev_switch[SWITCH_AP] = uplink_mac
# Ensure uplink_mac exists in device_data_bymac # Validate uplink_mac exists
if uplink_mac not in device_data_bymac: if uplink_mac not in device_data_bymac:
mylog("none", [f"[{pluginName}] uplink_mac '{uplink_mac}' not found in device_data_bymac"]) mylog("none", [f"[{pluginName}] uplink_mac '{uplink_mac}' not found in device_data_bymac"])
return return
# Determine port to uplink dev_uplink = device_data_bymac[uplink_mac]
if (
device_data_bymac[switch_mac].get(TYPE) == "Switch" and device_data_bymac[uplink_mac].get(TYPE) == "Switch" # Get TYPE safely
): switch_type = dev_switch[TYPE] if len(dev_switch) > TYPE else None
uplink_type = dev_uplink[TYPE] if len(dev_uplink) > TYPE else None
# Switch-to-switch link → use port mapping
if switch_type == "Switch" and uplink_type == "Switch":
port_to_uplink = port_byswitchmac_byclientmac.get(switch_mac, {}).get(uplink_mac) port_to_uplink = port_byswitchmac_byclientmac.get(switch_mac, {}).get(uplink_mac)
if port_to_uplink is None: if port_to_uplink is None:
mylog("none", [f"[{pluginName}] Missing port info for switch_mac '{switch_mac}' and uplink_mac '{uplink_mac}'"]) mylog("none", [
f"[{pluginName}] Missing port info for {switch_mac}{uplink_mac}"
])
return return
else: else:
port_to_uplink = device_data_bymac[uplink_mac].get(PORT_SSID) # Other device types → read PORT_SSID index
if len(dev_uplink) <= PORT_SSID:
mylog("none", [
f"[{pluginName}] PORT_SSID index missing for uplink {uplink_mac}"
])
return
port_to_uplink = dev_uplink[PORT_SSID]
# Assign port to switch_mac # Assign port to switch
device_data_bymac[switch_mac][PORT_SSID] = port_to_uplink if len(dev_switch) > PORT_SSID:
dev_switch[PORT_SSID] = port_to_uplink
else:
mylog("none", [
f"[{pluginName}] PORT_SSID index missing in switch {switch_mac}"
])
# Recursively add uplinks for linked devices # Process children recursively
for link in sadevices_linksbymac.get(switch_mac, []): for link in sadevices_linksbymac.get(switch_mac, []):
if ( if (
link in device_data_bymac and device_data_bymac[link].get(SWITCH_AP) in [None, "null"] and device_data_bymac[switch_mac].get(TYPE) == "Switch" link in device_data_bymac and len(device_data_bymac[link]) > SWITCH_AP and device_data_bymac[link][SWITCH_AP] in (None, "null") and len(dev_switch) > TYPE
): ):
add_uplink( if dev_switch[TYPE] == "Switch":
switch_mac, add_uplink(
link, switch_mac,
device_data_bymac, link,
sadevices_linksbymac, device_data_bymac,
port_byswitchmac_byclientmac, sadevices_linksbymac,
) port_byswitchmac_byclientmac,
)
# ---------------------------------------------- # ----------------------------------------------

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
""" """
This plugin imports devices and clients from Omada Controller using their OpenAPI. This plugin imports devices and clients from Omada Controller using their OpenAPI.
@@ -296,7 +296,7 @@ class OmadaAPI:
OmadaHelper.verbose(f"{method} request error: {str(ex)}") OmadaHelper.verbose(f"{method} request error: {str(ex)}")
return OmadaHelper.response("error", f"{method} request failed to endpoint '{endpoint}' with error: {str(ex)}") return OmadaHelper.response("error", f"{method} request failed to endpoint '{endpoint}' with error: {str(ex)}")
def authenticate(self) -> Dict[str, any]: def authenticate(self) -> Dict[str, Any]:
"""Make an endpoint request to get access token.""" """Make an endpoint request to get access token."""
OmadaHelper.verbose("Starting authentication process") OmadaHelper.verbose("Starting authentication process")

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
""" """
NetAlertX plugin: PIHOLEAPI NetAlertX plugin: PIHOLEAPI
Imports devices from Pi-hole v6 API (Network endpoints) into NetAlertX plugin results. Imports devices from Pi-hole v6 API (Network endpoints) into NetAlertX plugin results.

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
from __future__ import unicode_literals from __future__ import unicode_literals
import subprocess import subprocess

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import sys import sys

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import sys import sys

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
# Inspired by https://github.com/stevehoek/Pi.Alert # Inspired by https://github.com/stevehoek/Pi.Alert
from __future__ import unicode_literals from __future__ import unicode_literals

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import sys import sys

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import sys import sys

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
# Based on the work of https://github.com/leiweibau/Pi.Alert # Based on the work of https://github.com/leiweibau/Pi.Alert
import requests import requests

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python3 #!/usr/bin/env python3
import os import os
import sys import sys

4
ruff.toml Normal file
View File

@@ -0,0 +1,4 @@
[lint]
select = ["E", "F"] # or whatever you are using
# Add E402 so Ruff knows the noqa is legitimate
extend-select = ["E402"]

View File

@@ -1,5 +1,5 @@
# !/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
NetAlertX-New-Devices-Checkmk-Script NetAlertX-New-Devices-Checkmk-Script

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python3 #!/usr/bin/env python3
import subprocess import subprocess
import os import os

View File

@@ -30,7 +30,8 @@ def parse_timestamp(date_str):
dt = datetime.strptime(clean_date, '%Y/%m/%d %H:%M:%S') dt = datetime.strptime(clean_date, '%Y/%m/%d %H:%M:%S')
return int(dt.timestamp()) return int(dt.timestamp())
except Exception as e: except Exception as e:
logger.error(f"Failed to parse timestamp: {date_str} ({e})") if logger:
logger.error(f"Failed to parse timestamp: {date_str} ({e})")
return None return None
@@ -83,9 +84,8 @@ def get_lease_file(hostname, username, password=None, key_filename=None, port=22
# Clean up the output by removing the command echo and shell prompts # Clean up the output by removing the command echo and shell prompts
lines = output.split('\n') lines = output.split('\n')
# Remove first line (command echo) and any lines containing shell prompts # Remove first line (command echo) and any lines containing shell prompts
# cleaned_lines = [line for line in lines
# if not line.strip().startswith(command.strip()) and not line.strip().endswith('> ') and not line.strip().endswith('# ')]
cmd = command.strip() cmd = command.strip()
cleaned_lines = [] cleaned_lines = []

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
# #
# ------------------------------------------------------------------------------- # -------------------------------------------------------------------------------
# NetAlertX v2.70 / 2021-02-01 # NetAlertX v2.70 / 2021-02-01

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import json import json
import time import time
import threading import threading

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import base64 import base64

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import sys import sys

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import base64 import base64

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import sys import sys

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import sys import sys

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
import os import os
import sqlite3 import sqlite3

View File

@@ -136,23 +136,6 @@ def ensure_views(sql) -> bool:
"""CREATE VIEW Sessions_Devices AS SELECT * FROM Sessions LEFT JOIN "Devices" ON ses_MAC = devMac;""" """CREATE VIEW Sessions_Devices AS SELECT * FROM Sessions LEFT JOIN "Devices" ON ses_MAC = devMac;"""
) )
sql.execute(""" CREATE VIEW IF NOT EXISTS LatestEventsPerMAC AS
WITH RankedEvents AS (
SELECT
e.*,
ROW_NUMBER() OVER (PARTITION BY e.eve_MAC ORDER BY e.eve_DateTime DESC) AS row_num
FROM Events AS e
)
SELECT
e.*,
d.*,
c.*
FROM RankedEvents AS e
LEFT JOIN Devices AS d ON e.eve_MAC = d.devMac
INNER JOIN CurrentScan AS c ON e.eve_MAC = c.cur_MAC
WHERE e.row_num = 1;
""")
# handling the Convert_Events_to_Sessions / Sessions screens # handling the Convert_Events_to_Sessions / Sessions screens
sql.execute("""DROP VIEW IF EXISTS Convert_Events_to_Sessions;""") sql.execute("""DROP VIEW IF EXISTS Convert_Events_to_Sessions;""")
sql.execute("""CREATE VIEW Convert_Events_to_Sessions AS SELECT EVE1.eve_MAC, sql.execute("""CREATE VIEW Convert_Events_to_Sessions AS SELECT EVE1.eve_MAC,

View File

@@ -624,6 +624,11 @@ def extract_ip_addresses(text):
# Helper function to determine if a MAC address is random # Helper function to determine if a MAC address is random
def is_random_mac(mac): def is_random_mac(mac):
"""Determine if a MAC address is random, respecting user-defined prefixes not to mark as random.""" """Determine if a MAC address is random, respecting user-defined prefixes not to mark as random."""
# Validate input
if not mac or len(mac) < 2:
return False
# Check if second character matches "2", "6", "A", "E" (case insensitive) # Check if second character matches "2", "6", "A", "E" (case insensitive)
is_random = mac[1].upper() in ["2", "6", "A", "E"] is_random = mac[1].upper() in ["2", "6", "A", "E"]
@@ -631,7 +636,7 @@ def is_random_mac(mac):
if is_random: if is_random:
not_random_prefixes = get_setting_value("UI_NOT_RANDOM_MAC") not_random_prefixes = get_setting_value("UI_NOT_RANDOM_MAC")
for prefix in not_random_prefixes: for prefix in not_random_prefixes:
if mac.startswith(prefix): if mac.upper().startswith(prefix.upper()):
is_random = False is_random = False
break break
return is_random return is_random

View File

@@ -10,7 +10,7 @@ import re
# Register NetAlertX libraries # Register NetAlertX libraries
import conf import conf
from const import fullConfPath, fullConfFolder, default_tz from const import fullConfPath, fullConfFolder, default_tz
from helper import getBuildTimeStampAndVersion, fixPermissions, collect_lang_strings, updateSubnets, generate_random_string from helper import getBuildTimeStampAndVersion, collect_lang_strings, updateSubnets, generate_random_string
from utils.datetime_utils import timeNowDB from utils.datetime_utils import timeNowDB
from app_state import updateState from app_state import updateState
from logger import mylog from logger import mylog
@@ -680,10 +680,11 @@ def importConfigs(pm, db, all_plugins):
ccd('VERSION', new_version , c_d, '_KEEP_', '_KEEP_', '_KEEP_', '_KEEP_', None, "_KEEP_", None, None, True) ccd('VERSION', new_version , c_d, '_KEEP_', '_KEEP_', '_KEEP_', '_KEEP_', None, "_KEEP_", None, None, True)
write_notification(f'[Upgrade]: App upgraded from <code>{prev_version}</code> to \ write_notification(f'[Upgrade]: App upgraded from <code>{prev_version}</code> to \
<code>{new_version}</ code> 🚀 Please clear the cache: \ <code>{new_version}</code> 🚀 Please clear the cache: \
<ol> <li>Click OK below</li> <li>Clear the browser cache (shift + \ <ol> <li>Click OK below</li> \
browser refresh button)</li> <li> Clear app cache with the <i class="fa-solid fa-rotate"></i> \ <li>Clear the browser cache (shift + browser refresh button)</li> \
(reload) button in the header</li><li>Go to Settings and click Save</li> </ol>\ <li> Clear app cache with the <i class="fa-solid fa-rotate"></i> (reload) button in the header</li>\
<li>Go to Settings and click Save</li> </ol>\
Check out new features and what has changed in the \ Check out new features and what has changed in the \
<a href="https://github.com/jokob-sk/NetAlertX/releases" target="_blank">📓 release notes</a>.', <a href="https://github.com/jokob-sk/NetAlertX/releases" target="_blank">📓 release notes</a>.',
'interrupt', 'interrupt',
@@ -804,8 +805,6 @@ def renameSettings(config_file):
str(config_file) + "_temp", str(config_file) str(config_file) + "_temp", str(config_file)
) # Convert config_file to a string ) # Convert config_file to a string
# ensure correct ownership
fixPermissions()
else: else:
mylog( mylog(
"debug", "[Config] No old setting names found in the file. No changes made." "debug", "[Config] No old setting names found in the file. No changes made."

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python #!/usr/bin/env python
# from datetime import datetime # from datetime import datetime
from dateutil import parser from dateutil import parser

View File

@@ -199,7 +199,7 @@ def test_devices_by_status(client, api_token, test_mac):
assert "&#9733" in fav_data["title"] assert "&#9733" in fav_data["title"]
def test_delete_test_devices(client, api_token, test_mac): def test_delete_test_devices(client, api_token):
# Delete by MAC # Delete by MAC
resp = client.delete("/devices", json={"macs": ["AA:BB:CC:*"]}, headers=auth_headers(api_token)) resp = client.delete("/devices", json={"macs": ["AA:BB:CC:*"]}, headers=auth_headers(api_token))

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python3 #!/usr/bin/env python3
""" """
Comprehensive SQL Injection Prevention Tests for NetAlertX Comprehensive SQL Injection Prevention Tests for NetAlertX

View File

@@ -210,7 +210,6 @@ class TestDatabaseParameterSupport(unittest.TestCase):
# This should not cause SQL injection # This should not cause SQL injection
malicious_input = "'; DROP TABLE test_table; --" malicious_input = "'; DROP TABLE test_table; --"
cursor.execute("SELECT * FROM test_table WHERE name = :name", {'name': malicious_input}) cursor.execute("SELECT * FROM test_table WHERE name = :name", {'name': malicious_input})
# results = cursor.fetchall()
# The table should still exist and be queryable # The table should still exist and be queryable
cursor.execute("SELECT COUNT(*) FROM test_table") cursor.execute("SELECT COUNT(*) FROM test_table")

View File

@@ -1,4 +1,4 @@
# !/usr/bin/env python3 #!/usr/bin/env python3
""" """
Pytest-based Mount Diagnostic Tests for NetAlertX Pytest-based Mount Diagnostic Tests for NetAlertX

View File

@@ -19,7 +19,8 @@ from messaging.reporting import get_notifications # noqa: E402 [flake8 lint sup
@pytest.fixture @pytest.fixture
def test_db_path(): def test_db_path():
path = tempfile.mktemp(suffix=".db") with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as tmp:
path = tmp.name
yield path yield path
if os.path.exists(path): if os.path.exists(path):
os.remove(path) os.remove(path)