picky 2.2.0 → 2.2.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.
@@ -13,14 +13,16 @@
13
13
  # will generate an example <tt>project_name/app/application.rb</tt> file for you
14
14
  # with some example code inside.
15
15
  #
16
- # == Index::Memory.new(name, source)
16
+ # == Index::Memory.new(name)
17
17
  #
18
18
  # Next, define where your data comes from. You use the <tt>Index::Memory.new</tt> method for that:
19
- # my_index = Index::Memory.new :some_index_name, some_source
19
+ # my_index = Index::Memory.new :some_index_name
20
20
  # You give the index a name (or identifier), and a source (see Sources), where its data comes from. Let's do that:
21
21
  # class MyGreatSearch < Application
22
22
  #
23
- # books = Index::Memory.new :books, Sources::CSV.new(:title, :author, :isbn, file:'app/library.csv')
23
+ # books = Index::Memory.new :books do
24
+ # source Sources::CSV.new(:title, :author, :isbn, file:'app/library.csv')
25
+ # end
24
26
  #
25
27
  # end
26
28
  # Now we have an index <tt>books</tt>.
@@ -29,7 +31,7 @@
29
31
  #
30
32
  # Note that a Redis index is also available: Index::Redis.new.
31
33
  #
32
- # == index_instance.define_category(identifier, options = {})
34
+ # == category(identifier, options = {})
33
35
  #
34
36
  # Picky needs us to define categories on the data.
35
37
  #
@@ -39,8 +41,10 @@
39
41
  # Let's go ahead and define a category:
40
42
  # class MyGreatSearch < Application
41
43
  #
42
- # books = Index::Memory.new :books, Sources::CSV.new(:title, :author, :isbn, file:'app/library.csv')
43
- # books.define_category :title
44
+ # books = Index::Memory.new :books do
45
+ # source Sources::CSV.new(:title, :author, :isbn, file:'app/library.csv')
46
+ # category :title
47
+ # end
44
48
  #
45
49
  # end
46
50
  # Now we could already run the indexer:
@@ -52,7 +56,7 @@
52
56
  #
53
57
  # == Search.new(*indexes, options = {})
54
58
  #
55
- # We need somebody who asks the index (a Query object, also see http://github.com/floere/picky/wiki/Queries-Configuration). That works like this:
59
+ # We need somebody who asks the index (a Query object, also see http://github.com/floere/picky/wiki/Queries-Configuration):
56
60
  # books_search = Search.new books
57
61
  #
58
62
  # Now we have somebody we can ask about the index. But no external interface.
@@ -64,8 +68,10 @@
64
68
  # In full glory:
65
69
  # class MyGreatSearch < Application
66
70
  #
67
- # books = index :books, Sources::CSV.new(:title, :author, :isbn, file:'app/library.csv')
68
- # books.define_category :title
71
+ # books = index :books do
72
+ # source Sources::CSV.new(:title, :author, :isbn, file:'app/library.csv')
73
+ # category :title
74
+ # end
69
75
  #
70
76
  # route %r{^/books$} => Search.new(books)
71
77
  #
@@ -82,19 +88,19 @@
82
88
  #
83
89
  # Maybe you don't find everything. We need to process the data before it goes into the index.
84
90
  #
85
- # == default_indexing(options = {})
91
+ # == indexing(options = {})
86
92
  #
87
- # That's what the <tt>default_indexing</tt> method is for:
88
- # default_indexing options
93
+ # That's what the <tt>indexing</tt> method is for:
94
+ # indexing options
89
95
  # Read more about the options here: http://github.com/floere/picky/wiki/Indexing-configuration
90
96
  #
91
97
  # Same thing with the search text – we need to process that as well.
92
98
  #
93
- # == default_querying(options = {})
99
+ # == searching(options = {})
94
100
  #
95
- # Analog to the default_indexing method, we use the <tt>default_querying</tt> method.
96
- # default_querying options
97
- # Read more about the options here: http://github.com/floere/picky/wiki/Querying-Configuration
101
+ # Analog to the indexing method, we use the <tt>searching</tt> method.
102
+ # searching options
103
+ # Read more about the options here: http://github.com/floere/picky/wiki/Searching-Configuration
98
104
  #
99
105
  # And that's all there is. It's incredibly powerful though, as you can combine, weigh, refine to the max.
100
106
  #
@@ -109,35 +115,37 @@
109
115
  # Our example, fully fleshed out with indexing, querying, and weights:
110
116
  # class MyGreatSearch < Application
111
117
  #
112
- # default_indexing removes_characters: /[^a-zA-Z0-9\.]/,
113
- # stopwords: /\b(and|or|in|on|is|has)\b/,
114
- # splits_text_on: /\s/,
115
- # removes_characters_after_splitting: /\./,
116
- # substitutes_characters_with: CharacterSubstituters::WestEuropean.new,
117
- # normalizes_words: [
118
- # [/(.*)hausen/, 'hn'],
119
- # [/\b(\w*)str(eet)?/, 'st']
120
- # ]
121
- #
122
- # default_querying removes_characters: /[^a-zA-Z0-9\s\/\-\,\&\"\~\*\:]/,
123
- # stopwords: /\b(and|the|of|it|in|for)\b/,
124
- # splits_text_on: /[\s\/\-\,\&]+/,
125
- # removes_characters_after_splitting: /\./,
126
- # substitutes_characters_with: CharacterSubstituters::WestEuropean.new,
127
- # maximum_tokens: 4
128
- #
129
- # books = Index::Memory.new :books, Sources::CSV.new(:title, :author, :isbn, file:'app/library.csv')
130
- # books.define_category :title,
131
- # qualifiers: [:t, :title, :titre],
132
- # partial: Partial::Substring.new(:from => 1),
133
- # similarity: Similarity::DoubleMetaphone.new(2)
134
- # books.define_category :author,
135
- # partial: Partial::Substring.new(:from => -2)
136
- # books.define_category :isbn
137
- #
138
- # options = { :weights => { [:title, :author] => +3, [:author, :title] => -1 } }
139
- #
140
- # route %r{^/books$} => Search.new(books, options)
118
+ # indexing removes_characters: /[^a-zA-Z0-9\.]/,
119
+ # stopwords: /\b(and|or|in|on|is|has)\b/,
120
+ # splits_text_on: /\s/,
121
+ # removes_characters_after_splitting: /\./,
122
+ # substitutes_characters_with: CharacterSubstituters::WestEuropean.new,
123
+ # normalizes_words: [
124
+ # [/(.*)hausen/, 'hn'],
125
+ # [/\b(\w*)str(eet)?/, 'st']
126
+ # ]
127
+ #
128
+ # searching removes_characters: /[^a-zA-Z0-9\s\/\-\,\&\"\~\*\:]/,
129
+ # stopwords: /\b(and|the|of|it|in|for)\b/,
130
+ # splits_text_on: /[\s\/\-\,\&]+/,
131
+ # removes_characters_after_splitting: /\./,
132
+ # substitutes_characters_with: CharacterSubstituters::WestEuropean.new,
133
+ # maximum_tokens: 4
134
+ #
135
+ # books = Index::Memory.new :books do
136
+ # source Sources::CSV.new(:title, :author, :isbn, file:'app/library.csv')
137
+ # category :title,
138
+ # qualifiers: [:t, :title, :titre],
139
+ # partial: Partial::Substring.new(:from => 1),
140
+ # similarity: Similarity::DoubleMetaphone.new(2)
141
+ # category :author,
142
+ # partial: Partial::Substring.new(:from => -2)
143
+ # category :isbn
144
+ # end
145
+ #
146
+ # route %r{^/books$} => Search.new(books) do
147
+ # boost [:title, :author] => +3, [:author, :title] => -1
148
+ # end
141
149
  #
142
150
  # end
143
151
  # That's actually already a full-blown Picky App!
@@ -15,15 +15,15 @@ module Index
15
15
  #
16
16
  # === Parameters
17
17
  # * name: A name that will be used for the index directory and in the Picky front end.
18
- # * source: Where the data comes from, e.g. Sources::CSV.new(...). Optional, can be defined in the block using #source.
19
18
  #
20
19
  # === Options
20
+ # * source: Where the data comes from, e.g. Sources::CSV.new(...). Optional, can be defined in the block using #source.
21
21
  # * result_identifier: Use if you'd like a different identifier/name in the results than the name of the index.
22
22
  # * after_indexing: As of this writing only used in the db source. Executes the given after_indexing as SQL after the indexing process.
23
- # * tokenizer: The tokenizer to use for this index.
23
+ # * tokenizer: The tokenizer to use for this index. Optional, can be defined in the block using #indexing.
24
24
  #
25
25
  # Examples:
26
- # my_index = Index::Memory.new(:my_index, some_source) do
26
+ # my_index = Index::Memory.new(:my_index, source: some_source) do
27
27
  # category :bla
28
28
  # end
29
29
  #
@@ -64,10 +64,10 @@ module Index
64
64
  raise ArgumentError.new(<<-NAME
65
65
 
66
66
 
67
- The index identifier (you gave "#{name}") for Index::Memory/Index::Redis should be a String/Symbol,
67
+ The index identifier (you gave "#{name}") for Index::Memory/Index::Redis should be a Symbol/String,
68
68
  Examples:
69
- Index::Memory.new(:my_cool_index, ...) # Recommended
70
- Index::Redis.new("a-redis-index", ...)
69
+ Index::Memory.new(:my_cool_index) # Recommended
70
+ Index::Redis.new("a-redis-index")
71
71
  NAME
72
72
 
73
73
 
@@ -121,12 +121,12 @@ INDEX
121
121
 
122
122
  # Define an index tokenizer on the index.
123
123
  #
124
- # Parameters are the exact same as for the default_indexing.
124
+ # Parameters are the exact same as for indexing.
125
125
  #
126
- def define_indexing options = {}
126
+ def indexing options = {}
127
127
  internal_indexing.define_indexing options
128
128
  end
129
- alias indexing define_indexing
129
+ alias define_indexing indexing
130
130
 
131
131
  # Define a source on the index.
132
132
  #
@@ -134,10 +134,10 @@ INDEX
134
134
  # anything responding to #each and returning objects that
135
135
  # respond to id and the category names (or the category from option).
136
136
  #
137
- def define_source source
137
+ def source source
138
138
  internal_indexing.define_source source
139
139
  end
140
- alias source define_source
140
+ alias define_source source
141
141
 
142
142
  # Defines a searchable category on the index.
143
143
  #
@@ -152,7 +152,7 @@ INDEX
152
152
  # * source: Use a different source than the index uses. If you think you need that, there might be a better solution to your problem. Please post to the mailing list first with your application.rb :)
153
153
  # * from: Take the data from the data category with this name. Example: You have a source Sources::CSV.new(:title, file:'some_file.csv') but you want the category to be called differently. The you use from: define_category(:similar_title, :from => :title).
154
154
  #
155
- def define_category category_name, options = {}
155
+ def category category_name, options = {}
156
156
  category_name = category_name.to_sym
157
157
 
158
158
  indexing_category = internal_indexing.define_category category_name, options
@@ -162,11 +162,10 @@ INDEX
162
162
 
163
163
  self
164
164
  end
165
- alias category define_category
165
+ alias define_category category
166
166
 
167
- # HIGHLY EXPERIMENTAL Try if you feel "beta" ;)
168
- #
169
- # Make this category range searchable with a fixed range. If you need other ranges, define another category with a different range value.
167
+ # Make this category range searchable with a fixed range. If you need other
168
+ # ranges, define another category with a different range value.
170
169
  #
171
170
  # Example:
172
171
  # You have data values inside 1..100, and you want to have Picky return
@@ -174,22 +173,27 @@ INDEX
174
173
  # 45, 46, or 47.2, 48.9, in a range of 2 around 47, so (45..49).
175
174
  #
176
175
  # Then you use:
177
- # my_index.define_ranged_category :values_inside_1_100, 2
176
+ # ranged_category :values_inside_1_100, 2
178
177
  #
179
178
  # Optionally, you give it a precision value to reduce the error margin
180
179
  # around 47 (Picky is a bit liberal).
181
- # my_index.define_ranged_category :values_inside_1_100, 2, precision: 5
180
+ # Index::Memory.new :range do
181
+ # ranged_category :values_inside_1_100, 2, precision: 5
182
+ # end
182
183
  #
183
184
  # This will force Picky to maximally be wrong 5% of the given range value
184
185
  # (5% of 2 = 0.1) instead of the default 20% (20% of 2 = 0.4).
185
186
  #
186
- # We suggest not to use much more than 5 as a higher precision is more performance intensive for less and less precision gain.
187
+ # We suggest not to use much more than 5 as a higher precision is more
188
+ # performance intensive for less and less precision gain.
187
189
  #
188
190
  # == Protip 1
189
191
  #
190
192
  # Create two ranged categories to make an area search:
191
- # index.define_ranged_category :x, 1
192
- # index.define_ranged_category :y, 1
193
+ # Index::Memory.new :area do
194
+ # ranged_category :x, 1
195
+ # ranged_category :y, 1
196
+ # end
193
197
  #
194
198
  # Search for it using for example:
195
199
  # x:133, y:120
@@ -223,7 +227,7 @@ INDEX
223
227
  # * precision: Default is 1 (20% error margin, very fast), up to 5 (5% error margin, slower) makes sense.
224
228
  # * ... all options of #define_category.
225
229
  #
226
- def define_ranged_category category_name, range, options = {}
230
+ def ranged_category category_name, range, options = {}
227
231
  precision = options[:precision] || 1
228
232
 
229
233
  options = { partial: Partial::None.new }.merge options
@@ -233,17 +237,18 @@ INDEX
233
237
  Internals::Indexed::Wrappers::Category::Location.install_on indexed_category, range, precision
234
238
  end
235
239
  end
236
- alias ranged_category define_ranged_category
240
+ alias define_ranged_category ranged_category
237
241
 
238
242
  # HIGHLY EXPERIMENTAL Not correctly working yet. Try it if you feel "beta".
239
243
  #
240
- # Also a range search see #define_ranged_category, but on the earth's surface.
244
+ # Also a range search see #ranged_category, but on the earth's surface.
241
245
  #
242
246
  # Parameters:
243
- # * name: The name as used in #define_category.
247
+ # * lat_name: The latitude's name as used in #define_category.
248
+ # * lng_name: The longitude's name as used in #define_category.
244
249
  # * radius: The distance (in km) around the query point which we search for results.
245
250
  #
246
- # Note: Picky uses a square, not a circle. We hope that's ok for most usages.
251
+ # Note: Picky uses a square, not a circle. That should be ok for most usages.
247
252
  #
248
253
  # -----------------------------
249
254
  # | |
@@ -261,23 +266,40 @@ INDEX
261
266
  #
262
267
  # Options
263
268
  # * precision: Default 1 (20% error margin, very fast), up to 5 (5% error margin, slower) makes sense.
264
- # * from: The data category to take the data for this category from.
269
+ # * lat_from: The data category to take the data for the latitude from.
270
+ # * lng_from: The data category to take the data for the longitude from.
265
271
  #
266
- # TODO Redo. Will have to write a wrapper that combines two categories that are indexed simultaneously.
272
+ # TODO Will have to write a wrapper that combines two categories that are
273
+ # indexed simultaneously, since lat/lng are correlated.
267
274
  #
268
- def define_map_location name, radius, options = {} # :nodoc:
269
- # The radius is given as if all the locations were on the equator.
275
+ def geo_categories lat_name, lng_name, radius, options = {} # :nodoc:
276
+
277
+ # Extract lat/lng specific options.
270
278
  #
271
- # TODO Need to recalculate since not many locations are on the equator ;) This is just a prototype.
279
+ lat_from = options.delete :lat_from
280
+ lng_from = options.delete :lng_from
281
+
282
+ # One can be a normal ranged_category.
283
+ #
284
+ ranged_category lat_name, radius*0.00898312, options.merge(from: lat_from)
285
+
286
+ # The other needs to adapt the radius depending on the one.
287
+ #
288
+ # Depending on the latitude, the radius of the longitude
289
+ # needs to enlarge, the closer we get to the pole.
290
+ #
291
+ # In our simplified case, the radius is given as if all the
292
+ # locations were on the 45 degree line.
272
293
  #
273
294
  # This calculates km -> longitude (degrees).
274
295
  #
275
- # A degree on the equator is equal to ~111,319.9 meters.
276
- # So a km on the equator is equal to 0.00898312 degrees.
296
+ # A degree on the 45 degree line is equal to ~222.6398 km.
297
+ # So a km on the 45 degree line is equal to 0.01796624 degrees.
277
298
  #
278
- define_ranged_category name, radius * 0.00898312, options
299
+ ranged_category lng_name, radius*0.01796624, options.merge(from: lng_from)
300
+
279
301
  end
280
- alias map_location define_map_location
302
+ alias define_geo_categories geo_categories
281
303
  end
282
304
 
283
305
  end
@@ -2,8 +2,6 @@ module Internals
2
2
 
3
3
  module Indexed # :nodoc:all
4
4
 
5
- # TODO Rewrite.
6
- #
7
5
  # A Bundle is a number of indexes
8
6
  # per [index, category] combination.
9
7
  #
@@ -105,8 +105,6 @@ module Internals
105
105
  # (Also none of the categories matched, but the ignore unassigned
106
106
  # tokens option is true)
107
107
  #
108
- # TODO Could use Combinations class here and remove the inject.
109
- #
110
108
  def possible_for token, preselected_categories = nil
111
109
  possible = (preselected_categories || possible_categories(token)).inject([]) do |combinations, category|
112
110
  combination = category.combination_for token
@@ -12,8 +12,6 @@ module Internals
12
12
  :analyze,
13
13
  :to => :categories
14
14
 
15
- # TODO Externalize?
16
- #
17
15
  def initialize name, options = {}
18
16
  @name = name
19
17
 
@@ -24,8 +22,6 @@ module Internals
24
22
  @categories = Categories.new ignore_unassigned_tokens: ignore_unassigned_tokens
25
23
  end
26
24
 
27
- # TODO Doc. Externalize?
28
- #
29
25
  def define_category category_name, options = {}
30
26
  options = default_category_options.merge options
31
27
 
@@ -4,15 +4,11 @@ module Internals
4
4
  #
5
5
  module Indexed
6
6
 
7
- # TODO Spec
8
- #
9
7
  module Wrappers
10
8
 
11
9
  # This index combines an exact and partial index.
12
10
  # It serves to order the results such that exact hits are found first.
13
11
  #
14
- # TODO Need to use the right subtokens. Bake in?
15
- #
16
12
  class ExactFirst < Indexed::Bundle::Base
17
13
 
18
14
  delegate :similar,
@@ -42,8 +38,6 @@ module Internals
42
38
  new index_or_category
43
39
  end
44
40
  end
45
- # TODO Do not extract categories!
46
- #
47
41
  def self.wrap_each_of categories
48
42
  categories.categories.collect! { |category| new(category) }
49
43
  end
@@ -6,8 +6,6 @@ module Indexers
6
6
  #
7
7
  # Note: It is called serial since it indexes each
8
8
  #
9
- # FIXME Giving the serial a category would be enough, since it already contains an index!
10
- #
11
9
  class Serial < Base
12
10
 
13
11
  attr_reader :category
@@ -24,22 +22,13 @@ module Indexers
24
22
  @tokenizer ||= category.tokenizer
25
23
  end
26
24
 
25
+ # Harvest the data from the source, tokenize,
26
+ # and write to an intermediate "prepared index" file.
27
+ #
27
28
  def process
28
29
  comma = ?,
29
30
  newline = ?\n
30
31
 
31
- # TODO Move open to config?
32
- #
33
- # @category.prepared_index do |file|
34
- # source.harvest(@index, @category) do |indexed_id, text|
35
- # tokenizer.tokenize(text).each do |token_text|
36
- # next unless token_text
37
- # file.buffer indexed_id << comma << token_text << newline
38
- # end
39
- # file.write_maybe
40
- # end
41
- # end
42
- #
43
32
  local_tokenizer = tokenizer
44
33
  category.prepared_index_file do |file|
45
34
  result = []
@@ -3,26 +3,26 @@
3
3
  module Internals
4
4
 
5
5
  module Indexing # :nodoc:all
6
-
6
+
7
7
  module Bundle
8
-
9
- # The memory version dumps its generated indexes to disk
10
- # (mostly JSON) to load them into memory on startup.
8
+
9
+ # The Redis version dumps its generated indexes to
10
+ # the Redis backend.
11
11
  #
12
12
  class Redis < Base
13
-
13
+
14
14
  attr_reader :backend
15
-
16
- def initialize name, configuration, *args
17
- super name, configuration, *args
18
-
19
- @backend = Internals::Index::Redis.new name, configuration # TODO Needed?
15
+
16
+ def initialize name, category, *args
17
+ super name, category, *args
18
+
19
+ @backend = Internals::Index::Redis.new name, category
20
20
  end
21
-
21
+
22
22
  end
23
-
23
+
24
24
  end
25
-
25
+
26
26
  end
27
-
27
+
28
28
  end
@@ -44,10 +44,12 @@ module Internals
44
44
  # [combination, combination] # of token 3
45
45
  # ]
46
46
  #
47
- def possible_combinations_in type
47
+ def possible_combinations_in index
48
48
  @tokens.inject([]) do |combinations, token|
49
- possible_combinations = token.possible_combinations_in type
49
+ possible_combinations = token.possible_combinations_in index
50
50
 
51
+ # TODO Could move the ignore_unassigned_tokens here!
52
+ #
51
53
  # Note: Optimization for ignoring tokens that allocate to nothing and
52
54
  # can be ignored.
53
55
  # For example in a special search, where "florian" is not
@@ -117,7 +117,7 @@ Case sensitive? #{@case_sensitive ? "Yes." : "-"}
117
117
 
118
118
  # Reject tokens after tokenizing based on the given criteria.
119
119
  #
120
- # Note: Currently only for indexing. TODO Redesign and write for both!
120
+ # Note: Currently only for indexing.
121
121
  #
122
122
  def reject_token_if &condition
123
123
  @reject_condition = condition
@@ -6,8 +6,6 @@ require 'spec_helper'
6
6
  #
7
7
  require File.expand_path '../../../../aux/picky/cli', __FILE__
8
8
 
9
- # TODO Finish this prototype Spec, redesign.
10
- #
11
9
  describe Picky::CLI do
12
10
 
13
11
  describe '.mapping' do
@@ -53,6 +53,15 @@ ERROR
53
53
  context 'unit' do
54
54
  let(:api) { described_class.new :some_index_name, source: some_source }
55
55
 
56
+ describe 'geo_categories' do
57
+ it 'delegates correctly' do
58
+ api.should_receive(:ranged_category).once.with :some_lat, 0.00898312, from: :some_lat_from
59
+ api.should_receive(:ranged_category).once.with :some_lng, 0.01796624, from: :some_lng_from
60
+
61
+ api.geo_categories :some_lat, :some_lng, 1, :lat_from => :some_lat_from, :lng_from => :some_lng_from
62
+ end
63
+ end
64
+
56
65
  describe 'define_source' do
57
66
  it 'delegates to the internal indexing' do
58
67
  indexing = stub :indexing
@@ -11,22 +11,22 @@ describe Internals::Indexed::Wrappers::ExactFirst do
11
11
  end
12
12
 
13
13
  describe "self.wrap" do
14
- context "type" do
15
- # FIXME
16
- #
17
- # it "wraps each category" do
18
- # type = Index::Type.new :type_name
19
- # type.define_category :some_category
20
- #
21
- # Index::Wrappers::ExactFirst.wrap type
22
- #
23
- # type.categories.should be_kind_of(Index::Wrappers::ExactFirst)
24
- # end
25
- it "returns the type" do
26
- type = Internals::Indexed::Index.new :type_name
27
- type.define_category :some_category
14
+ context "index" do
15
+ it "wraps each category" do
16
+ index = Internals::Indexed::Index.new :index_name
17
+ index.define_category :some_category
18
+
19
+ Internals::Indexed::Wrappers::ExactFirst.wrap index
20
+
21
+ index.categories.categories.each do |category|
22
+ category.should be_kind_of(Internals::Indexed::Wrappers::ExactFirst)
23
+ end
24
+ end
25
+ it "returns the index" do
26
+ index = Internals::Indexed::Index.new :index_name
27
+ index.define_category :some_category
28
28
 
29
- described_class.wrap(type).should == type
29
+ described_class.wrap(index).should == index
30
30
  end
31
31
  end
32
32
  context "category" do
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: picky
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 2.2.0
5
+ version: 2.2.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - Florian Hanke
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-04-14 00:00:00 +10:00
13
+ date: 2011-04-15 00:00:00 +10:00
14
14
  default_executable: picky
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency