Erster Stand der Hintergrundprozesse, die auf der Synology unter /volume1/homes/wagner/SolarManager laufen: der Manager selbst, die Sammler je Geraet, die MQTT-Bruecke, der Wecker und - neu hinzugezogen - der AutoAction-Runner, der als Hintergrundprozess hierher gehoert und nicht ins Web-Verzeichnis. Zugangsdaten stehen nicht mehr im Quelltext, sondern in config.ini, die nicht mit eingecheckt wird. Vorlage ist config.ini.example, gelesen wird sie von konfig.py. Betroffen waren solarManager.py (Datenbank und Wattpilot), zeit.py, gatherWaterData.py, wecker.py und skoda_testdaten.py, das sich das Passwort bisher aus dem Quelltext eines anderen Moduls herausgesucht hat. Die Kia-Anbindung ist mit dem Fahrzeug entfallen: kiaTest.py, gatherCarData.py und hyundai_kia_connect_api sind nicht mehr dabei, ebenso gatherInverterData.py, auf das nur noch eine auskommentierte Zeile zeigte. Die mitgelieferten Bibliotheken bleiben im Repository - die NAS hat kein pip, sie muessen neben den Skripten liegen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
106 lines
2.6 KiB
Python
106 lines
2.6 KiB
Python
"""Low-level http related exceptions."""
|
|
|
|
|
|
from textwrap import indent
|
|
from typing import Optional, Union
|
|
|
|
from .typedefs import _CIMultiDict
|
|
|
|
__all__ = ("HttpProcessingError",)
|
|
|
|
|
|
class HttpProcessingError(Exception):
|
|
"""HTTP error.
|
|
|
|
Shortcut for raising HTTP errors with custom code, message and headers.
|
|
|
|
code: HTTP Error code.
|
|
message: (optional) Error message.
|
|
headers: (optional) Headers to be sent in response, a list of pairs
|
|
"""
|
|
|
|
code = 0
|
|
message = ""
|
|
headers = None
|
|
|
|
def __init__(
|
|
self,
|
|
*,
|
|
code: Optional[int] = None,
|
|
message: str = "",
|
|
headers: Optional[_CIMultiDict] = None,
|
|
) -> None:
|
|
if code is not None:
|
|
self.code = code
|
|
self.headers = headers
|
|
self.message = message
|
|
|
|
def __str__(self) -> str:
|
|
msg = indent(self.message, " ")
|
|
return f"{self.code}, message:\n{msg}"
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<{self.__class__.__name__}: {self.code}, message={self.message!r}>"
|
|
|
|
|
|
class BadHttpMessage(HttpProcessingError):
|
|
code = 400
|
|
message = "Bad Request"
|
|
|
|
def __init__(self, message: str, *, headers: Optional[_CIMultiDict] = None) -> None:
|
|
super().__init__(message=message, headers=headers)
|
|
self.args = (message,)
|
|
|
|
|
|
class HttpBadRequest(BadHttpMessage):
|
|
code = 400
|
|
message = "Bad Request"
|
|
|
|
|
|
class PayloadEncodingError(BadHttpMessage):
|
|
"""Base class for payload errors"""
|
|
|
|
|
|
class ContentEncodingError(PayloadEncodingError):
|
|
"""Content encoding error."""
|
|
|
|
|
|
class TransferEncodingError(PayloadEncodingError):
|
|
"""transfer encoding error."""
|
|
|
|
|
|
class ContentLengthError(PayloadEncodingError):
|
|
"""Not enough data for satisfy content length header."""
|
|
|
|
|
|
class LineTooLong(BadHttpMessage):
|
|
def __init__(
|
|
self, line: str, limit: str = "Unknown", actual_size: str = "Unknown"
|
|
) -> None:
|
|
super().__init__(
|
|
f"Got more than {limit} bytes ({actual_size}) when reading {line}."
|
|
)
|
|
self.args = (line, limit, actual_size)
|
|
|
|
|
|
class InvalidHeader(BadHttpMessage):
|
|
def __init__(self, hdr: Union[bytes, str]) -> None:
|
|
if isinstance(hdr, bytes):
|
|
hdr = hdr.decode("utf-8", "surrogateescape")
|
|
super().__init__(f"Invalid HTTP Header: {hdr}")
|
|
self.hdr = hdr
|
|
self.args = (hdr,)
|
|
|
|
|
|
class BadStatusLine(BadHttpMessage):
|
|
def __init__(self, line: str = "") -> None:
|
|
if not isinstance(line, str):
|
|
line = repr(line)
|
|
super().__init__(f"Bad status line {line!r}")
|
|
self.args = (line,)
|
|
self.line = line
|
|
|
|
|
|
class InvalidURLError(BadHttpMessage):
|
|
pass
|