Skip to content

Commit

Permalink
Extract XDG directory standard implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
JakobGM committed May 15, 2018
1 parent 1b3eb06 commit 13d404f
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 50 deletions.
26 changes: 7 additions & 19 deletions astrality/executed_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,8 @@
import logging

from astrality import actions
from astrality.config import expand_path
from astrality import utils


def xdg_data_home(application: str) -> Path:
"""Return XDG directory standard path for application data."""
xdg_data_home = expand_path(
path=Path(
os.environ.get(
'XDG_DATA_HOME',
'$HOME/.local/share',
),
),
config_directory=Path('/'),
)
application_data_home = xdg_data_home / application
application_data_home.mkdir(parents=True, exist_ok=True)
return application_data_home
from astrality.xdg import XDG


class ExecutedActions:
Expand All @@ -35,6 +19,9 @@ class ExecutedActions:
# True if we have checked executed() on a new action configuration.
newly_executed_actions: bool

# Path to file containing executed setup actions
_path: Path

def __init__(self, module_name: str) -> None:
"""Construct ExecutedActions object."""
self.module = module_name
Expand Down Expand Up @@ -125,8 +112,9 @@ def path(self) -> Path:
if hasattr(self, '_path'):
return self._path

self._path: Path = xdg_data_home('astrality') / 'setup.yml'
if not self._path.exists():
xdg = XDG('astrality')
self._path = xdg.data(resource='setup.yml')
if os.stat(self._path).st_size == 0:
self._path.touch()
utils.dump_yaml(data={}, path=self._path)

Expand Down
19 changes: 12 additions & 7 deletions astrality/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,18 +190,23 @@ def _action_block_factory(


@pytest.yield_fixture(autouse=True)
def patch_data_dir(tmpdir, monkeypatch):
"""Set DATA_HOME directory to a test directory in all tests."""
def patch_xdg_directory_standard(tmpdir, monkeypatch, request):
"""During testing, the XDG directory standard is monkeypatched."""
if 'dont_patch_xdg' in request.keywords:
yield
return

data_dir = Path(tmpdir).parent / '.local' / 'share' / 'astrality'
data_dir.mkdir(parents=True)
data_dir.mkdir(parents=True, exist_ok=True)

monkeypatch.setattr(
astrality.executed_actions,
'xdg_data_home',
lambda x: data_dir,
astrality.xdg.XDG,
'data_home',
data_dir,
)

yield data_dir

# Delete directory for next test
shutil.rmtree(str(data_dir))
if data_dir.exists():
shutil.rmtree(str(data_dir))
2 changes: 1 addition & 1 deletion astrality/tests/module/test_setup_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from astrality.module import Module


def test_that_module_block_is_persisted(patch_data_dir):
def test_that_module_block_is_persisted():
"""Module should create a 'setup' action block."""
module_config = {
'on_setup': {
Expand Down
24 changes: 1 addition & 23 deletions astrality/tests/test_executed_actions.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
"""Tests for astrality.executed_actions.ExecutedActions."""

import os
from pathlib import Path
import logging

from astrality.executed_actions import ExecutedActions, xdg_data_home
from astrality.executed_actions import ExecutedActions


def test_that_executed_action_path_is_monkeypatched_in_all_files():
Expand All @@ -17,26 +15,6 @@ def test_that_executed_action_path_is_monkeypatched_in_all_files():
assert 'test' in path.parents[3].name


def test_xdg_data_home_default_location():
"""Default location for XDG_DATA_HOME should be respected."""
default_dir = xdg_data_home('astrality')
assert default_dir == Path('~/.local/share/astrality').expanduser()
assert default_dir.is_dir()


def test_xdg_data_home_using_environment_variable(monkeypatch, tmpdir):
"""XDG_DATA_HOME environment variables should be respected."""
custom_data_home = Path(tmpdir, 'data')
monkeypatch.setattr(
os,
'environ',
{'XDG_DATA_HOME': str(custom_data_home)},
)
data_home = xdg_data_home('astrality')
assert data_home == custom_data_home / 'astrality'
assert data_home.is_dir()


def test_that_actions_are_saved_to_file(caplog):
"""Saved actions should be persisted properly."""
action_option = {'shell': 'echo setup'}
Expand Down
46 changes: 46 additions & 0 deletions astrality/tests/test_xdg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""Tests for astrality.xdg module."""

import os
from pathlib import Path

import pytest

from astrality.xdg import XDG


@pytest.mark.dont_patch_xdg
def test_xdg_data_home_default_location(monkeypatch):
"""Default location for XDG_DATA_HOME should be respected."""
xdg = XDG()
default_dir = xdg.data_home
assert default_dir == Path('~/.local/share/astrality').expanduser()
assert default_dir.is_dir()


@pytest.mark.dont_patch_xdg
def test_xdg_data_home_using_environment_variable(monkeypatch, tmpdir):
"""XDG_DATA_HOME environment variables should be respected."""
custom_data_home = Path(tmpdir, 'data')
monkeypatch.setattr(
os,
'environ',
{'XDG_DATA_HOME': str(custom_data_home)},
)

xdg = XDG()
data_home = xdg.data_home
assert data_home == custom_data_home / 'astrality'
assert data_home.is_dir()


def test_retrieving_data_resource(patch_xdg_directory_standard):
"""The data method should retrieve file resource from data home."""
xdg = XDG()
resource = xdg.data('modules/test.tmp')
assert resource == patch_xdg_directory_standard / 'modules' / 'test.tmp'
assert resource.exists()

# We should get the same file again
resource.write_text('hello')
refetched_resource = xdg.data('modules/test.tmp')
assert refetched_resource.read_text() == 'hello'
47 changes: 47 additions & 0 deletions astrality/xdg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"""Module implementing XDG directory standard for astrality."""

import os
from pathlib import Path


class XDG:
"""
Class for handling the XDG directory standard.
:param application_name: Name of application to use XDG directory standard.
"""

def __init__(self, application_name: str = 'astrality') -> None:
"""Contstruct XDG object for application."""
self.application_name = application_name
self.XDG_DATA_HOME = Path(os.environ.get(
'XDG_DATA_HOME',
'~/.local/share',
)).expanduser()
self.XDG_CONFIG_HOME = Path(os.environ.get(
'XDG_CONFIG_HOME',
'~/.config',
)).expanduser()

@property
def data_home(self) -> Path:
"""
Return XDG_DATA_HOME directory of application.
:return: Path to resolved value of XDG_DATA_HOME.
"""
application_data_home = self.XDG_DATA_HOME / self.application_name
application_data_home.mkdir(parents=True, exist_ok=True)
return application_data_home

def data(self, resource: str) -> Path:
"""
Return file resource of application.
:param resource: Relative string path, i.e. $XDG_DATA_HOME/<resource>.
:return: Path to touched data resource.
"""
resource_path = self.data_home / resource
resource_path.parent.mkdir(parents=True, exist_ok=True)
resource_path.touch(exist_ok=True)
return resource_path

0 comments on commit 13d404f

Please sign in to comment.