diff --git a/README.rst b/README.rst index 17b405c..fdda162 100644 --- a/README.rst +++ b/README.rst @@ -26,8 +26,8 @@ Add ``ua-parser[regex]`` to your project's dependencies, or run to install in the current environment. -ua-parser supports CPython 3.9 and newer, recent pypy (supporting -3.10), and GraalPy 24. +ua-parser supports CPython 3.10 and newer, recent pypy (supporting +3.10), and GraalPy 25. .. note:: diff --git a/src/ua_parser/core.py b/src/ua_parser/core.py index b7133d4..88ad5c8 100644 --- a/src/ua_parser/core.py +++ b/src/ua_parser/core.py @@ -16,78 +16,37 @@ ] -@dataclass(frozen=True) +@dataclass(frozen=True, slots=True) class UserAgent: """Browser ("user agent" aka the software responsible for the request) information parsed from the user agent string. """ - __slots__ = ("family", "major", "minor", "patch", "patch_minor") - family: str - major: Optional[str] - minor: Optional[str] - patch: Optional[str] - patch_minor: Optional[str] - - def __init__( - self, - family: str = "Other", - major: Optional[str] = None, - minor: Optional[str] = None, - patch: Optional[str] = None, - patch_minor: Optional[str] = None, - ) -> None: - object.__setattr__(self, "family", family) - object.__setattr__(self, "major", major) - object.__setattr__(self, "minor", minor) - object.__setattr__(self, "patch", patch) - object.__setattr__(self, "patch_minor", patch_minor) - - -@dataclass(frozen=True) + family: str = "Other" + major: Optional[str] = None + minor: Optional[str] = None + patch: Optional[str] = None + patch_minor: Optional[str] = None + + +@dataclass(frozen=True, slots=True) class OS: """OS information parsed from the user agent string.""" - __slots__ = ("family", "major", "minor", "patch", "patch_minor") - family: str - major: Optional[str] - minor: Optional[str] - patch: Optional[str] - patch_minor: Optional[str] - - def __init__( - self, - family: str = "Other", - major: Optional[str] = None, - minor: Optional[str] = None, - patch: Optional[str] = None, - patch_minor: Optional[str] = None, - ) -> None: - object.__setattr__(self, "family", family) - object.__setattr__(self, "major", major) - object.__setattr__(self, "minor", minor) - object.__setattr__(self, "patch", patch) - object.__setattr__(self, "patch_minor", patch_minor) - - -@dataclass(frozen=True) + family: str = "Other" + major: Optional[str] = None + minor: Optional[str] = None + patch: Optional[str] = None + patch_minor: Optional[str] = None + + +@dataclass(frozen=True, slots=True) class Device: """Device information parsed from the user agent string.""" - __slots__ = ("brand", "family", "model") - family: str - brand: Optional[str] - model: Optional[str] - - def __init__( - self, - family: str = "Other", - brand: Optional[str] = None, - model: Optional[str] = None, - ) -> None: - object.__setattr__(self, "family", family) - object.__setattr__(self, "brand", brand) - object.__setattr__(self, "model", model) + family: str = "Other" + brand: Optional[str] = None + model: Optional[str] = None class Domain(Flag): @@ -105,7 +64,7 @@ class Domain(Flag): ALL = USER_AGENT | OS | DEVICE -@dataclass(frozen=True) +@dataclass(frozen=True, slots=True) class DefaultedResult: """Variant of :class:`Result` where attributes are set to a default value if their resolution failed. @@ -120,7 +79,7 @@ class DefaultedResult: string: str -@dataclass(frozen=True) +@dataclass(frozen=True, slots=True) class Result: """Complete result. @@ -152,7 +111,7 @@ def with_defaults(self) -> DefaultedResult: ) -@dataclass(frozen=True) +@dataclass(frozen=True, slots=True) class PartialResult: """Potentially partial (incomplete) result. @@ -172,7 +131,6 @@ class PartialResult: """ - __slots__ = ("device", "domains", "os", "string", "user_agent") domains: Domain user_agent: Optional[UserAgent] os: Optional[OS]