duck_puncher 2.1.0 → 2.2.0

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: d3f3e8e62629faa8e0e9a59e754a21255648533e
4
- data.tar.gz: d39ba33cd952bd2dbf57cb1281169d3480696f10
3
+ metadata.gz: 6a46a207adebfd5c36e0f4d5dc51e9dd3b02d5a5
4
+ data.tar.gz: ad067c6ed3a67e38f95ff2185d51fffe2a9c11d2
5
5
  SHA512:
6
- metadata.gz: 0d52cce59da693d390269f0398266ef5c84840bcac9f7fad3082c1e80b987a766621b3a45b51e16c7cccbdcd0505940d7c1706067e1747eac95bfb3a4a6c79b9
7
- data.tar.gz: 9f4316045b90d20dd0ae18b4c05c7742d51576e077efd028f8175cc510fd532fddf87548c1aa0c8f37168df84d33a7628c85317afa51be200c66044834bc345d
6
+ metadata.gz: 61703bbb58544430f7bfe069abd9f4433d5c886d835864c1bcdbe0bcd6f889a33421cd91e0c0193e11640fd3fb93fb8b38b088d5521c0d1db4a7e5c69f29017e
7
+ data.tar.gz: 7b2d75382bbd9a1395da6736023077e95691d3a5df02f6129b918eca944f1ddafbce4a3ec7e92cf1a64ca94a9a7e6e05757b7accee1e9ea941d7bbca60839f60
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .duck_puncher/
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.2.1
5
+ - 2.2.2
6
+ - 2.2.3
7
+ before_install: gem install bundler -v 1.10.5
data/README.md CHANGED
@@ -12,6 +12,22 @@ These are the ducks I can punch:
12
12
  Numeric#to_rad => `10.15.to_rad` returns 0.17715091907742445
13
13
  String#pluralize => `'hour'.pluralize(2)` turns "hour" into "hours"
14
14
  Object#clone! => `Object.new.clone!` makes a deep clone of the object (using Marshal)
15
+ Object#require! => Downloads and activates a gem for the current and subsequent consoles. For example:
16
+ >> `require 'pry'`
17
+ LoadError: cannot load such file -- pry
18
+ from (irb):1:in `require'
19
+ from (irb):1
20
+ from bin/console:10:in `<main>'
21
+ >> require! 'pry'
22
+ Fetching: method_source-0.8.2.gem (100%)
23
+ Fetching: slop-3.6.0.gem (100%)
24
+ Fetching: coderay-1.1.0.gem (100%)
25
+ Fetching: pry-0.10.3.gem (100%)
26
+ => true
27
+ >> Pry.start
28
+ [1] pry(main)>
29
+ Method#to_instruct => `Benchmark.method(:measure).to_instruct` returns the Ruby VM instruction sequence for the method
30
+
15
31
 
16
32
  ## Install
17
33
 
@@ -25,3 +41,10 @@ Ducks need to be _loaded_ before they can be punched! Maybe do this in an initia
25
41
  DuckPuncher.punch! :Hash, :Object #=> only punches the specified ducks
26
42
  DuckPuncher.punch_all! #=> punches all the ducks
27
43
  ```
44
+
45
+ ## Contributing
46
+
47
+ * Fork it
48
+ * Run tests with `rake`
49
+ * Start an IRB console that already has all your ducks in a row `bin/console`
50
+ * Make changes and submit a PR to [https://github.com/ridiculous/duck_puncher](https://github.com/ridiculous/duck_puncher)
data/bin/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'pp'
5
+ require 'duck_puncher'
6
+ require 'irb'
7
+
8
+ DuckPuncher.punch_all!
9
+
10
+ IRB.start
@@ -0,0 +1,35 @@
1
+ require_relative 'json_storage'
2
+
3
+ class DuckPuncher::GemInstaller
4
+ def self.initialize!
5
+ spec_data = DuckPuncher::JSONStorage.read('load_paths.json').values
6
+ spec_data.each do |spec|
7
+ spec[:load_paths].each do |load_path|
8
+ next if $LOAD_PATH.include? load_path
9
+ $LOAD_PATH.unshift load_path
10
+ end
11
+ begin
12
+ require spec[:require_with]
13
+ rescue LoadError => e
14
+ puts "Failed to require #{spec[:require_with]}. #{e.inspect}"
15
+ end
16
+ end
17
+ end
18
+
19
+ # @param [String] name of the gem
20
+ # @param [String] version of the gem to install (e.g. '1.2.3')
21
+ def perform(*args)
22
+ require 'rubygems/dependency_installer'
23
+ installer = Gem::DependencyInstaller.new(install_dir: Bundler.bundle_path.to_s, bin_dir: RbConfig::CONFIG['bindir'])
24
+ installer.install *args.reject(&:empty?)
25
+ installer.installed_gems.each do |gem|
26
+ full_load_path = Bundler.bundle_path.join('gems', "#{gem.name}-#{gem.version}", "lib")
27
+ next if $LOAD_PATH.include?(full_load_path.to_s)
28
+ $LOAD_PATH.unshift full_load_path.to_s
29
+ DuckPuncher::JSONStorage.write 'load_paths.json', args.first, full_load_path
30
+ end
31
+ installer.installed_gems.any?
32
+ rescue => e
33
+ puts "Failed to install #{args.first}. #{e.inspect}"
34
+ end
35
+ end
@@ -0,0 +1,28 @@
1
+ module DuckPuncher
2
+ module JSONStorage
3
+ require 'json'
4
+
5
+ def self.dir_name
6
+ Pathname.new('.duck_puncher')
7
+ end
8
+
9
+ def self.write(file_name, key, load_path)
10
+ FileUtils.mkdir(dir_name) unless File.exists?(dir_name)
11
+ data = read(file_name)
12
+ key = key.to_sym
13
+ data[key] ||= {}
14
+ data[key][:require_with] ||= key.to_s.tr('-', '/')
15
+ data[key][:load_paths] ||= []
16
+ data[key][:load_paths] << load_path.to_s unless data[key][:load_paths].include?(load_path.to_s)
17
+ File.open(dir_name.join(file_name), 'wb') { |f| f << data.to_json }
18
+ end
19
+
20
+ def self.read(file_name)
21
+ if File.exists?(dir_name.join file_name)
22
+ JSON.parse File.read(dir_name.join file_name), symbolize_names: true
23
+ else
24
+ {}
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,44 @@
1
+ module DuckPuncher
2
+ module Method
3
+ def to_instruct
4
+ definition = Definition.new(self)
5
+ RubyVM::InstructionSequence.new(definition.lines.join).disasm if definition.lines.any?
6
+ end
7
+
8
+ class Definition
9
+ def initialize(method_handle)
10
+ @file_path, @line_num = *method_handle.source_location
11
+ @line_num = @line_num.to_i
12
+ end
13
+
14
+ # @description finds the method's source code using the indent size of the file. This means we are
15
+ # restricted when it comes to parsing crappy formatted ruby files
16
+ def lines
17
+ return @lines if defined? @lines
18
+ return [] unless @file_path
19
+ @lines = []
20
+ File.open(@file_path) do |f|
21
+ found = false
22
+ i = 0
23
+ while line = f.gets and i += 1 and !found
24
+ next if i < @line_num
25
+ @lines << line
26
+ if @indent_size
27
+ found = @indent_size == find_indent_size(line)
28
+ else
29
+ @indent_size = find_indent_size(line)
30
+ found = line.end_with?("end\n")
31
+ end
32
+ end
33
+ end
34
+ @lines
35
+ end
36
+
37
+ def find_indent_size(line)
38
+ line[/(\s*)/].size
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ Method.send(:include, DuckPuncher::Method)
@@ -1,9 +1,19 @@
1
+ require_relative 'json_storage'
2
+ require_relative 'gem_installer'
3
+
1
4
  module DuckPuncher
2
5
  module Object
3
6
  def clone!
4
7
  Marshal.load Marshal.dump self
5
8
  end unless defined? clone!
9
+
10
+ def require!(file_or_gem, version = '')
11
+ if DuckPuncher::GemInstaller.new.perform(file_or_gem, version)
12
+ require file_or_gem.tr('-', '/')
13
+ end
14
+ end
6
15
  end
7
16
  end
8
17
 
18
+ DuckPuncher::GemInstaller.initialize!
9
19
  Object.send(:include, DuckPuncher::Object)
@@ -1,3 +1,3 @@
1
1
  module DuckPuncher
2
- VERSION = '2.1.0'.freeze
2
+ VERSION = '2.2.0'.freeze
3
3
  end
data/lib/duck_puncher.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'pathname'
2
+ require 'fileutils'
1
3
  require 'duck_puncher/version'
2
4
 
3
5
  module DuckPuncher
@@ -6,6 +8,7 @@ module DuckPuncher
6
8
  autoload :Hash, 'duck_puncher/hash'
7
9
  autoload :String, 'duck_puncher/string'
8
10
  autoload :Object, 'duck_puncher/object'
11
+ autoload :Method, 'duck_puncher/method'
9
12
 
10
13
  if defined? ActiveRecord
11
14
  autoload :ActiveRecordExtensions, 'duck_puncher/active_record_extensions'
@@ -0,0 +1,30 @@
1
+ require_relative '../test_helper'
2
+ require_relative '../fixtures/wut'
3
+
4
+ class MethodTest < MiniTest::Test
5
+
6
+ # Called before every test method runs. Can be used
7
+ # to set up fixture information.
8
+ def setup
9
+ @subject = Wut.new
10
+ end
11
+
12
+ # Called after every test method runs. Can be used to tear
13
+ # down fixture information.
14
+
15
+ def teardown
16
+ # Do nothing
17
+ end
18
+
19
+ def test_to_instruct
20
+ assert_match /RubyVM::InstructionSequence:to_a/, @subject.method(:to_a).to_instruct
21
+ assert_match /newarray/, @subject.method(:to_a).to_instruct
22
+ assert_match /opt_plus/, @subject.method(:to_a).to_instruct
23
+ assert_equal nil, [].method(:to_s).to_instruct
24
+ end
25
+
26
+ def test_to_instruct_single_line
27
+ assert_match /RubyVM::InstructionSequence:to_f/, @subject.method(:to_f).to_instruct
28
+ assert_match /getconstant\s*:INFINITY/, @subject.method(:to_f).to_instruct
29
+ end
30
+ end
@@ -0,0 +1,7 @@
1
+ class Wut
2
+ def to_a
3
+ ['w'] + ['u'] + ['t']
4
+ end
5
+
6
+ def to_f() Float::INFINITY end
7
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: duck_puncher
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Buckley
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-26 00:00:00.000000000 Z
11
+ date: 2015-12-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -81,31 +81,39 @@ dependencies:
81
81
  description: Duck punches Ruby with some of my favorite class extensions
82
82
  email:
83
83
  - arebuckley@gmail.com
84
- executables: []
84
+ executables:
85
+ - console
85
86
  extensions: []
86
87
  extra_rdoc_files: []
87
88
  files:
88
89
  - ".gitignore"
89
90
  - ".ruby-gemset"
90
91
  - ".ruby-version"
92
+ - ".travis.yml"
91
93
  - Gemfile
92
94
  - LICENSE.txt
93
95
  - README.md
94
96
  - Rakefile
97
+ - bin/console
95
98
  - duck_puncher.gemspec
96
99
  - lib/duck_puncher.rb
97
100
  - lib/duck_puncher/active_record_extensions.rb
98
101
  - lib/duck_puncher/array.rb
102
+ - lib/duck_puncher/gem_installer.rb
99
103
  - lib/duck_puncher/hash.rb
104
+ - lib/duck_puncher/json_storage.rb
105
+ - lib/duck_puncher/method.rb
100
106
  - lib/duck_puncher/numeric.rb
101
107
  - lib/duck_puncher/object.rb
102
108
  - lib/duck_puncher/string.rb
103
109
  - lib/duck_puncher/version.rb
104
110
  - test/duck_puncher/array_test.rb
105
111
  - test/duck_puncher/hash_test.rb
112
+ - test/duck_puncher/method_test.rb
106
113
  - test/duck_puncher/numeric_test.rb
107
114
  - test/duck_puncher/object_test.rb
108
115
  - test/duck_puncher/string_test.rb
116
+ - test/fixtures/wut.rb
109
117
  - test/test_helper.rb
110
118
  homepage: https://github.com/ridiculous/duck_puncher
111
119
  licenses:
@@ -134,7 +142,9 @@ summary: Duck punches Ruby
134
142
  test_files:
135
143
  - test/duck_puncher/array_test.rb
136
144
  - test/duck_puncher/hash_test.rb
145
+ - test/duck_puncher/method_test.rb
137
146
  - test/duck_puncher/numeric_test.rb
138
147
  - test/duck_puncher/object_test.rb
139
148
  - test/duck_puncher/string_test.rb
149
+ - test/fixtures/wut.rb
140
150
  - test/test_helper.rb