예제 #1
0
 def reloadStage2(self):
     #disconnect before reloading dispatchers
     self._disconnect(self.oldservers)
     # Reset Dispatcher loaded modules
     # get a list of previously loaded modules so can track stale modules
     oldmodules = set(Dispatcher.MODULEDICT.keys())
     Dispatcher.reset()
     #create databases so init() can do database things.
     self.createDatabases(self.newservers)
     for server in self.servers.itervalues():
         server.initializeReload()
     Dispatcher.showLoadErrors()
     #compare currently loaded modules to oldmodules
     oldmodules = oldmodules.difference(set(Dispatcher.MODULEDICT.keys()))
     #remove oldmodules from sys.modules
     for module in oldmodules:
         module = "pyBurlyBot_%s" % module  #prefix as was set in Dispatcher.load
         print "Removing module: %s" % module
         try:
             del modules[module]
         except KeyError:
             print "WARNING: module was never in modules %s" % module
     # connect after load dispatchers
     self._connect(self.newservers)
     self.oldservers = self.newservers = []
예제 #2
0
 def initializeReload(self):
     # Dispatcher should only be created once.
     if self.dispatcher is None:
         #create dispatcher:
         self.dispatcher = Dispatcher(self)
     #else reload it
     else:
         self.dispatcher.reload()
예제 #3
0
	def shutdown(self, relaunch=False):
		self._disconnect(self.servers.keys())
		#stop timers or just not care...
		Timers._stopall()
		reactor.callLater(2.0, self.databasemanager.shutdown) # to give time for individual shutdown
		Dispatcher.unloadModules()
		reactor.callLater(2.5, reactor.stop) # to give time for individual shutdown
		# TODO: make sure this works properly
		# 	it may act odd on Windows due to execv not replacing current process.
		if relaunch:
			register(relaunchfunc, executable, argv)
예제 #4
0
	def initializeReload(self):
		# Addons should only be created once
		if self.addons is None: self.addons = _ADDONS()
		else: self.addons.clear()
		# Dispatcher should only be created once.
		if self.dispatcher is None:
			#create dispatcher:
			self.dispatcher = Dispatcher(self)
		#else reload it
		else:
			self.dispatcher.reload()
예제 #5
0
	def reloadStage2(self):
		#disconnect before reloading dispatchers
		self._disconnect(self.oldservers)
		# Reset Dispatcher loaded modules
		# get a list of previously loaded modules so can track stale modules
		oldmodules = set(Dispatcher.MODULEDICT.keys())
		Dispatcher.reset()
		#create databases so init() can do database things.
		self.createDatabases(self.newservers)
		for server in self.servers.itervalues():
			server.initializeReload()
		Dispatcher.showLoadErrors()
		#compare currently loaded modules to oldmodules
		oldmodules = oldmodules.difference(set(Dispatcher.MODULEDICT.keys()))
		#remove oldmodules from sys.modules
		for module in oldmodules:
			print "Removing module: %s" % module
			try: del modules[module]
			except KeyError:
				print "WARNING: module was never in modules %s" % module
		# connect after load dispatchers
		self._connect(self.newservers)
		self.oldservers = self.newservers = []
예제 #6
0
def run():
    """
    Bootstraps the application.
    """
    dispatcher = Dispatcher()

    input_file_path = sys.argv[1] if len(sys.argv) > 1 else None
    if input_file_path:
        try:
            with open(input_file_path, "r") as f:
                for cmd in f:
                    response = dispatcher.dispatch(cmd)
        except FileNotFoundError:
            logger.error("No such file: {}".format(input_file_path))

    else:
        cmd = None
        while True:
            cmd = input()
            if cmd:
                if cmd == 'exit':
                    break
                else:
                    response = dispatcher.dispatch(cmd)
예제 #7
0
 def setUp(self):
     self.dispatcher = Dispatcher()
예제 #8
0
class TestParkingLot(unittest.TestCase):
    def setUp(self):
        self.dispatcher = Dispatcher()

    def tearDown(self):
        self.dispatcher = None

    def test_1_parse_cmd(self):
        cmd = "CMD_{}".format(str(uuid4()))
        cmd_key, parsed_data = parse(cmd)
        self.assertIsNone(
            cmd_key,
            msg="{} is invalid command, command key must be null".format(cmd))
        self.assertIsNone(
            parsed_data,
            msg="{} is invalid command, command info must be null".format(cmd))

        cmd = "status"
        cmd_key, parsed_data = parse(cmd)
        self.assertIsNotNone(
            cmd_key,
            msg="{} is valid command, command key must not be null".format(
                cmd))
        self.assertIsNotNone(
            parsed_data,
            msg="{} is valid command, command info must not be null".format(
                cmd))

    def test_2_check_if_parking_lot_available(self):
        cmd = "status"
        response = self.dispatcher.dispatch(cmd)
        if not response.success:
            self.assertEqual(response.error,
                             ErrorConstant.NO_PARKING_LOT_FOUND)

    def test_3_create(self):
        size = 7
        response = self.create_parking_lot(size=size)
        self.assertEqual(size, int(response.data.get('size', 0)))

    def test_4_park(self):
        c_response = self.create_parking_lot(size=5)
        self.assertTrue(c_response.success)

        for i in range(0, 7):
            # PARKING_LOT_OVERFLOW
            p_response = self.dispatcher.dispatch(
                "park DL-3C-909{} GREY".format(i))
            if not p_response.success:
                self.assertIn(p_response.error,
                              (ErrorConstant.PARKING_LOT_OVERFLOW,
                               ErrorConstant.NO_PARKING_LOT_FOUND,
                               ErrorConstant.SLOT_OCCUPIED,
                               ErrorConstant.VEHICLE_IS_ALREADY_PARKED))

        c_response = self.create_parking_lot(size=5)
        self.assertTrue(c_response.success)
        for i in range(0, 5):
            # VEHICLE_IS_ALREADY_PARKED
            p_response = self.dispatcher.dispatch("park DL-3C-9010 GREY")
            if not p_response.success:
                self.assertIn(p_response.error,
                              (ErrorConstant.PARKING_LOT_OVERFLOW,
                               ErrorConstant.NO_PARKING_LOT_FOUND,
                               ErrorConstant.SLOT_OCCUPIED,
                               ErrorConstant.VEHICLE_IS_ALREADY_PARKED))

    def test_5_leave(self):
        c_response = self.create_parking_lot(size=5)
        self.assertTrue(c_response.success)

        reg_nums = ["DL-3C-9070", "DL-3C-9071"]
        for reg_num in reg_nums:
            self.dispatcher.dispatch("park {} GREY".format(reg_num))

        for slot_num in range(1, 7):
            l_res = self.dispatcher.dispatch("leave {}".format(slot_num))
            if not l_res.success:
                self.assertEqual(l_res.error,
                                 ErrorConstant.INVALID_SLOT,
                                 msg="Invalid slot")
            else:
                reg_num = l_res.data.get('reg_num', None)
                self.assertEqual(reg_num, reg_nums[slot_num - 1])

    def test_6_reg_nums_by_color(self):
        c_response = self.create_parking_lot(size=5)
        self.assertTrue(c_response.success)

        col_reg_nums_mapping = {
            'White': {'park DL-3C-9090', 'park DL-3C-9091', 'park DL-3C-9092'},
            'Black': {'park DL-3C-9080', 'park DL-3C-9081'}
        }
        for col, reg_nums in col_reg_nums_mapping.items():
            for reg_num in reg_nums:
                self.dispatcher.dispatch("park {} {}".format(reg_num, col))

        for col in ['White', 'Black', 'Grey']:
            response = self.dispatcher.dispatch(
                'registration_numbers_for_cars_with_colour {}'.format(col))
            fetched_reg_nums = set(response.data.get('reg_nums', []))
            if fetched_reg_nums and len(fetched_reg_nums) > 0:
                self.assertSetEqual(fetched_reg_nums,
                                    col_reg_nums_mapping.get(col, {}))

    def test_7_slot_nums_by_color(self):
        c_response = self.create_parking_lot(size=7)
        self.assertTrue(c_response.success)

        col_slot_nums_mapping = {'White': {'1', '2', '3'}, 'Black': {'4', '5'}}
        for col, slot_nums in col_slot_nums_mapping.items():
            for slot_num in slot_nums:
                self.dispatcher.dispatch("park DL-3C-909{} {}".format(
                    slot_num, col))

        for col in ['White', 'Black', 'Grey']:
            response = self.dispatcher.dispatch(
                'slot_numbers_for_cars_with_colour {}'.format(col))
            fetched_slot_nums = set(response.data.get('slot_nums', []))
            if fetched_slot_nums and len(fetched_slot_nums) > 0:
                self.assertSetEqual(fetched_slot_nums,
                                    col_slot_nums_mapping.get(col, {}))

    def test_8_slot_num_by_reg_num(self):
        c_response = self.create_parking_lot(size=7)
        self.assertTrue(c_response.success)

        reg_nums = ["DL-3C-9017", "DL-3C-9071", "DL-3C-9072", "DL-3C-9018"]
        for reg_num in reg_nums:
            self.dispatcher.dispatch("park {} GREY".format(reg_num))

        for reg_num in [
                "DL-3C-9017", "DL-3C-9071", "INVALID_REG_NUM1",
                "INVALID_REG_NUM2"
        ]:
            res = self.dispatcher.dispatch(
                'slot_number_for_registration_number {}'.format(reg_num))
            if not res.success:
                self.assertIsNone(res.data.get('slot_num', None))

    def create_parking_lot(self, size=5):
        cmd = "create_parking_lot {}".format(str(size))
        response = self.dispatcher.dispatch(cmd)
        return response
예제 #9
0
	def hardshutdown(self):
		Timers._stopall()
		Dispatcher.unloadModules()
		self.databasemanager.shutdown()
예제 #10
0
class Server(BaseServer):
	
	def __init__(self, opts):
		BaseServer.__init__(self, opts)
		self.addons = None
		#dispatcher placeholder (probably not needed)
		self.dispatcher = None
		# TODO: fix the complicated relationship between Factory<->Settings<->Container
		#       also the relationship between Dispatcher<->Settings<->Dispatcher
		self.container = Container(self)
		self._factory = BurlyBotFactory(self)

	def initializeReload(self):
		# Addons should only be created once
		if self.addons is None: self.addons = _ADDONS()
		else: self.addons.clear()
		# Dispatcher should only be created once.
		if self.dispatcher is None:
			#create dispatcher:
			self.dispatcher = Dispatcher(self)
		#else reload it
		else:
			self.dispatcher.reload()
		
	def __getattr__(self, name):
		# get Server setting if set, else fall back to global Settings
		if name in self.__dict__: 
			return getattr(self, name)
		else:
			return getattr(Settings, name)
	
	def getOptions(self, opts, **kwargs):
		vals = []
		for opt in opts:
			vals.append(self.getOption(opt, **kwargs))
		return vals
	
	# if channel or server is set, retrieve for that specific thing.
	# if channel or server is False, retrieve "global" for that thing.
	# TODO: make sure this optimized as it can be
	def getOption(self, opt, module=None, channel=None, server=None, default=NoDefault, setDefault=True, inreactor=False):
		if opt in KEYS_DENY: raise ValueError("Access denied. (%s)" % opt)
		if module:
			if server or server is None:
				# try searching for option in a server object
				if not server is None:
					try: moduleopts = Settings.servers[server].moduleopts
					except KeyError:
						raise ValueError("Server (%s) not found" % server)
				else:
					moduleopts = self.moduleopts
				if module in moduleopts:
					mod = moduleopts[module]
					if channel and "_channels" in mod and channel in mod["_channels"] and opt in mod["_channels"][channel]:
						value = mod["_channels"][channel][opt]
						if type(value) in TYPE_COPY: # copy value if compound datatype
							return deepcopy(value) if inreactor else blockingCallFromThread(reactor, deepcopy, value)
						else: return value
					if opt in mod:
						value = mod[opt]
						if type(value) in TYPE_COPY: # copy value if compound datatype
							return deepcopy(value) if inreactor else blockingCallFromThread(reactor, deepcopy, value)
						else: return value
			# fall back to global moduleopts (or server was False)
			moduleopts = Settings.moduleopts
			# duplicated code from above, micro-optimization because bad.
			if module in moduleopts:
				mod = moduleopts[module]
				if channel and "_channels" in mod and channel in mod["_channels"] and opt in mod["_channels"][channel]:
					value = mod["_channels"][channel][opt]
					if type(value) in TYPE_COPY: # copy value if compound datatype
						return deepcopy(value) if inreactor else blockingCallFromThread(reactor, deepcopy, value)
					else: return value
				if opt in mod:
					value = mod[opt]
					if type(value) in TYPE_COPY: # copy value if compound datatype
						return deepcopy(value) if inreactor else blockingCallFromThread(reactor, deepcopy, value)
					else: return value
			if default is NoDefault:
				raise AttributeError("No setting (%s) for module: %s" % (opt, module))
			else:
				if setDefault:
					moduleopts.setdefault(module, {})[opt] = default
				return default
		#non-module (core) options
		if server is None:
			server = self
		elif server:
			if not server in Settings.servers:
				raise ValueError("Server label (%s) not found." % server)
			server = Settings.servers[server]
		
		if server and opt in KEYS_SERVER_SET:
			value = getattr(self, opt)
		else:
			if not server or server is self:
				if opt not in KEYS_MAIN_SET:
					raise ValueError("Settings has no option: (%s) to get." % opt)
				else:
					value = getattr(Settings, opt)	
			else:
				#case where a server setting is specifically attempted to be got, but it's not in KEYS_SERVER
				# instead of falling back to KEYS_MAIN, raise error
				raise ValueError("Server setting has no option: (%s) to get." % opt)
		if opt in KEYS_COPY: # copy value if compound datatype
			return deepcopy(value) if inreactor else blockingCallFromThread(reactor, deepcopy, value)
		else: return value
	
	def setOption(self, opt, value, module=None, channel=None, server=None):
		if opt in KEYS_DENY: raise ValueError("Access denied. (%s)" % opt)
		if type(value) in TYPE_COPY: value = deepcopy(value) # copy value if compound datatype
		
		if module:
			if server or server is None:
				# try searching for option in a server object
				if not server is None:
					try: moduleopts = Settings.servers[server].moduleopts
					except KeyError:
						raise ValueError("Server (%s) not found" % server)
				else:
					moduleopts = self.moduleopts
				mod = moduleopts.setdefault(module, {})
				if channel: 
					mod.setdefault("_channels", {}).setdefault(channel, {})[opt] = value
				else:
					mod[opt] = value
				return
			# if server was False, (setting "global")
			moduleopts = Settings.moduleopts
			# duplicated code from above, micro-optimization because bad.
			mod = moduleopts.setdefault(module, {})
			if channel: 
				mod.setdefault("_channels", {}).setdefault(channel, {})[opt] = value
			else:
				mod[opt] = value
		else:
			if server is None:
				server = self
			elif server:
				if not server in Settings.servers:
					raise ValueError("Server label (%s) not found." % server)
				server = Settings.servers[server]
			
			if server and opt in KEYS_SERVER_SET:
				setattr(self, opt, value)
			else:
				if not server or server is self:
					if opt not in KEYS_MAIN_SET:
						raise ValueError("Settings has no option: (%s) to set." % opt)
					else:
						setattr(Settings, opt, value)	
				else:
					#case where a server setting is specifically attempted to be set, but it's not in KEYS_SERVER
					# instead of falling back to KEYS_MAIN, raise error
					raise ValueError("Server settings has no option: (%s) to set." % opt)
				
	def getModule(self, modname):
		if not self.isModuleAvailable(modname):
			raise ConfigException("Module (%s) is not available." % modname)
		else:
			return Dispatcher.MODULEDICT.get(modname)
	
	def isModuleAvailable(self, modname):
		return (modname not in self.denymodules) and (modname in Dispatcher.MODULEDICT)
		
	def getAddon(self, addonname):
		try:
			modname, f = self.addons._getModuleAddon(addonname)
		except KeyError:
			raise AttributeError("No provider for %s" % addonname)
		if self.isModuleAvailable(modname):
			return f
		else:
			raise AttributeError("Provider %s is not available because module (%s) is not available." % (addonname, modname))