async def test_digest_auth_qop_auth_int_not_implemented() -> None: url = "https://example.org/" auth = DigestAuth(username="******", password="******") client = AsyncClient(dispatch=MockDigestAuthDispatch(qop="auth-int")) with pytest.raises(NotImplementedError): await client.get(url, auth=auth)
async def test_digest_auth_qop_must_be_auth_or_auth_int() -> None: url = "https://example.org/" auth = DigestAuth(username="******", password="******") client = AsyncClient(dispatch=MockDigestAuthDispatch(qop="not-auth")) with pytest.raises(ProtocolError): await client.get(url, auth=auth)
async def test_digest_auth_qop_including_spaces_and_auth_returns_auth( qop: str) -> None: url = "https://example.org/" auth = DigestAuth(username="******", password="******") client = AsyncClient(dispatch=MockDigestAuthDispatch(qop=qop)) await client.get(url, auth=auth)
async def test_digest_auth_no_specified_qop() -> None: url = "https://example.org/" auth = DigestAuth(username="******", password="******") client = AsyncClient(dispatch=MockDigestAuthDispatch(qop="")) response = await client.get(url, auth=auth) assert response.status_code == 200 assert len(response.history) == 1 authorization = typing.cast(dict, response.json())["auth"] scheme, _, fields = authorization.partition(" ") assert scheme == "Digest" response_fields = [field.strip() for field in fields.split(",")] digest_data = dict(field.split("=") for field in response_fields) assert "qop" not in digest_data assert "nc" not in digest_data assert "cnonce" not in digest_data assert digest_data["username"] == '"tomchristie"' assert digest_data["realm"] == '"*****@*****.**"' assert len(digest_data["nonce"]) == 64 + 2 # extra quotes assert digest_data["uri"] == '"/"' assert len(digest_data["response"]) == 64 + 2 assert len(digest_data["opaque"]) == 64 + 2 assert digest_data["algorithm"] == "SHA-256"
async def test_digest_auth(algorithm: str, expected_hash_length: int, expected_response_length: int) -> None: url = "https://example.org/" auth = DigestAuth(username="******", password="******") app = DigestApp(algorithm=algorithm) async with httpx.AsyncClient(transport=MockTransport(app)) as client: response = await client.get(url, auth=auth) assert response.status_code == 200 assert len(response.history) == 1 authorization = typing.cast(dict, response.json())["auth"] scheme, _, fields = authorization.partition(" ") assert scheme == "Digest" response_fields = [field.strip() for field in fields.split(",")] digest_data = dict(field.split("=") for field in response_fields) assert digest_data["username"] == '"tomchristie"' assert digest_data["realm"] == '"*****@*****.**"' assert "nonce" in digest_data assert digest_data["uri"] == '"/"' assert len(digest_data["response"] ) == expected_response_length + 2 # extra quotes assert len(digest_data["opaque"]) == expected_hash_length + 2 assert digest_data["algorithm"] == algorithm assert digest_data["qop"] == "auth" assert digest_data["nc"] == "00000001" assert len(digest_data["cnonce"]) == 16 + 2
async def test_digest_auth_qop_auth_int_not_implemented() -> None: url = "https://example.org/" auth = DigestAuth(username="******", password="******") async with httpx.AsyncClient(transport=MockDigestAuthTransport( qop="auth-int")) as client: with pytest.raises(NotImplementedError): await client.get(url, auth=auth)
async def test_digest_auth_qop_must_be_auth_or_auth_int() -> None: url = "https://example.org/" auth = DigestAuth(username="******", password="******") async with httpx.AsyncClient(transport=MockDigestAuthTransport( qop="not-auth")) as client: with pytest.raises(ProtocolError): await client.get(url, auth=auth)
async def test_async_digest_auth_raises_protocol_error_on_malformed_header( auth_header: bytes, ) -> None: url = "https://example.org/" auth = DigestAuth(username="******", password="******") async with httpx.AsyncClient(transport=AsyncMockTransport( auth_header=auth_header, status_code=401)) as client: with pytest.raises(ProtocolError): await client.get(url, auth=auth)
async def test_digest_auth_incorrect_credentials(): url = "https://example.org/" auth = DigestAuth(username="******", password="******") client = Client(dispatch=MockDigestAuthDispatch(send_response_after_attempt=2)) response = await client.get(url, auth=auth) assert response.status_code == 401
async def _async_get(self, sub_url: str, timeout: float = TIMEOUT) -> Response: """Query URL asynchronously.""" url = f"{self.url}{sub_url}" self._logger.debug("Getting from %s", url) try: response = await self._session.get(url, auth=DigestAuth(self._user, self.password), timeout=timeout) if response.status_code == HTTPStatus.UNAUTHORIZED: self.password = hashlib.sha256(self.password.encode("utf-8")).hexdigest() response = await self._session.get(url, auth=DigestAuth(self._user, self.password), timeout=timeout) response.raise_for_status() return response except HTTPStatusError as e: if e.response.status_code == HTTPStatus.UNAUTHORIZED: raise DevicePasswordProtected("The used password is wrong.") from None raise e except (ConnectTimeout, ConnectError, ReadTimeout, RemoteProtocolError): raise DeviceUnavailable("The device is currently not available. Maybe on standby?") from None
async def test_digest_auth_raises_protocol_error_on_malformed_header( auth_header: str, ) -> None: url = "https://example.org/" auth = DigestAuth(username="******", password="******") client = AsyncClient( dispatch=MockDispatch(auth_header=auth_header, status_code=401)) with pytest.raises(ProtocolError): await client.get(url, auth=auth)
async def test_digest_auth_qop_including_spaces_and_auth_returns_auth(qop: str) -> None: url = "https://example.org/" auth = DigestAuth(username="******", password="******") client = AsyncClient(dispatch=MockDigestAuthDispatch(qop=qop)) response = await client.get(url, auth=auth) assert response.status_code == 200 assert len(response.history) == 1
async def test_digest_auth_401_response_without_digest_auth_header(): url = "https://example.org/" auth = DigestAuth(username="******", password="******") client = Client(dispatch=MockDispatch(auth_header="", status_code=401)) response = await client.get(url, auth=auth) assert response.status_code == 401 assert response.json() == {"auth": None}
async def test_digest_auth_returns_no_auth_if_no_digest_header_in_response(): url = "https://example.org/" auth = DigestAuth(username="******", password="******") client = Client(dispatch=MockDispatch()) response = await client.get(url, auth=auth) assert response.status_code == 200 assert response.json() == {"auth": None}
async def test_digest_auth_qop_including_spaces_and_auth_returns_auth(qop: str) -> None: url = "https://example.org/" auth = DigestAuth(username="******", password="******") app = DigestApp(qop=qop) async with httpx.AsyncClient(transport=MockTransport(app)) as client: response = await client.get(url, auth=auth) assert response.status_code == 200 assert len(response.history) == 1
async def test_digest_auth_200_response_including_digest_auth_header(): url = "https://example.org/" auth = DigestAuth(username="******", password="******") auth_header = 'Digest realm="*****@*****.**",qop="auth",nonce="abc",opaque="xyz"' client = Client(dispatch=MockDispatch(auth_header=auth_header, status_code=200)) response = await client.get(url, auth=auth) assert response.status_code == 200 assert response.json() == {"auth": None}
async def test_digest_auth_incorrect_credentials() -> None: url = "https://example.org/" auth = DigestAuth(username="******", password="******") client = AsyncClient(transport=MockDigestAuthTransport( send_response_after_attempt=2)) response = await client.get(url, auth=auth) assert response.status_code == 401 assert len(response.history) == 1
async def test_digest_auth_unavailable_streaming_body(): url = "https://example.org/" auth = DigestAuth(username="******", password="******") client = AsyncClient(transport=AsyncMockTransport()) async def streaming_body(): yield b"Example request body" # pragma: nocover with pytest.raises(RequestBodyUnavailable): await client.post(url, data=streaming_body(), auth=auth)
async def test_digest_auth_401_response_without_digest_auth_header() -> None: url = "https://example.org/" auth = DigestAuth(username="******", password="******") client = AsyncClient(transport=AsyncMockTransport(auth_header=b"", status_code=401)) response = await client.get(url, auth=auth) assert response.status_code == 401 assert response.json() == {"auth": None} assert len(response.history) == 0
async def test_digest_auth_returns_no_auth_if_no_digest_header_in_response() -> None: url = "https://example.org/" auth = DigestAuth(username="******", password="******") client = AsyncClient(transport=AsyncMockTransport()) response = await client.get(url, auth=auth) assert response.status_code == 200 assert response.json() == {"auth": None} assert len(response.history) == 0
async def test_digest_auth_unavailable_streaming_body(): url = "https://example.org/" auth = DigestAuth(username="******", password="******") app = DigestApp() async def streaming_body(): yield b"Example request body" # pragma: nocover async with httpx.AsyncClient(transport=MockTransport(app)) as client: with pytest.raises(httpx.StreamConsumed): await client.post(url, data=streaming_body(), auth=auth)
async def test_digest_auth_200_response_including_digest_auth_header() -> None: url = "https://example.org/" auth = DigestAuth(username="******", password="******") auth_header = b'Digest realm="*****@*****.**",qop="auth",nonce="abc",opaque="xyz"' client = AsyncClient( transport=AsyncMockTransport(auth_header=auth_header, status_code=200)) response = await client.get(url, auth=auth) assert response.status_code == 200 assert response.json() == {"auth": None} assert len(response.history) == 0
def test_digest_auth_returns_no_auth_if_alternate_auth_scheme() -> None: url = "https://example.org/" auth = DigestAuth(username="******", password="******") auth_header = b"Token ..." client = httpx.Client( transport=SyncMockTransport(auth_header=auth_header, status_code=401)) response = client.get(url, auth=auth) assert response.status_code == 401 assert response.json() == {"auth": None} assert len(response.history) == 0
async def test_digest_auth_no_specified_qop(): url = "https://example.org/" auth = DigestAuth(username="******", password="******") client = Client(dispatch=MockDigestAuthDispatch(qop=None)) response = await client.get(url, auth=auth) assert response.status_code == 200 auth = response.json()["auth"] assert auth.startswith("Digest ") response_fields = [field.strip() for field in auth[auth.find(" ") :].split(",")] digest_data = dict(field.split("=") for field in response_fields) assert "qop" not in digest_data assert "nc" not in digest_data assert "cnonce" not in digest_data assert digest_data["username"] == '"tomchristie"' assert digest_data["realm"] == '"*****@*****.**"' assert len(digest_data["nonce"]) == 64 + 2 # extra quotes assert digest_data["uri"] == '"/"' assert len(digest_data["response"]) == 64 + 2 assert len(digest_data["opaque"]) == 64 + 2 assert digest_data["algorithm"] == "SHA-256"
async def test_digest_auth(algorithm, expected_hash_length, expected_response_length): url = "https://example.org/" auth = DigestAuth(username="******", password="******") client = Client(dispatch=MockDigestAuthDispatch(algorithm=algorithm)) response = await client.get(url, auth=auth) assert response.status_code == 200 auth = response.json()["auth"] assert auth.startswith("Digest ") response_fields = [field.strip() for field in auth[auth.find(" ") :].split(",")] digest_data = dict(field.split("=") for field in response_fields) assert digest_data["username"] == '"tomchristie"' assert digest_data["realm"] == '"*****@*****.**"' assert "nonce" in digest_data assert digest_data["uri"] == '"/"' assert len(digest_data["response"]) == expected_response_length + 2 # extra quotes assert len(digest_data["opaque"]) == expected_hash_length + 2 assert digest_data["algorithm"] == algorithm assert digest_data["qop"] == "auth" assert digest_data["nc"] == "00000001" assert len(digest_data["cnonce"]) == 16 + 2
def request(query, params): offset = (params['pageno'] - 1) * number_of_results search_type = search_types.get(params.get('category'), '0') params['url'] = base_url +\ search_url.format(query=urlencode({'query': query}), offset=offset, limit=number_of_results, search_type=search_type) if http_digest_auth_user and http_digest_auth_pass: params['auth'] = DigestAuth(http_digest_auth_user, http_digest_auth_pass) # add language tag if specified if params['language'] != 'all': params['url'] += '&lr=lang_' + params['language'].split('-')[0] return params
async def read(self, sensors): """Returns necessary sensors from Sunways inverter""" try: print("ciao") #async with requests.Session() as session: current_url = self.url print(current_url) async with httpx.Client(auth = DigestAuth(username=self.username, password=self.password), timeout=2) as session: data = await session.get(current_url) # async with session.get(current_url, auth=HTTPDigestAuth(self.username, self.password), timeout=5) as response: #async with session.get(current_url) as response: # data = await response.text() # data="0.04 kW#0.2#226.3#0.1#350.3#---#---#10.42#138.2#2010.7#16147.1#4#0#0#0#" # if len(data.split(#)) > 15 : print(data.text) power, netCurrent, netVoltage, genCurrent, \ genVoltage, Temperature, irradiation, dayEnergy, \ monthEnergy, yearEnergy, totalEnergy, stat, err, \ warning, type, val5 = data.text.split('#') for sen in sensors: if sen.name == "current_power": sen.value = eval( "{0}{1}".format(power[:-2], sen.factor) ) else: if sen.name == "grid_current": sen.value = eval( "{0}{1}".format(netCurrent, sen.factor) ) else: if sen.name == "generator_current": sen.value = eval( "{0}{1}".format(genCurrent, sen.factor) ) else: if sen.name == "grid_voltage": sen.value = eval( "{0}{1}".format(netVoltage, sen.factor) ) else: if sen.name == "generator_voltage": sen.value = eval( "{0}{1}".format(genVoltage, sen.factor) ) else: if sen.name == "temperature": sen.value = eval( "{0}{1}".format(Temperature, sen.factor) ) else: if sen.name == "irradiation": sen.value = eval( "{0}{1}".format(irradiation, sen.factor) ) else: if sen.name == "today_yield": sen.value = eval( "{0}{1}".format(dayEnergy, sen.factor) ) else: if sen.name == "month_yield": sen.value = eval( "{0}{1}".format(monthEnergy, sen.factor) ) else: if sen.name == "year_yield": sen.value = eval( "{0}{1}".format(yearEnergy, sen.factor) ) else: if sen.name == "total_yield": sen.value = eval( "{0}{1}".format(totalEnergy, sen.factor) ) else: if sen.name == "state_Message": sen.value = "" if err == "1": sen.value = "Error" if warning == "1": sen.value = sen.value + " | Warning" else: if warning == "1": sen.value = "Warnig" else: if sen.name == "state_OutputMode": sen.value = "" if stat & 0x80: sen.value = "MPPT" if stat & 0x20: if len(sen): sen.value= sen.value + " | " sen.value = sen.value + "DC Current limitation" if stat & 0x400: if len(sen): sen.value= sen.value + " | " sen.value = sen.value + "AC Current limitation" if stat & 0x40: if len(sen): sen.value= sen.value + " | " sen.value = sen.value + "AC Output limitation" if stat & 0x200: if len(sen): sen.value= sen.value + " | " sen.value = sen.value + "Temperature limitation" else: if sen.name == "state_OutputMode": sen.value = "" if stat & 0x10: sen.value = "Start" if stat & 0x4: if len(sen): sen.value = sen.value + " | " sen.value = sen.value + "Feed" if stat & 0x8: if len(sen): sen.value = sen.value + " | " sen.value = sen.value + "Night" if stat & 0x1000: if len(sen): sen.value = sen.value + " | " sen.value = sen.value + "Test active" else: raise KeyError sen.date = date.today() _LOGGER.debug("Got new value for sensor %s: %s", sen.name, sen.value) return True except httpx.exceptions.ConnectTimeout : # Connection to inverter not possible. # This can be "normal" - so warning instead of error - as Sunways # inverters auto switch off after the sun # has set. _LOGGER.warning("Connection to Sunways inverter is not possible. " + "The inverter may be offline due to darkness. " + "Otherwise check host/ip address.") return False except httpx.exceptions.HTTPError as err: # 401 Unauthorized: wrong username/password if err.status == 401: raise UnauthorizedException(err) else: raise UnexpectedResponseException(err) except KeyError: # requested sensor not supported raise UnexpectedResponseException( str.format("Sunways sensor key {0} not found, inverter not " + "compatible?", sen.key) )