Skip to content

Commit

Permalink
Update determination of iraf and IRAFARCH variables
Browse files Browse the repository at this point in the history
These variables are now retrieved from the configuration for the
different IRAF architectures instead of from /usr/local/bin/cl.
  • Loading branch information
olebole committed Jun 4, 2024
1 parent 920f657 commit 73dac3c
Showing 1 changed file with 89 additions and 69 deletions.
158 changes: 89 additions & 69 deletions pyraf/iraffunctions.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
R. White, 2000 January 20
"""

import re

# define INDEF, yes, no, EOF, Verbose, IrafError, userIrafHome

Expand Down Expand Up @@ -146,32 +147,13 @@ def Init(doprint=1, hush=0, savefile=None):
restoreFromFile(savefile, doprint=doprint)
return
if len(_pkgs) == 0:
try:
iraf = _os.environ['iraf']
except KeyError:
# iraf or IRAFARCH environment variable not defined
# try to get them from cl startup file
try:
d = _getIrafEnv()
for key, value in d.items():
if key not in _os.environ:
_os.environ[key] = value
iraf = _os.environ['iraf']
except OSError:
raise OSError("""
Your "iraf" environment variable is not defined and could not be
determined from /usr/local/bin/cl. This is are needed to find IRAF
tasks. Before starting pyraf, define ot by doing (for example):
export iraf=/iraf/iraf/
at the Unix command line. Actual values will depend on your IRAF installation,
and they are set during the IRAF user installation (see https://iraf-community.github.io).
Also be sure to run the "mkiraf" command to create a logion.cl
(http://www.google.com/search?q=mkiraf).
""")
if "iraf" not in _os.environ:
_os.environ["iraf"] = _getIrafEnv()
iraf = _os.environ['iraf']

arch = _os.environ.get('IRAFARCH', '')
if "IRAFARCH" not in _os.environ:
_os.environ["IRAFARCH"] = _getIrafArch(iraf)
arch = _os.environ["IRAFARCH"]

# stacksize problem on linux
# https://iraf-community.github.io/iraf-v216/issues/61
Expand Down Expand Up @@ -256,51 +238,85 @@ def Init(doprint=1, hush=0, savefile=None):
listTasks('clpackage')


def _getIrafEnv(file='/usr/local/bin/cl', vars=('IRAFARCH', 'iraf')):
"""Returns dictionary of environment vars defined in cl startup file"""
def _getIrafEnv():
"""Retrieve the iraf root path from the configuration"""
if not _irafinst.EXISTS:
return {'iraf': '/iraf/is/not/here/', 'IRAFARCH': 'arch_is_unused'}
if not _os.path.exists(file):
raise OSError(f"CL startup file {file} does not exist")
with open(file, errors="ignore") as fh:
lines = fh.readlines()
# replace commands that exec cl with commands to print environment vars
pat = _re.compile(r'^\s*exec\s+')
newlines = []
nfound = 0
for line in lines:
if pat.match(line):
nfound += 1
for var in vars:
newlines.append(f'echo "{var}=${var}"\n')
newlines.append('exit 0\n')
else:
newlines.append(line)
if nfound == 0:
raise OSError(f"No exec statement found in script {file}")
# write new script to temporary file
(fd, newfile) = _tempfile.mkstemp()
_os.close(fd)
f = open(newfile, 'w')
f.writelines(newlines)
f.close()
_os.chmod(newfile, 0o700)
# run new script and capture output
fh = _io.StringIO()
status = clOscmd(newfile, Stdout=fh)
if status:
raise OSError(f"Execution error in script {newfile} (derived from {file})")
_os.remove(newfile)
result = fh.getvalue().split('\n')
fh.close()
# extract environment variables from the output
d = {}
for entry in result:
if entry.find('=') >= 0:
key, value = entry.split('=', 1)
d[key] = value
return d
return "/nonexistent/iraf/is/not/here"

# Community IRAF defines it in ~/.iraf/irafroot or /etc/iraf/irafroot
for irafroot in [_os.path.expanduser("~/.iraf/irafroot"),
"/etc/iraf/irafroot"]:
if _os.path.exists(irafroot):
with open(irafroot) as fp:
line = fp.readline().strip()
if line.startswith("/"):
return line

# NOIRLAB and NOAO personal installs have a setup.sh in the homedir
irafsetup = _os.path.expanduser("~/.iraf/setup.sh")
if _os.path.exists(irafsetup):
iraf_re = r"\s*export\s+iraf=\s*/\^S+/"
with open("/usr/include/iraf.h") as fp:
for line in fp.readlines():
m = iraf_re.match(line)
if m is not None:
return m[1]

# NOAO IRAF defines it in /usr/include/iraf.h
irafinc = "/usr/include/iraf.h"
if _os.path.exists(irafinc):
iraf_re = re.compile(r'\s*#define\s+iraf\s+"(/\S+/)"')
with open(irafinc) as fp:
for line in fp.readlines():
m = iraf_re.match(line)
if m is not None:
return m[1]

# Check some hardcoded directories as last resort
for irafdir in ["/usr/local/lib/iraf/",
"/usr/local/iraf/",
"/usr/lib/iraf/",
"/opt/iraf/",
"/iraf/iraf/",
"/Applications/IRAF.app/Contents/iraf-v218/"]:
if _os.path.exists(irafdir):
return irafdir

raise OSError("""
Your "iraf" environment variable is not defined and could not be
determined from the installation. This is are needed to find IRAF
tasks. Before starting pyraf, define ot by doing (for example):
export iraf=/usr/local/lib/iraf/
at the Unix command line. Actual values will depend on your IRAF installation.
""")


def _getIrafArch(iraf):
"""Retrieve the iraf architecture path from the configuration"""

# NOAO/NOIRLAB user installation
fname = _os.path.expanduser("~/.iraf/arch")
if _os.path.exists(fname):
with open(fname) as fp:
return fp.readline().strip()

# Check for standard iraf bindirs
bindir = _os.path.realpath(_os.path.join(iraf, "bin"))
m = re.match(r".*/bin\.(\w+)/?$", bindir)
if m is not None:
return m[1]

# Retrieve it from the irafarch script
fname = _os.path.join(iraf, "unix", "hlib", "irafarch")
if _os.path.exists(fname):
import subprocess
exitcode, arch = subprocess.getstatusoutput(fname)
if exitcode == 0:
return arch

return ""

# module variables that don't get saved (they get
# initialized when this module is imported)
Expand Down Expand Up @@ -3349,7 +3365,11 @@ def clExecute(s,
locals = {}
exec(codeObject, locals)
if pycode.vars.proc_name:
exec(pycode.vars.proc_name + "(taskObj=iraf.cl)", locals)
try:
exec(pycode.vars.proc_name + "(taskObj=iraf.cl)", locals)
except TypeError as e:
e.add_note(f"While executing\n\n{code}")
raise
return code
finally:
_clExecuteCount = _clExecuteCount - 1
Expand Down

0 comments on commit 73dac3c

Please sign in to comment.