From 9ca2018dfded681e286e8c3c41beb781ec349ddf Mon Sep 17 00:00:00 2001 From: NeonJarbas <59943014+NeonJarbas@users.noreply.github.com> Date: Thu, 2 Jun 2022 16:32:00 +0100 Subject: [PATCH] Fix/decouple from mycroft (#21) * fix/do not require mycroft * fix/decouple_decorators_from_skills being in the skills module was causing cyclic imports due to helper skill classes importing mycroft * build tests Co-authored-by: jarbasai --- .github/workflows/build_tests.yml | 2 - ovos_workshop/__init__.py | 4 +- ovos_workshop/app.py | 4 +- ovos_workshop/decorators/__init__.py | 22 +++ ovos_workshop/decorators/converse.py | 11 ++ ovos_workshop/decorators/fallback_handler.py | 8 ++ ovos_workshop/decorators/killable.py | 80 +++++++++++ ovos_workshop/decorators/layers.py | 130 +++++++++++++++++ ovos_workshop/decorators/ocp.py | 102 ++++++++++++++ ovos_workshop/skills/__init__.py | 12 +- ovos_workshop/skills/common_play.py | 2 +- ovos_workshop/skills/decorators/__init__.py | 24 +--- ovos_workshop/skills/decorators/converse.py | 13 +- .../skills/decorators/fallback_handler.py | 10 +- ovos_workshop/skills/decorators/killable.py | 82 +---------- ovos_workshop/skills/decorators/layers.py | 132 +----------------- ovos_workshop/skills/decorators/ocp.py | 104 +------------- ovos_workshop/skills/ovos.py | 2 +- 18 files changed, 378 insertions(+), 366 deletions(-) create mode 100644 ovos_workshop/decorators/__init__.py create mode 100644 ovos_workshop/decorators/converse.py create mode 100644 ovos_workshop/decorators/fallback_handler.py create mode 100644 ovos_workshop/decorators/killable.py create mode 100644 ovos_workshop/decorators/layers.py create mode 100644 ovos_workshop/decorators/ocp.py diff --git a/.github/workflows/build_tests.yml b/.github/workflows/build_tests.yml index 14562cf3..9ce0fbd3 100644 --- a/.github/workflows/build_tests.yml +++ b/.github/workflows/build_tests.yml @@ -24,8 +24,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - with: - ref: ${{ github.head_ref }} - name: Setup Python uses: actions/setup-python@v1 with: diff --git a/ovos_workshop/__init__.py b/ovos_workshop/__init__.py index 02e23ebe..cc71fb9d 100644 --- a/ovos_workshop/__init__.py +++ b/ovos_workshop/__init__.py @@ -1,5 +1,5 @@ from ovos_workshop.app import OVOSAbstractApplication -from ovos_workshop.skills.decorators import * -from ovos_workshop.skills.decorators.killable import killable_event, \ +from ovos_workshop.decorators import * +from ovos_workshop.decorators.killable import killable_event, \ AbortEvent, AbortQuestion from ovos_workshop.skills.layers import IntentLayers diff --git a/ovos_workshop/app.py b/ovos_workshop/app.py index 40103564..ac53e9be 100644 --- a/ovos_workshop/app.py +++ b/ovos_workshop/app.py @@ -25,8 +25,8 @@ from ovos_utils.skills import get_non_properties from ovos_utils.intents import IntentBuilder, Intent, AdaptIntent -from ovos_workshop.skills.decorators import * -from ovos_workshop.skills.decorators.killable import killable_event, \ +from ovos_workshop.decorators import * +from ovos_workshop.decorators.killable import killable_event, \ AbortEvent, AbortQuestion from ovos_workshop.skills.layers import IntentLayers diff --git a/ovos_workshop/decorators/__init__.py b/ovos_workshop/decorators/__init__.py new file mode 100644 index 00000000..aff36485 --- /dev/null +++ b/ovos_workshop/decorators/__init__.py @@ -0,0 +1,22 @@ +from ovos_workshop.decorators.killable import \ + killable_intent, killable_event +from ovos_workshop.decorators.layers import enables_layer, \ + disables_layer, layer_intent, removes_layer, resets_layers, replaces_layer +from ovos_workshop.decorators.converse import converse_handler +from ovos_workshop.decorators.fallback_handler import fallback_handler + + +def resting_screen_handler(name): + """Decorator for adding a method as an resting screen handler. + + If selected will be shown on screen when device enters idle mode. + """ + + def real_decorator(func): + # Store the resting information inside the function + # This will be used later in register_resting_screen + if not hasattr(func, 'resting_handler'): + func.resting_handler = name + return func + + return real_decorator diff --git a/ovos_workshop/decorators/converse.py b/ovos_workshop/decorators/converse.py new file mode 100644 index 00000000..126761d7 --- /dev/null +++ b/ovos_workshop/decorators/converse.py @@ -0,0 +1,11 @@ + + +def converse_handler(): + """Decorator for aliasing a method as the converse method""" + + def real_decorator(func): + if not hasattr(func, 'converse'): + func.converse = True + return func + + return real_decorator diff --git a/ovos_workshop/decorators/fallback_handler.py b/ovos_workshop/decorators/fallback_handler.py new file mode 100644 index 00000000..56b79c49 --- /dev/null +++ b/ovos_workshop/decorators/fallback_handler.py @@ -0,0 +1,8 @@ + +def fallback_handler(priority=50): + def real_decorator(func): + if not hasattr(func, 'fallback_priority'): + func.fallback_priority = priority + return func + + return real_decorator diff --git a/ovos_workshop/decorators/killable.py b/ovos_workshop/decorators/killable.py new file mode 100644 index 00000000..03ab827b --- /dev/null +++ b/ovos_workshop/decorators/killable.py @@ -0,0 +1,80 @@ +import time +from ovos_utils import create_killable_daemon +from ovos_utils.messagebus import Message +import threading +from inspect import signature +from functools import wraps + + +class AbortEvent(StopIteration): + """ abort bus event handler """ + + +class AbortIntent(AbortEvent): + """ abort intent parsing """ + + +class AbortQuestion(AbortEvent): + """ gracefully abort get_response queries """ + + +def killable_intent(msg="mycroft.skills.abort_execution", + callback=None, react_to_stop=True, call_stop=True, + stop_tts=True): + return killable_event(msg, AbortIntent, callback, react_to_stop, + call_stop, stop_tts) + + +def killable_event(msg="mycroft.skills.abort_execution", exc=AbortEvent, + callback=None, react_to_stop=False, call_stop=False, + stop_tts=False): + # Begin wrapper + def create_killable(func): + + @wraps(func) + def call_function(*args, **kwargs): + skill = args[0] + t = create_killable_daemon(func, args, kwargs, autostart=False) + + def abort(_): + if not t.is_alive(): + return + if stop_tts: + skill.bus.emit(Message("mycroft.audio.speech.stop")) + if call_stop: + # call stop on parent skill + skill.stop() + + # ensure no orphan get_response daemons + # this is the only killable daemon that core itself will + # create, users should also account for this condition with + # callbacks if using the decorator for other purposes + skill._handle_killed_wait_response() + + try: + while t.is_alive(): + t.raise_exc(exc) + time.sleep(0.1) + except threading.ThreadError: + pass # already killed + except AssertionError: + pass # could not determine thread id ? + if callback is not None: + if len(signature(callback).parameters) == 1: + # class method, needs self + callback(args[0]) + else: + callback() + + # save reference to threads so they can be killed later + skill._threads.append(t) + skill.bus.once(msg, abort) + if react_to_stop: + skill.bus.once(args[0].skill_id + ".stop", abort) + t.start() + return t + + return call_function + + return create_killable + diff --git a/ovos_workshop/decorators/layers.py b/ovos_workshop/decorators/layers.py new file mode 100644 index 00000000..5d1679c8 --- /dev/null +++ b/ovos_workshop/decorators/layers.py @@ -0,0 +1,130 @@ +import inspect +from functools import wraps + +from ovos_workshop.skills.layers import IntentLayers + + +def dig_for_skill(max_records: int = 10): + from ovos_workshop.app import OVOSAbstractApplication + from ovos_workshop.skills import MycroftSkill + stack = inspect.stack()[1:] # First frame will be this function call + stack = stack if len(stack) <= max_records else stack[:max_records] + for record in stack: + args = inspect.getargvalues(record.frame) + if args.locals.get("self"): + obj = args.locals["self"] + if isinstance(obj, MycroftSkill) or \ + isinstance(obj, OVOSAbstractApplication): + return obj + elif args.locals.get("args"): + for obj in args.locals["args"]: + if isinstance(obj, MycroftSkill) or \ + isinstance(obj, OVOSAbstractApplication): + return obj + return None + + +def enables_layer(layer_name): + def layer_handler(func): + @wraps(func) + def call_function(*args, **kwargs): + skill = dig_for_skill() + skill.intent_layers = skill.intent_layers or \ + IntentLayers().bind(skill) + func(*args, **kwargs) + skill.intent_layers.activate_layer(layer_name) + + return call_function + + return layer_handler + + +def disables_layer(layer_name): + def layer_handler(func): + @wraps(func) + def call_function(*args, **kwargs): + skill = dig_for_skill() + skill.intent_layers = skill.intent_layers or \ + IntentLayers().bind(skill) + func(*args, **kwargs) + skill.intent_layers.deactivate_layer(layer_name) + + return call_function + + return layer_handler + + +def replaces_layer(layer_name, intent_list): + def layer_handler(func): + @wraps(func) + def call_function(*args, **kwargs): + skill = dig_for_skill() + skill.intent_layers = skill.intent_layers or \ + IntentLayers().bind(skill) + func(*args, **kwargs) + skill.intent_layers.replace_layer(layer_name, intent_list) + + return call_function + + return layer_handler + + +def removes_layer(layer_name, intent_list): + def layer_handler(func): + @wraps(func) + def call_function(*args, **kwargs): + skill = dig_for_skill() + skill.intent_layers = skill.intent_layers or \ + IntentLayers().bind(skill) + func(*args, **kwargs) + skill.intent_layers.replace_layer(layer_name, intent_list) + + return call_function + + return layer_handler + + +def resets_layers(): + def layer_handler(func): + @wraps(func) + def call_function(*args, **kwargs): + skill = dig_for_skill() + skill.intent_layers = skill.intent_layers or \ + IntentLayers().bind(skill) + func(*args, **kwargs) + skill.intent_layers.disable() + + return call_function + + return layer_handler + + +def layer_intent(intent_parser, layer_name): + """Decorator for adding a method as an intent handler belonging to an + intent layer.""" + + def real_decorator(func): + # Store the intent_parser inside the function + # This will be used later to call register_intent + if not hasattr(func, 'intents'): + func.intents = [] + if not hasattr(func, 'intent_layers'): + func.intent_layers = {} + + func.intents.append(intent_parser) + if layer_name not in func.intent_layers: + func.intent_layers[layer_name] = [] + + # get intent_name + if hasattr(intent_parser, "build"): + intent = intent_parser.build() + intent_name = intent.name or func.__name__ + elif hasattr(intent_parser, "name"): + intent_name = intent_parser.name + else: + intent_name = intent_parser + + func.intent_layers[layer_name].append(intent_name) + return func + + return real_decorator diff --git a/ovos_workshop/decorators/ocp.py b/ovos_workshop/decorators/ocp.py new file mode 100644 index 00000000..0c91a3eb --- /dev/null +++ b/ovos_workshop/decorators/ocp.py @@ -0,0 +1,102 @@ +from functools import wraps +from ovos_workshop.skills.layers import IntentLayers +from ovos_plugin_common_play.ocp import * +from ovos_plugin_common_play.ocp.status import * + + +def ocp_search(): + """Decorator for adding a method as an common play search handler.""" + + def real_decorator(func): + # Store the flag inside the function + # This will be used later to identify the method + if not hasattr(func, 'is_ocp_search_handler'): + func.is_ocp_search_handler = True + + return func + + return real_decorator + + +def ocp_play(): + """Decorator for adding a method as an common play search handler.""" + + def real_decorator(func): + # Store the flag inside the function + # This will be used later to identify the method + if not hasattr(func, 'is_ocp_playback_handler'): + func.is_ocp_playback_handler = True + + return func + + return real_decorator + + +def ocp_previous(): + """Decorator for adding a method as an common play prev handler.""" + + def real_decorator(func): + # Store the flag inside the function + # This will be used later to identify the method + if not hasattr(func, 'is_ocp_prev_handler'): + func.is_ocp_prev_handler = True + + return func + + return real_decorator + + +def ocp_next(): + """Decorator for adding a method as an common play next handler.""" + + def real_decorator(func): + # Store the flag inside the function + # This will be used later to identify the method + if not hasattr(func, 'is_ocp_next_handler'): + func.is_ocp_next_handler = True + + return func + + return real_decorator + + +def ocp_pause(): + """Decorator for adding a method as an common play pause handler.""" + + def real_decorator(func): + # Store the flag inside the function + # This will be used later to identify the method + if not hasattr(func, 'is_ocp_pause_handler'): + func.is_ocp_pause_handler = True + + return func + + return real_decorator + + +def ocp_resume(): + """Decorator for adding a method as an common play resume handler.""" + + def real_decorator(func): + # Store the flag inside the function + # This will be used later to identify the method + if not hasattr(func, 'is_ocp_resume_handler'): + func.is_ocp_resume_handler = True + + return func + + return real_decorator + + +def ocp_featured_media(): + """Decorator for adding a method as an common play search handler.""" + + def real_decorator(func): + # Store the flag inside the function + # This will be used later to identify the method + if not hasattr(func, 'is_ocp_featured_handler'): + func.is_ocp_featured_handler = True + + return func + + return real_decorator diff --git a/ovos_workshop/skills/__init__.py b/ovos_workshop/skills/__init__.py index 53e36fd0..470d0356 100644 --- a/ovos_workshop/skills/__init__.py +++ b/ovos_workshop/skills/__init__.py @@ -1,8 +1,10 @@ -import inspect +try: + from ovos_workshop.skills.ovos import MycroftSkill, OVOSSkill, OVOSFallbackSkill + from ovos_workshop.skills.idle_display_skill import IdleDisplaySkill +except ImportError: + pass + # if mycroft is not available do not export the skill class + # this is common in OvosAbstractApp implementations such as OCP - -from ovos_workshop.skills.ovos import MycroftSkill, OVOSSkill, \ - OVOSFallbackSkill -from ovos_workshop.skills.idle_display_skill import IdleDisplaySkill from ovos_workshop.skills.layers import IntentLayers diff --git a/ovos_workshop/skills/common_play.py b/ovos_workshop/skills/common_play.py index 27761194..031d8300 100644 --- a/ovos_workshop/skills/common_play.py +++ b/ovos_workshop/skills/common_play.py @@ -1,6 +1,6 @@ from inspect import signature from threading import Event -from ovos_workshop.skills.decorators.ocp import * +from ovos_workshop.decorators.ocp import * from ovos_workshop.skills.ovos import OVOSSkill, MycroftSkill from mycroft_bus_client import Message from ovos_utils.log import LOG diff --git a/ovos_workshop/skills/decorators/__init__.py b/ovos_workshop/skills/decorators/__init__.py index 1fd3c535..dc89c06d 100644 --- a/ovos_workshop/skills/decorators/__init__.py +++ b/ovos_workshop/skills/decorators/__init__.py @@ -1,22 +1,2 @@ -from ovos_workshop.skills.decorators.killable import \ - killable_intent, killable_event -from ovos_workshop.skills.decorators.layers import enables_layer, \ - disables_layer, layer_intent, removes_layer, resets_layers, replaces_layer -from ovos_workshop.skills.decorators.converse import converse_handler -from ovos_workshop.skills.decorators.fallback_handler import fallback_handler - - -def resting_screen_handler(name): - """Decorator for adding a method as an resting screen handler. - - If selected will be shown on screen when device enters idle mode. - """ - - def real_decorator(func): - # Store the resting information inside the function - # This will be used later in register_resting_screen - if not hasattr(func, 'resting_handler'): - func.resting_handler = name - return func - - return real_decorator +from ovos_workshop.decorators import * +# backwards compat import diff --git a/ovos_workshop/skills/decorators/converse.py b/ovos_workshop/skills/decorators/converse.py index 126761d7..1c994fe9 100644 --- a/ovos_workshop/skills/decorators/converse.py +++ b/ovos_workshop/skills/decorators/converse.py @@ -1,11 +1,2 @@ - - -def converse_handler(): - """Decorator for aliasing a method as the converse method""" - - def real_decorator(func): - if not hasattr(func, 'converse'): - func.converse = True - return func - - return real_decorator +from ovos_workshop.decorators.converse import * +# backwards compat import diff --git a/ovos_workshop/skills/decorators/fallback_handler.py b/ovos_workshop/skills/decorators/fallback_handler.py index 56b79c49..acfcefdc 100644 --- a/ovos_workshop/skills/decorators/fallback_handler.py +++ b/ovos_workshop/skills/decorators/fallback_handler.py @@ -1,8 +1,2 @@ - -def fallback_handler(priority=50): - def real_decorator(func): - if not hasattr(func, 'fallback_priority'): - func.fallback_priority = priority - return func - - return real_decorator +from ovos_workshop.decorators.fallback_handler import * +# backwards compat import diff --git a/ovos_workshop/skills/decorators/killable.py b/ovos_workshop/skills/decorators/killable.py index 03ab827b..e25241f8 100644 --- a/ovos_workshop/skills/decorators/killable.py +++ b/ovos_workshop/skills/decorators/killable.py @@ -1,80 +1,2 @@ -import time -from ovos_utils import create_killable_daemon -from ovos_utils.messagebus import Message -import threading -from inspect import signature -from functools import wraps - - -class AbortEvent(StopIteration): - """ abort bus event handler """ - - -class AbortIntent(AbortEvent): - """ abort intent parsing """ - - -class AbortQuestion(AbortEvent): - """ gracefully abort get_response queries """ - - -def killable_intent(msg="mycroft.skills.abort_execution", - callback=None, react_to_stop=True, call_stop=True, - stop_tts=True): - return killable_event(msg, AbortIntent, callback, react_to_stop, - call_stop, stop_tts) - - -def killable_event(msg="mycroft.skills.abort_execution", exc=AbortEvent, - callback=None, react_to_stop=False, call_stop=False, - stop_tts=False): - # Begin wrapper - def create_killable(func): - - @wraps(func) - def call_function(*args, **kwargs): - skill = args[0] - t = create_killable_daemon(func, args, kwargs, autostart=False) - - def abort(_): - if not t.is_alive(): - return - if stop_tts: - skill.bus.emit(Message("mycroft.audio.speech.stop")) - if call_stop: - # call stop on parent skill - skill.stop() - - # ensure no orphan get_response daemons - # this is the only killable daemon that core itself will - # create, users should also account for this condition with - # callbacks if using the decorator for other purposes - skill._handle_killed_wait_response() - - try: - while t.is_alive(): - t.raise_exc(exc) - time.sleep(0.1) - except threading.ThreadError: - pass # already killed - except AssertionError: - pass # could not determine thread id ? - if callback is not None: - if len(signature(callback).parameters) == 1: - # class method, needs self - callback(args[0]) - else: - callback() - - # save reference to threads so they can be killed later - skill._threads.append(t) - skill.bus.once(msg, abort) - if react_to_stop: - skill.bus.once(args[0].skill_id + ".stop", abort) - t.start() - return t - - return call_function - - return create_killable - +from ovos_workshop.decorators.killable import * +# backwards compat import diff --git a/ovos_workshop/skills/decorators/layers.py b/ovos_workshop/skills/decorators/layers.py index 5d1679c8..690a9368 100644 --- a/ovos_workshop/skills/decorators/layers.py +++ b/ovos_workshop/skills/decorators/layers.py @@ -1,130 +1,2 @@ -import inspect -from functools import wraps - -from ovos_workshop.skills.layers import IntentLayers - - -def dig_for_skill(max_records: int = 10): - from ovos_workshop.app import OVOSAbstractApplication - from ovos_workshop.skills import MycroftSkill - stack = inspect.stack()[1:] # First frame will be this function call - stack = stack if len(stack) <= max_records else stack[:max_records] - for record in stack: - args = inspect.getargvalues(record.frame) - if args.locals.get("self"): - obj = args.locals["self"] - if isinstance(obj, MycroftSkill) or \ - isinstance(obj, OVOSAbstractApplication): - return obj - elif args.locals.get("args"): - for obj in args.locals["args"]: - if isinstance(obj, MycroftSkill) or \ - isinstance(obj, OVOSAbstractApplication): - return obj - return None - - -def enables_layer(layer_name): - def layer_handler(func): - @wraps(func) - def call_function(*args, **kwargs): - skill = dig_for_skill() - skill.intent_layers = skill.intent_layers or \ - IntentLayers().bind(skill) - func(*args, **kwargs) - skill.intent_layers.activate_layer(layer_name) - - return call_function - - return layer_handler - - -def disables_layer(layer_name): - def layer_handler(func): - @wraps(func) - def call_function(*args, **kwargs): - skill = dig_for_skill() - skill.intent_layers = skill.intent_layers or \ - IntentLayers().bind(skill) - func(*args, **kwargs) - skill.intent_layers.deactivate_layer(layer_name) - - return call_function - - return layer_handler - - -def replaces_layer(layer_name, intent_list): - def layer_handler(func): - @wraps(func) - def call_function(*args, **kwargs): - skill = dig_for_skill() - skill.intent_layers = skill.intent_layers or \ - IntentLayers().bind(skill) - func(*args, **kwargs) - skill.intent_layers.replace_layer(layer_name, intent_list) - - return call_function - - return layer_handler - - -def removes_layer(layer_name, intent_list): - def layer_handler(func): - @wraps(func) - def call_function(*args, **kwargs): - skill = dig_for_skill() - skill.intent_layers = skill.intent_layers or \ - IntentLayers().bind(skill) - func(*args, **kwargs) - skill.intent_layers.replace_layer(layer_name, intent_list) - - return call_function - - return layer_handler - - -def resets_layers(): - def layer_handler(func): - @wraps(func) - def call_function(*args, **kwargs): - skill = dig_for_skill() - skill.intent_layers = skill.intent_layers or \ - IntentLayers().bind(skill) - func(*args, **kwargs) - skill.intent_layers.disable() - - return call_function - - return layer_handler - - -def layer_intent(intent_parser, layer_name): - """Decorator for adding a method as an intent handler belonging to an - intent layer.""" - - def real_decorator(func): - # Store the intent_parser inside the function - # This will be used later to call register_intent - if not hasattr(func, 'intents'): - func.intents = [] - if not hasattr(func, 'intent_layers'): - func.intent_layers = {} - - func.intents.append(intent_parser) - if layer_name not in func.intent_layers: - func.intent_layers[layer_name] = [] - - # get intent_name - if hasattr(intent_parser, "build"): - intent = intent_parser.build() - intent_name = intent.name or func.__name__ - elif hasattr(intent_parser, "name"): - intent_name = intent_parser.name - else: - intent_name = intent_parser - - func.intent_layers[layer_name].append(intent_name) - return func - - return real_decorator +from ovos_workshop.decorators.layers import * +# backwards compat import diff --git a/ovos_workshop/skills/decorators/ocp.py b/ovos_workshop/skills/decorators/ocp.py index 0c91a3eb..f20850fd 100644 --- a/ovos_workshop/skills/decorators/ocp.py +++ b/ovos_workshop/skills/decorators/ocp.py @@ -1,102 +1,2 @@ -from functools import wraps -from ovos_workshop.skills.layers import IntentLayers -from ovos_plugin_common_play.ocp import * -from ovos_plugin_common_play.ocp.status import * - - -def ocp_search(): - """Decorator for adding a method as an common play search handler.""" - - def real_decorator(func): - # Store the flag inside the function - # This will be used later to identify the method - if not hasattr(func, 'is_ocp_search_handler'): - func.is_ocp_search_handler = True - - return func - - return real_decorator - - -def ocp_play(): - """Decorator for adding a method as an common play search handler.""" - - def real_decorator(func): - # Store the flag inside the function - # This will be used later to identify the method - if not hasattr(func, 'is_ocp_playback_handler'): - func.is_ocp_playback_handler = True - - return func - - return real_decorator - - -def ocp_previous(): - """Decorator for adding a method as an common play prev handler.""" - - def real_decorator(func): - # Store the flag inside the function - # This will be used later to identify the method - if not hasattr(func, 'is_ocp_prev_handler'): - func.is_ocp_prev_handler = True - - return func - - return real_decorator - - -def ocp_next(): - """Decorator for adding a method as an common play next handler.""" - - def real_decorator(func): - # Store the flag inside the function - # This will be used later to identify the method - if not hasattr(func, 'is_ocp_next_handler'): - func.is_ocp_next_handler = True - - return func - - return real_decorator - - -def ocp_pause(): - """Decorator for adding a method as an common play pause handler.""" - - def real_decorator(func): - # Store the flag inside the function - # This will be used later to identify the method - if not hasattr(func, 'is_ocp_pause_handler'): - func.is_ocp_pause_handler = True - - return func - - return real_decorator - - -def ocp_resume(): - """Decorator for adding a method as an common play resume handler.""" - - def real_decorator(func): - # Store the flag inside the function - # This will be used later to identify the method - if not hasattr(func, 'is_ocp_resume_handler'): - func.is_ocp_resume_handler = True - - return func - - return real_decorator - - -def ocp_featured_media(): - """Decorator for adding a method as an common play search handler.""" - - def real_decorator(func): - # Store the flag inside the function - # This will be used later to identify the method - if not hasattr(func, 'is_ocp_featured_handler'): - func.is_ocp_featured_handler = True - - return func - - return real_decorator +from ovos_workshop.decorators.ocp import * +# backwards compat import diff --git a/ovos_workshop/skills/ovos.py b/ovos_workshop/skills/ovos.py index bb514aaf..d18153ae 100644 --- a/ovos_workshop/skills/ovos.py +++ b/ovos_workshop/skills/ovos.py @@ -14,7 +14,7 @@ from ovos_utils.skills import get_non_properties from ovos_utils.intents import IntentBuilder, Intent, AdaptIntent from ovos_workshop.patches.base_skill import MycroftSkill, FallbackSkill -from ovos_workshop.skills.decorators.killable import killable_event, \ +from ovos_workshop.decorators.killable import killable_event, \ AbortEvent, AbortQuestion from ovos_workshop.skills.layers import IntentLayers