From 5f8601139a022600be7635d455acc97a17176bb6 Mon Sep 17 00:00:00 2001 From: James Turner Date: Tue, 18 Oct 2016 12:40:45 -0300 Subject: Compatibility with old OS Python versions (specifically 2.4 in RHE5!). --- scripts/ac_update_extern_pkg | 68 +++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/scripts/ac_update_extern_pkg b/scripts/ac_update_extern_pkg index 51905da..ec033dd 100644 --- a/scripts/ac_update_extern_pkg +++ b/scripts/ac_update_extern_pkg @@ -5,12 +5,14 @@ # in progress when it gets run. It is not made executable because conda insists # on changing any Python interpreter path to $PREFIX/bin/python, which does not # always exist; it can instead be invoked via ac_config_iraf_pkg. +# +# Supporting ancient OS Python versions (v2.4 in RHE 5) means avoiding features +# such as argparse, new-style string formatting, context managers etc. -import argparse +import sys import os, os.path import shutil import re -from collections import OrderedDict # AstroConda naming conventions: @@ -22,37 +24,41 @@ path_sub = 'UR_VDIR' # a regexp # Get command-line user arguments: -parser = argparse.ArgumentParser() +usage = """ +Usage: ac_update_extern_pkg path name -parser.add_argument('path', type=str, - help='path to {0} and {1}/'.format(extern_pkg, extern_dir)) +positional arguments: + path directory containing extern.pkg and iraf_extern/ + name name of IRAF package (and its directory) +""" +if len(sys.argv) != 3: + sys.exit(usage) +args_path, args_name = sys.argv[1:] -parser.add_argument('name', type=str, - help='name of IRAF package (and its directory)') - -args = parser.parse_args() # Convert to canonical path and ensure it exists, with an extern.pkg file and # an iraf_extern/package/ur_extern.pkg (ie. files already installed): -path = os.path.abspath(args.path) # env dir with extern.pkg +path = os.path.abspath(args_path) # env dir with extern.pkg extpkg_path = os.path.join(path, extern_pkg) # extern.pkg path extbak_path = os.path.join(path, extpkg_bak) # path to backup copy -pkg_path = os.path.join(path, extern_dir, args.name) # path to this IRAF pkg +pkg_path = os.path.join(path, extern_dir, args_name) # path to this IRAF pkg template_path = os.path.join(pkg_path, template) # this ur_extern.pkg if not os.access(extpkg_path, os.R_OK | os.W_OK): - raise ValueError("cannot access {0}".format(extpkg_path)) + raise ValueError("cannot access %s" % (extpkg_path)) if not os.access(template_path, os.R_OK): - raise ValueError("cannot access {0}".format(template_path)) + raise ValueError("cannot access %s" % (template_path)) # Read extern.pkg: -with open(extpkg_path, 'r+') as extpkg_file: - buffer = extpkg_file.read() +extpkg_file = open(extpkg_path, 'r+') +buffer = extpkg_file.read() +extpkg_file.close() # Read the package's template ur_extern.pkg, removing any outer blank lines: -with open(template_path, 'r') as template_file: - tempbuf = template_file.read().strip() +template_file = open(template_path, 'r') +tempbuf = template_file.read().strip() +template_file.close() # Here we convert the template entry to a regex for finding and removing old, # previously-generated entries for the same package. This mainly consists of @@ -63,7 +69,7 @@ with open(template_path, 'r') as template_file: # because it's easier & more understandable to do those subs in concert with # the others. The template ur_extern.pkg files must not contain backslashes. -replacements = OrderedDict(( +replacements = ( ('special_nospace', (r'([][.^${}\|*?])', r'\\\1')), ('special_sp_end', (r'[ \t]*([=+()])[ \t]*$', r'[ \t]*\\\1')), ('special_space', (r'[ \t]*([=+()])[ \t]*', r'[ \t]*\\\1[ \t]*')), @@ -72,7 +78,8 @@ replacements = OrderedDict(( ('extra_space', (r'[ \t]+', r'[ \t]+')), ('line_space', (r'\s*\n\s*', r'\s*\n\s*')), # see below ('path_sub', (path_sub, r'.*')), -)) +) +repdict = dict(replacements) # keep both because no OrderedDict in python < 2.7 # Note that ^ and $ only match in conjunction with their adjoining character, # which, unlike the \n above, can get consumed by a prior pattern. Also, @@ -81,17 +88,17 @@ replacements = OrderedDict(( # Concatenate individual expressions for replacement, so they can be done # simultaneously on the original buffer (otherwise they trip each other up): -cat_re = '|'.join(['(?P<{0}>{1})'.format(key, regex) \ - for key, (regex, sub) in replacements.items()]) # py 3 way +cat_re = '|'.join(['(?P<%s>%s)' % (key, regex) \ + for key, (regex, sub) in replacements]) # Determine the replacement for a given match to the concatenated regex: def match_fn(match): - sub_re, sub = replacements[match.lastgroup] # look up replacement tuple + sub_re, sub = repdict[match.lastgroup] # look up replacement tuple return re.sub(sub_re, sub, match.group()) # do & return the substitution # Perform the substitutions to turn the template string into a regex itself: # template_re = re.escape(tempbuf) # if using built-in escape for special chars -template_re = re.sub(cat_re, match_fn, tempbuf, flags=re.M) +template_re = re.compile(cat_re, flags=re.M).sub(match_fn, tempbuf) # Update the original template entry with our new path: tempbuf = re.sub(path_sub, os.path.join(pkg_path, ''), tempbuf) # trailing / @@ -109,7 +116,7 @@ if match: buffer = buffer[:match.start()] # Make sure that what goes before the "keep" ends with a new line: -buffer = re.sub('\n?\Z', '\n', buffer, flags=re.M) +buffer = re.compile('\n?\Z', flags=re.M).sub('\n', buffer) # Find the last entry in extern.pkg (if any) that matches the template: match = None @@ -129,15 +136,15 @@ if match: # Match any non-commented instances of the package name, in the remainder # of the buffer, that don't look like a substring of a longer name: - pkgname_re = '^[^\n#]*(? Date: Wed, 19 Oct 2016 13:07:40 -0300 Subject: Support uninstallation of IRAF packages from extern.pkg. --- scripts/ac_config_iraf_pkg | 14 +++++++++++--- scripts/ac_update_extern_pkg | 33 +++++++++++++++++++++------------ 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/scripts/ac_config_iraf_pkg b/scripts/ac_config_iraf_pkg index 0863a86..c1f3e09 100755 --- a/scripts/ac_config_iraf_pkg +++ b/scripts/ac_config_iraf_pkg @@ -9,12 +9,15 @@ script_dir=`dirname "$0"` st=1 -unset name +unset name remove flags while [ -n "$1" ]; do case "$1" in -h) st=0; break ;; + --remove) + remove=1 + ;; -*) st=1; break ;; @@ -30,10 +33,14 @@ while [ -n "$1" ]; do done if [ -n "$st" ]; then - echo "Usage: `basename "$0"` NAME (normally invoked by \"conda install\")" + echo "Usage: `basename "$0"` [--remove] NAME " >&2 + echo " (normally invoked automatically by \"conda install\")" >&2 + echo >&2 exit $st fi +[ -n "$remove" ] && flags="${flags}${flags:+ }--remove" + # If the shell environment isn't configured by "conda install" as expected, try # falling back to Anaconda's run-time path variables to support user invocation. if [ -z "$PREFIX" ]; then @@ -61,7 +68,8 @@ fi # depending on other packages. Both the LSB and MacOS define Python in /usr/bin # as standard, avoiding any dependence on the state of the installation. -if /usr/bin/python "$script_dir/ac_update_extern_pkg" "$PREFIX" "$name"; then +if /usr/bin/python "$script_dir/ac_update_extern_pkg" $flags "$PREFIX" "$name" +then if [ $inst = 1 ]; then echo "Updated extern.pkg file" >> "$PREFIX/.messages.txt" else diff --git a/scripts/ac_update_extern_pkg b/scripts/ac_update_extern_pkg index ec033dd..90d1c65 100644 --- a/scripts/ac_update_extern_pkg +++ b/scripts/ac_update_extern_pkg @@ -25,15 +25,21 @@ path_sub = 'UR_VDIR' # a regexp # Get command-line user arguments: usage = """ -Usage: ac_update_extern_pkg path name +Usage: ac_update_extern_pkg [--remove] path name positional arguments: path directory containing extern.pkg and iraf_extern/ name name of IRAF package (and its directory) """ -if len(sys.argv) != 3: +argv = sys.argv +if '--remove' in argv: + args_remove = True + argv.remove('--remove') +else: + args_remove = False +if len(argv) != 3 or argv[1].startswith('-') or argv[2].startswith('-'): sys.exit(usage) -args_path, args_name = sys.argv[1:] +args_path, args_name = argv[1:] # Convert to canonical path and ensure it exists, with an extern.pkg file and @@ -127,12 +133,13 @@ for match in re.finditer(template_re, buffer, flags=re.M): # on the template, requiring that our new definition be moved to the end of the # file, to override the other defs. without actually losing the user's edits: if match: + # The name of the path variable in our extern.pkg template entries must be # the name of the IRAF package, otherwise we would have to parse the actual # variable name from the template using these commented regexes and search # for that, instead of the package name itself, to find redefinitions: # pkgdef_re = '^[ \t]*task[ \t]+{0}[.]pkg[ \t]*=[ \t]*(.*)$'.format(name) - # pathvar_re = '["\']?(.*)[$].*[.]cl' # find path variable name in pkg def. + # pathvar_re = '["\']?(.*)[$].*[.]cl' # find path variable name in pkg def. # Match any non-commented instances of the package name, in the remainder # of the buffer, that don't look like a substring of a longer name: @@ -142,19 +149,21 @@ if match: # Where a later (user) definition is found, we still remove the last # template-based definition but then continue as if there had been no # match, so a new definition will get placed at the end of the file below: - if later_match: + if later_match or args_remove: buffer = '%s\n\n%s' % (buffer[:match.start()].rstrip(), buffer[match.end():].lstrip()) match = None -# Replace the applicable entry with the template-based version: -if match: - buffer = buffer[:match.start()] + tempbuf + buffer[match.end():] +if not args_remove: -# If there wasn't an existing entry, or the last one wasn't based on the -# template, put the new entry at the end: -else: - buffer += '%s\n\n' % tempbuf + # Replace the applicable entry with the template-based version: + if match: + buffer = buffer[:match.start()] + tempbuf + buffer[match.end():] + + # If there wasn't an existing entry, or the last one wasn't based on the + # template, put the new entry at the end: + else: + buffer += '%s\n\n' % tempbuf # Restore the "keep" line at the end (along with a semicolon to avoid an IRAF # parser bug when the last entry ends with a curly bracket): -- cgit From 8580f023028de7ecd63439a288effd9c6d5fa6d0 Mon Sep 17 00:00:00 2001 From: "James E.H. Turner" Date: Wed, 19 Oct 2016 16:29:54 -0300 Subject: Avoid blank lines at the start of the file when adding/removing the 1st entry. --- scripts/ac_update_extern_pkg | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/scripts/ac_update_extern_pkg b/scripts/ac_update_extern_pkg index 90d1c65..b44155d 100644 --- a/scripts/ac_update_extern_pkg +++ b/scripts/ac_update_extern_pkg @@ -121,8 +121,9 @@ match = re.search(keep_re, buffer, flags=re.M) if match: buffer = buffer[:match.start()] -# Make sure that what goes before the "keep" ends with a new line: -buffer = re.compile('\n?\Z', flags=re.M).sub('\n', buffer) +# Make sure what goes before the "keep" ends with a new line (unless empty): +sep = '\n' if buffer.strip() else '' +buffer = re.compile('\n?\Z', flags=re.M).sub(sep, buffer) # Find the last entry in extern.pkg (if any) that matches the template: match = None @@ -150,8 +151,12 @@ if match: # template-based definition but then continue as if there had been no # match, so a new definition will get placed at the end of the file below: if later_match or args_remove: - buffer = '%s\n\n%s' % (buffer[:match.start()].rstrip(), - buffer[match.end():].lstrip()) + + # Replace the entry by 2 separator lines (unless it's the first one): + buf_before = buffer[:match.start()].rstrip() + buf_after = buffer[match.end():].lstrip() + buffer = buf_before + ('\n\n' if buf_before else '') + buf_after + del buf_before, buf_after match = None if not args_remove: -- cgit From b498bad36b33764d0a7e098c3f47ef3a295030fc Mon Sep 17 00:00:00 2001 From: "James E.H. Turner" Date: Wed, 19 Oct 2016 17:03:08 -0300 Subject: Expand out ternary operators to support Python 2.4... --- scripts/ac_update_extern_pkg | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/scripts/ac_update_extern_pkg b/scripts/ac_update_extern_pkg index b44155d..00d9259 100644 --- a/scripts/ac_update_extern_pkg +++ b/scripts/ac_update_extern_pkg @@ -122,7 +122,10 @@ if match: buffer = buffer[:match.start()] # Make sure what goes before the "keep" ends with a new line (unless empty): -sep = '\n' if buffer.strip() else '' +if buffer.strip(): + sep = '\n' +else: + sep = '' buffer = re.compile('\n?\Z', flags=re.M).sub(sep, buffer) # Find the last entry in extern.pkg (if any) that matches the template: @@ -155,7 +158,11 @@ if match: # Replace the entry by 2 separator lines (unless it's the first one): buf_before = buffer[:match.start()].rstrip() buf_after = buffer[match.end():].lstrip() - buffer = buf_before + ('\n\n' if buf_before else '') + buf_after + if buf_before: + sep = '\n\n' + else: + sep = '' + buffer = buf_before + sep + buf_after del buf_before, buf_after match = None -- cgit From 65c2b11cf0ea44e5c09db6fba4d5629426896150 Mon Sep 17 00:00:00 2001 From: James Turner Date: Wed, 19 Oct 2016 20:31:38 -0300 Subject: Avoid trailing space in XC_LFLAGS when not already set, since this gets passed to gcc as a non-existent filename, causing linking to fail! --- scripts/ac_build_iraf_pkg | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/ac_build_iraf_pkg b/scripts/ac_build_iraf_pkg index d6a92ce..91d6d0f 100755 --- a/scripts/ac_build_iraf_pkg +++ b/scripts/ac_build_iraf_pkg @@ -95,8 +95,9 @@ if [ -L bin ]; then # apart from being safer, there is a bin/ dir in mscdb ln -s "bin.$IRAFARCH" bin fi -# Enable compilation with debugging symbols (from the STScI IRAF "make_all"): -export XC_LFLAGS="-g $XC_LFLAGS" +# Enable compilation with debugging symbols (from the STScI IRAF "make_all"; +# avoiding trailing space, which gcc fails on as a non-existent filename!): +export XC_LFLAGS="-g${XC_LFLAGS:+ $XC_LFLAGS}" # Compile the package source, either as specified by the recipe or as usual: file_path="${RECIPE_DIR}/${pkg_mkpkg_cmd}" -- cgit From 46e0e458820ad0876c8d045109b20ce2171756c0 Mon Sep 17 00:00:00 2001 From: James Turner Date: Wed, 19 Oct 2016 21:32:46 -0300 Subject: Create extern.pkg if it doesn't already exist, for better foolproofing; we already check that ur_extern.pkg exists, so this is unlikely to lead to extern.pkg being written to weird places when invoked improperly (not a big deal anyway). --- scripts/ac_config_iraf_pkg | 3 +++ scripts/ac_update_extern_pkg | 26 ++++++++++++++++---------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/scripts/ac_config_iraf_pkg b/scripts/ac_config_iraf_pkg index c1f3e09..f41f943 100755 --- a/scripts/ac_config_iraf_pkg +++ b/scripts/ac_config_iraf_pkg @@ -61,6 +61,9 @@ if [ ! -d "$PREFIX" -o ! -w "$PREFIX" ]; then exit 1 fi +# Create any new file with the expected permissions: +umask 022 + # The Python script for updating extern.pkg must be invoked as follows because # (if directly executable) conda insists on changing its interpreter path to # one in the env that may not exist, since IRAF packages do not require python diff --git a/scripts/ac_update_extern_pkg b/scripts/ac_update_extern_pkg index 00d9259..9c751a5 100644 --- a/scripts/ac_update_extern_pkg +++ b/scripts/ac_update_extern_pkg @@ -42,24 +42,28 @@ if len(argv) != 3 or argv[1].startswith('-') or argv[2].startswith('-'): args_path, args_name = argv[1:] -# Convert to canonical path and ensure it exists, with an extern.pkg file and -# an iraf_extern/package/ur_extern.pkg (ie. files already installed): +# Convert to canonical path and ensure it exists and is writeable, with an +# iraf_extern/package/ur_extern.pkg (ie. files already installed): path = os.path.abspath(args_path) # env dir with extern.pkg extpkg_path = os.path.join(path, extern_pkg) # extern.pkg path extbak_path = os.path.join(path, extpkg_bak) # path to backup copy pkg_path = os.path.join(path, extern_dir, args_name) # path to this IRAF pkg template_path = os.path.join(pkg_path, template) # this ur_extern.pkg -if not os.access(extpkg_path, os.R_OK | os.W_OK): - raise ValueError("cannot access %s" % (extpkg_path)) +if not os.access(path, os.W_OK): + raise ValueError("cannot write to %s" % (path)) if not os.access(template_path, os.R_OK): raise ValueError("cannot access %s" % (template_path)) -# Read extern.pkg: -extpkg_file = open(extpkg_path, 'r+') -buffer = extpkg_file.read() -extpkg_file.close() +# Read extern.pkg (if there is one): +if os.path.isfile(extpkg_path): + extpkg_file = open(extpkg_path, 'r') + buffer = extpkg_file.read() + extpkg_file.close() +else: + buffer = '' + extbak_path = None # Read the package's template ur_extern.pkg, removing any outer blank lines: template_file = open(template_path, 'r') @@ -182,7 +186,8 @@ if not args_remove: buffer += keep_str # Back up the original extern.pkg: -os.rename(extpkg_path, extbak_path) +if extbak_path: + os.rename(extpkg_path, extbak_path) # Write the modified extern.pkg as a new file with the same name, otherwise # conda's hard linking propagates its changes to other environments!: @@ -191,5 +196,6 @@ extpkg_file.write(buffer) extpkg_file.close() # Inherit permissions from the original copy (just as good practice): -shutil.copymode(extbak_path, extpkg_path) +if extbak_path: + shutil.copymode(extbak_path, extpkg_path) -- cgit