11import datetime
22import logging
3- import sys
43import traceback
4+ from json import JSONDecodeError
55from typing import List , Dict
66
77import dryable
88import requests
99
10-
1110logger = logging # default logger
1211
1312
1413class ObjectVersion :
15- '''
16- A version of an object in the CCDB.
17-
18- In the CCDB an object can have many versions with different validity intervals.
19- This class represents a single version.
20- '''
14+ """
15+ A version of an object in the CCDB.
16+
17+ In the CCDB an object can have many versions with different validity intervals.
18+ This class represents a single version.
19+ """
2120
22- def __init__ (self , path : str , validFrom , validTo , createdAt , uuid = None , metadata = None ):
23- '''
21+ def __init__ (self , path : str , valid_from , valid_to , created_at , uuid = None , metadata = None ):
22+ """
2423 Construct an ObjectVersion.
2524 :param path: path to the object
2625 :param uuid: unique id of the object
27- :param validFrom : validity range smaller limit (in ms)
28- :param validTo : validity range bigger limit (in ms)
29- :param createdAt : creation timestamp of the object
30- '''
26+ :param valid_from : validity range smaller limit (in ms)
27+ :param valid_to : validity range bigger limit (in ms)
28+ :param created_at : creation timestamp of the object
29+ """
3130 self .path = path
3231 self .uuid = uuid
33- self .validFrom = validFrom
32+ self .valid_from = valid_from
3433 # precomputed Datetime ("Dt") of the timestamp `validFrom`
35- self .validFromAsDt = datetime .datetime .fromtimestamp (int (validFrom ) / 1000 ) # /1000 because we get ms
36- self .validTo = validTo
34+ self .valid_from_as_dt = datetime .datetime .fromtimestamp (int (valid_from ) / 1000 ) # /1000 because we get ms
35+ self .valid_to = valid_to
3736 self .metadata = metadata
38- self .createdAt = createdAt
37+ self .created_at = created_at
3938 # precomputed Datetime ("Dt") of the timestamp `createdAt`
40- self .createdAtDt = datetime .datetime .fromtimestamp (int (createdAt ) / 1000 ) # /1000 because we get ms
39+ self .created_at_as_dt = datetime .datetime .fromtimestamp (int (created_at ) / 1000 ) # /1000 because we get ms
4140
4241 def __repr__ (self ):
4342 if "Run" in self .metadata or "RunNumber" in self .metadata :
4443 run_number = self .metadata ["Run" ] if "Run" in self .metadata else self .metadata ["RunNumber" ]
45- return f"Version of object { self .path } created at { self .createdAtDt .strftime ('%Y-%m-%d %H:%M:%S' )} , valid from { self .validFromAsDt .strftime ('%Y-%m-%d %H:%M:%S' )} , run { run_number } (uuid { self .uuid } )"
44+ return f"Version of object { self .path } created at { self .created_at_as_dt .strftime ('%Y-%m-%d %H:%M:%S' )} , valid from { self .valid_from_as_dt .strftime ('%Y-%m-%d %H:%M:%S' )} , run { run_number } (uuid { self .uuid } )"
4645 else :
47- return f"Version of object { self .path } created at { self .createdAtDt .strftime ('%Y-%m-%d %H:%M:%S' )} , valid from { self .validFromAsDt .strftime ('%Y-%m-%d %H:%M:%S' )} (uuid { self .uuid } , " \
48- f"ts { self .validFrom } )"
46+ return f"Version of object { self .path } created at { self .created_at_as_dt .strftime ('%Y-%m-%d %H:%M:%S' )} , valid from { self .valid_from_as_dt .strftime ('%Y-%m-%d %H:%M:%S' )} (uuid { self .uuid } , " \
47+ f"ts { self .valid_from } )"
4948
5049
5150class Ccdb :
52- '''
51+ """
5352 Class to interact with the CCDB.
54- '''
53+ """
5554
5655 counter_deleted : int = 0
5756 counter_validity_updated : int = 0
@@ -62,16 +61,16 @@ def __init__(self, url):
6261 logger .info (f"Instantiate CCDB at { url } " )
6362 self .url = url
6463
65- def getObjectsList (self , added_since : int = 0 , path : str = "" , no_wildcard : bool = False ) -> List [str ]:
66- '''
64+ def get_objects_list (self , added_since : int = 0 , path : str = "" , no_wildcard : bool = False ) -> List [str ]:
65+ """
6766 Get the full list of objects in the CCDB that have been created since added_since.
6867
6968 :param no_wildcard: if true, the path for which we get the list is not modified to add `/.*`.
7069 Set it to true if you need to get the versions of an object and not a folder.
7170 :param path: the path
7271 :param added_since: if specified, only return objects added since this timestamp in epoch milliseconds.
7372 :return A list of strings, each containing a path to an object in the CCDB.
74- '''
73+ """
7574 url_for_all_obj = self .url + '/latest/' + path
7675 url_for_all_obj += '/' if path else ''
7776 url_for_all_obj += '' if no_wildcard else '.*'
@@ -81,7 +80,7 @@ def getObjectsList(self, added_since: int = 0, path: str = "", no_wildcard: bool
8180 r .raise_for_status ()
8281 try :
8382 json = r .json ()
84- except json . decoder . JSONDecodeError as err :
83+ except JSONDecodeError as err :
8584 logger .error (f"JSON decode error: { err } " )
8685 raise
8786 paths = []
@@ -90,25 +89,25 @@ def getObjectsList(self, added_since: int = 0, path: str = "", no_wildcard: bool
9089
9190 return paths
9291
93- def getFullObjectsDetails (self , path : str = "" ) -> List [Dict ]:
94- '''
92+ def get_full_objects_details (self , path : str = "" ) -> List [Dict ]:
93+ """
9594 Return the full json of all the objects found in the path.
9695 :param path:
9796 :return:
98- '''
97+ """
9998 url_for_all_obj = self .url + '/latest/' + path + '.*'
10099 logger .debug (f"Ccdb::getFullObjectsDetails -> { url_for_all_obj } " )
101100 headers = {'Accept' : 'application/json' }
102101 r = requests .get (url_for_all_obj , headers = headers )
103102 r .raise_for_status ()
104103 try :
105104 json = r .json ()
106- except json . decoder . JSONDecodeError as err :
105+ except JSONDecodeError as err :
107106 logger .error (f"JSON decode error: { err } " )
108107 raise
109108 return json ['objects' ]
110109
111- def getVersionsList (self , object_path : str , from_ts : str = "" , to_ts : str = "" , run : int = - 1 , metadata : str = "" ) \
110+ def get_versions_list (self , object_path : str , from_ts : str = "" , to_ts : str = "" , run : int = - 1 , metadata : str = "" ) \
112111 -> List [ObjectVersion ]:
113112 """
114113 Get the list of all versions for a given object sorted by CreatedAt.
@@ -141,56 +140,56 @@ def getVersionsList(self, object_path: str, from_ts: str = "", to_ts: str = "",
141140 versions = []
142141 for object_path in json_result ['objects' ]:
143142 version = ObjectVersion (path = object_path ['path' ], uuid = object_path ['id' ],
144- validFrom = object_path ['validFrom' ], validTo = object_path ['validUntil' ],
145- metadata = object_path , createdAt = object_path ['Created' ])
143+ valid_from = object_path ['validFrom' ], valid_to = object_path ['validUntil' ],
144+ metadata = object_path , created_at = object_path ['Created' ])
146145 versions .insert (0 , version )
147- versions .sort (key = lambda v : v .createdAt , reverse = False )
146+ versions .sort (key = lambda v : v .created_at , reverse = False )
148147 return versions
149148
150149 @dryable .Dryable ()
151- def deleteVersion (self , version : ObjectVersion ):
152- '''
153- Delete the specified version of an object.
150+ def delete_version (self , version : ObjectVersion ):
151+ """
152+ Delete the specified version of an object.
154153 :param version: The version of the object to delete, as an instance of ObjectVersion.
155- '''
156- url_delete = self .url + '/' + version .path + '/' + str (version .validFrom ) + '/' + version .uuid
154+ """
155+ url_delete = self .url + '/' + version .path + '/' + str (version .valid_from ) + '/' + version .uuid
157156 logger .debug (f"Delete version at url { url_delete } " )
158157 headers = {'Connection' : 'close' }
159158 try :
160159 r = requests .delete (url_delete , headers = headers )
161160 r .raise_for_status ()
162161 self .counter_deleted += 1
163- except requests .exceptions .RequestException as e :
162+ except requests .exceptions .RequestException :
164163 logging .error (f"Exception in deleteVersion: { traceback .format_exc ()} " )
165164
166165 @dryable .Dryable ()
167- def moveVersion (self , version : ObjectVersion , to_path : str ):
168- '''
166+ def move_version (self , version : ObjectVersion , to_path : str ):
167+ """
169168 Move the version to a different path.
170169 :param version: The version of the object to move, as an instance of ObjectVersion.
171170 :param to_path: The destination path
172- '''
173- url_move = self .url + '/' + version .path + '/' + str (version .validFrom ) + '/' + version .uuid
171+ """
172+ url_move = self .url + '/' + version .path + '/' + str (version .valid_from ) + '/' + version .uuid
174173 logger .debug (f"Move version at url { url_move } to { to_path } " )
175174 headers = {'Connection' : 'close' , 'Destination' : to_path }
176175 try :
177176 r = requests .request ("MOVE" , url_move , headers = headers )
178177 r .raise_for_status ()
179178 self .counter_deleted += 1
180- except requests .exceptions .RequestException as e :
179+ except requests .exceptions .RequestException :
181180 logging .error (f"Exception in moveVersion: { traceback .format_exc ()} " )
182181
183182 @dryable .Dryable ()
184- def updateValidity (self , version : ObjectVersion , valid_from : int , valid_to : int , metadata = None ):
185- '''
183+ def update_validity (self , version : ObjectVersion , valid_from : int , valid_to : int , metadata = None ):
184+ """
186185 Update the validity range of the specified version of an object.
187186 :param version: The ObjectVersion to update.
188187 :param valid_from: The new "from" validity.
189188 :param valid_to: The new "to" validity.
190189 :param metadata: Add or modify metadata
191- '''
190+ """
192191 full_path = self .url + '/' + version .path + '/' + str (valid_from ) + '/' + str (valid_to ) + '/' + str (version .uuid ) + '?'
193- logger .debug (f"Update end limit validity of { version .path } ({ version .uuid } ) from { version .validTo } to { valid_to } " )
192+ logger .debug (f"Update end limit validity of { version .path } ({ version .uuid } ) from { version .valid_to } to { valid_to } " )
194193 if metadata is not None :
195194 logger .debug (f"{ metadata } " )
196195 for key in metadata :
@@ -203,13 +202,13 @@ def updateValidity(self, version: ObjectVersion, valid_from: int, valid_to: int,
203202 r = requests .put (full_path , headers = headers )
204203 r .raise_for_status ()
205204 self .counter_validity_updated += 1
206- except requests .exceptions .RequestException as e :
205+ except requests .exceptions .RequestException :
207206 logging .error (f"Exception in updateValidity: { traceback .format_exc ()} " )
208207
209208 @dryable .Dryable ()
210- def updateMetadata (self , version : ObjectVersion , metadata ):
209+ def update_metadata (self , version : ObjectVersion , metadata ):
211210 logger .debug (f"update metadata : { metadata } " )
212- full_path = self .url + '/' + version .path + '/' + str (version .validFrom ) + '/' + str (version .uuid ) + '?'
211+ full_path = self .url + '/' + version .path + '/' + str (version .valid_from ) + '/' + str (version .uuid ) + '?'
213212 if metadata is not None :
214213 for key in metadata :
215214 full_path += key + "=" + metadata [key ] + "&"
@@ -220,17 +219,17 @@ def updateMetadata(self, version: ObjectVersion, metadata):
220219 headers = {'Connection' : 'close' }
221220 r = requests .put (full_path , headers = headers )
222221 r .raise_for_status ()
223- except requests .exceptions .RequestException as e :
222+ except requests .exceptions .RequestException :
224223 logging .error (f"Exception in updateMetadata: { traceback .format_exc ()} " )
225224
226225 @dryable .Dryable ()
227- def putVersion (self , version : ObjectVersion , data ):
228- '''
226+ def put_version (self , version : ObjectVersion , data ):
227+ """
229228 :param version: An ObjectVersion that describes the data to be uploaded.
230229 :param data: the actual data to send. E.g.:{'somekey': 'somevalue'}
231230 :return A list of ObjectVersion.
232- '''
233- full_path = self .url + "/" + version .path + "/" + str (version .validFrom ) + "/" + str (version .validTo ) + "/"
231+ """
232+ full_path = self .url + "/" + version .path + "/" + str (version .valid_from ) + "/" + str (version .valid_to ) + "/"
234233 if version .metadata is not None :
235234 for key in version .metadata :
236235 full_path += key + "=" + version .metadata [key ] + "/"
@@ -242,17 +241,3 @@ def putVersion(self, version: ObjectVersion, data):
242241 else :
243242 logger .error (f"Could not post a new version of { version .path } : { r .text } " )
244243
245- def main ():
246- logger .basicConfig (level = logger .INFO , format = '%(asctime)s - %(levelname)s - %(message)s' , datefmt = '%d-%b-%y %H:%M:%S' )
247- logger .getLogger ().setLevel (int (10 ))
248-
249- ccdb = Ccdb ('http://ccdb-test.cern.ch:8080' )
250-
251- data = {'somekey' : 'somevalue' }
252- metadata = {'RunNumber' : '213564' , 'test' : 'on' }
253- version_info = ObjectVersion (path = "qc/TST/MO/repo/test" , validFrom = 1605091858183 , validTo = 1920451858183 , metadata = metadata )
254- ccdb .putVersion (version_info , data )
255-
256-
257- if __name__ == "__main__" : # to be able to run the test code above when not imported.
258- main ()
0 commit comments