From 8fe3f75bd7dc4022c3cd4fcf4c6f7a1832ec6364 Mon Sep 17 00:00:00 2001 From: Ales Erjavec Date: Thu, 26 Mar 2020 16:05:56 +0100 Subject: [PATCH 1/2] environ: Read config from a file --- Orange/misc/environ.py | 119 ++++++++++++++++++++++++++++++++++------- 1 file changed, 100 insertions(+), 19 deletions(-) diff --git a/Orange/misc/environ.py b/Orange/misc/environ.py index 1d1e7000aa0..f2522052843 100644 --- a/Orange/misc/environ.py +++ b/Orange/misc/environ.py @@ -1,33 +1,97 @@ """ -Retrive basic library/application data/cache locations. +environ +======= -The basic FS layout for Orange data files is +This module contains some basic configuration options for Orange +(for now mostly changing directories where settings and data are saved). -$DATA_HOME/Orange/$VERSION/ - widgets/ - canvas/ +How it works +------------ + +The configuration is read from '{sys.prefix}/etc/orangerc.cfg' +which is a standard `configparser` file. + +orangerc.cfg +------------ + +.. code-block:: cfg + + # An exemple orangerc.cfg file + # ---------------------------- + # + # A number of variables are predefined: + # - prefix: `sys.prefix` + # - name: The application/library name ('Orange') + # - version: The application/library name ('Orange.__version__') + # - version.major, version.minor, version.micro: The version components + + [paths] + # The base path where persistent application data can be stored + # (here we define a prefix relative path) + data_dir_base = %(prefix)s/share + # the base path where application data can be stored + cache_dir = %(prefix)s/cache/%(name)s/%(version)s + + # The following is only applicable for a running orange canvas application. + + # The base dir where widgets store their settings + widget_settings_dir = %(prefix)s/config/%(name)s/widgets + # The base dir where canvas stores its settings + canvas_settings_dir = %(prefix)s/config/%(name)s/canvas -where DATA_HOME is a platform dependent application directory -(:ref:`data_dir_base`) and VERSION is Orange.__version__ string. """ import os import sys import warnings +import sysconfig +import configparser + +from typing import Optional import Orange -def data_dir_base(): +def _get_parsed_config(): + version = Orange.__version__.split(".") + data = sysconfig.get_path("data") + vars = { + "home": os.path.expanduser("~/"), + "prefix": sys.prefix, + "data": sysconfig.get_path("data"), + "name": "Orange", + "version": Orange.__version__, + "version.major": version[0], + "version.minor": version[1], + "version.micro": version[2], + } + conf = configparser.ConfigParser(vars) + conf.read([ + os.path.join(data, "etc/orangerc.conf"), + ], encoding="utf-8") + if not conf.has_section("paths"): + conf.add_section("paths") + return conf + + +def get_path(name: str, default: Optional[str] = None) -> Optional[str]: """ - Return the platform dependent application directory. - - This is usually - - - on windows: "%USERPROFILE%\\AppData\\Local\\" - - on OSX: "~/Library/Application Support/" - - other: "~/.local/share/ + Get configured path + + Parameters + ---------- + name: str + The named config path value + default: Optional[str] + The default to return if `name` is not defined """ + cfg = _get_parsed_config() + try: + return cfg.get('paths', name) + except (configparser.NoOptionError, configparser.NoSectionError): + return default + +def _default_data_dir_base(): if sys.platform == "darwin": base = os.path.expanduser("~/Library/Application Support") elif sys.platform == "win32": @@ -39,6 +103,19 @@ def data_dir_base(): return base +def data_dir_base(): + """ + Return the platform dependent application directory. + + This is usually + + - on windows: "%USERPROFILE%\\AppData\\Local\\" + - on OSX: "~/Library/Application Support/" + - other: "~/.local/share/ + """ + return get_path('data_dir_base', _default_data_dir_base()) + + def data_dir(versioned=True): """ Return the platform dependent Orange data directory. @@ -67,10 +144,7 @@ def widget_settings_dir(versioned=True): return orangewidget.settings.widget_settings_dir(versioned) -def cache_dir(*args): - """ - Return the platform dependent Orange cache directory. - """ +def _default_cache_dir(): if sys.platform == "darwin": base = os.path.expanduser("~/Library/Caches") elif sys.platform == "win32": @@ -87,3 +161,10 @@ def cache_dir(*args): return os.path.join(base, "Cache") else: return base + + +def cache_dir(*args): + """ + Return the platform dependent Orange cache directory. + """ + return get_path("cache_dir", _default_cache_dir()) From 7422079baf2cd9d8ea0f910bb5dcc8317596c329 Mon Sep 17 00:00:00 2001 From: Ales Erjavec Date: Thu, 26 Mar 2020 16:06:50 +0100 Subject: [PATCH 2/2] config: Apply configured paths if defined --- Orange/canvas/config.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/Orange/canvas/config.py b/Orange/canvas/config.py index f4970639b48..f7117e28e0b 100644 --- a/Orange/canvas/config.py +++ b/Orange/canvas/config.py @@ -16,13 +16,15 @@ import requests from AnyQt.QtGui import QPainter, QFont, QFontMetrics, QColor, QPixmap, QIcon -from AnyQt.QtCore import Qt, QPoint, QRect +from AnyQt.QtCore import Qt, QPoint, QRect, QSettings from orangecanvas import config as occonfig from orangecanvas.utils.settings import config_slot from orangewidget.workflow import config +from orangewidget.settings import set_widget_settings_dir_components import Orange +from Orange.misc import environ # generated from biolab/orange3-addons repository OFFICIAL_ADDON_LIST = "https://orange.biolab.si/addons/list" @@ -68,6 +70,21 @@ class Config(config.Config): def init(self): super().init() + widget_settings_dir_cfg = environ.get_path("widget_settings_dir", "") + if widget_settings_dir_cfg: + # widget_settings_dir is configured via config file + set_widget_settings_dir_components( + widget_settings_dir_cfg, self.ApplicationVersion + ) + + canvas_settings_dir_cfg = environ.get_path("canvas_settings_dir", "") + if canvas_settings_dir_cfg: + # canvas_settings_dir is configured via config file + QSettings.setPath( + QSettings.IniFormat, QSettings.UserScope, + canvas_settings_dir_cfg + ) + for t in spec: occonfig.register_setting(*t) @@ -197,7 +214,6 @@ def data_dir(): Return the Orange application data directory. If the directory path does not yet exists then create it. """ - from Orange.misc import environ path = os.path.join(environ.data_dir(), "canvas") try: os.makedirs(path, exist_ok=True) @@ -211,7 +227,6 @@ def cache_dir(): Return the Orange application cache directory. If the directory path does not yet exists then create it. """ - from Orange.misc import environ path = os.path.join(environ.cache_dir(), "canvas") try: os.makedirs(path, exist_ok=True) @@ -230,6 +245,8 @@ def log_dir(): else: logdir = data_dir() + logdir = environ.get_path("log_dir", logdir) + try: os.makedirs(logdir, exist_ok=True) except OSError: