Skip to content
This repository has been archived by the owner on Sep 8, 2024. It is now read-only.

Replace hardcoded use of /tmp directory #2892

Merged
merged 17 commits into from
May 7, 2021
Empty file added buggix
Empty file.
26 changes: 14 additions & 12 deletions mycroft/client/enclosure/mark1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from mycroft.util.audio_test import record
from mycroft.util.log import LOG
from queue import Queue
from mycroft.util.file_utils import get_temp_path

# The Mark 1 hardware consists of a Raspberry Pi main CPU which is connected
# to an Arduino over the serial port. A custom serial protocol sends
Expand All @@ -53,9 +54,9 @@ class EnclosureReader(Thread):
Mycroft Core.
E.g. Mycroft Stop Feature
#. Arduino sends a Stop command after a button press on a Mycroft unit
#. ``EnclosureReader`` captures the Stop command
#. Notify all Mycroft Core processes (e.g. skills) to be stopped
# . Arduino sends a Stop command after a button press on a Mycroft unit
# . ``EnclosureReader`` captures the Stop command
# . Notify all Mycroft Core processes (e.g. skills) to be stopped
Note: A command is identified by a line break
"""
Expand Down Expand Up @@ -130,9 +131,9 @@ def process(self, data):
'utterance': "I am testing one two three"}))

time.sleep(0.5) # Prevents recording the loud button press
record("/tmp/test.wav", 3.0)
record(get_temp_path('test.wav', 3.0))
mixer.setvolume(prev_vol)
play_wav("/tmp/test.wav").communicate()
play_wav(get_temp_path('test.wav')).communicate()

# Test audio muting on arduino
subprocess.call('speaker-test -P 10 -l 0 -s 1', shell=True)
Expand Down Expand Up @@ -207,15 +208,15 @@ def stop(self):
class EnclosureWriter(Thread):
"""
Writes data to Serial port.
#. Enqueues all commands received from Mycroft enclosures
# . Enqueues all commands received from Mycroft enclosures
implementation
#. Process them on the received order by writing on the Serial port
# . Process them on the received order by writing on the Serial port
E.g. Displaying a text on Mycroft's Mouth
#. ``EnclosureMouth`` sends a text command
#. ``EnclosureWriter`` captures and enqueue the command
#. ``EnclosureWriter`` removes the next command from the queue
#. ``EnclosureWriter`` writes the command to Serial port
# . ``EnclosureMouth`` sends a text command
# . ``EnclosureWriter`` captures and enqueue the command
# . ``EnclosureWriter`` removes the next command from the queue
# . ``EnclosureWriter`` writes the command to Serial port
Note: A command has to end with a line break
"""
Expand Down Expand Up @@ -337,7 +338,8 @@ def __init_serial(self):
LOG.info("Connected to: %s rate: %s timeout: %s" %
(self.port, self.rate, self.timeout))
except Exception:
LOG.error("Impossible to connect to serial port: "+str(self.port))
LOG.error("Impossible to connect to serial port: " +
str(self.port))
raise

def __register_events(self):
Expand Down
3 changes: 2 additions & 1 deletion mycroft/lock/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
# Wrapper around chain of handler functions for a specific system level signal.
# Often used to trap Ctrl-C for specific application purposes.
from mycroft.util import LOG
from mycroft.util.file_utils import get_temp_path


class Signal: # python 3+ class Signal
Expand Down Expand Up @@ -98,7 +99,7 @@ class Lock: # python 3+ 'class Lock'

#
# Class constants
DIRECTORY = '/tmp/mycroft'
DIRECTORY = get_temp_path('mycroft')
FILE = '/{}.pid'

#
Expand Down
3 changes: 2 additions & 1 deletion mycroft/skills/msm_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

from mycroft.util.combo_lock import ComboLock
from mycroft.util.log import LOG
from mycroft.util.file_utils import get_temp_path

MsmConfig = namedtuple(
'MsmConfig',
Expand All @@ -44,7 +45,7 @@
def _init_msm_lock():
msm_lock = None
try:
msm_lock = ComboLock('/tmp/mycroft-msm.lck')
msm_lock = ComboLock(get_temp_path('mycroft-msm.lck'))
LOG.debug('mycroft-msm combo lock instantiated')
except Exception:
LOG.exception('Failed to create msm lock!')
Expand Down
7 changes: 4 additions & 3 deletions mycroft/skills/skill_updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from mycroft.util.combo_lock import ComboLock
from mycroft.util.log import LOG
from .msm_wrapper import build_msm_config, create_msm
from mycroft.util.file_utils import get_temp_path

ONE_HOUR = 3600
FIVE_MINUTES = 300 # number of seconds in a minute
Expand All @@ -48,7 +49,7 @@ class SkillUpdater:
_msm = None

def __init__(self, bus=None):
self.msm_lock = ComboLock('/tmp/mycroft-msm.lck')
self.msm_lock = ComboLock(get_temp_path('mycroft-msm.lck'))
self.install_retries = 0
self.config = Configuration.get()
update_interval = self.config['skills']['update_interval']
Expand All @@ -72,8 +73,8 @@ def _determine_next_download_time(self):
otherwise use the timestamp on .msm as a basis.
"""
msm_files_exist = (
os.path.exists(self.dot_msm_path) and
os.path.exists(self.installed_skills_file_path)
os.path.exists(self.dot_msm_path) and
os.path.exists(self.installed_skills_file_path)
)
if msm_files_exist:
mtime = os.path.getmtime(self.dot_msm_path)
Expand Down
5 changes: 4 additions & 1 deletion mycroft/tts/tts.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from mycroft.util import (
play_wav, play_mp3, check_for_signal, create_signal, resolve_resource_file
)
from mycroft.util.file_utils import get_temp_path
from mycroft.util.log import LOG
from mycroft.util.plugins import load_plugin
from queue import Queue, Empty
Expand Down Expand Up @@ -164,6 +165,7 @@ class TTS(metaclass=ABCMeta):
phonetic_spelling (bool): Whether to spell certain words phonetically
ssml_tags (list): Supported ssml properties. Ex. ['speak', 'prosody']
"""

def __init__(self, lang, config, validator, audio_ext='wav',
phonetic_spelling=True, ssml_tags=None):
super(TTS, self).__init__()
Expand All @@ -176,7 +178,7 @@ def __init__(self, lang, config, validator, audio_ext='wav',
self.ssml_tags = ssml_tags or []

self.voice = config.get("voice")
self.filename = '/tmp/tts.wav'
self.filename = get_temp_path('tts.wav')
self.enclosure = None
random.seed()
self.queue = Queue()
Expand Down Expand Up @@ -471,6 +473,7 @@ class TTSValidator(metaclass=ABCMeta):
It exposes and implements ``validate(tts)`` function as a template to
validate the TTS engines.
"""

def __init__(self, tts):
self.tts = tts

Expand Down
12 changes: 9 additions & 3 deletions mycroft/util/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,15 @@
from .string_utils import camel_case_split
from .audio_utils import (play_audio_file, play_wav, play_ogg, play_mp3,
record, find_input_device)
from .file_utils import (resolve_resource_file, read_stripped_lines, read_dict,
create_file, ensure_directory_exists,
curate_cache, get_cache_directory)
from .file_utils import (
resolve_resource_file,
read_stripped_lines,
read_dict,
create_file,
get_temp_path,
ensure_directory_exists,
curate_cache,
get_cache_directory)
from .network_utils import connected
from .process_utils import (reset_sigint_handler, create_daemon,
wait_for_exit_signal, create_echo_function,
Expand Down
9 changes: 7 additions & 2 deletions mycroft/util/audio_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from mycroft.util.audio_utils import play_wav
from mycroft.util.log import LOG
import logging
from mycroft.util.file_utils import get_temp_path

"""
Audio Test
Expand Down Expand Up @@ -72,8 +73,12 @@ def record(filename, duration):
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
'-f', '--filename', dest='filename', default="/tmp/test.wav",
help="Filename for saved audio (Default: /tmp/test.wav)")
'-f',
'--filename',
dest='filename',
default=get_temp_path('test.wav'),
help="Filename for saved audio (Default:{}".format(
get_temp_path('test.wav')))
parser.add_argument(
'-d', '--duration', dest='duration', type=int, default=10,
help="Duration of recording in seconds (Default: 10)")
Expand Down
27 changes: 26 additions & 1 deletion mycroft/util/file_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ def get_cache_directory(domain=None):
directory = config.get("cache_path")
if not directory:
# If not defined, use /tmp/mycroft/cache
directory = os.path.join(tempfile.gettempdir(), "mycroft", "cache")
directory = get_temp_path('mycroft', 'cache')
return ensure_directory_exists(directory, domain)


Expand Down Expand Up @@ -275,3 +275,28 @@ def create_file(filename):
ensure_directory_exists(os.path.dirname(filename), permissions=0o775)
with open(filename, 'w') as f:
f.write('')


def get_temp_path(*args):
"""Generate a valid path in the system temp directory.

This method accepts one or more strings as arguments. The arguments are
joined and returned as a complete path inside the systems temp directory.
Importantly, this will not create any directories or files.

Example usage: get_temp_path('mycroft', 'audio', 'example.wav')
Will return the equivalent of: '/tmp/mycroft/audio/example.wav'

Args:
path_element (str): directories and/or filename

Returns:
(str) a valid path in the systems temp directory
"""
try:
path = os.path.join(tempfile.gettempdir(), *args)
except TypeError:
path = None
LOG.error('Could not create a temp path, '
'get_temp_path() only accepts Strings')
forslund marked this conversation as resolved.
Show resolved Hide resolved
return path
5 changes: 3 additions & 2 deletions test/unittests/audio/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import mycroft.audio
from mycroft.util import create_signal, check_for_signal
from mycroft.util.file_utils import get_temp_path

"""Tests for public audio service utils."""

Expand All @@ -38,8 +39,8 @@ def wait_while_speaking_thread():

class TestInterface(unittest.TestCase):
def setUp(self):
if exists('/tmp/mycroft'):
rmtree('/tmp/mycroft')
if exists(get_temp_path('mycroft')):
rmtree(get_temp_path('mycroft'))

def test_is_speaking(self):
create_signal('isSpeaking')
Expand Down
23 changes: 15 additions & 8 deletions test/unittests/lock/test_lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,41 +21,48 @@
from os.path import exists, isfile

from mycroft.lock import Lock
from mycroft.util.file_utils import get_temp_path


class TestLock(unittest.TestCase):
def setUp(self):
if exists('/tmp/mycroft'):
rmtree('/tmp/mycroft')
if exists(get_temp_path('mycroft')):
rmtree(get_temp_path('mycroft'))

def test_create_lock(self):
l1 = Lock('test')
self.assertTrue(isfile('/tmp/mycroft/test.pid'))
self.assertTrue(
isfile(get_temp_path('mycroft', 'test.pid')))

def test_delete_lock(self):
l1 = Lock('test')
self.assertTrue(isfile('/tmp/mycroft/test.pid'))
self.assertTrue(
isfile(get_temp_path('mycroft', 'test.pid')))
l1.delete()
self.assertFalse(isfile('/tmp/mycroft/test.pid'))
self.assertFalse(
isfile(get_temp_path('mycroft', 'test.pid')))

@patch('os.kill')
def test_existing_lock(self, mock_kill):
""" Test that an existing lock will kill the old pid. """
l1 = Lock('test')
self.assertTrue(isfile('/tmp/mycroft/test.pid'))
self.assertTrue(
isfile(get_temp_path('mycroft', 'test.pid')))
l2 = Lock('test2')
self.assertFalse(mock_kill.called)
l2 = Lock('test')
self.assertTrue(mock_kill.called)

def test_keyboard_interrupt(self):
l1 = Lock('test')
self.assertTrue(isfile('/tmp/mycroft/test.pid'))
self.assertTrue(
isfile(get_temp_path('mycroft', 'test.pid')))
try:
os.kill(os.getpid(), signal.SIGINT)
except KeyboardInterrupt:
pass
self.assertFalse(isfile('/tmp/mycroft/test.pid'))
self.assertFalse(
isfile(get_temp_path('mycroft', 'test.pid')))


if __name__ == '__main__':
Expand Down
6 changes: 4 additions & 2 deletions test/unittests/util/test_audio_utils.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@

from unittest import TestCase, mock

from test.util import Anything
from mycroft.util import (play_ogg, play_mp3, play_wav, play_audio_file,
record)
from mycroft.util.file_utils import get_temp_path

test_config = {
'play_wav_cmdline': 'mock_wav %1',
Expand Down Expand Up @@ -137,7 +139,7 @@ def test_record_with_duration(self, mock_subprocess):
mock_subprocess.Popen.return_value = mock_proc
rate = 16000
channels = 1
filename = '/tmp/test.wav'
filename = get_temp_path('test.wav')
duration = 42
res = record(filename, duration, rate, channels)
mock_subprocess.Popen.assert_called_once_with(['arecord',
Expand All @@ -152,7 +154,7 @@ def test_record_without_duration(self, mock_subprocess):
mock_subprocess.Popen.return_value = mock_proc
rate = 16000
channels = 1
filename = '/tmp/test.wav'
filename = get_temp_path('test.wav')
duration = 0
res = record(filename, duration, rate, channels)
mock_subprocess.Popen.assert_called_once_with(['arecord',
Expand Down
18 changes: 11 additions & 7 deletions test/unittests/util/test_download.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@

from threading import Event
from unittest import TestCase, mock

from mycroft.util.download import (download, _running_downloads,
_get_download_tmp)
from mycroft.util.file_utils import get_temp_path

TEST_URL = 'http://example.com/mycroft-test.tar.gz'
TEST_DEST = '/tmp/file.tar.gz'
TEST_DEST = get_temp_path('file.tar.gz')


@mock.patch('mycroft.util.download.subprocess')
Expand Down Expand Up @@ -90,16 +92,18 @@ def wget_call(*args, **kwargs):
class TestGetTemp(TestCase):
def test_no_existing(self, mock_glob):
mock_glob.return_value = []
dest = '/tmp/test'
dest = get_temp_path('test')
self.assertEqual(_get_download_tmp(dest), dest + '.part')

def test_existing(self, mock_glob):
mock_glob.return_value = ['/tmp/test.part']
dest = '/tmp/test'
mock_glob.return_value = [get_temp_path('test.part')]
dest = get_temp_path('test')
self.assertEqual(_get_download_tmp(dest), dest + '.part.1')

def test_multiple_existing(self, mock_glob):
mock_glob.return_value = ['/tmp/test.part', '/tmp/test.part.1',
'/tmp/test.part.2']
dest = '/tmp/test'
mock_glob.return_value = [get_temp_path('test.part'),
get_temp_path('test.part.1'),
get_temp_path('test.part.2')]

dest = get_temp_path('test')
self.assertEqual(_get_download_tmp(dest), dest + '.part.3')
Loading