Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/license_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,3 @@ jobs:
uses: neongeckocom/.github/.github/workflows/license_tests.yml@master
with:
package-extras: audio,configuration,networking
packages-exclude: '^(precise-runner|fann2|tqdm|bs4|ovos-phal-plugin|ovos-skill|neon-core|nvidia|neon-phal-plugin|bitstruct|audioread|RapidFuzz|click|setuptools|typing_extensions|urllib|marisa-trie).*'
3 changes: 1 addition & 2 deletions neon_utils/file_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@
from tempfile import mkstemp

from typing import Optional, List
from ovos_utils.signal import ensure_directory_exists

from ovos_utils.file_utils import ensure_directory_exists
from neon_utils.logger import LOG


Expand Down
105 changes: 95 additions & 10 deletions neon_utils/signal_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,11 @@ def init_signal_handlers():
log_deprecation("Import patching will be deprecated. Disable in "
"configuration by setting `signal`.`patch_imports` "
"to `False`", "2.0.0")
import ovos_utils.signal
ovos_utils.signal.check_for_signal = _check_for_signal
ovos_utils.signal.create_signal = _create_signal
try:
import mycroft.util.signal
mycroft.util.signal.create_signal = _create_signal
mycroft.util.signal.check_for_signal = _check_for_signal
LOG.info(f"Overrode mycroft.util.signal methods")
LOG.info("Overrode mycroft.util.signal methods")
except (ImportError, AttributeError) as e:
LOG.debug(e)
except TypeError as e:
Expand All @@ -141,12 +138,100 @@ def init_signal_handlers():
else:
LOG.warning("FS signals are deprecated. Signal methods will have no effect.")
if patch_imports:
log_deprecation("Import patching will be deprecated. Disable in "
"configuration by setting `signal`.`patch_imports` "
"to `False`", "2.0.0")
import ovos_utils.signal
_create_signal = ovos_utils.signal.create_signal
_check_for_signal = ovos_utils.signal.check_for_signal
import os
import tempfile
from ovos_utils.file_utils import ensure_directory_exists

def get_ipc_directory(domain=None, config=None):
"""Get the directory used for Inter Process Communication

Files in this folder can be accessed by different processes on the
machine. Useful for communication. This is often a small RAM disk.

Args:
domain (str): The IPC domain. Basically a subdirectory to prevent
overlapping signal filenames.
config (dict): mycroft.conf, to read ipc directory from

Returns:
str: a path to the IPC directory
"""
if config is None:
try:
from ovos_config.config import Configuration
config = Configuration()
except ImportError:
LOG.warning("Config not provided and ovos_config not available")
config = dict()
path = config.get("ipc_path")
if not path:
# If not defined, use /tmp/mycroft/ipc
path = os.path.join(tempfile.gettempdir(), "mycroft", "ipc")
return ensure_directory_exists(path, domain)

def create_file(filename):
""" Create the file filename and create any directories needed

Args:
filename: Path to the file to be created
"""
try:
os.makedirs(os.path.dirname(filename))
except OSError:
pass
with open(filename, 'w') as f:
f.write('')

def create_signal(signal_name, config=None):
"""Create a named signal

Args:
signal_name (str): The signal's name. Must only contain characters
valid in filenames.
config (dict): mycroft.conf, to read ipc directory from
"""
try:
path = os.path.join(get_ipc_directory(config=config),
"signal", signal_name)
create_file(path)
return os.path.isfile(path)
except IOError:
return False


def check_for_signal(signal_name, sec_lifetime=0, config=None):
"""See if a named signal exists

Args:
signal_name (str): The signal's name. Must only contain characters
valid in filenames.
sec_lifetime (int, optional): How many seconds the signal should
remain valid. If 0 or not specified, it is a single-use signal.
If -1, it never expires.
config (dict): mycroft.conf, to read ipc directory from

Returns:
bool: True if the signal is defined, False otherwise
"""
path = os.path.join(get_ipc_directory(config=config),
"signal", signal_name)
if os.path.isfile(path):
if sec_lifetime == 0:
# consume this single-use signal
os.remove(path)
elif sec_lifetime == -1:
return True
elif int(os.path.getctime(path) + sec_lifetime) < int(time.time()):
# remove once expired
os.remove(path)
return False
return True

# No such signal exists
return False

_create_signal = create_signal
_check_for_signal = check_for_signal
_wait_for_signal_clear = _fs_wait_for_signal_clear
_wait_for_signal_create = _fs_wait_for_signal_create
else:
Expand Down
6 changes: 4 additions & 2 deletions requirements/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ pyyaml>=5.4,<7.0
ovos-lingua-franca~=0.4
ovos-utils~=0.0,>=0.0.35
geopy~=2.1
ovos-config~=0.0,>=0.0.9
ovos-workshop~=0.0,>=0.0.15
ovos-config~=0.1
ovos-workshop~=0.0,>=0.0.15
# TODO: Refactor to remove `pkg_resources` imports
setuptools<82.0.0
4 changes: 2 additions & 2 deletions tests/location_util_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,9 @@ def test_get_full_location(self):

location_es = get_full_location("Seattle, Washington", "es")
self.assertAlmostEqual(float(location_es['lat']),
float(location_en['lat']), places=6)
float(location_en['lat']), places=3)
self.assertAlmostEqual(float(location_es['lon']),
float(location_en['lon']), places=6)
float(location_en['lon']), places=3)
self.assertEqual(location_es['address']['country'],
"Estados Unidos de América")
self.assertEqual(location_en['address']['country_code'], "us")
Expand Down
27 changes: 1 addition & 26 deletions tests/signal_util_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
from threading import Event
from os.path import join, dirname

import ovos_utils.signal
from ovos_bus_client import Message
from ovos_utils.messagebus import FakeBus

Expand Down Expand Up @@ -132,7 +131,7 @@ def on_create(message):
self.assertEqual(msg.data, {'signal_name': 'test_signal'})
self.assertEqual(msg.context['origin_module'],
'tests.signal_util_tests')
self.assertEqual(msg.context['origin_line'], 130)
self.assertEqual(msg.context['origin_line'], 129)

def test_signal_utils_manager_available(self):
TestSignalManager(self.test_bus)
Expand All @@ -151,40 +150,21 @@ def test_signal_utils_manager_available(self):
self.assertEqual(neon_utils.signal_utils._wait_for_signal_create,
neon_utils.signal_utils._manager_wait_for_signal_create)

# Check ovos_utils references
self.assertEqual(ovos_utils.signal.check_for_signal,
neon_utils.signal_utils._manager_check_for_signal)
self.assertEqual(ovos_utils.signal.create_signal,
neon_utils.signal_utils._manager_create_signal)

def test_signal_utils_manager_unavailable(self):
import ovos_utils.signal
neon_utils.signal_utils.init_signal_handlers()
self.assertFalse(neon_utils.signal_utils.check_signal_manager_available())
self.assertIsInstance(neon_utils.signal_utils._MAX_TIMEOUT, int)
self.assertEqual(neon_utils.signal_utils._check_for_signal,
ovos_utils.signal.check_for_signal)
self.assertEqual(neon_utils.signal_utils._create_signal,
ovos_utils.signal.create_signal)
self.assertEqual(neon_utils.signal_utils._wait_for_signal_clear,
neon_utils.signal_utils._fs_wait_for_signal_clear)
self.assertEqual(neon_utils.signal_utils._wait_for_signal_create,
neon_utils.signal_utils._fs_wait_for_signal_create)

def test_signal_utils_reload(self):
import ovos_utils.signal
from neon_utils.signal_utils import _check_for_signal
self.assertFalse(neon_utils.signal_utils.check_signal_manager_available())
self.assertEqual(neon_utils.signal_utils._check_for_signal,
ovos_utils.signal.check_for_signal)
self.assertEqual(neon_utils.signal_utils._create_signal,
ovos_utils.signal.create_signal)
self.assertEqual(neon_utils.signal_utils._wait_for_signal_clear,
neon_utils.signal_utils._fs_wait_for_signal_clear)
self.assertEqual(neon_utils.signal_utils._wait_for_signal_create,
neon_utils.signal_utils._fs_wait_for_signal_create)
self.assertEqual(_check_for_signal,
ovos_utils.signal.check_for_signal)

TestSignalManager(self.test_bus)
neon_utils.signal_utils.init_signal_handlers()
Expand All @@ -197,13 +177,8 @@ def test_signal_utils_reload(self):
self.assertEqual(neon_utils.signal_utils._wait_for_signal_create,
neon_utils.signal_utils._manager_wait_for_signal_create)

# Previously imported method is not updated
self.assertEqual(_check_for_signal,
ovos_utils.signal.check_for_signal)

def test_check_signal_manager_available_lazy_load_bus(self):
from ovos_bus_client import MessageBusClient
from neon_utils.signal_utils import check_signal_manager_available
neon_utils.signal_utils._BUS = None
neon_utils.signal_utils.check_signal_manager_available()
self.assertIsInstance(neon_utils.signal_utils._BUS, MessageBusClient)
Expand Down
6 changes: 3 additions & 3 deletions tests/web_util_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@
class WebUtilTests(unittest.TestCase):
def test_scrape_page_for_links(self):
try:
links = scrape_page_for_links("neon.ai")
links = scrape_page_for_links("2025.neon.ai")
self.assertIsInstance(links, dict)
self.assertIn("company", links.keys())
# TODO: Update test to validate absolute and relative URL paths
# Relative href
self.assertIn(links["company"],
("https://neon.ai/company",
"https://neon.ai/company/"))
("https://2025.neon.ai/company",
"https://2025.neon.ai/company/"))
except ConnectTimeout:
LOG.error("Github testing breaks here")

Expand Down
Loading