epitools 0.5.19 → 0.5.20

Sign up to get free protection for your applications and to get access to all the features.
data/Guardfile CHANGED
@@ -10,7 +10,8 @@
10
10
  guard :rspec, :version => 2, :cli => "--color", :bundler => false, :all_after_pass => false, :all_on_start => false, :keep_failed => false do
11
11
  #guard 'rspec', :version => 2 do
12
12
  watch(%r{^spec/.+_spec\.rb$})
13
- watch(%r{^lib/epitools/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
14
- watch('spec/spec_helper.rb') { "spec" }
13
+ watch(%r{^lib/epitools/([^/]+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
14
+ watch(%r{^lib/epitools/([^/]+)/.+\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
15
+ watch('spec/spec_helper.rb') { "spec" }
15
16
  end
16
17
 
@@ -1,8 +1,8 @@
1
1
  = epitools
2
2
 
3
3
  Useful miscellaneous improvements for base Ruby objects, plus some extra
4
- data structures and handy wrappers. (Think of it as a light-weight version
5
- of ActiveSupport.
4
+ data structures and handy wrappers. You can think of it as a light-weight
5
+ ActiveSupport.
6
6
 
7
7
  All epitools modules (and a bunch of Ruby's stdlib) are
8
8
  {loaded on demand with "autoload"}[https://github.com/epitron/epitools/blob/master/lib/epitools/autoloads.rb],
data/Rakefile CHANGED
@@ -1,13 +1,13 @@
1
- VERSION = File.read("VERSION").strip
1
+ gem_version = File.read("VERSION").strip
2
2
 
3
3
  task :build do
4
4
  system "gem build .gemspec"
5
5
  end
6
6
 
7
7
  task :release => :build do
8
- system "gem push epitools-#{VERSION}.gem"
8
+ system "gem push epitools-#{gem_version}.gem"
9
9
  end
10
10
 
11
11
  task :install => :build do
12
- system "gem install epitools-#{VERSION}.gem"
12
+ system "gem install epitools-#{gem_version}.gem"
13
13
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.19
1
+ 0.5.20
@@ -1,9 +1,9 @@
1
1
  ## Standard library
2
+
2
3
  autoload :Set, 'set'
3
4
  autoload :URI, 'uri'
4
5
  autoload :CGI, 'cgi'
5
6
  autoload :Base64, 'base64'
6
- autoload :JSON, 'json'
7
7
  autoload :Zlib, 'zlib'
8
8
  autoload :FileUtils, 'fileutils'
9
9
  autoload :Tempfile, 'tempfile'
@@ -18,28 +18,22 @@ autoload :Find, 'find'
18
18
  autoload :Benchmark, 'benchmark'
19
19
  autoload :Tracer, 'tracer'
20
20
  autoload :CSV, 'csv'
21
- #autoload :DelegateClass, 'delegate'
22
21
 
23
- # YAML is sometimes loaded improperly.
24
- if defined? YAML and not defined? YAML.parse
25
- del YAML # remove the existing module
22
+ module Digest
23
+ autoload :SHA1, 'digest/sha1'
24
+ autoload :SHA2, 'digest/sha2'
25
+ autoload :MD5, 'digest/md5'
26
26
  end
27
27
 
28
- autoload :YAML, 'yaml'
29
-
30
28
  if RUBY_VERSION["1.8.7"]
31
29
  autoload :Prime, 'mathn'
32
30
  else
33
31
  autoload :Prime, 'prime'
34
32
  end
35
33
 
36
- module Digest
37
- autoload :SHA1, 'digest/sha1'
38
- autoload :SHA2, 'digest/sha2'
39
- autoload :MD5, 'digest/md5'
40
- end
41
34
 
42
- ## Nonstandard library
35
+ ## Nonstandard library (epitools)
36
+
43
37
  autoload :Path, 'epitools/path'
44
38
  autoload :Ezdb, 'epitools/ezdb'
45
39
  autoload :Browser, 'epitools/browser'
@@ -54,7 +48,31 @@ autoload :WM, 'epitools/wm'
54
48
  autoload :TypedStruct, 'epitools/typed_struct'
55
49
  autoload :Sys, 'epitools/sys'
56
50
 
51
+
57
52
  ## Gems (common)
53
+
58
54
  autoreq :Nokogiri, 'nokogiri'
59
55
  autoreq :ANSI, 'ansi'
60
56
  autoreq :BSON, 'bson'
57
+ autoreq :JSON, 'json'
58
+
59
+
60
+ ## Network stuff
61
+
62
+ # Sockets
63
+ ['IP', 'Basic', 'TCP', 'UDP', 'UNIX', ''].each do |type|
64
+ autoload :"#{type}Socket", 'socket'
65
+ end
66
+
67
+ # Servers
68
+ ['TCP', 'UNIX'].each do |type|
69
+ autoload :"#{type}Server", 'socket'
70
+ end
71
+
72
+
73
+ ## YAML hacks (sometimes the module is loaded improperly)
74
+
75
+ if defined? YAML and not defined? YAML.parse
76
+ del YAML # remove the existing module
77
+ end
78
+ autoreq :YAML, 'yaml'
@@ -66,7 +66,7 @@ class Array
66
66
  #
67
67
  # Shuffle the array
68
68
  #
69
- unless defined? shuffle
69
+ unless instance_methods.include? :shuffle
70
70
  def shuffle
71
71
  sort_by{rand}
72
72
  end
@@ -75,13 +75,20 @@ class Array
75
75
  #
76
76
  # Pick (a) random element(s).
77
77
  #
78
- unless defined? sample
78
+ unless instance_methods.include? :sample
79
79
  def sample(n=1)
80
- if n == 1
81
- self[rand(size)]
82
- else
83
- shuffle[0...n]
80
+ return self[rand sz] if n == 1
81
+
82
+ sz = size
83
+ indices = []
84
+
85
+ loop do
86
+ indices += (0..n*1.2).map { rand sz }
87
+ indices.uniq
88
+ break if indices.size >= n
84
89
  end
90
+
91
+ values_at(*indices[0...n])
85
92
  end
86
93
  end
87
94
  alias_method :pick, :sample
@@ -35,7 +35,7 @@ module Enumerable
35
35
  end
36
36
  end
37
37
  else
38
- enum_for :skip, n
38
+ to_enum(:skip, n)
39
39
  end
40
40
  end
41
41
 
@@ -166,16 +166,22 @@ module Enumerable
166
166
  # Example:
167
167
  # [ [1,2], [3,4] ].deep_map{|e| e ** 2 } #=> [ [1,4], [9,16] ]
168
168
  #
169
- def deep_map(depth=nil, &block)
170
- map do |obj|
169
+ def deep_map(max_depth=nil, current_depth=0, parent=nil, &block)
170
+ return self if max_depth and (current_depth > max_depth)
171
171
 
172
- case obj
173
- when Enumerable
174
- obj.deep_map(&block)
172
+ map do |obj|
173
+ if obj == parent # infinite loop scenario!
174
+ yield obj
175
175
  else
176
- block.call(obj)
176
+ case obj
177
+ when String
178
+ yield obj
179
+ when Enumerable
180
+ obj.deep_map(max_depth, current_depth+1, self, &block)
181
+ else
182
+ yield obj
183
+ end
177
184
  end
178
-
179
185
  end
180
186
  end
181
187
 
@@ -190,30 +196,58 @@ module Enumerable
190
196
  # Example:
191
197
  # [ [1,2], [3,4] ].deep_select{|e| e % 2 == 0 } #=> [ [2], [4] ]
192
198
  #
193
- def deep_select(depth=nil, &block)
194
- map do |*args|
195
-
196
- obj = args.last
197
-
198
- if depth.nil? or depth > 0
199
+ def deep_select(max_depth=nil, current_depth=0, parent=nil, &block)
200
+ return self if max_depth and (current_depth > max_depth)
199
201
 
202
+ map do |obj|
203
+ p [:obj, obj]
204
+ result = if obj == parent # infinite loop scenario!
205
+ p :infinite
206
+ obj if yield obj
207
+ else
200
208
  case obj
201
- when Hash
202
-
203
- when Array, Enumerable
204
- result = obj.deep_select(depth ? depth-1 : nil, &block)
205
- result.any? ? result : nil
209
+ when String
210
+ p :string
211
+ obj if yield obj
212
+ when Enumerable
213
+ p :recurse
214
+ obj.deep_select(max_depth, current_depth+1, self, &block)
215
+ else
216
+ p :else
217
+ p [:yield, yield(obj)]
218
+ obj if yield obj
206
219
  end
207
-
208
- else
209
- obj if block.call(obj)
210
220
  end
211
-
221
+ p [:result, result]
222
+ result
212
223
  end.compact
213
224
  end
214
225
 
215
- alias_method :recursive_select, :deep_select
226
+ # def deep_select(depth=nil, &block)
227
+ # map do |*args|
228
+
229
+ # obj = args.last
230
+
231
+ # if depth.nil? or depth > 0
232
+
233
+ # case obj
234
+ # when Hash
235
+
236
+ # when Array, Enumerable
237
+ # result = obj.deep_select(depth ? depth-1 : nil, &block)
238
+ # result.any? ? result : nil
239
+ # end
240
+
241
+ # else
242
+ # obj if block.call(obj)
243
+ # end
244
+
245
+ # end.compact
246
+ # end
216
247
 
248
+ alias_method :recursive_select, :deep_select
249
+ alias_method :select_recursively, :deep_select
250
+ alias_method :select_recursive, :deep_select
217
251
 
218
252
  #
219
253
  # Identical to "reduce" in ruby1.9 (or foldl in haskell.)
@@ -324,7 +358,7 @@ class Enumerator
324
358
  # Display a spinner every `every` elements that pass through the Enumerator.
325
359
  #
326
360
  def with_spinner(every=37)
327
- Enumerator.new do |yielder|
361
+ to_enum do |yielder|
328
362
  spins = 0
329
363
 
330
364
  each.with_index do |e, i|
@@ -9,6 +9,7 @@ class MatchData
9
9
 
10
10
  end
11
11
 
12
+
12
13
  class Binding
13
14
 
14
15
  #
@@ -30,15 +31,22 @@ class Binding
30
31
  #
31
32
  # Return all the local variables in the binding
32
33
  #
33
- def local_variables
34
- eval("local_variables")
34
+
35
+ if RUBY_VERSION["1.8"]
36
+ def local_variables
37
+ eval("local_variables").map(&:to_sym)
38
+ end
39
+ else
40
+ def local_variables
41
+ eval("local_variables")
42
+ end
35
43
  end
44
+
36
45
  alias_method :keys, :local_variables
37
46
 
38
47
  end
39
48
 
40
49
 
41
-
42
50
  class Proc
43
51
 
44
52
  #
@@ -19,8 +19,12 @@ class Numeric
19
19
  def clamp(range)
20
20
  if self < range.first
21
21
  range.first
22
- elsif self > range.last
23
- range.last
22
+ elsif self >= range.last
23
+ if range.exclude_end?
24
+ range.last - 1
25
+ else
26
+ range.last
27
+ end
24
28
  else
25
29
  self
26
30
  end
@@ -95,8 +99,11 @@ class Numeric
95
99
 
96
100
  end
97
101
 
98
- def log(n)
99
- Math.log(self, n)
102
+ # Math.log is different in 1.8
103
+ if RUBY_VERSION["1.8"]
104
+ def log(n); Math.log(self) / Math.log(n); end
105
+ else
106
+ def log(n); Math.log(self, n); end
100
107
  end
101
108
 
102
109
 
@@ -1,3 +1,4 @@
1
+ require 'epitools/minimal'
1
2
  require 'epitools/core_ext/numbers'
2
3
 
3
4
  class String
@@ -107,6 +108,7 @@ class String
107
108
  # Convert a query string to a hash of params
108
109
  #
109
110
  def to_params
111
+ require 'cgi' unless defined? CGI.parse
110
112
  CGI.parse(self).map_values do |v|
111
113
  # CGI.parse wraps every value in an array. Unwrap them!
112
114
  if v.is_a?(Array) and v.size == 1
@@ -231,7 +233,7 @@ class String
231
233
  # Parse this string as YAML
232
234
  #
233
235
  def from_yaml
234
- YAML.parse(self).to_ruby
236
+ YAML.load(self)
235
237
  end
236
238
 
237
239
  #
@@ -4,14 +4,6 @@ if RUBY_VERSION["1.8"]
4
4
  Enumerator = Enumerable::Enumerator unless defined? Enumerator
5
5
  end
6
6
 
7
- unless defined? Enum
8
- if defined? Enumerator
9
- Enum = Enumerator
10
- else
11
- $stderr.puts "WARNING: Couldn't find the Enumerator class. Enum will not be available."
12
- end
13
- end
14
-
15
7
  RbConfig = Config unless defined? RbConfig
16
8
 
17
9
 
@@ -121,7 +113,7 @@ class Object
121
113
  alias_method "#{meth}_without_enumerator", meth
122
114
  class_eval %{
123
115
  def #{meth}(*args, &block)
124
- return Enum.new(self, #{meth.inspect}, *args, &block) unless block_given?
116
+ return to_enum(#{meth.inspect}, *args, &block) unless block_given?
125
117
  #{meth}_without_enumerator(*args, &block)
126
118
  end
127
119
  }
@@ -51,7 +51,7 @@ class Rash
51
51
  # Return everything that matches the query.
52
52
  #
53
53
  def all(query)
54
- return Enumerator.new(self, :all, query) unless block_given?
54
+ return to_enum(:all, query) unless block_given?
55
55
 
56
56
  if @hash.include? query
57
57
  yield @hash[query]
@@ -37,6 +37,10 @@ module Term
37
37
  def goto(x,y); @x, @y = x, y; end
38
38
  def pos; [@x, @y]; end
39
39
 
40
+ def clear
41
+ print "\e[H\e[J"
42
+ end
43
+
40
44
  def color(fore, back=nil)
41
45
  @fore = fore
42
46
  @back = back if back
@@ -1,16 +1,8 @@
1
+ # require 'pry-rescue/rspec'
1
2
  require 'epitools'
2
3
 
3
4
  describe Object do
4
5
 
5
- it "has Enum" do
6
- defined?(Enum).should_not == nil
7
- end
8
-
9
- #it "enums" do
10
- # generator = enum { |y| y.yield 1 }
11
- # generator.next.should == 1
12
- #end
13
-
14
6
  it "withs" do
15
7
  class Cookie; attr_accessor :size, :chips; end
16
8
 
@@ -161,7 +153,7 @@ describe Numeric do
161
153
  20.sin.should == Math.sin(20)
162
154
  1.5.exp.should == Math.exp(1.5)
163
155
 
164
- 253.log(5).should == Math.log(253,5)
156
+ 253.log(5).should == 3.438088195871358
165
157
  (2**(4212.log(2))).round.should == 4212.0
166
158
  end
167
159
 
@@ -357,12 +349,33 @@ end
357
349
 
358
350
  describe Enumerable do
359
351
 
352
+ it "maps deeply" do
353
+ [["a\n", "b\n"], ["c\n", "d\n"]].map_recursively(&:strip).should == [ %w[a b], %w[c d] ]
354
+
355
+ [[1,2],[3,4]].deep_map {|e| e ** 2}.should == [[1,4],[9,16]]
356
+ [1,2,3,4].deep_map {|e| e ** 2}.should == [1,4,9,16]
357
+ [[],[],1,2,3,4].deep_map {|e| e ** 2}.should == [[], [], 1, 4, 9, 16]
358
+
359
+ {1=>2, 3=>{4=>5, 6=>7}}.deep_map {|k,v| [k, v**2] }.should == [ [1,4], [3, [[4,25], [6,49]]] ]
360
+ end
361
+
362
+ it "selects deeply" do
363
+
364
+ [[1,2],[3,4]].deep_select {|e| e % 2 == 0 }.should == [[2],[4]]
365
+ puts
366
+
367
+ {1=>2, 3=>{4=>5, 6=>7}}.deep_select {|k,v| k == 1 }.should == {1=>2}
368
+ #[1,2,3,4].deep_select {|e| e ** 2}.should == [1,4,9,16]
369
+ #[[],[],1,2,3,4].deep_select {|e| e ** 2}.should == [[], [], 1, 4, 9, 16]
370
+ end
371
+
360
372
  it "splits" do
361
373
  [1,2,3,4,5].split_at {|e| e == 3}.should == [ [1,2], [4,5] ]
362
374
  [1,2,3,4,5].split_after {|e| e == 3}.should == [ [1,2,3], [4,5] ]
363
375
  [1,2,3,4,5].split_before {|e| e == 3}.should == [ [1,2], [3,4,5] ]
364
376
 
365
- "a\nb\n---\nc\nd\n".lines.split_at(/---/).map_recursively(&:strip).should == [ %w[a b], %w[c d] ]
377
+ result = "a\nb\n---\nc\nd\n".lines.split_at(/---/)
378
+ result.map_recursively(&:strip).should == [ %w[a b], %w[c d] ]
366
379
  end
367
380
 
368
381
  it "handles nested things" do
@@ -394,19 +407,6 @@ describe Enumerable do
394
407
  [1,1,3,3].average.should == 2.0
395
408
  end
396
409
 
397
- it "maps deeply" do
398
- [[1,2],[3,4]].deep_map {|e| e ** 2}.should == [[1,4],[9,16]]
399
- [1,2,3,4].deep_map {|e| e ** 2}.should == [1,4,9,16]
400
- [[],[],1,2,3,4].deep_map {|e| e ** 2}.should == [[], [], 1, 4, 9, 16]
401
- end
402
-
403
- it "selects deeply" do
404
- [[1,2],[3,4]].deep_select {|e| e % 2 == 0 }.should == [[2],[4]]
405
- {1=>2, 3=>{4=>5, 6=>7}}.deep_select {|k,v| k == 1 }.should == {1=>2}
406
- #[1,2,3,4].deep_select {|e| e ** 2}.should == [1,4,9,16]
407
- #[[],[],1,2,3,4].deep_select {|e| e ** 2}.should == [[], [], 1, 4, 9, 16]
408
- end
409
-
410
410
  it "foldl's" do
411
411
  a = [1,2,3,4]
412
412
  a.foldl(:+).should == a.sum
@@ -417,7 +417,7 @@ describe Enumerable do
417
417
 
418
418
  it "powersets" do
419
419
  [1,2,3].powerset.should == [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
420
- Enum.new([1,2], :each).powerset.should == [[], [1], [2], [1, 2]]
420
+ [1,2].to_enum.powerset.should == [[], [1], [2], [1, 2]]
421
421
  end
422
422
 
423
423
  it "unzips" do
@@ -466,10 +466,10 @@ describe Hash do
466
466
  it "maps values" do
467
467
  h = @h.map_values{|v| v.upcase}
468
468
 
469
- h.values.should == @h.values.map{|v| v.upcase}
470
- h.keys.should == @h.keys
469
+ h.values.should =~ @h.values.map{|v| v.upcase}
470
+ h.keys.should =~ @h.keys
471
471
  h.map_values! { 1 }
472
- h.values.should == [1,1]
472
+ h.values.should =~ [1,1]
473
473
  end
474
474
 
475
475
  it "slices" do
@@ -490,7 +490,7 @@ describe Hash do
490
490
  h.mkdir_p(["a", "b", "whoa"]).should == {"a"=>{"b"=>{"c"=>{}, "whoa"=>{}}}}
491
491
 
492
492
  lambda {
493
- h.tree.should == ["a", " b", " c", " whoa"]
493
+ h.tree.should =~ ["a", " b", " c", " whoa"]
494
494
  }.should_not raise_error
495
495
  end
496
496
 
@@ -529,7 +529,7 @@ describe Binding do
529
529
  a = 1
530
530
  b = proc { a }
531
531
 
532
- b.binding.keys.should == [:a, :b]
532
+ b.binding.keys.should =~ [:a, :b]
533
533
  b.binding.keys.should == b.binding.local_variables
534
534
 
535
535
  b.binding[:a].should == 1
@@ -592,13 +592,13 @@ describe "truthiness" do
592
592
  {
593
593
  # truthy things
594
594
  true => [
595
- "yes", "on", "1", "Enabled", 1, 1.7, :blah, true, [1,2,3], Enumerator.new([1,2,3], :each),
595
+ "yes", "on", "1", "Enabled", 1, 1.7, :blah, true, [1,2,3], [1,2,3].to_enum,
596
596
  1938389127239847129803741980237498012374,
597
597
  ],
598
598
 
599
599
  # untruthy things
600
600
  false => [
601
- "", " ", "asdf", 0, 0.0, false, nil, [], Enumerator.new([], :each),
601
+ "", " ", "asdf", 0, 0.0, false, nil, [], [].to_enum,
602
602
  ]
603
603
  }.each do |truthiness, objs|
604
604
  objs.each { |obj| obj.truthy?.should == truthiness }
@@ -0,0 +1,29 @@
1
+ require 'epitools/core_ext/array'
2
+
3
+ describe "Array#histogram" do
4
+
5
+ it "does 1..10" do
6
+ nums = (1..10).to_a
7
+ nums.histogram(2).should == [ 5, 5 ]
8
+ nums.histogram(5).should == [ 2, 2, 2, 2, 2 ]
9
+ end
10
+
11
+ it "does -10..10" do
12
+ nums = (-9..10).to_a
13
+ nums.histogram(2).should == [ 10, 10 ]
14
+ end
15
+
16
+ it "does floats" do
17
+ nums = [0.12, 1.0, 2.2, 3.5, 4.7, 5.9, 6.6, 7.777, 8.898]
18
+ nums.histogram(3).should == [3,3,3]
19
+ end
20
+
21
+ it "does ranges" do
22
+ nums = (0..9).to_a
23
+ nums.histogram(2, ranges: true).should == {
24
+ 0.0...4.5 => 5,
25
+ 4.5...9.0 => 5
26
+ }
27
+ end
28
+
29
+ end
@@ -14,7 +14,7 @@ Spork.prefork do
14
14
 
15
15
  require 'rspec'
16
16
  require 'epitools'
17
-
17
+
18
18
  Rspec.configure do |c|
19
19
  c.mock_with :rspec
20
20
  end
metadata CHANGED
@@ -1,32 +1,32 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: epitools
3
3
  version: !ruby/object:Gem::Version
4
+ version: 0.5.20
4
5
  prerelease:
5
- version: 0.5.19
6
6
  platform: ruby
7
7
  authors:
8
8
  - epitron
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-08 00:00:00.000000000 Z
12
+ date: 2013-02-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- type: :development
15
+ name: rspec
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ! '>='
19
+ - - '>='
20
20
  - !ruby/object:Gem::Version
21
21
  version: '0'
22
+ type: :development
22
23
  prerelease: false
23
24
  version_requirements: !ruby/object:Gem::Requirement
24
25
  none: false
25
26
  requirements:
26
- - - ! '>='
27
+ - - '>='
27
28
  - !ruby/object:Gem::Version
28
29
  version: '0'
29
- name: rspec
30
30
  description: Miscellaneous utility libraries to make my life easier.
31
31
  email: chris@ill-logic.com
32
32
  executables: []
@@ -90,6 +90,7 @@ files:
90
90
  - spec/colored_spec.rb
91
91
  - spec/core_ext_spec.rb
92
92
  - spec/ezdb_spec.rb
93
+ - spec/histogram_spec.rb
93
94
  - spec/iter_spec.rb
94
95
  - spec/lcs_spec.rb
95
96
  - spec/numwords_spec.rb
@@ -114,18 +115,18 @@ require_paths:
114
115
  required_ruby_version: !ruby/object:Gem::Requirement
115
116
  none: false
116
117
  requirements:
117
- - - ! '>='
118
+ - - '>='
118
119
  - !ruby/object:Gem::Version
119
120
  version: '0'
120
121
  required_rubygems_version: !ruby/object:Gem::Requirement
121
122
  none: false
122
123
  requirements:
123
- - - ! '>='
124
+ - - '>='
124
125
  - !ruby/object:Gem::Version
125
126
  version: '0'
126
127
  requirements: []
127
128
  rubyforge_project:
128
- rubygems_version: 1.8.24
129
+ rubygems_version: 1.8.25
129
130
  signing_key:
130
131
  specification_version: 3
131
132
  summary: Not utils... METILS!