is_a 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +7 -5
- data/Rakefile +20 -64
- data/ext/is_a/is_a.c +25 -7
- data/is_a.gemspec +1 -0
- data/lib/is_a/version.rb +1 -1
- data/spec/is_a_spec.rb +51 -0
- metadata +23 -5
    
        data/README.md
    CHANGED
    
    | @@ -6,7 +6,9 @@ A small library of missing ruby methods for introspection. See Usage. | |
| 6 6 |  | 
| 7 7 | 
             
            Add this line to your application's Gemfile:
         | 
| 8 8 |  | 
| 9 | 
            -
             | 
| 9 | 
            +
            ```ruby
         | 
| 10 | 
            +
            gem 'is_a'
         | 
| 11 | 
            +
            ```
         | 
| 10 12 |  | 
| 11 13 | 
             
            And then execute:
         | 
| 12 14 |  | 
| @@ -42,7 +44,7 @@ ObjectSpace._id2ref(id) == obj # => true | |
| 42 44 | 
             
             #For 1.9.3 use BasicObject#__id__
         | 
| 43 45 | 
             
            ```
         | 
| 44 46 |  | 
| 45 | 
            -
            ### Fast  | 
| 47 | 
            +
            ### Fast single line from caller
         | 
| 46 48 |  | 
| 47 49 | 
             
            Ruby's `caller` is handy, but sometimes you do not need the whole array of strings it allocates generates on each call.
         | 
| 48 50 |  | 
| @@ -61,9 +63,9 @@ end | |
| 61 63 | 
             
            Results:
         | 
| 62 64 |  | 
| 63 65 | 
             
            ```
         | 
| 64 | 
            -
             | 
| 65 | 
            -
            caller[1] | 
| 66 | 
            -
            caller_line | 
| 66 | 
            +
                                      user     system      total        real
         | 
| 67 | 
            +
            caller[1]             1.760000   0.040000   1.800000 (  1.802799)
         | 
| 68 | 
            +
            caller_line           0.080000   0.000000   0.080000 (  0.089649)
         | 
| 67 69 | 
             
            ```
         | 
| 68 70 |  | 
| 69 71 |  | 
    
        data/Rakefile
    CHANGED
    
    | @@ -4,77 +4,33 @@ require "bundler/gem_tasks" | |
| 4 4 | 
             
            require 'rake/extensiontask'
         | 
| 5 5 | 
             
            Rake::ExtensionTask.new('is_a')
         | 
| 6 6 |  | 
| 7 | 
            -
             | 
| 8 | 
            -
            task :test => :compile do
         | 
| 7 | 
            +
            require 'rake/testtask'
         | 
| 9 8 |  | 
| 10 | 
            -
             | 
| 9 | 
            +
            Rake::TestTask.new(:test) do |t|
         | 
| 10 | 
            +
              t.pattern = 'spec/**/*_spec.rb'
         | 
| 11 | 
            +
              t.libs.push 'spec'
         | 
| 12 | 
            +
            end
         | 
| 11 13 |  | 
| 12 | 
            -
              require "bundler/setup"
         | 
| 13 | 
            -
              require 'is_a'
         | 
| 14 14 |  | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
                  @search_me = 12345
         | 
| 18 | 
            -
                end
         | 
| 19 | 
            -
                def lala
         | 
| 20 | 
            -
                end
         | 
| 21 | 
            -
              end
         | 
| 15 | 
            +
            desc "Simple dump test,just to check if extension compiles and does not segfault on simple dump"
         | 
| 16 | 
            +
            task :test => :compile
         | 
| 22 17 |  | 
| 23 | 
            -
             | 
| 18 | 
            +
            task :default => :test
         | 
| 24 19 |  | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 20 | 
            +
            desc "Make simple benchmark for caller_line"
         | 
| 21 | 
            +
            task :bench_caller_line do
         | 
| 22 | 
            +
              require 'bundler/setup'
         | 
| 23 | 
            +
              require 'is_a'
         | 
| 24 | 
            +
              require 'benchmark'
         | 
| 25 | 
            +
              n = 50000
         | 
| 26 | 
            +
              class UtilClassWithCallerline
         | 
| 27 | 
            +
                class << self
         | 
| 28 | 
            +
                  define_method :caller_line, method(:caller_line)
         | 
| 31 29 | 
             
                end
         | 
| 32 | 
            -
             | 
| 33 | 
            -
                puts "Cls is #{cls1.inspect}, #{classes.inspect}"
         | 
| 34 | 
            -
                cls1
         | 
| 35 | 
            -
              end
         | 
| 36 | 
            -
             | 
| 37 | 
            -
              c = cls obj
         | 
| 38 | 
            -
              cls c
         | 
| 39 | 
            -
              cls nil
         | 
| 40 | 
            -
             | 
| 41 | 
            -
              id = IsA.id_of(obj)
         | 
| 42 | 
            -
              puts "Id is #{id}"
         | 
| 43 | 
            -
              if ObjectSpace._id2ref(id) == obj
         | 
| 44 | 
            -
                puts "Getref ok"
         | 
| 45 | 
            -
              else
         | 
| 46 | 
            -
                puts "Getref FAIL"
         | 
| 47 30 | 
             
              end
         | 
| 48 | 
            -
             | 
| 49 | 
            -
              unless IsA.object?(obj)
         | 
| 50 | 
            -
                puts "object? ok"
         | 
| 51 | 
            -
              else
         | 
| 52 | 
            -
                puts "object? FAIL"
         | 
| 53 | 
            -
              end
         | 
| 54 | 
            -
             | 
| 55 | 
            -
              if IsA.object?(c)
         | 
| 56 | 
            -
                puts "object? ok"
         | 
| 57 | 
            -
              else
         | 
| 58 | 
            -
                puts "object? FAIL"
         | 
| 59 | 
            -
              end
         | 
| 60 | 
            -
             | 
| 61 | 
            -
              def test_caller
         | 
| 62 | 
            -
                puts "Real caller: #{caller[0]}"
         | 
| 63 | 
            -
                puts "Caller at 0: #{IsA.caller_line(0)}"
         | 
| 64 | 
            -
                puts caller_line
         | 
| 65 | 
            -
              end
         | 
| 66 | 
            -
             | 
| 67 | 
            -
              test_caller
         | 
| 68 | 
            -
             | 
| 69 | 
            -
              require 'benchmark'
         | 
| 70 | 
            -
              n = 10000
         | 
| 71 | 
            -
              Benchmark.bm(11) do |x|
         | 
| 31 | 
            +
              Benchmark.bm(19) do |x|
         | 
| 72 32 | 
             
                x.report("caller[1]") { n.times { caller[1] } }
         | 
| 73 33 | 
             
                x.report("caller_line") { n.times { caller_line(1) } }
         | 
| 34 | 
            +
                x.report("caller_line in ctx") { n.times { UtilClassWithCallerline.caller_line(1) } }
         | 
| 74 35 | 
             
              end
         | 
| 75 | 
            -
             | 
| 76 | 
            -
              #require 'heap_dump'
         | 
| 77 | 
            -
              #HeapDump.dump
         | 
| 78 | 
            -
            end
         | 
| 79 | 
            -
             | 
| 80 | 
            -
            task :default => :test
         | 
| 36 | 
            +
            end
         | 
    
        data/ext/is_a/is_a.c
    CHANGED
    
    | @@ -35,13 +35,17 @@ static VALUE caller_line(int offset) | |
| 35 35 | 
             
              rb_control_frame_t* cfp = th->cfp + offset;
         | 
| 36 36 | 
             
              const rb_control_frame_t* stack_end = (void *)(th->stack + th->stack_size);
         | 
| 37 37 |  | 
| 38 | 
            -
               | 
| 38 | 
            +
              VALUE name = 0;
         | 
| 39 | 
            +
             | 
| 40 | 
            +
              while(cfp < stack_end){
         | 
| 39 41 | 
             
                if (cfp->iseq != 0) {
         | 
| 40 42 | 
             
                  if (cfp->pc != 0) {
         | 
| 41 43 | 
             
                    rb_iseq_t *iseq = cfp->iseq;
         | 
| 42 44 | 
             
                    int line_no = rb_vm_get_sourceline(cfp);
         | 
| 43 | 
            -
                    VALUE file = iseq->filename | 
| 44 | 
            -
             | 
| 45 | 
            +
                    VALUE file = iseq->filename;
         | 
| 46 | 
            +
                    //name may be passed from previous iteration
         | 
| 47 | 
            +
                    if(!name)
         | 
| 48 | 
            +
                      name = iseq->name;
         | 
| 45 49 | 
             
                    if (line_no) {
         | 
| 46 50 | 
             
                      return rb_enc_sprintf(
         | 
| 47 51 | 
             
                            rb_enc_compatible(file, name),
         | 
| @@ -55,12 +59,26 @@ static VALUE caller_line(int offset) | |
| 55 59 | 
             
                    }
         | 
| 56 60 | 
             
                  }
         | 
| 57 61 | 
             
                } else {
         | 
| 58 | 
            -
                  //  | 
| 59 | 
            -
                   | 
| 62 | 
            +
                  // for CFUNCs - search for previous ruby frame for location
         | 
| 63 | 
            +
                  if (RUBYVM_CFUNC_FRAME_P(cfp)) {
         | 
| 64 | 
            +
                    if (!name){
         | 
| 65 | 
            +
                      ID id;
         | 
| 66 | 
            +
                      if (cfp->me->def)
         | 
| 67 | 
            +
                        id = cfp->me->def->original_id;
         | 
| 68 | 
            +
                      else
         | 
| 69 | 
            +
                        id = cfp->me->called_id;
         | 
| 70 | 
            +
                      if (id != ID_ALLOCATOR){
         | 
| 71 | 
            +
                        name = rb_id2str(id);
         | 
| 72 | 
            +
                      }
         | 
| 73 | 
            +
                    }
         | 
| 74 | 
            +
                  }
         | 
| 75 | 
            +
                  cfp += 1;
         | 
| 76 | 
            +
                  continue;
         | 
| 60 77 | 
             
                }
         | 
| 61 | 
            -
             | 
| 62 | 
            -
                // level is out of bounds
         | 
| 78 | 
            +
                break;
         | 
| 63 79 | 
             
              }
         | 
| 80 | 
            +
             | 
| 81 | 
            +
              // level is out of bounds
         | 
| 64 82 | 
             
              return Qnil;
         | 
| 65 83 | 
             
            }
         | 
| 66 84 |  | 
    
        data/is_a.gemspec
    CHANGED
    
    
    
        data/lib/is_a/version.rb
    CHANGED
    
    
    
        data/spec/is_a_spec.rb
    ADDED
    
    | @@ -0,0 +1,51 @@ | |
| 1 | 
            +
            require 'minitest/autorun'
         | 
| 2 | 
            +
            require 'benchmark'
         | 
| 3 | 
            +
            require 'is_a'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            describe IsA do
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              subject { IsA }
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              it 'id_of' do
         | 
| 10 | 
            +
                obj = Class.new(BasicObject){}.new
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                id = subject.id_of(obj)
         | 
| 13 | 
            +
                assert_equal(obj, ObjectSpace._id2ref(id))
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              it "object?" do
         | 
| 17 | 
            +
                subject.object?(Class.new(BasicObject){}.new).must_equal false
         | 
| 18 | 
            +
                subject.object?("string is object").must_equal true
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              describe "caller_line" do
         | 
| 22 | 
            +
                it "in methods" do
         | 
| 23 | 
            +
                  def test_caller
         | 
| 24 | 
            +
                    [caller[0], subject.caller_line(0)]
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
                  r = test_caller
         | 
| 27 | 
            +
                  r.first.must_equal r.last
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                it "in blocks" do
         | 
| 31 | 
            +
                  r = proc{
         | 
| 32 | 
            +
                    [caller[0], subject.caller_line(0)]
         | 
| 33 | 
            +
                  }.call
         | 
| 34 | 
            +
                  r.last.wont_be_nil
         | 
| 35 | 
            +
                  r.first.must_equal r.last
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                it "should be faster than caller[0]" do
         | 
| 39 | 
            +
                  n = 1000
         | 
| 40 | 
            +
                  anchor = Benchmark.measure{ n.times{ caller[0] } }
         | 
| 41 | 
            +
                  res = Benchmark.measure{ n.times{ subject.caller_line(0) } }
         | 
| 42 | 
            +
                  assert_operator res.total, :<, anchor.total
         | 
| 43 | 
            +
                  assert_operator res.real, :<, anchor.real
         | 
| 44 | 
            +
                  assert_operator res.utime, :<, anchor.utime
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  # no large memory allocation => no system cpu time
         | 
| 47 | 
            +
                  res.stime.must_equal 0.0
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: is_a
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.1. | 
| 4 | 
            +
              version: 0.1.1
         | 
| 5 5 | 
             
              prerelease: 
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| @@ -9,7 +9,7 @@ authors: | |
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2013-07- | 
| 12 | 
            +
            date: 2013-07-03 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: debugger-ruby_core_source
         | 
| @@ -43,6 +43,22 @@ dependencies: | |
| 43 43 | 
             
                - - ! '>='
         | 
| 44 44 | 
             
                  - !ruby/object:Gem::Version
         | 
| 45 45 | 
             
                    version: '0'
         | 
| 46 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 47 | 
            +
              name: minitest
         | 
| 48 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 49 | 
            +
                none: false
         | 
| 50 | 
            +
                requirements:
         | 
| 51 | 
            +
                - - ! '>='
         | 
| 52 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 53 | 
            +
                    version: '0'
         | 
| 54 | 
            +
              type: :development
         | 
| 55 | 
            +
              prerelease: false
         | 
| 56 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 57 | 
            +
                none: false
         | 
| 58 | 
            +
                requirements:
         | 
| 59 | 
            +
                - - ! '>='
         | 
| 60 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 61 | 
            +
                    version: '0'
         | 
| 46 62 | 
             
            description: Fear weak references to BasicObject no more
         | 
| 47 63 | 
             
            email:
         | 
| 48 64 | 
             
            - vasilyfedoseyev@gmail.com
         | 
| @@ -61,6 +77,7 @@ files: | |
| 61 77 | 
             
            - is_a.gemspec
         | 
| 62 78 | 
             
            - lib/is_a.rb
         | 
| 63 79 | 
             
            - lib/is_a/version.rb
         | 
| 80 | 
            +
            - spec/is_a_spec.rb
         | 
| 64 81 | 
             
            homepage: http://github.com/Vasfed/is_a
         | 
| 65 82 | 
             
            licenses: []
         | 
| 66 83 | 
             
            post_install_message: 
         | 
| @@ -75,7 +92,7 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 75 92 | 
             
                  version: '0'
         | 
| 76 93 | 
             
                  segments:
         | 
| 77 94 | 
             
                  - 0
         | 
| 78 | 
            -
                  hash:  | 
| 95 | 
            +
                  hash: 2510194417071522637
         | 
| 79 96 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 80 97 | 
             
              none: false
         | 
| 81 98 | 
             
              requirements:
         | 
| @@ -84,11 +101,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 84 101 | 
             
                  version: '0'
         | 
| 85 102 | 
             
                  segments:
         | 
| 86 103 | 
             
                  - 0
         | 
| 87 | 
            -
                  hash:  | 
| 104 | 
            +
                  hash: 2510194417071522637
         | 
| 88 105 | 
             
            requirements: []
         | 
| 89 106 | 
             
            rubyforge_project: 
         | 
| 90 107 | 
             
            rubygems_version: 1.8.24
         | 
| 91 108 | 
             
            signing_key: 
         | 
| 92 109 | 
             
            specification_version: 3
         | 
| 93 110 | 
             
            summary: Defines methods to introspect any ruby object more deeply
         | 
| 94 | 
            -
            test_files: | 
| 111 | 
            +
            test_files:
         | 
| 112 | 
            +
            - spec/is_a_spec.rb
         |