seeing_is_believing 2.1.3 → 2.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 924b2f9837ef55a65692edd1552bb4e28c497e04
4
- data.tar.gz: c527cc92aea505196789779036ff2b9fb3265056
3
+ metadata.gz: 1952064fe97bbd42814728d8562a23f401b11ccc
4
+ data.tar.gz: 41ebff3b5b92e9003ef4e587d25367a610ea45e3
5
5
  SHA512:
6
- metadata.gz: a327a0865eb016d325158d9eb17fb34803634e37b2a0c31037df8385f076b3dbb23627c04498b5c9f5d6f4128efa544afe8c90b802536cb194f0b01bed3e53ad
7
- data.tar.gz: fb8f88092ae5e16ea2ff1ca5f9ee22f7b993062ab8c67f93a4ec02b6ca3a7b0c8876998ee28e6994cbe6affd2af4ac96f6bcdba0fdefa6c2396df3a252542776
6
+ metadata.gz: d40b823e70ff45521c324895cde5d0d76195ef26339ba0dc431d6009ec901bcc1e0e9ad509eb752477a3973035b88667ab6e0ef3ca97e354a2c8c90369a3dc2e
7
+ data.tar.gz: c766a89c201e945347575eed23044fd1635628bfb1b6857bfa4d62bc4641dfe809e15fe91322f7590d344db752e562a533e7d56ce926649befe5e4aa1353b31a
data/.travis.yml CHANGED
@@ -4,3 +4,12 @@ rvm:
4
4
  - 1.9.3
5
5
  - 2.0.0
6
6
  - 2.1.2
7
+ - ruby-head
8
+ - rbx-2
9
+ - jruby-head
10
+
11
+ matrix:
12
+ allow_failures:
13
+ - rvm: ruby-head
14
+ - rvm: jruby-head
15
+ - rvm: rbx-2
data/Readme.md CHANGED
@@ -68,6 +68,7 @@ Editor Integration
68
68
  * [TextMate 2](https://github.com/JoshCheek/text_mate_2-seeing-is_believing)
69
69
  * [vim-ruby-xmpfilter](https://github.com/t9md/vim-ruby-xmpfilter) (has support for `seeing_is_believing`)
70
70
  * [vim-seeing-is-believing](https://github.com/hwartig/vim-seeing-is-believing)
71
+ * [atom-seeing-is-believing](https://github.com/JoshCheek/atom-seeing-is-believing) (prob has best installation instructions)
71
72
 
72
73
  Emacs Integration
73
74
  =================
@@ -561,8 +561,8 @@ Feature: Using flags
561
561
  result = SeeingIsBelieving::Result.new
562
562
  result.record_result(1, /omg/)
563
563
 
564
- require 'yaml'
565
- puts YAML.dump result
564
+ require 'json'
565
+ puts JSON.dump result.to_primitive
566
566
  """
567
567
  When I run "chmod +x fake_ruby"
568
568
  When I run "seeing_is_believing -e 123 --shebang ./fake_ruby"
@@ -287,3 +287,98 @@ Feature:
287
287
  Then stderr includes "1: unterminated string meets end of file"
288
288
  And the exit status is 2
289
289
  And stdout is empty
290
+
291
+ Scenario: A program using system
292
+ Given the file "invoking_system.rb":
293
+ """
294
+ system %(ruby -e '$stdout.puts %(hello)')
295
+ system %(ruby -e '$stderr.puts %(world)')
296
+ """
297
+ When I run "seeing_is_believing invoking_system.rb"
298
+ Then stderr is empty
299
+ And the exit status is 0
300
+ And stdout is:
301
+ """
302
+ system %(ruby -e '$stdout.puts %(hello)') # => true
303
+ system %(ruby -e '$stderr.puts %(world)') # => true
304
+
305
+ # >> hello
306
+
307
+ # !> world
308
+ """
309
+
310
+ Scenario: A program overriding stdout/stderr
311
+ Given the file "black_hole.rb":
312
+ """
313
+ File.open '/dev/null', 'w' do |black_hole|
314
+ STDERR = $stderr = black_hole
315
+ STDOUT = $stdout = black_hole
316
+ puts "You won't see this, it goes into the black hole"
317
+ system %q(ruby -e '$stdout.puts "stdout gets past it b/c of dumb ruby bug"')
318
+ system %q(ruby -e '$stderr.puts "stderr gets past it b/c of dumb ruby bug"')
319
+ end
320
+ """
321
+ When I run "seeing_is_believing black_hole.rb"
322
+ Then stderr is empty
323
+ And the exit status is 0
324
+ And stdout is:
325
+ """
326
+ File.open '/dev/null', 'w' do |black_hole| # => File
327
+ STDERR = $stderr = black_hole # => #<File:/dev/null>
328
+ STDOUT = $stdout = black_hole # => #<File:/dev/null>
329
+ puts "You won't see this, it goes into the black hole" # => nil
330
+ system %q(ruby -e '$stdout.puts "stdout gets past it b/c of dumb ruby bug"') # => true
331
+ system %q(ruby -e '$stderr.puts "stderr gets past it b/c of dumb ruby bug"') # => true
332
+ end # => true
333
+
334
+ # >> stdout gets past it b/c of dumb ruby bug
335
+
336
+ # !> stderr gets past it b/c of dumb ruby bug
337
+ """
338
+
339
+ Scenario: Incorrect wrapping in some programs
340
+ Given the file "incorrect_wrapping.rb":
341
+ """
342
+ a
343
+ class B
344
+ def c
345
+ d = 1
346
+ end
347
+ end
348
+ """
349
+ When I run "seeing_is_believing incorrect_wrapping.rb"
350
+ Then stderr is empty
351
+ And the exit status is 1
352
+ And stdout is:
353
+ """
354
+ a # ~> NameError: undefined local variable or method `a' for main:Object
355
+ class B
356
+ def c
357
+ d = 1
358
+ end
359
+ end
360
+
361
+ # ~> NameError
362
+ # ~> undefined local variable or method `a' for main:Object
363
+ # ~>
364
+ # ~> incorrect_wrapping.rb:1:in `<main>'
365
+ """
366
+
367
+ Scenario: Can deal with hostile environments
368
+ Given the file "bang_object.rb":
369
+ """
370
+ class Object
371
+ def !(a)
372
+ end
373
+ end
374
+ """
375
+ When I run "seeing_is_believing bang_object.rb"
376
+ Then stderr is empty
377
+ And the exit status is 0
378
+ And stdout is:
379
+ """
380
+ class Object
381
+ def !(a)
382
+ end
383
+ end
384
+ """
@@ -8,12 +8,12 @@ end
8
8
 
9
9
 
10
10
  Then 'stdout is exactly:' do |code|
11
- @last_executed.stdout.should == eval_curlies(code)
11
+ expect(@last_executed.stdout).to eq eval_curlies(code)
12
12
  end
13
13
 
14
14
  Then 'stdout is the JSON:' do |json|
15
15
  require 'json'
16
16
  expected = JSON.parse(json)
17
17
  actual = JSON.parse(@last_executed.stdout)
18
- actual.should == expected
18
+ expect(actual).to eq expected
19
19
  end
@@ -52,10 +52,12 @@ class SeeingIsBelieving
52
52
  WrapExpressions.call "#{@program}\n",
53
53
  before_all: "begin; $SiB.number_of_captures = #{number_of_captures_as_str}; ",
54
54
  after_all: ";rescue Exception;"\
55
- "line_number = $!.backtrace.grep(/\#{__FILE__}/).first[/:\\d+/][1..-1].to_i;"\
56
- "$SiB.record_exception line_number, $!;"\
57
- "$SiB.exitstatus = 1;"\
58
- "$SiB.exitstatus = $!.status if $!.kind_of? SystemExit;"\
55
+ "lambda {"\
56
+ "line_number = $!.backtrace.grep(/\#{__FILE__}/).first[/:\\d+/][1..-1].to_i;"\
57
+ "$SiB.record_exception line_number, $!;"\
58
+ "$SiB.exitstatus = 1;"\
59
+ "$SiB.exitstatus = $!.status if $!.kind_of? SystemExit;"\
60
+ "}.call;"\
59
61
  "end",
60
62
  before_each: -> line_number { "$SiB.record_result(#{line_number}, (" },
61
63
  after_each: -> line_number { "))" }
@@ -22,7 +22,7 @@ class SeeingIsBelieving
22
22
  buffer, parser, rewriter = ParserHelpers.initialize_parser code, 'strip_comments'
23
23
  comments = ParserHelpers.comments_from parser, buffer
24
24
 
25
- removed_comments = { result: [], exception: [], stdout: [], stderr: [] }
25
+ removed_comments = { result: [], exception: [], stdout: [], stderr: [] }
26
26
 
27
27
  comments.each do |comment|
28
28
  case comment.text
@@ -1,5 +1,12 @@
1
1
  class SeeingIsBelieving
2
2
  class Binary
3
+ # not sure I like this name, it formats comments that
4
+ # show results e.g. "# => [1, 2, 3]"
5
+ #
6
+ # line_length is the length of the line this comment is being appended to
7
+ #
8
+ # For examples of what the options are, and how they all fit together, see
9
+ # spec/binary/comment_formatter_spec.rb
3
10
  class CommentFormatter
4
11
  def self.call(*args)
5
12
  new(*args).call
@@ -48,7 +55,7 @@ class SeeingIsBelieving
48
55
  end
49
56
 
50
57
  def ellipsify(string)
51
- string.sub(/.{0,3}$/) { |last_chars| last_chars.gsub /./, '.' }
58
+ string.sub(/.{0,3}$/) { |last_chars| '.' * last_chars.size }
52
59
  end
53
60
  end
54
61
  end
@@ -1,6 +1,7 @@
1
1
  require 'seeing_is_believing/binary/commentable_lines'
2
2
 
3
3
  class SeeingIsBelieving
4
+ # spec/binary/comment_lines_spec.rb
4
5
  class Binary
5
6
 
6
7
  # takes a body and a block
@@ -4,6 +4,9 @@ class SeeingIsBelieving
4
4
  class Binary
5
5
 
6
6
  # could possibly be sped up by just reflecting on the tokens instead of the whole ast
7
+ #
8
+ # specs for this class are in spec/binary/comment_lines_spec.rb
9
+ # because it was extracted from that class
7
10
  class CommentableLines
8
11
 
9
12
  include ParserHelpers
@@ -11,7 +11,7 @@
11
11
  # read the wrong file... of course, since we rewrite the file,
12
12
  # its body will be incorrect, anyway.
13
13
 
14
- require 'yaml'
14
+ require 'json'
15
15
  require 'open3'
16
16
  require 'timeout'
17
17
  require 'stringio'
@@ -137,7 +137,7 @@ class SeeingIsBelieving
137
137
  end
138
138
 
139
139
  def deserialize_result
140
- YAML.load stdout
140
+ Result.from_primitive JSON.load stdout
141
141
  end
142
142
 
143
143
  def wrap_error(error)
@@ -2,7 +2,23 @@ class SeeingIsBelieving
2
2
 
3
3
  # We cannot serialize the actual exception because we do not have any guarantee that its class is defined on the SIB side,
4
4
  # so we must use simpler data structures (Strings and arrays)
5
- RecordedException = Struct.new :class_name, :message, :backtrace
5
+ RecordedException = Struct.new :class_name, :message, :backtrace do
6
+ def self.from_primitive(primitive)
7
+ return nil unless primitive
8
+ exception = new
9
+ exception.class_name = primitive['class_name']
10
+ exception.message = primitive['message']
11
+ exception.backtrace = primitive['backtrace']
12
+ exception
13
+ end
14
+
15
+ def to_primitive
16
+ { 'class_name' => class_name,
17
+ 'message' => message,
18
+ 'backtrace' => backtrace,
19
+ }
20
+ end
21
+ end
6
22
 
7
23
  module HasException
8
24
  attr_accessor :exception
@@ -14,6 +14,33 @@ class SeeingIsBelieving
14
14
  end
15
15
  end
16
16
 
17
+ def to_float(n)
18
+ return n unless n == Float::INFINITY
19
+ 'FUCKING_INFINITY_AND_JESUS_FUCKING_CHRIST_JSON_AND_MARSHAL_AND_YAML_WHAT_THE_FUCK?'
20
+ end
21
+
22
+ def from_float(n)
23
+ return n if n.kind_of? Float
24
+ Float::INFINITY
25
+ end
26
+
27
+ def to_primitive
28
+ { 'array' => @array,
29
+ 'max_number_of_captures' => to_float(@max_number_of_captures),
30
+ 'num_results' => @num_results,
31
+ 'total_size' => @total_size,
32
+ 'exception' => (exception && exception.to_primitive)
33
+ }
34
+ end
35
+
36
+ def from_primitive(primitive)
37
+ @array = primitive['array']
38
+ @max_number_of_captures = from_float primitive['max_number_of_captures']
39
+ @num_results = primitive['num_results']
40
+ @total_size = primitive['total_size']
41
+ @exception = RecordedException.from_primitive primitive['exception']
42
+ end
43
+
17
44
  def to_a
18
45
  @array.dup
19
46
  end
@@ -32,6 +59,12 @@ class SeeingIsBelieving
32
59
  inspected = value.inspect.to_str # only invoke inspect once, b/c the inspection may be recorded
33
60
  rescue NoMethodError
34
61
  inspected = "#<no inspect available>"
62
+ rescue SystemStackError
63
+ # this is necessary because SystemStackError won't show the backtrace of the method we tried to call
64
+ # which means there won't be anything showing the user where this came from
65
+ # so we need to re-raise the error to get a backtrace that shows where we came from
66
+ # otherwise it looks like the bug is in SiB and not the user's program, see https://github.com/JoshCheek/seeing_is_believing/issues/37
67
+ raise SystemStackError, "Calling inspect blew the stack (is it recursive w/o a base case?)"
35
68
  end
36
69
 
37
70
  if size < @max_number_of_captures then @array << inspected
@@ -6,6 +6,37 @@ class SeeingIsBelieving
6
6
  include HasException
7
7
  include Enumerable
8
8
 
9
+ def self.from_primitive(primitive)
10
+ new.from_primitive(primitive)
11
+ end
12
+
13
+ def from_primitive(primitive)
14
+ self.exitstatus = primitive['exitstatus']
15
+ self.stdout = primitive['stdout']
16
+ self.stderr = primitive['stderr']
17
+ self.bug_in_sib = primitive['bug_in_sib']
18
+ self.exception = RecordedException.from_primitive primitive['exception']
19
+ primitive['results'].each do |line_number, primitive_line|
20
+ results_for(line_number.to_i).from_primitive(primitive_line)
21
+ end
22
+ self
23
+ end
24
+
25
+ def to_primitive
26
+ primitive = {
27
+ 'exitstatus' => exitstatus,
28
+ 'stdout' => stdout,
29
+ 'stderr' => stderr,
30
+ 'bug_in_sib' => bug_in_sib,
31
+ 'exception' => (exception && exception.to_primitive),
32
+ }
33
+ primitive['results'] = results.each_with_object({}) do |(line_number, line), r|
34
+ r[line_number] = line.to_primitive
35
+ end
36
+ primitive
37
+ end
38
+
39
+
9
40
  attr_accessor :stdout, :stderr, :exitstatus, :bug_in_sib, :number_of_captures
10
41
 
11
42
  alias bug_in_sib? bug_in_sib
@@ -1,24 +1,40 @@
1
1
  # WARNING: DO NOT REQUIRE THIS FILE, IT WILL FUCK YOU UP!!!!!!
2
2
 
3
+ # READ THIS IF YOU WANT TO USE YOUR OWN MATRIX FILE:
4
+ # https://github.com/JoshCheek/seeing_is_believing/issues/24
5
+ #
6
+ # (or if you want to understand why we do the pipe dance)
3
7
 
4
- require 'yaml'
5
- require 'stringio'
6
- real_stdout = STDOUT
7
- real_stderr = STDERR
8
- STDOUT = $stdout = fake_stdout = StringIO.new
9
- STDERR = $stderr = fake_stderr = StringIO.new
10
8
 
9
+ require 'json'
11
10
  require 'seeing_is_believing/result'
12
11
  $SiB = SeeingIsBelieving::Result.new
13
12
 
13
+ stdout_real_obj = STDOUT # the real Ruby object, but its FD is going to keep getting reopened
14
+ stderr_real_obj = STDERR
15
+ stdout_real_fd = STDOUT.dup # duped Ruby object, but with the real file descriptor
16
+ stderr_real_fd = STDERR.dup
17
+
18
+ read_from_mock_out, write_to_mock_out = IO.pipe
19
+ read_from_mock_err, write_to_mock_err = IO.pipe
20
+
21
+ stdout_real_obj.reopen write_to_mock_out
22
+ stderr_real_obj.reopen write_to_mock_err
23
+
14
24
  at_exit do
15
- $SiB.stdout = fake_stdout.string
16
- $SiB.stderr = fake_stderr.string
25
+ stdout_real_obj.reopen stdout_real_fd
26
+ stderr_real_obj.reopen stderr_real_fd
27
+ write_to_mock_out.close unless write_to_mock_out.closed?
28
+ write_to_mock_err.close unless write_to_mock_err.closed?
29
+ $SiB.stdout = read_from_mock_out.read
30
+ $SiB.stderr = read_from_mock_err.read
31
+ read_from_mock_out.close
32
+ read_from_mock_err.close
17
33
 
18
34
  $SiB.exitstatus ||= 0
19
35
  $SiB.exitstatus = 1 if $!
20
36
  $SiB.exitstatus = $!.status if $!.kind_of? SystemExit
21
37
  $SiB.bug_in_sib = $! && ! $!.kind_of?(SystemExit)
22
38
 
23
- real_stdout.write YAML.dump $SiB
39
+ stdout_real_fd.write JSON.dump $SiB.to_primitive
24
40
  end
@@ -1,3 +1,3 @@
1
1
  class SeeingIsBelieving
2
- VERSION = '2.1.3'
2
+ VERSION = '2.1.4'
3
3
  end
@@ -41,10 +41,7 @@ class SeeingIsBelieving
41
41
  rewriter.insert_after range, after_each.call(line_num)
42
42
  end
43
43
 
44
- # another stupid hack to get around a heredoc at the end of the document
45
- # hopefully we can remove this after next version of Parser is released
46
- last_index, (range, col) = wrappings.max_by(&:first)
47
- range ||= root.location.expression
44
+ range = root.location.expression
48
45
  rewriter.insert_after range, after_all
49
46
  end
50
47
 
@@ -141,16 +138,23 @@ class SeeingIsBelieving
141
138
  add_to_wrappings range
142
139
  add_children ast.children.last
143
140
  end
144
- when :lvasgn, :ivasgn, :gvasgn, :cvasgn, :casgn # local variable, instance variable, global variable, class variable, constant
141
+ when :lvasgn, # a = 1
142
+ :ivasgn, # @a = 1
143
+ :gvasgn, # $a = 1
144
+ :cvasgn, # @@a = 1
145
+ :casgn, # A = 1
146
+ :or_asgn, # a ||= b
147
+ :and_asgn, # a &&= b
148
+ :op_asgn # a += b, a -= b, a *= b, etc
149
+
145
150
  # because the RHS can be a heredoc, and parser currently handles heredocs locations incorrectly
146
151
  # we must hack around this
147
-
148
152
  if ast.children.last.kind_of? ::AST::Node
149
153
  begin_pos = ast.location.expression.begin_pos
150
154
  end_pos = heredoc_hack(ast.children.last).location.expression.end_pos
151
155
  range = Parser::Source::Range.new buffer, begin_pos, end_pos
152
156
  add_to_wrappings range
153
- add_children ast
157
+ add_children ast, true
154
158
  end
155
159
  when :send
156
160
  # because the target and the last child can be heredocs
@@ -160,7 +164,11 @@ class SeeingIsBelieving
160
164
  range = ast.location.expression
161
165
 
162
166
  # first two children: target, message, so we want the last child only if it is an argument
163
- target, message, *, last_arg = ast.children
167
+ children = ast.children
168
+ target = children[0]
169
+ message = children[1]
170
+ last_arg = children.size > 2 ? children[-1] : nil
171
+
164
172
 
165
173
  # last arg is a heredoc, use the closing paren, or the end of the first line of the heredoc
166
174
  if heredoc? last_arg