Beispiel #1
0
def test_illegal_nested_modules():
    with LogCapture(attributes=strip_prefix) as log_capture:
        with Module(name="a"):
            with pytest.raises(RuntimeError) as exc:
                with Module(name="b"):
                    pass
            assert str(
                exc.value
            ) == "Nested `with Module(...)` calls are not supported!`"
Beispiel #2
0
def register(*, name: str = "", props=(), states=(), config={}):
    """
    May be called to register a named set of states, properties and config entries,
    which form a coherent bundle.
    :param name: The name of the module. Will be prefixed to property and signal names like
     <modulename>:<proeprty/signal-name>.
    :param props: The properties that should be registered.
    :param states: The states that should be registered.
    :param config: A dictionary of config entries and their default values, which should be read
     from the default/user config files.
    :return:
    """
    global _registered_modules
    global _registration_callback

    if name in _registered_modules:
        logging.error(f"Attempt to add module {name} twice!")
        return

    _registered_modules[name] = Module(name=name,
                                       props=props,
                                       states=states,
                                       config=config)
    if _registration_callback:
        _registration_callback(_registered_modules[name])
Beispiel #3
0
def test_add_state_configurable_age(context_with_property_fixture: Context):
    my_cond = s(signal_name=DEFAULT_PROPERTY_CHANGED, min_age=ConfigurableAge(key="min_age_key"),
                max_age=ConfigurableAge(key="max_age_key"))

    @state(cond=my_cond)
    def conf_st(ctx):
        pass
    conf_st.module_name = DEFAULT_MODULE_NAME
    context_with_property_fixture._config.add_conf(mod=Module(name=DEFAULT_MODULE_NAME,
                                                              config={"min_age_key": 2.5, "max_age_key": 4.5}))
    context_with_property_fixture.add_state(st=conf_st)
    assert my_cond.min_age == 2.5
    assert my_cond.max_age == 4.5
Beispiel #4
0
    def __init__(self, *arguments, runtime_overrides: List[Tuple[str, str, Any]] = None):
        """
        Construct a context from command line arguments.

        * `arguments`: A series of command line arguments which can be parsed
         by the ravestate command line parser (see argparse.py).
        * `runtime_overrides`: A list of config overrides in the form of (modulename, key, value).
         Can be used to set config entries to values other than strings or lists like in command line arguments.
         An example use-case is a module that starts a new context (in separate process) and can set
         config entries to Connection Objects to enable communication between old and new context.
        """
        modules, overrides, config_files = argparse.handle_args(*arguments)
        self._config = Configuration(config_files)
        self._core_config = {
            self.import_modules_config: [],
            self.tick_rate_config: 20
        }
        self._config.add_conf(Module(name=self.core_module_name, config=self._core_config))
        self._lock = RLock()
        self._shutdown_flag = Event()
        self._properties = dict()
        self._spikes = set()
        self._act_per_state_per_signal_age = dict()
        self._signal_causes = dict()
        self._activations_per_state = dict()
        self._run_task = None

        # Register default signals
        for signal in self._default_signals:
            self._add_sig(signal)

        # Register default properties
        for prop in self._default_properties:
            self.add_prop(prop=prop)

        # Load required modules
        for module_name in self._core_config[self.import_modules_config] + modules:
            self.add_module(module_name)

        # Set required config overrides
        for module_name, key, value in overrides:
            self._config.set(module_name, key, value)
        # Set additional config runtime overrides
        if runtime_overrides:
            for module_name, key, value in runtime_overrides:
                self._config.set(module_name, key, value)

        if self._core_config[self.tick_rate_config] < 1:
            logger.error("Attempt to set core config `tickrate` to a value less-than 1!")
            self._core_config[self.tick_rate_config] = 1
Beispiel #5
0
def test_unknown_module(under_test: Configuration):
    with LogCapture(attributes=strip_prefix) as log_capture:
        under_test.get_conf(DEFAULT_MODULE_NAME)
        log_capture.check(
            f"Bad request for unknown module config {DEFAULT_MODULE_NAME}!")

        under_test.set(module_name=DEFAULT_MODULE_NAME, key="a", value=True)
        log_capture.check_present(
            f"Attempt to run set() for unknown modname {DEFAULT_MODULE_NAME}!")

        under_test.add_conf(Module(name=DEFAULT_MODULE_NAME, config={}))
        under_test.set(module_name=DEFAULT_MODULE_NAME, key="a", value=True)
        log_capture.check_present(
            f"Not setting unknown conf key a for module {DEFAULT_MODULE_NAME}."
        )
Beispiel #6
0
def test_config_write(mocker, under_test: Configuration):
    under_test.add_conf(
        Module(name=DEFAULT_MODULE_NAME, config={"a": "value_A"}))
    m = mocker.mock_open()
    mocker.patch('builtins.open', m)
    under_test.write(path="config_mock.yml")

    m.assert_called_once_with('config_mock.yml', mode='w')
    handle = m()
    expected_calls = [
        'config', ':', '\n', '  ', 'a', ':', ' ', 'value_A', '\n', 'module',
        ':', ' ', 'module', '\n'
    ]
    handle.write.assert_has_calls(
        [mocker.call(exp_call) for exp_call in expected_calls])
Beispiel #7
0
def test_apply_config(under_test: Configuration, config_file_paths):
    under_test.read(config_file_paths[0])
    under_test.read(config_file_paths[1])
    with LogCapture(attributes=strip_prefix) as log_capture:
        under_test.add_conf(
            Module(name="foo", config={
                "a": "hehe",
                "b": "hoho",
                "c": "lol"
            }))
        log_capture.check(
            f"Config entry for foo.a has conflicting type bool (should be str)."
        )
        assert under_test.get("foo", "a") == False
        assert under_test.get("foo", "b") == "haha"
        assert under_test.get("foo", "c") == "lol"
Beispiel #8
0
    def __init__(self, *arguments):
        """
        Construct a context from command line arguments.

        * `arguments`: A series of command line arguments which can be parsed
         by the ravestate command line parser (see argparse.py).
        """
        modules, overrides, config_files = argparse.handle_args(*arguments)
        self._config = Configuration(config_files)
        self._core_config = {
            self._import_modules_config: [],
            self._tick_rate_config: 20
        }
        self._config.add_conf(Module(name=self._core_module_name, config=self._core_config))
        self._lock = Lock()
        self._shutdown_flag = Event()
        self._properties = dict()
        self._spikes = set()
        self._act_per_state_per_signal_age = dict()
        self._signal_causes = dict()
        self._activations_per_state = dict()
        self._run_task = None

        # Register default signals
        for signal in self._default_signals:
            self._add_sig(signal)

        # Register default properties
        for prop in self._default_properties:
            self.add_prop(prop=prop)

        # Set required config overrides
        for module_name, key, value in overrides:
            self._config.set(module_name, key, value)
        if self._core_config[self._tick_rate_config] < 1:
            logger.error("Attempt to set core config `tickrate` to a value less-than 1!")
            self._core_config[self._tick_rate_config] = 1

        # Load required modules
        for module_name in self._core_config[self._import_modules_config]+modules:
            self.add_module(module_name)
Beispiel #9
0
def test_list_convert(under_test: Configuration, config_file_paths):
    under_test.read(config_file_paths[0])
    under_test.read(config_file_paths[1])
    under_test.add_conf(
        Module(name="foo",
               config={
                   "a": "hehe",
                   "b": "hoho",
                   "c": "lol",
                   "d": [],
                   "e": [1]
               }))
    under_test.set("foo", "d", "value")
    value = under_test.get("foo", "d")
    assert isinstance(value, list) and value[0] == "value"
    under_test.set("foo", "e", "30")
    value = under_test.get("foo", "e")
    assert isinstance(value, list) and value[0] == 30
    under_test.set("foo", "e", [True])
    value = under_test.get("foo", "e")
    assert isinstance(value, list) and value[0] == True
Beispiel #10
0
def test_run_with_pressure():

    with Module(name=DEFAULT_MODULE_NAME):

        prop = Property(name=DEFAULT_PROPERTY_NAME)

        a = Signal("a")
        b = Signal("b")

        @state(cond=sig_startup, signal=a)
        def signal_a(ctx):
            return Emit()

        @state(cond=a, signal=b)
        def signal_b(ctx):
            return Emit()

        @state(cond=a, write=prop)
        def pressuring_state(ctx):
            pass

        @state(cond=a & b, write=prop)
        def specific_state(ctx):
            pass

    ctx = Context(DEFAULT_MODULE_NAME)
    ctx.emit(sig_startup)

    ctx.run_once()
    assert signal_a.wait()

    ctx.run_once()
    assert signal_b.wait()

    # make sure that pressuring_state is pressuring specific_state
    acts = ctx._state_activations(st=specific_state)
    assert any(act.is_pressured() for act in acts)

    ctx.run_once()
    assert specific_state.wait()
Beispiel #11
0
from ravestate.property import PropertyBase
from ravestate.module import Module

with Module(name="interloc"):

    # TODO: Make interloc:all a special property type, that only accepts ScientioNodeProperty as children
    all = PropertyBase(name="all",
                       allow_read=True,
                       allow_write=False,
                       allow_push=True,
                       allow_pop=True)
Beispiel #12
0
from ravestate.module import Module
from ravestate_telegramio import telegram_bot

import ravestate_rawio as rawio
import ravestate_interloc as interloc
import ravestate_ontology as ontology


CONFIG = {
    # Token for the Telegram Bot
    telegram_bot.TOKEN_CONFIG_KEY: "",
    # Not to be set in a config file or via the command line. Will be set by master process as a runtime_override.
    telegram_bot.CHILD_CONN_CONFIG_KEY: None,
    # The config-paths listed here will be used for each new telegram chat (if they don't share the same context).
    # Currently only absolute paths are supported
    telegram_bot.CHILD_FILES_CONFIG_KEY: [],
    # Whether all telegram chats should share the same context or not
    telegram_bot.ALL_IN_ONE_CONTEXT_CONFIG_KEY: False,
    # The timespan in minutes in which a chat will be kept active after the last message
    telegram_bot.CHAT_LIFETIME: 5
}

with Module(
        name=telegram_bot.MODULE_NAME,
        config=CONFIG,
        depends=(rawio.mod, interloc.mod, ontology.mod)) as mod:

    mod.add(telegram_bot.telegram_run)
    mod.add(telegram_bot.telegram_output)
Beispiel #13
0
from ravestate.module import Module
from ravestate.property import PropertyBase

with Module(name="rawio"):

    input = PropertyBase(name="in",
                         default_value="",
                         allow_pop=False,
                         allow_push=False,
                         always_signal_changed=True)
    output = PropertyBase(name="out",
                          default_value="",
                          allow_pop=False,
                          allow_push=False,
                          always_signal_changed=True)
Beispiel #14
0
    from roboy_cognition_msgs.msg import RecognizedSpeech
    PYROBOY_AVAILABLE = True
except ImportError as e:
    logger.error(f"""
--------
An exception occured during imports: {e}
Please make sure to have the following items installed & sourced:
1. ROS2 bouncy
2. roboy_communication
3. pyroboy
--------
    """)

if PYROBOY_AVAILABLE:

    with Module(name="roboyio"):

        recognized_speech = Ros2SubProperty(
            name="recognized_speech",
            topic="/roboy/cognition/speech/recognition",
            msg_type=RecognizedSpeech,
            always_signal_changed=True)

        @state(read=recognized_speech.id())
        def roboy_input(ctx: ContextWrapper):
            handle_single_interlocutor_input(ctx,
                                             ctx[recognized_speech.id()].text)

        @state(read="rawio:out")
        def roboy_output(ctx):
            ret = say(ctx["rawio:out:changed"])
Beispiel #15
0
from ravestate.module import Module
from ravestate.property import PropertyBase
from ravestate.state import state
from ravestate_nlp.question_word import QuestionWord
from ravestate_nlp.triple import Triple
from ravestate_nlp.extract_triples import extract_triples
from ravestate_nlp.triple import Triple
from ravestate.state import Emit
from ravestate.constraint import s
from ravestate_nlp.yes_no import yes_no

from reggol import get_logger

logger = get_logger(__name__)

with Module(name="nlp"):

    tokens = PropertyBase(name="tokens",
                          default_value="",
                          always_signal_changed=True,
                          allow_pop=False,
                          allow_push=False),
    postags = PropertyBase(name="postags",
                           default_value="",
                           always_signal_changed=True,
                           allow_pop=False,
                           allow_push=False),
    lemmas = PropertyBase(name="lemmas",
                          default_value="",
                          always_signal_changed=True,
                          allow_pop=False,
Beispiel #16
0
import ravestate_rawio
import ravestate_interloc
from ravestate_verbaliser.verbaliser import get_phrase_list
import ravestate_phrases_basic_en
import ravestate_ontology

from scientio.ontology.node import Node
from scientio.session import Session
from scientio.ontology.ontology import Ontology

from reggol import get_logger
logger = get_logger(__name__)

DEFAULT_INTERLOC_ID = "terminal_user"

with Module(name="consoleio"):

    @state(cond=s(":startup"), read="interloc:all")
    def console_input(ctx: ContextWrapper):
        @receptor(ctx_wrap=ctx, write="rawio:in")
        def write_console_input(ctx_input, value: str):
            ctx_input["rawio:in"] = value

        @receptor(ctx_wrap=ctx, write="interloc:all")
        def push_console_interloc(ctx: ContextWrapper, console_node: Node):
            if ctx.push(parentpath="interloc:all",
                        child=PropertyBase(name=DEFAULT_INTERLOC_ID,
                                           default_value=console_node)):
                logger.debug(f"Pushed {console_node} to interloc:all")

        @receptor(ctx_wrap=ctx, write="interloc:all")
Beispiel #17
0
from ravestate_sendpics.face_recognition import recognize_face_from_image_file

from reggol import get_logger
logger = get_logger(__name__)

REDIS_HOST_CONF = "redis_host"
REDIS_PORT_CONF = "redis_port"
REDIS_PASS_CONF = "redis_pass"
CONFIG = {
    REDIS_HOST_CONF: "localhost",
    REDIS_PORT_CONF: 6379,
    REDIS_PASS_CONF: None
}


with Module(name="sendpics", config=CONFIG):

    face_vec = PropertyBase(name="face_vec", always_signal_changed=True)

    @state(cond=s("idle:bored"), write="rawio:out", weight=1.2, cooldown=30.)
    def prompt_send(ctx):
        ctx["rawio:out"] = "Why don't you send me a picture? I'm really good at recognizing faces!"

    @state(
        read="rawio:pic_in",
        write=("rawio:out", "sendpics:face_vec"),
        emit_detached=True)
    def prompt_name(ctx):
        # Get face ancoding
        face = recognize_face_from_image_file(ctx["rawio:pic_in"])
        # Prompt name
Beispiel #18
0
from ravestate.module import Module
from ravestate.constraint import ConfigurableAge
from ravestate.constraint import s
from ravestate.wrappers import ContextWrapper
from ravestate.state import state, Emit

from reggol import get_logger
logger = get_logger(__name__)

IMPATIENCE_THRESHOLD_CONFIG_KEY = "impatience_threshold"
CONFIG = {
    # duration in seconds how long ":pressure" should be true before getting impatient
    IMPATIENCE_THRESHOLD_CONFIG_KEY: 1.0
}

with Module(name="idle", config=CONFIG):

    @state(read=":activity", signal_name="bored")
    def am_i_bored(ctx: ContextWrapper):
        """
        Emits idle:bored signal if no states are currently partially fulfilled
        """
        if ctx[":activity"] == 0:
            return Emit(wipe=True)

    @state(cond=s(signal_name=":pressure:true",
                  min_age=ConfigurableAge(key=IMPATIENCE_THRESHOLD_CONFIG_KEY),
                  max_age=-1.),
           signal_name="impatient")
    def am_i_impatient(ctx: ContextWrapper):
        return Emit(wipe=True)
Beispiel #19
0
def test_add_list_of_props(state_signal_a_fixture, state_signal_b_fixture):
    with Module(name=DEFAULT_MODULE_NAME) as mod:
        mod.add([state_signal_a_fixture, state_signal_b_fixture])
        assert len(mod.states) == 2
        assert state_signal_a_fixture in mod.states
        assert state_signal_b_fixture in mod.states
Beispiel #20
0
import rclpy
from ravestate.module import Module
from ravestate.constraint import s
from ravestate.state import state
from ravestate.receptor import receptor
from ravestate.property import PropertyBase
from std_msgs.msg import String


rclpy.init()
node = rclpy.create_node("vision_node")


with Module(name="facerec"):

    face = PropertyBase(name="face", default_value="")

    @state(cond=s(":startup"))
    def facerec_run(ctx):

        @receptor(ctx_wrap=ctx, write="facerec:face")
        def face_recognition_callback(ctx, msg):
            ctx["facerec:face"] = msg

        node.create_subscription(String, "/roboy/vision/recognized_faces", face_recognition_callback)
        rclpy.spin(node)


    @state(cond=s(":shutdown"))
    def facerec_shutdown():
        node.destroy_node()
Beispiel #21
0
from ravestate.state import state
from ravestate.module import Module
from ravestate.constraint import s

from roboy_parlai import wildtalk
import ravestate_rawio

with Module(name="wildtalk"):

    @state(cond=s("rawio:in:changed", max_age=-1),
           read="rawio:in",
           write="rawio:out")
    def wildtalk_state(ctx):
        text = ctx["rawio:in"]
        if not text:  # make sure that text is not empty
            text = " "
        ctx["rawio:out"] = wildtalk(text)
Beispiel #22
0
from ravestate.property import Property
from ravestate.activation import Activation
from ravestate import argparser
from ravestate.config import Configuration
from ravestate.constraint import *
from ravestate.spike import Spike

from reggol import get_logger
logger = get_logger(__name__)

CORE_MODULE_NAME = "core"
IMPORT_MODULES_CONFIG_KEY = "import"
TICK_RATE_CONFIG_KEY = "tickrate"
CORE_MODULE_CONFIG = {IMPORT_MODULES_CONFIG_KEY: [], TICK_RATE_CONFIG_KEY: 20}

with Module(name="core", config=CORE_MODULE_CONFIG) as core_module:
    """
    The startup signal, which is fired once when `Context.run()` is executed.
    """
    sig_startup = Signal("startup")
    """
    The shutdown signal, which is fired once when `Context.shutdown()` is called.
    """
    sig_shutdown = Signal("shutdown")

    prop_pressure = Property(name="pressure",
                             allow_read=True,
                             allow_write=True,
                             allow_push=False,
                             allow_pop=False,
                             default_value=False,
Beispiel #23
0
from ravestate.state import state
from ravestate.module import Module
from ravestate.constraint import s
from ravestate.wrappers import ContextWrapper

import ravestate_verbaliser
import ravestate_phrases_basic_en
import ravestate_interloc

with Module(name="hibye"):

    @state(cond=s("interloc:all:pushed") & s("rawio:in:changed"),
           write="verbaliser:intent")
    def react_to_pushed_interloc(ctx: ContextWrapper):
        ctx["verbaliser:intent"] = "greeting"

    @state(cond=s("interloc:all:popped") & s("rawio:in:changed"),
           write="verbaliser:intent")
    def react_to_popped_interloc(ctx: ContextWrapper):
        ctx["verbaliser:intent"] = "farewells"
Beispiel #24
0
from ravestate_verbaliser import verbaliser

from os.path import realpath, dirname, join
import random
import datetime

import ravestate_idle

from reggol import get_logger
logger = get_logger(__name__)

verbaliser.add_folder(join(dirname(realpath(__file__)), "answering_phrases"))

ROBOY_NODE_CONF_KEY = "roboy_node_id"

with Module(name="roboyqa", config={ROBOY_NODE_CONF_KEY: 356}):

    @state(cond=s("idle:bored"), write="rawio:out")
    def hello_world_roboyqa(ctx):
        ctx["rawio:out"] = "Ask me something about myself!"

    @state(cond=s("nlp:contains-roboy") & s("nlp:is-question"),
           read="nlp:triples",
           write="rawio:out")
    def roboyqa(ctx):
        """
        answers question regarding roboy by retrieving the information out of the neo4j roboy memory graph
        state gets triggered when nlp extracts a new triple: subject, predicate, object
        by analysing the triple the content of the question can be ascertained
        the necessary information is gathered using the neo4j memory session
        if the triple combination is known and the information could be retrieved an answer will be given
Beispiel #25
0
import logging

from ravestate.module import Module
from ravestate.property import PropertyBase
from ravestate.state import state
from ravestate_verbaliser import verbaliser

with Module(name="verbaliser"):

    intent = PropertyBase(name="intent",
                          default_value="",
                          allow_push=False,
                          allow_pop=False,
                          always_signal_changed=True)

    @state(read="verbaliser:intent", write="rawio:out")
    def react_to_intent(ctx):
        """
        Looks for intents written to the verbaliser:intent property and
        writes a random phrase for that intent to rawio:out
        """
        intent = ctx["verbaliser:intent"]
        phrase = verbaliser.get_random_phrase(intent)
        if phrase:
            ctx["rawio:out"] = phrase
        else:
            logging.error('No phrase for intent ' + intent + ' found.')
Beispiel #26
0
from ravestate.module import Module
from ravestate.wrappers import ContextWrapper
from ravestate.constraint import s
from ravestate.state import state

import ravestate_idle
import ravestate_verbaliser
import ravestate_phrases_basic_en


with Module(name="fillers"):

    @state(cond=s("idle:impatient"), write=("verbaliser:intent",))
    def impatient_fillers(ctx: ContextWrapper):
        ctx["verbaliser:intent"] = "fillers"
Beispiel #27
0
from ravestate.module import Module
from ravestate_telegramio import telegram_bot

CONFIG = {
    # Token for the Telegram Bot
    telegram_bot.TOKEN_CONFIG_KEY:
    "",
    # Not to be set in a config file or via the command line. Will be set by master process as a runtime_override.
    telegram_bot.CHILD_CONN_CONFIG_KEY:
    None,
    # The config-paths listed here will be used for each new telegram chat (if they don't share the same context).
    # Currently only absolute paths are supported
    telegram_bot.CHILD_FILES_CONFIG_KEY: [],
    # Whether all telegram chats should share the same context or not
    telegram_bot.ALL_IN_ONE_CONTEXT_CONFIG_KEY:
    False,
    # The timespan in minutes in which a chat will be kept active after the last message
    telegram_bot.CHAT_LIFETIME:
    5
}

with Module(name=telegram_bot.MODULE_NAME, config=CONFIG) as mod:

    mod.add(telegram_bot.telegram_run)
    mod.add(telegram_bot.telegram_output)
Beispiel #28
0
An exception occurred during `from roboy_cognition_msgs.msg import RecognizedFaces`: {e}
Roboy will not comment on recognized faces!
--------
""")

if ROBOY_COGNITION_AVAILABLE:

    ROS2_FACE_TOPIC_CONFIG = "ros2-node"
    FACE_CONFIDENCE_THRESHOLD = "min-confidence"

    CONFIG = {
        ROS2_FACE_TOPIC_CONFIG: "/roboy/cognition/vision/visible_face_names",
        FACE_CONFIDENCE_THRESHOLD: 0.85
    }

    with Module(name="stalker", config=CONFIG) as mod:

        # Create a dummy parent, under which we can push the actual recognized faces topic,
        #  once a context with a configuration is available.
        subscriber_parent = PropertyBase(name="face_names_parent")

        @state(cond=startup(),  write=subscriber_parent.id())
        def create_subscriber(ctx: ContextWrapper):
            
            face_names = Ros2SubProperty(
                "face_names",
                topic=ctx.conf(key=ROS2_FACE_TOPIC_CONFIG),
                msg_type=RecognizedFaces,
                always_signal_changed=False)

            rec_faces = PropertyBase(name="rec_faces",
Beispiel #29
0
from ravestate.property import PropertyBase
from ravestate.state import state, Resign, Emit, Delete
from ravestate.constraint import s
from ravestate_akinator.api import Api

from reggol import get_logger
logger = get_logger(__name__)

import ravestate_idle
import ravestate_nlp
import ravestate_rawio

akinator_api: Api
CERTAINTY = "certainty_percentage"

with Module(name="akinator", config={CERTAINTY: 90}):

    initiate_play_again = PropertyBase(name="initiate_play_again",
                                       default_value="",
                                       always_signal_changed=True,
                                       allow_pop=False,
                                       allow_push=False,
                                       is_flag_property=True)

    is_it = PropertyBase(name="is_it",
                         default_value="",
                         always_signal_changed=True,
                         allow_pop=False,
                         allow_push=False,
                         is_flag_property=True)
Beispiel #30
0
logger = get_logger(__name__)

onto = None
sess = None
initialized: Event = Event()
NEO4J_ADDRESS_KEY: str = "neo4j_address"
NEO4J_USERNAME_KEY: str = "neo4j_username"
NEO4J_PASSWORD_KEY: str = "neo4j_pw"
CONFIG = {
    NEO4J_ADDRESS_KEY: "bolt://*****:*****@state(cond=s(":startup"))
    def hello_world_ontology(ctx):
        """
        Creates a scientio session with neo4j backend.
        (neo4j is a knowledge graph)
        an ontology is loaded from a yaml file - it can be accessed with a getter
        (the ontology description is a collection of named entity types,
        their properties and relationships)
        then the session is created - it can be accessed with a getter
        Using ravestate_ontology.initialized.wait() it can be made sure that the session was created before accessing it
        """
        # TODO: Make sess and onto context properties?
        global onto, sess, initialized
        onto = Ontology(path_to_yaml=join(dirname(realpath(__file__)),