invoca-utils 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 60e1c062370766eca1fa617f36be49862eaf88ac
4
+ data.tar.gz: e459f4db3a562dd66d965f781471931b69721f22
5
+ SHA512:
6
+ metadata.gz: 13f0207b9e47f0197970d027c6ce5956a8513f9cc4d6771a880470d57ef0bc0f54cc851b3220d683b98025790d49ff2f05c21a19c34e1ce4887073c10f83ea0f
7
+ data.tar.gz: 917afbc8c609b0361cc3a5e1c373c7164de6b2350c6f2209ca3ede0288393c9c3b8d4e02e50625b85bd89973302e15fe0559f570af9cd4846d8c907c94126bcd
data/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ .DS_Store
2
+ *.gem
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+ *.bundle
20
+ *.so
21
+ *.o
22
+ *.a
23
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in invoca-utils.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Invoca, Inc.
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,25 @@
1
+ # Invoca::Utils
2
+
3
+ A public collection of helpers used in multiple project.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'invoca-utils'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install invoca-utils
18
+
19
+ ## Contributing
20
+
21
+ 1. Fork it ( https://github.com/[my-github-username]/invoca-utils/fork )
22
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
23
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
24
+ 4. Push to the branch (`git push origin my-new-feature`)
25
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rake/testtask'
4
+
5
+ namespace :test do
6
+
7
+ Rake::TestTask.new do |t|
8
+ t.name = :unit
9
+ t.libs << "test"
10
+ t.pattern = 'test/unit/**/*_test.rb'
11
+ t.verbose = true
12
+ end
13
+ Rake::Task['test:unit'].comment = "Run the unit tests"
14
+
15
+ end
16
+
17
+ task :default => 'test:unit'
18
+
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'invoca/utils/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "invoca-utils"
8
+ spec.version = Invoca::Utils::VERSION
9
+ spec.authors = ["Cary Penniman"]
10
+ spec.email = ["cpenniman@invoca.com"]
11
+ spec.summary = %q{A public collection of helpers used in multiple projects}
12
+ spec.description = %q{A public collection of helpers used in multiple projects}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ spec.add_development_dependency "rake"
23
+
24
+ spec.add_development_dependency "test-unit", "= 1.2.3"
25
+ spec.add_development_dependency "rr", "=1.1.2"
26
+ spec.add_development_dependency "shoulda", "= 3.5.0"
27
+ spec.add_development_dependency "pry"
28
+ spec.add_development_dependency "ruby-prof"
29
+ spec.add_development_dependency "minitest"
30
+ end
@@ -0,0 +1,377 @@
1
+ # adapted from http://users.cybercity.dk/~dsl8950/ruby/diff-0.3.tar.gz
2
+
3
+ class Diff
4
+
5
+ VERSION = 0.3
6
+
7
+ def self.lcs(a, b)
8
+ astart = 0
9
+ bstart = 0
10
+ afinish = a.length-1
11
+ bfinish = b.length-1
12
+ lcs = []
13
+
14
+ # First we prune off any common elements at the beginning
15
+ while (astart <= afinish && bstart <= afinish && a[astart] == b[bstart])
16
+ lcs[astart] = bstart
17
+ astart += 1
18
+ bstart += 1
19
+ end
20
+
21
+ # now the end
22
+ while (astart <= afinish && bstart <= bfinish && a[afinish] == b[bfinish])
23
+ lcs[afinish] = bfinish
24
+ afinish -= 1
25
+ bfinish -= 1
26
+ end
27
+
28
+ bmatches = reverse_hash(b, bstart..bfinish)
29
+ thresh = []
30
+ links = []
31
+
32
+ (astart..afinish).each { |aindex|
33
+ aelem = a[aindex]
34
+ next unless bmatches.has_key? aelem
35
+ k = nil
36
+ bmatches[aelem].reverse.each { |bindex|
37
+ if k && (thresh[k] > bindex) && (thresh[k-1] < bindex)
38
+ thresh[k] = bindex
39
+ else
40
+ k = replacenextlarger(thresh, bindex, k)
41
+ end
42
+ links[k] = [ (k==0) ? nil : links[k-1], aindex, bindex ] if k
43
+ }
44
+ }
45
+
46
+ if !thresh.empty?
47
+ link = links[thresh.length-1]
48
+ while link
49
+ lcs[link[1]] = link[2]
50
+ link = link[0]
51
+ end
52
+ end
53
+
54
+ return lcs
55
+ end
56
+
57
+ def self.nested_compare( subtractions, additions, index )
58
+ subtraction = subtractions[index]
59
+ addition = additions[index]
60
+ if subtraction.is_a?( Array ) && addition.is_a?( Array )
61
+ return "Nested array diff:\n#{ compare( subtraction, addition ) }\n"
62
+ elsif subtraction.is_a?( Hash ) && addition.is_a?( Hash )
63
+ return "Nested hash diff:\n#{ compare( subtraction, addition ) }\n"
64
+ else
65
+ ""
66
+ end
67
+ end
68
+
69
+ def self.format(value)
70
+ value.is_a?(Numeric) || value.is_a?(String) ? value : value.inspect
71
+ end
72
+
73
+ def self.compare arg1, arg2, options={}
74
+ result = ''
75
+ if arg1 != arg2
76
+ if arg1.class == arg2.class || (arg1.is_a?(Hash) && arg2.is_a?(Hash)) || (arg1.is_a?(Array) && arg2.is_a?(Array)) # Hash and Array are equivalent when specialized
77
+ case arg1
78
+ when Array
79
+ diff_obj = Diff.new(arg1, arg2)
80
+ summary = diff_obj.summary
81
+ curr_diff = nil
82
+ (arg1 + [nil]).each_with_index do |arg, index|
83
+ if curr_diff.nil? || index > curr_diff[1].last
84
+ curr_diff = summary.shift
85
+ end
86
+ unless curr_diff && (curr_diff[1].first..curr_diff[1].last) === index
87
+ result << " #{format arg}\n" unless arg.nil? || options[:short_description]
88
+ end
89
+ if curr_diff && curr_diff[1].first == index
90
+ verb, a_range, b_range, del, add = curr_diff
91
+ result <<
92
+ case verb
93
+ when 'd'
94
+ del.map { |t| "- #{format t}\n"}.join
95
+ when 'a'
96
+ add.map { |t| "+ #{format t}\n"}.join +
97
+ (arg.nil? ? '' : " #{format arg}\n")
98
+ when 'c'
99
+ del.map_with_index { |t,index| "- #{format t}\n#{ nested_compare( del, add, index ) }"}.join +
100
+ add.map_with_index { |t,index| "+ #{format t}\n"}.join
101
+ end
102
+ end
103
+ end
104
+ summary.empty? or raise "Summary left: #{summary.inspect}"
105
+ when Hash
106
+ arg1.each do |key, value|
107
+ if arg2.has_key? key
108
+ result += "[#{key.inspect}] #{compare value, arg2[key]};\n" if value != arg2[key]
109
+ else
110
+ result += "[#{key.inspect}] expected #{value.inspect}, was missing;\n"
111
+ end
112
+ end
113
+ (arg2.keys - arg1.keys).each do |key|
114
+ result += "[#{key.inspect}] not expected, was #{arg2[key].inspect};\n"
115
+ end
116
+ else
117
+ result = "expected #{arg1.inspect}, was #{arg2.inspect} "
118
+ end
119
+ elsif arg1.class.in?([Float,BigDecimal]) && arg2.class.in?([Float,BigDecimal])
120
+ result = "expected #{arg1.class}: #{arg1.to_s}, was #{arg2.class}: #{arg2.to_s} "
121
+ else
122
+ result = "expected #{arg1.class}:#{arg1.inspect}, was #{arg2.class}:#{arg2.inspect} "
123
+ end
124
+ end
125
+ result
126
+ end
127
+
128
+
129
+ def makediff(a, b)
130
+ lcs = self.class.lcs(a, b)
131
+ ai = bi = 0
132
+ while ai < lcs.length
133
+ if lcs[ai]
134
+ while bi < lcs[ai]
135
+ discardb(bi, b[bi])
136
+ bi += 1
137
+ end
138
+ match
139
+ bi += 1
140
+ else
141
+ discarda(ai, a[ai])
142
+ end
143
+ ai += 1
144
+ end
145
+ while ai < a.length
146
+ discarda(ai, a[ai])
147
+ ai += 1
148
+ end
149
+ while bi < b.length
150
+ discardb(bi, b[bi])
151
+ bi += 1
152
+ end
153
+ match
154
+ end
155
+
156
+ def compact!
157
+ diffs = []
158
+ @diffs.each do |diff|
159
+ puts "compacting #{diff.inspect}"
160
+ i = 0
161
+ curdiff = []
162
+ while i < diff.length
163
+ action = diff[i][0]
164
+ s = @difftype.is_a?(String) ? diff[i][2,1] : [diff[i][2]]
165
+ offset = diff[i][1]
166
+ last = offset
167
+ i += 1
168
+ while diff[i] && diff[i][0] == action && diff[i][1] == last+1
169
+ s << diff[i][2]
170
+ last = diff[i][1]
171
+ i += 1
172
+ end
173
+ curdiff.push [action, offset, s]
174
+ end
175
+ diffs.push curdiff
176
+ end
177
+ @diffs = diffs
178
+ self
179
+ end
180
+
181
+ def compact
182
+ result = self.dup
183
+ result.compact!
184
+ result
185
+ end
186
+
187
+ def summary
188
+ result = []
189
+ b_offset = 0
190
+ @diffs.each do |block|
191
+ del = []
192
+ add = []
193
+ block.each do |diff|
194
+ case diff[0]
195
+ when "-"
196
+ del << diff[2]
197
+ when "+"
198
+ add << diff[2]
199
+ end
200
+ end
201
+ first = block[0][1]
202
+ verb, a_range, b_range =
203
+ if del.empty?
204
+ [ 'a', [first-b_offset,first-b_offset], [first, first+add.size-1] ]
205
+ elsif add.empty?
206
+ [ 'd', [first, first+del.size-1], [first+b_offset, first+b_offset] ]
207
+ else
208
+ [ 'c', [first, first+del.size-1], [first+b_offset, first+b_offset+add.size-1] ]
209
+ end
210
+ b_offset = b_offset + add.size - del.size
211
+ result << [verb, a_range, b_range, del, add]
212
+ end
213
+ result
214
+ end
215
+
216
+ attr_reader :diffs, :difftype
217
+
218
+ def initialize(a, b)
219
+ @difftype = a.class
220
+ @diffs = []
221
+ @curdiffs = []
222
+ makediff(a, b)
223
+ end
224
+
225
+ def match
226
+ @diffs << @curdiffs unless @curdiffs.empty?
227
+ @curdiffs = []
228
+ end
229
+
230
+ def discarda(i, elem)
231
+ @curdiffs.push ['-', i, elem]
232
+ end
233
+
234
+ def discardb(i, elem)
235
+ @curdiffs.push ['+', i, elem]
236
+ end
237
+
238
+ def inspect
239
+ @diffs.inspect
240
+ end
241
+
242
+ # Create a hash that maps elements of the array to arrays of indices
243
+ # where the elements are found.
244
+
245
+ def self.reverse_hash(lhs, range = nil)
246
+ range ||= (0...lhs.length)
247
+ revmap = {}
248
+ range.each { |i|
249
+ elem = lhs[i]
250
+ if revmap.has_key? elem
251
+ revmap[elem].push i
252
+ else
253
+ revmap[elem] = [i]
254
+ end
255
+ }
256
+ return revmap
257
+ end
258
+
259
+ def self.replacenextlarger(lhs, value, high = nil)
260
+ high ||= lhs.length
261
+ if lhs.empty? || value > lhs[-1]
262
+ lhs.push value
263
+ return high
264
+ end
265
+ # binary search for replacement point
266
+ low = 0
267
+ while low < high
268
+ index = (high+low)/2
269
+ found = lhs[index]
270
+ return nil if value == found
271
+ if value > found
272
+ low = index + 1
273
+ else
274
+ high = index
275
+ end
276
+ end
277
+
278
+ lhs[low] = value
279
+ # $stderr << "replace #{value} : 0/#{low}/#{init_high} (#{steps} steps) (#{init_high-low} off )\n"
280
+ # $stderr.puts lhs.inspect
281
+ #gets
282
+ #p length - low
283
+ return low
284
+ end
285
+
286
+ def self.patch(lhs, diff)
287
+ newary = nil
288
+ if diff.difftype == String
289
+ newary = diff.difftype.new('')
290
+ else
291
+ newary = diff.difftype.new
292
+ end
293
+ ai = 0
294
+ bi = 0
295
+ diff.diffs.each { |d|
296
+ d.each { |mod|
297
+ case mod[0]
298
+ when '-'
299
+ while ai < mod[1]
300
+ newary << lhs[ai]
301
+ ai += 1
302
+ bi += 1
303
+ end
304
+ ai += 1
305
+ when '+'
306
+ while bi < mod[1]
307
+ newary << lhs[ai]
308
+ ai += 1
309
+ bi += 1
310
+ end
311
+ newary << mod[2]
312
+ bi += 1
313
+ else
314
+ raise "Unknown diff action"
315
+ end
316
+ }
317
+ }
318
+ while ai < lhs.length
319
+ newary << lhs[ai]
320
+ ai += 1
321
+ bi += 1
322
+ end
323
+ return newary
324
+ end
325
+ end
326
+
327
+ module Diffable
328
+ def diff(b)
329
+ Diff.new(self, b)
330
+ end
331
+ end
332
+
333
+ #
334
+ #class Array
335
+ # include Diffable
336
+ #end
337
+ #
338
+ #class String
339
+ # include Diffable
340
+ #end
341
+
342
+ =begin
343
+ = Diff
344
+ (({diff.rb})) - computes the differences between two arrays or
345
+ strings. Copyright (C) 2001 Lars Christensen
346
+
347
+ == Synopsis
348
+
349
+ diff = Diff.new(a, b)
350
+ b = a.patch(diff)
351
+
352
+ == Class Diff
353
+ === Class Methods
354
+ --- Diff.new(a, b)
355
+ --- a.diff(b)
356
+ Creates a Diff object which represent the differences between
357
+ ((|a|)) and ((|b|)). ((|a|)) and ((|b|)) can be either be arrays
358
+ of any objects, strings, or object of any class that include
359
+ module ((|Diffable|))
360
+
361
+ == Module Diffable
362
+ The module ((|Diffable|)) is intended to be included in any class for
363
+ which differences are to be computed. Diffable is included into String
364
+ and Array when (({diff.rb})) is (({require}))'d.
365
+
366
+ Classes including Diffable should implement (({[]})) to get element at
367
+ integer indices, (({<<})) to append elements to the object and
368
+ (({ClassName#new})) should accept 0 arguments to create a new empty
369
+ object.
370
+
371
+ === Instance Methods
372
+ --- Diffable#patch(diff)
373
+ Applies the differences from ((|diff|)) to the object ((|obj|))
374
+ and return the result. ((|obj|)) is not changed. ((|obj|)) and
375
+ can be either an array or a string, but must match the object
376
+ from which the ((|diff|)) was created.
377
+ =end
@@ -0,0 +1,84 @@
1
+ #
2
+ # Used by functional tests to track exceptions.
3
+ #
4
+
5
+ module LogErrorStub
6
+ class UnexpectedExceptionLogged < StandardError; end
7
+ class ExpectedExceptionNotLogged < StandardError; end
8
+
9
+ def setup_log_error_stub
10
+ clear_exception_whitelist
11
+ stub_log_error unless respond_to?(:dont_stub_log_error) && dont_stub_log_error
12
+ end
13
+
14
+ def teardown_log_error_stub
15
+ ExceptionHandling.stub_handler = nil
16
+ return unless @exception_whitelist
17
+ @exception_whitelist.each do |item|
18
+ add_failure("log_error expected #{item[1][:expected]} times with pattern: '#{item[0].is_a?(Regexp) ? item[0].source : item[0]}' #{item[1][:count]} found #{item[1][:found]}") unless item[1][:expected] == item[1][:found]
19
+ end
20
+ end
21
+
22
+ attr_accessor :exception_whitelist
23
+
24
+ #
25
+ # Call this function in your functional tests - usually first line after a "should" statement
26
+ # once called, you can then call expects_exception
27
+ # By stubbing log error, ExceptionHandling will keep a list of all expected exceptions and
28
+ # gracefully note their occurrence.
29
+ #
30
+ def stub_log_error
31
+ ExceptionHandling.stub_handler = self
32
+ end
33
+
34
+ #
35
+ # Gets called by ExceptionHandling::log_error in test mode.
36
+ # If you have called expects_exception then this function will simply note that an
37
+ # instance of that exception has occurred - otherwise it will raise (which will
38
+ # generally result in a 500 return code for your test request)
39
+ #
40
+ def handle_stub_log_error(exception_data, always_raise = false)
41
+ raise_unexpected_exception(exception_data) if always_raise || !exception_filtered?(exception_data)
42
+ end
43
+
44
+ #
45
+ # Did the calling code call expects_exception on this exception?
46
+ #
47
+ def exception_filtered?(exception_data)
48
+ @exception_whitelist && @exception_whitelist.any? do |expectation|
49
+ if expectation[0] === exception_data[:error]
50
+ expectation[1][:found] += 1
51
+ true
52
+ end
53
+ end
54
+ end
55
+
56
+ #
57
+ # Call this from your test file to declare what exceptions you expect to raise.
58
+ #
59
+ def expects_exception(pattern, options = {})
60
+ @exception_whitelist ||= []
61
+ expected_count = options[:count] || 1
62
+ options = {:expected => expected_count, :found => 0}
63
+ if to_increment = @exception_whitelist.find {|ex| ex[0] == pattern}
64
+ to_increment[1][:expected] += expected_count
65
+ else
66
+ @exception_whitelist << [pattern, options]
67
+ end
68
+ end
69
+
70
+ def clear_exception_whitelist
71
+ @exception_whitelist = nil
72
+ end
73
+
74
+ private
75
+
76
+ def raise_unexpected_exception(exception_data)
77
+ raise(UnexpectedExceptionLogged,
78
+ exception_data[:error] + "\n" +
79
+ "---original backtrace---\n" +
80
+ exception_data[:backtrace].join("\n") + "\n" +
81
+ "------")
82
+ end
83
+
84
+ end
@@ -0,0 +1,5 @@
1
+ module Invoca
2
+ module Utils
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ require "invoca/utils/version"
2
+
3
+ require "invoca/utils/diff"
4
+ require "invoca/utils/log_error_stub"
5
+
6
+ module Invoca
7
+ module Utils
8
+
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+ require "minitest/autorun"
3
+ require 'rr'
4
+ require 'shoulda'
5
+ require 'pry'
@@ -0,0 +1,5 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ class UtilsTest < Minitest::Test
4
+ require 'invoca/utils'
5
+ end
metadata ADDED
@@ -0,0 +1,170 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: invoca-utils
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Cary Penniman
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: test-unit
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 1.2.3
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 1.2.3
55
+ - !ruby/object:Gem::Dependency
56
+ name: rr
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 1.1.2
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 1.1.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: shoulda
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 3.5.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 3.5.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: ruby-prof
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: minitest
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: A public collection of helpers used in multiple projects
126
+ email:
127
+ - cpenniman@invoca.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".gitignore"
133
+ - Gemfile
134
+ - LICENSE.txt
135
+ - README.md
136
+ - Rakefile
137
+ - invoca-utils.gemspec
138
+ - lib/invoca/utils.rb
139
+ - lib/invoca/utils/diff.rb
140
+ - lib/invoca/utils/log_error_stub.rb
141
+ - lib/invoca/utils/version.rb
142
+ - test/test_helper.rb
143
+ - test/unit/utils_test.rb
144
+ homepage: ''
145
+ licenses:
146
+ - MIT
147
+ metadata: {}
148
+ post_install_message:
149
+ rdoc_options: []
150
+ require_paths:
151
+ - lib
152
+ required_ruby_version: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ required_rubygems_version: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - ">="
160
+ - !ruby/object:Gem::Version
161
+ version: '0'
162
+ requirements: []
163
+ rubyforge_project:
164
+ rubygems_version: 2.2.2
165
+ signing_key:
166
+ specification_version: 4
167
+ summary: A public collection of helpers used in multiple projects
168
+ test_files:
169
+ - test/test_helper.rb
170
+ - test/unit/utils_test.rb