async def _async_check_and_create(self, step_id, user_input): """Validate input, proceed to create.""" user_input[CONF_URL] = url_normalize( user_input[CONF_URL], default_scheme="http" ) if "://" not in user_input[CONF_URL]: return await self._async_show_form( step_id=step_id, user_input=user_input, errors={CONF_URL: "invalid_url"} ) # If we don't have a unique id, copy one from existing entry with same URL if not self.unique_id: for existing_entry in ( x for x in self._async_current_entries() if x.data[CONF_URL] == user_input[CONF_URL] and x.unique_id ): await self.async_set_unique_id(existing_entry.unique_id) break session = aiohttp_client.async_get_clientsession(self.hass) printer = SyncThru( user_input[CONF_URL], session, connection_mode=ConnectionMode.API ) errors = {} try: await printer.update() if not user_input.get(CONF_NAME): user_input[CONF_NAME] = DEFAULT_NAME_TEMPLATE.format( printer.model() or DEFAULT_MODEL ) except SyncThruAPINotSupported: errors[CONF_URL] = "syncthru_not_supported" else: if printer.is_unknown_state(): errors[CONF_URL] = "unknown_state" if errors: return await self._async_show_form( step_id=step_id, user_input=user_input, errors=errors ) return self.async_create_entry( title=user_input.get(CONF_NAME), data=user_input, )
async def async_setup_entry(hass, config_entry, async_add_entities): """Set up from config entry.""" session = aiohttp_client.async_get_clientsession(hass) printer = SyncThru(config_entry.data[CONF_URL], session) # Test if the discovered device actually is a syncthru printer # and fetch the available toner/drum/etc try: # No error is thrown when the device is off # (only after user added it manually) # therefore additional catches are inside the Sensor below await printer.update() supp_toner = printer.toner_status(filter_supported=True) supp_drum = printer.drum_status(filter_supported=True) supp_tray = printer.input_tray_status(filter_supported=True) supp_output_tray = printer.output_tray_status() except ValueError as ex: raise SyncThruNotSupported from ex else: if printer.is_unknown_state(): raise PlatformNotReady name = config_entry.data[CONF_NAME] devices = [SyncThruMainSensor(printer, name)] for key in supp_toner: devices.append(SyncThruTonerSensor(printer, name, key)) for key in supp_drum: devices.append(SyncThruDrumSensor(printer, name, key)) for key in supp_tray: devices.append(SyncThruInputTraySensor(printer, name, key)) for key in supp_output_tray: devices.append(SyncThruOutputTraySensor(printer, name, key)) async_add_entities(devices, True)
class NonSyncthruWebTest(unittest.TestCase): server = None server_control = None # type: Server port = 0 url = "http://localhost:80" syncthru = None # type: SyncThru def test_no_syncthru(self) -> None: """Test that an error is thrown when no syncthru is supported""" # Create an arbitrary subclass of TCP Server as the server to be started # Here, it is an Simple HTTP file serving server handler = SyncThruRequestHandler max_retries = 10 r = 0 while not self.server: try: # Connect to any open port self.server = SyncThruServer((ADDRESS, 0), handler) except OSError: if r < max_retries: r += 1 else: raise time.sleep(1) self.server_control = Server(self.server) self.port = self.server_control.get_port() self.url = "{}:{}".format(ADDRESS, self.port) # Start test server before running any tests self.server_control.start_server() # Block server to make sure we get "no support" self.server.set_blocked() try: async def fetch() -> None: async with aiohttp.ClientSession() as session: self.syncthru = SyncThru( self.url, session, connection_mode=ConnectionMode.API ) await self.syncthru.update() loop = asyncio.get_event_loop() loop.run_until_complete(fetch()) self.fail( "No error thrown when noticing that the host does not support Syncthru" ) except SyncThruAPINotSupported: pass def test_offline_unknown(self) -> None: """Test that nothing is returned when syncthru is offline""" async def fetch() -> None: async with aiohttp.ClientSession() as session: self.syncthru = SyncThru( self.url, session, connection_mode=ConnectionMode.API ) await self.syncthru.update() loop = asyncio.get_event_loop() loop.run_until_complete(fetch()) self.assertFalse(self.syncthru.is_online()) self.assertTrue(self.syncthru.is_unknown_state())