def test_config_file_0(): #-------------------------------------------------------------------------------------- from test_utils import adjust_environment, assert_equals adjust_environment() from reinteract.config_file import _quote_list, _quote, _unquote, _unquote_list import tempfile def test_quote(s, expected): quoted = _quote(s) assert_equals(quoted, expected) unquoted = _unquote(quoted) assert_equals(unquoted, s) test_quote(r'', r'""') test_quote(r'foo', r'foo') test_quote(r'fo"o', r'"fo\"o"') test_quote(r'fo o', r'"fo o"') test_quote(r'fo\o', r'fo\\o') def test_quote_list(l, expected): quoted = _quote_list(l) assert_equals(quoted, expected) unquoted = _unquote_list(quoted) assert_equals(unquoted, l) test_quote_list(['foo'], 'foo') test_quote_list(['foo bar'], '"foo bar"') test_quote_list(['foo', 'bar'], 'foo bar') test_quote_list(['foo', 'bar baz'], 'foo "bar baz"') #-------------------------------------------------------------------------------------- pass
def test_worksheet_2() : #-------------------------------------------------------------------------------------- from test_utils import adjust_environment global_settings = adjust_environment() import os examplesdir = global_settings.examples_dir filename = os.path.join(examplesdir, 'imshow.rws').decode('UTF-8') #-------------------------------------------------------------------------------------- from reinteract.notebook import Notebook from reinteract.worksheet import Worksheet worksheet = Worksheet( Notebook() ) worksheet.load(filename) worksheet.calculate(wait=True) custom_results = [] from reinteract.chunks import StatementChunk from reinteract.custom_result import CustomResult for x in worksheet.iterate_chunks() : if not isinstance(x,StatementChunk) : continue if len(x.results) == 0 : continue arg = x.results[0] if isinstance(arg, CustomResult): custom_results.append(arg) pass pass assert len(custom_results) == 2 #-------------------------------------------------------------------------------------- pass
def test_application_state_0(): #-------------------------------------------------------------------------------------- from test_utils import adjust_environment, assert_equals adjust_environment() from reinteract.application_state import ApplicationState, _section_name import tempfile, os #-------------------------------------------------------------------------------------- def test_section_name(path, expected): section_name = _section_name(path) assert_equals(section_name, expected) test_section_name('C:\foo', 'C:\foo') test_section_name('foo[]', 'foo%5b%5d') #-------------------------------------------------------------------------------------- f, location = tempfile.mkstemp(".state", "reinteract") os.close(f) try: nb_path = "C:\\Foo\\Bar" application_state = ApplicationState(location) application_state.notebook_opened(nb_path) nb_state = application_state.get_notebook_state(nb_path) nb_state.set_open_files([u"foo.rws", u"bar.rws"]) application_state.flush() application_state = ApplicationState(location) recent_notebooks = application_state.get_recent_notebooks() assert_equals(len(recent_notebooks), 1) assert_equals(recent_notebooks[0].path, nb_path) nb_state = application_state.get_notebook_state(nb_path) assert nb_state.get_last_opened() > 0 assert_equals(nb_state.get_open_files(), [u"foo.rws", u"bar.rws"]) finally: try: os.remove(location) except: pass pass #-------------------------------------------------------------------------------------- pass
def test_recorded_object_0(): #-------------------------------------------------------------------------------------- from test_utils import adjust_environment, assert_equals adjust_environment() from reinteract.recorded_object import RecordedObject #-------------------------------------------------------------------------------------- class TestTarget: def __init__(): pass def exactargs(self, a, b): pass def defaultargs(self, a, b=1): pass def varargs(self, *args): pass def kwargs(self, **kwargs): pass pass class TestRecorded(RecordedObject): pass TestRecorded._set_target_class(TestTarget) o = TestRecorded() # Tests of our argument checking def expect_ok(method, *args, **kwargs): o.__class__.__dict__[method](o, *args, **kwargs) def expect_fail(method, msg, *args, **kwargs): try: o.__class__.__dict__[method](o, *args, **kwargs) raise AssertionError("Expected failure with '%s', got success" % (msg, )) except TypeError, e: if str(e) != msg: raise AssertionError("Expected failure with '%s', got '%s'" % (msg, str(e)))
def test_recorded_object_0(): #-------------------------------------------------------------------------------------- from test_utils import adjust_environment, assert_equals adjust_environment() from reinteract.recorded_object import RecordedObject #-------------------------------------------------------------------------------------- class TestTarget: def __init__(): pass def exactargs(self, a, b): pass def defaultargs(self, a, b=1): pass def varargs(self, *args): pass def kwargs(self, **kwargs): pass pass class TestRecorded(RecordedObject): pass TestRecorded._set_target_class(TestTarget) o = TestRecorded() # Tests of our argument checking def expect_ok(method, *args, **kwargs): o.__class__.__dict__[method](o, *args, **kwargs) def expect_fail(method, msg, *args, **kwargs): try: o.__class__.__dict__[method](o, *args, **kwargs) raise AssertionError("Expected failure with '%s', got success" % (msg,)) except TypeError, e: if str(e) != msg: raise AssertionError("Expected failure with '%s', got '%s'" % (msg, str(e)))
def test_destroyable_0(): #-------------------------------------------------------------------------------------- from test_utils import adjust_environment, assert_equals adjust_environment() from reinteract.destroyable import Destroyable import gobject #-------------------------------------------------------------------------------------- class A(Destroyable, gobject.GObject): __gsignals__ = { 'changed': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()) } def do_a(*args): results.append('a') def do_b(*args): results.append('b') a = A() a.connect('changed', do_a) handler_id = a.connect('changed', do_b) a.disconnect(handler_id) results = [] a.emit('changed') assert_equals(results, ['a']) a.destroy() results = [] a.emit('changed') assert_equals(results, []) #-------------------------------------------------------------------------------------- pass
def test_reunicode_0(): #-------------------------------------------------------------------------------------- from test_utils import adjust_environment, assert_equals adjust_environment() from reinteract.reunicode import decode, escape_unsafe #-------------------------------------------------------------------------------------- def test_escape_unsafe(u, expected): assert_equals(escape_unsafe(u), expected) # Embedded NUL is \x00 test_escape_unsafe(u"a\x00b", u"a\\x00b") # Test a tab is left untouched test_escape_unsafe(u"\t", u"\t") # Non-BMP character (represented as surrogates for UCS-2 python) test_escape_unsafe(u"\U00010000", u"\\U00010000") # Unpaired surrogate test_escape_unsafe(u"\ud800", u"\\ud800") def test_decode_escaped(s, expected): assert_equals(decode(s, escape=True), expected) # Valid UTF-8 test_decode_escaped(u"\u1234".encode("utf8"), u"\u1234") # Invalid UTF-8 test_decode_escaped("abc\x80\x80abc", u"abc\\x80\\x80abc") # Mixture test_decode_escaped(u"\u1234".encode("utf8") + "\x80", u"\u1234\\x80") # embedded NUL test_decode_escaped("\x00", "\\x00") # Test a non-UTF-8 encoding assert_equals(decode("\xc0", encoding="ISO-8859-1"), u"\u00c0") #-------------------------------------------------------------------------------------- pass
def test_signals_2(): #-------------------------------------------------------------------------------------- from test_utils import adjust_environment global_settings = adjust_environment() from reinteract.signals import Signal, Append #-------------------------------------------------------------------------------------- class Container(object): def __init__(self): pass @Append(__init__) def __init__(self, *args, **kwargs): self._attr = 'dummy' self.attr_sig = Signal() pass @property def attr(self): return self._attr @attr.setter def attr(self, the_value): self._attr = the_value self.attr_sig(self, self._attr) pass pass #-------------------------------------------------------------------------------------- def listener(the_container, the_attr): listener.LOGGER.append(the_attr) pass listener.LOGGER = [] #-------------------------------------------------------------------------------------- a_container = Container() a_container.attr_sig.connect(listener) a_container.attr = 'funny' assert len(listener.LOGGER) == 1 #-------------------------------------------------------------------------------------- pass
def test_signals_2() : #-------------------------------------------------------------------------------------- from test_utils import adjust_environment global_settings = adjust_environment() from reinteract.signals import Signal, Append #-------------------------------------------------------------------------------------- class Container( object ) : def __init__( self ) : pass @Append( __init__ ) def __init__( self, *args, **kwargs ) : self._attr = 'dummy' self.attr_sig = Signal() pass @property def attr( self ) : return self._attr @attr.setter def attr( self, the_value ) : self._attr = the_value self.attr_sig( self, self._attr ) pass pass #-------------------------------------------------------------------------------------- def listener( the_container, the_attr ) : listener.LOGGER.append( the_attr ) pass listener.LOGGER = [] #-------------------------------------------------------------------------------------- a_container = Container() a_container.attr_sig.connect( listener ) a_container.attr = 'funny' assert len( listener.LOGGER ) == 1 #-------------------------------------------------------------------------------------- pass
def test_worksheet_1() : #-------------------------------------------------------------------------------------- from test_utils import adjust_environment topdir = adjust_environment() from reinteract.notebook import Notebook from reinteract.worksheet import Worksheet #-------------------------------------------------------------------------------------- class Logger : def __init__( self ) : self._log = [] pass def __call__( self, *args ) : self._log.append( args ) pass def __len__( self ) : return len( self._log ) def clean( self ) : del self._log[ : ] pass pass #-------------------------------------------------------------------------------------- worksheet = Worksheet( Notebook() ) a_logger = Logger() worksheet.sig_code_modified.connect( lambda *args : a_logger( *args ) ) #-------------------------------------------------------------------------------------- a_logger.clean() worksheet.begin_user_action() worksheet.insert(0, 0, "11\n22\n33") assert worksheet.in_user_action() == True assert len( a_logger ) == 1 worksheet.end_user_action() #-------------------------------------------------------------------------------------- pass
def test_worksheet_0() : #-------------------------------------------------------------------------------------- from test_utils import adjust_environment adjust_environment() from reinteract.chunks import StatementChunk, BlankChunk, CommentChunk from reinteract.notebook import Notebook, NotebookFile from reinteract.worksheet import Worksheet, _debug S = StatementChunk B = BlankChunk C = CommentChunk #-------------------------------------------------------------------------------------- def compare(l1, l2): if len(l1) != len(l2): return False for i in xrange(0, len(l1)): e1 = l1[i] e2 = l2[i] if type(e1) != type(e2) or e1.start != e2.start or e1.end != e2.end: return False return True #-------------------------------------------------------------------------------------- worksheet = Worksheet(Notebook()) #-------------------------------------------------------------------------------------- def expect(expected): chunks = [ x for x in worksheet.iterate_chunks() ] if not compare(chunks, expected): raise AssertionError("\nGot:\n %s\nExpected:\n %s" % (chunks, expected)) #-------------------------------------------------------------------------------------- def expect_text(expected, start_line=0, start_offset=0, end_line=-1, end_offset=-1): text = worksheet.get_text(start_line, start_offset, end_line, end_offset) if (text != expected): raise AssertionError("\nGot:\n '%s'\nExpected:\n '%s'" % (text, expected)) #-------------------------------------------------------------------------------------- def expect_doctests(expected, start_line, end_line): text = worksheet.get_doctests(start_line, end_line) if (text != expected): raise AssertionError("\nGot:\n '%s'\nExpected:\n '%s'" % (text, expected)) #-------------------------------------------------------------------------------------- def expect_results(expected): results = [ (x.results if isinstance(x,StatementChunk) else None) for x in worksheet.iterate_chunks() ] if (results != expected): raise AssertionError("\nGot:\n '%s'\nExpected:\n '%s'" % (results, expected)) #-------------------------------------------------------------------------------------- def insert(line, offset, text): worksheet.insert(line, offset, text) #-------------------------------------------------------------------------------------- def delete(start_line, start_offset, end_line, end_offset): worksheet.delete_range(start_line, start_offset, end_line, end_offset) #-------------------------------------------------------------------------------------- def calculate(): worksheet.calculate(wait=True) #-------------------------------------------------------------------------------------- def clear(): worksheet.clear() #-------------------------------------------------------------------------------------- def chunk_label(chunk): if chunk.end - chunk.start == 1: return "[%s]" % chunk.start else: return "[%s:%s]" % (chunk.start, chunk.end) #-------------------------------------------------------------------------------------- class CI: def __init__(self, start, end): self.start = start self.end = end def __eq__(self, other): if not isinstance(other, CI): return False return self.start == other.start and self.end == other.end def __repr__(self): return "CI(%s, %s)" % (self.start, self.end) #-------------------------------------------------------------------------------------- class CC: def __init__(self, start, end, changed_lines): self.start = start self.end = end self.changed_lines = changed_lines def __eq__(self, other): if not isinstance(other, CC): return False return self.start == other.start and self.end == other.end and self.changed_lines == other.changed_lines def __repr__(self): return "CC(%s, %s, %s)" % (self.start, self.end, self.changed_lines) #-------------------------------------------------------------------------------------- class CD: def __eq__(self, other): if not isinstance(other, CD): return False return True def __repr__(self): return "CD()" #-------------------------------------------------------------------------------------- class CSC: def __init__(self, start, end): self.start = start self.end = end def __eq__(self, other): if not isinstance(other, CSC): return False return self.start == other.start and self.end == other.end def __repr__(self): return "CSC(%s, %s)" % (self.start, self.end) #-------------------------------------------------------------------------------------- class CRC: def __init__(self, start, end): self.start = start self.end = end def __eq__(self, other): if not isinstance(other, CRC): return False return self.start == other.start and self.end == other.end def __repr__(self): return "CRC(%s, %s)" % (self.start, self.end) pass #-------------------------------------------------------------------------------------- class Logger : def __init__( self ) : self._log = [] pass def on_chunk_inserted( self, worksheet, chunk ) : _debug("...Chunk %s inserted", chunk_label(chunk)) self._log.append(CI(chunk.start, chunk.end)) pass def on_chunk_changed( self, worksheet, chunk, changed_lines ) : _debug("...Chunk %s changed", chunk_label(chunk)) self._log.append(CC(chunk.start, chunk.end, changed_lines)) pass def on_chunk_deleted( self, worksheet, chunk ) : _debug("...Chunk %s deleted", chunk_label(chunk)) self._log.append(CD()) pass def on_chunk_status_changed( self, worksheet, chunk ) : _debug("...Chunk %s status changed", chunk_label(chunk)) self._log.append(CSC(chunk.start, chunk.end)) pass def on_chunk_results_changed( self, worksheet, chunk ) : _debug("...Chunk %s results changed", chunk_label(chunk)) self._log.append(CRC(chunk.start, chunk.end)) pass def clear_log( self ) : self._log = [] pass def expect_log( self, expected ) : if self._log != expected: raise AssertionError("\nGot:\n '%s'\nExpected:\n '%s'" % (log, expected)) self.clear_log() pass pass #-------------------------------------------------------------------------------------- a_logger = Logger() worksheet.sig_chunk_inserted.connect( a_logger.on_chunk_inserted ) worksheet.sig_chunk_changed.connect( a_logger.on_chunk_changed ) worksheet.sig_chunk_deleted.connect( a_logger.on_chunk_deleted ) worksheet.sig_chunk_status_changed.connect( a_logger.on_chunk_status_changed ) worksheet.sig_chunk_results_changed.connect( a_logger.on_chunk_results_changed ) # Insertions insert(0, 0, "11\n22\n33") expect_text("11\n22\n33") expect([S(0,1), S(1,2), S(2,3)]) insert(0, 1, "a") expect_text("1a1\n22\n33") expect([S(0,1), S(1,2), S(2,3)]) insert(1, 1, "a\na") expect_text("1a1\n2a\na2\n33") expect([S(0,1), S(1,2), S(2,3), S(3,4)]) insert(1, 0, "bb\n") expect_text("1a1\nbb\n2a\na2\n33") expect([S(0,1), S(1,2), S(2,3), S(3,4), S(4, 5)]) insert(4, 3, "\n") expect_text("1a1\nbb\n2a\na2\n33\n") expect([S(0,1), S(1,2), S(2,3), S(3,4), S(4, 5), B(5, 6)]) # Deletions delete(4, 3, 5, 0) expect_text("1a1\nbb\n2a\na2\n33") expect([S(0,1), S(1,2), S(2,3), S(3,4), S(4, 5)]) delete(0, 1, 0, 2) expect_text("11\nbb\n2a\na2\n33") expect([S(0,1), S(1,2), S(2,3), S(3,4), S(4, 5)]) delete(0, 0, 1, 0) expect_text("bb\n2a\na2\n33") expect([S(0,1), S(1,2), S(2,3), S(3,4)]) delete(1, 1, 2, 1) expect_text("bb\n22\n33") expect([S(0,1), S(1,2), S(2,3)]) delete(2, 1, 1, 0) expect_text("bb\n3") expect([S(0,1), S(1,2)]) # Test deleting part of a BlankChunk clear() insert(0, 0, "if True\n: pass\n \n") delete(2, 4, 3, 0) # Check that tracking of changes works properly when there # is an insertion or deletion before the change clear() insert(0, 0, "1\n2") worksheet.begin_user_action() insert(1, 0, "#") insert(0, 0, "0\n") worksheet.end_user_action() expect_text("0\n1\n#2") expect([S(0,1), S(1,2), C(2,3)]) worksheet.begin_user_action() delete(2, 0, 2, 1) delete(0, 0, 1, 0) worksheet.end_user_action() expect([S(0,1), S(1,2)]) # Basic tokenization of valid python clear() insert(0, 0, "1\n\n#2\ndef a():\n 3") expect([S(0,1), B(1,2), C(2,3), S(3,5)]) clear() expect([B(0,1)]) # Multiple consecutive blank lines clear() insert(0, 0, "1") insert(0, 1, "\n") expect([S(0,1),B(1,2)]) insert(1, 0, "\n") expect([S(0,1),B(1,3)]) # Continuation lines at the beginning clear() insert(0, 0, "# Something\n pass") expect([C(0,1), S(1,2)]) delete(0, 0, 1, 0) expect([S(0,1)]) # Decorators clear() insert(0, 0, "def foo():\n return 42") expect([S(0,2)]) insert(0, 0, "@decorated\n") expect([S(0,3)]) insert(0, 0, "@decorated\n") expect([S(0,4)]) # decorator in the middle breaks things up insert(3, 0, "@decorated\n") expect([S(0,3), S(3,5)]) delete(3, 0, 4, 0) expect([S(0,4)]) # lonely decorator at the end of a worksheet clear() insert(0, 0, "@decorated\n# some comment\n") expect([S(0,1), C(1,2), B(2,3)]) insert(2, 0, "def foo():\n return 42") expect([S(0,4)]) # Calculation clear() insert(0, 0, "1 + 1") calculate() expect_results([['2']]) clear() insert(0, 0, "print 1") calculate() expect_results([['1']]) clear() insert(0, 0, "if True:\n print 1\n print 1") calculate() expect_results([['1', '1']]) clear() insert(0, 0, "a = 1\nb = 2\na + b") calculate() expect_results([[], [], ['3']]) delete(1, 4, 1, 5) insert(1, 4, "3") calculate() expect_results([[], [], ['4']]) #-------------------------------------------------------------------------------------- # # Test out signals and expect_log() # clear() a_logger.clear_log() insert(0, 0, "1 + 1") a_logger.expect_log([CD(), CI(0,1)]) calculate() a_logger.expect_log([CSC(0,1), CRC(0,1)]) insert(0, 0, "#") a_logger.expect_log([CD(), CI(0,1)]) # Deleting a chunk with results clear() insert(0, 0, "1\n2") calculate() expect([S(0,1),S(1,2)]) expect_results([['1'],['2']]) a_logger.clear_log() delete(0, 0, 0, 1) expect([B(0,1),S(1,2)]) a_logger.expect_log([CD(), CI(0,1), CSC(1,2)]) # change a statement into a comment clear() insert(0, 0, "# a\nb") a_logger.clear_log() insert(1, 0, "#") expect([C(0,2)]) a_logger.expect_log([CD(), CC(0,2,[1])]) # Turning a statement into a continuation line clear() insert(0, 0, "1 \\\n+ 2\n") a_logger.clear_log() insert(1, 0, " ") expect([S(0,2), B(2,3)]) a_logger.expect_log([CD(), CC(0,2,[1])]) # And back delete(1, 0, 1, 1) expect([S(0,1), S(1,2), B(2,3)]) a_logger.expect_log([CC(0,1,[]),CI(1,2)]) # Shortening the last chunk in the buffer clear() insert(0, 0, "def a():\n x = 1\n return 1") delete(1, 0, 2, 0) expect([S(0, 2)]) # Inserting a statement above a continuation line at the start of the buffer clear() insert(0, 0, "#def a(x):\n return x") delete(0, 0, 0, 1) expect([S(0,2)]) # Deleting an entire continuation line clear() insert(0, 0, "for i in (1,2):\n print i\n print i + 1\n") expect([S(0,3), B(3,4)]) delete(1, 0, 2, 0) expect([S(0,2), B(2,3)]) # Editing a continuation line, while leaving it a continuation clear() insert(0, 0, "1\\\n + 2\\\n + 3") delete(1, 0, 1, 1) expect([S(0,3)]) # Test that changes that substitute text with identical # text counts as changes # New text clear() insert(0, 0, "if") a_logger.clear_log() worksheet.begin_user_action() delete(0, 1, 0, 2) insert(0, 1, "f") worksheet.end_user_action() expect([S(0,1)]) a_logger.expect_log([CC(0,1,[0])]) # Text from elsewhere in the buffer clear() insert(0, 0, "if\nif") a_logger.clear_log() delete(0, 1, 1, 1) expect([S(0,1)]) a_logger.expect_log([CD(), CC(0,1,[0])]) # Test that commenting out a line marks subsequent lines for recalculation clear() insert(0, 0, "a = 1\na = 2\na") calculate() insert(1, 0, "#") assert worksheet.get_chunk(2).needs_execute # Test that we don't send out '::sig_chunk_deleted' signal for chunks for # which we never sent a '::sig_chunk_inserted' signal clear() insert(0, 0, "[1]") a_logger.clear_log() worksheet.begin_user_action() insert(0, 2, "\n") worksheet.rescan() insert(1, 0, " ") worksheet.end_user_action() a_logger.expect_log([CC(0,2,[0,1])]) # # Undo tests # clear() insert(0, 0, "1") worksheet.undo() expect_text("") worksheet.redo() expect_text("1") # Undoing insertion of a newline clear() insert(0, 0, "1 ") insert(0, 1, "\n") calculate() worksheet.undo() expect_text("1 ") # Test the "pruning" behavior of modifications after undos clear() insert(0, 0, "1") worksheet.undo() expect_text("") insert(0, 0, "2") worksheet.redo() # does nothing expect_text("2") insert(0, 0, "2\n") # Test coalescing consecutive inserts clear() insert(0, 0, "1") insert(0, 1, "2") worksheet.undo() expect_text("") # Test grouping of multiple undos by user actions clear() insert(0, 0, "1") worksheet.begin_user_action() delete(0, 0, 0, 1) insert(0, 0, "2") worksheet.end_user_action() worksheet.undo() expect_text("1") worksheet.redo() expect_text("2") # Make sure that coalescing doesn't coalesce one user action with # only part of another clear() insert(0, 0, "1") worksheet.begin_user_action() insert(0, 1, "2") delete(0, 0, 0, 1) worksheet.end_user_action() worksheet.undo() expect_text("1") worksheet.redo() expect_text("2") # # Tests of get_text() # clear() insert(0, 0, "12\n34\n56") expect_text("12\n34\n56", -1, -1, 0, 0) expect_text("2\n34\n5", 0, 1, 2, 1) expect_text("", -1, -1, -1, -1) expect_text("1", 0, 0, 0, 1) expect_text("2\n3", 0, 1, 1, 1) expect_text("2\n3", 1, 1, 0, 1) # # Tests of get_doctests() # clear() insert(0, 0, """# A tests of doctests def a(x): return x + 1 a(2) """) calculate() expect_doctests("""# A tests of doctests >>> def a(x): ... return x + 1 >>> a(2) 3 """, 0, 5) expect_doctests(""">>> def a(x): ... return x + 1 """, 2, 2) # # Try writing to a file, and reading it back # import tempfile, os clear() expect([B(0,1)]) SAVE_TEST = """a = 1 a # A comment b = 2""" insert(0, 0, SAVE_TEST) calculate() handle, fname = tempfile.mkstemp(u".rws", u"reinteract_worksheet") os.close(handle) try: worksheet.save(fname) f = open(fname, "r") saved = f.read() f.close() if saved != SAVE_TEST: raise AssertionError("Got '%s', expected '%s'", saved, SAVE_TEST) worksheet.load(fname) calculate() expect_text(SAVE_TEST) expect([S(0,1), S(1,2), C(2,3), B(3,4), S(4,5)]) expect_results([[], ['1'], None, None, []]) finally: os.remove(fname) clear() expect([B(0,1)]) pass
def test_signals_0() : #-------------------------------------------------------------------------------------- from test_utils import adjust_environment global_settings = adjust_environment() from reinteract.signals import Signal #-------------------------------------------------------------------------------------- class Button: def __init__(self): # Creating a signal as a member of a class self.sigClick = Signal() pass pass #-------------------------------------------------------------------------------------- class Listener: LOGGER = [] def onClick( self ) : Listener.LOGGER.append( "onClick " ) pass def __call__( self ) : self.onClick() pass pass #-------------------------------------------------------------------------------------- # a sample function to connect to the signal def listenFunction(): listenFunction.LOGGER.append( "listenFunction" ) pass listenFunction.LOGGER = [] #-------------------------------------------------------------------------------------- # a function that accepts arguments def listenWithArgs(text): listenWithArgs.LOGGER.append( text ) pass listenWithArgs.LOGGER = [] #-------------------------------------------------------------------------------------- def reset_logs() : del Listener.LOGGER[ : ] del listenFunction.LOGGER[ : ] del listenWithArgs.LOGGER[ : ] pass #-------------------------------------------------------------------------------------- def count() : return \ len( Listener.LOGGER ) + \ len( listenFunction.LOGGER ) + \ len( listenWithArgs.LOGGER ) #-------------------------------------------------------------------------------------- b = Button() l = Listener() #-------------------------------------------------------------------------------------- # Demonstrating connecting and calling signals b.sigClick.connect( l.onClick ) reset_logs() b.sigClick() assert len( Listener.LOGGER ) == 1 #-------------------------------------------------------------------------------------- # Disconnecting all signals b.sigClick.disconnectAll() reset_logs() b.sigClick() assert len( Listener.LOGGER ) == 0 #-------------------------------------------------------------------------------------- # connecting multiple functions to a signal l2 = Listener() b.sigClick.connect( l.onClick ) b.sigClick.connect( l2.onClick ) reset_logs() b.sigClick() assert len( Listener.LOGGER ) == 2 #-------------------------------------------------------------------------------------- # disconnecting individual functions b.sigClick.disconnect( l.onClick ) b.sigClick.connect( listenFunction ) reset_logs() b.sigClick() assert len( Listener.LOGGER ) == 1 assert len( listenFunction.LOGGER ) == 1 #-------------------------------------------------------------------------------------- # example with arguments and a local signal sig = Signal() sig.connect( listenWithArgs ) reset_logs() sig( "Hello, World!" ) assert len( listenWithArgs.LOGGER ) == 1 #-------------------------------------------------------------------------------------- # signals disconnecting 'method slots' automatically b.sigClick.disconnectAll() b.sigClick.connect( l.onClick ) b.sigClick.connect( l2.onClick ) del l2 reset_logs() b.sigClick() assert len( Listener.LOGGER ) == 1 #-------------------------------------------------------------------------------------- # signals disconnecting 'object slots' automatically b.sigClick.disconnectAll() b.sigClick.connect( l ) del l reset_logs() b.sigClick() assert len( Listener.LOGGER ) == 0 #-------------------------------------------------------------------------------------- # signals disconnecting 'lambda slots' automatically sig = Signal() sig.connect( lambda *args : listenFunction() ) reset_logs() sig( "Hello, World!" ) assert len( listenFunction.LOGGER ) == 1 #-------------------------------------------------------------------------------------- pass
def test_notebook_0(): #-------------------------------------------------------------------------------------- from test_utils import adjust_environment, assert_equals adjust_environment() from reinteract.notebook import Notebook import copy import os, sys import tempfile import zipfile #-------------------------------------------------------------------------------------- base = tempfile.mkdtemp("", u"shell_buffer") def cleanup(): for root, dirs, files in os.walk(base, topdown=False): for name in files: os.remove(os.path.join(root, name)) for name in dirs: os.rmdir(os.path.join(root, name)) def cleanup_pyc(): # Not absolutely necessary, but makes things less confusing if we do # this between tests for root, dirs, files in os.walk(base, topdown=False): for name in files: if name.endswith(".pyc"): os.remove(os.path.join(root, name)) def write_file(name, contents): absname = os.path.join(base, name) dirname = os.path.dirname(absname) try: os.makedirs(dirname) except: pass f = open(absname, "w") f.write(contents) f.close() def write_zipfile(zippath, name, contents): abspath = os.path.join(base, zippath) dirpath = os.path.dirname(abspath) try: os.makedirs(dirpath) except: pass if os.path.exists(abspath): zip = zipfile.ZipFile(abspath, "a") else: zip = zipfile.ZipFile(abspath, "w") zip.writestr(name, contents) zip.close() def do_test(import_text, evaluate_text, expected, nb=None): if nb is None: nb = Notebook(base) scope = {} nb.setup_globals(scope) exec import_text in scope result = eval(evaluate_text, scope) assert_equals(result, expected) cleanup_pyc() try: write_file("mod1.py", "a = 1") write_file("package1/__init__.py", "import os\n__all__ = ['mod2']") write_file("package1/mod2.py", "b = 2") write_file("package1/mod8.py", "import os\nimport mod2\nf = mod2.b + 1") write_file( "package1/mod9.py", "from __future__ import absolute_import\nfrom . import mod2\ng = mod2.b + 2" ) write_file("package2/__init__.py", "") write_file("package2/mod3.py", "import package1.mod2\nc = package1.mod2.b + 1") write_file("mod10.py", "def __reinteract_wrap__(obj): return 2") write_file("mod11.py", "def __reinteract_wrap__(obj): return 3") sys.path.append(os.path.join(base, "ZippedModules.zip")) write_zipfile("ZippedModules.zip", "zipmod.py", "d = 4") write_zipfile("ZippedModules.zip", "zippackage/__init__.py", "") write_zipfile("ZippedModules.zip", "zippackage/mod2.py", "e = 5") do_test("import mod1", "mod1.__file__", os.path.join(base, "mod1.py")) do_test("import mod1", "mod1.a", 1) do_test("import mod1 as m", "m.a", 1) do_test("from mod1 import a", "a", 1) do_test("from mod1 import a as a2", "a2", 1) do_test("import package1.mod2", "package1.mod2.b", 2) do_test("import package1.mod2 as m", "m.b", 2) do_test("from package1 import mod2", "mod2.b", 2) do_test("from package1 import *", "mod2.b", 2) do_test("import package1.mod8", "package1.mod8.f", 3) do_test("import package1.mod9", "package1.mod9.g", 4) # Test loading the same local module a second time in the same notebook nb = Notebook(base) do_test("import package1.mod2", "package1.mod2.b", 2, nb=nb) do_test("import package1.mod2", "package1.mod2.b", 2, nb=nb) # http://www.reinteract.org/trac/ticket/5 do_test("import package2.mod3", "package2.mod3.c", 3) do_test("import zipmod", "zipmod.d", 4) do_test("import zippackage.mod2", "zippackage.mod2.e", 5) # Simple test of __reinteract_wrap__; last has highest priority do_test("import mod10\nimport mod11", "__reinteract_wrappers[0](1)", 3) do_test("import mod10\nimport mod11", "__reinteract_wrappers[1](1)", 2) # Test changing file contents and reloading the module nb = Notebook(base) write_file("mod4.py", "a = 1") do_test("import mod4", "mod4.a", 1, nb=nb) write_file("mod4.py", "a = 2") nb.reset_module_by_filename(os.path.join(base, "mod4.py")) do_test("import mod4", "mod4.a", 2, nb=nb) # Test recovering from a syntax error nb = Notebook(base) write_file("mod4.py", "= 1") try: do_test("import mod4", "mod4.a", 1, nb=nb) except SyntaxError, e: pass write_file("mod4.py", "a = 1") nb.reset_module_by_filename(os.path.join(base, "mod4.py")) do_test("import mod4", "mod4.a", 1, nb=nb) # Test recovering from a runtime error during import nb = Notebook(base) write_file("mod5.py", "a = b") try: do_test("import mod5", "mod5.a", 1, nb=nb) except NameError, e: pass
def test_shell_buffer() : #-------------------------------------------------------------------------------------- from test_utils import adjust_environment adjust_environment() # The tests we include here are tests of the interaction of editing # with results. Results don't appear inline in a Worksheet, so these # tests have to be here rather than with Worksheet. Almost all other # testing is done in Worksheet. from reinteract.shell_buffer import ShellBuffer, ADJUST_NONE, _forward_line from reinteract.chunks import StatementChunk, BlankChunk, CommentChunk from reinteract.notebook import Notebook from reinteract import reunicode import sys from StringIO import StringIO buf = ShellBuffer(Notebook()) def insert(line, offset, text): i = buf.get_iter_at_line_offset(line, offset) buf.insert_interactive(i, text, True) def delete(start_line, start_offset, end_line, end_offset): i = buf.get_iter_at_line_offset(start_line, start_offset) j = buf.get_iter_at_line_offset(end_line, end_offset) buf.delete_interactive(i, j, True) def calculate(): buf.worksheet.calculate(True) def clear(): buf.worksheet.clear() def expect(expected): si = StringIO() i = buf.get_start_iter() while True: end = i.copy() if not end.ends_line(): end.forward_to_line_end() text = reunicode.decode(buf.get_slice(i, end)) line, _ = buf.iter_to_pos(i, adjust=ADJUST_NONE) if line is not None: chunk = buf.worksheet.get_chunk(line) else: chunk = None if chunk and isinstance(chunk, StatementChunk): if line == chunk.start: si.write(">>> ") else: si.write("... ") si.write(text) if _forward_line(i): si.write("\n") else: break result = si.getvalue() if not result == expected: raise AssertionError("\nGot:\n%s\nExpected:\n%s" % (result, expected)) # Calculation resulting in result chunks insert(0, 0, "1 \\\n + 2\n3\n") calculate() expect(""">>> 1 \\ ... + 2 3 >>> 3 3 """) # Check that splitting a statement with a delete results in the # result chunk being moved to the last line of the first half delete(1, 0, 1, 1) expect(""">>> 1 \\ 3 >>> + 2 >>> 3 3 """) # Editing a line with an existing error chunk to fix the error clear() insert(0, 0, "a\na = 2") calculate() insert(0, 0, "2") delete(0, 1, 0, 2) calculate() expect(""">>> 2 2 >>> a = 2""") # Test an attempt to join a ResultChunk onto a previous chunk; should join # the line with the following line, moving the result chunk clear() insert(0, 0, "1\n"); calculate() expect(""">>> 1 1 """) delete(0, 1, 1, 0) expect(""">>> 1 1""") # Test an attempt to join a chunk onto a previous ResultChunk, should move # the ResultChunk and do the modification clear() expect("") insert(0, 0, "1\n2\n"); calculate() expect(""">>> 1 1 >>> 2 2 """) delete(1, 1, 2, 0) expect(""">>> 12 1 """) # Test inserting random text inside a result chunk, should ignore clear() insert(0, 0, "1\n2"); calculate() expect(""">>> 1 1 >>> 2 2""") insert(1, 0, "foo") expect(""">>> 1 1 >>> 2 2""") # Calculation resulting in a multi-line result change clear() insert(0, 0, "for i in range(0, 3): print i") calculate() expect(""">>> for i in range(0, 3): print i 0 1 2""") # Test deleting a range containing both results and statements clear() insert(0, 0, "1\n2\n3\n4\n") calculate() expect(""">>> 1 1 >>> 2 2 >>> 3 3 >>> 4 4 """) delete(2, 0, 5, 0) expect(""">>> 1 1 >>> 4 4 """) # Inserting an entire new statement in the middle insert(2, 0, "2.5\n") expect(""">>> 1 1 >>> 2.5 >>> 4 4 """) calculate() expect(""">>> 1 1 >>> 2.5 2.5 >>> 4 4 """) # Check that inserting a blank line at the beginning of a statement leaves # the result behind insert(2, 0, "\n") expect(""">>> 1 1 >>> 2.5 2.5 >>> 4 4 """) # Test deleting a range including a result and joining two statements clear() insert(0, 0, "12\n34") calculate() expect(""">>> 12 12 >>> 34 34""") delete(0, 1, 2, 1) expect(""">>> 14 12""") # Test a deletion that splits the buffer into two (invalid) pieces clear() insert(0, 0, "try:\n a = 1\nfinally:\n print 'Done'") calculate() expect(""">>> try: ... a = 1 ... finally: ... print 'Done' Done""") delete(2, 7, 2, 8) calculate() expect(""">>> try: ... a = 1 invalid syntax >>> finally ... print 'Done' invalid syntax""") # Try an insertion that combines the two pieces and makes them valid # again (combining across the error result chunk) insert(3, 7, ":") calculate() expect(""">>> try: ... a = 1 ... finally: ... print 'Done' Done""") # Test an undo of an insert that caused insertion of result chunks clear() insert(0, 0, "2\n") expect(""">>> 2 """) calculate() expect(""">>> 2 2 """) insert(0, 0, "1\n") calculate() buf.worksheet.undo() expect(""">>> 2 2 """) # Test insertion of WarningResult clear() insert(0, 0, """class A(object): def __copy__(self): raise RuntimeError("Can't copy") def __repr__(a): return 'A()' def foo(x): return x a = A() a.foo()""") calculate() expect(""">>> class A(object): ... def __copy__(self): raise RuntimeError("Can't copy") ... def __repr__(a): return 'A()' ... def foo(x): return x >>> a = A() >>> a.foo() 'a' apparently modified, but can't copy it A()""")
def test_signals_0(): #-------------------------------------------------------------------------------------- from test_utils import adjust_environment global_settings = adjust_environment() from reinteract.signals import Signal #-------------------------------------------------------------------------------------- class Button: def __init__(self): # Creating a signal as a member of a class self.sigClick = Signal() pass pass #-------------------------------------------------------------------------------------- class Listener: LOGGER = [] def onClick(self): Listener.LOGGER.append("onClick ") pass def __call__(self): self.onClick() pass pass #-------------------------------------------------------------------------------------- # a sample function to connect to the signal def listenFunction(): listenFunction.LOGGER.append("listenFunction") pass listenFunction.LOGGER = [] #-------------------------------------------------------------------------------------- # a function that accepts arguments def listenWithArgs(text): listenWithArgs.LOGGER.append(text) pass listenWithArgs.LOGGER = [] #-------------------------------------------------------------------------------------- def reset_logs(): del Listener.LOGGER[:] del listenFunction.LOGGER[:] del listenWithArgs.LOGGER[:] pass #-------------------------------------------------------------------------------------- def count(): return \ len( Listener.LOGGER ) + \ len( listenFunction.LOGGER ) + \ len( listenWithArgs.LOGGER ) #-------------------------------------------------------------------------------------- b = Button() l = Listener() #-------------------------------------------------------------------------------------- # Demonstrating connecting and calling signals b.sigClick.connect(l.onClick) reset_logs() b.sigClick() assert len(Listener.LOGGER) == 1 #-------------------------------------------------------------------------------------- # Disconnecting all signals b.sigClick.disconnectAll() reset_logs() b.sigClick() assert len(Listener.LOGGER) == 0 #-------------------------------------------------------------------------------------- # connecting multiple functions to a signal l2 = Listener() b.sigClick.connect(l.onClick) b.sigClick.connect(l2.onClick) reset_logs() b.sigClick() assert len(Listener.LOGGER) == 2 #-------------------------------------------------------------------------------------- # disconnecting individual functions b.sigClick.disconnect(l.onClick) b.sigClick.connect(listenFunction) reset_logs() b.sigClick() assert len(Listener.LOGGER) == 1 assert len(listenFunction.LOGGER) == 1 #-------------------------------------------------------------------------------------- # example with arguments and a local signal sig = Signal() sig.connect(listenWithArgs) reset_logs() sig("Hello, World!") assert len(listenWithArgs.LOGGER) == 1 #-------------------------------------------------------------------------------------- # signals disconnecting 'method slots' automatically b.sigClick.disconnectAll() b.sigClick.connect(l.onClick) b.sigClick.connect(l2.onClick) del l2 reset_logs() b.sigClick() assert len(Listener.LOGGER) == 1 #-------------------------------------------------------------------------------------- # signals disconnecting 'object slots' automatically b.sigClick.disconnectAll() b.sigClick.connect(l) del l reset_logs() b.sigClick() assert len(Listener.LOGGER) == 0 #-------------------------------------------------------------------------------------- # signals disconnecting 'lambda slots' automatically sig = Signal() sig.connect(lambda *args: listenFunction()) reset_logs() sig("Hello, World!") assert len(listenFunction.LOGGER) == 1 #-------------------------------------------------------------------------------------- pass
def test_notebook_0(): #-------------------------------------------------------------------------------------- from test_utils import adjust_environment, assert_equals adjust_environment() from reinteract.notebook import Notebook import copy import os, sys import tempfile import zipfile #-------------------------------------------------------------------------------------- base = tempfile.mkdtemp("", u"shell_buffer") def cleanup(): for root, dirs, files in os.walk(base, topdown=False): for name in files: os.remove(os.path.join(root, name)) for name in dirs: os.rmdir(os.path.join(root, name)) def cleanup_pyc(): # Not absolutely necessary, but makes things less confusing if we do # this between tests for root, dirs, files in os.walk(base, topdown=False): for name in files: if name.endswith(".pyc"): os.remove(os.path.join(root, name)) def write_file(name, contents): absname = os.path.join(base, name) dirname = os.path.dirname(absname) try: os.makedirs(dirname) except: pass f = open(absname, "w") f.write(contents) f.close() def write_zipfile(zippath, name, contents): abspath = os.path.join(base, zippath) dirpath = os.path.dirname(abspath) try: os.makedirs(dirpath) except: pass if os.path.exists(abspath): zip = zipfile.ZipFile(abspath, "a") else: zip = zipfile.ZipFile(abspath, "w") zip.writestr(name, contents) zip.close() def do_test(import_text, evaluate_text, expected, nb=None): if nb is None: nb = Notebook(base) scope = {} nb.setup_globals(scope) exec import_text in scope result = eval(evaluate_text, scope) assert_equals(result, expected) cleanup_pyc() try: write_file("mod1.py", "a = 1") write_file("package1/__init__.py", "import os\n__all__ = ['mod2']") write_file("package1/mod2.py", "b = 2") write_file("package1/mod8.py", "import os\nimport mod2\nf = mod2.b + 1") write_file("package1/mod9.py", "from __future__ import absolute_import\nfrom . import mod2\ng = mod2.b + 2") write_file("package2/__init__.py", "") write_file("package2/mod3.py", "import package1.mod2\nc = package1.mod2.b + 1") write_file("mod10.py", "def __reinteract_wrap__(obj): return 2") write_file("mod11.py", "def __reinteract_wrap__(obj): return 3") sys.path.append(os.path.join(base, "ZippedModules.zip")) write_zipfile("ZippedModules.zip", "zipmod.py", "d = 4"); write_zipfile("ZippedModules.zip", "zippackage/__init__.py", ""); write_zipfile("ZippedModules.zip", "zippackage/mod2.py", "e = 5"); do_test("import mod1", "mod1.__file__", os.path.join(base, "mod1.py")) do_test("import mod1", "mod1.a", 1) do_test("import mod1 as m", "m.a", 1) do_test("from mod1 import a", "a", 1) do_test("from mod1 import a as a2", "a2", 1) do_test("import package1.mod2", "package1.mod2.b", 2) do_test("import package1.mod2 as m", "m.b", 2) do_test("from package1 import mod2", "mod2.b", 2) do_test("from package1 import *", "mod2.b", 2) do_test("import package1.mod8", "package1.mod8.f", 3); do_test("import package1.mod9", "package1.mod9.g", 4); # Test loading the same local module a second time in the same notebook nb = Notebook(base) do_test("import package1.mod2", "package1.mod2.b", 2, nb=nb) do_test("import package1.mod2", "package1.mod2.b", 2, nb=nb) # http://www.reinteract.org/trac/ticket/5 do_test("import package2.mod3", "package2.mod3.c", 3) do_test("import zipmod", "zipmod.d", 4) do_test("import zippackage.mod2", "zippackage.mod2.e", 5) # Simple test of __reinteract_wrap__; last has highest priority do_test("import mod10\nimport mod11", "__reinteract_wrappers[0](1)", 3) do_test("import mod10\nimport mod11", "__reinteract_wrappers[1](1)", 2) # Test changing file contents and reloading the module nb = Notebook(base) write_file("mod4.py", "a = 1") do_test("import mod4", "mod4.a", 1, nb=nb) write_file("mod4.py", "a = 2") nb.reset_module_by_filename(os.path.join(base, "mod4.py")) do_test("import mod4", "mod4.a", 2, nb=nb) # Test recovering from a syntax error nb = Notebook(base) write_file("mod4.py", "= 1") try: do_test("import mod4", "mod4.a", 1, nb=nb) except SyntaxError, e: pass write_file("mod4.py", "a = 1") nb.reset_module_by_filename(os.path.join(base, "mod4.py")) do_test("import mod4", "mod4.a", 1, nb=nb) # Test recovering from a runtime error during import nb = Notebook(base) write_file("mod5.py", "a = b") try: do_test("import mod5", "mod5.a", 1, nb=nb) except NameError, e: pass
#!/usr/bin/env python ######################################################################## # # Copyright 2007-2009 Owen Taylor # Copyright 2008 Kai Willadsen # # This file is part of Reinteract and distributed under the terms # of the BSD license. See the file COPYING in the Reinteract # distribution for full details. # ######################################################################## #-------------------------------------------------------------------------------------- if __name__ == "__main__": #-------------------------------------------------------------------------------------- from test_utils import adjust_environment adjust_environment() from reinteract.main import main main() #-------------------------------------------------------------------------------------- pass #--------------------------------------------------------------------------------------
def test_statement_0(): from test_utils import assert_equals, adjust_environment adjust_environment() from reinteract.statement import Statement from reinteract.notebook import Notebook nb = Notebook() from reinteract.worksheet import Worksheet worksheet = Worksheet(nb) def expect_result(text, result): s = Statement(text, worksheet) s.compile() s.execute() if s.error_message != None : raise Exception(s.error_message) if isinstance(result, basestring): assert_equals(s.results[0], result) else: assert_equals(s.results, result) pass pass # A bare expression should give the repr of the expression expect_result("'a'", repr('a')) expect_result("1,2", repr((1,2))) # Print, on the other hand, gives the string form of the expression, with # one result object per output line expect_result("print 'a'", 'a') expect_result("print 'a', 'b'", ['a b']) expect_result("print 'a\\nb'", ['a','b']) # Test that we copy a variable before mutating it (when we can detect # the mutation) s1 = Statement("b = [0]", worksheet) s1.compile() s1.execute() s2 = Statement("b[0] = 1", worksheet, parent=s1) s2.compile() s2.execute() s3 = Statement("b[0]", worksheet, parent=s2) s3.compile() s3.execute() assert_equals(s3.results[0], "1") s2a = Statement("b[0]", worksheet, parent=s1) s2a.compile() s2a.execute() assert_equals(s2a.results[0], "0") # Test __reinteract_wrappers with an unrealistic example s1 = Statement("__reinteract_wrappers = [ lambda x: 2 ]", worksheet) s1.compile() s1.execute() s2 = Statement("1", worksheet, parent=s1) s2.compile() s2.execute() assert_equals(s2.results[0], "2") # Tests of catching errors s1 = Statement("b = ", worksheet) assert_equals(s1.compile(), False) assert s1.error_message is not None s1 = Statement("b", worksheet) assert_equals(s1.compile(), True) assert_equals(s1.execute(), False) assert s1.error_message is not None # Tests of 'from __future__ import...' s1 = Statement("from __future__ import division", worksheet) s1.compile() assert_equals(s1.future_features, ['division']) s2 = Statement("from __future__ import with_statement", worksheet, parent=s1) s2.compile() assert_equals(s2.future_features, ['division', 'with_statement']) s1 = Statement("import __future__", worksheet) # just a normal import assert_equals(s1.future_features, None) # Advanced use of "context manager" protocol expect_result('from reinteract.statement import Statement; Statement.get_current() != None', repr(True)) #-------------------------------------------------------------------------------------- pass
def test_shell_buffer(): #-------------------------------------------------------------------------------------- from test_utils import adjust_environment adjust_environment() # The tests we include here are tests of the interaction of editing # with results. Results don't appear inline in a Worksheet, so these # tests have to be here rather than with Worksheet. Almost all other # testing is done in Worksheet. from reinteract.shell_buffer import ShellBuffer, ADJUST_NONE, _forward_line from reinteract.chunks import StatementChunk, BlankChunk, CommentChunk from reinteract.notebook import Notebook from reinteract import reunicode import sys from StringIO import StringIO buf = ShellBuffer(Notebook()) def insert(line, offset, text): i = buf.get_iter_at_line_offset(line, offset) buf.insert_interactive(i, text, True) def delete(start_line, start_offset, end_line, end_offset): i = buf.get_iter_at_line_offset(start_line, start_offset) j = buf.get_iter_at_line_offset(end_line, end_offset) buf.delete_interactive(i, j, True) def calculate(): buf.worksheet.calculate(True) def clear(): buf.worksheet.clear() def expect(expected): si = StringIO() i = buf.get_start_iter() while True: end = i.copy() if not end.ends_line(): end.forward_to_line_end() text = reunicode.decode(buf.get_slice(i, end)) line, _ = buf.iter_to_pos(i, adjust=ADJUST_NONE) if line is not None: chunk = buf.worksheet.get_chunk(line) else: chunk = None if chunk and isinstance(chunk, StatementChunk): if line == chunk.start: si.write(">>> ") else: si.write("... ") si.write(text) if _forward_line(i): si.write("\n") else: break result = si.getvalue() if not result == expected: raise AssertionError("\nGot:\n%s\nExpected:\n%s" % (result, expected)) # Calculation resulting in result chunks insert(0, 0, "1 \\\n + 2\n3\n") calculate() expect(""">>> 1 \\ ... + 2 3 >>> 3 3 """) # Check that splitting a statement with a delete results in the # result chunk being moved to the last line of the first half delete(1, 0, 1, 1) expect(""">>> 1 \\ 3 >>> + 2 >>> 3 3 """) # Editing a line with an existing error chunk to fix the error clear() insert(0, 0, "a\na = 2") calculate() insert(0, 0, "2") delete(0, 1, 0, 2) calculate() expect(""">>> 2 2 >>> a = 2""") # Test an attempt to join a ResultChunk onto a previous chunk; should join # the line with the following line, moving the result chunk clear() insert(0, 0, "1\n") calculate() expect(""">>> 1 1 """) delete(0, 1, 1, 0) expect(""">>> 1 1""") # Test an attempt to join a chunk onto a previous ResultChunk, should move # the ResultChunk and do the modification clear() expect("") insert(0, 0, "1\n2\n") calculate() expect(""">>> 1 1 >>> 2 2 """) delete(1, 1, 2, 0) expect(""">>> 12 1 """) # Test inserting random text inside a result chunk, should ignore clear() insert(0, 0, "1\n2") calculate() expect(""">>> 1 1 >>> 2 2""") insert(1, 0, "foo") expect(""">>> 1 1 >>> 2 2""") # Calculation resulting in a multi-line result change clear() insert(0, 0, "for i in range(0, 3): print i") calculate() expect(""">>> for i in range(0, 3): print i 0 1 2""") # Test deleting a range containing both results and statements clear() insert(0, 0, "1\n2\n3\n4\n") calculate() expect(""">>> 1 1 >>> 2 2 >>> 3 3 >>> 4 4 """) delete(2, 0, 5, 0) expect(""">>> 1 1 >>> 4 4 """) # Inserting an entire new statement in the middle insert(2, 0, "2.5\n") expect(""">>> 1 1 >>> 2.5 >>> 4 4 """) calculate() expect(""">>> 1 1 >>> 2.5 2.5 >>> 4 4 """) # Check that inserting a blank line at the beginning of a statement leaves # the result behind insert(2, 0, "\n") expect(""">>> 1 1 >>> 2.5 2.5 >>> 4 4 """) # Test deleting a range including a result and joining two statements clear() insert(0, 0, "12\n34") calculate() expect(""">>> 12 12 >>> 34 34""") delete(0, 1, 2, 1) expect(""">>> 14 12""") # Test a deletion that splits the buffer into two (invalid) pieces clear() insert(0, 0, "try:\n a = 1\nfinally:\n print 'Done'") calculate() expect(""">>> try: ... a = 1 ... finally: ... print 'Done' Done""") delete(2, 7, 2, 8) calculate() expect(""">>> try: ... a = 1 invalid syntax >>> finally ... print 'Done' invalid syntax""") # Try an insertion that combines the two pieces and makes them valid # again (combining across the error result chunk) insert(3, 7, ":") calculate() expect(""">>> try: ... a = 1 ... finally: ... print 'Done' Done""") # Test an undo of an insert that caused insertion of result chunks clear() insert(0, 0, "2\n") expect(""">>> 2 """) calculate() expect(""">>> 2 2 """) insert(0, 0, "1\n") calculate() buf.worksheet.undo() expect(""">>> 2 2 """) # Test insertion of WarningResult clear() insert( 0, 0, """class A(object): def __copy__(self): raise RuntimeError("Can't copy") def __repr__(a): return 'A()' def foo(x): return x a = A() a.foo()""") calculate() expect(""">>> class A(object): ... def __copy__(self): raise RuntimeError("Can't copy") ... def __repr__(a): return 'A()' ... def foo(x): return x >>> a = A() >>> a.foo() 'a' apparently modified, but can't copy it A()""")
def test_rewrite_0(): #-------------------------------------------------------------------------------------- from test_utils import adjust_environment, assert_equals adjust_environment() from reinteract.rewrite import Rewriter, UnsupportedSyntaxError import copy, re def rewrite_and_compile(code, output_func_name=None, future_features=None, print_func_name=None, encoding="utf8"): return Rewriter(code, encoding, future_features).rewrite_and_compile(output_func_name, print_func_name) # # Test that our intercepting of bare expressions to save the output works # def test_output(code, expected): compiled, _ = rewrite_and_compile(code, output_func_name='reinteract_output') test_args = [] def set_test_args(*args): test_args[:] = args class Builder: def __init__(self, arg=None): self.arg = arg def __enter__(self): return self.arg def __exit__(self, exception_type, exception_value, traceback): pass scope = { 'reinteract_output': set_test_args, '__reinteract_builder': Builder } exec compiled in scope if tuple(test_args) != tuple(expected): raise AssertionError("Got '%s', expected '%s'" % (test_args, expected)) test_output('a=3', ()) test_output('1', (1,)) test_output('1,2', (1,2)) test_output('1;2', (2,)) test_output('a=3; a', (3,)) test_output('def x():\n 1\ny = x()', ()) test_output('class X():\n 1\n pass\nx = X()', ()) # # Test our build "keyword" # test_output('build list() as l:\n l.append(1)', ([1],)) test_output('build list():\n pass', ([],)) test_output('build as l:\n l = 42', (42,)) test_output('build:\n pass', (None,)) # # Test that our intercepting of print works # def test_print(code, expected): compiled, _ = rewrite_and_compile(code, print_func_name='reinteract_print') test_args = [] def set_test_args(*args): test_args[:] = args scope = { 'reinteract_print': set_test_args } exec compiled in scope if tuple(test_args) != tuple(expected): raise AssertionError("Got '%s', expected '%s'" % (test_args, expected)) test_print('a=3', ()) test_print('print 1', (1,)) test_print('print 1,2', (1,2)) test_print('print "",', ("",)) test_print('for i in [0]: print i', (0,)) test_print('import sys; print >>sys.stderr, "",', ()) # # Test catching possible mutations of variables # def test_mutated(code, expected, prepare=None, assert_old=None, assert_new=None): compiled, mutated = rewrite_and_compile(code) # # Basic test - check the root and description for the returned list of mutations # mutated_root_desc = sorted(((root, description) for (root, description, _) in mutated)) # Extract the root from a description (just take the first word) def expand_root_desc(description): m = re.match(r"([a-zA-Z_0-9]+)", description) return m.group(1), description expected_root_desc = sorted((expand_root_desc(x) for x in expected)) if tuple(mutated_root_desc) != tuple(expected_root_desc): raise AssertionError("Got '%s', expected '%s'" % (mutated, expected)) # More complex test # # a) create old scope, execute 'prepare' in it # b) copy old scope, execute each copy statement # c) execute the code # c) run assertion checks in old and new scope if prepare: old_scope = { '__copy' : copy.copy } exec prepare in old_scope new_scope = dict(old_scope) for _, _, copy_code in mutated: exec copy_code in new_scope exec compiled in new_scope old_ok = eval(assert_old, old_scope) if not old_ok: raise AssertionError("Old scope assertion '%s' failed" % assert_old) new_ok = eval(assert_new, new_scope) if not new_ok: raise AssertionError("New scope assertion '%s' failed" % assert_new) test_mutated('a[0] = 1', ('a',), 'a = [2]', 'a[0] == 2', 'a[0] == 1') test_mutated('a[0], b[0] = 1, 2', ('a', 'b'), 'a,b = [2],[1]', 'a[0],b[0] == 2,1', 'a[0],b[0] == 1,2') test_mutated('a[0], _ = 1', ('a')) test_mutated('a[0], b[0] = c[0], d[0] = 1, 2', ('a', 'b', 'c', 'd')) test_mutated('a[0][1] = 1', ('a', 'a[...]'), 'a = [[0,2],1]', 'a[0][1] == 2', 'a[0][1] == 1') # This isn't fully right - in the new scope b should be [1], not [] test_mutated('a[0].append(1)', ('a', 'a[...]'), 'b = []; a = [b]', 'b == [] and a == [b]', 'b == [] and a == [[1]]') test_mutated('a += 1', ('a',)) test_mutated('a[0] += 1', ('a', 'a[...]')) prepare = """ class A: def __init__(self): self.b = 1 def addmul(self, x,y): self.b += x * y def get_a(self): return self.a pass a = A() a.a = A() """ test_mutated('a.b = 2', ('a',), prepare, 'a.b == 1', 'a.b == 2') test_mutated('a.b = 2', ('a',), prepare, 'a.b == 1', 'a.b == 2') test_mutated('a.a.b = 2', ('a','a.a'), prepare, 'a.a.b == 1', 'a.a.b == 2') test_mutated('a.a.b += 1', ('a','a.a','a.a.b'), prepare, 'a.a.b == 1', 'a.a.b == 2') test_mutated('a.addmul(1,2)', ('a',), prepare, 'a.b == 1', 'a.b == 3') test_mutated('a.a.addmul(1,2)', ('a', 'a.a'), prepare, 'a.a.b == 1', 'a.a.b == 3') # We exempt some methods as being most likely getters. test_mutated('a.get_a()', ()) test_mutated('a.hasA()', ()) test_mutated('a.isa()', ()) # These don't actually work properly since we don't know to copy a.a # So we just check the descriptions and not the execution # test_mutated('a.get_a().b = 2', ('a.get_a(...)',)) test_mutated('a.get_a().a.b = 2', ('a.get_a(...).a',)) # Tests of skipping mutations when the mutations are actually of # local variables test_mutated('def f(x):\n x[1] = 2\n', ()) test_mutated('def f(y):\n x = [1]\n x[1] = 2\n', ()) test_mutated('def f(x):\n def g(x):\n pass', ()) test_mutated('def f(x):\n import g', ()) test_mutated('def f(x):\n from m import g', ()) test_mutated('def f(x):\n from m import g as h\n h[2] = 3', ()) test_mutated('class X:\n x = [1]\n x[1] = 2\n', ()) test_mutated('def f(x):\n class C:\n pass', ()) test_mutated('def f((x,)):\n x[1] = 2\n', ()) test_mutated('def f(((x,),)):\n x[1] = 2\n', ()) # But these are global mutations test_mutated('class X:\n x[1] = 2\n', ('x')) test_mutated('class X:\n global x\n x[1] = 2\n x = [1]\n', ('x')) # Trying to mutate a global variable inside a function is an error def test_unsupported_syntax(code): caught_exception = False try: rewrite_and_compile(code) except UnsupportedSyntaxError, e: caught_exception = True assert_equals(caught_exception, True)
######################################################################## # # Copyright 2008-2009 Owen Taylor # # This file is part of Reinteract and distributed under the terms # of the BSD license. See the file COPYING in the Reinteract # distribution for full details. # ######################################################################## #-------------------------------------------------------------------------------------- if __name__ == "__main__": #-------------------------------------------------------------------------------------- from test_utils import adjust_environment adjust_environment() from reinteract.notebook import Notebook from reinteract.worksheet_editor import WorksheetEditor an_editor = WorksheetEditor(Notebook()) import gtk window = gtk.Window(gtk.WINDOW_TOPLEVEL) window.set_resizable(True) window.connect("destroy", lambda widget : gtk.main_quit()) window.set_title(__file__) window.set_border_width(0) window.resize(500, 500) window.add(an_editor.widget) window.show()
######################################################################## # # Copyright 2007-2011 Owen Taylor # # This file is part of Reinteract and distributed under the terms # of the BSD license. See the file COPYING in the Reinteract # distribution for full details. # ######################################################################## #-------------------------------------------------------------------------------------- if __name__ == "__main__": #-------------------------------------------------------------------------------------- from test_utils import adjust_environment global_settings = adjust_environment() import os examplesdir = global_settings.examples_dir filename = os.path.join(examplesdir, 'imshow.rws').decode('UTF-8') import gtk window = gtk.Window(gtk.WINDOW_TOPLEVEL) window.set_resizable(True) window.connect("destroy", lambda widget : gtk.main_quit()) window.set_title(__file__) window.set_border_width(0) window.resize(500, 500) vbox = gtk.VBox(False, 0) window.add(vbox)
def test_thread_executor_0() : from test_utils import adjust_environment, assert_equals global_settings = adjust_environment() from reinteract.notebook import Notebook from reinteract.statement import Statement from reinteract.worksheet import Worksheet import threading import time from reinteract.thread_executor import ThreadExecutor, _pthread_kill, eventLoop failed = False notebook = Notebook() worksheet = Worksheet(notebook) def test_execute(statements): executor = ThreadExecutor() loop = executor.event_loop for s, expected_state, expected_results in statements: statement = Statement(s, worksheet) statement._expected_state = expected_state statement._expected_results = expected_results statement._got_executing = False executor.add_statement(statement) def on_statement_executing(executor, statement): if hasattr(statement, '_got_state'): statement._out_of_order = True statement._got_executing = True def on_statement_complete(executor, statement): statement._got_state = statement.state statement._got_results = statement.results statement._out_of_order = False def on_complete(executor): loop.quit() def interrupt(): executor.interrupt() global timed_out timed_out = False def timeout(): global timed_out timed_out = True loop.quit() executor.sig_statement_executing.connect(on_statement_executing) executor.sig_statement_complete.connect(on_statement_complete) executor.sig_complete.connect(on_complete) if executor.compile(): executor.execute() interrupt_source = threading.Timer(0.5, interrupt) interrupt_source.start() timeout_source = threading.Timer(1.0, timeout) timeout_source.start() loop.run() if timed_out: raise AssertionError("Interrupting ThreadExecutor failed") interrupt_source.cancel() timeout_source.cancel() for s in executor.statements: assert_equals(s._got_state, s._expected_state) assert_equals(s._got_results, s._expected_results) if s._out_of_order: raise AssertionError("ThreadExecutor sent 'sig_statement_executing' after 'sig_statement_complete'") if s._expected_state == Statement.INTERRUPTED and not s._got_executing: raise AssertionError("ThreadExecutor did not send 'sig_statement_executing' within timeout") test_execute( [ ("a = 1", Statement.COMPILE_SUCCESS, None), ("a =", Statement.COMPILE_ERROR, None) ]) test_execute( [ ("a = 1", Statement.EXECUTE_SUCCESS, []), ("a", Statement.EXECUTE_SUCCESS, ['1']) ]) test_execute( [ ("a = 1", Statement.EXECUTE_SUCCESS, []), ("b", Statement.EXECUTE_ERROR, None), ("c = 2", Statement.COMPILE_SUCCESS, None) ]) # Test interrupting straight python code test_execute( [ ("y = 1", Statement.EXECUTE_SUCCESS, []), ("for x in xrange(0,100000000):\n y = y * 2\n if y > 100: y = 1", Statement.INTERRUPTED, None), ("z = 1", Statement.COMPILE_SUCCESS, None) ]) # Test interrupting a blocking syscall, if support on this platform if _pthread_kill is not None: test_execute( [ ("import sys", Statement.EXECUTE_SUCCESS, []), ("sys.stdin.readline()", Statement.INTERRUPTED, None), ("z = 1", Statement.COMPILE_SUCCESS, None) ]) pass
def test_thread_executor_0(): from test_utils import adjust_environment, assert_equals global_settings = adjust_environment() from reinteract.notebook import Notebook from reinteract.statement import Statement from reinteract.worksheet import Worksheet import threading import time from reinteract.thread_executor import ThreadExecutor, _pthread_kill, eventLoop failed = False notebook = Notebook() worksheet = Worksheet(notebook) def test_execute(statements): executor = ThreadExecutor() loop = executor.event_loop for s, expected_state, expected_results in statements: statement = Statement(s, worksheet) statement._expected_state = expected_state statement._expected_results = expected_results statement._got_executing = False executor.add_statement(statement) def on_statement_executing(executor, statement): if hasattr(statement, '_got_state'): statement._out_of_order = True statement._got_executing = True def on_statement_complete(executor, statement): statement._got_state = statement.state statement._got_results = statement.results statement._out_of_order = False def on_complete(executor): loop.quit() def interrupt(): executor.interrupt() global timed_out timed_out = False def timeout(): global timed_out timed_out = True loop.quit() executor.sig_statement_executing.connect(on_statement_executing) executor.sig_statement_complete.connect(on_statement_complete) executor.sig_complete.connect(on_complete) if executor.compile(): executor.execute() interrupt_source = threading.Timer(0.5, interrupt) interrupt_source.start() timeout_source = threading.Timer(1.0, timeout) timeout_source.start() loop.run() if timed_out: raise AssertionError("Interrupting ThreadExecutor failed") interrupt_source.cancel() timeout_source.cancel() for s in executor.statements: assert_equals(s._got_state, s._expected_state) assert_equals(s._got_results, s._expected_results) if s._out_of_order: raise AssertionError( "ThreadExecutor sent 'sig_statement_executing' after 'sig_statement_complete'" ) if s._expected_state == Statement.INTERRUPTED and not s._got_executing: raise AssertionError( "ThreadExecutor did not send 'sig_statement_executing' within timeout" ) test_execute([("a = 1", Statement.COMPILE_SUCCESS, None), ("a =", Statement.COMPILE_ERROR, None)]) test_execute([("a = 1", Statement.EXECUTE_SUCCESS, []), ("a", Statement.EXECUTE_SUCCESS, ['1'])]) test_execute([("a = 1", Statement.EXECUTE_SUCCESS, []), ("b", Statement.EXECUTE_ERROR, None), ("c = 2", Statement.COMPILE_SUCCESS, None)]) # Test interrupting straight python code test_execute([ ("y = 1", Statement.EXECUTE_SUCCESS, []), ("for x in xrange(0,100000000):\n y = y * 2\n if y > 100: y = 1", Statement.INTERRUPTED, None), ("z = 1", Statement.COMPILE_SUCCESS, None) ]) # Test interrupting a blocking syscall, if support on this platform if _pthread_kill is not None: test_execute([("import sys", Statement.EXECUTE_SUCCESS, []), ("sys.stdin.readline()", Statement.INTERRUPTED, None), ("z = 1", Statement.COMPILE_SUCCESS, None)]) pass
def test_statement_0(): from test_utils import assert_equals, adjust_environment adjust_environment() from reinteract.statement import Statement from reinteract.notebook import Notebook nb = Notebook() from reinteract.worksheet import Worksheet worksheet = Worksheet(nb) def expect_result(text, result): s = Statement(text, worksheet) s.compile() s.execute() if s.error_message != None: raise Exception(s.error_message) if isinstance(result, basestring): assert_equals(s.results[0], result) else: assert_equals(s.results, result) pass pass # A bare expression should give the repr of the expression expect_result("'a'", repr('a')) expect_result("1,2", repr((1, 2))) # Print, on the other hand, gives the string form of the expression, with # one result object per output line expect_result("print 'a'", 'a') expect_result("print 'a', 'b'", ['a b']) expect_result("print 'a\\nb'", ['a', 'b']) # Test that we copy a variable before mutating it (when we can detect # the mutation) s1 = Statement("b = [0]", worksheet) s1.compile() s1.execute() s2 = Statement("b[0] = 1", worksheet, parent=s1) s2.compile() s2.execute() s3 = Statement("b[0]", worksheet, parent=s2) s3.compile() s3.execute() assert_equals(s3.results[0], "1") s2a = Statement("b[0]", worksheet, parent=s1) s2a.compile() s2a.execute() assert_equals(s2a.results[0], "0") # Test __reinteract_wrappers with an unrealistic example s1 = Statement("__reinteract_wrappers = [ lambda x: 2 ]", worksheet) s1.compile() s1.execute() s2 = Statement("1", worksheet, parent=s1) s2.compile() s2.execute() assert_equals(s2.results[0], "2") # Tests of catching errors s1 = Statement("b = ", worksheet) assert_equals(s1.compile(), False) assert s1.error_message is not None s1 = Statement("b", worksheet) assert_equals(s1.compile(), True) assert_equals(s1.execute(), False) assert s1.error_message is not None # Tests of 'from __future__ import...' s1 = Statement("from __future__ import division", worksheet) s1.compile() assert_equals(s1.future_features, ['division']) s2 = Statement("from __future__ import with_statement", worksheet, parent=s1) s2.compile() assert_equals(s2.future_features, ['division', 'with_statement']) s1 = Statement("import __future__", worksheet) # just a normal import assert_equals(s1.future_features, None) # Advanced use of "context manager" protocol expect_result( 'from reinteract.statement import Statement; Statement.get_current() != None', repr(True)) #-------------------------------------------------------------------------------------- pass