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

1"""Mixin for mapping set/getattr to self.set/get""" 

2 

3# Copyright (C) PyZMQ Developers 

4# Distributed under the terms of the Modified BSD License. 

5 

6import errno 

7from typing import TypeVar, Union 

8 

9from .. import constants 

10 

11T = TypeVar("T") 

12OptValT = Union[str, bytes, int] 

13 

14 

15class AttributeSetter: 

16 def __setattr__(self, key: str, value: OptValT) -> None: 

17 """set zmq options by attribute""" 

18 

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 

27 

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) 

37 

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) 

41 

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 

53 

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 

64 

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) 

68 

69 def get(self, opt: int) -> OptValT: 

70 """Override in subclass""" 

71 raise NotImplementedError("override in subclass") 

72 

73 def set(self, opt: int, val: OptValT) -> None: 

74 """Override in subclass""" 

75 raise NotImplementedError("override in subclass") 

76 

77 

78__all__ = ['AttributeSetter']