def checkcache(orig_checkcache=linecache.checkcache): """Discard cache entries that are out of date. (This is not checked upon each call!)""" # Rather than repeat linecache.checkcache code, we check & save the # CL script entries, call the original function, and then # restore the saved entries. (Modelled after Idle/PyShell.py.) cache = linecache.cache save = {} for filename in cache.keys(): if filename[:10] == "<CL script": entry = cache[filename] del cache[filename] # special CL script case - find original script file for time check if filename[10:13] == " CL": # temporary script created dynamically -- just save it save[filename] = entry else: size, mtime, lines, taskname = entry try: taskobj = iraf.getTask(taskname) fullname = taskobj.getFullpath() stat = os.stat(fullname) newsize = stat[ST_SIZE] newmtime = stat[ST_MTIME] except (os.error, iraf.IrafError): continue if size == newsize and mtime == newmtime: # save the ones that didn't change save[filename] = entry orig_checkcache() cache.update(save)
def _setTaskParsObj(self, theTask): """ Overridden version, so as to use Iraf tasks and IrafParList """ if isinstance(theTask, irafpar.IrafParList): # IrafParList acts as an IrafTask for our purposes self._taskParsObj = theTask else: # theTask must be a string name of, or an IrafTask object self._taskParsObj = iraf.getTask(theTask)
def flush(self, *args): """Flush given processes (all non-locked if no args given) Takes task names (strings) as arguments. """ if args: for taskname in args: task = iraf.getTask(taskname, found=1) if task is not None: self.terminate(task) else: for rank, proxy in self._data.values(): executable = proxy.process.executable if not self._locked.has_key(executable): self.terminate(executable)
def updateCLscript(filename): cache = linecache.cache if cache.has_key(filename): del cache[filename] try: taskname = filename[11:-1] taskobj = iraf.getTask(taskname) fullname = taskobj.getFullpath() stat = os.stat(fullname) size = stat[ST_SIZE] mtime = stat[ST_MTIME] lines = string.split(taskobj.getCode(),'\n') cache[filename] = size, mtime, lines, taskname return lines except (iraf.IrafError, KeyError, AttributeError): return []
def argument_matches(self, text, taskname, line): """Compute matches for tokens that could be file or parameter names""" matches = [] # only look at keywords if this one was whitespace-delimited # this avoids matching keywords after e.g. directory part of filename lt = len(line) - len(text) if line[lt - 1:lt] in " \t": m = re.match(r"\w*$", text) if m is not None: # could be a parameter name task = iraf.getTask(taskname, found=1) # get all parameters that could match (null list if none) if task is not None: matches = task.getAllMatches(text) # add matching filenames matches.extend(self.filename_matches(text, line[:lt])) return matches
def argument_matches(self, text, taskname, line): """Compute matches for tokens that could be file or parameter names""" matches = [] # only look at keywords if this one was whitespace-delimited # this avoids matching keywords after e.g. directory part of filename lt = len(line)-len(text) if line[lt-1:lt] in " \t": m = re.match(r"\w*$", text) if m is not None: # could be a parameter name task = iraf.getTask(taskname, found=1) # get all parameters that could match (null list if none) if task is not None: matches = task.getAllMatches(text) # add matching filenames matches.extend(self.filename_matches(text, line[:lt])) return matches
def _getExecutable(arg): """Get executable pathname. Arg may be a string with the path, an IrafProcess, an IrafTask, or a string with the name of an IrafTask. """ if isinstance(arg, IrafProcess): return arg.executable elif isinstance(arg, IrafTask): return arg.getFullpath() elif isinstance(arg, types.StringType): if os.path.exists(arg): return arg task = iraf.getTask(arg, found=1) if task is not None: return task.getFullpath() raise IrafProcessError("Cannot find task or executable %s" % arg)
def attr_matches(self, text): """Compute matches when text contains a dot.""" line = self.get_line_buffer() if line == text: # at start of line, special handling for iraf.xxx and # taskname.xxx fields = text.split(".") if fields[0] == "": # line starts with dot, look in executive commands return self.executive_matches(text) elif fields[0] == "iraf": return self.taskdot_matches(fields) elif iraf.getTask(fields[0], found=1): # include both eval results and task. matches fields.insert(0, 'iraf') matches = self.taskdot_matches(fields) try: matches.extend(Completer.attr_matches(self, text)) except KeyboardInterrupt: raise except: pass return matches else: return Completer.attr_matches(self, text) else: # Check first character following initial alphabetic string # If next char is alphabetic (or null) use filename matches # Otherwise use matches from Python dictionaries #XXX need to make this consistent with the other places #XXX where same tests are done m = self.taskpat.match(line) if m is None or keyword.iskeyword(m.group(1)): fields = text.split(".") if fields[0] == "iraf": return self.taskdot_matches(fields) else: return Completer.attr_matches(self, text) else: #XXX Could try to match pset.param keywords too? lt = len(line) - len(text) return self.filename_matches(text, line[:lt])
def attr_matches(self, text): """Compute matches when text contains a dot.""" line = self.get_line_buffer() if line == text: # at start of line, special handling for iraf.xxx and # taskname.xxx fields = string.split(text,".") if fields[0] == "": # line starts with dot, look in executive commands return self.executive_matches(text) elif fields[0] == "iraf": return self.taskdot_matches(fields) elif iraf.getTask(fields[0], found=1): # include both eval results and task. matches fields.insert(0, 'iraf') matches = self.taskdot_matches(fields) try: matches.extend(Completer.attr_matches(self,text)) except KeyboardInterrupt: raise except: pass return matches else: return Completer.attr_matches(self,text) else: # Check first character following initial alphabetic string # If next char is alphabetic (or null) use filename matches # Otherwise use matches from Python dictionaries #XXX need to make this consistent with the other places #XXX where same tests are done m = self.taskpat.match(line) if m is None or keyword.iskeyword(m.group(1)): fields = string.split(text,".") if fields[0] == "iraf": return self.taskdot_matches(fields) else: return Completer.attr_matches(self,text) else: #XXX Could try to match pset.param keywords too? lt = len(line)-len(text) return self.filename_matches(text, line[:lt])
def lock(self, *args): """Lock the specified tasks into the cache Takes task names (strings) as arguments. """ # don't bother if cache is disabled or full if self._plimit <= len(self._locked): return for taskname in args: task = iraf.getTask(taskname, found=1) if task is None: print "No such task `%s'" % taskname elif task.__class__.__name__ == "IrafTask": # cache only executable tasks (not CL tasks, etc.) executable = task.getFullpath() process = self.get(task, iraf.getVarDict()) self.add(process) if self._data.has_key(executable): self._locked[executable] = 1 else: self.error("Cannot cache %s\n" % taskname)
def __init__(self, taskName, parent=None, isChild=0, title="PyRAF Parameter Editor", childList=None): # Get the Iraftask object if isinstance(taskName, irafpar.IrafParList): # IrafParList acts as an IrafTask for our purposes self.taskObject = taskName else: # taskName must be a string or an IrafTask object self.taskObject = iraf.getTask(taskName) # Now go back and ensure we have the full taskname self.taskName = self.taskObject.getName() self.pkgName = self.taskObject.getPkgname() self.paramList = self.taskObject.getParList(docopy=1) # Ignore the last parameter which is $nargs self.numParams = len(self.paramList) - 1 # Get default parameter values for unlearn self.getDefaultParamList() # Create the root window as required, but hide it self.parent = parent if self.parent == None: root = Tk() root.withdraw() # Track whether this is a parent or child window self.isChild = isChild # Set up a color for the background to differeniate parent and child if self.isChild: # self.bkgColor = "LightSteelBlue" self.iconLabel = "EPAR Child" else: # self.bkgColor = "SlateGray3" self.iconLabel = "EPAR Parent" self.bkgColor = None # help windows do not exist yet self.irafHelpWin = None self.eparHelpWin = None # no last focus widget self.lastFocusWidget = None # Generate the top epar window self.top = top = Toplevel(self.parent, bg=self.bkgColor, visual="best") self.top.title("%s: %s.%s" % (title, self.pkgName, self.taskName)) self.top.iconname(self.iconLabel) # Read in the epar options database file optfile = "epar.optionDB" try: # User's current directory self.top.option_readfile(os.path.join(os.curdir, optfile)) except TclError: try: # User's startup directory self.top.option_readfile(os.path.join(userWorkingHome, optfile)) except TclError: # PyRAF default self.top.option_readfile(os.path.join(pyrafDir, optfile)) # Create an empty list to hold child EparDialogs # *** Not a good way, REDESIGN with Mediator! # Also, build the parent menu bar if self.parent == None: self.top.childList = [] elif childList is not None: # all children share a list self.top.childList = childList # Build the EPAR menu bar self.makeMenuBar(self.top) # Create a spacer Frame(self.top, bg=self.bkgColor, height=10).pack(side=TOP, fill=X) # Print the package and task names self.printNames(self.top, self.taskName, self.pkgName) # Insert a spacer between the static text and the buttons Frame(self.top, bg=self.bkgColor, height=15).pack(side=TOP, fill=X) # Set control buttons at the top of the frame self.buttonBox(self.top) # Insert a spacer between the static text and the buttons Frame(self.top, bg=self.bkgColor, height=15).pack(side=TOP, fill=X) # Set up an information Frame at the bottom of the EPAR window # RESIZING is currently disabled. # Do this here so when resizing to a smaller sizes, the parameter # panel is reduced - not the information frame. self.top.status = Label(self.top, text="", relief=SUNKEN, borderwidth=1, anchor=W) self.top.status.pack(side=BOTTOM, fill=X, padx=0, pady=3, ipady=3) # Set up a Frame to hold a scrollable Canvas self.top.f = frame = Frame(self.top, relief=RIDGE, borderwidth=1) # Overlay a Canvas which will hold a Frame self.top.f.canvas = canvas = Canvas(self.top.f, width=100, height=100, takefocus=FALSE) # Always build the scrollbar, even if number of parameters is small, # to allow window to be resized. # Attach a vertical Scrollbar to the Frame/Canvas self.top.f.vscroll = Scrollbar( self.top.f, orient=VERTICAL, width=11, relief=SUNKEN, activerelief=RAISED, takefocus=FALSE ) canvas["yscrollcommand"] = self.top.f.vscroll.set self.top.f.vscroll["command"] = canvas.yview # Pack the Scrollbar self.top.f.vscroll.pack(side=RIGHT, fill=Y) # enable Page Up/Down keys scroll = canvas.yview_scroll top.bind("<Next>", lambda event, fs=scroll: fs(1, "pages")) top.bind("<Prior>", lambda event, fs=scroll: fs(-1, "pages")) # make up, down arrows and return/shift-return do same as Tab, Shift-Tab top.bind("<Up>", self.focusPrev) top.bind("<Down>", self.focusNext) top.bind("<Shift-Return>", self.focusPrev) top.bind("<Return>", self.focusNext) try: # special shift-tab binding needed for (some? all?) linux systems top.bind("<KeyPress-ISO_Left_Tab>", self.focusPrev) except TclError: # Ignore exception here, the binding can't be relevant # if ISO_Left_Tab is unknown. pass # Pack the Frame and Canvas canvas.pack(side=TOP, expand=TRUE, fill=BOTH) self.top.f.pack(side=TOP, expand=TRUE, fill=BOTH) # Define a Frame to contain the parameter information canvas.entries = Frame(canvas) # Generate the window to hold the Frame which sits on the Canvas cWindow = canvas.create_window(0, 0, anchor=NW, window=canvas.entries) # Insert a spacer between the Canvas and the information frame Frame(self.top, bg=self.bkgColor, height=4).pack(side=TOP, fill=X) # The parent has the control, unless there are children # Fix the geometry of where the windows first appear on the screen if self.parent == None: # self.top.grab_set() # Position this dialog relative to the parent self.top.geometry("+%d+%d" % (PARENTX, PARENTY)) else: # self.parent.grab_release() # self.top.grab_set() # Declare the global variables so they can be updated global CHILDX global CHILDY # Position this dialog relative to the parent CHILDX = CHILDX + DCHILDX CHILDY = CHILDY + DCHILDY self.top.geometry("+%d+%d" % (CHILDX, CHILDY)) # # Now fill in the Canvas Window # # The makeEntries method creates the parameter entry Frame self.makeEntries(canvas.entries, self.top.status) # Force an update of the entry Frame canvas.entries.update() # Determine the size of the entry Frame width = canvas.entries.winfo_width() height = canvas.entries.winfo_height() # Reconfigure the Canvas size based on the Frame. if self.numParams <= MINPARAMS: viewHeight = height else: # Set the minimum display viewHeight = MINVIEW # Scrollregion is based upon the full size of the entry Frame canvas.config(scrollregion=(0, 0, width, height)) # Smooth scroll self.yscrollincrement = 50 canvas.config(yscrollincrement=self.yscrollincrement) # Set the actual viewable region for the Canvas canvas.config(width=width, height=viewHeight) # Force an update of the Canvas canvas.update() # Associate deletion of the main window to a Abort self.top.protocol("WM_DELETE_WINDOW", self.abort) # Set focus to first parameter self.entryNo[0].focus_set() # Enable interactive resizing in height self.top.resizable(width=FALSE, height=TRUE) # Limit maximum window height width = self.top.winfo_width() height = self.top.winfo_height() + height - viewHeight self.top.maxsize(width=width, height=height) # run the mainloop if not self.isChild: self.top.mainloop()
def __init__(self, taskName): MODE_KEYS_EMACS = [ "esc"] MODE_KEYS_VI = ["esc", "tab", "ctrl u", "ctrl U", "ctrl t", "ctrl T"] TPAR_BINDINGS = { # Page level bindings "quit" : self.QUIT, "exit " : self.EXIT, "help" : self.HELP, "end" : self.MOVE_END, "home" : self.MOVE_START, } # Get the Iraftask object if isinstance(taskName, irafpar.IrafParList): # IrafParList acts as an IrafTask for our purposes self.taskObject = taskName else: # taskName must be a string or an IrafTask object self.taskObject = iraf.getTask(taskName) # Now go back and ensure we have the full taskname self.taskName = self.taskObject.getName() self.pkgName = self.taskObject.getPkgname() self.paramList = self.taskObject.getParList(docopy=1) # See if there exist any special versions on disk to load self.__areAnyToLoad = irafpar.haveSpecialVersions(self.taskName, self.pkgName) # irafpar caches them # Ignore the last parameter which is $nargs self.numParams = len(self.paramList) - 1 # Get default parameter values for unlearn self.get_default_param_list() self.make_entries() self.escape = False if URWID_PRE_9P9: self._createButtonsOld() else: self._createButtons() self.colon_edit = PyrafEdit("", "", wrap="clip", align="left", inform=self.inform) self.listitems = [urwid.Divider(" ")] + self.entryNo + \ [urwid.Divider(" "), self.colon_edit, self.buttons] self.listbox = urwid.ListBox( self.listitems ) self.listbox.set_focus(1) self.footer = urwid.Text("") self.header = TparHeader(self.pkgName, self.taskName) self.view = urwid.Frame( self.listbox, header=self.header, footer=self.footer) self._editor = iraf.envget("editor") BINDINGS = {} BINDINGS.update(TPAR_BINDINGS) if self._editor == "vi": BINDINGS.update(TPAR_BINDINGS_VI) MODE_KEYS = MODE_KEYS_VI else: BINDINGS.update(TPAR_BINDINGS_EMACS) MODE_KEYS = MODE_KEYS_EMACS Binder.__init__(self, BINDINGS, self.inform, MODE_KEYS)
def __init__(self, taskName): MODE_KEYS_EMACS = ["esc"] MODE_KEYS_VI = ["esc", "tab", "ctrl u", "ctrl U", "ctrl t", "ctrl T"] TPAR_BINDINGS = { # Page level bindings "quit" : self.QUIT, "exit " : self.EXIT, "help" : self.HELP, "end" : self.MOVE_END, "home" : self.MOVE_START, } # Get the Iraftask object if isinstance(taskName, irafpar.IrafParList): # IrafParList acts as an IrafTask for our purposes self.taskObject = taskName else: # taskName must be a string or an IrafTask object self.taskObject = iraf.getTask(taskName) # Now go back and ensure we have the full taskname self.taskName = self.taskObject.getName() self.pkgName = self.taskObject.getPkgname() self.paramList = self.taskObject.getParList(docopy=1) # See if there exist any special versions on disk to load self.__areAnyToLoad = irafpar.haveSpecialVersions( self.taskName, self.pkgName) # irafpar caches them # Ignore the last parameter which is $nargs self.numParams = len(self.paramList) - 1 # Get default parameter values for unlearn self.get_default_param_list() self.make_entries() self.escape = False if URWID_PRE_9P9: self._createButtonsOld() else: self._createButtons() self.colon_edit = PyrafEdit("", "", wrap="clip", align="left", inform=self.inform) self.listitems = [urwid.Divider(" ")] + self.entryNo + \ [urwid.Divider(" "), self.colon_edit, self.buttons] self.listbox = urwid.ListBox(self.listitems) self.listbox.set_focus(1) self.footer = urwid.Text("") self.header = TparHeader(self.pkgName, self.taskName) self.view = urwid.Frame(self.listbox, header=self.header, footer=self.footer) self._editor = iraf.envget("editor") BINDINGS = {} BINDINGS.update(TPAR_BINDINGS) if self._editor == "vi": BINDINGS.update(TPAR_BINDINGS_VI) MODE_KEYS = MODE_KEYS_VI else: BINDINGS.update(TPAR_BINDINGS_EMACS) MODE_KEYS = MODE_KEYS_EMACS Binder.__init__(self, BINDINGS, self.inform, MODE_KEYS)