Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/zmq/sugar/attrsettr.py: 33%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
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.
5from __future__ import annotations
7import errno
8from typing import TypeVar, Union
10from .. import constants
12T = TypeVar("T")
13OptValT = Union[str, bytes, int]
16class AttributeSetter:
17 def __setattr__(self, key: str, value: OptValT) -> None:
18 """set zmq options by attribute"""
20 if key in self.__dict__:
21 object.__setattr__(self, key, value)
22 return
23 # regular setattr only allowed for class-defined attributes
24 for cls in self.__class__.mro():
25 if key in cls.__dict__ or key in getattr(cls, "__annotations__", {}):
26 object.__setattr__(self, key, value)
27 return
29 upper_key = key.upper()
30 try:
31 opt = getattr(constants, upper_key)
32 except AttributeError:
33 raise AttributeError(
34 f"{self.__class__.__name__} has no such option: {upper_key}"
35 )
36 else:
37 self._set_attr_opt(upper_key, opt, value)
39 def _set_attr_opt(self, name: str, opt: int, value: OptValT) -> None:
40 """override if setattr should do something other than call self.set"""
41 self.set(opt, value)
43 def __getattr__(self, key: str) -> OptValT:
44 """get zmq options by attribute"""
45 upper_key = key.upper()
46 try:
47 opt = getattr(constants, upper_key)
48 except AttributeError:
49 raise AttributeError(
50 f"{self.__class__.__name__} has no such option: {upper_key}"
51 ) from None
52 else:
53 from zmq import ZMQError
55 try:
56 return self._get_attr_opt(upper_key, opt)
57 except ZMQError as e:
58 # EINVAL will be raised on access for write-only attributes.
59 # Turn that into an AttributeError
60 # necessary for mocking
61 if e.errno in {errno.EINVAL, errno.EFAULT}:
62 raise AttributeError(f"{key} attribute is write-only")
63 else:
64 raise
66 def _get_attr_opt(self, name, opt) -> OptValT:
67 """override if getattr should do something other than call self.get"""
68 return self.get(opt)
70 def get(self, opt: int) -> OptValT:
71 """Override in subclass"""
72 raise NotImplementedError("override in subclass")
74 def set(self, opt: int, val: OptValT) -> None:
75 """Override in subclass"""
76 raise NotImplementedError("override in subclass")
79__all__ = ['AttributeSetter']