1 """module iraftask.py -- defines IrafTask and IrafPkg classes
2
3 $Id: iraftask.py 1463 2011-06-24 22:58:30Z stsci_embray $
4
5 R. White, 2000 June 26
6
7 iraftask defines the original PyRAF task functionality which pre-dates
8 the creation of IRAF ECL. irafecl is closely related and derived from
9 iraftask, providing drop-in replacements for the Task classes defined
10 here which also support ECL syntax like "iferr" and $errno.
11 """
12 from __future__ import division
13
14 import os, sys, copy, re
15 from stsci.tools import basicpar, minmatch, irafutils, irafglobals, taskpars
16 import subproc, irafinst, iraf, irafpar, irafexecute, cl2py
17 import fnmatch
18
19
20
21
22 executionMonitor = None
23
24
25
26
27
28
29 _IrafTask_attr_dict = {
30 '_name': None,
31 '_pkgname': None,
32 '_pkgbinary': None,
33 '_hidden': 0,
34 '_hasparfile': 1,
35 '_tbflag': 0,
36
37 '_fullpath': None,
38
39 '_currentParList': None,
40 '_defaultParList': None,
41 '_runningParList': None,
42 '_currentParpath': None,
43 '_defaultParpath': None,
44 '_scrunchParpath': None,
45 '_parDictList': None,
46 '_foreign': 0,
47 }
48
49
50
51
52
53
54
55
56
57
58
59
60 all_task_definitions = [ ]
61
62
63
64
65 -class IrafTask(irafglobals.IrafTask, taskpars.TaskPars):
66
67 """IRAF task class"""
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93 - def __init__(self, prefix, name, suffix, filename, pkgname, pkgbinary):
94
95
96
97
98
99
100 objdict = self.__dict__
101
102
103 all_task_definitions.append( self )
104
105 objdict['_saved_suffix'] = suffix
106 objdict['_saved_prefix'] = prefix
107
108
109 objdict.update(_IrafTask_attr_dict)
110 sname = name.replace('.', '_')
111 if sname != name:
112 print "Warning: '.' illegal in task name, changing", name, \
113 "to", sname
114 spkgname = pkgname.replace('.', '_')
115 if spkgname != pkgname:
116 print "Warning: '.' illegal in pkgname, changing", pkgname, \
117 "to", spkgname
118 objdict['_name'] = sname
119 objdict['_pkgname'] = spkgname
120 objdict['_pkgbinary'] = []
121 self.addPkgbinary(pkgbinary)
122
123 if name[0:1] == '_': objdict['_hidden'] = 1
124 if prefix == '$': objdict['_hasparfile'] = 0
125 if suffix == '.tb': objdict['_tbflag'] = 1
126 if filename and filename[0] == '$':
127
128 objdict['_foreign'] = 1
129 objdict['_filename'] = filename[1:]
130
131 if self._filename == 'foreign':
132 objdict['_filename'] = name
133 elif self._filename[:8] == 'foreign ':
134 objdict['_filename'] = name + self._filename[7:]
135 elif filename[:2] == '$0':
136 objdict['_filename'] = name + filename[2:]
137 else:
138 objdict['_filename'] = filename
139
141 """Fill in full pathnames of files and read parameter file(s)
142
143 Force indicates whether shortcut initialization can be used
144 or not. (No difference for base IrafTask.)
145 """
146 if self._filename and not self._fullpath:
147 if irafinst.EXISTS:
148 self._initFullpath()
149 else:
150 try:
151 self._initFullpath()
152 except iraf.IrafError:
153 self._initNoIrafTask()
154 if self._currentParList is None:
155 self._initParpath()
156 self._initParList()
157
158
160 """ Special-case handle the initialization that is going awry due
161 to a missing IRAF installation. """
162
163
164 orig = self._filename
165 base = os.path.basename(self._filename)
166 base = base[1+base.rfind('$'):]
167 if base and base.endswith('.par'):
168 self._filename = irafinst.tmpParFile(base)
169 else:
170 self._filename = irafinst.NO_IRAF_PFX+base
171 if iraf.Verbose>1:
172 print 'Task "'+self._name+'" needed "'+orig+'" got: '+self._filename
173
174
175
176
177
178
179
180
181
182
183
184 - def getName(self): return self._name
187 - def isHidden(self): return self._hidden
192
193
194
195
196
197
199 """Return full path name of executable"""
200 self.initTask()
201 return self._fullpath
202
204 """Return full path name of parameter file"""
205 self.initTask()
206 return self._currentParpath
207
209 """Return list of all parameter objects"""
210 self.initTask(force=1)
211 plist = self._runningParList or self._currentParList
212 if plist:
213 return plist.getParList(docopy=docopy)
214 else:
215 return []
216
218 """Return default list of all parameter objects"""
219 self.initTask(force=1)
220 plist = self._defaultParList
221 if plist:
222 return plist.getParList()
223 else:
224 return []
225
227 """Return (min-match) dictionary of all parameter objects"""
228 self.initTask(force=1)
229 plist = self._runningParList or self._currentParList
230 if plist:
231 return plist.getParDict()
232 else:
233 return minmatch.MinMatchDict()
234
236 """Get the IrafPar object for a parameter
237
238 If exact is set, param name must match exactly.
239 If alldict is set, look in all dictionaries (default is
240 just this task's dictionaries.)
241 """
242 self.initTask()
243
244
245
246 try:
247 paramdict = self.getParDict()
248 if paramdict.has_key(paramname,exact=exact):
249 return paramdict[paramname]
250 except minmatch.AmbiguousKeyError, e:
251
252 raise iraf.IrafError("Cannot get parameter `%s'\n%s" %
253 (paramname, str(e)))
254
255 if alldict:
256
257
258
259 if self._parDictList is None: self._setParDictList()
260 for dictname, paramdict in self._parDictList:
261 if paramdict.has_key(paramname,exact=exact):
262 return paramdict[paramname]
263
264 raise iraf.IrafError("Unknown parameter requested: " + paramname)
265
267 """Return list of names of all parameters that may match param"""
268 self.initTask(force=1)
269 plist = self._runningParList or self._currentParList
270 if plist:
271 return plist.getAllMatches(param)
272 else:
273 return []
274
275
276
277
278
280 """Add another entry in list of possible package binary locations
281
282 Parameter can be a string or a list of strings"""
283
284 if not pkgbinary:
285 return
286 elif isinstance(pkgbinary,str):
287 if pkgbinary and (pkgbinary not in self._pkgbinary):
288 self._pkgbinary.append(pkgbinary)
289 else:
290 for pbin in pkgbinary:
291 if pbin and (pbin not in self._pkgbinary):
292 self._pkgbinary.append(pbin)
293
294
296 """set hidden attribute, which can be specified in
297 a separate 'hide' statement
298 """
299 self._hidden = value
300
308
309
310
311
312
313 - def run(self,*args,**kw):
363
365 """Returns mode string for this task
366
367 Searches up the task, package, cl hierarchy for automatic modes
368 """
369 if parList is not None:
370 mode = parList.getValue('mode',prompt=0)
371 else:
372 pdict = self.getParDict()
373 if pdict:
374 mode = pdict['mode'].get(prompt=0)
375 else:
376 mode = "a"
377 if mode[:1] != "a": return mode
378
379
380 if self is iraf.cl: return "h"
381
382
383
384 if not self._pkgname: return "ql"
385
386
387 pkg = iraf.getPkg(self._pkgname)
388
389 if pkg is not self:
390 return pkg.getMode()
391
392 mode = iraf.cl.mode
393
394 if mode[:1] == "a":
395 return "h"
396 else:
397 return mode
398
400 """Set arguments to task in _runningParList copy of par list
401
402 Creates a copy of the task parameter list and sets the
403 parameters. It is up to subsequent code (in the run method)
404 to propagate these changes to the persistent parameter list.
405
406 Special arguments:
407 _setMode=1 to set modes of automatic parameters
408 ParList can be used to pass in an entire parameter list object
409 """
410 self.initTask(force=1)
411
412 if not self._currentParList:
413 return None
414
415
416
417 if kw.has_key('ParList'):
418 parList = kw['ParList']
419 del kw['ParList']
420 if isinstance(parList, str):
421
422 filename = parList
423 parList = irafpar.IrafParList(self.getName(), filename)
424 elif parList and not isinstance(parList, irafpar.IrafParList):
425 raise TypeError("ParList parameter must be a filename or "
426 "an IrafParList object")
427 else:
428 parList = None
429
430 if self._runningParList is not None:
431
432 newParList = self._runningParList
433 parList = None
434 else:
435 newParList = copy.deepcopy(parList or self._currentParList)
436
437 if kw.has_key('_setMode'):
438 _setMode = kw['_setMode']
439 del kw['_setMode']
440 else:
441 _setMode = 0
442
443 for p in newParList.getParList():
444 if isinstance(p, irafpar.IrafParPset):
445 p.get().setParList()
446
447 apply(newParList.setParList, args, kw)
448 if _setMode:
449
450 mode = self.getMode(newParList)
451 for p in newParList.getParList():
452 p.mode = p.mode.replace("a",mode)
453 if parList:
454
455
456
457 newParList.setAllFlags()
458
459 self._runningParList = newParList
460
461
462
463
464
465 - def setParam(self, qualifiedName, newvalue, check=1, exact=0, scope='',
466 idxHint=None):
467 """Set parameter specified by qualifiedName to newvalue.
468
469 qualifiedName can be a simple parameter name or can be
470 [[package.]task.]paramname[.field].
471 If check is set to zero, does not check value to make sure it
472 satisfies min-max range or choice list. scope, idxHint are ignored.
473 """
474
475 package, task, paramname, pindex, field = _splitName(qualifiedName)
476
477
478 if task == "_": task = self._pkgname
479
480 if task or package:
481 if not package:
482
483 if self._parDictList is None: self._setParDictList()
484 for dictname, paramdict in self._parDictList:
485 if dictname == task:
486 if paramdict.has_key(paramname):
487 paramdict[paramname].set(newvalue,index=pindex,
488 field=field,check=check)
489 return
490 else:
491 raise iraf.IrafError("Attempt to set unknown parameter " +
492 qualifiedName+' for task '+task)
493
494 if package: task = package + '.' + task
495 try:
496 tobj = iraf.getTask(task)
497
498 if pindex: paramname = paramname + '[' + `pindex+1` + ']'
499 if field: paramname = paramname + '.' + field
500 tobj.setParam(paramname,newvalue,check=check)
501 return
502 except KeyError:
503 raise iraf.IrafError("Could not find task " + task +
504 " to get parameter " + qualifiedName)
505 except iraf.IrafError, e:
506 raise iraf.IrafError(str(e) + "\nFailed to set parameter " +
507 qualifiedName)
508
509
510
511
512 paramdict = self.getParDict()
513 if paramdict.has_key(paramname,exact=exact):
514 paramdict[paramname].set(newvalue,index=pindex,
515 field=field,check=check)
516 return
517
518
519
520
521 if self._parDictList is None: self._setParDictList()
522 for dictname, paramdict in self._parDictList:
523 if paramdict.has_key(paramname,exact=exact):
524 paramdict[paramname].set(newvalue,index=pindex,
525 field=field,check=check)
526 return
527 else:
528 raise iraf.IrafError("Attempt to set unknown lone parameter " +
529 qualifiedName)
530
531 - def getParam(self,qualifiedName,native=1,mode=None,exact=0,prompt=1):
532 """Return parameter specified by qualifiedName.
533
534 qualifiedName can be a simple parameter name or can be
535 [[package.]task.]paramname[.field].
536 Paramname can also have an optional subscript, "param[1]".
537 If native is non-zero (default), returns native format (e.g. float
538 for floating point parameter.), otherwise returns string value.
539 If exact is set, parameter name must match exactly. Default
540 is to do minimum match.
541 If prompt is 0, does not prompt for parameter value (even if
542 parameter is undefined.)
543 """
544
545 package, task, paramname, pindex, field = _splitName(qualifiedName)
546
547 if (not task) or (task == self._name):
548
549 return self._getParValue(paramname, pindex, field, native, mode,
550 exact=exact, prompt=prompt)
551
552
553
554
555 if task == "_": task = self._pkgname
556
557 if not package:
558
559 if self._parDictList is None: self._setParDictList()
560 for dictname, paramdict in self._parDictList:
561 if dictname == task:
562 if paramdict.has_key(paramname):
563 return self._getParFromDict(paramdict, paramname,
564 pindex, field, native, mode="h", prompt=prompt)
565 else:
566 raise iraf.IrafError("Unknown parameter requested: " +
567 qualifiedName)
568
569
570 if package: task = package + '.' + task
571 try:
572 tobj = iraf.getTask(task)
573 return tobj._getParValue(paramname, pindex, field, native, mode="h",
574 prompt=prompt)
575 except KeyError:
576 raise iraf.IrafError("Could not find task " + task +
577 " to get parameter " + qualifiedName)
578 except iraf.IrafError, e:
579 raise iraf.IrafError(str(e) + "\nFailed to get parameter " +
580 qualifiedName)
581
582 - def _getParValue(self, paramname, pindex, field, native, mode, exact=0,
583 prompt=1):
584
585
586 paramdict = self.getParDict()
587 try:
588 if paramdict.has_key(paramname,exact=exact):
589 return self._getParFromDict(paramdict, paramname, pindex,
590 field, native, mode=mode, prompt=prompt)
591 except minmatch.AmbiguousKeyError, e:
592
593 raise iraf.IrafError("Cannot get parameter `%s'\n%s" %
594 (paramname, str(e)))
595
596
597
598 if self._parDictList is None: self._setParDictList()
599 for dictname, paramdict in self._parDictList:
600 if paramdict.has_key(paramname,exact=exact):
601 return self._getParFromDict(paramdict, paramname, pindex,
602 field, native, mode="h", prompt=prompt)
603 else:
604 raise iraf.IrafError('Unknown parameter requested: "'+paramname+
605 '" for task: "'+self._name+'" in pkg: "'+self._pkgname+'"')
606
607
608
609
610
612 """List the task parameters"""
613 self.initTask(force=1)
614 plist = self._runningParList or self._currentParList
615 if plist:
616 plist.lParam(verbose=verbose)
617 else:
618 sys.stderr.write("Task %s has no parameter file\n" % self._name)
619 sys.stderr.flush()
620
622 """Edit the task parameters, PyRAF Tk style"""
623 self.initTask(force=1)
624
625 if self._currentParList:
626 import epar
627 epar.epar(self)
628 else:
629 sys.stderr.write("Task %s has no parameter file\n" % self._name)
630 sys.stderr.flush()
631
633 """Edit the task parameters, IRAF curses style"""
634 self.initTask(force=1)
635
636 if self._currentParList:
637 import tpar
638 tpar.tpar(self)
639 else:
640 sys.stderr.write("Task %s has no parameter file\n" % self._name)
641 sys.stderr.flush()
642
644 """Dump the task parameters
645
646 Default is to write CL version of code; if cl parameter is
647 false, writes Python executable code instead.
648 """
649 self.initTask(force=1)
650 plist = self._runningParList or self._currentParList
651 if plist:
652 if cl:
653 taskname = self._name
654 else:
655 taskname = "iraf.%s" % self._name
656 plist.dParam(taskname, cl=cl)
657 else:
658 sys.stderr.write("Task %s has no parameter file\n" % self._name)
659 sys.stderr.flush()
660
662 """Write task parameters in .par format to filename (name or handle)
663
664 If filename is omitted, writes to uparm scrunch file (if possible)
665 Returns a string with the results.
666 """
667 self.initTask()
668
669 if not self._currentParList:
670 return "No parameters to save for task %s" % (self._name,)
671 if filename is None:
672 if self._scrunchParpath:
673 filename = self._scrunchParpath
674 else:
675 status = "Unable to save parameters for task %s" % \
676 (self._name,)
677 if iraf.Verbose>0: print status
678 return status
679 rv = self._currentParList.saveParList(filename, comment)
680 return rv
681
683 """Reset task parameters to their default values"""
684 self.initTask(force=1)
685
686 if not self._currentParList:
687 return
688 if self._defaultParList is not None:
689
690 self._defaultParList.Update()
691 if self._scrunchParpath and \
692 (self._scrunchParpath == self._currentParpath):
693 try:
694 os.remove(iraf.Expand(self._scrunchParpath, noerror=1))
695 except OSError:
696 pass
697 self._currentParList = copy.deepcopy(self._defaultParList)
698 self._currentParpath = self._defaultParpath
699 else:
700 raise iraf.IrafError("Cannot find default .par file for task " +
701 self._name)
702
704 """Return scrunched version of filename (used for uparm files)
705
706 Scrunched version of filename is chars 1,2,last from package
707 name and chars 1-5,last from task name.
708 """
709 s = self._pkgname[0:2]
710 if len(self._pkgname) > 2:
711 s = s + self._pkgname[-1:]
712 s = s + self._name[0:5]
713 if len(self._name) > 5:
714 s = s + self._name[-1:]
715 return s
716
717
718
719
720
721
722
724 if name[:1] == '_':
725 raise AttributeError(name)
726 self.initTask()
727 try:
728 return self.getParam(name,native=1)
729 except SyntaxError, e:
730 raise AttributeError(str(e))
731
733
734
735 if name[:1] == '_':
736 self.__dict__[name] = value
737 elif self.is_pseudo(name):
738 self.__dict__[name] = value
739 else:
740 self.initTask()
741 self.setParam(name,value)
742
744 """Hook enabling ECL pseudos... always returns False"""
745 return False
746
747
748
749
751 return apply(self.run,args,kw)
752
754 s = '<%s %s (%s) Pkg: %s Bin: %s' % \
755 (self.__class__.__name__, self._name, self._filename,
756 self._pkgname, ':'.join(self._pkgbinary))
757 if self._foreign: s = s + ' Foreign'
758 if self._hidden: s = s + ' Hidden'
759 if self._hasparfile == 0: s = s + ' No parfile'
760 if self._tbflag: s = s + ' .tb'
761 return s + '>'
762
765
766
767
768
769
770
772 """Return dictionary of any special keywords (subclass hook)"""
773 return {}
774
776 """Apply I/O redirection (irafexecute does this for executables)
777
778 Return a list of redirections that need to be restored when done.
779 """
780 return []
781
783 """Restore redirected I/O and close files"""
784 return iraf.redirReset(resetList, closeFHList)
785
786 - def _run(self, redirKW, specialKW):
787 """Execute task after parameters, I/O redirection are prepared.
788
789 The implementation of this can differ for each type of task.
790 """
791 try:
792 apply(irafexecute.IrafExecute,
793 (self, iraf.getVarDict()), redirKW)
794 except irafexecute.IrafProcessError, value:
795 raise iraf.IrafError("Error running IRAF task " + self._name +
796 "\n" + str(value))
797
799 """Update parameter list after successful task completion
800
801 Updates parameter save file if any parameters change. If save
802 flag is set, all changes are saved; if save flag is false, only
803 explicit parameter changes requested by the task are saved.
804 """
805 if not (self._currentParList and self._runningParList):
806 return
807 newParList = self._runningParList
808 self._runningParList = None
809 mode = self.getMode(newParList)
810 changed = 0
811 for par in newParList.getParList():
812 if par.name != "$nargs" and (par.isChanged() or
813 (save and par.isCmdline() and par.isLearned(mode))):
814 changed = 1
815
816 tpar = self._currentParList.getParObject(par.name)
817
818
819 tpar.value = par.value
820
821
822
823 tpar.min = par.min
824 tpar.max = par.max
825 tpar.choice = par.choice
826 tpar.prompt = par.prompt
827 tpar.setChanged()
828 if isinstance(par, irafpar.IrafParPset):
829 par.get()._updateParList(save)
830
831 if changed:
832 rv = self.saveParList()
833 if iraf.Verbose>1: print rv
834
836 """Delete the _runningParList parameter list for this and psets"""
837 if self._currentParList and self._runningParList:
838 newParList = self._runningParList
839 self._runningParList = None
840 for par in newParList.getParList():
841 if isinstance(par, irafpar.IrafParPset):
842 par.get()._deleteRunningParList()
843
845 """Set the list of (up to 3) parameter dictionaries for task execution.
846
847 Parameter dictionaries for execution consist of this
848 task's parameters (which includes any psets
849 referenced), all the parameters for the task of the package
850 loaded for the current task, and the cl parameters. Each
851 dictionary has an associated name (because parameters could be
852 asked for as task.parname as well as just parname).
853
854 Create this list anew for each execution in case the
855 list of loaded packages has changed. It is stored as
856 an attribute of this object so it can be accessed by
857 the getParam() and setParam() methods.
858 """
859
860
861 self.initTask()
862 parDictList = [(self._name,self.getParDict())]
863
864
865
866 pd = iraf.getTask(self.getPkgname()).getParDict()
867 if (pd):
868 parDictList.append( (self.getPkgname(),pd) )
869
870
871 cl = iraf.cl
872 if cl is not None:
873 parDictList.append( (cl.getName(),cl.getParDict()) )
874
875
876 self._parDictList = parDictList
877
878
879 - def _getParFromDict(self, paramdict, paramname, pindex, field,
880 native, mode, prompt):
881
882
883 par = paramdict[paramname]
884 pmode = par.mode[:1]
885 if pmode == "a":
886 pmode = mode or self.getMode()
887 v = par.get(index=pindex,field=field,
888 native=native,mode=pmode,prompt=prompt)
889 if isinstance(v,str) and v[:1] == ")":
890
891
892
893
894
895
896
897
898
899
900 return self.getParam(v[1:],native=native,mode="h",prompt=prompt)
901 else:
902 return v
903
905 """Fill in full pathname of executable"""
906
907
908
909
910
911
912 try:
913 exename1 = iraf.Expand(self._filename)
914
915 basedir, basename = os.path.split(exename1)
916 except iraf.IrafError, e:
917 if iraf.Verbose>0:
918 print "Error searching for executable for task " + \
919 self._name
920 print str(e)
921 exename1 = ""
922
923
924 basedir = ""
925 s = self._filename.split("$")
926 basename = s[-1]
927 if basename == "":
928 self._fullpath = ""
929 raise iraf.IrafError("No filename in task %s definition: `%s'"
930 % (self._name, self._filename))
931
932
933 if self._foreign:
934 self._fullpath = self._filename
935 else:
936
937 exelist = []
938 for pbin in self._pkgbinary:
939 try:
940 exelist.append(iraf.Expand(pbin + basename))
941 except iraf.IrafError, e:
942 if iraf.Verbose>0:
943 print "Error searching for executable for task " + \
944 self._name
945 print str(e)
946 for exename2 in exelist:
947 if os.path.exists(exename2):
948 self._fullpath = exename2
949 break
950 else:
951 if os.path.exists(exename1):
952 self._fullpath = exename1
953 else:
954 self._fullpath = ""
955 exelist.append(exename1)
956 raise iraf.IrafError(
957 "Cannot find executable for task %s\nTried %s" %
958 (self._name, ", ".join(exelist)))
959
961 """Initialize parameter file paths"""
962
963 if not self._filename:
964
965
966 self._noParFile()
967 self._hasparfile = 0
968
969 if not self._hasparfile:
970
971 self._defaultParpath = ""
972 self._currentParpath = ""
973 self._scrunchParpath = ""
974 return
975
976 try:
977 exename1 = iraf.Expand(self._filename)
978 basedir, basename = os.path.split(exename1)
979 if basedir=="": basedir = "."
980 except iraf.IrafError, e:
981 if iraf.Verbose>0:
982 print "Error expanding executable name for task " + \
983 self._name + ", tried: " + self._filename
984 print str(e)
985 exename1 = ""
986 basedir = ""
987
988
989 self._defaultParpath = os.path.join(basedir,self._name + ".par")
990 if not os.path.exists(iraf.Expand(self._defaultParpath, noerror=1)):
991 self._noParFile()
992 self._defaultParpath = ""
993
994
995
996 self._scrunchParpath = "uparm$/"+self.scrunchName()+".par"
997
999 """Decide what to do if .par file is not found"""
1000
1001
1002 raise iraf.IrafError("Cannot find .par file for task "+self._name+\
1003 ", tried: "+self._defaultParpath+", for file: "+self._filename)
1004
1006
1007 """Initialize parameter list by reading parameter file"""
1008
1009 if not self._hasparfile:
1010 return
1011
1012 self._defaultParList = irafpar.IrafParList(self._name,
1013 iraf.Expand(self._defaultParpath, noerror=1))
1014
1015 if self._scrunchParpath and \
1016 os.path.exists(iraf.Expand(self._scrunchParpath, noerror=1)):
1017 self._currentParpath = self._scrunchParpath
1018 self._currentParList = irafpar.IrafParList(self._name,
1019 iraf.Expand(self._currentParpath, noerror=1))
1020
1021 if not self._isConsistentPar():
1022 sys.stderr.write("uparm parameter list `%s' inconsistent "
1023 "with default parameters for %s `%s'\n" %
1024 (self._currentParpath, self.__class__.__name__, self._name,))
1025 sys.stderr.flush()
1026
1027 try:
1028 os.remove(iraf.Expand(self._scrunchParpath, noerror=1))
1029 except OSError:
1030 pass
1031 self._currentParpath = self._defaultParpath
1032 self._currentParList = copy.deepcopy(self._defaultParList)
1033 else:
1034 self._currentParpath = self._defaultParpath
1035 self._currentParList = copy.deepcopy(self._defaultParList)
1036
1038 """Check current par list and default par list for consistency"""
1039 return (not self._currentParList) or \
1040 self._currentParList.isConsistent(self._defaultParList)
1041
1042
1043
1044
1045
1047
1048 """IRAF graphics kernel class (special case of IRAF task)"""
1049
1051 """Initialize: only name and executable filename are needed"""
1052 IrafTask.__init__(self,'',name,'',filename,'clpackage','bin$')
1053 self.setHidden()
1054
1055 pars = irafpar.IrafParList(name)
1056 makepar = irafpar.makeIrafPar
1057 pars.addParam(makepar('', datatype='string', name='input', mode='ql'))
1058 pars.addParam(makepar('', datatype='string', name='device', mode='h'))
1059 pars.addParam(makepar('yes', datatype='bool', name='generic', mode='h'))
1060 self._defaultParList = pars
1061 self._currentParList = pars
1062
1064 """Never save parameters for kernels"""
1065 return ""
1066
1067
1068
1069
1070
1071
1073
1074 """IRAF pset class (special case of IRAF task)"""
1075
1076 - def __init__(self, prefix, name, suffix, filename, pkgname, pkgbinary):
1077 IrafTask.__init__(self,prefix,name,suffix,filename,pkgname,pkgbinary)
1078
1079
1080
1081 if self.getForeign():
1082 raise iraf.IrafError("Bad filename for pset %s: %s" %
1083 (self.getName(), filename))
1084 if not self.hasParfile():
1085 raise KeyError("Pset "+self.getName()+" has no parameter file")
1086
1087 - def _run(self, redirKW, specialKW):
1090
1092
1093
1094 return self.getName()
1095
1096
1097
1098
1099
1100
1102
1103 """IRAF Python task class"""
1104
1105 - def __init__(self, prefix, name, suffix, filename, pkgname, pkgbinary,
1106 function):
1107
1108 IrafTask.__init__(self,prefix,name,suffix,filename,pkgname,pkgbinary)
1109 if self.getForeign():
1110 raise iraf.IrafError(
1111 "Python task `%s' cannot be foreign (filename=`%s')" %
1112 (self.getName(), filename))
1113 self.__dict__['_pyFunction'] = function
1114
1116 """Returns true if this task is consistent with another task object"""
1117 return IrafTask.isConsistent(self, other) and \
1118 self._pyFunction == other._pyFunction
1119
1120
1121
1122
1123
1125
1126 """Return state for pickling
1127
1128 Note that __setstate__ is not needed because
1129 returned state is a dictionary
1130 """
1131
1132
1133
1134 if self._pyFunction is None:
1135 return self.__dict__
1136 try:
1137 module = self._pyFunction.func_globals['__name__']
1138 if module[:6] == 'pyraf.':
1139 return self.__dict__
1140 except KeyError:
1141 pass
1142 file = self._pyFunction.func_code.co_filename
1143
1144 dict = self.__dict__.copy()
1145 dict['_pyFunction'] = None
1146 return dict
1147
1148
1149
1150
1151
1155
1156 - def _run(self, redirKW, specialKW):
1157 """Execute task after parameters, I/O redirection are prepared."""
1158
1159 parList = self.getParList()
1160 pl = []
1161 for par in parList:
1162 if par.name not in ['mode', '$nargs']:
1163 if isinstance(par, irafpar.IrafParL):
1164
1165 pl.append(par)
1166 elif par.mode == "h" and not par.isLegal():
1167
1168 pl.append(None)
1169 else:
1170
1171 pl.append(par.get(native=1))
1172
1173 apply(self._pyFunction, pl)
1174
1175
1176
1177
1178
1179
1182 self.__dict__['_taskObj'] = taskObj
1183
1185 if self._taskObj.is_pseudo(paramname):
1186 return getattr(self._taskObj, paramname)
1187 if paramname[:1] == '_':
1188 raise AttributeError(paramname)
1189
1190 try:
1191 return self._taskObj.getParam(paramname,native=1,mode="h",exact=1)
1192 except iraf.IrafError, e:
1193 pass
1194
1195 try:
1196 p = self._taskObj.getParObject(paramname,alldict=1)
1197 except iraf.IrafError, e:
1198
1199 raise AttributeError(str(e))
1200
1201
1202 raise AttributeError(
1203 "Unknown parameter `%s' (possibly intended `%s'?)" %
1204 (paramname, p.name))
1205
1207
1208 try:
1209 return self._taskObj.getParObject(paramname,exact=1,alldict=1)
1210 except iraf.IrafError, e:
1211 pass
1212
1213 try:
1214 p = self._taskObj.getParObject(paramname,alldict=1)
1215 except iraf.IrafError, e:
1216
1217 raise AttributeError(str(e))
1218
1219
1220 raise AttributeError(
1221 "Unknown parameter `%s' (possibly intended `%s'?)" %
1222 (paramname, p.name))
1223
1225 if self._taskObj.is_pseudo(paramname):
1226 return setattr(self._taskObj, paramname, value)
1227 if paramname[:1] == '_': raise AttributeError(paramname)
1228
1229 try:
1230 return self._taskObj.setParam(paramname,value,exact=1)
1231 except iraf.IrafError, e:
1232 pass
1233
1234 try:
1235 p = self._taskObj.getParObject(paramname,alldict=1)
1236 except iraf.IrafError, e:
1237
1238 raise AttributeError(str(e))
1239
1240
1241 raise AttributeError(
1242 "Unknown parameter `%s' (possibly intended `%s'?)" %
1243 (paramname, p.name))
1244
1245
1246
1247
1248
1249
1251
1252 """IRAF CL task class"""
1253
1254 - def __init__(self, prefix, name, suffix, filename, pkgname, pkgbinary):
1255
1256 if isinstance(filename,str):
1257 fh = None
1258 else:
1259 if not hasattr(filename,'read'):
1260 raise TypeError(
1261 'filename must be either a string or a filehandle')
1262 fh = filename
1263 if hasattr(fh,'name'):
1264 filename = fh.name
1265 else:
1266 filename = None
1267 IrafTask.__init__(self,prefix,name,suffix,filename,pkgname,pkgbinary)
1268 if self.getForeign():
1269 raise iraf.IrafError(
1270 "CL task `%s' cannot be foreign (filename=`%s')" %
1271 (self.getName(), filename))
1272
1273
1274 self.__dict__['_pycode'] = None
1275 self.__dict__['_codeObject'] = None
1276 self.__dict__['_clFunction'] = None
1277 if fh is not None:
1278
1279
1280 self.initTask(filehandle=fh)
1281
1282
1283
1284
1285
1287 """Return a string with the Python code for this task"""
1288 self.initTask(force=1)
1289 return self._pycode.code
1290
1292 """Force recompilation of CL code"""
1293 if self._pycode is not None:
1294 self._pycode.index = None
1295 cl2py.codeCache.remove(self)
1296 self.initTask(force=1)
1297
1298
1299
1300
1301
1302 - def initTask(self,force=0,filehandle=None):
1303 """Fill in full pathnames of files, read par file, compile CL code
1304
1305 If filehandle is specified, reads CL code from there
1306 """
1307
1308 if (not force) and (self._pycode is not None):
1309
1310 return
1311
1312 if self._filename is None and filehandle is None and \
1313 self._pycode is not None:
1314
1315
1316
1317
1318 return
1319
1320 if filehandle is not None and self._filename:
1321 self._fullpath = iraf.Expand(self._filename)
1322
1323 IrafTask.initTask(self)
1324
1325 if filehandle is None:
1326 filehandle = self._fullpath
1327
1328 justMade = False
1329 fcopy = self._filename
1330 if not irafinst.EXISTS and fcopy.startswith(irafinst.NO_IRAF_PFX):
1331
1332 if iraf.Verbose>0:
1333 print "Compiling No-IRAF CL task %s" % (self._name,)
1334 fcopy = os.path.basename(fcopy)
1335 self._codeObject = None
1336 self._pycode = cl2py.cl2py(None,
1337 string=irafinst.getNoIrafClFor(fcopy),
1338 parlist=self._defaultParList,
1339 parfile=self._defaultParpath)
1340 justMade = True
1341
1342 if not justMade and not cl2py.checkCache(filehandle, self._pycode):
1343
1344 self._pycode = None
1345 if iraf.Verbose>1:
1346 print "Cached version of %s is out-of-date" % (self._name,)
1347
1348 if self._pycode is None:
1349
1350 if iraf.Verbose>1:
1351 print "Compiling CL task %s" % (self._name,)
1352 self._codeObject = None
1353 self._pycode = cl2py.cl2py(filehandle,
1354 parlist=self._defaultParList, parfile=self._defaultParpath)
1355
1356 if self._codeObject is None:
1357
1358
1359
1360 self._clFunction = None
1361 if self._pkgname:
1362 scriptname = '<CL script %s.%s>' % (self._pkgname, self._name)
1363 else:
1364
1365 scriptname = '<CL script %s>' % self._name
1366
1367 self._codeObject = compile(self._pycode.code,scriptname,'exec',0,0)
1368
1369
1370 if self._clFunction is None:
1371
1372 clDict = {}
1373 exec self._codeObject in clDict
1374 self._clFunction = clDict[self._pycode.vars.proc_name]
1375
1376
1377
1378
1379 self._defaultParList = self._pycode.vars.parList
1380
1381 if self._currentParpath:
1382 if not self._defaultParList.isConsistent(self._currentParList):
1383 sys.stderr.write("uparm parameter list `%s' inconsistent "
1384 "with default parameters for %s `%s'\n" %
1385 (self._currentParpath, self.__class__.__name__,
1386 self._name,))
1387 sys.stderr.flush()
1388
1389 if self._currentParpath == self._scrunchParpath:
1390 try:
1391 os.remove(iraf.Expand(self._scrunchParpath, noerror=1))
1392 except OSError:
1393 pass
1394 self._currentParpath = self._defaultParpath
1395 self._currentParList = copy.deepcopy(self._defaultParList)
1396 else:
1397 self._currentParList = copy.deepcopy(self._pycode.vars.parList)
1398 self._currentParpath = self._defaultParpath
1399
1400
1401
1402
1403
1405 """Return state for pickling"""
1406
1407
1408
1409 if self._clFunction is None:
1410 return self.__dict__
1411
1412 dict = self.__dict__.copy()
1413 dict['_clFunction'] = None
1414 return dict
1415
1416
1417
1418
1419
1423
1424 - def _run(self, redirKW, specialKW):
1425 """Execute task after parameters, I/O redirection are prepared."""
1426 self._runCode()
1427
1428 - def _runCode(self, parList=None, kw={}):
1429 """Run the procedure with current parameters"""
1430
1431 kw['taskObj'] = ParDictListSearch(self)
1432 if parList is None: parList = self.getParList()
1433
1434
1435
1436
1437
1438
1439
1440
1441 apply(self._clFunction, parList, kw)
1442
1444 """Decide what to do if .par file is not found"""
1445
1446 pass
1447
1449 """Check current par list and default par list for consistency"""
1450
1451
1452
1453 return 1
1454
1455
1456
1457
1458
1459
1460
1461
1462 -class IrafPkg(IrafCLTask, irafglobals.IrafPkg):
1463
1464 """IRAF package class (special case of IRAF task)"""
1465
1466 - def __init__(self, prefix, name, suffix, filename, pkgname, pkgbinary):
1467 IrafCLTask.__init__(self,prefix,name,suffix,filename,pkgname,pkgbinary)
1468 self._loaded = 0
1469 self._tasks = minmatch.MinMatchDict()
1470 self._subtasks = minmatch.MinMatchDict()
1471 self._pkgs = minmatch.MinMatchDict()
1472
1473
1474
1475
1476
1478 """Returns true if this package has already been loaded"""
1479 return self._loaded
1480
1481 - def addTask(self, task, fullname):
1482 """Add a task to the task list for this package
1483
1484 Just store the name of the task to avoid cycles
1485 """
1486 name = task.getName()
1487 self._tasks.add(name, fullname)
1488
1489 if isinstance(task, IrafPkg): self._pkgs.add(name, name)
1490
1491
1492
1493
1494
1496 """Return list of names of all parameters/tasks that may match name"""
1497 self.initTask(force=1)
1498 plist = self._runningParList or self._currentParList
1499 if plist:
1500 matches = plist.getAllMatches(name)
1501 else:
1502 matches = []
1503 if self._loaded:
1504
1505 if name == "":
1506 matches.extend(self._tasks.keys())
1507 else:
1508 matches.extend(self._tasks.getallkeys(name, []))
1509
1510 if not triedpkgs: triedpkgs = {}
1511 triedpkgs[id(self)] = 1
1512 getPkg = iraf.getPkg
1513 getTried = triedpkgs.get
1514 for fullname in self._pkgs.values():
1515 p = getPkg(fullname)
1516 if p._loaded and (not getTried(id(p))):
1517 try:
1518 matches.extend(p.getAllMatches(name,
1519 triedpkgs=triedpkgs))
1520 except AttributeError, e:
1521 pass
1522 return matches
1523
1533
1535 """Return the task or param 'name' from this package (if it exists)."""
1536 if name[:1] == '_':
1537 raise AttributeError(name)
1538 self.initTask()
1539
1540 plist = self._runningParList or self._currentParList
1541 if plist and plist.hasPar(name):
1542 return plist.getValue(name,native=1,mode=self.getMode())
1543
1544 if not self._loaded:
1545 raise AttributeError("Package " + self.getName() +
1546 " has not been loaded; no tasks are defined")
1547 fullname = self._getTaskFullname(name)
1548 if fullname:
1549 return iraf.getTask(fullname)
1550 else:
1551 raise AttributeError("Parameter %s not found" % name)
1552
1553
1554
1555
1556
1558 """Return the full name (pkg.task) of task 'name' from this package
1559
1560 Returns None if task is not found.
1561
1562 Also searches subpackages for the task. triedpkgs is
1563 a dictionary with all the packages that have already been
1564 tried. It is used to avoid infinite recursion when
1565 packages contain themselves.
1566
1567 Tasks that are found are added to _tasks dictionary to speed
1568 repeated searches.
1569 """
1570 if not self._loaded:
1571 return None
1572 task = self._tasks.get(name)
1573 if task:
1574 return task
1575
1576 task = self._subtasks.get(name)
1577 if task:
1578 return task
1579
1580 if not triedpkgs: triedpkgs = {}
1581 triedpkgs[id(self)] = 1
1582 getPkg = iraf.getPkg
1583 getTried = triedpkgs.get
1584 for fullname in self._pkgs.values():
1585 p = getPkg(fullname)
1586 if p._loaded and (not getTried(id(p))):
1587 task = p._getTaskFullname(name,triedpkgs=triedpkgs)
1588 if task:
1589 self._subtasks.add(name,task)
1590 return task
1591 return None
1592
1594 """Handle special _doprint, _hush keywords"""
1595
1596
1597
1598
1599
1600 if kw.has_key('_hush'):
1601 if kw['_hush'] and \
1602 not (kw.has_key('Stdout') or kw.has_key('StdoutAppend')):
1603 kw['Stdout'] = '/dev/null'
1604 del kw['_hush']
1605
1606
1607
1608 if kw.has_key('_doprint'):
1609 doprint = kw['_doprint']
1610 del kw['_doprint']
1611 else:
1612 doprint = iraf.cl.menus
1613 return {'doprint': doprint}
1614
1615 - def _run(self, redirKW, specialKW):
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1656
1657 """Hack an IRAF CL task object into an IRAF package object"""
1658
1659 if isinstance(o, IrafPkg):
1660 return
1661 if not isinstance(o, IrafCLTask):
1662 raise TypeError("Cannot turn object `%s' into an IrafPkg" % `o`)
1663
1664
1665
1666
1667 o._loaded = loaded
1668 o._tasks = minmatch.MinMatchDict()
1669 o._pkgs = minmatch.MinMatchDict()
1670
1671
1672 o.__class__ = klass
1673
1674
1675
1676
1677
1678
1679 _re_foreign_par = re.compile(r'\$' +
1680 r'((?P<n>[0-9]+)' +
1681 r'|(?P<all>\*)' +
1682 r'|(\((?P<paren>[0-9]+)\))' +
1683 r'|(\((?P<allparen>\*)\))' +
1684 r')')
1685
1687
1688 """IRAF foreign task class"""
1689
1690 - def __init__(self, prefix, name, suffix, filename, pkgname, pkgbinary):
1691 IrafTask.__init__(self,prefix,name,suffix,filename,pkgname,pkgbinary)
1692
1693
1694
1695 if not self.getForeign():
1696 raise iraf.IrafError("Bad filename for foreign task %s: %s" %
1697 (self.getName(), filename))
1698 if self.hasParfile():
1699 if iraf.Verbose>0:
1700 print "Foreign task " + self.getName() + \
1701 " cannot have a parameter file"
1702 self._hasparfile = 0
1703
1705 """Set arguments to task
1706
1707 Does not use IrafParList structure -- just keeps list of
1708 the arguments
1709 """
1710 if kw.has_key('_setMode'):
1711 del kw['_setMode']
1712 if len(kw)>0:
1713 raise ValueError('Illegal keyword parameters %s for task %s' %
1714 (kw.keys(), self._name,))
1715
1716
1717
1718
1719
1720 self._args = map(self._str_escape, args)
1721
1722
1723
1724
1726 if not isinstance(arg, str):
1727 _arg = re.escape(str(arg))
1728 else: _arg = arg
1729 return _arg
1730
1734
1735 - def _run(self, redirKW, specialKW):
1736 """Execute task after parameters, I/O redirection are prepared."""
1737 args = self._args
1738 self._nsub = 0
1739
1740 cmdline = _re_foreign_par.sub(self._parSub,self._filename)
1741 if self._nsub==0 and args:
1742
1743 cmdline = cmdline + ' ' + ' '.join(args)
1744 if iraf.Verbose>1: print "Running foreign task:", cmdline
1745
1746 subproc.subshellRedir(cmdline)
1747
1749 """Substitute an argument for this match object"""
1750 self._nsub = self._nsub+1
1751 n = mo.group('n')
1752 if n is not None:
1753
1754 n = int(n)
1755 if n>len(self._args):
1756 return ''
1757 elif n==0:
1758 return self._name
1759 else:
1760 return self._args[n-1]
1761 n = mo.group('paren')
1762 if n is not None:
1763
1764 n = int(n)
1765 if n>len(self._args):
1766 return ''
1767 elif n==0:
1768 return self._name
1769 else:
1770 return iraf.Expand(self._args[n-1])
1771 n = mo.group('all')
1772 if n is not None:
1773
1774 return ' '.join(self._args)
1775 n = mo.group('allparen')
1776 if n is not None:
1777
1778 return ' '.join(map(iraf.Expand,self._args))
1779 raise iraf.IrafError("Cannot handle foreign string `%s' "
1780 "for task %s" % (self._filename, self._name))
1781
1782
1783
1784
1785
1786
1788 """Split qualifiedName into components.
1789
1790 qualifiedName looks like [[package.]task.]paramname[subscript][.field],
1791 where subscript is an index in brackets. Returns a tuple with
1792 (package, task, paramname, subscript, field). IRAF one-based subscript
1793 is changed to Python zero-based subscript.
1794 """
1795
1796 slist = map(irafutils.untranslateName, qualifiedName.split('.'))
1797
1798
1799
1800 if len(slist)==1 or not basicpar.isParField(slist[-1]):
1801
1802 slist.append(None)
1803 if len(slist) > 4:
1804 raise iraf.IrafError("Illegal syntax for parameter: " + qualifiedName)
1805 slist = [None]*(4-len(slist)) + slist
1806
1807
1808
1809 paramname = slist[2]
1810 pstart = paramname.find('[')
1811 if pstart >= 0:
1812 try:
1813 pend = paramname.rindex(']')
1814 pindex = int(paramname[pstart+1:pend])-1
1815 slist[2:3] = [paramname[:pstart], pindex]
1816 except (TypeError, ValueError):
1817 raise iraf.IrafError("Illegal syntax for array parameter: " +
1818 qualifiedName)
1819 else:
1820 slist[3:3] = [None]
1821 return slist
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1838
1839
1840
1841
1843 cl = str(x.__class__)
1844 if '.' in cl :
1845 cl=cl.split('.')[-1]
1846
1847
1848
1849 s= "%s : %s - pkgbinary=%s class=%s"% ( x._name, x.getFullpath(), x._pkgbinary, cl )
1850 return s
1851
1852
1853
1854
1856 l = gettask(name)
1857 if len(l) < 1 :
1858 print (" "*level)+'%s : NOT FOUND'%name
1859 else :
1860 l.sort()
1861 for x in l :
1862 print (" "*level)+printable_task_def(x)
1863 next_name = x._pkgname
1864 if (next_name == name) or ( level > 15 ) :
1865 pass
1866 else :
1867 showtasklong(next_name, level=level+1)
1868