From 38435f7fe91b0e356ac72693c507f7b2030facae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20M=C3=BCller?= Date: Fri, 17 May 2024 12:24:07 +0200 Subject: [PATCH] GRC: GR conf&persistent paths instead of ~/.gnuradio || ~/.grc_gnuradio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcus Müller --- converter/main.py | 5 ++- core/Config.py | 4 +- core/Constants.py | 9 ++-- core/generator/flow_graph.py.mako | 2 +- core/platform.py | 7 ++- grc.conf.in | 2 +- gui/Config.py | 3 +- gui_qt/Config.py | 3 +- gui_qt/components/example_browser.py | 7 ++- gui_qt/properties.py | 1 + main.py | 66 +++++++++++++++++++++++++++- 11 files changed, 95 insertions(+), 14 deletions(-) diff --git a/converter/main.py b/converter/main.py index 5eb80a5..2467023 100644 --- a/converter/main.py +++ b/converter/main.py @@ -10,6 +10,8 @@ import json import logging import os +from ..main import get_state_directory +from ..core import Constants from . import block_tree, block path = os.path @@ -18,6 +20,7 @@ logger = logging.getLogger(__name__) excludes = [ 'qtgui_', '.grc_gnuradio/', + os.path.join(get_state_directory(), Constants.GRC_SUBDIR), 'blks2', 'wxgui', 'epy_block.xml', @@ -31,7 +34,7 @@ excludes = [ class Converter(object): - def __init__(self, search_path, output_dir='~/.cache/grc_gnuradio'): + def __init__(self, search_path: str, output_dir: str = os.path.join(get_state_directory(), Constants.GRC_SUBDIR)): self.search_path = search_path self.output_dir = os.path.expanduser(output_dir) logger.info("Saving converted files to {}".format(self.output_dir)) diff --git a/core/Config.py b/core/Config.py index 1d823d7..b7d52e5 100644 --- a/core/Config.py +++ b/core/Config.py @@ -9,6 +9,7 @@ import os from os.path import expanduser, normpath, expandvars, exists from collections import OrderedDict +from ..main import get_state_directory, get_config_file_path from . import Constants @@ -17,8 +18,7 @@ class Config(object): license = __doc__.strip() website = 'https://www.gnuradio.org/' - hier_block_lib_dir = os.environ.get( - 'GRC_HIER_PATH', Constants.DEFAULT_HIER_BLOCK_LIB_DIR) + hier_block_lib_dir = os.environ.get('GRC_HIER_PATH', get_state_directory()) def __init__(self, version, version_parts=None, name=None, prefs=None): self._gr_prefs = prefs if prefs else DummyPrefs() diff --git a/core/Constants.py b/core/Constants.py index 1aac44d..2fdabd7 100644 --- a/core/Constants.py +++ b/core/Constants.py @@ -19,11 +19,14 @@ import numpy DATA_DIR = os.path.dirname(__file__) BLOCK_DTD = os.path.join(DATA_DIR, 'block.dtd') DEFAULT_FLOW_GRAPH = os.path.join(DATA_DIR, 'default_flow_graph.grc') -DEFAULT_HIER_BLOCK_LIB_DIR = os.path.expanduser('~/.grc_gnuradio') DEFAULT_FLOW_GRAPH_ID = 'default' -CACHE_FILE = os.path.expanduser('~/.cache/grc_gnuradio/cache_v2.json') -EXAMPLE_CACHE_FILE = os.path.expanduser('~/.cache/grc_gnuradio/example_cache.json') +PROJECT_DEFAULT_DIR = 'gnuradio' +GRC_SUBDIR = 'grc' +CACHE_FILE_NAME = 'cache_v2.json' +FALLBACK_CACHE_FILE = os.path.expanduser(f'~/.cache/{PROJECT_DEFAULT_DIR}/{GRC_SUBDIR}/{CACHE_FILE_NAME}') +EXAMPLE_CACHE_FILE_NAME = 'example_cache.json' +FALLBACK_EXAMPLE_CACHE_FILE = os.path.expanduser(f'~/.cache/{PROJECT_DEFAULT_DIR}/{GRC_SUBDIR}/{EXAMPLE_CACHE_FILE_NAME}') BLOCK_DESCRIPTION_FILE_FORMAT_VERSION = 1 # File format versions: diff --git a/core/generator/flow_graph.py.mako b/core/generator/flow_graph.py.mako index 07bae7e..64c1661 100644 --- a/core/generator/flow_graph.py.mako +++ b/core/generator/flow_graph.py.mako @@ -95,7 +95,7 @@ class ${class_name}(gr.top_block, Qt.QWidget): self.top_grid_layout = Qt.QGridLayout() self.top_layout.addLayout(self.top_grid_layout) - self.settings = Qt.QSettings("GNU Radio", "${class_name}") + self.settings = Qt.QSettings("gnuradio/flowgraphs", "${class_name}") try: geometry = self.settings.value("geometry") diff --git a/core/platform.py b/core/platform.py index 1d88e25..4340635 100644 --- a/core/platform.py +++ b/core/platform.py @@ -133,7 +133,12 @@ class Platform(Element): self.cpp_connection_templates.clear() self._block_categories.clear() - with Cache(Constants.CACHE_FILE, version=self.config.version) as cache: + try: + from gnuradio.gr import paths + cache_file = os.path.join(paths.cache(), Constants.GRC_SUBDIR, Constants.CACHE_FILE_NAME) + except ImportError: + cache_file = Constants.FALLBACK_CACHE_FILE + with Cache(cache_file, version=self.config.version) as cache: for file_path in self._iter_files_in_block_path(path): if file_path.endswith('.block.yml'): diff --git a/grc.conf.in b/grc.conf.in index 9e5bf42..24a93a2 100644 --- a/grc.conf.in +++ b/grc.conf.in @@ -1,6 +1,6 @@ # This file contains system wide configuration data for GNU Radio. # You may override any setting on a per-user basis by editing -# ~/.gnuradio/config.conf +# ~/.config/gnuradio/grc.conf [grc] global_blocks_path = @blocksdir@ diff --git a/gui/Config.py b/gui/Config.py index 5aab9d7..91b3a33 100644 --- a/gui/Config.py +++ b/gui/Config.py @@ -11,6 +11,7 @@ import sys import os import configparser +from ..main import get_config_file_path from ..core.Config import Config as CoreConfig from . import Constants @@ -28,7 +29,7 @@ class Config(CoreConfig): name = 'GNU Radio Companion' gui_prefs_file = os.environ.get( - 'GRC_PREFS_PATH', os.path.expanduser('~/.gnuradio/grc.conf')) + 'GRC_PREFS_PATH', os.path.join(get_config_file_path(), '/grc.conf')) def __init__(self, install_prefix, *args, **kwargs): CoreConfig.__init__(self, *args, **kwargs) diff --git a/gui_qt/Config.py b/gui_qt/Config.py index 28b7357..ec5fffc 100644 --- a/gui_qt/Config.py +++ b/gui_qt/Config.py @@ -3,6 +3,7 @@ from os.path import expanduser, normpath, expandvars, exists from collections import OrderedDict from ..core.Config import Config as CoreConfig +from ..main import get_config_file_path from qtpy import QtCore @@ -11,7 +12,7 @@ class Config(CoreConfig): name = 'GNU Radio Companion' gui_prefs_file = os.environ.get( - 'GRC_QT_PREFS_PATH', os.path.expanduser('~/.gnuradio/grc_qt.conf')) + 'GRC_QT_PREFS_PATH', os.path.join(get_config_file_path(), 'grc_qt.conf')) def __init__(self, install_prefix, *args, **kwargs): CoreConfig.__init__(self, *args, **kwargs) diff --git a/gui_qt/components/example_browser.py b/gui_qt/components/example_browser.py index 46ddd9a..a6b4bd0 100644 --- a/gui_qt/components/example_browser.py +++ b/gui_qt/components/example_browser.py @@ -250,7 +250,12 @@ class ExampleBrowser(QWidget, base.Component): def find_examples(self, progress_callback, ext="grc"): """Iterate through the example flowgraph directories and parse them.""" examples_dict = {} - with Cache(Constants.EXAMPLE_CACHE_FILE, log=False) as cache: + try: + from gnuradio.gr import paths + cache_file = os.path.join(paths.cache(), Constants.GRC_SUBDIR, Constants.EXAMPLE_CACHE_FILE_NAME) + except ImportError: + cache_file = Constants.FALLBACK_EXAMPLE_CACHE_FILE + with Cache(cache_file, log=False) as cache: for entry in self.platform.config.example_paths: if entry == '': log.info("Empty example path!") diff --git a/gui_qt/properties.py b/gui_qt/properties.py index 6608b5a..2315dea 100644 --- a/gui_qt/properties.py +++ b/gui_qt/properties.py @@ -53,6 +53,7 @@ class Paths(object): TOP_BLOCK_FILE_MODE = HIER_BLOCK_FILE_MODE | stat.S_IXUSR | stat.S_IXGRP # Setup paths + # FIXME: this should use ..main.get_config_directory() and get_state_directory(), probably. ''' HIER_BLOCKS_LIB_DIR = os.environ.get('GRC_HIER_PATH', os.path.expanduser('~/.grc_gnuradio')) diff --git a/main.py b/main.py index 2f9cf54..76932c3 100755 --- a/main.py +++ b/main.py @@ -187,9 +187,71 @@ def run_qt(args, log): sys.exit(app.run()) +def get_config_file_path(config_file: str = "grc.conf") -> str: + oldpath = os.path.join(os.path.expanduser("~/.gnuradio"), config_file) + try: + from gnuradio.gr import paths + newpath = os.path.join(paths.userconf(), config_file) + if os.path.exists(newpath): + return newpath + if os.path.exists(oldpath): + log.warn(f"Found specification for config path '{newpath}', but file does not exist. " + + f"Old default config file path '{oldpath}' exists; using that. " + + "Please consider moving configuration to new location.") + return oldpath + # Default to the correct path if both are configured. + # neither old, nor new path exist: create new path, return that + os.makedirs(newpath, exist_ok=True) + return newpath + except ImportError: + log.warn("Could not retrieve GNU Radio configuration directory from GNU Radio. Trying defaults.") + xdgconf = os.getenv("XDG_CONFIG_HOME", os.path.expanduser("~/.config")) + xdgcand = os.path.join(xdgconf, config_file) + if os.path.exists(xdgcand): + return xdgcand + if os.path.exists(oldpath): + log.warn(f"Using legacy config path '{oldpath}'. Please consider moving configuration " + + f"files to '{newpath}'.") + return oldpath + # neither old, nor new path exist: create new path, return that + os.makedirs(xdgcand, exist_ok=True) + return xdgcand + + +def get_state_directory() -> str: + oldpath = os.path.expanduser("~/.gnuradio") + try: + from gnuradio.gr import paths + newpath = paths.persistent() + if os.path.exists(newpath): + return newpath + if os.path.exists(oldpath): + log.warn(f"Found specification for persistent state path '{newpath}', but file does not exist. " + + f"Old default persistent state path '{oldpath}' exists; using that. " + + "Please consider moving state to new location.") + return oldpath + # Default to the correct path if both are configured. + # neither old, nor new path exist: create new path, return that + os.makedirs(newpath, exist_ok=True) + return newpath + except (ImportError, NameError): + log.warn("Could not retrieve GNU Radio persistent state directory from GNU Radio. Trying defaults.") + xdgstate = os.getenv("XDG_STATE_HOME", os.path.expanduser("~/.local/state")) + xdgcand = os.path.join(xdgstate, "gnuradio") + if os.path.exists(xdgcand): + return xdgcand + if os.path.exists(oldpath): + log.warn(f"Using legacy state path '{oldpath}'. Please consider moving state " + + f"files to '{newpath}'.") + return oldpath + # neither old, nor new path exist: create new path, return that + os.makedirs(xdgcand, exist_ok=True) + return xdgcand + + def main(): grc_version_from_config = "" - grc_qt_config_file = os.path.expanduser('~/.gnuradio/grc_qt.conf') + grc_qt_config_file = get_config_file_path('grc_qt.conf') if os.path.isfile(grc_qt_config_file): try: from qtpy.QtCore import QSettings @@ -227,7 +289,7 @@ def main(): log.info("Starting GNU Radio Companion {} (Python {})".format(gr.version(), py_version)) # File logging - log_file = os.path.expanduser('~') + "/.gnuradio/grc.log" + log_file = os.path.join(get_state_directory(), "grc.log") try: fileHandler = logging.FileHandler(log_file) file_msg_format = '%(asctime)s [%(levelname)s] %(message)s'