seeing_is_believing 3.6.0 → 3.6.1

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
- SHA1:
3
- metadata.gz: 2191c3427344ea922d31c319fe5442b7cc548d35
4
- data.tar.gz: c9d3e073bbeb2d093a69ffbea07f287750b42f73
2
+ SHA256:
3
+ metadata.gz: abaf2ec44d75ad4ca500c71bf90128baea06be5c0bd61fef5a0de81a402fef49
4
+ data.tar.gz: b487790b90fb61b27e77fee26622c8210a0b6e435c2084205bb791bcf3e28c08
5
5
  SHA512:
6
- metadata.gz: bbfb8141efc9ca5a3ec5eaaae28588439b593911eb411305843d39d5b42ab0d670386c0934e95d2b709f90e2d5a80133637b7b6e2181ef37387530387b8caa31
7
- data.tar.gz: 37148dff2dd6e2231a1a8be45437f41160e747eef14e52f5df2bb68258ec630ffe2345ea310b47b1b432507cf9253c9c2b7dca26d59d98f0c786df4a55087ad2
6
+ metadata.gz: '03996ee758737b276089eec6037a0c999678097759fc1dac9a1a338eae62327cb5d76253e0c491ae77a7e0852edb104da629e59db1c60228c43076d100ae8215'
7
+ data.tar.gz: 915f7e561d0bcb18f863c068e72305fa445f1b4f5f9d390843478a4ddb662cf8c38af388d5cc8da5f9ddaeeba1e569ad803c5d5c5b913d92bc6642e60155484e
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
1
  desc 'Have Bundler setup a standalone environment -- run tests in this, b/c its faster and safer'
2
2
  task :install do
3
- # Running without rubygems # http://myronmars.to/n/dev-blog/2012/03/faster-test-boot-times-with-bundler-standalone
3
+ # Running without rubygems http://myronmars.to/n/dev-blog/2012/03/faster-test-boot-times-with-bundler-standalone
4
4
  which("bundle") or sh 'gem', 'install', 'bundler', '--no-ri', '--no-rdoc'
5
5
  Dir.exist? 'bundle' or sh 'bundle', 'install', '--standalone', '--binstubs', 'bundle/bin'
6
6
  end
@@ -834,3 +834,84 @@ Feature:
834
834
  Then stdout is "1 # => 1"
835
835
  When I run "seeing_is_believing -e '1;'"
836
836
  Then stdout is "1; # => 1"
837
+
838
+
839
+ Scenario: A spy / proxy class (Issue #136)
840
+ Given the file "spy_class.rb":
841
+ """
842
+ class String
843
+ def self.===(obj)
844
+ true
845
+ end
846
+ end
847
+ class Spy < BasicObject
848
+ def method_missing(name, *args, &block)
849
+ self
850
+ end
851
+ end
852
+ Spy.new # =>
853
+ """
854
+ When I run "seeing_is_believing -x spy_class.rb"
855
+ Then stderr is empty
856
+ And the exit status is 0
857
+ And stdout includes "Spy.new # => #<Spy:"
858
+
859
+
860
+ Scenario: Refined inspect
861
+ Given the file "refined_inspect.rb":
862
+ """
863
+ module Humanize
864
+ refine Float do
865
+ def inspect
866
+ rounded = "%.2f" % self
867
+ rounded.reverse!
868
+ rounded.gsub! /(\d{3})/, '\1,'
869
+ rounded.chomp! ","
870
+ rounded.reverse!
871
+ rounded
872
+ end #
873
+ end
874
+ end
875
+ using Humanize
876
+ 12345.6789 # =>
877
+ """
878
+ When I run "seeing_is_believing refined_inspect.rb"
879
+ Then stderr is empty
880
+ And the exit status is 0
881
+ And stdout is:
882
+ """
883
+ module Humanize
884
+ refine Float do
885
+ def inspect
886
+ rounded = "%.2f" % self # => "12345.68"
887
+ rounded.reverse! # => "86.54321"
888
+ rounded.gsub! /(\d{3})/, '\1,' # => "86.543,21"
889
+ rounded.chomp! "," # => nil
890
+ rounded.reverse! # => "12,345.68"
891
+ rounded # => "12,345.68"
892
+ end #
893
+ end # => #<refinement:Float@Humanize>
894
+ end # => #<refinement:Float@Humanize>
895
+ using Humanize # => main
896
+ 12345.6789 # => 12,345.68
897
+ """
898
+ When I run "seeing_is_believing refined_inspect.rb -x"
899
+ Then stderr is empty
900
+ And the exit status is 0
901
+ Then stdout is:
902
+ """
903
+ module Humanize
904
+ refine Float do
905
+ def inspect
906
+ rounded = "%.2f" % self
907
+ rounded.reverse!
908
+ rounded.gsub! /(\d{3})/, '\1,'
909
+ rounded.chomp! ","
910
+ rounded.reverse!
911
+ rounded
912
+ end #
913
+ end
914
+ end
915
+ using Humanize
916
+ 12345.6789 # => 12,345.68
917
+ """
@@ -7,7 +7,7 @@ require 'seeing_is_believing/code'
7
7
 
8
8
  class SeeingIsBelieving
9
9
  module Binary
10
- # Based on the behaviour of xmpfilger (a binary in the rcodetools gem)
10
+ # Based on the behaviour of xmpfilter (a binary in the rcodetools gem)
11
11
  # See https://github.com/JoshCheek/seeing_is_believing/issues/44 for more details
12
12
  class AnnotateMarkedLines
13
13
  def self.map_markers_to_linenos(program, markers)
@@ -64,7 +64,7 @@ class SeeingIsBelieving
64
64
  # 79 - "# => ".length # => 4
65
65
  # ALSO: This should be configurable, b/c otherwise you have to go into the guts of `pp`
66
66
  # https://gist.github.com/JoshCheek/6472c8f334ae493f4ab1f7865e2470e5
67
- inspect = "))"
67
+ inspect = ")) { |v| v.inspect }"
68
68
  pp = ")) { |v| PP.pp v, '', 74 }"
69
69
 
70
70
  should_inspect = inspect_linenos.include? line_number
@@ -1,3 +1,7 @@
1
+ # Polyfill String#scrub on Ruby 2.0.0
2
+ require 'seeing_is_believing/compatibility'
3
+ using SeeingIsBelieving::Compatibility
4
+
1
5
  class SeeingIsBelieving
2
6
  module Binary
3
7
  # not sure I like this name, it formats comments that show results
@@ -64,12 +68,11 @@ class SeeingIsBelieving
64
68
  end
65
69
 
66
70
  def escape_non_printable(str, omissions)
67
- str.each_char
68
- .map { |char|
69
- next char if 0x20 <= char.ord # above this has a printable representation
70
- next char if omissions.include? char
71
- char.inspect[1...-1]
72
- }.join('')
71
+ str.scrub { |c| c.inspect[1...-1] }
72
+ .gsub(/[\u0000-\u0020]/) { |char|
73
+ next char if omissions.include? char
74
+ char.inspect[1...-1]
75
+ }
73
76
  end
74
77
  end
75
78
  end
@@ -0,0 +1,28 @@
1
+ class SeeingIsBelieving
2
+ module Compatibility
3
+ end
4
+ end
5
+
6
+ # Ruby 2.0.0 is soooooo painful >.<
7
+ # want to stop supporting this so bad!!
8
+ is_v2_0 = !String.instance_methods.include?(:scrub)
9
+
10
+ is_v2_0 && begin
11
+ old_verbose, $VERBOSE = $VERBOSE, nil
12
+ module SeeingIsBelieving::Compatibility
13
+ refine String do
14
+ def scrub(char=nil, &block)
15
+ char && block = lambda { |c| char }
16
+ each_char.inject("") do |new_str, char|
17
+ if char.valid_encoding?
18
+ new_str << char
19
+ else
20
+ new_str << block.call(char)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ ensure
27
+ $VERBOSE = old_verbose
28
+ end
@@ -39,7 +39,7 @@ class SeeingIsBelieving
39
39
  self.timeout_seconds = options.delete(:timeout_seconds) || 0 # 0 is the new infinity
40
40
  self.provided_input = options.delete(:provided_input) || String.new
41
41
  self.event_handler = options.delete(:event_handler) || raise(ArgumentError, "must provide an :event_handler")
42
- self.load_path_flags = (options.delete(:load_path_dirs) || []).map { |dir| ['-I', dir] }.flatten
42
+ self.load_path_flags = (options.delete(:load_path_dirs) || []).flat_map { |dir| ['-I', dir] }
43
43
  self.require_flags = (options.delete(:require_files) || ['seeing_is_believing/the_matrix']).map { |filename| ['-r', filename] }.flatten
44
44
  self.max_line_captures = (options.delete(:max_line_captures) || Float::INFINITY) # (optimization: child stops producing results at this number, even though it might make more sense for the consumer to stop emitting them)
45
45
  self.local_cwd = options.delete(:local_cwd) || false
@@ -4,6 +4,10 @@ require 'seeing_is_believing/event_stream/events'
4
4
  require 'seeing_is_believing/error'
5
5
  require 'thread'
6
6
 
7
+ # Polyfill String#scrub on Ruby 2.0.0
8
+ require 'seeing_is_believing/compatibility'
9
+ using SeeingIsBelieving::Compatibility
10
+
7
11
  class SeeingIsBelieving
8
12
  module EventStream
9
13
  class Consumer
@@ -60,15 +64,7 @@ class SeeingIsBelieving
60
64
  rescue EncodingError
61
65
  str = str.force_encoding(Encoding::UTF_8)
62
66
  end
63
- return str.scrub('�') if str.respond_to? :scrub
64
- # basically reimplement scrub, b/c it's not implemented on 2.0.0
65
- str.each_char.inject("") do |new_str, char|
66
- if char.valid_encoding?
67
- new_str << char
68
- else
69
- new_str << '�'
70
- end
71
- end
67
+ str.scrub('�')
72
68
  end
73
69
 
74
70
  def initialize(streams)
@@ -169,51 +165,51 @@ class SeeingIsBelieving
169
165
  end
170
166
  end
171
167
 
172
- def extract_token(line)
168
+ def shift_token(line)
173
169
  event_name = line[/[^ ]+/]
174
170
  line.sub!(/^\s*[^ ]+\s*/, '')
175
171
  event_name
176
172
  end
177
173
 
178
174
  # For a consideration of many different ways of passing the message, see 5633064
179
- def extract_string(line)
180
- str = Marshal.load extract_token(line).unpack('m0').first
175
+ def shift_string(line)
176
+ str = Marshal.load shift_token(line).unpack('m0').first
181
177
  Consumer.fix_encoding(str)
182
178
  end
183
179
 
184
180
  def event_for(original_line)
185
181
  line = original_line.chomp
186
- event_name = extract_token(line).intern
182
+ event_name = shift_token(line).intern
187
183
  case event_name
188
184
  when :result
189
- line_number = extract_token(line).to_i
190
- type = extract_token(line).intern
191
- inspected = extract_string(line)
185
+ line_number = shift_token(line).to_i
186
+ type = shift_token(line).intern
187
+ inspected = shift_string(line)
192
188
  Events::LineResult.new(type: type, line_number: line_number, inspected: inspected)
193
189
  when :maxed_result
194
- line_number = extract_token(line).to_i
195
- type = extract_token(line).intern
190
+ line_number = shift_token(line).to_i
191
+ type = shift_token(line).intern
196
192
  Events::ResultsTruncated.new(type: type, line_number: line_number)
197
193
  when :exception
198
194
  Events::Exception.new \
199
- line_number: extract_token(line).to_i,
200
- class_name: extract_string(line),
201
- message: extract_string(line),
202
- backtrace: extract_token(line).to_i.times.map { extract_string line }
195
+ line_number: shift_token(line).to_i,
196
+ class_name: shift_string(line),
197
+ message: shift_string(line),
198
+ backtrace: shift_token(line).to_i.times.map { shift_string line }
203
199
  when :max_line_captures
204
- token = extract_token(line)
200
+ token = shift_token(line)
205
201
  value = token =~ /infinity/i ? Float::INFINITY : token.to_i
206
202
  Events::MaxLineCaptures.new(value: value)
207
203
  when :num_lines
208
- Events::NumLines.new(value: extract_token(line).to_i)
204
+ Events::NumLines.new(value: shift_token(line).to_i)
209
205
  when :sib_version
210
- Events::SiBVersion.new(value: extract_string(line))
206
+ Events::SiBVersion.new(value: shift_string(line))
211
207
  when :ruby_version
212
- Events::RubyVersion.new(value: extract_string(line))
208
+ Events::RubyVersion.new(value: shift_string(line))
213
209
  when :filename
214
- Events::Filename.new(value: extract_string(line))
210
+ Events::Filename.new(value: shift_string(line))
215
211
  when :exec
216
- Events::Exec.new(args: extract_string(line))
212
+ Events::Exec.new(args: shift_string(line))
217
213
  else
218
214
  raise UnknownEvent, original_line.inspect
219
215
  end
@@ -49,9 +49,13 @@ class SeeingIsBelieving
49
49
  if count < max_line_captures
50
50
  begin
51
51
  if block_given?
52
- inspected = yield(value).to_str
52
+ inspected = yield(value)
53
53
  else
54
- inspected = value.inspect.to_str
54
+ inspected = value.inspect
55
+ end
56
+ unless String === inspected
57
+ inspected = inspected.to_str
58
+ raise unless String === inspected
55
59
  end
56
60
  rescue *StackErrors
57
61
  # this is necessary because SystemStackError won't show the backtrace of the method we tried to call
@@ -76,9 +80,11 @@ class SeeingIsBelieving
76
80
  # records the exception, returns the exitstatus for that exception
77
81
  def record_exception(line_number, exception)
78
82
  return exception.status if SystemExit === exception # TODO === is not in the list
79
- if !line_number && filename
80
- begin line_number = exception.backtrace.grep(/#{filename.to_s}/).first[/:\d+/][1..-1].to_i
81
- rescue NoMethodError
83
+ unless line_number
84
+ if filename
85
+ begin line_number = exception.backtrace.grep(/#{filename.to_s}/).first[/:\d+/][1..-1].to_i
86
+ rescue NoMethodError
87
+ end
82
88
  end
83
89
  end
84
90
  line_number ||= -1
@@ -1,6 +1,13 @@
1
1
  # require this before anything else, b/c it expects the world to be sane when it is loaded
2
2
  class SeeingIsBelieving
3
3
  module Safe
4
+
5
+ # Subclasses must refine before superclasses in older Rubies, otherwise
6
+ # it finds the superclass method and behaves unexpectedly.
7
+ refine String.singleton_class do
8
+ alias === ===
9
+ end
10
+
4
11
  refine Class do
5
12
  alias === ===
6
13
  end
@@ -1,3 +1,3 @@
1
1
  class SeeingIsBelieving
2
- VERSION = '3.6.0'
2
+ VERSION = '3.6.1'
3
3
  end
@@ -9,7 +9,7 @@ class SeeingIsBelieving
9
9
  "$SiB.record_result(:inspect, #{line_number}, ("
10
10
  },
11
11
  after_each: -> line_number {
12
- "))"
12
+ ")) { |v| v.inspect }"
13
13
  }
14
14
  end
15
15
  end
@@ -60,7 +60,10 @@ RSpec.describe SeeingIsBelieving::Binary::FormatComment do
60
60
 
61
61
  def assert_printed(c, printed)
62
62
  c = c.force_encoding 'utf-8'
63
- expect(result_for 0, '', c).to eq printed
63
+ result = result_for 0, '', c
64
+ expect(result).to eq printed
65
+ expect(result.encoding).to eq Encoding::UTF_8
66
+ expect(result).to be_valid_encoding
64
67
  end
65
68
 
66
69
  it 'escapes any non-printable characters' do
@@ -192,6 +195,7 @@ RSpec.describe SeeingIsBelieving::Binary::FormatComment do
192
195
  assert_printed 124.chr , "|"
193
196
  assert_printed 125.chr , "}"
194
197
  assert_printed 126.chr , "~"
198
+ assert_printed 127.chr, "\u007F"
195
199
  end
196
200
 
197
201
  it 'can be given a list of characters to not escape' do
@@ -437,6 +437,13 @@ module SeeingIsBelieving::EventStream
437
437
  end
438
438
  end
439
439
 
440
+ it 'works with objects whose boolean inquiries have been messed with (#131)' do
441
+ exception = begin; raise; rescue; $!; end
442
+ bad_bool = Object.new
443
+ def bad_bool.!(*) raise; end
444
+ producer.record_exception bad_bool, exception # should not explode
445
+ end
446
+
440
447
  context 'recorded line number | line num is provided | it knows the file | exception comes from within file' do
441
448
  let(:exception) { begin; raise "zomg"; rescue; $!; end }
442
449
  let(:linenum) { __LINE__ - 1 }
@@ -531,6 +531,13 @@ RSpec.describe SeeingIsBelieving do
531
531
  expect(result.exception.message).to match /recursive/i
532
532
  end
533
533
 
534
+ it 'does not blow up when returning an object that recursively responds to everything' do
535
+ result = invoke('obj = BasicObject.new
536
+ def obj.method_missing(*) self; end
537
+ obj')
538
+ expect(result[3][0]).to start_with '#<BasicObject:'
539
+ end
540
+
534
541
  it 'does not blow up when the first line looks like it might have a magic comment in it (#126)' do
535
542
  expect(values_for "1+1 # and a comment with 'Accept-Encoding: gzip' in it").to eq [['2']]
536
543
  end
@@ -547,6 +554,25 @@ RSpec.describe SeeingIsBelieving do
547
554
  expect(values_for 'o = BasicObject.new; def o.inspect; "some obj"; end; o').to eq [['some obj']]
548
555
  end
549
556
 
557
+ it 'sees refined inspect (#128)' do
558
+ result = invoke <<-RUBY
559
+ module BinMeUp
560
+ refine Fixnum do
561
+ def inspect
562
+ "%08b" % self
563
+ end
564
+ end
565
+ end
566
+ using BinMeUp
567
+ 5
568
+ RUBY
569
+ expect(result[9]).to eq ['00000101']
570
+ end
571
+
572
+ it 'works when the exception does not have a backtrace (#134)' do
573
+
574
+ end
575
+
550
576
  it 'respects timeout, even when children do semi-ridiculous things, it cleans up children rather than orphaning them' do
551
577
  pre = Time.now
552
578
  result = invoke <<-CHILD, timeout_seconds: 0.5
@@ -783,14 +809,18 @@ RSpec.describe SeeingIsBelieving do
783
809
  end').stderr).to eq ''
784
810
  end
785
811
 
786
- specify 'when String does not have ==, to_s, inspect, to_i' do
812
+ specify 'when String does not have ==, to_s, inspect, to_i, ===' do
787
813
  expect(invoke('class String
788
814
  undef ==
789
815
  undef to_s
790
816
  undef to_str
791
817
  undef inspect
792
818
  undef to_i
793
- end').stderr).to eq ''
819
+ end
820
+ class << String
821
+ undef ===
822
+ end
823
+ ').stderr).to eq ''
794
824
  end
795
825
 
796
826
  specify 'when Fixnum does not have <, <<, next, ==, inspect, to_s' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: seeing_is_believing
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.0
4
+ version: 3.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Cheek
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-29 00:00:00.000000000 Z
11
+ date: 2018-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -189,6 +189,7 @@ files:
189
189
  - lib/seeing_is_believing/binary/remove_annotations.rb
190
190
  - lib/seeing_is_believing/binary/rewrite_comments.rb
191
191
  - lib/seeing_is_believing/code.rb
192
+ - lib/seeing_is_believing/compatibility.rb
192
193
  - lib/seeing_is_believing/customize_pp.rb
193
194
  - lib/seeing_is_believing/debugger.rb
194
195
  - lib/seeing_is_believing/error.rb
@@ -287,7 +288,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
287
288
  version: '0'
288
289
  requirements: []
289
290
  rubyforge_project: seeing_is_believing
290
- rubygems_version: 2.5.2
291
+ rubygems_version: 2.7.6
291
292
  signing_key:
292
293
  specification_version: 4
293
294
  summary: Records results of every line of code in your file