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
« 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######################################################################
9"""
10Perforce _P4OOSpecObj object
12P4OO._SpecObj provides common behaviors for all P4OO Spec-based
13objects.
14"""
16import json
17import datetime
18from dataclasses import dataclass, field
19from P4OO._Base import _P4OOBase
20from P4OO.Exceptions import P4OOFatal
23class DateTimeJSONEncoder(json.JSONEncoder):
24 """ JSON Encoder subclass for _toJSON to leverage """
26 def default(self, o):
27 if isinstance(o, datetime.datetime):
28 return o.isoformat()
30 return super().default(o)
32@dataclass(unsafe_hash=True)
33class _P4OOSpecObj(_P4OOBase):
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)
39 # Subclasses must define SPECOBJ_TYPE
40 _SPECOBJ_TYPE = None
42 def _uniqueID(self):
43 """ _uniqueID overrides the _Base definition to use
44 self._getSpecID() instead
45 """
47 return self._getSpecID()
49 def _getSpecID(self):
51 specID = self.id
53 if specID is None:
54 self.__initialize()
55 specID = self.id
57 # If specID is still undef, oh well.
58 return specID
60 def _getSpecAttr(self, attrName):
62 self.__initialize()
64 modifiedSpec = self._modifiedSpec
66 # Allow the caller to use any case for the spec attribute
67 lcAttrName = attrName.lower()
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))
74 return modifiedSpec[lcAttrName]
76 def _setSpecAttr(self, attrName, value):
77# self.__initialize()
79 # Allow caller to create a new spec this way
80 if self._modifiedSpec is None:
81 self._modifiedSpec = {}
83 modifiedSpec = self._modifiedSpec
85 # Allow the caller to use any case for the spec attribute
86 lcAttrName = attrName.lower()
87 modifiedSpec[lcAttrName] = value
88 return value
90 def _delSpecAttr(self, attrName):
91 self.__initialize()
93 modifiedSpec = self._modifiedSpec
95 # Allow the caller to use any case for the spec attribute
96 lcAttrName = attrName.lower()
98 value = None
99 if lcAttrName in modifiedSpec:
100 value = modifiedSpec[lcAttrName]
101 modifiedSpec[lcAttrName] = None
103 return value
105 def saveSpec(self, force=False):
106 p4ConnObj = self._getP4Connection()
107 return p4ConnObj.saveSpec(self, force)
109 def deleteSpec(self, force=False):
110 p4ConnObj = self._getP4Connection()
111 return p4ConnObj.deleteSpec(self, force)
113 def _toJSON(self):
114 self.__initialize()
116 return DateTimeJSONEncoder().encode(self._modifiedSpec)
118 ######################################################################
119 # Internal (private) methods
120 #
121 def __initialize(self):
123 if self._p4SpecObj is None:
124 p4ConnObj = self._getP4Connection()
126 self._p4SpecObj = p4ConnObj.readSpec(self)
128 return self._p4SpecObj