def check_events(self, event: EventEmitter, event_counts: Dict[str, int]): for event_name in event.event_names: count = event_counts.get(event_name) self.assertIsNotNone(count, "Unexpected event '{}'".format(event_name)) self.assertEqual( event.listener_count(event_name), count, "Mismatch event '{}' count. Expected {:d} but have {:d}". format(event, count, event.listener_count(event_name)))
def __init__(self): self.emitter = EventEmitter() self.hardware_event_job = SCHEDULER.add_job(self.update_hardware_state, "interval", seconds=ms(100), coalesce=True, max_instances=1)
class Board(object): """ Base class for Board hardware implementations """ __metaclass__ = ABCMeta def __init__(self): self.emitter = EventEmitter() self.hardware_event_job = SCHEDULER.add_job( self.update_hardware_state, "interval", seconds=ms(100), coalesce=True, max_instances=1 ) def trigger_hardware_event(self, event, *args, **kwargs): """ Signal hardware event. """ self.emitter.emit(event, *args, **kwargs) def add_event_handler(self, event, handler, once=False): """ Add hardware event handler. """ if once: self.emitter.once(event, handler) else: self.emitter.on(event, handler) def remove_event_handler(self, event, handler): """ Remove hardware event handler. """ self.emitter.remove(event, handler) @abstractmethod def update_hardware_state(self): """ Abstract method for updating hardware state. """ pass
def __init__(self): self.emitter = EventEmitter() self.hardware_event_job = SCHEDULER.add_job( self.update_hardware_state, "interval", seconds=ms(100), coalesce=True, max_instances=1)
def __init__(self, **kwargs): self.initializing = True self.max_w_val = 0 pronsole.pronsole.__init__(self) EventEmitter.__init__(self) self.settings.sensor_names = {'T': 'extruder', 'B': 'bed'} self.settings.sensor_poll_rate = 1 # seconds self.p.loud = kwargs['loud'] self.dry_run = kwargs['dry_run'] self.heaptrace = kwargs['heaptrace'] self.stdout = sys.stdout self.load_default_rc() self.p.sendcb = self.sendcb self.initializing = False dir = os.path.dirname(__file__) self.server = ConstructServer( printer= self, settings= dict( pause_between_prints = self.settings.pause_between_prints, sensor_poll_rate = self.settings.sensor_poll_rate * 1000 ), components= dict( temps= ["e0", "b"], fans= ["f0"], conveyors= ["c0"], axes= [] # In the far off future we may have axes like these for position data: # axes= ["x", "y", "z"] ), server_settings= dict( template_path= os.path.join(dir, "server", "templates"), static_path= os.path.join(dir, "server", "static"), debug= True ), routes= [ (r"/", RootHandler), (r"/inspect", InspectHandler) ] )
def __init__(self, **kwargs): self.printer = kwargs["printer"] EventEmitter.__init__(self) # Configuring the Web Server if not kwargs["routes"]: kwargs["routes"] = [] routes = kwargs["routes"] + [ (r"/socket", ConstructSocketHandler), (r"/jobs", ConstructJobUploadHandler), ] server_settings = kwargs["server_settings"] if server_settings == None: server_settings = {} self.clients = {} self.ioloop = tornado.ioloop.IOLoop.instance() signal.signal(signal.SIGINT, self.sigint_handler) tornado.web.Application.__init__(self, routes, **server_settings) # Configuring the print job queue self.jobs = PrintJobQueue(self) self.jobs.listeners.add(self) # Configuring the printer components self.components = dict(motors=dict(enabled=False), jobs=dict(), pause_between_prints=True, sensor_poll_rate=3000, sessions_count=0, status='idle') self.components = dict(self.components, **kwargs["settings"]) for t, default_vals in self.component_defaults.iteritems(): for key in kwargs["components"][inflection.pluralize(t)]: self.components[key] = copy.deepcopy(default_vals) self.components[key]["type"] = t # Setting the printer's initial values self.sensor_update_received = True self.reset_timeout = 0 self.blockers = []
def __init__(self, adapter_namespace, adapter, httpd, name='Hubot'): """ Constructor. Args: adapter_namespace : A String of the path to local adapters. adapter : A String of the adapter name. httpd : A Boolean whether to enable the HTTP daemon. name : A String of the robot name, defaults to Hubot. Returns nothing. """ self.name = name self.events = EventEmitter() self.brain = Brain(self) self.alias = False self.adapter = None self.response = Response self.commands = [] self.listeners = [] loglevel = LOGGING_LEVEL['info'] logging.basicConfig(level=loglevel) self.logger = logging.getLogger() env_loglevel = os.environ.get('HUBOT_LOG_LEVEL') if env_loglevel and env_loglevel.lower() in LOGGING_LEVEL: loglevel = LOGGING_LEVEL[env_loglevel.lower()] self.logger.setLevel(loglevel) self.ping_interval_id = None self.parse_version() if httpd: self.setup_express() else: self.setup_null_router() self.load_adapter(adapter_namespace, adapter) self.adapter_name = adapter self.error_handlers = [] ## TODO: Write this code as Python """
class Robot(object): """ Robots recieve message from a chat source (Campfire, irc, etc), and dispatch them to matching listeners. """ def __init__(self, adapter_namespace, adapter, httpd, name='Hubot'): """ Constructor. Args: adapter_namespace : A String of the path to local adapters. adapter : A String of the adapter name. httpd : A Boolean whether to enable the HTTP daemon. name : A String of the robot name, defaults to Hubot. Returns nothing. """ self.name = name self.events = EventEmitter() self.brain = Brain(self) self.alias = False self.adapter = None self.response = Response self.commands = [] self.listeners = [] loglevel = LOGGING_LEVEL['info'] logging.basicConfig(level=loglevel) self.logger = logging.getLogger() env_loglevel = os.environ.get('HUBOT_LOG_LEVEL') if env_loglevel and env_loglevel.lower() in LOGGING_LEVEL: loglevel = LOGGING_LEVEL[env_loglevel.lower()] self.logger.setLevel(loglevel) self.ping_interval_id = None self.parse_version() if httpd: self.setup_express() else: self.setup_null_router() self.load_adapter(adapter_namespace, adapter) self.adapter_name = adapter self.error_handlers = [] ## TODO: Write this code as Python """ @on 'error', (err, msg) => @invokeErrorHandlers(err, msg) process.on 'uncaughtException', (err) => @emit 'error', err """ def hear(self, regex, callback): """ Public: Adds a Listener that attempts to match incoming messages based on a Regex. Args: regex : A Regex that determines if the callback should be called. callback: A Function that is called with a Response object. Returns nothing. """ self.listeners.append(TextListener(self, regex.match, callback)) def respond(self, regex, callback): """ Public: Adds a Listener that attempts to match incoming messages directed at the robot based on a Regex. All regexes treat patterns like they begin with a '^' Args: regex : A Regex that determines if the callback should be called. callback: A Function that is called with a Response object. Returns nothing. """ re = str(regex).split('/') re = re[1:] modifiers = re.pop() ## TODO: Check "is this evaluation collect?" if re[0] and re[0][0] is '^': self.logger.warning("Anchors don't work well with respond,", "perhaps you want to use 'hear'") self.logger.warning("The regex in question was %s" % str(regex)) pattern = re.join('/') name = re.sub(r'[-[\]{}()*+?.,\\^$|#\s]', '\\$&', self.name) if self.alias: alias = re.sub(r'[-[\]{}()*+?.,\\^$|#\s]', '\\$&', self.alias) pattern = (r'^\s*[@]?(?:%s[:,]?|%s[:,]?)\s*(?:%s)' % (alias, name, pattern)) else: pattern = r'^\s*[@]?%s[:,]?\s*(?:%s)' % (name, pattern) flags = 0 if 'i' in modifiers: flags += re.I if 'm' in modifiers: flags += re.M r = re.compile(pattern, flags) if 'g' in modifiers: new_regex = r.match else: new_regex = r.search self.listeners.append(TextListener(self, new_regex, callback)) def enter(self, callback): """ Public: Adds a Listener that triggers when anyone enters the room. Args: callback : A Function that is called with a Response object. Returns nothing. """ self.listeners.append(Listener( self, lambda(msg): isinstance(msg, EnterMessage), callback)) def leave(self, callback): """ Public: Adds a Listener that triggers when anyone leaves the room. Args: callback : A Function that is called with a Response object. Returns nothing. """ self.listeners.append(Listener( self, lambda(msg): isinstance(msg, LeaveMessage)), callback) def topic(self, callback): """ Public: Adds a Listener that triggers when anyone changes the topic. Args: callback : A Function that is called with a Response object. Returns nothing. """ self.listeners.append(Listener( self, lambda(msg): isinstance(msg, TopicMessage), callback)) def error(self, callback): """ Public: Adds an error handler when an uncaught exception or user emitted error event occurs. Args: callback : A Function that is called with the error object. Return nothing. """ self.error_handlers.append(callback) def invoke_error_handlers(self, err, msg): """ Calls and passes any registered error handlers for unhandled exceptions or user emitted error events. Args: err : An Error object. msg : An optional Response object that generated the error Returns nothing. """ self.logger.error(err.stack) for error_handler in self.error_handlers: try: error_handler(err, msg) except: self.logger.error("while invoking error handler: %s\n%s" % (err, err.stack)) def catch_all(self, callback): """ Public. Adds a Listener that triggers when no other text matchers match. Args: callback : A Function that is called with a Response object. Return nothing. """ self.listeners.append(Listener(self, lambda msg: isinstance(msg, CatchAllMessage), callback_for_listener)) def callback_for_listener(msg): msg.message = msg.message.message callback(msg) def recieve(self, message): """ Public. Passes the given message to any interested Listeners. Args: message : A Message instance. Listeners can flag this message as 'done' to prevent futher execution. Returns nothing. """ results = [] ## TODO: This need try, except processing ? for listener in self.listeners: results.append(listener.call(message)) if message.done: break if not isinstance(message, CatchAllMessage) and True not in results: self.recieve(CatchAllMessage(message)) def load_file(self, path, namespace, file): """ Public. Loads a file in path. Args: path : A String path on the filesystem. file : A String filename in path on the filesystem. Returns nothing. """ script_name = os.path.splitext(file)[0] try: script = getattr(__import__(namespace + '.' + script_name, fromlist=[namespace.split('.')]), 'script') if isfunction(script): script(self) #self._parse_help(os.path.join(path, file), script_name) else: self.logger.warn("Expected %s to assign a function, " "but it's not defined in this script" % namespace + '.' + script_name) except (AttributeError, NameError) as e: print >> sys.stderr, 'Unable to load ' + file + ': ' + e.message #sys.exit(1) def load(self, path, namespace): """ Public. Loads every script in the given path. Args: path : A String path on the filesystem. Returns nothing. """ self.logger.debug("Loading scripts from %s" % path) if os.path.exists(path): #files = glob.glob(path + '/*.py') files = os.listdir(path) for file in files: self.logger.debug("Found '%s' script file" % file) self.load_file(path, namespace, file) def load_hubot_scripts(self, path, namespace, scripts): """ Public. Load scripts specified in the `hubot-scripts.json` file. Args: path : A String path to the hubot-scripts files. scripts : An Array of scripts to load. Returns nothing. """ self.logger.debug("Loading hubot-scritps from %s" % path) for script in scripts: self.load_file(path, namespace, script) def load_external_scripts(self, packages): pass def setup_express(self): pass def setup_null_router(self): pass def load_adapter(self, namespace, adapter): """ Load the adapter Hubot is going to use. Args: path : A String of the path to adapter if local adapter : A String of the adapter name to use Returns nothing. """ self.logger.debug("Loading adapter %s" % adapter) #if adapter in HUBOT_DEFAULT_ADAPTERS: # path += '/' + adapter #else: # path = 'huobt-' + adapter namespace += '.' + adapter target = namespace.split('.') (package, module, cls_name) = (target[0], namespace, target[-1]) cls_name = cls_name[0].upper() + cls_name[1:] Adapter = getattr(__import__(module, fromlist=[package]), cls_name) self.adapter = Adapter(self) def help_commands(self): pass def _parse_help(self, path, script_name): """ Private: load help info from a loaded script. Args: path : A String path to the file on disk. Returns nothing. """ self.logger.debug("Parsing help for %s" % path) script_document = {} ## TODO: Complete code of this function def send(self, user, *strings): """ Public: A helper send function which delegates to the adapter's send function. Args: user : A User instance. string : One or more String for each message to send. Returns nothing. """ self.adapter.send(user, *strings) def reply(self, user, *strings): """ Public: A helper reply function which delegates to the adapter's reply function. Args: user : A User instance. string : One or more Strings for each message to send. Returns nothing. """ self.adapter.reply(user, *strings) def message_room(self, room, *strings): """ Public: A helper send function to message a room that the robot is in. Args: room : String designating the room to message. strings : One or more Strings for each message to send. Returns nothing. """ user = {room: room } self.adapter.send(user, *strings) def on(self, event, *args): ## TODO: Check is this args comment right? """ Public: A wrapper around the EventEmitter API to make usage sematicly better. Args: event : The event name. listener: A Function that is called with the event parameter when event happens. Returns nothing. """ self.events.on(event, *args) def emit(self, event, *args): """ Public: A wrapper around the EventEmitter API to make usage semanticly better. Args: event : The event name. *args : Arguments emitted by the event """ self.events.emit(event, *args) def run(self): """ Public: Kick off the event loop for the adapter Returns nothing. """ self.emit("running") self.adapter.run() def shutdown(self): """ Public: Gracefully shutdown the robot process Returns nothing. """ if self.ping_interval_id: clear_interval(self.ping_interval_id) self.adapter.close() self.brain.close() def parse_version(self): """ Public: The version of Hubot from npm Returns a String of the version number. """ ## TODO: Write Code insted of below tmporary one self.version = '0.1.0' return self.version def http(self, url, options): """ ### Not implemented !!! ### Public: Creates a scoped http client with chainable methods for medifying the request. This doesn't actually make a request though. Once your the request os assembled, you can call `get()`/`post()`/etc to send the request. Args: url : String URL to access. options : Optional options to pass on to the client. Exmples: robot.http("http://example.com") # set a single header .header('Authorization', 'bearer abcdef') # set multiple headers .headers(Authorization: 'bearer abcdef', Accept: 'application') # add URI query parameters .query(a: 1, b: 'foo & bar') # make the actual request .get() (err, res, body) -> console.log body # or , you can POST data .post(data) (err, res, body) -> console.log body # Can also set options robot.http("https://example.com", {rejectUnauthorized: false}) Returns a ScopedClient instance. """ pass
def test_listeners(self): listener_add = threading.Event() listener_remove = threading.Event() listener_done = threading.Event() listener_once = threading.Event() event_tester = EventEmitter() def emitter_callback(): time.sleep(10) event_tester.emit("test", "Running Unit Test", test_str="Test String", test_int=10) def create_listener_callback(event: threading.Event): def listener_callback(label, *, test_str, test_int): self.assertEqual(label, "Running Unit Test") self.assertEqual(test_str, "Test String") self.assertEqual(test_int, 10) self.assertIsInstance(test_str, str) self.assertIsInstance(test_int, int) event.set() return listener_callback def new_listener_callback(event_name, listener): if not listener_add.is_set() and event_name == "test": listener_add.set() def remove_listener_callback(event_name, listener): if not listener_remove.is_set() and event_name == "test": listener_remove.set() event_tester.on("removeListener", remove_listener_callback) self.check_events(event_tester, {"removeListener": 1}) event_tester.on("newListener", new_listener_callback) self.check_events(event_tester, { "newListener": 1, "removeListener": 1 }) event_listener_callback = create_listener_callback(listener_done) event_tester.on("test", event_listener_callback) self.check_events(event_tester, { "newListener": 1, "removeListener": 1, "test": 1 }) once_listener_callback = create_listener_callback(listener_once) event_tester.once("test", once_listener_callback) self.check_events(event_tester, { "newListener": 1, "removeListener": 1, "test": 2 }) thr = threading.Thread(target=emitter_callback) thr.start() listener_add.wait(1) thr.join() listener_once.wait(1) self.check_events(event_tester, { "newListener": 1, "removeListener": 1, "test": 1 }) listener_done.wait(1) event_tester.remove_listener("test", event_listener_callback) listener_remove.wait(1) self.check_events(event_tester, { "newListener": 1, "removeListener": 1 }) self.assertTrue(listener_done.is_set(), "Listener call failed") self.assertTrue(listener_once.is_set(), "Listener (once) call failed") self.assertTrue(listener_add.is_set(), "Listener for newListener failed") self.assertTrue(listener_remove.is_set(), "Listener for removeListener failed") self.assertEqual(len(event_tester.event_names), 2, "Mismatch event counts")
def test_async_listeners(self): loop = asyncio.get_event_loop() future_add = Future() future_remove = Future() future_done = Future() future_once = Future() event_tester = EventEmitter() async def emitter_callback(): await asyncio.sleep(10) event_tester.emit("test", "Running Unit Test", test_str="Test String", test_int=10) def create_listener_callback(future: Future): async def listener_callback(label, *, test_str, test_int): try: self.assertEqual(label, "Running Unit Test") self.assertEqual(test_str, "Test String") self.assertEqual(test_int, 10) self.assertIsInstance(test_str, str) self.assertIsInstance(test_int, int) except BaseException as exc: future.set_exception(exc) else: future.set_result(True) return listener_callback async def new_listener_callback(event_name, listener): if not future_add.done() and event_name == "test": future_add.set_result(True) async def remove_listener_callback(event_name, listener): if not future_remove.done() and event_name == "test": future_remove.set_result(True) event_tester.on("removeListener", remove_listener_callback) self.check_events(event_tester, {"removeListener": 1}) event_tester.on("newListener", new_listener_callback) self.check_events(event_tester, { "newListener": 1, "removeListener": 1 }) event_listener_callback = create_listener_callback(future_done) event_tester.on("test", event_listener_callback) self.check_events(event_tester, { "newListener": 1, "removeListener": 1, "test": 1 }) once_listener_callback = create_listener_callback(future_once) event_tester.once("test", once_listener_callback) self.check_events(event_tester, { "newListener": 1, "removeListener": 1, "test": 2 }) loop.run_until_complete(emitter_callback()) loop.run_until_complete( asyncio.sleep(1)) # Workaround for pending tasks to complete event_tester.remove_listener("test", event_listener_callback) loop.run_until_complete(asyncio.sleep(1)) self.check_events(event_tester, { "newListener": 1, "removeListener": 1 }) self.assertTrue(future_done.result(1), "Listener call failed") self.assertTrue(future_once.result(1), "Listener (once) call failed") self.assertTrue(future_add.result(1), "Listener for newListener failed") self.assertTrue(future_remove.result(1), "Listener for removeListener failed") self.assertEqual(len(event_tester.event_names), 2, "Mismatch event counts")