ATLAS Offline Software
Loading...
Searching...
No Matches
python.db.DefectsDB Class Reference
Inheritance diagram for python.db.DefectsDB:
Collaboration diagram for python.db.DefectsDB:

Public Types

typedef HLT::TypeInformation::for_each_type_c< typenameEDMLIST::map, my_functor, my_result<>, my_arg< HLT::TypeInformation::get_cont, CONTAINER > >::type result

Public Member Functions

None __init__ (self, str connection_string=DEFAULT_CONNECTION_STRING, bool read_only=True, bool create=False, Union[str, Tuple] tag="HEAD")
None __del__ (self)
None create_defect (self, str name, str description)
IOVSet retrieve (self, Optional[Union[int, Tuple[int, int], RunLumi]] since=None, Optional[Union[int, Tuple[int, int], RunLumi]] until=None, Optional[Iterable[Union[str, int]]] channels=None, bool nonpresent=False, bool primary_only=False, Optional[Collection[str]] ignore=None, bool with_primary_dependencies=False, bool intersect=False, bool with_time=False, bool evaluate_full=True)
 storage_buffer (self)
None insert (self, Union[str, int] defect_id, int since, int until, str comment, str added_by, bool present=True, bool recoverable=False)
 insert_multiple (self, Iterable[IOVType] defect_list, str tag='HEAD', bool use_flask=False, str flask_cool_target='oracle://ATONR_COOLOFL_GPN/ATLAS_COOLOFL_GLOBAL', Mapping[str, str] flask_auth={}, str flask_db='CONDBR2', str flask_uri='https://cool-proxy-app.cern.ch/cool/multi_iovs')
None validate_clauses (self, str clauses)
None update_virtual_defect (self, str defect_name, str clauses, Optional[str] comment=None)
None rename_defect (self, str defect_name, str new_defect_name)
int new_virtual_defect (self, str defect_name, Optional[str] comment, str clauses)
Set[str] resolve_primary_defects (self, Iterable[DefectLogic] defect_logics)
Mapping[str, DefectLogic] virtual_defect_logics (self)
 get_intolerable_defects (self, bool old_primary_only=True, Sequence[str] exclude=['TIGHT', 'IDTIGHT', 'PHYS_.*'])
bool logics_tag_valid (self)
List[str] defects_tags (self)
str next_logics_tag (self)
str new_hierarchical_tag (self, str defects_tag, str logics_tag)
bool defects_tag_valid (self)
None check_tag_validity (self)
str defects_tag (self)
tagtype tag (self)
List[str] tags (self)
str new_logics_tag (self, str description="")
str new_defects_tag (self, str name, str description, Optional[Iterable] iovranges=None)
cool.IFolderSet parent_folderset (self)
cool.IFolder defects_folder (self)
cool.IFolder defect_logic_folder (self)
Set[int] virtual_defect_ids (self)
Set[str] defect_names (self)
Set[str] virtual_defect_names (self)
Set[int] defect_ids (self)
MutableMapping[Union[str, int], Union[str, int]] defect_id_map (self)
MutableMapping[Union[str, int], Union[str, int]] virtual_defect_id_map (self)
int defect_chan_as_id (self, Union[str, int] channel, bool primary_only=False)
List[int] defect_names_as_ids (self, Iterable[Union[str, int]] channels)
Tuple[Set[int], Set[str], Mapping[Union[str, int], Union[str, int]]] get_channels (self)
Tuple[Set[int], Set[str], Mapping[Union[str, int], Union[str, int]]] get_virtual_channels (self)
MutableMapping[Union[str, int], str] get_channel_descriptions (self, Iterable[Union[str, int]] channels)
MutableMapping[Union[str, int], str] get_virtual_channel_descriptions (self, Iterable[Union[str, int]] channels)
Mapping[Union[str, int], str] all_defect_descriptions (self)
None set_channel_description (self, Union[str, int] channel, str description)
bool defect_is_virtual (self, Union[str, int] defect_id)
Union[str, List[str]] normalize_defect_names (self, Union[str, Iterable[str]] defect_id)

Public Attributes

 connection_string = connection_string
str logics_tag = "HEAD", NONHEAD_MODIFICATION_MSG
 logics_tags
 logics_tag_valid
 virtual_defect_ids
 defect_names
 virtual_defect_names
 defect_ids

Protected Member Functions

None _create_defect_with_id (self, int did, str name, str description)
None _insert_iov (self, IOVType iov, str tag)
None _insert (self, Union[str, int] defect_id, Union[int, Tuple[int, int], RunLumi] since, Union[int, Tuple[int, int], RunLumi] until, str comment, str added_by, bool present=True, bool recoverable=False, str tag='HEAD')
 _insert_multiple_flask (self, Iterable[IOVType] defect_list, str tag, str flask_cool_target, Mapping[str, str] flask_auth, str flask_db, str flask_uri)
None _update_virtual_defect (self, str defect_name, str clauses, Optional[str] comment=None, Optional[str] tag=None)
List[DefectLogic] _resolve_evaluation_order (self, Optional[Iterable[str]] defects=None)
Mapping[str, DefectLogic] _get_virtual_defect_logics (self, str tag)
bool _virtual_defect_consistency_check (self)
None _tag_head_and_lock (self, cool.IFolder folder, str name, str description)
None _clear_connections (self)
Tuple[cool.IFolder, cool.Record] _load_folder (self, folder, create_function)
None _load_defects_folder (self)
cool.IFolder _create_defects_folder (self, cool.IDatabase db)
None _load_defect_logic_folder (self)
cool.IFolder _create_defect_logic_folder (self, cool.IDatabase db)
None _populate_defect_ids (self)
None _populate_virtual_defect_ids (self)
None _new_defect (self, int did, str dname)
None _new_virtual_defect (self, int did, str dname)

Protected Attributes

bool _bad_state = False
Mapping[str, DefectLogic] _virtual_defect_logics = None
 _read_only
 _defect_logic_payload
 _virtual_defect_names = set()
dict _virtual_defect_id_map = {}
bool _virtual_initialized = False
 _defect_names = set()
dict _defect_id_map = {}
bool _initialized = False
 _tag
 _defects_folder = None
 _defect_logic_folder = None
 _parent_folderset = None
list _connections = []
 _create
 _defect_payload = res
Set[int] _defect_ids = set()
Set[int] _virtual_defect_ids = set()
dict _virtual_defect_map = {}

Detailed Description

Implementation is split into mixins.

    DefectsDBIDsNamesMixin:
        Defines functions for dealing with defect IDs
    
    DefectsDBFolderMixin:
        Logic for loading or creating the COOL folder/database
    
    DefectsDBFoldersMixin:
        Functions for managing tags
    
    DefectsDBVirtualDefectsMixin:
        Internal code for managing and computing virutal defects
        
Public interface is nominally defined in this class (DefectsDB).

Definition at line 36 of file DQDefects/python/db.py.

Member Typedef Documentation

◆ result

Definition at line 90 of file EDM_MasterSearch.h.

Constructor & Destructor Documentation

◆ __init__()

None python.db.DefectsDB.__init__ ( self,
str connection_string = DEFAULT_CONNECTION_STRING,
bool read_only = True,
bool create = False,
Union[str, Tuple] tag = "HEAD" )
Create a new DefectsDB instance.

The COOL folder resides at `DEFECTS_FOLDER`, which is a module-level
varaiable in this module.

Parameters:
    `connection_string` : A COOL connection string, or a string ending 
                          in .db. In the latter case, the database is
                          assumed to be a sqlite database at that path.
    `read_only` : Indicates whether insertions will be disallowed on
                  this connection. (Default: True)
    `create`    : If True, attempt to create the database if it doesn't
                  exist. (Default: False)
    `tag`       : The COOL tag(s) to use.  Either a single string used
                  for both defects and virtual defect logic, or a
                  2-tuple (defecttag, logictag).  The default is to
                  use HEAD for both defects and logic.  Either
                  folder-level or hierarchical tags can be given.

Definition at line 59 of file DQDefects/python/db.py.

60 read_only: bool = True, create: bool = False, tag: Union[str, Tuple] = "HEAD") -> None:
61 """
62 Create a new DefectsDB instance.
63
64 The COOL folder resides at `DEFECTS_FOLDER`, which is a module-level
65 varaiable in this module.
66
67 Parameters:
68 `connection_string` : A COOL connection string, or a string ending
69 in .db. In the latter case, the database is
70 assumed to be a sqlite database at that path.
71 `read_only` : Indicates whether insertions will be disallowed on
72 this connection. (Default: True)
73 `create` : If True, attempt to create the database if it doesn't
74 exist. (Default: False)
75 `tag` : The COOL tag(s) to use. Either a single string used
76 for both defects and virtual defect logic, or a
77 2-tuple (defecttag, logictag). The default is to
78 use HEAD for both defects and logic. Either
79 folder-level or hierarchical tags can be given.
80 """
81 self.connection_string = connection_string
82 self._read_only = read_only
83 self._create = create
84 if isinstance(tag, str):
85 self._tag = tagtype(tag, tag) if tag else tagtype("HEAD", "HEAD")
86 else:
87 try:
88 tag = tagtype._make(tag)
89 except Exception:
90 raise TypeError('tag argument must be a 2-element sequence')
91 if len(tag) != 2:
92 raise TypeError('tag argument must be a 2-element sequence')
93 self._tag = tag
94 self._tag = tagtype(self._tag[0],
95 self._tag[1])
96
97 # COOL has no way of emptying a storage buffer. Creating a new storage
98 # buffer flushes the old one. Therefore, if an exception happens
99 # halfway through setting up a storage buffer, subsequent operations
100 # risk flushing a half-completed operation. In that case, we refuse to
101 # do any more write operations with that database connection.
102 self._bad_state = False
103
104 super(DefectsDB, self).__init__()
105
106 if create:
107 # Trigger creation of folders through properties
108 self.defects_folder
109 self.defect_logic_folder
110

◆ __del__()

None python.db.DefectsDB.__del__ ( self)
Ideally we would use inheritance to call destructors, but this isn't 
possible in the general case with the way we (ab)use mixins, so we just 
do it here.

Definition at line 111 of file DQDefects/python/db.py.

111 def __del__(self) -> None:
112 """
113 Ideally we would use inheritance to call destructors, but this isn't
114 possible in the general case with the way we (ab)use mixins, so we just
115 do it here.
116 """
117 self._clear_connections()
118

Member Function Documentation

◆ _clear_connections()

None python.folders.DefectsDBFoldersMixin._clear_connections ( self)
protectedinherited

Definition at line 29 of file folders.py.

29 def _clear_connections(self) -> None:
30 log.debug("DefectsDB connections cleared")
31 for connection in self._connections:
32 connection.closeDatabase()
33 self._connections = []
34

◆ _create_defect_logic_folder()

cool.IFolder python.folders.DefectsDBFoldersMixin._create_defect_logic_folder ( self,
cool.IDatabase db )
protectedinherited
Creates the COOL database/folder for virtual defect logic, if they don't exist.
Internal - use create=True in the constructor to create the COOL folder.

Definition at line 115 of file folders.py.

115 def _create_defect_logic_folder(self, db: cool.IDatabase) -> cool.IFolder:
116 """
117 Creates the COOL database/folder for virtual defect logic, if they don't exist.
118 Internal - use create=True in the constructor to create the COOL folder.
119 """
120 log.info("Creating defect logic folder")
121
122 record_spec = cool.RecordSpecification()
123 record_spec.extend("clauses", ST.String4k)
124
125 folder_spec = cool.FolderSpecification(FV.MULTI_VERSION, record_spec)
126 return db.createFolder(DEFECT_LOGIC_FOLDER, folder_spec,
127 DEFECT_LOGIC_FOLDER_DESC, True)

◆ _create_defect_with_id()

None python.db.DefectsDB._create_defect_with_id ( self,
int did,
str name,
str description )
protected
Create a new type of defect, specifying the defect ID.
See also: `create_defect`, `new_system_defect`.

Parameters:
    `did` : defect_id
    `name` : name of the defect
    `description` : a human-readable description of the defect

Definition at line 134 of file DQDefects/python/db.py.

134 def _create_defect_with_id(self, did: int, name: str, description: str) -> None:
135 """
136 Create a new type of defect, specifying the defect ID.
137 See also: `create_defect`, `new_system_defect`.
138
139 Parameters:
140 `did` : defect_id
141 `name` : name of the defect
142 `description` : a human-readable description of the defect
143 """
144 log.info("Creating new defect %s (0x%08x)", name, did)
145 if did in self.defect_ids: raise DefectExistsError(did)
146 try:
147 oldname = self.normalize_defect_names(name)
148 raise DefectExistsError(f'Defect {oldname} already exists')
149 except DefectUnknownError:
150 pass
151
152 self.defects_folder.createChannel(did,
153 name.encode('ascii'),
154 description.encode('utf-8'))
155 self._new_defect(did, name)
156

◆ _create_defects_folder()

cool.IFolder python.folders.DefectsDBFoldersMixin._create_defects_folder ( self,
cool.IDatabase db )
protectedinherited
Creates the COOL database/folder for defects, if they don't exist.
Internal - use create=True in the constructor to create the COOL folder.

Definition at line 82 of file folders.py.

82 def _create_defects_folder(self, db: cool.IDatabase) -> cool.IFolder:
83 """
84 Creates the COOL database/folder for defects, if they don't exist.
85 Internal - use create=True in the constructor to create the COOL folder.
86 """
87 log.info("Creating defects folder")
88
89 record_spec = cool.RecordSpecification()
90 record_spec.extend("present", ST.Bool)
91 record_spec.extend("recoverable", ST.Bool)
92 record_spec.extend("user", ST.String255)
93 record_spec.extend("comment", ST.String255)
94
95 folder_spec = cool.FolderSpecification(FV.MULTI_VERSION, record_spec)
96 return db.createFolder(DEFECTS_FOLDER, folder_spec,
97 DEFECT_FOLDER_DESC, True)
98

◆ _get_virtual_defect_logics()

Mapping[str, DefectLogic] python.virtual_mixin.DefectsDBVirtualDefectsMixin._get_virtual_defect_logics ( self,
str tag )
protectedinherited

Definition at line 232 of file virtual_mixin.py.

232 def _get_virtual_defect_logics(self, tag: str) -> Mapping[str, DefectLogic]:
233 if tag != "HEAD" and not self.defect_logic_folder.existsUserTag(tag.encode('ascii')):
234 # The tag doesn't exist, so there is nothing to fetch.
235 return {}
236
237 logics = fetch_iovs(self.defect_logic_folder, tag=tag.encode('ascii'),
238 named_channels=True)
239
240 logics = {l.channel: DefectLogic(l) for l in logics}
241
242 for _, defect_logic in logics.items():
243 defect_logic._populate(logics)
244
245 return logics
246

◆ _insert()

None python.db.DefectsDB._insert ( self,
Union[str, int] defect_id,
Union[int, Tuple[int, int], RunLumi] since,
Union[int, Tuple[int, int], RunLumi] until,
str comment,
str added_by,
bool present = True,
bool recoverable = False,
str tag = 'HEAD' )
protected
Implementation of insert, allows tag specification for internal
functions

Definition at line 326 of file DQDefects/python/db.py.

328 present: bool = True, recoverable: bool = False, tag: str = 'HEAD') -> None:
329 """
330 Implementation of insert, allows tag specification for internal
331 functions
332 """
333 assert not self._read_only, "Insertion on read-only database"
334 assert not self._bad_state, "Please see comment in DefectsDB constructor"
335
336 # Force load of defects_folder to populate _defect_payload
337 store = self.defects_folder.storeObject
338 p = self._defect_payload
339
340 p["present"] = present
341 p["recoverable"] = recoverable
342 p["user"] = added_by.encode('utf-8')
343 p["comment"] = comment.encode('utf-8')
344
345 defect_id = self.defect_chan_as_id(defect_id, True)
346
347 store(since, until, p, defect_id, tag.encode('ascii'),
348 (True if tag != 'HEAD' else False))
349

◆ _insert_iov()

None python.db.DefectsDB._insert_iov ( self,
IOVType iov,
str tag )
protected
Helper function for inserting IOV objects, since record order doesn't
match function argument order

Definition at line 318 of file DQDefects/python/db.py.

318 def _insert_iov(self, iov: IOVType, tag: str) -> None:
319 """
320 Helper function for inserting IOV objects, since record order doesn't
321 match function argument order
322 """
323 return self._insert(iov.channel, iov.since, iov.until, iov.comment,
324 iov.user, iov.present, iov.recoverable, tag)
325

◆ _insert_multiple_flask()

python.db.DefectsDB._insert_multiple_flask ( self,
Iterable[IOVType] defect_list,
str tag,
str flask_cool_target,
Mapping[str, str] flask_auth,
str flask_db,
str flask_uri )
protected

Definition at line 369 of file DQDefects/python/db.py.

374 flask_uri: str):
375 import requests
376 import json
377 import urllib.parse
378 import os
379 from DQUtils.oracle import get_authentication
380 data = {'grant_type':'client_credentials',
381 'audience': 'cool-flask-server'}
382 data.update(flask_auth)
383 auth = requests.post('https://auth.cern.ch/auth/realms/cern/api-access/token',
384 data=data
385 )
386 if not auth:
387 raise RuntimeError('Cannot authenticate to Flask server')
388 else:
389 token = auth.json()['access_token']
390 log.debug(f'auth succeeded {token}')
391 username, password = get_authentication(flask_cool_target)
392 p = urllib.parse.urlparse(flask_cool_target)
393 if not p.hostname:
394 raise ValueError(f'Cannot interpret {flask_cool_target} as a path')
395 server, schema = p.hostname.upper(), p.path[1:]
396
397 submit_map = {'cmd': 'addIov',
398 'COOLDEST': flask_cool_target,
399 'ORA_SCHEMA': schema,
400 'ORA_INST': flask_db,
401 'COOLOPTS': 'None',
402 'COOLSINST': flask_db,
403 'ORA_SRV': server,
404 'COOLXP': password,
405 'ORA_USER': username,
406 'cool_data': {
407 'folder': DEFECTS_FOLDER,
408 'description': '',
409 'tag': tag,
410 'record': {'present': 'Bool', 'recoverable': 'Bool',
411 'user': 'String255', 'comment': 'String255'},
412 'size': 0,
413 'iovs': []
414 }}
415
416 for defect in defect_list:
417 submit_map['cool_data']['iovs'].append(
418 {'channel': self.defect_chan_as_id(defect.channel, True),
419 'since': defect.since,
420 'until': defect.until,
421 'payload': {'present': defect.present,
422 'recoverable': defect.recoverable,
423 'user': defect.user,
424 'comment': defect.comment
425 }
426 }
427 )
428 submit_map['cool_data']['size'] += 1
429 r = requests.post(flask_uri,
430 headers={'Authorization': f'Bearer {token}'},
431 files={'file': ('iov.json',
432 json.dumps({'cool_multi_iov_request': submit_map}))},
433 verify=('DQM_COOL_FLASK_NOVERIFY' not in os.environ)
434 )
435 log.debug(r.content)
436 if not r or r.json()['code'] != 0:
437 raise RuntimeError(f'Unable to upload defects. Flask server returned error:\n{r.json()["message"]}')

◆ _load_defect_logic_folder()

None python.folders.DefectsDBFoldersMixin._load_defect_logic_folder ( self)
protectedinherited
Internal function for populating the self._defect_logic_folder variable

Definition at line 107 of file folders.py.

107 def _load_defect_logic_folder(self) -> None:
108 """
109 Internal function for populating the self._defect_logic_folder variable
110 """
111 res = self._load_folder(DEFECT_LOGIC_FOLDER,
112 self._create_defect_logic_folder)
113 self._defect_logic_folder, self._defect_logic_payload = res
114

◆ _load_defects_folder()

None python.folders.DefectsDBFoldersMixin._load_defects_folder ( self)
protectedinherited
Internal function for populating the self._defects_folder variable

Definition at line 74 of file folders.py.

74 def _load_defects_folder(self) -> None:
75 """
76 Internal function for populating the self._defects_folder variable
77 """
78 log.debug("Loading defects folder")
79 res = self._load_folder(DEFECTS_FOLDER, self._create_defects_folder)
80 self._defects_folder, self._defect_payload = res
81

◆ _load_folder()

Tuple[cool.IFolder, cool.Record] python.folders.DefectsDBFoldersMixin._load_folder ( self,
folder,
create_function )
protectedinherited
Internal function used to load a COOL folder

Definition at line 46 of file folders.py.

46 def _load_folder(self, folder, create_function) -> Tuple[cool.IFolder, cool.Record]:
47 """
48 Internal function used to load a COOL folder
49 """
50 db_folder_string = "%s::%s" % (self.connection_string, folder)
51
52 if not self._create:
53 create_function = None
54
55 db, folder = Databases.get_folder(db_folder_string,
56 read_only=self._read_only,
57 create_function=create_function,
58 also_db=True)
59
60 self._connections.append(db)
61
62 payload = cool.Record(folder.payloadSpecification())
63
64 return folder, payload
65

◆ _new_defect()

None python.ids.DefectsDBIDsNamesMixin._new_defect ( self,
int did,
str dname )
protectedinherited
Internal function used to keep defect IDs/names uptodate.

Definition at line 120 of file ids.py.

120 def _new_defect(self, did: int, dname: str) -> None:
121 """
122 Internal function used to keep defect IDs/names uptodate.
123 """
124 self.defect_ids.add(did)
125 self.defect_names.add(dname)
126 self.defect_id_map[did] = dname
127 self.defect_id_map[dname] = did
128
bool add(const std::string &hname, TKey *tobj)
Definition fastadd.cxx:55

◆ _new_virtual_defect()

None python.ids.DefectsDBIDsNamesMixin._new_virtual_defect ( self,
int did,
str dname )
protectedinherited
Internal function used to keep defect IDs/names uptodate.

Definition at line 129 of file ids.py.

129 def _new_virtual_defect(self, did: int, dname: str) -> None:
130 """
131 Internal function used to keep defect IDs/names uptodate.
132 """
133 self.virtual_defect_ids.add(did)
134 self.virtual_defect_names.add(dname)
135 self.virtual_defect_id_map[did] = dname
136 self.virtual_defect_id_map[dname] = did
137 # Reset this so we will reload logic later
138 self._virtual_defect_logics = None
139

◆ _populate_defect_ids()

None python.ids.DefectsDBIDsNamesMixin._populate_defect_ids ( self)
protectedinherited
Called the first time any of defect_{ids,names,id_map,etc} is called,
and populates internal variables to store the channel ids/names for the
life of the DefectsDB instance.

Definition at line 89 of file ids.py.

89 def _populate_defect_ids(self) -> None:
90 """
91 Called the first time any of defect_{ids,names,id_map,etc} is called,
92 and populates internal variables to store the channel ids/names for the
93 life of the DefectsDB instance.
94 """
95 ids, names, mapping = get_channel_ids_names(self.defects_folder)
96 self._defect_ids = set(ids)
97 self._defect_names = set(names)
98 self._defect_id_map = mapping
99
STL class.

◆ _populate_virtual_defect_ids()

None python.ids.DefectsDBIDsNamesMixin._populate_virtual_defect_ids ( self)
protectedinherited
Called the first time any of virtual_defect_{ids,names,id_map,etc} is called,
and populates internal variables to store the channel ids/names for the
life of the DefectsDB instance.

Definition at line 100 of file ids.py.

100 def _populate_virtual_defect_ids(self) -> None:
101 """
102 Called the first time any of virtual_defect_{ids,names,id_map,etc} is called,
103 and populates internal variables to store the channel ids/names for the
104 life of the DefectsDB instance.
105 """
106 _, _, mapping = get_channel_ids_names(self.defect_logic_folder)
107 try:
108 self._virtual_defect_names = set(self.virtual_defect_logics.keys())
109 self._virtual_defect_ids = set(mapping[name] for name in self._virtual_defect_names)
110 all_defects = self._virtual_defect_names | self._virtual_defect_ids
111 self._virtual_defect_id_map = dict(item for item in mapping.items()
112 if item[0] in all_defects)
113 except InvalidLogicTagError:
114 # Presumably this tag doesn't exist yet, which is ok if we're about
115 # to create some new virtual defects. ?
116 self._virtual_defect_names = set()
117 self._virtual_defect_ids = set()
118 self._virtual_defect_map = {}
119

◆ _resolve_evaluation_order()

List[DefectLogic] python.virtual_mixin.DefectsDBVirtualDefectsMixin._resolve_evaluation_order ( self,
Optional[Iterable[str]] defects = None )
protectedinherited
Returns a list of DefectLogic objects that need to be evaluated, 
in the correct order for them to be consistent.

`defects` should be a list of names

Definition at line 183 of file virtual_mixin.py.

183 def _resolve_evaluation_order(self, defects: Optional[Iterable[str]] = None) -> List[DefectLogic]:
184 """
185 Returns a list of DefectLogic objects that need to be evaluated,
186 in the correct order for them to be consistent.
187
188 `defects` should be a list of names
189 """
190 if defects is None:
191 logics = self.virtual_defect_logics.items()
192 else:
193 # flags begins as a list of names.
194 # Make it a list of logic objects instead
195 # If it is not in the logics map, the logic is not defined for the
196 # query interval and we shouldn't try to resolve it.
197
198
199 logics = [self.virtual_defect_logics[d] for d in defects]
200
201 class MasterNode(object):
202 dependencies = logics
203
204 resolved = _resolve_dependencies(MasterNode)
205 resolved.remove(MasterNode)
206 return resolved
207

◆ _tag_head_and_lock()

None python.tags.DefectsDBTagsMixin._tag_head_and_lock ( self,
cool.IFolder folder,
str name,
str description )
protectedinherited
Give the current HEAD of `folder` a new tag and lock it.

Definition at line 52 of file tags.py.

52 def _tag_head_and_lock(self, folder: cool.IFolder, name: str, description: str) -> None:
53 """
54 Give the current HEAD of `folder` a new tag and lock it.
55 """
56 LOCKED = cool.HvsTagLock.LOCKED
57 aname = name.encode('ascii')
58 folder.cloneTagAsUserTag('HEAD', aname, description.encode('utf-8'))
59 folder.setTagLockStatus(aname, LOCKED)
60

◆ _update_virtual_defect()

None python.virtual_mixin.DefectsDBVirtualDefectsMixin._update_virtual_defect ( self,
str defect_name,
str clauses,
Optional[str] comment = None,
Optional[str] tag = None )
protectedinherited

Definition at line 62 of file virtual_mixin.py.

63 comment: Optional[str] = None, tag: Optional[str] = None) -> None:
64 defect_id = self.defect_chan_as_id(defect_name)
65
66 assert self.defect_is_virtual(defect_id), ("Tried to update nonvirtual"
67 " defect with update_virtual_defect()")
68
69 self.validate_clauses(clauses)
70
71 tag = tag if tag is not None else 'HEAD'
72 ucomment = comment.encode('utf-8') if comment is not None else None
73
74 self._defect_logic_payload["clauses"] = clauses.encode('ascii')
75
76 store = self.defect_logic_folder.storeObject
77 store(0, 2**63-1, self._defect_logic_payload, defect_id, tag.encode('ascii'),
78 (True if tag != 'HEAD' else False))
79
80 if comment is not None:
81 self.defect_logic_folder.setChannelDescription(defect_id, ucomment)
82

◆ _virtual_defect_consistency_check()

bool python.virtual_mixin.DefectsDBVirtualDefectsMixin._virtual_defect_consistency_check ( self)
protectedinherited
When called, uses an assertion to check that there are no missing 
defects. This is a database consistency check which should never be
violated (but was when DQDefects was new).

Definition at line 265 of file virtual_mixin.py.

265 def _virtual_defect_consistency_check(self) -> bool:
266 """
267 When called, uses an assertion to check that there are no missing
268 defects. This is a database consistency check which should never be
269 violated (but was when DQDefects was new).
270 """
271 all_defects = self.defect_names | self.virtual_defect_names
272 used_defects = set()
273
274 used_by = {}
275 for defect, logic in self.virtual_defect_logics.items():
276 used_defects.update(logic.realclauses)
277 for clause in logic.realclauses:
278 used_by.setdefault(clause, []).append(defect)
279
280 missing_defects = used_defects - all_defects
281
282 if missing_defects:
283 log.error("-- The missing defects are used by the following virtual defects")
284 log.error("<missing> : <used by>")
285 for missing in missing_defects:
286 log.error(missing + ":" + ", ".join(used_by[missing]))
287
288 assert not missing_defects, ("The following defects are used but not "
289 "defined anywhere: %r" % missing_defects)
290 return True

◆ all_defect_descriptions()

Mapping[Union[str, int], str] python.ids.DefectsDBIDsNamesMixin.all_defect_descriptions ( self)
inherited
A dictionary of all (virtual and primary) defect descriptions

Definition at line 264 of file ids.py.

264 def all_defect_descriptions(self) -> Mapping[Union[str, int], str]:
265 """
266 A dictionary of all (virtual and primary) defect descriptions
267 """
268 result = self.get_channel_descriptions(self.defect_names)
269 gvcd = self.get_virtual_channel_descriptions
270 result.update(gvcd(self.virtual_defect_names))
271 return result
272

◆ check_tag_validity()

None python.tags.DefectsDBTagsMixin.check_tag_validity ( self)
inherited
Ensure that the tags that this DefectsDB instance was constructed with
are functional

Definition at line 110 of file tags.py.

110 def check_tag_validity(self) -> None:
111 """
112 Ensure that the tags that this DefectsDB instance was constructed with
113 are functional
114 """
115 if not (self.defects_tag_valid or self.logics_tag_valid):
116 raise InvalidTagError("Tag doesn't resolve: {0}".format(self._tag))
117

◆ create_defect()

None python.db.DefectsDB.create_defect ( self,
str name,
str description )
Create a new type of defect; tries to figure out system ID from the
defect name. See also: `create_defect_with_id`, `new_system_defect`.

Parameters:
    `name` : name of the defect
    `description` : a human-readable description of the defect
Returns:
    the ID number of the new defect

Definition at line 119 of file DQDefects/python/db.py.

119 def create_defect(self, name: str, description: str) -> None:
120 """
121 Create a new type of defect; tries to figure out system ID from the
122 defect name. See also: `create_defect_with_id`, `new_system_defect`.
123
124 Parameters:
125 `name` : name of the defect
126 `description` : a human-readable description of the defect
127 Returns:
128 the ID number of the new defect
129 """
130 sysid = choose_new_defect_id(self.defect_id_map, name)
131 log.info("Creating new defect %s: system ID %08x", name, sysid)
132 self._create_defect_with_id(sysid, name, description)
133

◆ defect_chan_as_id()

int python.ids.DefectsDBIDsNamesMixin.defect_chan_as_id ( self,
Union[str, int] channel,
bool primary_only = False )
inherited
Returns the defect ID for a virtual defect.
Accepts a `channel` as an integer/string and returns it as an integer.

Will raise DefectUnknownError if `channel` is an unknown ID or string.

This function first checks against non-virtual defects, then virutal 
defects. Thus virtual-defects are lazily loaded.        

Definition at line 202 of file ids.py.

202 def defect_chan_as_id(self, channel: Union[str, int], primary_only: bool = False) -> int:
203 """
204 Returns the defect ID for a virtual defect.
205 Accepts a `channel` as an integer/string and returns it as an integer.
206
207 Will raise DefectUnknownError if `channel` is an unknown ID or string.
208
209 This function first checks against non-virtual defects, then virutal
210 defects. Thus virtual-defects are lazily loaded.
211 """
212 from builtins import int
213 if isinstance(channel, int):
214 if (channel not in self.defect_ids and
215 (not primary_only and channel not in self.virtual_defect_ids)):
216 raise DefectUnknownError(channel)
217 return channel
218 elif isinstance(channel, str):
219 if channel in self.defect_names:
220 return self.defect_id_map[channel]
221 if not primary_only and channel in self.virtual_defect_names:
222 return self.virtual_defect_id_map[channel]
223 raise DefectUnknownError(channel)
224 raise RuntimeError("Invalid `channel` type, got %s, expected integer"
225 " or string" % type(channel))
226

◆ defect_id_map()

MutableMapping[Union[str,int], Union[str,int]] python.ids.DefectsDBIDsNamesMixin.defect_id_map ( self)
inherited
Gives the dictionary relating COOL channel ids to defect names and vice
versa, retrieving them from the database if necessary.

Definition at line 162 of file ids.py.

162 def defect_id_map(self) -> MutableMapping[Union[str,int], Union[str,int]]:
163 """
164 Gives the dictionary relating COOL channel ids to defect names and vice
165 versa, retrieving them from the database if necessary.
166 """
167 if not self._initialized:
168 self._populate_defect_ids()
169 self._initialized = True
170 return self._defect_id_map
171

◆ defect_ids()

Set[int] python.ids.DefectsDBIDsNamesMixin.defect_ids ( self)
inherited
Gives the set of defect IDs that exist in COOL

Definition at line 141 of file ids.py.

141 def defect_ids(self) -> Set[int]:
142 """
143 Gives the set of defect IDs that exist in COOL
144 """
145 if not self._initialized:
146 self._populate_defect_ids()
147 self._initialized = True
148 return self._defect_ids
149

◆ defect_is_virtual()

bool python.ids.DefectsDBIDsNamesMixin.defect_is_virtual ( self,
Union[str, int] defect_id )
inherited
Returns True if the `defect_id` represents a virtual defect, False if it 
is not and raises if it doesn't exist

Parameters:
    `defect_id` : defect channel id or name

Definition at line 284 of file ids.py.

284 def defect_is_virtual(self, defect_id: Union[str, int]) -> bool:
285 """
286 Returns True if the `defect_id` represents a virtual defect, False if it
287 is not and raises if it doesn't exist
288
289 Parameters:
290 `defect_id` : defect channel id or name
291 """
292 from builtins import int
293 if isinstance(defect_id, int):
294 return DefectID(defect_id).is_virtual
295
296 if not isinstance(defect_id, str):
297 raise RuntimeError("Invalid defect_id, expected int or string")
298
299 if defect_id in self.defect_names:
300 return False
301
302 if defect_id in self.virtual_defect_names:
303 return True
304
305 raise DefectUnknownError(defect_id)
306

◆ defect_logic_folder()

cool.IFolder python.folders.DefectsDBFoldersMixin.defect_logic_folder ( self)
inherited
Returns the folder containing the virtual defect logic, loading it if necessary

Definition at line 100 of file folders.py.

100 def defect_logic_folder(self) -> cool.IFolder:
101 """
102 Returns the folder containing the virtual defect logic, loading it if necessary
103 """
104 if self._defect_logic_folder is None: self._load_defect_logic_folder()
105 return self._defect_logic_folder
106

◆ defect_names()

Set[str] python.ids.DefectsDBIDsNamesMixin.defect_names ( self)
inherited
Gives the set of defect names that exist in COOL

Definition at line 151 of file ids.py.

151 def defect_names(self) -> Set[str]:
152 """
153 Gives the set of defect names that exist in COOL
154 """
155 if not self._initialized:
156 self._populate_defect_ids()
157 self._initialized = True
158 assert self._defect_names is not None, self._initialized
159 return self._defect_names
160

◆ defect_names_as_ids()

List[int] python.ids.DefectsDBIDsNamesMixin.defect_names_as_ids ( self,
Iterable[Union[str, int]] channels )
inherited
Returns a list of channels as IDs

Definition at line 227 of file ids.py.

227 def defect_names_as_ids(self, channels: Iterable[Union[str, int]]) -> List[int]:
228 """
229 Returns a list of channels as IDs
230 """
231 return [self.defect_chan_as_id(chan) for chan in channels]
232

◆ defects_folder()

cool.IFolder python.folders.DefectsDBFoldersMixin.defects_folder ( self)
inherited
Returns the folder containing the defects, loading it if necessary

Definition at line 67 of file folders.py.

67 def defects_folder(self) -> cool.IFolder:
68 """
69 Returns the folder containing the defects, loading it if necessary
70 """
71 if self._defects_folder is None: self._load_defects_folder()
72 return self._defects_folder
73

◆ defects_tag()

str python.tags.DefectsDBTagsMixin.defects_tag ( self)
inherited
Return the tag used for retrieving defects on this DefectsDB instance

Definition at line 119 of file tags.py.

119 def defects_tag(self) -> str:
120 """
121 Return the tag used for retrieving defects on this DefectsDB instance
122 """
123 if self._tag.defects == "HEAD": return "HEAD"
124 try:
125 return self.defects_folder.resolveTag(self._tag.defects)
126 except Exception:
127 if self._read_only:
128 raise InvalidDefectTagError(self._tag.defects)
129 # assume user knows what they're doing (e.g. writing to fresh tag)
130 return self._tag.defects
131

◆ defects_tag_valid()

bool python.tags.DefectsDBTagsMixin.defects_tag_valid ( self)
inherited

Definition at line 93 of file tags.py.

93 def defects_tag_valid(self) -> bool:
94 try:
95 self.defects_tag
96 except InvalidTagError:
97 return False
98 else:
99 return True
100

◆ defects_tags()

List[str] python.tags.DefectsDBTagsMixin.defects_tags ( self)
inherited
Returns a list of existing defect tags

Definition at line 34 of file tags.py.

34 def defects_tags(self) -> List[str]:
35 """
36 Returns a list of existing defect tags
37 """
38 return [str(t) for t in self.defects_folder.listTags()]
39

◆ get_channel_descriptions()

MutableMapping[Union[str, int], str] python.ids.DefectsDBIDsNamesMixin.get_channel_descriptions ( self,
Iterable[Union[str, int]] channels )
inherited
For the list of channel IDs "channels", return dict mapping ID to
description

Definition at line 245 of file ids.py.

245 def get_channel_descriptions(self, channels: Iterable[Union[str, int]]) -> MutableMapping[Union[str, int], str]:
246 """
247 For the list of channel IDs "channels", return dict mapping ID to
248 description
249 """
250 get_desc = self.defects_folder.channelDescription
251 return {channel: get_desc(self.defect_chan_as_id(channel))
252 for channel in channels}
253

◆ get_channels()

Tuple[Set[int], Set[str], Mapping[Union[str, int], Union[str, int]]] python.ids.DefectsDBIDsNamesMixin.get_channels ( self)
inherited
Return channel IDs, names, and dict relating the two

Definition at line 233 of file ids.py.

233 def get_channels(self) -> Tuple[Set[int], Set[str], Mapping[Union[str, int], Union[str, int]]]:
234 """
235 Return channel IDs, names, and dict relating the two
236 """
237 return self.defect_ids, self.defect_names, self.defect_id_map
238

◆ get_intolerable_defects()

python.virtual_mixin.DefectsDBVirtualDefectsMixin.get_intolerable_defects ( self,
bool old_primary_only = True,
Sequence[str] exclude = ['TIGHT', 'IDTIGHT', 'PHYS_.*'] )
inherited
Returns primary defects that are depended on by a virtual defect
if old_primary_only == True, only return those depended on by a
virtual defect with no _ in the name
ignores virtual defects in exclude list
accepts regexes in exclude list

Definition at line 247 of file virtual_mixin.py.

248 exclude: Sequence[str] = ['TIGHT', 'IDTIGHT', 'PHYS_.*']):
249 """
250 Returns primary defects that are depended on by a virtual defect
251 if old_primary_only == True, only return those depended on by a
252 virtual defect with no _ in the name
253 ignores virtual defects in exclude list
254 accepts regexes in exclude list
255 """
256 vdl = self.virtual_defect_logics
257 if old_primary_only:
258 vdl = dict(l for l in vdl.items() if '_' not in l[0])
259 if len(exclude) > 0:
260 import re
261 rex = re.compile('(%s)' % '|'.join(exclude))
262 vdl = dict(l for l in vdl.items() if not rex.match(l[0]))
263 return self.resolve_primary_defects(vdl.values())
264

◆ get_virtual_channel_descriptions()

MutableMapping[Union[str, int], str] python.ids.DefectsDBIDsNamesMixin.get_virtual_channel_descriptions ( self,
Iterable[Union[str, int]] channels )
inherited
For the list of channel IDs "channels", return dict mapping ID to
descriptiondefect_id

Definition at line 254 of file ids.py.

254 def get_virtual_channel_descriptions(self, channels: Iterable[Union[str, int]]) -> MutableMapping[Union[str, int], str]:
255 """
256 For the list of channel IDs "channels", return dict mapping ID to
257 descriptiondefect_id
258 """
259 get_desc = self.defect_logic_folder.channelDescription
260 return {channel: get_desc(self.defect_chan_as_id(channel))
261 for channel in channels}
262

◆ get_virtual_channels()

Tuple[Set[int], Set[str], Mapping[Union[str, int], Union[str, int]]] python.ids.DefectsDBIDsNamesMixin.get_virtual_channels ( self)
inherited
Return channel IDs, names, and dict relating the two

Definition at line 239 of file ids.py.

239 def get_virtual_channels(self) -> Tuple[Set[int], Set[str], Mapping[Union[str, int], Union[str, int]]]:
240 """
241 Return channel IDs, names, and dict relating the two
242 """
243 return self.virtual_defect_ids, self.virtual_defect_names, self.virtual_defect_id_map
244

◆ insert()

None python.db.DefectsDB.insert ( self,
Union[str, int] defect_id,
int since,
int until,
str comment,
str added_by,
bool present = True,
bool recoverable = False )
Insert a new defect into the database.

Parameters:
    `defect_id` : The name or channel identifier for the deect
    `since`, `until` : The COOL IoV for the range
    `comment`   : String255 arbitrary text comment
    `added_by`  : The user name or "sys:"-prefixed string of the
                  application that inserted the defect
    `present`   : The state of the flag (Default: True)
    `recoverable` : Indicates whether there is any possibility to set
                    present=False in the future (Default: False)

Definition at line 300 of file DQDefects/python/db.py.

301 present: bool = True, recoverable: bool = False) -> None:
302 """
303 Insert a new defect into the database.
304
305 Parameters:
306 `defect_id` : The name or channel identifier for the deect
307 `since`, `until` : The COOL IoV for the range
308 `comment` : String255 arbitrary text comment
309 `added_by` : The user name or "sys:"-prefixed string of the
310 application that inserted the defect
311 `present` : The state of the flag (Default: True)
312 `recoverable` : Indicates whether there is any possibility to set
313 present=False in the future (Default: False)
314 """
315 return self._insert(defect_id, since, until, comment, added_by,
316 present, recoverable, self.defects_tag)
317

◆ insert_multiple()

python.db.DefectsDB.insert_multiple ( self,
Iterable[IOVType] defect_list,
str tag = 'HEAD',
bool use_flask = False,
str flask_cool_target = 'oracle://ATONR_COOLOFL_GPN/ATLAS_COOLOFL_GLOBAL',
Mapping[str, str] flask_auth = {},
str flask_db = 'CONDBR2',
str flask_uri = 'https://cool-proxy-app.cern.ch/cool/multi_iovs' )

Definition at line 350 of file DQDefects/python/db.py.

356 ):
357 if not use_flask:
358 for defect in defect_list:
359 self._insert_iov(defect, tag)
360 else:
361 # Allow for override from environment
362 import os
363 flask_uri = os.environ.get('DQM_COOL_FLASK_URI', flask_uri)
364
365 log.debug(f'Flask server URI: {flask_uri}')
366 self._insert_multiple_flask(defect_list, tag, flask_cool_target,
367 flask_auth, flask_db, flask_uri)
368

◆ logics_tag_valid()

bool python.tags.DefectsDBTagsMixin.logics_tag_valid ( self)
inherited

Definition at line 102 of file tags.py.

102 def logics_tag_valid(self) -> bool:
103 try:
104 self.logics_tag
105 except InvalidTagError:
106 return False
107 else:
108 return True
109

◆ new_defects_tag()

str python.tags.DefectsDBTagsMixin.new_defects_tag ( self,
str name,
str description,
Optional[Iterable] iovranges = None )
inherited
Clones the current DEFECTS tag (specified in the constructor) to a new one
If iovranges != None, does the slower thing of copying IOVs one by one

Parameters:
    `name` : Name of the new tag
    `description` : Description of the contents of this tag

Definition at line 175 of file tags.py.

175 def new_defects_tag(self, name: str, description: str, iovranges: Optional[Iterable] = None) -> str:
176 """
177 Clones the current DEFECTS tag (specified in the constructor) to a new one
178 If iovranges != None, does the slower thing of copying IOVs one by one
179
180 Parameters:
181 `name` : Name of the new tag
182 `description` : Description of the contents of this tag
183 """
184 if name.startswith("DetStatus"):
185 raise RuntimeError("Only specify the last part of the defect tag")
186 adescription = description.encode('utf-8')
187
188 log.info("Creating new tag %s", name)
189
190 name = f"DetStatusDEFECTS-{name}"
191 aname = name.encode('ascii')
192
193 if iovranges is None:
194 self.defects_folder.cloneTagAsUserTag(self.defects_tag.encode('ascii'), aname, adescription)
195 return name
196
197 # Fetch all primary defects relevant to `iovranges`
198 kwargs = dict(primary_only=True, nonpresent=True, intersect=True)
199 iovsets = (self.retrieve(*iovrange, **kwargs) for iovrange in iovranges)
200 to_copy = IOVSet.from_iovsets(iovsets)
201
202 log.info("Copying IoVs: %r", to_copy)
203
204 with self.storage_buffer:
205 for iov in to_copy:
206 self._insert_iov(iov, name)
207
208 # If there are no IOVs to copy, there is no new tag to describe
209 if to_copy:
210 self.defects_folder.setTagDescription(aname, adescription)
211
212 return name

◆ new_hierarchical_tag()

str python.tags.DefectsDBTagsMixin.new_hierarchical_tag ( self,
str defects_tag,
str logics_tag )
inherited
Create a new heirarchical tag relating the defects and logics

New tag is of the form
"DetStatus-[Logic revision number]-[Defect tagname]"
and has description
"(v%i) blah"

Definition at line 61 of file tags.py.

61 def new_hierarchical_tag(self, defects_tag: str, logics_tag: str) -> str:
62 """
63 Create a new heirarchical tag relating the defects and logics
64
65 New tag is of the form
66 "DetStatus-[Logic revision number]-[Defect tagname]"
67 and has description
68 "(v%i) blah"
69 """
70 logic_revision = int(logics_tag.split("-")[-1])
71 defect_part = "-".join(defects_tag.split("-")[1:])
72 hierarchical_tag = "DetStatus-v%02i-%s" % (logic_revision, defect_part)
73 logicspart = "(%i) " % logic_revision
74
75 adefects_tag = defects_tag.encode('ascii')
76 alogics_tag = logics_tag.encode('ascii')
77 ahierarchical_tag = hierarchical_tag.encode('ascii')
78 logicspart = logicspart.encode('ascii')
79 defect_descr = self.defects_folder.tagDescription(adefects_tag).encode('utf-8')
80
81 # Protection here against making descriptions too long
82 description = logicspart + defect_descr[:255 - len(logicspart)]
83
84 parent_folder = self.parent_folderset
85 self.defects_folder.createTagRelation(ahierarchical_tag, adefects_tag)
86 self.defect_logic_folder.createTagRelation(ahierarchical_tag, alogics_tag)
87 parent_folder.setTagDescription(ahierarchical_tag, description)
88
89 log.info("New hierarchical tag %s", hierarchical_tag)
90 return hierarchical_tag
91

◆ new_logics_tag()

str python.tags.DefectsDBTagsMixin.new_logics_tag ( self,
str description = "" )
inherited
Create a new tag for the logic folder and lock it.

Parameters:
    `description` : What changed in this tag? (optional, default "")

Definition at line 160 of file tags.py.

160 def new_logics_tag(self, description: str = "") -> str:
161 """
162 Create a new tag for the logic folder and lock it.
163
164 Parameters:
165 `description` : What changed in this tag? (optional, default "")
166 """
167 assert self.logics_tag == "HEAD", NONHEAD_MODIFICATION_MSG
168
169 new_tag_name = self.next_logics_tag
170 folder = self.defect_logic_folder
171 self._tag_head_and_lock(folder, new_tag_name, description)
172 log.info("Tagged DEFECTLOGICS HEAD with %s", new_tag_name)
173 return new_tag_name
174

◆ new_virtual_defect()

int python.virtual_mixin.DefectsDBVirtualDefectsMixin.new_virtual_defect ( self,
str defect_name,
Optional[str] comment,
str clauses )
inherited
Create a new virtual defect

Definition at line 148 of file virtual_mixin.py.

148 def new_virtual_defect(self, defect_name: str, comment: Optional[str], clauses: str) -> int:
149 """
150 Create a new virtual defect
151 """
152 assert self.logics_tag == "HEAD", NONHEAD_MODIFICATION_MSG
153 assert not self._read_only, "Insertion on read-only database"
154 from DQUtils.channel_mapping import get_channel_ids_names
155
156 # Force load of defects_folder to populate _defect_payload
157 store = self.defect_logic_folder.storeObject
158 p = self._defect_logic_payload
159
160 self.validate_clauses(clauses)
161
162 p["clauses"] = clauses.encode('ascii')
163
164 # need to get true mapping of folder, not just what is visible
165 # from this tag
166 ids, _, mapping = get_channel_ids_names(self.defect_logic_folder)
167 defect_id = choose_new_defect_id(mapping, defect_name, True)
168 log.debug("Creating new defect %s: 0x%08x", defect_name, defect_id)
169
170 try:
171 oldname = self.normalize_defect_names(defect_name)
172 raise DefectExistsError('Defect %s already exists' % oldname)
173 except DefectUnknownError:
174 pass
175
176 if (defect_id in ids):
177 raise DefectExistsError(defect_name)
178 self.defect_logic_folder.createChannel(defect_id, defect_name.encode('ascii'), comment.encode('utf-8'))
179 store(0, 2**63-1, p, defect_id)
180 self._new_virtual_defect(defect_id, defect_name)
181 return defect_id
182

◆ next_logics_tag()

str python.tags.DefectsDBTagsMixin.next_logics_tag ( self)
inherited
Gives the next available DEFECTLOGICS tag

Definition at line 41 of file tags.py.

41 def next_logics_tag(self) -> str:
42 """
43 Gives the next available DEFECTLOGICS tag
44 """
45 existing_tags = self.logics_tags
46 if existing_tags:
47 new_id = max(int(str(t).split("-")[-1]) for t in existing_tags) + 1
48 else:
49 new_id = 0
50 return DEFECT_LOGIC_TAG_FORMAT % new_id
51
#define max(a, b)
Definition cfImp.cxx:41
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177

◆ normalize_defect_names()

Union[str, List[str]] python.ids.DefectsDBIDsNamesMixin.normalize_defect_names ( self,
Union[str, Iterable[str]] defect_id )
inherited
Returns correct name(s) of defects, given name(s) that possibly differ
from the correct ones by case.  Raises if an input name doesn't map to
any existing defect.  You can pass either a string or an iterable
object as `defect_id`.

Definition at line 307 of file ids.py.

307 def normalize_defect_names(self, defect_id: Union[str, Iterable[str]]) -> Union[str, List[str]]:
308 """
309 Returns correct name(s) of defects, given name(s) that possibly differ
310 from the correct ones by case. Raises if an input name doesn't map to
311 any existing defect. You can pass either a string or an iterable
312 object as `defect_id`.
313 """
314 wasstring = False
315 if isinstance(defect_id, str):
316 defect_id = [defect_id]
317 wasstring = True
318 if any(not isinstance(i, str) for i in defect_id):
319 raise ValueError('All input values must be strings')
320
321 uppered_defects = dict((i.upper(), i) for i in self.defect_names)
322 uppered_defects.update(dict((i.upper(), i) for i in self.virtual_defect_names))
323
324 rv = []
325 for i in defect_id:
326 up = i.upper()
327 if up in uppered_defects:
328 rv.append(uppered_defects[up])
329 else:
330 raise DefectUnknownError(i)
331
332 if wasstring:
333 return rv[0]
334 else:
335 return rv

◆ parent_folderset()

cool.IFolderSet python.folders.DefectsDBFoldersMixin.parent_folderset ( self)
inherited
Lazy-loads parent folderset (useful for heirarchical tag manipulation)

Definition at line 36 of file folders.py.

36 def parent_folderset(self) -> cool.IFolderSet:
37 """
38 Lazy-loads parent folderset (useful for heirarchical tag manipulation)
39 """
40 if self._parent_folderset is None:
41 db = Databases.get_instance(self.connection_string,
42 read_only=self._read_only)
43 self._parent_folderset = db.getFolderSet(PARENT_FOLDERSET)
44 return self._parent_folderset
45

◆ rename_defect()

None python.virtual_mixin.DefectsDBVirtualDefectsMixin.rename_defect ( self,
str defect_name,
str new_defect_name )
inherited
Rename a defect (primary or virtual).  Will keep data and channel ID.
Will fix up all virtual defect dependencies in all tags.

Definition at line 83 of file virtual_mixin.py.

83 def rename_defect(self, defect_name: str, new_defect_name: str) -> None:
84 """
85 Rename a defect (primary or virtual). Will keep data and channel ID.
86 Will fix up all virtual defect dependencies in all tags.
87 """
88 assert not self._read_only, "Channel rename on read-only database"
89
90 try:
91 oldname = self.normalize_defect_names(new_defect_name)
92 raise DefectExistsError('Defect %s already exists' % oldname)
93 except DefectUnknownError:
94 pass
95
96 defect_id = self.defect_chan_as_id(defect_name)
97
98 anew_defect_name = new_defect_name.encode('ascii')
99 if self.defect_is_virtual(defect_id):
100 self.defect_logic_folder.setChannelName(defect_id, anew_defect_name)
101 self._virtual_defect_names = set()
102 self._virtual_defect_id_map = {}
103 self._virtual_defect_logics = None
104 self._virtual_initialized = False
105 else:
106 self.defects_folder.setChannelName(defect_id, anew_defect_name)
107 self._defect_names = set()
108 self._defect_id_map = {}
109 self._initialized = False
110
111 import contextlib
112 @contextlib.contextmanager
113 def logics_unlocking(tag):
114 atag = tag.encode('ascii')
115 log.info('Unlocking tag %s', tag)
116 folder = self.defect_logic_folder
117 orig_status = folder.tagLockStatus(atag)
118 if orig_status != 0:
119 folder.setTagLockStatus(atag, 0)
120 yield
121 if orig_status != 0:
122 folder.setTagLockStatus(atag, orig_status)
123 log.info('Done with tag %s', tag)
124
125 def logic_substitute(clause, oldname, newname):
126 oclause = clause
127 prefix = ''
128 if clause[0] in ('!',):
129 prefix = clause[0]
130 clause = clause[1:]
131 if clause != oldname:
132 return oclause
133 else:
134 return prefix + newname
135
136 for tag in ['HEAD'] + self.logics_tags:
137 logics = self._get_virtual_defect_logics(tag)
138 for vd, logic in logics.items():
139 if defect_name in logic.realclauses:
140 newclauses = ' '.join([logic_substitute(x, defect_name,
141 new_defect_name)
142 for x in logic.clauses
143 ])
144 with logics_unlocking(tag):
145 self._update_virtual_defect(vd, newclauses, tag=tag)
146 self._virtual_defect_logics = None
147

◆ resolve_primary_defects()

Set[str] python.virtual_mixin.DefectsDBVirtualDefectsMixin.resolve_primary_defects ( self,
Iterable[DefectLogic] defect_logics )
inherited
Determine which primary flags are used for 
a given list of input `virtual_defect_names`.

Definition at line 208 of file virtual_mixin.py.

208 def resolve_primary_defects(self, defect_logics: Iterable[DefectLogic]) -> Set[str]:
209 """
210 Determine which primary flags are used for
211 a given list of input `virtual_defect_names`.
212 """
213 primary_defects = set()
214 for defect_logic in defect_logics:
215 primary_defects |= defect_logic.primary_defects
216
217 return primary_defects
218

◆ retrieve()

IOVSet python.db.DefectsDB.retrieve ( self,
Optional[Union[int, Tuple[int,int], RunLumi]] since = None,
Optional[Union[int, Tuple[int,int], RunLumi]] until = None,
Optional[Iterable[Union[str,int]]] channels = None,
bool nonpresent = False,
bool primary_only = False,
Optional[Collection[str]] ignore = None,
bool with_primary_dependencies = False,
bool intersect = False,
bool with_time = False,
bool evaluate_full = True )
Retrieve defects from the database.

Parameters:
    `since`, `until` : IoV range to query (Default: All)
    `channels`  : A list of channels to query. Can contain a mixture of
                 defect names and ids. (Default: None means all 
                channels, including all virtual)
    `nonpresent` : Only return IoVs which are currently "present"
    `primary_only` : Only return primary IoVs, no virtual ones.
    `ignore` : Set of defects which won't be treated as bad.
    `with_primary_dependencies` : When querying virtual flags, also get
        primary flags which went into the calculation.
    `intersect` : Intersect the result with the query range so that no
                  iov spans outside the query range
    `with_time` : Also retrieves the time the defect was inserted
                  ~2x slower queries, doesn't work for virtual defects
    `evaluate_full` : If specified, also compute the `comment` and
                      `recoverable` fields of virtual defects.
                      Causes a ~0.6x slowdown

Definition at line 157 of file DQDefects/python/db.py.

162 with_time: bool = False, evaluate_full: bool = True) -> IOVSet:
163 """
164 Retrieve defects from the database.
165
166 Parameters:
167 `since`, `until` : IoV range to query (Default: All)
168 `channels` : A list of channels to query. Can contain a mixture of
169 defect names and ids. (Default: None means all
170 channels, including all virtual)
171 `nonpresent` : Only return IoVs which are currently "present"
172 `primary_only` : Only return primary IoVs, no virtual ones.
173 `ignore` : Set of defects which won't be treated as bad.
174 `with_primary_dependencies` : When querying virtual flags, also get
175 primary flags which went into the calculation.
176 `intersect` : Intersect the result with the query range so that no
177 iov spans outside the query range
178 `with_time` : Also retrieves the time the defect was inserted
179 ~2x slower queries, doesn't work for virtual defects
180 `evaluate_full` : If specified, also compute the `comment` and
181 `recoverable` fields of virtual defects.
182 Causes a ~0.6x slowdown
183 """
184 if ignore is not None and not isinstance(ignore, set):
185 raise RuntimeError("ignore parameter should be set type")
186
187 desired_channels = None
188 # Figure out the IDs of channels to query and their virtuality
189 if channels is not None:
190 query_channels = set(self.defect_names_as_ids(channels))
191 virtual_channels = query_channels - self.defect_ids
192 primary_channels = query_channels & self.defect_ids
193 else:
194 # Empty channels list means query all channels
195 # (including all virtual)
196 if primary_only:
197 virtual_channels = None
198 else:
199 virtual_channels = self.virtual_defect_ids
200 primary_channels = set(self.defect_ids)
201 query_channels = None # (all)
202
203 primary_output_names = [self.defect_id_map[pid] for pid in primary_channels]
204 virtual_output_names = [] # (optionally populated below)
205
206 # Resolve virtual channels to query here, and the primary dependents.
207 if virtual_channels:
208 assert not primary_only, "Requested virtual channels with primary_only=True"
209 assert not with_time, "with_time flag only works for primary defects"
210 virtual_output_names = [self.virtual_defect_id_map[vid]
211 for vid in virtual_channels]
212
213 ordered_logics = self._resolve_evaluation_order(virtual_output_names)
214
215 if channels is not None:
216 # Since not all channels are being queried, it is necessary to
217 # add the desired primary channels to the query
218 primary_needed = self.resolve_primary_defects(ordered_logics)
219 primary_channels |= set(self.defect_names_as_ids(primary_needed))
220 query_channels = primary_channels
221
222 if with_primary_dependencies:
223 primary_output_names.extend(sorted(primary_needed))
224
225 for logic in ordered_logics:
226 logic.set_evaluation(evaluate_full)
227 else:
228 ordered_logics = []
229
230 # Figure out if the set of channels will produce too many ranges for COOL
231 if query_channels is not None:
232 query_channels = sorted(query_channels)
233 query_ranges = list_to_channelselection(query_channels, None, True)
234
235 if len(query_ranges) >= 50:
236 # We're querying too many ranges. Query everything, filter later.
237 desired_channels = set(primary_output_names + virtual_output_names)
238 query_channels = None # (everything)
239
240 # Retrieve primary IoVs
241 primary_iovs = fetch_iovs(self.defects_folder, since, until,
242 query_channels, self.defects_tag,
243 named_channels=True, unicode_strings=True,
244 with_time=with_time)
245
246 # Calculate virtual defects (if necessary)
247 if primary_only or not virtual_channels:
248 result = primary_iovs
249 else:
250 if not primary_iovs:
251 return IOVSet()
252 args = (primary_iovs, ordered_logics,
253 virtual_output_names, primary_output_names,
254 since, until, ignore)
255 result = calculate_virtual_defects(*args)
256
257 # Filter out results which have their present bit removed
258 # (unless otherwise specified)
259 if not nonpresent:
260 result = IOVSet(iov for iov in result if iov.present)
261
262 # Filter out channels which weren't queried by the user
263 # (to get around 50 channelselection COOL limit)
264 if desired_channels:
265 result = IOVSet(iov for iov in result
266 if iov.channel in desired_channels)
267
268 if intersect:
269 result = result.intersect_range((since, until))
270
271 return result
272

◆ set_channel_description()

None python.ids.DefectsDBIDsNamesMixin.set_channel_description ( self,
Union[str, int] channel,
str description )
inherited
Set a defect description

Definition at line 273 of file ids.py.

273 def set_channel_description(self, channel: Union[str, int], description: str) -> None:
274 """
275 Set a defect description
276 """
277 chan_id = self.defect_chan_as_id(channel)
278 if self.defect_is_virtual(chan_id):
279 folder = self.defect_logic_folder
280 else:
281 folder = self.defects_folder
282 folder.setChannelDescription(chan_id, description.encode('utf-8'))
283

◆ storage_buffer()

python.db.DefectsDB.storage_buffer ( self)
Gives a new context manager for use with the with statement, e.g.:
    with ddb.storage_buffer:
        for d in many_defects:
            ddb.insert(...defect...)

Reimplemented from python.tags.DefectsDBTagsMixin.

Definition at line 274 of file DQDefects/python/db.py.

274 def storage_buffer(self):
275 """
276 Gives a new context manager for use with the with statement, e.g.:
277 with ddb.storage_buffer:
278 for d in many_defects:
279 ddb.insert(...defect...)
280 """
281 assert not self._bad_state, "Please see comment in DefectsDB constructor"
282
283 @contextmanager
284 def thunk():
285 log.debug("setupStorageBuffer()")
286 self.defects_folder.setupStorageBuffer()
287 try:
288 yield
289 except Exception:
290 log.warning("Exception raised during DefectsDB.storage_buffer. "
291 "Not flushing storage buffer - but COOL has no way "
292 "to empty it. ")
293 self._bad_state = True
294 raise
295 else:
296 log.debug("flushStorageBuffer()")
297 self.defects_folder.flushStorageBuffer()
298 return thunk()
299

◆ tag()

tagtype python.tags.DefectsDBTagsMixin.tag ( self)
inherited
Readonly property stating the tag that the database was instantiated on

Definition at line 147 of file tags.py.

147 def tag(self) -> tagtype:
148 """
149 Readonly property stating the tag that the database was instantiated on
150 """
151 return self._tag
152

◆ tags()

List[str] python.tags.DefectsDBTagsMixin.tags ( self)
inherited
The list of tags which are on the database

Definition at line 154 of file tags.py.

154 def tags(self) -> List[str]:
155 """
156 The list of tags which are on the database
157 """
158 return [str(t) for t in self.parent_folderset.listTags()]
159
std::vector< std::string > tags
Definition hcg.cxx:105

◆ update_virtual_defect()

None python.virtual_mixin.DefectsDBVirtualDefectsMixin.update_virtual_defect ( self,
str defect_name,
str clauses,
Optional[str] comment = None )
inherited

Definition at line 55 of file virtual_mixin.py.

55 def update_virtual_defect(self, defect_name: str, clauses: str, comment: Optional[str] = None) -> None:
56 # HEAD protection is here, to allow other functions to
57 # change other tags in a known manner with _update_virtual_defect
58 assert self.logics_tag == "HEAD", NONHEAD_MODIFICATION_MSG
59 assert not self._read_only, "Insertion on read-only database"
60 self._update_virtual_defect(defect_name, clauses, comment)
61

◆ validate_clauses()

None python.virtual_mixin.DefectsDBVirtualDefectsMixin.validate_clauses ( self,
str clauses )
inherited

Definition at line 48 of file virtual_mixin.py.

48 def validate_clauses(self, clauses: str) -> None:
49 all_defects = self.defect_names | self.virtual_defect_names
50 for clause in clauses.split():
51 if clause[0] in ('!', '-'):
52 clause = clause[1:]
53 assert clause in all_defects, (clause + " is not a known defect")
54

◆ virtual_defect_id_map()

MutableMapping[Union[str,int], Union[str,int]] python.ids.DefectsDBIDsNamesMixin.virtual_defect_id_map ( self)
inherited
Returns a dict() mapping virtual defect names to IDs and vice-versa.

Definition at line 193 of file ids.py.

193 def virtual_defect_id_map(self) -> MutableMapping[Union[str,int], Union[str,int]]:
194 """
195 Returns a dict() mapping virtual defect names to IDs and vice-versa.
196 """
197 if not self._virtual_initialized:
198 self._populate_virtual_defect_ids()
199 self._virtual_initialized = True
200 return self._virtual_defect_id_map
201

◆ virtual_defect_ids()

Set[int] python.ids.DefectsDBIDsNamesMixin.virtual_defect_ids ( self)
inherited
Returns the set of existing virtual defect IDs

Definition at line 173 of file ids.py.

173 def virtual_defect_ids(self) -> Set[int]:
174 """
175 Returns the set of existing virtual defect IDs
176 """
177 if not self._virtual_initialized:
178 self._populate_virtual_defect_ids()
179 self._virtual_initialized = True
180 return self._virtual_defect_ids
181

◆ virtual_defect_logics()

Mapping[str, DefectLogic] python.virtual_mixin.DefectsDBVirtualDefectsMixin.virtual_defect_logics ( self)
inherited
Returns all virtual defects in the form {"defect_name" : DefectLogic()}
for the tag DefectDB was constructed on.

Definition at line 220 of file virtual_mixin.py.

220 def virtual_defect_logics(self) -> Mapping[str, DefectLogic]:
221 """
222 Returns all virtual defects in the form {"defect_name" : DefectLogic()}
223 for the tag DefectDB was constructed on.
224 """
225 if self._virtual_defect_logics is not None:
226 return self._virtual_defect_logics
227
228 self._virtual_defect_logics = self._get_virtual_defect_logics(self.logics_tag)
229
230 return self._virtual_defect_logics
231

◆ virtual_defect_names()

Set[str] python.ids.DefectsDBIDsNamesMixin.virtual_defect_names ( self)
inherited
Returns the set of existing virtual defect names

Definition at line 183 of file ids.py.

183 def virtual_defect_names(self) -> Set[str]:
184 """
185 Returns the set of existing virtual defect names
186 """
187 if not self._virtual_initialized:
188 self._populate_virtual_defect_ids()
189 self._virtual_initialized = True
190 return self._virtual_defect_names
191

Member Data Documentation

◆ _bad_state

python.db.DefectsDB._bad_state = False
protected

Definition at line 102 of file DQDefects/python/db.py.

◆ _connections

list python.folders.DefectsDBFoldersMixin._connections = []
protectedinherited

Definition at line 26 of file folders.py.

◆ _create

python.folders.DefectsDBFoldersMixin._create
protectedinherited

Definition at line 52 of file folders.py.

◆ _defect_id_map

dict python.virtual_mixin.DefectsDBVirtualDefectsMixin._defect_id_map = {}
protectedinherited

Definition at line 108 of file virtual_mixin.py.

◆ _defect_ids

Set[int] python.ids.DefectsDBIDsNamesMixin._defect_ids = set()
protectedinherited

Definition at line 82 of file ids.py.

◆ _defect_logic_folder

python.folders.DefectsDBFoldersMixin._defect_logic_folder = None
protectedinherited

Definition at line 24 of file folders.py.

◆ _defect_logic_payload

python.virtual_mixin.DefectsDBVirtualDefectsMixin._defect_logic_payload
protectedinherited

Definition at line 77 of file virtual_mixin.py.

◆ _defect_names

python.virtual_mixin.DefectsDBVirtualDefectsMixin._defect_names = set()
protectedinherited

Definition at line 107 of file virtual_mixin.py.

◆ _defect_payload

python.folders.DefectsDBFoldersMixin._defect_payload = res
protectedinherited

Definition at line 80 of file folders.py.

◆ _defects_folder

python.folders.DefectsDBFoldersMixin._defects_folder = None
protectedinherited

Definition at line 23 of file folders.py.

◆ _initialized

bool python.virtual_mixin.DefectsDBVirtualDefectsMixin._initialized = False
protectedinherited

Definition at line 109 of file virtual_mixin.py.

◆ _parent_folderset

python.folders.DefectsDBFoldersMixin._parent_folderset = None
protectedinherited

Definition at line 25 of file folders.py.

◆ _read_only

python.virtual_mixin.DefectsDBVirtualDefectsMixin._read_only
protectedinherited

Definition at line 59 of file virtual_mixin.py.

◆ _tag

python.tags.DefectsDBTagsMixin._tag
protectedinherited

Definition at line 116 of file tags.py.

◆ _virtual_defect_id_map

dict python.virtual_mixin.DefectsDBVirtualDefectsMixin._virtual_defect_id_map = {}
protectedinherited

Definition at line 102 of file virtual_mixin.py.

◆ _virtual_defect_ids

Set[int] python.ids.DefectsDBIDsNamesMixin._virtual_defect_ids = set()
protectedinherited

Definition at line 85 of file ids.py.

◆ _virtual_defect_logics

Mapping[str, DefectLogic] python.virtual_mixin.DefectsDBVirtualDefectsMixin._virtual_defect_logics = None
protectedinherited

Definition at line 45 of file virtual_mixin.py.

◆ _virtual_defect_map

dict python.ids.DefectsDBIDsNamesMixin._virtual_defect_map = {}
protectedinherited

Definition at line 118 of file ids.py.

◆ _virtual_defect_names

python.virtual_mixin.DefectsDBVirtualDefectsMixin._virtual_defect_names = set()
protectedinherited

Definition at line 101 of file virtual_mixin.py.

◆ _virtual_initialized

bool python.virtual_mixin.DefectsDBVirtualDefectsMixin._virtual_initialized = False
protectedinherited

Definition at line 104 of file virtual_mixin.py.

◆ connection_string

python.db.DefectsDB.connection_string = connection_string

Definition at line 81 of file DQDefects/python/db.py.

◆ defect_ids

python.ids.DefectsDBIDsNamesMixin.defect_ids
inherited

Definition at line 237 of file ids.py.

◆ defect_names

python.ids.DefectsDBIDsNamesMixin.defect_names
inherited

Definition at line 219 of file ids.py.

◆ logics_tag

str python.virtual_mixin.DefectsDBVirtualDefectsMixin.logics_tag = "HEAD", NONHEAD_MODIFICATION_MSG
inherited

Definition at line 58 of file virtual_mixin.py.

◆ logics_tag_valid

python.tags.DefectsDBTagsMixin.logics_tag_valid
inherited

Definition at line 115 of file tags.py.

◆ logics_tags

python.virtual_mixin.DefectsDBVirtualDefectsMixin.logics_tags
inherited

Definition at line 136 of file virtual_mixin.py.

◆ virtual_defect_ids

python.ids.DefectsDBIDsNamesMixin.virtual_defect_ids
inherited

Definition at line 215 of file ids.py.

◆ virtual_defect_names

python.ids.DefectsDBIDsNamesMixin.virtual_defect_names
inherited

Definition at line 221 of file ids.py.


The documentation for this class was generated from the following file: