roezio: migrate poezio/xdg.py

Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
This commit is contained in:
Maxime “pep” Buquet 2022-08-21 22:54:52 +02:00
parent 5fdcb95e8a
commit 5dcccad90b
11 changed files with 94 additions and 55 deletions

View file

@ -17,6 +17,7 @@ ncurses = "5"
lazy_static = "1" lazy_static = "1"
enum-set = "0.0" enum-set = "0.0"
clap = { version = "3.2.17", features = ["derive"] } clap = { version = "3.2.17", features = ["derive"] }
directories = "4.0.1"
[lib] [lib]
crate-type = ["cdylib"] crate-type = ["cdylib"]

View file

@ -19,7 +19,7 @@ from configparser import RawConfigParser, NoOptionError, NoSectionError
from pathlib import Path from pathlib import Path
from typing import Dict, List, Optional, Union, Tuple, cast, Any from typing import Dict, List, Optional, Union, Tuple, cast, Any
from poezio import xdg from poezio.libpoezio import XDG
from slixmpp import JID, InvalidJID from slixmpp import JID, InvalidJID
log = logging.getLogger(__name__) # type: logging.Logger log = logging.getLogger(__name__) # type: logging.Logger
@ -603,7 +603,7 @@ def get_image_cache() -> Optional[Path]:
tmp_dir = config.getstr('tmp_image_dir') tmp_dir = config.getstr('tmp_image_dir')
if tmp_dir: if tmp_dir:
return Path(tmp_dir) return Path(tmp_dir)
return xdg.CACHE_HOME / 'images' return XDG.cache_dir / 'images'
def check_config(): def check_config():
@ -656,7 +656,7 @@ def setup_logging(debug_file=''):
"Change the logging config according to the cmdline options and config" "Change the logging config according to the cmdline options and config"
global LOG_DIR global LOG_DIR
LOG_DIR = config.get('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 from copy import deepcopy
logging_config = deepcopy(LOGGING_CONFIG) logging_config = deepcopy(LOGGING_CONFIG)
if config.get('log_errors'): if config.get('log_errors'):

View file

@ -27,7 +27,7 @@ from slixmpp.util import FileSystemCache
from poezio import common from poezio import common
from poezio import fixes from poezio import fixes
from poezio import xdg from poezio.libpoezio import XDG
from poezio.config import config from poezio.config import config
@ -136,7 +136,7 @@ class Connection(slixmpp.ClientXMPP):
'https://poez.io', 'https://poez.io',
'cache': 'cache':
FileSystemCache( FileSystemCache(
str(xdg.CACHE_HOME), str(XDG.cache_dir),
'caps', 'caps',
encode=str, encode=str,
decode=lambda x: DiscoInfo(ET.fromstring(x))), decode=lambda x: DiscoInfo(ET.fromstring(x))),

View file

@ -11,7 +11,7 @@ from slixmpp import JID, InvalidJID
from poezio import common from poezio import common
from poezio import tabs from poezio import tabs
from poezio import xdg from poezio.libpoezio import XDG
from poezio.config import config from poezio.config import config
from poezio.roster import roster from poezio.roster import roster
@ -82,7 +82,7 @@ class CompletionCore:
""" Completion for /theme""" """ Completion for /theme"""
themes_dir = config.getstr('themes_dir') themes_dir = config.getstr('themes_dir')
themes_dir = Path(themes_dir).expanduser( themes_dir = Path(themes_dir).expanduser(
) if themes_dir else xdg.DATA_HOME / 'themes' ) if themes_dir else XDG.data_dir / 'themes'
try: try:
theme_files = [ theme_files = [
name.stem for name in themes_dir.iterdir() name.stem for name in themes_dir.iterdir()

View file

@ -66,7 +66,8 @@ from poezio.size_manager import SizeManager
from poezio.user import User from poezio.user import User
from poezio.text_buffer import TextBuffer from poezio.text_buffer import TextBuffer
from poezio.timed_events import DelayedEvent 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.completions import CompletionCore
from poezio.core.tabs import Tabs from poezio.core.tabs import Tabs
@ -154,7 +155,7 @@ class Core:
self.bookmarks = BookmarkList() self.bookmarks = BookmarkList()
self.remote_fifo = None self.remote_fifo = None
self.avatar_cache = FileSystemPerJidCache( 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 # a unique buffer used to store global information
# that are displayed in almost all tabs, in an # that are displayed in almost all tabs, in an
# information window. # information window.

View file

@ -1,4 +1,10 @@
from typing import Any, Dict, List, Tuple from typing import Any, Dict, List, Tuple
from pathlib import Path
def to_curses_attr(fg: int, bg: int, attrs: str) -> int: ... def to_curses_attr(fg: int, bg: int, attrs: str) -> int: ...
def run_cmdline_args(argv: List[str]) -> Tuple[Dict[Any, Any], bool]: ... def run_cmdline_args(argv: List[str]) -> Tuple[Dict[Any, Any], bool]: ...
class XDG:
cache_dir: Path
config_dir: Path
data_dir: Path

View file

@ -13,7 +13,8 @@ from pathlib import Path
from os import path from os import path
import pkg_resources 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.core.structs import Command, Completion
from poezio.plugin import PluginAPI from poezio.plugin import PluginAPI
from poezio.config import config from poezio.config import config
@ -395,7 +396,7 @@ class PluginManager:
""" """
plugins_conf_dir = config.getstr('plugins_conf_dir') plugins_conf_dir = config.getstr('plugins_conf_dir')
self.plugins_conf_dir = Path(plugins_conf_dir).expanduser( 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() self.check_create_plugins_conf_dir()
def check_create_plugins_conf_dir(self): def check_create_plugins_conf_dir(self):
@ -420,7 +421,7 @@ class PluginManager:
""" """
plugins_dir = config.getstr('plugins_dir') plugins_dir = config.getstr('plugins_dir')
self.plugins_dir = Path(plugins_dir).expanduser( 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() self.check_create_plugins_dir()
def check_create_plugins_dir(self): def check_create_plugins_dir(self):

View file

@ -77,7 +77,7 @@ from typing import Dict, List, Union, Tuple, Optional, cast
from pathlib import Path from pathlib import Path
from os import path from os import path
from datetime import datetime from datetime import datetime
from poezio import colors, xdg, libpoezio from poezio import colors, libpoezio
from importlib import machinery from importlib import machinery
finder = machinery.PathFinder() finder = machinery.PathFinder()
@ -450,7 +450,7 @@ def update_themes_dir(option: Optional[str] = None,
# import from the user-defined prefs # import from the user-defined prefs
themes_dir_str = config.getstr('themes_dir') themes_dir_str = config.getstr('themes_dir')
themes_dir = Path(themes_dir_str).expanduser( 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: try:
themes_dir.mkdir(parents=True, exist_ok=True) themes_dir.mkdir(parents=True, exist_ok=True)
except OSError: except OSError:

View file

@ -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')

View file

@ -4,6 +4,7 @@ mod args;
mod error; mod error;
mod logger; mod logger;
mod theming; mod theming;
mod xdg;
use crate::args::parse_args; use crate::args::parse_args;
use crate::logger::LogItem; 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!(to_curses_attr, m)?)?;
m.add_function(wrap_pyfunction!(parse_logs, m)?)?; m.add_function(wrap_pyfunction!(parse_logs, m)?)?;
m.add_function(wrap_pyfunction!(run_cmdline_args, m)?)?; m.add_function(wrap_pyfunction!(run_cmdline_args, m)?)?;
m.add("XDG", xdg::PyProject::new(xdg::PROJECT.clone()))?;
Ok(()) Ok(())
} }

69
src/xdg.rs Normal file
View file

@ -0,0 +1,69 @@
// Copyright (C) 2018-2099 The crate authors.
//
// 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(),))?)
}
}