summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml1
-rw-r--r--poezio/config.py6
-rw-r--r--poezio/connection.py4
-rw-r--r--poezio/core/completions.py4
-rw-r--r--poezio/core/core.py5
-rw-r--r--poezio/libpoezio.pyi6
-rw-r--r--poezio/plugin_manager.py7
-rwxr-xr-xpoezio/theming.py4
-rw-r--r--poezio/xdg.py41
-rw-r--r--src/lib.rs2
-rw-r--r--src/xdg.rs69
11 files changed, 94 insertions, 55 deletions
diff --git a/Cargo.toml b/Cargo.toml
index bd86bf6b..6c28926d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,6 +17,7 @@ ncurses = "5"
lazy_static = "1"
enum-set = "0.0"
clap = { version = "3.2.17", features = ["derive"] }
+directories = "4.0.1"
[lib]
crate-type = ["cdylib"]
diff --git a/poezio/config.py b/poezio/config.py
index 4eb43cad..0a86ac8a 100644
--- a/poezio/config.py
+++ b/poezio/config.py
@@ -19,7 +19,7 @@ from configparser import RawConfigParser, NoOptionError, NoSectionError
from pathlib import Path
from typing import Dict, List, Optional, Union, Tuple, cast, Any
-from poezio import xdg
+from poezio.libpoezio import XDG
from slixmpp import JID, InvalidJID
log = logging.getLogger(__name__) # type: logging.Logger
@@ -603,7 +603,7 @@ def get_image_cache() -> Optional[Path]:
tmp_dir = config.getstr('tmp_image_dir')
if tmp_dir:
return Path(tmp_dir)
- return xdg.CACHE_HOME / 'images'
+ return XDG.cache_dir / 'images'
def check_config():
@@ -656,7 +656,7 @@ def setup_logging(debug_file=''):
"Change the logging config according to the cmdline options and config"
global LOG_DIR
LOG_DIR = config.get('log_dir')
- LOG_DIR = Path(LOG_DIR).expanduser() if LOG_DIR else xdg.DATA_HOME / 'logs'
+ LOG_DIR = Path(LOG_DIR).expanduser() if LOG_DIR else XDG.data_dir / 'logs'
from copy import deepcopy
logging_config = deepcopy(LOGGING_CONFIG)
if config.get('log_errors'):
diff --git a/poezio/connection.py b/poezio/connection.py
index 503d9169..b0c6fb45 100644
--- a/poezio/connection.py
+++ b/poezio/connection.py
@@ -27,7 +27,7 @@ from slixmpp.util import FileSystemCache
from poezio import common
from poezio import fixes
-from poezio import xdg
+from poezio.libpoezio import XDG
from poezio.config import config
@@ -136,7 +136,7 @@ class Connection(slixmpp.ClientXMPP):
'https://poez.io',
'cache':
FileSystemCache(
- str(xdg.CACHE_HOME),
+ str(XDG.cache_dir),
'caps',
encode=str,
decode=lambda x: DiscoInfo(ET.fromstring(x))),
diff --git a/poezio/core/completions.py b/poezio/core/completions.py
index 084910a2..1cb934c0 100644
--- a/poezio/core/completions.py
+++ b/poezio/core/completions.py
@@ -11,7 +11,7 @@ from slixmpp import JID, InvalidJID
from poezio import common
from poezio import tabs
-from poezio import xdg
+from poezio.libpoezio import XDG
from poezio.config import config
from poezio.roster import roster
@@ -82,7 +82,7 @@ class CompletionCore:
""" Completion for /theme"""
themes_dir = config.getstr('themes_dir')
themes_dir = Path(themes_dir).expanduser(
- ) if themes_dir else xdg.DATA_HOME / 'themes'
+ ) if themes_dir else XDG.data_dir / 'themes'
try:
theme_files = [
name.stem for name in themes_dir.iterdir()
diff --git a/poezio/core/core.py b/poezio/core/core.py
index 7690e769..b1b6c8a2 100644
--- a/poezio/core/core.py
+++ b/poezio/core/core.py
@@ -66,7 +66,8 @@ from poezio.size_manager import SizeManager
from poezio.user import User
from poezio.text_buffer import TextBuffer
from poezio.timed_events import DelayedEvent
-from poezio import keyboard, xdg
+from poezio import keyboard
+from poezio.libpoezio import XDG
from poezio.core.completions import CompletionCore
from poezio.core.tabs import Tabs
@@ -154,7 +155,7 @@ class Core:
self.bookmarks = BookmarkList()
self.remote_fifo = None
self.avatar_cache = FileSystemPerJidCache(
- str(xdg.CACHE_HOME), 'avatars', binary=True)
+ str(XDG.cache_dir), 'avatars', binary=True)
# a unique buffer used to store global information
# that are displayed in almost all tabs, in an
# information window.
diff --git a/poezio/libpoezio.pyi b/poezio/libpoezio.pyi
index 1212d2c2..cc5a7311 100644
--- a/poezio/libpoezio.pyi
+++ b/poezio/libpoezio.pyi
@@ -1,4 +1,10 @@
from typing import Any, Dict, List, Tuple
+from pathlib import Path
def to_curses_attr(fg: int, bg: int, attrs: str) -> int: ...
def run_cmdline_args(argv: List[str]) -> Tuple[Dict[Any, Any], bool]: ...
+
+class XDG:
+ cache_dir: Path
+ config_dir: Path
+ data_dir: Path
diff --git a/poezio/plugin_manager.py b/poezio/plugin_manager.py
index 17673a9e..ba3f94a1 100644
--- a/poezio/plugin_manager.py
+++ b/poezio/plugin_manager.py
@@ -13,7 +13,8 @@ from pathlib import Path
from os import path
import pkg_resources
-from poezio import tabs, xdg
+from poezio import tabs
+from poezio.libpoezio import XDG
from poezio.core.structs import Command, Completion
from poezio.plugin import PluginAPI
from poezio.config import config
@@ -395,7 +396,7 @@ class PluginManager:
"""
plugins_conf_dir = config.getstr('plugins_conf_dir')
self.plugins_conf_dir = Path(plugins_conf_dir).expanduser(
- ) if plugins_conf_dir else xdg.CONFIG_HOME / 'plugins'
+ ) if plugins_conf_dir else XDG.config_dir / 'plugins'
self.check_create_plugins_conf_dir()
def check_create_plugins_conf_dir(self):
@@ -420,7 +421,7 @@ class PluginManager:
"""
plugins_dir = config.getstr('plugins_dir')
self.plugins_dir = Path(plugins_dir).expanduser(
- ) if plugins_dir else xdg.DATA_HOME / 'plugins'
+ ) if plugins_dir else XDG.data_dir / 'plugins'
self.check_create_plugins_dir()
def check_create_plugins_dir(self):
diff --git a/poezio/theming.py b/poezio/theming.py
index 446455e0..319440ec 100755
--- a/poezio/theming.py
+++ b/poezio/theming.py
@@ -77,7 +77,7 @@ from typing import Dict, List, Union, Tuple, Optional, cast
from pathlib import Path
from os import path
from datetime import datetime
-from poezio import colors, xdg, libpoezio
+from poezio import colors, libpoezio
from importlib import machinery
finder = machinery.PathFinder()
@@ -450,7 +450,7 @@ def update_themes_dir(option: Optional[str] = None,
# import from the user-defined prefs
themes_dir_str = config.getstr('themes_dir')
themes_dir = Path(themes_dir_str).expanduser(
- ) if themes_dir_str else xdg.DATA_HOME / 'themes'
+ ) if themes_dir_str else libpoezio.XDG.data_dir / 'themes'
try:
themes_dir.mkdir(parents=True, exist_ok=True)
except OSError:
diff --git a/poezio/xdg.py b/poezio/xdg.py
deleted file mode 100644
index d7ff9d73..00000000
--- a/poezio/xdg.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2018 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
-#
-# This file is part of Poezio.
-#
-# Poezio is free software: you can redistribute it and/or modify
-# it under the terms of the GPL-3.0+ license. See the COPYING file.
-"""
-Implements the XDG base directory specification.
-
-https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
-"""
-
-from pathlib import Path
-from os import environ
-from typing import Dict
-
-# $HOME has already been checked to not be None in test_env().
-DEFAULT_PATHS: Dict[str, Path] = {
- 'XDG_CONFIG_HOME': Path.home() / '.config',
- 'XDG_DATA_HOME': Path.home() / '.local' / 'share',
- 'XDG_CACHE_HOME': Path.home() / '.cache',
-}
-
-
-def _get_directory(variable: str) -> Path:
- """
- returns the default configuration directory path
- """
- if variable not in DEFAULT_PATHS:
- raise ValueError('Invalid XDG basedir variable')
- xdg = environ.get(variable)
- if xdg is not None:
- xdg_path = Path(xdg)
- if xdg_path.is_absolute():
- return xdg_path / 'poezio'
- return DEFAULT_PATHS[variable] / 'poezio'
-
-
-CONFIG_HOME = _get_directory('XDG_CONFIG_HOME')
-DATA_HOME = _get_directory('XDG_DATA_HOME')
-CACHE_HOME = _get_directory('XDG_CACHE_HOME')
diff --git a/src/lib.rs b/src/lib.rs
index 96cefa51..72007500 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -4,6 +4,7 @@ mod args;
mod error;
mod logger;
mod theming;
+mod xdg;
use crate::args::parse_args;
use crate::logger::LogItem;
@@ -27,6 +28,7 @@ fn libpoezio(py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(to_curses_attr, m)?)?;
m.add_function(wrap_pyfunction!(parse_logs, m)?)?;
m.add_function(wrap_pyfunction!(run_cmdline_args, m)?)?;
+ m.add("XDG", xdg::PyProject::new(xdg::PROJECT.clone()))?;
Ok(())
}
diff --git a/src/xdg.rs b/src/xdg.rs
new file mode 100644
index 00000000..d5c9d41d
--- /dev/null
+++ b/src/xdg.rs
@@ -0,0 +1,69 @@
+// Copyright (C) 2022 Maxime “pep” Buquet <pep@bouah.net>
+//
+// This program is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation, either version 3 of the License, or (at your
+// option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+use std::cell::LazyCell;
+
+use directories::ProjectDirs;
+use pyo3::{
+ marker::Python,
+ prelude::{pyclass, pymethods, PyObject, PyResult},
+ IntoPy,
+};
+
+/// Project qualifier
+pub const QUALIFIER: &'static str = "io";
+/// Project organization
+pub const ORGANIZATION: &'static str = "poez";
+/// Project appname
+pub const APPNAME: &'static str = "Poezio";
+
+/// Project directories
+pub const PROJECT: LazyCell<ProjectDirs> = LazyCell::new(|| {
+ ProjectDirs::from(QUALIFIER, ORGANIZATION, APPNAME).expect("HOME dir should be available.")
+});
+
+#[pyclass(name = "XDG")]
+pub struct PyProject(ProjectDirs);
+
+fn get_path(py: Python<'_>) -> PyResult<PyObject> {
+ // TODO: Stop importing pathlib all the time
+ let pathlib = py.import("pathlib")?;
+ let path = pathlib.getattr("Path")?;
+ Ok(path.into_py(py))
+}
+
+impl PyProject {
+ pub fn new(dirs: ProjectDirs) -> Self {
+ PyProject(dirs)
+ }
+}
+
+#[pymethods]
+impl PyProject {
+ #[getter]
+ pub fn cache_dir(&self, py: Python<'_>) -> PyResult<PyObject> {
+ Ok(get_path(py)?.call1(py, (self.0.cache_dir(),))?)
+ }
+
+ #[getter]
+ pub fn config_dir(&self, py: Python<'_>) -> PyResult<PyObject> {
+ Ok(get_path(py)?.call1(py, (self.0.config_dir(),))?)
+ }
+
+ #[getter]
+ pub fn data_dir(&self, py: Python<'_>) -> PyResult<PyObject> {
+ Ok(get_path(py)?.call1(py, (self.0.data_dir(),))?)
+ }
+}