def depthFirstSearch(problem): """ Search the deepest nodes in the search tree first. Your search algorithm needs to return a list of actions that reaches the goal. Make sure to implement a graph search algorithm. To get started, you might want to try some of these simple commands to understand the search problem that is being passed in: """ root = problem.getStartState() rootNode = [root, []] if problem.isGoalState(root): return [] frontier = Stack() frontier.push(rootNode) explored = [] while not frontier.isEmpty(): if problem.isGoalState(frontier.top()[0]): print("Found goal state") goal = frontier.pop() return goal[1] node = frontier.pop() if node[0] not in explored: explored.append(node[0]) for child_state in problem.getSuccessors(node[0]): if child_state[0] not in explored: child_path = node[1][:] child_path.append(child_state[1]) frontier.push([child_state[0], child_path]) return []
class RESTServer(HTTPServer): def __init__(self, config, **kwargs): addr = ("", config["port"]) super().__init__(addr, RequestHandler, **kwargs) self.endpoints = [] self.plugins = [] self.load_plugins() self._endpoints_to_register = None self._errors = Stack() self._error_lock = Lock() logging.info("Running server.") try: self.serve_forever() except KeyboardInterrupt: self.shutdown() def load_plugins(self): # import for el in pkgutil.iter_modules([PLUGINDIR]): plugin = el[1] try: p = pkgutil.importlib.import_module("{}.{}".format( PLUGINDIR, plugin)) except Exception as e: logging.error("Unable to load plugin: {} ({})".format( plugin, e)) continue else: self.plugins.append(p) # load failed = [] for i in range(len(self.plugins)): module = self.plugins[i] try: self._endpoints_to_register = [] plugin = module.Plugin(self) logging.info("Loaded Plugin: {}".format(plugin.name)) except (AttributeError, TypeError, Exception) as e: failed.append(module) logging.error("Unable to load plugin: {} ({})".format( module, e)) continue self.plugins[i] = plugin for endpoint in self._endpoints_to_register: self.endpoints.append((endpoint, plugin)) logging.info("Registered endpoint: {}".format(endpoint.path)) self._endpoints_to_register = None for el in failed: self.plugins.remove(el) def match_endpoints(self, path): """ Finds the endpoint that matches best with path. If path is "/a/b/c", it matches "/a/b" better than "/a". It does not match "/b". :param path: path that is to be matched :return: endpoint object that matches; None if no match is found """ path = sanitize_path(path).split("/") candidates = [] for el in self.endpoints: candidates.append(el[0]) matches = [] todel = [] # comparison loop for i in range(len(path)): if not candidates: break for el in candidates: if len(el.pathlist) == i: matches.append(el) todel.append(el) elif el.pathlist[i] != path[i]: todel.append(el) elif i == len(el.pathlist) - 1: matches.append(el) for el in todel: candidates.remove(el) todel = [] if not matches: return None # get best match best = matches[0] for el in matches: if len(el.pathlist) > len(best.pathlist): best = el return best def register_endpoint(self, endpoint): """ Registers and endpoint. :param endpoint: Endpoint object """ if self._endpoints_to_register is None: logging.error( "Endpoints must be registered in the Plugin constructor ({})". format(endpoint.path)) return if endpoint not in self.endpoints and endpoint not in self._endpoints_to_register: self._endpoints_to_register.append(endpoint) else: logging.error("Endpoint already registered: {}".format( endpoint.path)) def report_error(self, endpoint, msg, timestamp=None): """ Reports an error to the server error stack. :param endpoint: Endpoint object the error occured in. :param msg: Error message. :param timestamp: Error timestamp; uses now if ommited. :return: """ error = Error(endpoint, msg, timestamp) self._error_lock.acquire() self._errors.push(error) self._error_lock.release() def consume_errors(self): """ Generator for all errors on the server error stack. Errors are removed from the stack (popped). """ self._error_lock.acquire() while True: try: yield self._errors.pop() except IndexError: break self._error_lock.release() def consume_error(self): """ Pops one error from the server error stack (read and remove). :return: Last error """ self._error_lock.acquire() r = self._errors.pop() self._error_lock.release() return r def has_error(self): return not self._errors.is_empty() def last_error(self): """ Reads the last error from the error stack. Does not remove it. :return: Last error """ self._error_lock.acquire() r = self._errors.top() self._error_lock.release() return r def shutdown(self): for plugin in self.plugins: try: plugin.shutdown() except AttributeError: logging.info( "Plugin {} has no shutdown method.".format(plugin)) pass except Exception as e: logging.error("Plugin {} failed to shut down ({})".format( plugin, e)) logging.info("Shutting down.") try: self.shutdown() except Exception as e: logging.error("Clean shutdown failed ({})".format(e))