Skip to content

Commit

Permalink
make unexpected SAS termination an exception instead of just an error…
Browse files Browse the repository at this point in the history
… message
  • Loading branch information
tomweber-sas committed Jan 9, 2024
1 parent f6ec652 commit e7b1cee
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 64 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ gen
.idea/
build/
dist/
misc/
saspy/__pycache__/
8 changes: 8 additions & 0 deletions saspy/sasexceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ def __str__(self):
return 'Failure establishing SASsession.\n{}'.format(self.msg+extra)


class SASIOConnectionTerminated(Exception):
def __init__(self, msg: str):
self.msg = msg

def __str__(self):
return 'No SAS process attached. SAS process has terminated unexpectedly.\n{}'.format(self.msg)


class SASHTTPauthenticateError(Exception):
def __init__(self, msg: str):
self.msg = msg
Expand Down
8 changes: 5 additions & 3 deletions saspy/sasiohttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
from saspy.sasexceptions import (SASHTTPauthenticateError,
SASHTTPconnectionError,
SASHTTPsubmissionError,
SASDFNamesToLongError
SASDFNamesToLongError,
SASIOConnectionTerminated
)

import logging
Expand Down Expand Up @@ -1080,8 +1081,9 @@ def submit(self, code: str, results: str ="html", prompt: dict = None, **kwargs)
ods = True;

if self._session == None:
logger.error("No SAS process attached. SAS process has terminated unexpectedly.")
return dict(LOG="No SAS process attached. SAS process has terminated unexpectedly.", LST='')
#return dict(LOG="No SAS process attached. SAS process has terminated unexpectedly.", LST='')
logger.fatal("No SAS process attached. SAS process has terminated unexpectedly.")
raise SASIOConnectionTerminated(Exception)

if len(prompt):
pcodeiv = ''
Expand Down
83 changes: 53 additions & 30 deletions saspy/sasioiom.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
import logging
logger = logging.getLogger('saspy')

from saspy.sasexceptions import SASDFNamesToLongError
from saspy.sasexceptions import (SASDFNamesToLongError,
SASIOConnectionTerminated
)

try:
import pandas as pd
Expand Down Expand Up @@ -862,28 +864,35 @@ def submit(self, code: str, results: str ="html", prompt: dict = None, **kwargs)

if self.pid == None:
self._sb.SASpid = None
logger.error("No SAS process attached. SAS process has terminated unexpectedly.")
return dict(LOG="No SAS process attached. SAS process has terminated unexpectedly.", LST='')
#return dict(LOG="No SAS process attached. SAS process has terminated unexpectedly.", LST='')
logger.fatal("No SAS process attached. SAS process has terminated unexpectedly.")
raise SASIOConnectionTerminated(Exception)

if os.name == 'nt':
try:
rc = self.pid.wait(0)
self.pid = None
self._sb.SASpid = None
return dict(LOG='SAS process has terminated unexpectedly. RC from wait was: '+str(rc), LST='')
except:
#return dict(LOG='SAS process has terminated unexpectedly. RC from wait was: '+str(rc), LST='')
logger.fatal("SAS process has terminated unexpectedly. RC from wait was: "+str(rc))
raise SASIOConnectionTerminated(Exception)
except subprocess.TimeoutExpired:
pass
else:
if self.pid == None:
self._sb.SASpid = None
return "No SAS process attached. SAS process has terminated unexpectedly."
#return "No SAS process attached. SAS process has terminated unexpectedly."
logger.fatal("No SAS process attached. SAS process has terminated unexpectedly.")
raise SASIOConnectionTerminated(Exception)
#rc = os.waitid(os.P_PID, self.pid, os.WEXITED | os.WNOHANG)
rc = os.waitpid(self.pid, os.WNOHANG)
#if rc != None:
if rc[1]:
self.pid = None
self._sb.SASpid = None
return dict(LOG='SAS process has terminated unexpectedly. Pid State= '+str(rc), LST='')
#return dict(LOG='SAS process has terminated unexpectedly. Pid State= '+str(rc), LST='')
logger.fatal("SAS process has terminated unexpectedly. Pid State= "+str(rc))
raise SASIOConnectionTerminated(Exception)

# to cover the possibility of an _asubmit w/ lst output not read; no known cases now; used to be __flushlst__()
# removing this and adding comment in _asubmit to use _getlst[txt] so this will never be necessary; delete later
Expand Down Expand Up @@ -936,8 +945,10 @@ def submit(self, code: str, results: str ="html", prompt: dict = None, **kwargs)
self.pid = None
self._sb.SASpid = None
log = logf.partition(logcodeo)[0]+b'\nSAS process has terminated unexpectedly. RC from wait was: '+str(rc).encode()
return dict(LOG=log.decode(errors='replace'), LST='')
except:
#return dict(LOG=log.decode(errors='replace'), LST='')
logger.fatal(log.decode(errors='replace'))
raise SASIOConnectionTerminated(Exception)
except subprocess.TimeoutExpired:
pass
else:
#rc = os.waitid(os.P_PID, self.pid, os.WEXITED | os.WNOHANG)
Expand All @@ -947,7 +958,9 @@ def submit(self, code: str, results: str ="html", prompt: dict = None, **kwargs)
self.pid = None
self._sb.SASpid = None
log = logf.partition(logcodeo)[0]+b'\nSAS process has terminated unexpectedly. Pid State= '+str(rc).encode()
return dict(LOG=log.decode(errors='replace'), LST='')
#return dict(LOG=log.decode(errors='replace'), LST='')
logger.fatal(log.decode(errors='replace'))
raise SASIOConnectionTerminated(Exception)

if bail:
if lstf.count(logcodeo) >= 1:
Expand Down Expand Up @@ -993,7 +1006,9 @@ def submit(self, code: str, results: str ="html", prompt: dict = None, **kwargs)
self.pid = None
self._sb.SASpid = None
log =logf.partition(logcodeo)[0]+b'\nConnection Reset: SAS process has terminated unexpectedly. Pid State= '+str(rc).encode()
return dict(LOG=log.decode(errors='replace'), LST='')
#return dict(LOG=log.decode(errors='replace'), LST='')
logger.fatal(log.decode(errors='replace'))
raise SASIOConnectionTerminated(Exception)

except (KeyboardInterrupt, SystemExit):
print('Exception caught!')
Expand Down Expand Up @@ -1418,17 +1433,21 @@ def download(self, localfile: str, remotefile: str, overwrite: bool = True, **kw
rc = self.pid.wait(0)
self.pid = None
self._sb.SASpid = None
return {'Success' : False,
'LOG' : "SAS process has terminated unexpectedly. RC from wait was: "+str(rc)}
except:
#return {'Success' : False,
# 'LOG' : "SAS process has terminated unexpectedly. RC from wait was: "+str(rc)}
logger.fatal("SAS process has terminated unexpectedly. RC from wait was: "+str(rc))
raise SASIOConnectionTerminated(Exception)
except subprocess.TimeoutExpired:
pass
else:
rc = os.waitpid(self.pid, os.WNOHANG)
if rc[1]:
self.pid = None
self._sb.SASpid = None
return {'Success' : False,
'LOG' : "SAS process has terminated unexpectedly. RC from wait was: "+str(rc)}
self.pid = None
self._sb.SASpid = None
#return {'Success' : False,
# 'LOG' : "SAS process has terminated unexpectedly. RC from wait was: "+str(rc)}
logger.fatal("SAS process has terminated unexpectedly. Pid State= "+str(rc))
raise SASIOConnectionTerminated(Exception)

if bail:
if datar.count(logcodeb) >= 1:
Expand Down Expand Up @@ -1904,17 +1923,19 @@ def sasdata2dataframeCSV(self, table: str, libref: str ='', dsopts: dict = None,
rc = self.pid.wait(0)
self.pid = None
self._sb.SASpid = None
#return None
logger.fatal('\nSAS process has terminated unexpectedly. RC from wait was: '+str(rc))
return None
except:
raise SASIOConnectionTerminated(Exception)
except subprocess.TimeoutExpired:
pass
else:
rc = os.waitpid(self.pid, os.WNOHANG)
if rc[1]:
self.pid = None
self._sb.SASpid = None
logger.fatal('\nSAS process has terminated unexpectedly. RC from wait was: '+str(rc))
return None
self.pid = None
self._sb.SASpid = None
#return None
logger.fatal("\nSAS process has terminated unexpectedly. Pid State= "+str(rc))
raise SASIOConnectionTerminated(Exception)
raise
else:
while True:
Expand Down Expand Up @@ -2158,17 +2179,19 @@ def sasdata2dataframeDISK(self, table: str, libref: str ='', dsopts: dict = None
rc = self.pid.wait(0)
self.pid = None
self._sb.SASpid = None
#return None
logger.fatal('\nSAS process has terminated unexpectedly. RC from wait was: '+str(rc))
return None
except:
raise SASIOConnectionTerminated(Exception)
except subprocess.TimeoutExpired:
pass
else:
rc = os.waitpid(self.pid, os.WNOHANG)
if rc[1]:
self.pid = None
self._sb.SASpid = None
logger.fatal('\nSAS process has terminated unexpectedly. RC from wait was: '+str(rc))
return None
self.pid = None
self._sb.SASpid = None
#return None
logger.fatal("\nSAS process has terminated unexpectedly. Pid State= "+str(rc))
raise SASIOConnectionTerminated(Exception)
raise

if k_dts is None: # don't override these if user provided their own dtypes
Expand Down
Loading

0 comments on commit e7b1cee

Please sign in to comment.