uaf.git

uaf

~
git clone https://github.com/debuman/uaf.git

ap_scanner/config.py (2623B)

      1 """Configuration file support using configparser.
      2 
      3 Default path: ~/.config/ap-scanner/config.ini
      4 CLI arguments always take precedence over config file values.
      5 """
      6 
      7 import configparser
      8 from pathlib import Path
      9 
     10 DEFAULT_CONFIG_PATH = Path.home() / ".config" / "ap-scanner" / "config.ini"
     11 
     12 # Defaults that match CLI defaults
     13 DEFAULTS = {
     14     "interface": "",
     15     "channels": "",
     16     "band": "all",
     17     "sort": "rssi",
     18     "no_color": "false",
     19     "verbose": "false",
     20     "log_file": "",
     21     "write": "",
     22     "dwell": "",
     23 }
     24 
     25 
     26 def load_config(config_path: str | None = None) -> dict[str, str]:
     27     """Load configuration from an INI file.
     28 
     29     Returns a dict of setting name -> string value.
     30     Missing keys are filled with defaults.
     31     """
     32     path = Path(config_path) if config_path else DEFAULT_CONFIG_PATH
     33     result = dict(DEFAULTS)
     34 
     35     if not path.is_file():
     36         return result
     37 
     38     parser = configparser.ConfigParser()
     39     parser.read(path, encoding="utf-8")
     40 
     41     if parser.has_section("scanner"):
     42         for key in DEFAULTS:
     43             if parser.has_option("scanner", key):
     44                 result[key] = parser.get("scanner", key)
     45 
     46     return result
     47 
     48 
     49 def apply_config_to_args(args, config: dict[str, str]) -> None:
     50     """Apply config file values to argparse namespace where CLI didn't override.
     51 
     52     CLI arguments (non-default values) always take precedence.
     53     """
     54     # interface: CLI default is None
     55     if args.interface is None and config["interface"]:
     56         args.interface = config["interface"]
     57 
     58     # channels: CLI default is None
     59     if args.channels is None and config["channels"]:
     60         args.channels = config["channels"]
     61 
     62     # band: CLI default is "all"
     63     if args.band == "all" and config["band"] != "all":
     64         args.band = config["band"]
     65 
     66     # sort: CLI default is "rssi"
     67     if args.sort == "rssi" and config["sort"] != "rssi":
     68         args.sort = config["sort"]
     69 
     70     # no_color: CLI default is False
     71     if not args.no_color and config["no_color"].lower() == "true":
     72         args.no_color = True
     73 
     74     # verbose: CLI default is False
     75     if not args.verbose and config["verbose"].lower() == "true":
     76         args.verbose = True
     77 
     78     # log_file: CLI default is None
     79     if args.log_file is None and config["log_file"]:
     80         args.log_file = config["log_file"]
     81 
     82     # write: CLI default is None
     83     if args.write is None and config["write"]:
     84         args.write = config["write"]
     85 
     86     # dwell: CLI default is None
     87     if getattr(args, "dwell", None) is None and config.get("dwell"):
     88         try:
     89             args.dwell = float(config["dwell"])
     90         except ValueError:
     91             pass