Coverage for src/P4OO/_SpecObj.py: 95%

63 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2024-09-07 17:17 +0000

1###################################################################### 

2# Copyright (c)2011-2012,2024 David L. Armstrong. 

3# Copyright (c)2012-2013, Cisco Systems, Inc. 

4# 

5# P4OO._SpecObj.py 

6# 

7###################################################################### 

8 

9""" 

10Perforce _P4OOSpecObj object 

11 

12P4OO._SpecObj provides common behaviors for all P4OO Spec-based 

13objects. 

14""" 

15 

16import json 

17import datetime 

18from dataclasses import dataclass, field 

19from P4OO._Base import _P4OOBase 

20from P4OO.Exceptions import P4OOFatal 

21 

22 

23class DateTimeJSONEncoder(json.JSONEncoder): 

24 """ JSON Encoder subclass for _toJSON to leverage """ 

25 

26 def default(self, o): 

27 if isinstance(o, datetime.datetime): 

28 return o.isoformat() 

29 

30 return super().default(o) 

31 

32@dataclass(unsafe_hash=True) 

33class _P4OOSpecObj(_P4OOBase): 

34 

35 id: str = field(default=None, compare=True) 

36 _modifiedSpec: dict = field(default=None, compare=False, repr=False) 

37 _p4SpecObj: dict = field(default=None, compare=False, repr=False) 

38 

39 # Subclasses must define SPECOBJ_TYPE 

40 _SPECOBJ_TYPE = None 

41 

42 def _uniqueID(self): 

43 """ _uniqueID overrides the _Base definition to use 

44 self._getSpecID() instead 

45 """ 

46 

47 return self._getSpecID() 

48 

49 def _getSpecID(self): 

50 

51 specID = self.id 

52 

53 if specID is None: 

54 self.__initialize() 

55 specID = self.id 

56 

57 # If specID is still undef, oh well. 

58 return specID 

59 

60 def _getSpecAttr(self, attrName): 

61 

62 self.__initialize() 

63 

64 modifiedSpec = self._modifiedSpec 

65 

66 # Allow the caller to use any case for the spec attribute 

67 lcAttrName = attrName.lower() 

68 

69 if lcAttrName not in modifiedSpec: 

70 specType = self._SPECOBJ_TYPE 

71 raise P4OOFatal("Invalid Spec attribute \"%s\" for type \"%s\"\n" 

72 % (lcAttrName, specType)) 

73 

74 return modifiedSpec[lcAttrName] 

75 

76 def _setSpecAttr(self, attrName, value): 

77# self.__initialize() 

78 

79 # Allow caller to create a new spec this way 

80 if self._modifiedSpec is None: 

81 self._modifiedSpec = {} 

82 

83 modifiedSpec = self._modifiedSpec 

84 

85 # Allow the caller to use any case for the spec attribute 

86 lcAttrName = attrName.lower() 

87 modifiedSpec[lcAttrName] = value 

88 return value 

89 

90 def _delSpecAttr(self, attrName): 

91 self.__initialize() 

92 

93 modifiedSpec = self._modifiedSpec 

94 

95 # Allow the caller to use any case for the spec attribute 

96 lcAttrName = attrName.lower() 

97 

98 value = None 

99 if lcAttrName in modifiedSpec: 

100 value = modifiedSpec[lcAttrName] 

101 modifiedSpec[lcAttrName] = None 

102 

103 return value 

104 

105 def saveSpec(self, force=False): 

106 p4ConnObj = self._getP4Connection() 

107 return p4ConnObj.saveSpec(self, force) 

108 

109 def deleteSpec(self, force=False): 

110 p4ConnObj = self._getP4Connection() 

111 return p4ConnObj.deleteSpec(self, force) 

112 

113 def _toJSON(self): 

114 self.__initialize() 

115 

116 return DateTimeJSONEncoder().encode(self._modifiedSpec) 

117 

118 ###################################################################### 

119 # Internal (private) methods 

120 # 

121 def __initialize(self): 

122 

123 if self._p4SpecObj is None: 

124 p4ConnObj = self._getP4Connection() 

125 

126 self._p4SpecObj = p4ConnObj.readSpec(self) 

127 

128 return self._p4SpecObj