1
0
Fork 0
mirror of synced 2024-06-01 06:51:10 -04:00
dotbot/test/utils.py

159 lines
6.2 KiB
Python

import sys, os
PROJECT_ROOT_DIRECTORY = os.path.dirname(
os.path.dirname(os.path.realpath(__file__)))
def inject(lib_path):
path = os.path.join(PROJECT_ROOT_DIRECTORY, 'lib', lib_path)
sys.path.insert(0, path)
# version dependent libraries
if sys.version_info[0] >= 3:
inject('pyyaml/lib3')
else:
inject('pyyaml/lib')
if os.path.exists(os.path.join(PROJECT_ROOT_DIRECTORY, 'dotbot')):
if PROJECT_ROOT_DIRECTORY not in sys.path:
sys.path.insert(0, PROJECT_ROOT_DIRECTORY)
os.putenv('PYTHONPATH', PROJECT_ROOT_DIRECTORY)
import shutil
import dotbot
import tempfile
import unittest
import shlex
import yaml
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
# mock is built-in after py3.3, otherwise import the 3rd party mock
try:
from unittest import mock
except ImportError:
import mock
class DotbotTestCase(unittest.TestCase):
""" Dotbot specific TestCase that will take care of setting up temporary directories and a convenience
function for simulating running Dotbot from the CLI """
def setUp(self):
""" Creates a temporary directory to run in for every test """
self.tempdir = tempfile.mkdtemp()
self.dotbot_dir = os.path.join(self.tempdir, 'dotbot')
self.home_dir = os.path.join(self.tempdir, 'home')
self.config_file = os.path.join(self.dotbot_dir, 'dotbot.config')
if int(os.environ.get('NO_CLEAN', '0')):
print(self.tempdir) # If we're not going to clean up, print out where we're runnin
os.mkdir(self.dotbot_dir)
os.mkdir(self.home_dir)
def add_file(self, filename, contents=""):
""" Create a file in temporary dotbot_dir. Optionally with content """
with open(os.path.join(self.dotbot_dir, filename), 'w') as f:
f.write(contents)
def add_home_file(self, filename, contents=""):
""" Create a file in the temporary home_dir. Optionally with content """
with open(os.path.join(self.home_dir, filename), 'w') as f:
f.write(contents)
def add_dirs(self, path):
""" Create directories within the temporary dotbot_dir. Acts like ``mkdir -p``. Path is relative to the
dotbot dir """
os.makedirs(os.path.join(self.dotbot_dir, path))
def add_home_dirs(self, path):
""" Create directories within the temporary home_dir. Acts like ``mkdir -p``. Path is relative to the
home dir """
os.makedirs(os.path.join(self.home_dir, path))
def add_symlink(self, path, dotbot_path=None):
""" Creates a symlink from ``self.home_dir``/path to ``self.dotbot_dir``/dotbot_path.
If dotbot_path is None, path will be used for home_dir and dotbot_dir """
dotbot_path = path if dotbot_path is None else dotbot_path
os.symlink(os.path.join(self.dotbot_dir, dotbot_path), os.path.join(self.home_dir, path))
def assertIsLinked(self, path, dotbot_path=None):
""" Asserts that the given ``path`` in self.home_dir is symlinked to the corresponding ``path``
in self.dotbot_dir """
dotbot_path = path if dotbot_path is None else dotbot_path
self.assertTrue(os.path.islink(os.path.join(self.home_dir, path)))
self.assertEqual(os.stat(os.path.join(self.dotbot_dir, dotbot_path)),
os.stat(os.path.join(self.home_dir, path)))
def assertNotLinked(self, path, dotbot_path=None):
""" Asserts that the given ``path`` in self.home_dir is symlinked to the corresponding ``path``
in self.dotbot_dir """
dotbot_path = path if dotbot_path is None else dotbot_path
self.assertNotEqual(os.stat(os.path.join(self.dotbot_dir, dotbot_path)),
os.stat(os.path.join(self.home_dir, path)))
def assertDoesNotExist(self, path):
""" Asserts the given ``path`` in self.home_dir does not exist """
self.assertFalse(os.path.exists(os.path.join(self.home_dir, path)) or
os.path.lexists(os.path.join(self.home_dir, path)))
def run_dotbot(self, config="", args="", skip_config=False):
""" Runs dotbot in a simulated way temporarily intercepting stdout, stderr, setting the HOME
environment variable to ``self.home_dir``, and setting sys.argv to the simulated command
line options. ``run_dotbot`` will automatically set the ``--base-directory`` and
``--config-file`` command line arguments appropriately.
The ``config`` argument is a string that is written out as the configuration file for dotbot
to use. The ``args`` argument is a string of extra command line arguments to pass to dotbot
just like they would be passed on the command line.
If ``skip_config`` is True, a config file will not be written.
Returns a tuple (out, err) of the stdout and stderr from dotbot.
"""
if not skip_config:
with open(self.config_file, 'w') as f:
if not isinstance(config, str):
f.write(yaml.dump(config, default_flow_style=False))
else:
f.write(config)
base_args = [
'dotbot',
'--base-directory', self.dotbot_dir,
'--config-file', self.config_file,
]
old_home, os.environ['HOME'] = os.path.expanduser('~'), self.home_dir
old_stdout, sys.stdout = sys.stdout, StringIO()
old_stderr, sys.stderr = sys.stderr, StringIO()
old_argv, sys.argv = sys.argv, base_args + shlex.split(args)
old_environ = os.environ.copy()
try:
dotbot.cli.main()
finally:
os.environ['HOME'] = old_home
out, sys.stdout = sys.stdout.getvalue(), old_stdout
err, sys.stderr = sys.stderr.getvalue(), old_stderr
sys.argv = old_argv
os.environ.clear()
os.environ.update(old_environ)
if int(os.environ.get('DEBUG', '0')):
print("\nDotbot Output:")
print('out:\n', out)
print('err:\n', err)
return out, err
def tearDown(self):
""" Clean up the temporary directory that was created. Set NO_CLEAN=1 to disable cleanup """
if not int(os.environ.get('NO_CLEAN', '0')):
shutil.rmtree(self.tempdir)