Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/zmq/sugar/attrsettr.py: 31%
42 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-01 06:54 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-01 06:54 +0000
1"""Mixin for mapping set/getattr to self.set/get"""
3# Copyright (C) PyZMQ Developers
4# Distributed under the terms of the Modified BSD License.
6import errno
7from typing import TypeVar, Union
9from .. import constants
11T = TypeVar("T")
12OptValT = Union[str, bytes, int]
15class AttributeSetter:
16 def __setattr__(self, key: str, value: OptValT) -> None:
17 """set zmq options by attribute"""
19 if key in self.__dict__:
20 object.__setattr__(self, key, value)
21 return
22 # regular setattr only allowed for class-defined attributes
23 for cls in self.__class__.mro():
24 if key in cls.__dict__ or key in getattr(cls, "__annotations__", {}):
25 object.__setattr__(self, key, value)
26 return
28 upper_key = key.upper()
29 try:
30 opt = getattr(constants, upper_key)
31 except AttributeError:
32 raise AttributeError(
33 f"{self.__class__.__name__} has no such option: {upper_key}"
34 )
35 else:
36 self._set_attr_opt(upper_key, opt, value)
38 def _set_attr_opt(self, name: str, opt: int, value: OptValT) -> None:
39 """override if setattr should do something other than call self.set"""
40 self.set(opt, value)
42 def __getattr__(self, key: str) -> OptValT:
43 """get zmq options by attribute"""
44 upper_key = key.upper()
45 try:
46 opt = getattr(constants, upper_key)
47 except AttributeError:
48 raise AttributeError(
49 f"{self.__class__.__name__} has no such option: {upper_key}"
50 ) from None
51 else:
52 from zmq import ZMQError
54 try:
55 return self._get_attr_opt(upper_key, opt)
56 except ZMQError as e:
57 # EINVAL will be raised on access for write-only attributes.
58 # Turn that into an AttributeError
59 # necessary for mocking
60 if e.errno in {errno.EINVAL, errno.EFAULT}:
61 raise AttributeError(f"{key} attribute is write-only")
62 else:
63 raise
65 def _get_attr_opt(self, name, opt) -> OptValT:
66 """override if getattr should do something other than call self.get"""
67 return self.get(opt)
69 def get(self, opt: int) -> OptValT:
70 """Override in subclass"""
71 raise NotImplementedError("override in subclass")
73 def set(self, opt: int, val: OptValT) -> None:
74 """Override in subclass"""
75 raise NotImplementedError("override in subclass")
78__all__ = ['AttributeSetter']