Changeset 5041:c94d1336fcc4
- Timestamp:
- 06/18/07 16:24:41 (6 years ago)
- Branch:
- default
- Children:
- 5042:2ef6ae624621, 5050:c4b38e5530da
- File:
-
- 1 edited
-
sage/server/notebook/worksheet.py (modified) (27 diffs)
Legend:
- Unmodified
- Added
- Removed
-
sage/server/notebook/worksheet.py
r5038 r5041 107 107 108 108 self.clear() 109 109 110 def __cmp__(self, other): 111 try: 112 return cmp(self.__filename, other.__filename) 113 except AttributeError: 114 return cmp(type(self), type(other)) 115 116 def __repr__(self): 117 return str(self.__cells) 118 119 def __len__(self): 120 return len(self.__cells) 121 122 ########################################################## 123 # Basic properties 124 # TODO: Need to create a worksheet configuration object 125 ########################################################## 126 def notebook(self): 127 return self.__notebook 128 129 def name(self): 130 return self.__name 131 132 def set_name(self, name): 133 self.__name = name 134 dir = list(name) 135 for i in range(len(dir)): 136 if not dir[i].isalnum() and dir[i] != '_': 137 dir[i] = '_' 138 dir = ''.join(dir) 139 self.__filename = dir 140 141 def filename(self): 142 return self.__filename 143 144 def directory(self): 145 if not os.path.exists(self.__dir): 146 # prevent "rm -rf" accidents. 147 os.makedirs(self.__dir) 148 return self.__dir 149 150 def DIR(self): 151 return self.__notebook.DIR() 152 153 def system(self): 154 try: 155 return self.__system 156 except AttributeError: 157 self.__system = None 158 return None 159 160 def set_system(self, system=None): 161 self.__system = system 162 163 ########################################################## 164 # Owner/viewer/user management 165 ########################################################## 110 166 111 167 def owner(self): … … 152 208 self.__collaborators = [user] 153 209 154 def clear(self): 155 self.__comp_is_running = False 156 if not os.path.exists(self.__dir): 157 os.makedirs(self.__dir) 158 self.__queue = [] 159 self.__cells = [ ] 160 for i in range(INITIAL_NUM_CELLS): 161 self.append_new_cell() 162 210 ########################################################## 211 # Setting and 212 ########################################################## 163 213 def set_notebook(self, notebook): 164 214 owner = self.owner() 165 215 self.__notebook = notebook 166 216 self.__dir = '%s/%s/%s'%(notebook.worksheet_directory(), owner, self.__filename) 167 168 def filename(self):169 return self.__filename170 217 171 218 def save(self, filename=None): … … 175 222 save(self, filename) 176 223 177 def __cmp__(self, other):178 try:179 return cmp(self.__filename, other.__filename)180 except AttributeError:181 return cmp(type(self), type(other))182 183 def computing(self):184 try:185 return self.__comp_is_running186 except AttributeError:187 return False188 189 def set_not_computing(self): 190 self.__comp_is_running = False191 self.__queue = []192 224 # The following setstate method is here 225 # so that when this object is pickled and 226 # unpickled, the self.__sage attribute 227 # will not be set, so it will properly initialized. 228 def __setstate__(self, state): 229 self.__dict__ = state 230 try: 231 del self.__sage 232 del self.__variables 233 self.__queue = [] 234 except AttributeError: 235 pass 236 237 ########################################################## 238 # Exporting the worksheet in plain text command-line format 239 ########################################################## 193 240 def plain_text(self, prompts=False): 194 241 """ … … 206 253 return s 207 254 255 def input_text(self): 256 """ 257 Return text version of the input to the worksheet. 258 """ 259 return '\n\n---\n\n'.join([C.input_text() for C in self.__cells]) 260 261 ########################################################## 262 # Editing the worksheet in plain text format (export and import) 263 ########################################################## 208 264 def edit_text(self, prompts=False): 209 265 """ … … 241 297 self.__cells = cells 242 298 243 def input_text(self): 244 """ 245 Return text version of the input to the worksheet. 246 """ 247 return '\n\n---\n\n'.join([C.input_text() for C in self.__cells]) 248 249 # The following setstate method is here 250 # so that when this object is pickled and 251 # unpickled, the self.__sage attribute 252 # will not be set, so it will properly initialized. 253 def __setstate__(self, state): 254 self.__dict__ = state 255 try: 256 del self.__sage 257 del self.__variables 258 self.__queue = [] 259 except AttributeError: 260 pass 299 ########################################################## 300 # HTML rendering of the whole worksheet 301 ########################################################## 302 def html(self, include_title=True, do_print=False, 303 confirm_before_leave=False, read_only=False): 304 n = len(self.__cells) 305 s = '' 306 if include_title: 307 if self.computing(): 308 interrupt_class = "interrupt" 309 else: 310 interrupt_class = "interrupt_grey" 311 S = self.system() 312 if not (S is None): 313 system = ' (%s mode)'%S 314 else: 315 system ='' 316 317 vbar = '<span class="vbar"></span>' 318 319 name = self.filename() 320 menu = ' <span class="worksheet_control_commands">' 321 menu += ' <a class="%s" onClick="interrupt()" id="interrupt">Interrupt</a>'%interrupt_class + vbar 322 menu += ' <a class="restart_sage" onClick="restart_sage()" id="restart_sage">Restart</a>' +vbar 323 menu += ' <a class="plain_text" href="%s">Edit</a>'%self.worksheet_command('edit') + vbar 324 #menu += ' <a class="doctest_text" onClick="doctest_window(\'%s\')">Text</a>'%name + vbar 325 menu += ' <a class="doctest_text" href="%s">Text</a>'%self.worksheet_command('plain') + vbar 326 #menu += ' <a class="doctest_text" onClick="print_window(\'%s\')">Print</a>'%name + vbar 327 menu += ' <a class="doctest_text" href="%s">Printable</a>'%self.worksheet_command('print') + vbar 328 menu += ' <a class="evaluate" onClick="evaluate_all()">Eval All</a>' + vbar 329 menu += ' <a class="hide" onClick="hide_all()">Hide</a>/<a class="hide" onClick="show_all()">Show</a>' + vbar 330 menu += ' <a class="slide_mode" onClick="slide_mode()">Focus</a>' + vbar 331 menu += ' <a class="download_sws" href="download/%s.sws">Download</a>'%self.filename() + vbar 332 menu += ' <a class="delete" href="delete">Delete</a>' 333 menu += ' </span>' 334 335 s += '<div class="worksheet_title">' 336 s += '%s%s%s%s</div>\n'%(self.name(), ' (read only) ' if read_only else '', system, menu) 337 338 D = self.__notebook.defaults() 339 ncols = D['word_wrap_cols'] 340 s += '<div class="worksheet_cell_list" id="worksheet_cell_list">\n' 341 for i in range(n): 342 cell = self.__cells[i] 343 s += cell.html(ncols,do_print=do_print) + '\n' 344 345 s += '\n</div>\n' 346 s += '\n<div class="insert_new_cell" id="insert_last_cell" onmousedown="insert_new_cell_after(cell_id_list[cell_id_list.length-1]);"> </div>\n' 347 s += '<div class="worksheet_bottom_padding"></div>\n' 348 349 if not do_print: 350 s += '<script language=javascript>cell_id_list=%s;\n'%self.compute_cell_id_list() 351 s += 'for(i=0;i<cell_id_list.length;i++) prettify_cell(cell_id_list[i]);</script>\n' 352 else: 353 s += '<script language=javascript>jsMath.ProcessBeforeShowing();</script>\n' 354 355 if not do_print and confirm_before_leave: 356 s += """<script type="text/javascript"> 357 window.onbeforeunload = confirmBrowseAway; 358 function confirmBrowseAway() 359 { 360 return "Unsubmitted cells will be lost."; 361 } 362 </script> 363 """ 364 return s 365 366 ########################################################## 367 # Managing cells and groups of cells in this worksheet 368 ########################################################## 261 369 262 370 def cell_id_list(self): … … 329 437 return cells[0].id() 330 438 331 def directory(self): 439 ########################################################## 440 # Managing whether computing is happening: stop, start, clear, etc. 441 ########################################################## 442 def clear(self): 443 self.__comp_is_running = False 332 444 if not os.path.exists(self.__dir): 333 # prevent "rm -rf" accidents.334 445 os.makedirs(self.__dir) 335 return self.__dir 336 337 def DIR(self): 338 return self.__notebook.DIR() 446 self.__queue = [] 447 self.__cells = [ ] 448 for i in range(INITIAL_NUM_CELLS): 449 self.append_new_cell() 450 451 def computing(self): 452 try: 453 return self.__comp_is_running 454 except AttributeError: 455 return False 456 457 def set_not_computing(self): 458 self.__comp_is_running = False 459 self.__queue = [] 339 460 340 461 def quit(self): … … 370 491 # We do this to avoid getting a stale SAGE that uses old code. 371 492 self.clear_queue() 372 373 493 374 494 def next_block_id(self): … … 433 553 self.initialize_sage() 434 554 return self.__sage 435 436 def _enqueue_auto_cells(self):437 for c in self.__cells:438 if c.is_auto_cell():439 self.enqueue(c)440 441 def _new_text_cell(self, plain_text, id=None):442 if id is None:443 id = self.__next_id444 self.__next_id += 1445 return TextCell(id, plain_text, self)446 447 def _new_cell(self, id=None):448 if id is None:449 id = self.__next_id450 self.__next_id += 1451 return Cell(id, '', '', self)452 453 def __repr__(self):454 return str(self.__cells)455 456 def __len__(self):457 return len(self.__cells)458 459 def __getitem__(self, n):460 try:461 return self.__cells[n]462 except IndexError:463 if n >= 0: # this should never happen -- but for robustness we cover this case.464 for k in range(len(self.__cells),n+1):465 self.__cells.append(self._new_cell())466 return self.__cells[n]467 raise IndexError468 469 470 def get_cell_with_id(self, id):471 for c in self.__cells:472 if c.id() == id:473 return c474 return self._new_cell(id)475 476 def queue(self):477 return list(self.__queue)478 479 def queue_id_list(self):480 return [c.id() for c in self.__queue]481 482 def _enqueue_auto(self):483 for c in self.__cells:484 if c.is_auto_cell():485 self.__queue.append(c)486 487 488 def enqueue(self, C):489 if not isinstance(C, Cell):490 raise TypeError491 if C.worksheet() != self:492 raise ValueError, "C must be have self as worksheet."493 # If the SAGE server hasn't started and the queue is empty,494 # first enqueue the auto cells:495 if len(self.__queue) == 0:496 try:497 self.__sage498 except AttributeError:499 self._enqueue_auto()500 501 # Now enqueue the requested cell.502 if not (C in self.__queue):503 self.__queue.append(C)504 self.start_next_comp()505 506 507 def synchronize(self, s):508 try:509 i = (self.__synchro + 1)%65536510 except AttributeError:511 i = 0512 self.__synchro = i513 return 'print "%s%s"\n'%(SAGE_BEGIN,i) + s + '\nprint "%s%s"\n'%(SAGE_END,i)514 515 def synchro(self):516 try:517 return self.__synchro518 except AttributeError:519 return 0520 521 def delete_cell_input_files(self):522 """523 Delete all the files code_%s.py and code_%s.spyx that are created524 when evaluating cells. We do this when we first start the notebook525 to get rid of clutter.526 """527 D = self.directory() + '/code/'528 if os.path.exists(D):529 for X in os.listdir(D):530 os.unlink('%s/%s'%(D,X))531 else:532 os.makedirs(D)533 555 534 556 def start_next_comp(self): … … 554 576 C.set_output_text('Exited %s process'%S,'') 555 577 return 556 if I [:5] == '%time':578 if I.startswith('%time'): 557 579 C.do_time() 558 I = I[5:].lstrip()559 elif I[:5] in ['time ', 'time\n', 'time\t']and not 'time' in V:580 I = after_first_word(I).lstrip() 581 elif first_word(I) == 'time' and not 'time' in V: 560 582 C.do_time() 561 I = I[5:].lstrip()583 I = after_first_word(I).lstrip() 562 584 else: 563 585 I = C.introspect()[0] … … 580 602 if C.time(): 581 603 input += '__SAGE_t__=cputime()\n__SAGE_w__=walltime()\n' 582 if I [-1:] == '?':604 if I.endswith('?'): 583 605 C.set_introspect(I, '') 584 606 I = I.replace('\\\n','') … … 634 656 C.set_output_text('The SAGE compute process quit (possibly SAGE crashed?).\nPlease retry your calculation.','') 635 657 636 637 638 def check_cell(self, id):639 """640 Check the status on computation of the cell with given id.641 642 INPUT:643 id -- an integer644 645 OUTPUT:646 status -- a string, either 'd' (done) or 'w' (working)647 cell -- the cell with given id648 """649 cell = self.get_cell_with_id(id)650 651 if cell in self.__queue:652 status = 'w'653 else:654 status = 'd'655 return status, cell656 657 658 def check_comp(self): 658 659 if len(self.__queue) == 0: … … 707 708 return 'd', C 708 709 710 def interrupt(self): 711 """ 712 Interrupt all currently queued up calculations. 713 714 OUTPUT: 715 bool -- return True if no problems interrupting calculation 716 return False if the SAGE interpreter had to be restarted. 717 """ 718 if len(self.__queue) == 0: 719 # nothing to do 720 return True 721 722 success = False 723 # stop the current computation in the running SAGE 724 try: 725 S = self.__sage 726 except AttributeError: 727 pass 728 else: 729 success = S.interrupt(INTERRUPT_TRIES, timeout=0.3, quit_on_fail=False) 730 731 if success: 732 self.clear_queue() 733 734 return success 735 736 def clear_queue(self): 737 # empty the queue 738 for C in self.__queue: 739 C.interrupt() 740 self.__queue = [] 741 self.__comp_is_running = False 742 743 def restart_sage(self): 744 """ 745 Restart SAGE kernel. 746 """ 747 self.quit() 748 749 self.__sage = initialized_sage(server = self.notebook().get_server(), 750 ulimit = self.notebook().get_ulimit()) 751 self.initialize_sage() 752 self._enqueue_auto_cells() 753 self.start_next_comp() 754 755 756 def worksheet_command(self, cmd): 757 return '/home/%s/%s'%(self.filename(), cmd) 758 759 ########################################################## 760 # Enqueuing cells 761 ########################################################## 762 def queue(self): 763 return list(self.__queue) 764 765 def queue_id_list(self): 766 return [c.id() for c in self.__queue] 767 768 def _enqueue_auto(self): 769 for c in self.__cells: 770 if c.is_auto_cell(): 771 self.__queue.append(c) 772 773 774 def enqueue(self, C): 775 if not isinstance(C, Cell): 776 raise TypeError 777 if C.worksheet() != self: 778 raise ValueError, "C must be have self as worksheet." 779 # If the SAGE server hasn't started and the queue is empty, 780 # first enqueue the auto cells: 781 if len(self.__queue) == 0: 782 try: 783 self.__sage 784 except AttributeError: 785 self._enqueue_auto() 786 787 # Now enqueue the requested cell. 788 if not (C in self.__queue): 789 self.__queue.append(C) 790 self.start_next_comp() 791 792 def _enqueue_auto_cells(self): 793 for c in self.__cells: 794 if c.is_auto_cell(): 795 self.enqueue(c) 796 797 def _new_text_cell(self, plain_text, id=None): 798 if id is None: 799 id = self.__next_id 800 self.__next_id += 1 801 return TextCell(id, plain_text, self) 802 803 def _new_cell(self, id=None): 804 if id is None: 805 id = self.__next_id 806 self.__next_id += 1 807 return Cell(id, '', '', self) 808 809 def append(self, L): 810 self.__cells.append(L) 811 812 ########################################################## 813 # Accessing existing cells 814 ########################################################## 815 def __getitem__(self, n): 816 try: 817 return self.__cells[n] 818 except IndexError: 819 if n >= 0: # this should never happen -- but for robustness we cover this case. 820 for k in range(len(self.__cells),n+1): 821 self.__cells.append(self._new_cell()) 822 return self.__cells[n] 823 raise IndexError 824 825 def get_cell_with_id(self, id): 826 for c in self.__cells: 827 if c.id() == id: 828 return c 829 return self._new_cell(id) 830 831 def synchronize(self, s): 832 try: 833 i = (self.__synchro + 1)%65536 834 except AttributeError: 835 i = 0 836 self.__synchro = i 837 return 'print "%s%s"\n'%(SAGE_BEGIN,i) + s + '\nprint "%s%s"\n'%(SAGE_END,i) 838 839 def synchro(self): 840 try: 841 return self.__synchro 842 except AttributeError: 843 return 0 844 845 def delete_cell_input_files(self): 846 """ 847 Delete all the files code_%s.py and code_%s.spyx that are created 848 when evaluating cells. We do this when we first start the notebook 849 to get rid of clutter. 850 """ 851 D = self.directory() + '/code/' 852 if os.path.exists(D): 853 for X in os.listdir(D): 854 os.unlink('%s/%s'%(D,X)) 855 else: 856 os.makedirs(D) 857 858 859 860 def check_cell(self, id): 861 """ 862 Check the status on computation of the cell with given id. 863 864 INPUT: 865 id -- an integer 866 867 OUTPUT: 868 status -- a string, either 'd' (done) or 'w' (working) 869 cell -- the cell with given id 870 """ 871 cell = self.get_cell_with_id(id) 872 873 if cell in self.__queue: 874 status = 'w' 875 else: 876 status = 'd' 877 return status, cell 878 879 def is_last_id_and_previous_is_nonempty(self, id): 880 if self.__cells[-1].id() != id: 881 return False 882 if len(self.__cells) == 1: 883 return False 884 if len(self.__cells[-2].output_text(ncols=0)) == 0: 885 return False 886 return True 887 888 889 ########################################################## 890 # (Tab) Completions 891 ########################################################## 709 892 def best_completion(self, s, word): 710 893 completions = s.split() … … 746 929 return self.__notebook.format_completions_as_html(id, rows) 747 930 931 ########################################################## 932 # Processing of input and output to worksheet process. 933 ########################################################## 934 def preparse_input(self, input, C): 935 C.set_is_html(False) 936 introspect = C.introspect() 937 if introspect: 938 input = self.preparse_introspection_input(input, C) 939 else: 940 switched, input = self.check_for_system_switching(input, C) 941 if not switched: 942 input = self.preparse_nonswitched_input(input) 943 input += '\n' 944 return input 945 946 def preparse_introspection_input(self, input, C): 947 before_prompt, after_prompt = introspect 948 i = 0 949 while i < len(after_prompt): 950 if after_prompt[i] == '?': 951 if i < len(after_prompt)-1 and after_prompt[i+1] == '?': 952 i += 1 953 before_prompt += after_prompt[:i+1] 954 after_prompt = after_prompt[i+1:] 955 C.set_introspect(before_prompt, after_prompt) 956 break 957 elif after_prompt[i] in ['"', "'", ' ', '\t', '\n']: 958 break 959 i += 1 960 if before_prompt.endswith('??'): 961 input = self._get_last_identifier(before_prompt[:-2]) 962 input = 'print _support_.source_code("%s", globals())'%input 963 elif before_prompt.endswith('?'): 964 input = self._get_last_identifier(before_prompt[:-1]) 965 input = 'print _support_.docstring("%s", globals())'%input 966 else: 967 input = self._get_last_identifier(before_prompt) 968 C._word_being_completed = input 969 input = 'print "\\n".join(_support_.completions("%s", globals()))'%(input) 970 return input 971 972 def preparse_nonswitched_input(self, input): 973 input = ignore_prompts_and_output(input).rstrip() 974 input = self.preparse(input) 975 input = self.load_any_changed_attached_files(input) 976 input = self.do_sage_extensions_preparsing(input) 977 input = input.split('\n') 978 979 # The following is all so the last line (or single lines) 980 # will implicitly print as they should, unless they are 981 # an assignment. "display hook" It's very complicated, 982 # but it has to be... 983 i = len(input)-1 984 if i >= 0: 985 while len(input[i]) > 0 and input[i][0] in ' \t': 986 i -= 1 987 t = '\n'.join(input[i:]) 988 if not t.startswith('def '): 989 try: 990 compile(t+'\n', '', 'single') 991 t = t.replace("'", "\\u0027").replace('\n','\\u000a') 992 # IMPORTANT: If you change this line, also change 993 # the function format_exception in cell.py 994 input[i] = "exec compile(ur'%s' + '\\n', '', 'single')"%t 995 input = input[:i+1] 996 except SyntaxError, msg: 997 pass 998 input = '\n'.join(input) 999 return input 1000 1001 748 1002 def _strip_synchro_from_start_of_output(self, s): 749 1003 z = SAGE_BEGIN+str(self.synchro()) … … 771 1025 return s.replace(SAGE_BEGIN,'').replace(SAGE_END,'').replace(SC,'') 772 1026 773 def is_last_id_and_previous_is_nonempty(self, id):774 if self.__cells[-1].id() != id:775 return False776 if len(self.__cells) == 1:777 return False778 if len(self.__cells[-2].output_text(ncols=0)) == 0:779 return False780 return True781 782 def interrupt(self):783 """784 Interrupt all currently queued up calculations.785 786 OUTPUT:787 bool -- return True if no problems interrupting calculation788 return False if the SAGE interpreter had to be restarted.789 """790 if len(self.__queue) == 0:791 # nothing to do792 return True793 794 success = False795 # stop the current computation in the running SAGE796 try:797 S = self.__sage798 except AttributeError:799 pass800 else:801 success = S.interrupt(INTERRUPT_TRIES, timeout=0.3, quit_on_fail=False)802 803 if success:804 self.clear_queue()805 806 return success807 808 def clear_queue(self):809 # empty the queue810 for C in self.__queue:811 C.interrupt()812 self.__queue = []813 self.__comp_is_running = False814 815 def restart_sage(self):816 """817 Restart SAGE kernel.818 """819 self.quit()820 821 self.__sage = initialized_sage(server = self.notebook().get_server(),822 ulimit = self.notebook().get_ulimit())823 self.initialize_sage()824 self._enqueue_auto_cells()825 self.start_next_comp()826 827 1027 def postprocess_output(self, out, C): 828 1028 i = out.find('\r\n') … … 873 1073 return s 874 1074 1075 ########################################################## 1076 # Loading and attaching files 1077 ########################################################## 875 1078 def load_any_changed_attached_files(self, s): 876 1079 """ … … 933 1136 if len(filename) > 0 and filename[0] != '/': 934 1137 filename = '%s/%s'%(self.DIR(), filename) 935 if filename[-3:] != '.py' and filename[-5:] != '.sage'and \936 filename[-5:] != '.sobj'and not os.path.exists(filename):1138 if not filename.endswith('.py') and not filename.endswith('.sage') and \ 1139 not filename.endswith('.sobj') and not os.path.exists(filename): 937 1140 if os.path.exists(filename + '.sage'): 938 1141 filename = filename + '.sage' … … 945 1148 946 1149 def _load_file(self, filename, files_seen_so_far, this_file): 947 if filename[-5:] == '.sobj': 948 i = filename.rfind('/') 949 if i != -1: 950 name = filename[i+1:-5] 951 else: 952 name = filename[:-5] 1150 if filename.endswith('.sobj'): 1151 name = os.path.splitext(filename)[0] 1152 name = os.path.split(name)[-1] 953 1153 return '%s = load("%s");'%(name, filename) 954 1154 … … 960 1160 return "print 'Error loading %s -- file not found'"%filename 961 1161 else: 962 if filename [-3:] == '.py':1162 if filename.endswith('.py'): 963 1163 t = F 964 elif filename [-5:] == '.sage':1164 elif filename.endswith('.sage'): 965 1165 t = self.preparse(F) 966 1166 else: … … 980 1180 u = [] 981 1181 for t in s.split('\n'): 982 if t [:5] == 'load ':1182 if t.startswith('load '): 983 1183 z = '' 984 for filename in self._normalized_filenames( t[5:]):1184 for filename in self._normalized_filenames(after_first_word(t)): 985 1185 z += self._load_file(filename, files_seen_so_far, this_file) + '\n' 986 1186 t = z 987 1187 988 elif t [:7] == 'attach ':1188 elif t.startswith('attach '): 989 1189 z = '' 990 for filename in self._normalized_filenames( t[7:]):1190 for filename in self._normalized_filenames(after_first_word(t)): 991 1191 if not os.path.exists(filename): 992 1192 z += "print 'Error attaching %s -- file not found'\n"%filename … … 996 1196 t = z 997 1197 998 elif t [:7] == 'detach ':999 for filename in self._normalized_filenames( t[7:]):1198 elif t.startswith('detach '): 1199 for filename in self._normalized_filenames(after_first_word(t)): 1000 1200 self.detach(filename) 1001 1201 t = '' 1002 1202 1003 elif t [:12] in ['save_session', 'load_session']:1004 F = t[12:].strip().strip('(').strip(')').strip("'").strip('"').split(',')[0]1203 elif t.startswith('save_session') or t.startswith('load_session'): 1204 F = after_first_word(t).strip().strip('(').strip(')').strip("'").strip('"').split(',')[0] 1005 1205 if len(F) == 0: 1006 1206 filename = self.__filename 1007 1207 else: 1008 1208 filename = F 1009 if t [:4] == 'save':1209 if t.startswith('save'): 1010 1210 t = '_support_.save_session("%s")'%filename 1011 1211 else: 1012 1212 t = 'load_session(locals(), "%s")'%filename 1013 1213 1014 elif t [:5] == 'save ':1015 t = self._save_objects( t[5:])1214 elif t.startswith('save '): 1215 t = self._save_objects(after_first_word(t)) 1016 1216 1017 1217 u.append(t) … … 1019 1219 return '\n'.join(u) 1020 1220 1021 def system(self):1022 try:1023 return self.__system1024 except AttributeError:1025 self.__system = None1026 return None1027 1028 def set_system(self, system=None):1029 self.__system = system1030 1031 1221 def _eval_cmd(self, system, cmd): 1032 1222 cmd = cmd.replace("'", "\\u0027") 1033 1223 return "print _support_.syseval(%s, ur'''%s''')"%(system, cmd) 1224 1225 ########################################################## 1226 # Parsing the %sagex, %jsmath, %python, etc., extension. 1227 ########################################################## 1034 1228 1035 1229 def sagex_import(self, cmd, C): … … 1056 1250 S = self.system() 1057 1251 if not (S is None): 1058 if s[:5] != '%sage': 1252 if s.startswith('%sage'): 1253 s = after_first_word(s).lstrip() 1254 z = s 1255 else: 1059 1256 return True, self._eval_cmd(self.__system, s) 1060 else:1061 s = s[5:].lstrip()1062 z = s1063 1257 1064 1258 if len(s) == 0 or s[0] != '%': 1065 1259 return False, z 1066 if s [:5] == '%hide':1067 t = s[5:].lstrip()1260 if s.startswith('%hide'): 1261 t = after_first_word(s).lstrip() 1068 1262 if len(t) == 0 or t[0] != '%': 1069 1263 return False, t 1070 1264 s = t 1071 if s [:12] == '%save_server':1265 if s.startswith('%save_server'): 1072 1266 self.notebook().save() 1073 t = s[12:].lstrip()1267 t = after_first_word(s).lstrip() 1074 1268 if len(t) == 0 or t[0] != '%': 1075 1269 return False, t 1076 1270 s = t 1077 if s [:6] == "%pyrex" or s[:6] == "%sagex": # a block of Sagex code.1078 return True, self.sagex_import( s[6:].lstrip(), C)1271 if s.startswith("%pyrex") or s.startswith("%sagex"): # a block of Sagex code. 1272 return True, self.sagex_import(after_first_word(s).lstrip(), C) 1079 1273 1080 1274 i = s.find('\n') … … 1094 1288 return True, cmd 1095 1289 1096 def preparse_input(self, input, C): 1097 C.set_is_html(False) 1098 introspect = C.introspect() 1099 if introspect: 1100 before_prompt, after_prompt = introspect 1101 i = 0 1102 while i < len(after_prompt): 1103 if after_prompt[i] == '?': 1104 if i < len(after_prompt)-1 and after_prompt[i+1] == '?': 1105 i += 1 1106 before_prompt += after_prompt[:i+1] 1107 after_prompt = after_prompt[i+1:] 1108 C.set_introspect(before_prompt, after_prompt) 1109 break 1110 elif after_prompt[i] in ['"', "'", ' ', '\t', '\n']: 1111 break 1112 i += 1 1113 if before_prompt[-2:] == '??': 1114 input = self._get_last_identifier(before_prompt[:-2]) 1115 input = 'print _support_.source_code("%s", globals())'%input 1116 elif before_prompt[-1:] == '?': 1117 input = self._get_last_identifier(before_prompt[:-1]) 1118 input = 'print _support_.docstring("%s", globals())'%input 1119 else: 1120 input = self._get_last_identifier(before_prompt) 1121 C._word_being_completed = input 1122 input = 'print "\\n".join(_support_.completions("%s", globals()))'%(input) 1123 1124 else: 1125 switched, input = self.check_for_system_switching(input, C) 1126 1127 if not switched: 1128 input = ignore_prompts_and_output(input).rstrip() 1129 input = self.preparse(input) 1130 input = self.load_any_changed_attached_files(input) 1131 input = self.do_sage_extensions_preparsing(input) 1132 input = input.split('\n') 1133 1134 # The following is all so the last line (or single lines) 1135 # will implicitly print as they should, unless they are 1136 # an assignment. "display hook" It's very complicated, 1137 # but it has to be... 1138 i = len(input)-1 1139 if i >= 0: 1140 while len(input[i]) > 0 and input[i][0] in ' \t': 1141 i -= 1 1142 t = '\n'.join(input[i:]) 1143 if t[:4] != 'def ': 1144 try: 1145 compile(t+'\n', '', 'single') 1146 t = t.replace("'", "\\u0027").replace('\n','\\u000a') 1147 # IMPORTANT: If you change this line, also change 1148 # the function format_exception in cell.py 1149 input[i] = "exec compile(ur'%s' + '\\n', '', 'single')"%t 1150 input = input[:i+1] 1151 except SyntaxError, msg: 1152 pass 1153 input = '\n'.join(input) 1154 1155 input += '\n' 1156 1157 #print input 1158 return input 1159 1160 def notebook(self): 1161 return self.__notebook 1162 1163 def name(self): 1164 return self.__name 1165 1166 def set_name(self, name): 1167 self.__name = name 1168 dir = list(name) 1169 for i in range(len(dir)): 1170 if not dir[i].isalnum() and dir[i] != '_': 1171 dir[i] = '_' 1172 dir = ''.join(dir) 1173 self.__filename = dir 1174 1175 def append(self, L): 1176 self.__cells.append(L) 1177 1290 ########################################################## 1291 # List of defined variables. 1292 ########################################################## 1178 1293 def known_variables(self): 1179 1294 try: … … 1223 1338 return s 1224 1339 1225 def worksheet_command(self, cmd): 1226 return '/home/%s/%s'%(self.filename(), cmd) 1227 1228 def html(self, include_title=True, do_print=False, 1229 confirm_before_leave=False, read_only=False): 1230 n = len(self.__cells) 1231 s = '' 1232 if include_title: 1233 if self.computing(): 1234 interrupt_class = "interrupt" 1235 else: 1236 interrupt_class = "interrupt_grey" 1237 S = self.system() 1238 if not (S is None): 1239 system = ' (%s mode)'%S 1240 else: 1241 system ='' 1242 1243 vbar = '<span class="vbar"></span>' 1244 1245 name = self.filename() 1246 menu = ' <span class="worksheet_control_commands">' 1247 menu += ' <a class="%s" onClick="interrupt()" id="interrupt">Interrupt</a>'%interrupt_class + vbar 1248 menu += ' <a class="restart_sage" onClick="restart_sage()" id="restart_sage">Restart</a>' +vbar 1249 menu += ' <a class="plain_text" href="%s">Edit</a>'%self.worksheet_command('edit') + vbar 1250 #menu += ' <a class="doctest_text" onClick="doctest_window(\'%s\')">Text</a>'%name + vbar 1251 menu += ' <a class="doctest_text" href="%s">Text</a>'%self.worksheet_command('plain') + vbar 1252 #menu += ' <a class="doctest_text" onClick="print_window(\'%s\')">Print</a>'%name + vbar 1253 menu += ' <a class="doctest_text" href="%s">Printable</a>'%self.worksheet_command('print') + vbar 1254 menu += ' <a class="evaluate" onClick="evaluate_all()">Eval All</a>' + vbar 1255 menu += ' <a class="hide" onClick="hide_all()">Hide</a>/<a class="hide" onClick="show_all()">Show</a>' + vbar 1256 menu += ' <a class="slide_mode" onClick="slide_mode()">Focus</a>' + vbar 1257 menu += ' <a class="download_sws" href="download/%s.sws">Download</a>'%self.filename() + vbar 1258 menu += ' <a class="delete" href="delete">Delete</a>' 1259 menu += ' </span>' 1260 1261 s += '<div class="worksheet_title">' 1262 s += '%s%s%s%s</div>\n'%(self.name(), ' (read only) ' if read_only else '', system, menu) 1263 1264 D = self.__notebook.defaults() 1265 ncols = D['word_wrap_cols'] 1266 s += '<div class="worksheet_cell_list" id="worksheet_cell_list">\n' 1267 for i in range(n): 1268 cell = self.__cells[i] 1269 s += cell.html(ncols,do_print=do_print) + '\n' 1270 1271 s += '\n</div>\n' 1272 s += '\n<div class="insert_new_cell" id="insert_last_cell" onmousedown="insert_new_cell_after(cell_id_list[cell_id_list.length-1]);"> </div>\n' 1273 s += '<div class="worksheet_bottom_padding"></div>\n' 1274 1275 if not do_print: 1276 s += '<script language=javascript>cell_id_list=%s;\n'%self.compute_cell_id_list() 1277 s += 'for(i=0;i<cell_id_list.length;i++) prettify_cell(cell_id_list[i]);</script>\n' 1278 else: 1279 s += '<script language=javascript>jsMath.ProcessBeforeShowing();</script>\n' 1280 1281 if not do_print and confirm_before_leave: 1282 s += """<script type="text/javascript"> 1283 window.onbeforeunload = confirmBrowseAway; 1284 function confirmBrowseAway() 1285 { 1286 return "Unsubmitted cells will be lost."; 1287 } 1288 </script> 1289 """ 1290 return s 1291 1340 ########################################################## 1341 # Showing and hiding all cells 1342 ########################################################## 1292 1343 def show_all(self): 1293 1344 for C in self.__cells: … … 1317 1368 for I in t: 1318 1369 I2 = I.lstrip() 1319 if I2 [:5] == 'sage:' or I2[:3] == '>>>':1370 if I2.startswith('sage:') or I2.startswith('>>>'): 1320 1371 do_strip = True 1321 1372 break … … 1325 1376 for I in t: 1326 1377 I2 = I.lstrip() 1327 if I2 [:5] == 'sage:':1328 s += I2[5:].lstrip() + '\n'1329 elif I2 [:3] == '>>>':1330 s += I2[3:].lstrip() + '\n'1331 elif I2 [:3] == '...':1332 s += I2[3:]+ '\n'1378 if I2.startswith('sage:'): 1379 s += after_first_word(I2).lstrip() + '\n' 1380 elif I2.startswith('>>>'): 1381 s += after_first_word(I2).lstrip() + '\n' 1382 elif I2.startswith('...'): 1383 s += after_first_word(I2) + '\n' 1333 1384 return s 1334 1385 … … 1377 1428 output = text[k+4:l].strip() 1378 1429 return input.strip(), output, graphics, j+4 1379 1430 1431 import re 1432 whitespace = re.compile('\s') # Match any whitespace character 1433 def after_first_word(s): 1434 """ 1435 Return everything after the first whitespace in the string s. 1436 Returns the empty string if there is nothing after the 1437 first whitespace. 1438 1439 INPUT: 1440 s -- string 1441 OUTPUT: 1442 a string 1443 """ 1444 i = whitespace.search(s) 1445 if i is None: 1446 return '' 1447 return s[i.start()+1:] 1448 1449 def first_word(s): 1450 i = whitespace.search(s) 1451 if i is None: 1452 return s 1453 return s[:i.start()]
Note: See TracChangeset
for help on using the changeset viewer.
