Skip to content

Commit

Permalink
Provide functions rather than variables
Browse files Browse the repository at this point in the history
Refactoring the API to provide functions rather than variables means
that xdg will now respect changes to environment variables made after it
is imported. This additionally makes testing easier.

The previous variable based API is maintained for backward
compatibility, but is no longer documented.
  • Loading branch information
srstevenson committed Oct 29, 2020
1 parent d87bd40 commit f7ab87c
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 211 deletions.
42 changes: 25 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# xdg

`xdg` is a tiny Python module which provides the variables defined by the [XDG
Base Directory Specification][spec], to save you from duplicating the same
snippet of logic in every Python utility you write that deals with user cache,
configuration, or data files. It has no external dependencies.
`xdg` is a Python module which provides functions to return paths to the
directories defined by the [XDG Base Directory Specification][spec], to save you
from duplicating the same snippet of logic in every Python utility you write
that deals with user cache, configuration, or data files. It has no external
dependencies.

## Installation

Expand All @@ -21,23 +22,30 @@ Alternatively, since `xdg` is only a single file you may prefer to just copy
## Usage

```python
from xdg import (XDG_CACHE_HOME, XDG_CONFIG_DIRS, XDG_CONFIG_HOME,
XDG_DATA_DIRS, XDG_DATA_HOME, XDG_RUNTIME_DIR)
from xdg import (
xdg_cache_home,
xdg_config_dirs,
xdg_config_home,
xdg_data_dirs,
xdg_data_home,
xdg_runtime_dir,
)
```

`XDG_CACHE_HOME`, `XDG_CONFIG_HOME`, and `XDG_DATA_HOME` are [`pathlib.Path`
objects][path] containing the value of the environment variable of the same
name, or the default defined in the specification if the environment variable is
unset or empty.
`xdg_cache_home()`, `xdg_config_home()`, and `xdg_data_home()` return
[`pathlib.Path` objects][path] containing the value of the environment variable
named `XDG_CACHE_HOME`, `XDG_CONFIG_HOME`, and `XDG_DATA_HOME` respectively, or
the default defined in the specification if the environment variable is unset or
empty.

`XDG_CONFIG_DIRS` and `XDG_DATA_DIRS` are lists of `pathlib.Path` objects
containing the value of the environment variable of the same name split on
colons, or the default defined in the specification if the environment variable
is unset or empty.
`xdg_config_dirs()` and `xdg_data_dirs()` return a list of `pathlib.Path`
objects containing the value, split on colons, of the environment variable named
`XDG_CONFIG_DIRS` and `XDG_DATA_DIRS` respectively, or the default defined in
the specification if the environment variable is unset or empty.

`XDG_RUNTIME_DIR` is a `pathlib.Path` object containing the value of the
environment variable of the same name, or `None` if the environment variable is
unset.
`xdg_runtime_dir()` returns a `pathlib.Path` object containing the value of the
`XDG_RUNTIME_DIR` environment variable, or `None` if the environment variable is
not set.

## Copyright

Expand Down
92 changes: 67 additions & 25 deletions src/xdg/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,20 @@

"""XDG Base Directory Specification variables.
XDG_CACHE_HOME, XDG_CONFIG_HOME, and XDG_DATA_HOME are pathlib.Path
objects containing the value of the environment variable of the same
name, or the default defined in the specification if the environment
variable is unset or empty.
XDG_CONFIG_DIRS and XDG_DATA_DIRS are lists of pathlib.Path objects
containing the value of the environment variable of the same name split
on colons, or the default defined in the specification if the
environment variable is unset or empty.
XDG_RUNTIME_DIR is a pathlib.Path object containing the value of the
environment variable of the same name, or None if the environment
xdg_cache_home(), xdg_config_home(), and xdg_data_home() return
pathlib.Path objects containing the value of the environment variable
named XDG_CACHE_HOME, XDG_CONFIG_HOME, and XDG_DATA_HOME respectively,
or the default defined in the specification if the environment variable
is unset or empty.
xdg_config_dirs() and xdg_data_dirs() return a list of pathlib.Path
objects containing the value, split on colons, of the environment
variable named XDG_CONFIG_DIRS and XDG_DATA_DIRS respectively, or the
default defined in the specification if the environment variable is
unset or empty.
xdg_runtime_dir() returns a pathlib.Path object containing the value of
the XDG_RUNTIME_DIR environment variable, or None if the environment
variable is not set.
"""
Expand All @@ -39,6 +41,12 @@
from typing import List, Optional

__all__ = [
"xdg_cache_home",
"xdg_config_dirs",
"xdg_config_home",
"xdg_data_dirs",
"xdg_data_home",
"xdg_runtime_dir",
"XDG_CACHE_HOME",
"XDG_CONFIG_DIRS",
"XDG_CONFIG_HOME",
Expand All @@ -47,7 +55,10 @@
"XDG_RUNTIME_DIR",
]

HOME = Path(os.path.expandvars("$HOME"))

def _home_dir() -> Path:
"""Return a Path corresponding to the user's home directory."""
return Path(os.path.expandvars("$HOME"))


def _path_from_env(variable: str, default: Path) -> Path:
Expand Down Expand Up @@ -105,20 +116,51 @@ def _paths_from_env(variable: str, default: List[Path]) -> List[Path]:
return default


XDG_CACHE_HOME = _path_from_env("XDG_CACHE_HOME", HOME / ".cache")
def xdg_cache_home() -> Path:
"""Return a Path corresponding to XDG_CACHE_HOME."""
return _path_from_env("XDG_CACHE_HOME", _home_dir() / ".cache")

XDG_CONFIG_DIRS = _paths_from_env("XDG_CONFIG_DIRS", [Path("/etc/xdg")])

XDG_CONFIG_HOME = _path_from_env("XDG_CONFIG_HOME", HOME / ".config")
def xdg_config_dirs() -> List[Path]:
"""Return a list of Paths corresponding to XDG_CONFIG_DIRS."""
return _paths_from_env("XDG_CONFIG_DIRS", [Path("/etc/xdg")])

XDG_DATA_DIRS = _paths_from_env(
"XDG_DATA_DIRS",
[Path(path) for path in "/usr/local/share/:/usr/share/".split(":")],
)

XDG_DATA_HOME = _path_from_env("XDG_DATA_HOME", HOME / ".local" / "share")
def xdg_config_home() -> Path:
"""Return a Path corresponding to XDG_CONFIG_HOME."""
return _path_from_env("XDG_CONFIG_HOME", _home_dir() / ".config")


def xdg_data_dirs() -> List[Path]:
"""Return a list of Paths corresponding to XDG_DATA_DIRS."""
return _paths_from_env(
"XDG_DATA_DIRS",
[Path(path) for path in "/usr/local/share/:/usr/share/".split(":")],
)


try:
XDG_RUNTIME_DIR: Optional[Path] = Path(os.environ["XDG_RUNTIME_DIR"])
except KeyError:
XDG_RUNTIME_DIR = None
def xdg_data_home() -> Path:
"""Return a Path corresponding to XDG_DATA_HOME."""
return _path_from_env("XDG_DATA_HOME", _home_dir() / ".local" / "share")


def xdg_runtime_dir() -> Optional[Path]:
"""Return a Path corresponding to XDG_RUNTIME_DIR.
If the XDG_RUNTIME_DIR environment variable is not set, None will be
returned as per the specification.
"""
try:
return Path(os.environ["XDG_RUNTIME_DIR"])
except KeyError:
return None


# The following variables are deprecated, but remain for backward compatibility.
XDG_CACHE_HOME = xdg_cache_home()
XDG_CONFIG_DIRS = xdg_config_dirs()
XDG_CONFIG_HOME = xdg_config_home()
XDG_DATA_DIRS = xdg_data_dirs()
XDG_DATA_HOME = xdg_data_home()
XDG_RUNTIME_DIR = xdg_runtime_dir()
Loading

0 comments on commit f7ab87c

Please sign in to comment.