From db2c294e180feeac6f24f116e980e90dd2530f08 Mon Sep 17 00:00:00 2001 From: Matias Carrasco Kind Date: Thu, 21 Jul 2016 14:33:33 -0500 Subject: [PATCH 01/16] dev version --- easyaccess/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easyaccess/version.py b/easyaccess/version.py index a65b385..ae69fe5 100644 --- a/easyaccess/version.py +++ b/easyaccess/version.py @@ -17,7 +17,7 @@ # versions.sort() # return versions[-1] -version_tag = (1, 3, 1) +version_tag = (1, 3, 2, 'dev') __version__ = '.'.join(map(str, version_tag[:3])) if len(version_tag) > 3: From ee6125d346e5c665a8077f4b1d7881492035e9f2 Mon Sep 17 00:00:00 2001 From: Matias Carrasco Kind Date: Thu, 21 Jul 2016 14:34:43 -0500 Subject: [PATCH 02/16] add api file --- easyaccess/eautils/db_api.py | 462 +++++++++++++++++++++++++++++++++++ 1 file changed, 462 insertions(+) create mode 100644 easyaccess/eautils/db_api.py diff --git a/easyaccess/eautils/db_api.py b/easyaccess/eautils/db_api.py new file mode 100644 index 0000000..7b73cc4 --- /dev/null +++ b/easyaccess/eautils/db_api.py @@ -0,0 +1,462 @@ +from __future__ import print_function +""" +api client to access cutout services in DES for coadded images and Single Exposures +""" +__author__ = 'Matias Carrasco Kind' +import easyaccess.config_ea as config_mod +import os +import stat +import getpass +import requests +import time +import easyaccess + +DESFILE = os.getenv("DES_SERVICES") +if not DESFILE: + DESFILE = os.path.join(os.getenv("HOME"), ".desservices.ini") +if os.path.exists(DESFILE): + AMODE = stat.S_IMODE(os.stat(DESFILE).st_mode) + if AMODE != 2 ** 8 + 2 ** 7: + print('Changing permissions to des_service file to read/write only by user') + os.chmod(DESFILE, 2 ** 8 + 2 ** 7) + +class Token(object): + """ + Token object that keeps track of tockes created to make requests + """ + def __init__(self, token, url): + self.value = token + self.url = url + self._active = True + def __repr__(self): + return 'Token(token=%s, url=%s)' % (self.value, self.url) + def __str__(self): + return self.value + def ttl(self): + """ + Time-To-Live (ttl) prints out the time in seconds for the current token + """ + req = self.url+'/api/token/?token=%s' % self.value + temp = requests.get(req) + if temp.json()['status'] == 'ok': + self._active = True + else: + self._active = False + print(temp.json()['message']) + + @property + def active(self): + """ + Checks whether the token is still active and valid + """ + req = self.url+'/api/token/?token=%s' % self.value + temp = requests.get(req) + if temp.json()['status'] == 'ok': + self._active = True + else: + self._active = False + return self._active + + +class DesCoaddCuts(object): + """ + This Class handles the object for the cutouts + + Parameters: + ----------- + + user (optional) : DB username + passwd (optional) : DB password + root_url (optional) : The url for the cutouts API + db (optional) : DB to be used (default: desoper) + verbose (optional) : print extra information + """ + def __init__(self, user=None, root_url=None, db='desoper', verbose=True): + passwd = None + self.desconf = config_mod.get_desconfig(DESFILE, db) + self._db = db + self.verbose = verbose + self.jobid = None + self.token = None + self.submit = None + self._status = None + self.job = None + self.links = None + self.files = [] + if user is not None: + if self.verbose: + print('Bypassing .desservices file with user : %s' % user) + if passwd is None: + passwd = getpass.getpass(prompt='Enter password : ') + self.desconf.set('db-' + self._db, 'user', user) + self.desconf.set('db-' + self._db, 'passwd', passwd) + self.user = self.desconf.get('db-' + self._db, 'user') + self._passwd = self.desconf.get('db-' + self._db, 'passwd') + self.root_url = root_url + + def get_token(self): + """Generate a new token using user and password in the API.""" + ext = '/api/token/?username={0}&password={1}'.format(self.user, self._passwd) + req = self.root_url+ext + res = requests.get(req) + status = res.json()['status'] + if status == 'ok': + self.token = Token(res.json()['token'], self.root_url) + else: + self.token = None + if self.verbose: + print(res.json()['message']) + return self.token.value + + def make_cuts(self, ra, dec, xsize=None, ysize=None, email=None, wait=False, timeout=3600): + """ + Submit a job to generate the cuts on the server side, if wait keyword id + True the functions waits until the job is completed + """ + assert len(ra) == len(dec), 'ra and dec must have same dimension' + req = self.root_url+'/api/?token={}&ra={}&dec={}'.format(self.token, ra, dec) + if xsize is not None: + req += '&xsize={}'.format(xsize) + if ysize is not None: + req += '&ysize={}'.format(ysize) + if email is not None: + req += '&email={}'.format(email) + self.submit = requests.get(req) + self._status = 'Submitted' + if self.verbose: + print(self.submit.json()['message']) + if self.submit.json()['status'] == 'ok': + self.jobid = self.submit.json()['job'] + elif self.submit.json()['status'] == 'error': + self.jobid = None + if not self.verbose: + print(self.submit.json()['message']) + else: + assert False, self.submit.text + if wait: + t_init = time.time() + if self.submit.json()['status'] == 'ok': + req = self.root_url+'/api/jobs/?token={}&jobid={}'.format(self.token, self.jobid) + for _ in range(1000): + self.job = requests.get(req) + if self.job.json()['status'] == 'ok': + self._status = self.job.json()['status'] + if self.verbose: + print(self.job.json()['message']) + break + if time.time() - t_init > timeout: + break + if self._status != 'ok': + print('Job is taking longer than expected, will continue running but check status later') + + @property + def status(self): + """Return the status of the submited job (if any).""" + if self.jobid is None: + return 'No jobs has been submitted' + else: + req = self.root_url+'/api/jobs/?token={}&jobid={}'.format(self.token, self.jobid) + self.job = requests.get(req) + try: + self._status = self.job.json()['status'] + return self.job.json()['message'] + except: + self._status = 'Error!' + return self.job.text + + def get_files(self, folder=None, print_only=False, force=True): + """Copy all files generated to local folder.""" + if self._status == 'ok': + self.links = self.job.json()['links'] + if folder is not None: + if not os.path.exists(folder): + os.mkdir(folder) + else: + folder = '' + k = 0 + for link in self.links: + if link.endswith('png') or link.endswith('fits'): + temp_file = os.path.join(folder, os.path.basename(link)) + self.files.append(temp_file) + if print_only: + print(temp_file) + else: + if not force: + if os.path.exists(temp_file): + continue + req = requests.get(link, stream=True) + if req.status_code == 200: + with open(temp_file, 'wb') as temp_file: + for chunk in req: + temp_file.write(chunk) + k += 1 + if self.verbose: + print('%d files copied to local server' % k) + else: + print('Something went wrong with the job') + + + def show_pngs(self, folder=None, limit=100): + """Display all pngs generated after copying files in local directory.""" + from IPython.display import Image, display + if folder is None: + folder = '' + displayed = 0 + for file_png in self.files: + if file_png.endswith('.png'): + if displayed == limit: + break + temp_display = Image(filename=os.path.join(folder, file_png)) + display(temp_display) + displayed += 1 + + +class DesSingleCuts(object): + """ + This Class handles the object for the cutouts for Single Exposures + + Parameters: + ----------- + + user (optional) : DB username + passwd (optional) : DB password + root_url (optional) : The url for the cutouts API + db (optional) : DB to be used (default: desoper) + verbose (optional) : print extra information + """ + def __init__(self, user=None, root_url=None, db='desoper', verbose=True): + passwd = None + self.desconf = config_mod.get_desconfig(DESFILE, db) + self._db = db + self.verbose = verbose + self.jobid = None + self.token = None + self.submit = None + self._status = None + self.job = None + self.links = None + self.files = [] + if user is not None: + if self.verbose: + print('Bypassing .desservices file with user : %s' % user) + if passwd is None: + passwd = getpass.getpass(prompt='Enter password : ') + self.desconf.set('db-' + self._db, 'user', user) + self.desconf.set('db-' + self._db, 'passwd', passwd) + self.user = self.desconf.get('db-' + self._db, 'user') + self._passwd = self.desconf.get('db-' + self._db, 'passwd') + self.root_url = root_url + + def get_token(self): + """Generate a new token using user and password in the API.""" + ext = '/api/token/?username={0}&password={1}'.format(self.user, self._passwd) + req = self.root_url+ext + res = requests.get(req) + status = res.json()['status'] + if status == 'ok': + self.token = Token(res.json()['token'], self.root_url) + else: + self.token = None + if self.verbose: + print(res.json()['message']) + return self.token.value + + def make_cuts(self, ra, dec, xsize=None, ysize=None, email=None, bands=None, blacklist=False, wait=False, timeout=3600): + """ + Submit a job to generate the cuts on the server side, if wait keyword id + True the functions waits until the job is completed + """ + assert len(ra) == len(dec), 'ra and dec must have same dimension' + req = self.root_url+'/api/?token={}&ra={}&dec={}'.format(self.token, ra, dec) + if xsize is not None: + req += '&xsize={}'.format(xsize) + if ysize is not None: + req += '&ysize={}'.format(ysize) + if bands is not None: + req += '&bands={}'.format(bands) + if email is not None: + req += '&email={}'.format(email) + self.submit = requests.get(req) + self._status = 'Submitted' + if self.verbose: + print(self.submit.json()['message']) + if self.submit.json()['status'] == 'ok': + self.jobid = self.submit.json()['job'] + elif self.submit.json()['status'] == 'error': + self.jobid = None + if not self.verbose: + print(self.submit.json()['message']) + else: + assert False, self.submit.text + if wait: + t_init = time.time() + if self.submit.json()['status'] == 'ok': + req = self.root_url+'/api/jobs/?token={}&jobid={}'.format(self.token, self.jobid) + for _ in range(1000): + self.job = requests.get(req) + if self.job.json()['status'] == 'ok': + self._status = self.job.json()['status'] + self.links = self.job.json()['links'] + if self.verbose: + print(self.job.json()['message']) + break + if time.time() - t_init > timeout: + break + if self._status != 'ok': + print('Job is taking longer than expected, will continue running but check status later') + + @property + def status(self): + """Return the status of the submited job (if any).""" + if self.jobid is None: + return 'No jobs has been submitted' + else: + req = self.root_url+'/api/jobs/?token={}&jobid={}'.format(self.token, self.jobid) + self.job = requests.get(req) + try: + self._status = self.job.json()['status'] + return self.job.json()['message'] + except: + self._status = 'Error!' + return self.job.text + + def get_files(self, folder=None, print_only=False, force=True): + """Copy all files generated to local folder.""" + if self._status == 'ok': + self.links = self.job.json()['links'] + if folder is not None: + if not os.path.exists(folder): + os.mkdir(folder) + else: + folder = '' + k = 0 + for link in self.links: + link = link.replace('.edu','.edu:8000') + if link.endswith('png') or link.endswith('fits'): + temp_file = os.path.join(folder, os.path.basename(link)) + self.files.append(temp_file) + if print_only: + print(temp_file) + else: + if not force: + if os.path.exists(temp_file): + continue + req = requests.get(link, stream=True) + if req.status_code == 200: + with open(temp_file, 'wb') as temp_file: + for chunk in req: + temp_file.write(chunk) + k += 1 + if self.verbose: + print('%d files copied to local server' % k) + else: + print('Something went wrong with the job') + + + def show_pngs(self, folder=None, limit=100): + """Display all pngs generated after copying files in local directory.""" + from IPython.display import Image, display + if folder is None: + folder = '' + displayed = 0 + for file_png in self.files: + if file_png.endswith('.png'): + if displayed == limit: + break + temp_display = Image(filename=file_png) + display(temp_display) + displayed += 1 + +class DesSingleExposure(object): + """ + This Class handles the object for Single Exposures and individual CCDs + + Parameters: + ----------- + + user (optional) : DB username + passwd (optional) : DB password + root_url (optional) : The url for the cutouts API + db (optional) : DB to be used (default: desoper) + verbose (optional) : print extra information + """ + + def __init__(self, user=None, root_url='https://desar2.cosmology.illinois.edu/DESFiles/desarchive/', db='desoper', verbose=True): + passwd = None + self.desconf = config_mod.get_desconfig(DESFILE, db) + self._db = db + self.verbose = verbose + self.links = [] + self.files = [] + if user is not None: + if self.verbose: + print('Bypassing .desservices file with user : %s' % user) + if passwd is None: + passwd = getpass.getpass(prompt='Enter password : ') + self.desconf.set('db-' + self._db, 'user', user) + self.desconf.set('db-' + self._db, 'passwd', passwd) + self.user = self.desconf.get('db-' + self._db, 'user') + self._passwd = self.desconf.get('db-' + self._db, 'passwd') + self.root_url = root_url + self.base_query=""" + SELECT + file_archive_info.PATH || '/' || file_archive_info.FILENAME || file_archive_info.COMPRESSION as path, + image.PFW_ATTEMPT_ID, + ops_proctag.UNITNAME, + image.BAND, + image.CCDNUM, + image.NITE, + image.EXPNUM + FROM + ops_proctag, image, file_archive_info + WHERE + file_archive_info.FILENAME = image.FILENAME AND + image.PFW_ATTEMPT_ID = ops_proctag.PFW_ATTEMPT_ID AND + image.FILETYPE = 'red_immask' AND + ops_proctag.TAG = '{tag}' AND + image.EXPNUM = {expnum} AND image.CCDNUM in ({ccd}); + """ + + def get_paths(self, expnum, ccd, tag='Y3A1_FINALCUT'): + + try: + ccd=','.join(map(str,ccd)) + except: + pass + inputs = dict(expnum=expnum, ccd=ccd, tag=tag) + self.base_query = self.base_query.format(**inputs) + print(self.base_query) + con = easyaccess.connect(self._db, user=self.user, passwd=self._passwd) + self.data = con.query_to_pandas(self.base_query) + print(self.data) + for j in range(len(self.data)): + self.links.append(self.root_url + self.data.PATH.ix[j]) + + + def get_files(self, folder=None, print_only=False, force=True): + """Copy all files to local folder.""" + + if folder is not None: + if not os.path.exists(folder): + os.mkdir(folder) + else: + folder = '' + k = 0 + for link in self.links: + temp_file = os.path.join(folder, os.path.basename(link)) + self.files.append(temp_file) + if print_only: + print(temp_file) + else: + if not force: + if os.path.exists(temp_file): + continue + req = requests.get(link, stream=True, auth=(self.user, self._passwd)) + if req.status_code == 200: + with open(temp_file, 'wb') as temp_file: + for chunk in req: + temp_file.write(chunk) + k += 1 + if self.verbose: + print('%d files copied to local server' % k) + From f2901e5f5bb1ea028ecdb357942796e2644b2237 Mon Sep 17 00:00:00 2001 From: Matias Carrasco Kind Date: Thu, 21 Jul 2016 14:46:44 -0500 Subject: [PATCH 03/16] update __init__ files --- easyaccess/__init__.py | 3 +++ easyaccess/eautils/__init__.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/easyaccess/__init__.py b/easyaccess/__init__.py index 3d25db3..34e08f3 100644 --- a/easyaccess/__init__.py +++ b/easyaccess/__init__.py @@ -1,5 +1,8 @@ from .easyaccess import * from .version import __version__ +from eautils import db_api as api version = __version__ __all__ = ["eautils", "config_ea", "easyaccess", "version"] + + diff --git a/easyaccess/eautils/__init__.py b/easyaccess/eautils/__init__.py index 847905d..f7f8094 100644 --- a/easyaccess/eautils/__init__.py +++ b/easyaccess/eautils/__init__.py @@ -1 +1 @@ -__all__=["des_logo", "dircache", "dtypes", "fileio","fun_utils","import_utils"] +__all__=["db_api","des_logo", "dircache", "dtypes", "fileio","fun_utils","import_utils"] From ce125cb190ad578cd36905adb14632dc56bfe5da Mon Sep 17 00:00:00 2001 From: Matias Carrasco Kind Date: Thu, 21 Jul 2016 16:02:56 -0500 Subject: [PATCH 04/16] fixed typo init file --- easyaccess/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easyaccess/__init__.py b/easyaccess/__init__.py index 34e08f3..89c3a40 100644 --- a/easyaccess/__init__.py +++ b/easyaccess/__init__.py @@ -1,6 +1,6 @@ from .easyaccess import * from .version import __version__ -from eautils import db_api as api +from .eautils import db_api as api version = __version__ __all__ = ["eautils", "config_ea", "easyaccess", "version"] From 4a03bddb9d8c1756e718c30afc9ee1480197a678 Mon Sep 17 00:00:00 2001 From: Matias Carrasco Kind Date: Sat, 27 Aug 2016 13:00:14 -0500 Subject: [PATCH 05/16] updated api for new descut --- easyaccess/eautils/db_api.py | 136 ++++++++++++++++++++++++++++++++--- 1 file changed, 125 insertions(+), 11 deletions(-) diff --git a/easyaccess/eautils/db_api.py b/easyaccess/eautils/db_api.py index 7b73cc4..c2f9552 100644 --- a/easyaccess/eautils/db_api.py +++ b/easyaccess/eautils/db_api.py @@ -58,6 +58,96 @@ def active(self): return self._active +class Job(object): + def __init__(self,jobid, user, token, url): + self._jobid = jobid + self._user = user + self._token = token + self._url = url + def __repr__(self): + return 'Job(jobid=%s, user=%s, token=%s, url=%s)' % (self._jobid, self._user, self._token, self._url) + def __str__(self): + return self._jobid + @property + def status(self): + req = self._url+'/api/jobs/?token=%s&jobid=%s' % (self._token, self._jobid) + temp = requests.get(req) + if temp.json()['status'] == 'ok': + self._status = temp.json()['job_status'] + else: + self._status = 'Error' + return self._status + + def __del__(self): + req = self._url+'/api/jobs/?token=%s&jobid=%s' % (self._token, self._jobid) + temp = requests.delete(req) + if temp.json()['status'] == 'ok': + print('Job %s was deleted from the DB' % self._jobid) + else: + print(temp.text) + + + + + +class MyJobs(object): + + def __init__(self, user=None, token=None, root_url=None, db='desoper', verbose=False): + passwd = None + self.desconf = config_mod.get_desconfig(DESFILE, db) + self._db = db + self.verbose = verbose + self.jobid = None + self.token = None + self.submit = None + self._status = None + self.job = None + self.links = None + self.files = [] + if user is not None: + if self.verbose: + print('Bypassing .desservices file with user : %s' % user) + if passwd is None: + passwd = getpass.getpass(prompt='Enter password : ') + self.desconf.set('db-' + self._db, 'user', user) + self.desconf.set('db-' + self._db, 'passwd', passwd) + self.user = self.desconf.get('db-' + self._db, 'user') + self._passwd = self.desconf.get('db-' + self._db, 'passwd') + self.root_url = root_url.strip('/') + self.get_token() + temp = requests.get(self.root_url+'/api/jobs/?token=%s&list_jobs' % self.token) + self._jobs = [Job(j, self.user, self.token, self.root_url) for j in temp.json()['list_jobs']] + + + def get_token(self): + """Generate a new token using user and password in the API.""" + ext = '/api/token/' + req = self.root_url+ext + res = requests.post(req, data={'username': self.user, 'password' : self._passwd}) + status = res.json()['status'] + if status == 'ok': + self.token = Token(res.json()['token'], self.root_url) + else: + self.token = None + + + def __len__(self): + return len(self._jobs) + + def __repr__(self): + return 'My Jobs (%d in total)' % len(self._jobs) + + def __getitem__(self,index): + return self._jobs[index] + + def __delitem__(self,index): + del self._jobs[index] + return + + @property + def list(self): + return self._jobs + class DesCoaddCuts(object): """ This Class handles the object for the cutouts @@ -92,13 +182,13 @@ def __init__(self, user=None, root_url=None, db='desoper', verbose=True): self.desconf.set('db-' + self._db, 'passwd', passwd) self.user = self.desconf.get('db-' + self._db, 'user') self._passwd = self.desconf.get('db-' + self._db, 'passwd') - self.root_url = root_url + self.root_url = root_url.strip('/') def get_token(self): """Generate a new token using user and password in the API.""" - ext = '/api/token/?username={0}&password={1}'.format(self.user, self._passwd) + ext = '/api/token/' req = self.root_url+ext - res = requests.get(req) + res = requests.post(req, data={'username': self.user, 'password' : self._passwd}) status = res.json()['status'] if status == 'ok': self.token = Token(res.json()['token'], self.root_url) @@ -108,20 +198,41 @@ def get_token(self): print(res.json()['message']) return self.token.value - def make_cuts(self, ra, dec, xsize=None, ysize=None, email=None, wait=False, timeout=3600): + def make_cuts(self, ra=None, dec=None, csvfile = None, xsize=None, ysize=None, email=None, list_only=False, wait=False, timeout=3600): """ Submit a job to generate the cuts on the server side, if wait keyword id True the functions waits until the job is completed """ - assert len(ra) == len(dec), 'ra and dec must have same dimension' - req = self.root_url+'/api/?token={}&ra={}&dec={}'.format(self.token, ra, dec) + req = self.root_url+'/api/jobs/' + self.body = { 'token': self.token.value, 'list_only': 'false', 'job_type':'coadd' } + if ra is not None: + try: + self.body['ra'] = str(list(ra)) + self.body['dec'] = str(list(dec)) + except: + self.body['ra'] = str(ra) + self.body['dec'] = str(dec) if xsize is not None: - req += '&xsize={}'.format(xsize) + try: + self.body['xsize'] = str(list(xsize)) + except: + self.body['xsize'] = str(xsize) if ysize is not None: - req += '&ysize={}'.format(ysize) + try: + self.body['ysize'] = str(list(ysize)) + except: + self.body['ysize'] = str(ysize) if email is not None: - req += '&email={}'.format(email) - self.submit = requests.get(req) + self.body['email'] = email + if list_only: + self.body['list_only'] = 'true' + if csvfile is not None: + self.body['ra'] = '0,0' + self.body['dec'] = '0,0' + self.body_files = {'csvfile': open(csvfile,'rb')} + self.submit = requests.post(req, data=self.body, files=self.body_files) + else: + self.submit = requests.post(req, data=self.body) self._status = 'Submitted' if self.verbose: print(self.submit.json()['message']) @@ -139,7 +250,8 @@ def make_cuts(self, ra, dec, xsize=None, ysize=None, email=None, wait=False, tim req = self.root_url+'/api/jobs/?token={}&jobid={}'.format(self.token, self.jobid) for _ in range(1000): self.job = requests.get(req) - if self.job.json()['status'] == 'ok': + if self.job.json()['job_status'] == 'SUCCESS': + requests.get(self.root_url+'/api/refresh/?user={}&jid={}'.format(self.user, self.jobid)) self._status = self.job.json()['status'] if self.verbose: print(self.job.json()['message']) @@ -159,6 +271,8 @@ def status(self): self.job = requests.get(req) try: self._status = self.job.json()['status'] + if self._status == 'ok': + requests.get(self.root_url+'/api/refresh/?user={}&jid={}'.format(self.user, self.jobid)) return self.job.json()['message'] except: self._status = 'Error!' From 124cbad687208b30d844b2b42b475f8000cc8f8a Mon Sep 17 00:00:00 2001 From: Matias Carrasco Kind Date: Sat, 27 Aug 2016 13:05:42 -0500 Subject: [PATCH 06/16] updated version --- easyaccess/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easyaccess/version.py b/easyaccess/version.py index ae69fe5..0403440 100644 --- a/easyaccess/version.py +++ b/easyaccess/version.py @@ -17,7 +17,7 @@ # versions.sort() # return versions[-1] -version_tag = (1, 3, 2, 'dev') +version_tag = (1, 3, 2, 'dev-4a03bdd') __version__ = '.'.join(map(str, version_tag[:3])) if len(version_tag) > 3: From 5cde1b873f909d371deecf070ede486f2429ffa4 Mon Sep 17 00:00:00 2001 From: Matias Carrasco Kind Date: Sat, 27 Aug 2016 17:26:13 -0500 Subject: [PATCH 07/16] final touch to cutout api --- easyaccess/eautils/db_api.py | 39 +++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/easyaccess/eautils/db_api.py b/easyaccess/eautils/db_api.py index c2f9552..371a07f 100644 --- a/easyaccess/eautils/db_api.py +++ b/easyaccess/eautils/db_api.py @@ -72,8 +72,12 @@ def __str__(self): def status(self): req = self._url+'/api/jobs/?token=%s&jobid=%s' % (self._token, self._jobid) temp = requests.get(req) + self.req_status = temp.json()['status'] + self.message = temp.json()['message'] if temp.json()['status'] == 'ok': self._status = temp.json()['job_status'] + if temp.json()['job_status'] == 'SUCCESS': + self.links = temp.json()['links'] else: self._status = 'Error' return self._status @@ -86,6 +90,14 @@ def __del__(self): else: print(temp.text) + def __delete__(self): + req = self._url+'/api/jobs/?token=%s&jobid=%s' % (self._token, self._jobid) + temp = requests.delete(req) + if temp.json()['status'] == 'ok': + print('Job %s was deleted from the DB' % self._jobid) + else: + print(temp.text) + @@ -237,24 +249,20 @@ def make_cuts(self, ra=None, dec=None, csvfile = None, xsize=None, ysize=None, e if self.verbose: print(self.submit.json()['message']) if self.submit.json()['status'] == 'ok': - self.jobid = self.submit.json()['job'] + self.job = Job(self.submit.json()['job'], self.user, self.token, self.root_url) elif self.submit.json()['status'] == 'error': - self.jobid = None + self.job = None if not self.verbose: print(self.submit.json()['message']) else: assert False, self.submit.text if wait: t_init = time.time() - if self.submit.json()['status'] == 'ok': - req = self.root_url+'/api/jobs/?token={}&jobid={}'.format(self.token, self.jobid) + if self.job is not None: for _ in range(1000): - self.job = requests.get(req) - if self.job.json()['job_status'] == 'SUCCESS': + if self.job.status == 'SUCCESS': requests.get(self.root_url+'/api/refresh/?user={}&jid={}'.format(self.user, self.jobid)) - self._status = self.job.json()['status'] - if self.verbose: - print(self.job.json()['message']) + self._status = self.job.req_status break if time.time() - t_init > timeout: break @@ -264,16 +272,15 @@ def make_cuts(self, ra=None, dec=None, csvfile = None, xsize=None, ysize=None, e @property def status(self): """Return the status of the submited job (if any).""" - if self.jobid is None: + if self.job is None: return 'No jobs has been submitted' else: - req = self.root_url+'/api/jobs/?token={}&jobid={}'.format(self.token, self.jobid) - self.job = requests.get(req) try: - self._status = self.job.json()['status'] - if self._status == 'ok': + status = self.job.status + if status == 'SUCCESS': + self._status = 'ok' requests.get(self.root_url+'/api/refresh/?user={}&jid={}'.format(self.user, self.jobid)) - return self.job.json()['message'] + return status except: self._status = 'Error!' return self.job.text @@ -281,7 +288,7 @@ def status(self): def get_files(self, folder=None, print_only=False, force=True): """Copy all files generated to local folder.""" if self._status == 'ok': - self.links = self.job.json()['links'] + self.links = self.job.links if folder is not None: if not os.path.exists(folder): os.mkdir(folder) From 57e86ec5efc8980ba809e88ae0f42be021bbbede Mon Sep 17 00:00:00 2001 From: Matias Carrasco Kind Date: Sat, 27 Aug 2016 17:28:42 -0500 Subject: [PATCH 08/16] update version --- easyaccess/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easyaccess/version.py b/easyaccess/version.py index 0403440..de167ee 100644 --- a/easyaccess/version.py +++ b/easyaccess/version.py @@ -17,7 +17,7 @@ # versions.sort() # return versions[-1] -version_tag = (1, 3, 2, 'dev-4a03bdd') +version_tag = (1, 3, 2, 'dev-5cde1b8') __version__ = '.'.join(map(str, version_tag[:3])) if len(version_tag) > 3: From 8252c36a1e944120c124da4cfd43823b2dd42749 Mon Sep 17 00:00:00 2001 From: Matias Carrasco Kind Date: Mon, 29 Aug 2016 00:19:39 -0500 Subject: [PATCH 09/16] remove __del__ method and added delete method to avoid deletion on overriding jobs --- easyaccess/eautils/db_api.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/easyaccess/eautils/db_api.py b/easyaccess/eautils/db_api.py index 371a07f..73d50ee 100644 --- a/easyaccess/eautils/db_api.py +++ b/easyaccess/eautils/db_api.py @@ -82,22 +82,18 @@ def status(self): self._status = 'Error' return self._status - def __del__(self): - req = self._url+'/api/jobs/?token=%s&jobid=%s' % (self._token, self._jobid) - temp = requests.delete(req) - if temp.json()['status'] == 'ok': - print('Job %s was deleted from the DB' % self._jobid) - else: - print(temp.text) - def __delete__(self): req = self._url+'/api/jobs/?token=%s&jobid=%s' % (self._token, self._jobid) temp = requests.delete(req) if temp.json()['status'] == 'ok': print('Job %s was deleted from the DB' % self._jobid) + print('mm') else: print(temp.text) + def delete(self): + return self.__delete__() + @@ -127,8 +123,8 @@ def __init__(self, user=None, token=None, root_url=None, db='desoper', verbose=F self._passwd = self.desconf.get('db-' + self._db, 'passwd') self.root_url = root_url.strip('/') self.get_token() - temp = requests.get(self.root_url+'/api/jobs/?token=%s&list_jobs' % self.token) - self._jobs = [Job(j, self.user, self.token, self.root_url) for j in temp.json()['list_jobs']] + self.jobs_info = requests.get(self.root_url+'/api/jobs/?token=%s&list_jobs' % self.token) + self._jobs = [Job(j, self.user, self.token, self.root_url) for j in self.jobs_info.json()['list_jobs']] def get_token(self): @@ -259,13 +255,14 @@ def make_cuts(self, ra=None, dec=None, csvfile = None, xsize=None, ysize=None, e if wait: t_init = time.time() if self.job is not None: - for _ in range(1000): + for _ in range(100000): if self.job.status == 'SUCCESS': requests.get(self.root_url+'/api/refresh/?user={}&jid={}'.format(self.user, self.jobid)) self._status = self.job.req_status break if time.time() - t_init > timeout: break + time.sleep(0.5) if self._status != 'ok': print('Job is taking longer than expected, will continue running but check status later') From 016ca384dcf0095e7fea8c7535336683a400f822 Mon Sep 17 00:00:00 2001 From: Matias Carrasco Kind Date: Mon, 29 Aug 2016 00:21:36 -0500 Subject: [PATCH 10/16] update version --- easyaccess/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easyaccess/version.py b/easyaccess/version.py index de167ee..72ccabe 100644 --- a/easyaccess/version.py +++ b/easyaccess/version.py @@ -17,7 +17,7 @@ # versions.sort() # return versions[-1] -version_tag = (1, 3, 2, 'dev-5cde1b8') +version_tag = (1, 3, 2, 'dev-8252c36') __version__ = '.'.join(map(str, version_tag[:3])) if len(version_tag) > 3: From 04c8eba513ee4ed375b16cae77a2569628858f37 Mon Sep 17 00:00:00 2001 From: Matias Carrasco Kind Date: Mon, 29 Aug 2016 00:29:37 -0500 Subject: [PATCH 11/16] added creation times and job types to My Jobs --- easyaccess/eautils/db_api.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/easyaccess/eautils/db_api.py b/easyaccess/eautils/db_api.py index 73d50ee..624513b 100644 --- a/easyaccess/eautils/db_api.py +++ b/easyaccess/eautils/db_api.py @@ -123,8 +123,10 @@ def __init__(self, user=None, token=None, root_url=None, db='desoper', verbose=F self._passwd = self.desconf.get('db-' + self._db, 'passwd') self.root_url = root_url.strip('/') self.get_token() - self.jobs_info = requests.get(self.root_url+'/api/jobs/?token=%s&list_jobs' % self.token) - self._jobs = [Job(j, self.user, self.token, self.root_url) for j in self.jobs_info.json()['list_jobs']] + self.jobs_info = requests.get(self.root_url+'/api/jobs/?token=%s&list_jobs' % self.token).json() + self._jobs = [Job(j, self.user, self.token, self.root_url) for j in self.jobs_info['list_jobs']] + self.creation_times=self.jobs_info['creation_time'] + self.job_types=self.jobs_info['job_type'] def get_token(self): From 0ef5feaa9c73b9b27ce464d9e109ee162e9b5ad7 Mon Sep 17 00:00:00 2001 From: Matias Carrasco Kind Date: Mon, 29 Aug 2016 00:30:19 -0500 Subject: [PATCH 12/16] update version --- easyaccess/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easyaccess/version.py b/easyaccess/version.py index 72ccabe..fb09a19 100644 --- a/easyaccess/version.py +++ b/easyaccess/version.py @@ -17,7 +17,7 @@ # versions.sort() # return versions[-1] -version_tag = (1, 3, 2, 'dev-8252c36') +version_tag = (1, 3, 2, 'dev-04c8eba') __version__ = '.'.join(map(str, version_tag[:3])) if len(version_tag) > 3: From 99e884d08fe29e65b73730381d45e842603a35e3 Mon Sep 17 00:00:00 2001 From: Matias Carrasco Kind Date: Mon, 29 Aug 2016 00:37:42 -0500 Subject: [PATCH 13/16] remove extra print --- easyaccess/eautils/db_api.py | 1 - 1 file changed, 1 deletion(-) diff --git a/easyaccess/eautils/db_api.py b/easyaccess/eautils/db_api.py index 624513b..93074f6 100644 --- a/easyaccess/eautils/db_api.py +++ b/easyaccess/eautils/db_api.py @@ -87,7 +87,6 @@ def __delete__(self): temp = requests.delete(req) if temp.json()['status'] == 'ok': print('Job %s was deleted from the DB' % self._jobid) - print('mm') else: print(temp.text) From bda4d593e5e161c482ded841fd9d40b1e9a3ffb8 Mon Sep 17 00:00:00 2001 From: Matias Carrasco Kind Date: Mon, 29 Aug 2016 00:38:08 -0500 Subject: [PATCH 14/16] update version --- easyaccess/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easyaccess/version.py b/easyaccess/version.py index fb09a19..022603c 100644 --- a/easyaccess/version.py +++ b/easyaccess/version.py @@ -17,7 +17,7 @@ # versions.sort() # return versions[-1] -version_tag = (1, 3, 2, 'dev-04c8eba') +version_tag = (1, 3, 2, 'dev-99e884d') __version__ = '.'.join(map(str, version_tag[:3])) if len(version_tag) > 3: From 01ae3bc131952272ddde962c78b6419c0cefbef5 Mon Sep 17 00:00:00 2001 From: Matias Carrasco Kind Date: Mon, 29 Aug 2016 00:47:34 -0500 Subject: [PATCH 15/16] reset self.files for every job --- easyaccess/eautils/db_api.py | 1 + 1 file changed, 1 insertion(+) diff --git a/easyaccess/eautils/db_api.py b/easyaccess/eautils/db_api.py index 93074f6..88893cf 100644 --- a/easyaccess/eautils/db_api.py +++ b/easyaccess/eautils/db_api.py @@ -286,6 +286,7 @@ def status(self): def get_files(self, folder=None, print_only=False, force=True): """Copy all files generated to local folder.""" if self._status == 'ok': + self.files = [] self.links = self.job.links if folder is not None: if not os.path.exists(folder): From 8af2fd9153572af3b2e608c43e0554bac9da034c Mon Sep 17 00:00:00 2001 From: Matias Carrasco Kind Date: Mon, 29 Aug 2016 00:48:09 -0500 Subject: [PATCH 16/16] update version --- easyaccess/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easyaccess/version.py b/easyaccess/version.py index 022603c..aa7b227 100644 --- a/easyaccess/version.py +++ b/easyaccess/version.py @@ -17,7 +17,7 @@ # versions.sort() # return versions[-1] -version_tag = (1, 3, 2, 'dev-99e884d') +version_tag = (1, 3, 2, 'dev-01ae3bc') __version__ = '.'.join(map(str, version_tag[:3])) if len(version_tag) > 3: