benschwarz-smoke 0.3.6 → 0.3.7

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.markdown CHANGED
@@ -70,13 +70,15 @@ Integrity [is running for smoke](http://integrity.ffolio.net/smoke)
70
70
 
71
71
  ### TODO (working on, just mental notes)
72
72
 
73
- * Implement a disaptch / request method that will actually thread property (event-machine)
73
+ * Secrets
74
74
  * Checkout experimental fakeweb version to stub out the yql specs
75
75
 
76
76
  #### Later / maybe
77
- * Allow for sources to explicitly set the content type being returned for those stupid content providers
78
77
  * YQL w/oAuth
79
78
  * YQL Subqueries?
79
+ * Implement basic auth for sources
80
+ * Allow for sources to explicitly set the content type being returned for those stupid content providers
81
+
80
82
 
81
83
  #### For wiki pages (docs, later)
82
84
  * How to use `path`
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
+ :patch: 7
2
3
  :major: 0
3
4
  :minor: 3
4
- :patch: 6
data/lib/smoke.rb CHANGED
@@ -1,9 +1,9 @@
1
- require 'rubygems'
1
+ require 'zlib'
2
2
  require 'open-uri'
3
3
  require 'logger'
4
- require 'json'
5
4
  require 'crack'
6
5
  require 'simple-rss'
6
+ require 'json'
7
7
 
8
8
  $:<< File.join(File.dirname(__FILE__))
9
9
 
@@ -13,7 +13,10 @@ require 'core_ext/hash.rb'
13
13
  module Smoke
14
14
  class << self
15
15
  @@active_sources = {}
16
- attr_reader :active_sources
16
+ @@config = {
17
+ :enable_logging => true,
18
+ :user_agent => "Ruby/#{RUBY_VERSION}/Smoke"
19
+ }
17
20
 
18
21
  # Access registered smoke source instances
19
22
  #
@@ -58,7 +61,25 @@ module Smoke
58
61
  # Smoke.log.error "message"
59
62
  # Smoke.log.warn "message"
60
63
  def log
61
- @@log ||= Logger.new($stdout)
64
+ @@log ||= Logger.new(config[:enable_logging] ? $stdout : "/dev/null")
65
+ end
66
+
67
+ # Set any configurable options
68
+ #
69
+ # Smoke.configure do |c|
70
+ # c[:user_agent] = "Some other site"
71
+ # end
72
+ #
73
+ def configure(&block)
74
+ yield @@config
75
+ end
76
+
77
+ # Access configuration options
78
+ #
79
+ # Smoke.config[:option_name]
80
+ # => true
81
+ def config
82
+ @@config
62
83
  end
63
84
 
64
85
  def yql(name, &block); Smoke::Source::YQL.new(name, &block); end
data/lib/smoke/origin.rb CHANGED
@@ -34,8 +34,9 @@ module Smoke
34
34
  end
35
35
  end
36
36
 
37
- def items=(items) # :nodoc:
38
- @items = items.flatten.map{|i| i.symbolize_keys! }
37
+ def items=(response) # :nodoc:
38
+ @items = [(@path.nil?) ? response : drill(response, *@path)]
39
+ symbolize_keys!
39
40
  transform!
40
41
  end
41
42
 
@@ -73,6 +74,24 @@ module Smoke
73
74
  @transformation << block
74
75
  end
75
76
 
77
+ # Transform must be used inside an `emit` block.
78
+ # It can be used to alter the a single field at a time
79
+ #
80
+ # Usage:
81
+ # emit do
82
+ # transform :name do |name|
83
+ # name.gsub(/\302/, "")
84
+ # end
85
+ # end
86
+ #
87
+ # In quasi-english: The result of the block is returned and set to each
88
+ # of the :name attributes in the result set.
89
+ def transform(name, &block)
90
+ items.each do |item|
91
+ item[name] = yield(item[name]) || item[name]
92
+ end
93
+ end
94
+
76
95
  # Prepare is used when you'd like to provision for
77
96
  # arguments / variables to be set after the source definition.
78
97
  # Eg, create a source definition for twitter, omitting the "username".
@@ -188,6 +207,10 @@ module Smoke
188
207
  @transformation.each{|t| t.call } unless @transformation.nil?
189
208
  end
190
209
 
210
+ def symbolize_keys!
211
+ @items = items.flatten.map{|i| i.symbolize_keys! } if items.respond_to? :flatten
212
+ end
213
+
191
214
  def drill(*path)
192
215
  path.inject(nil) do |obj, pointer|
193
216
  obj = obj.nil? ? pointer : obj[pointer]
data/lib/smoke/request.rb CHANGED
@@ -20,9 +20,14 @@ module Smoke
20
20
 
21
21
  private
22
22
  def dispatch
23
+ opts = {
24
+ "User-Agent" => Smoke.config[:user_agent],
25
+ "Accept-Encoding" => "gzip"
26
+ }
23
27
  Thread.new {
24
- open(@uri, "User-Agent" => "Ruby/#{RUBY_VERSION}/Smoke") do |request|
28
+ open(@uri, opts) do |request|
25
29
  @content_type = request.content_type
30
+ request = Zlib::GzipReader.new(request) if request.content_encoding.include? "gzip"
26
31
  @body = request.read
27
32
  end
28
33
  }.join
@@ -28,7 +28,7 @@ module Smoke
28
28
  protected
29
29
  def dispatch
30
30
  @request = Smoke::Request.new(@url)
31
- self.items = (@path.nil?) ? @request.body : drill(@request.body, *@path)
31
+ self.items = @request.body
32
32
  end
33
33
  end
34
34
  end
@@ -6,7 +6,6 @@ module Smoke
6
6
  #
7
7
  # Usage:
8
8
  # Smoke.join(:delicious, :twitter, :flickr) do
9
- # name :stream
10
9
  # path :photos, :photo
11
10
  # end
12
11
  class Join < Origin # :nodoc:
@@ -63,7 +63,7 @@ module Smoke
63
63
 
64
64
  def dispatch
65
65
  @request = Smoke::Request.new(build_uri)
66
- self.items = [(@path.nil?) ? @request.body : drill(@request.body, *@path)]
66
+ self.items = @request.body
67
67
  end
68
68
 
69
69
  private
@@ -6,6 +6,10 @@ describe Smoke::Origin do
6
6
  emit do
7
7
  rename(:head => :title)
8
8
  sort(:title)
9
+
10
+ transform :title do |title|
11
+ title.gsub(/Animal: /, '')
12
+ end
9
13
  end
10
14
  end
11
15
  end
@@ -43,8 +47,21 @@ describe Smoke::Origin do
43
47
 
44
48
  describe "filtering" do
45
49
  before do
46
- TestSource.source(:keep)
47
- TestSource.source(:discard)
50
+ TestSource.source(:keep) do
51
+ emit do
52
+ transform :head do |head|
53
+ head.gsub(/Animal: /, '')
54
+ end
55
+ end
56
+ end
57
+
58
+ TestSource.source(:discard) do
59
+ emit do
60
+ transform :head do |head|
61
+ head.gsub(/Animal: /, '')
62
+ end
63
+ end
64
+ end
48
65
  end
49
66
 
50
67
  it "should keep items" do
@@ -93,12 +110,18 @@ describe Smoke::Origin do
93
110
  end
94
111
 
95
112
  it "method chaining" do
96
- @source = TestSource.source(:chain)
97
- @source.rename(:head => :header).sort(:header).output.should == [{:header => "Kangaroo"}, {:header => "Platypus"}]
113
+ TestSource.source(:chain) do
114
+ emit do
115
+ transform :head do |head|
116
+ head.gsub(/Animal: /, '')
117
+ end
118
+ end
119
+ end
120
+ Smoke[:chain].rename(:head => :header).sort(:header).output.should == [{:header => "Kangaroo"}, {:header => "Platypus"}]
98
121
  end
99
122
 
100
123
  it "should softly error when attempting to sort on a key that doesn't exist" do
101
- TestSource.source(:chain).sort(:header).should_not raise_error("NoMethodError")
124
+ Smoke[:chain].sort(:header).should_not raise_error("NoMethodError")
102
125
  end
103
126
 
104
127
  describe "preperation" do
@@ -114,51 +137,65 @@ describe Smoke::Origin do
114
137
  lambda { @source.prepare }.should raise_error
115
138
  lambda { @source.prepare {} }.should_not raise_error
116
139
  end
117
-
118
- describe "call order" do
119
- before :all do
120
- @url = "http://domain.tld/benschwarz/feed"
121
- FakeWeb.register_uri(@url, :response => File.join(SPEC_DIR, 'supports', 'flickr-photo.json'))
122
-
123
- Smoke.data :feed_preperation_call_order do
124
- prepare do
125
- url "http://domain.tld/#{username}/feed"
126
- end
127
-
128
- path :photos, :photo
140
+ end
141
+
142
+ describe "call order" do
143
+ before :all do
144
+ @url = "http://domain.tld/benschwarz/feed"
145
+ FakeWeb.register_uri(@url, :response => File.join(SPEC_DIR, 'supports', 'flickr-photo.json'))
146
+
147
+ Smoke.data :feed_preperation_call_order do
148
+ prepare do
149
+ url "http://domain.tld/#{username}/feed"
129
150
  end
151
+
152
+ path :photos, :photo
153
+ end
154
+ end
155
+
156
+ describe "before setting variables" do
157
+ it "should fail" do
158
+ lambda { Smoke[:feed_preperation_call_order].output }.should raise_error(NameError)
159
+ end
160
+ end
161
+
162
+ describe "setting abstract properties" do
163
+ it "should not respond to a property that hasn't been set" do
164
+ lambda { Smoke[:feed_preperation_call_order].abstract }.should raise_error(NoMethodError)
130
165
  end
131
166
 
132
- describe "before setting variables" do
133
- it "should fail" do
134
- lambda { Smoke[:feed_preperation_call_order].output }.should raise_error(NameError)
135
- end
167
+ it "should allow setting a property" do
168
+ lambda { Smoke[:feed_preperation_call_order].abstract(:value) }.should_not raise_error(NoMethodError)
169
+ Smoke[:feed_preperation_call_order].abstract.should == :value
136
170
  end
137
171
 
138
- describe "setting abstract properties" do
139
- it "should not respond to a property that hasn't been set" do
140
- lambda { Smoke[:feed_preperation_call_order].abstract }.should raise_error(NoMethodError)
141
- end
142
-
143
- it "should allow setting a property" do
144
- lambda { Smoke[:feed_preperation_call_order].abstract(:value) }.should_not raise_error(NoMethodError)
145
- Smoke[:feed_preperation_call_order].abstract.should == :value
146
- end
147
-
148
- it "should chain the source when setting a property" do
149
- Smoke[:feed_preperation_call_order].abstract(:value).should be_an_instance_of(Smoke::Source::Data)
150
- end
172
+ it "should chain the source when setting a property" do
173
+ Smoke[:feed_preperation_call_order].abstract(:value).should be_an_instance_of(Smoke::Source::Data)
174
+ end
175
+ end
176
+
177
+ describe "after setting variables" do
178
+ it "should output successfully" do
179
+ lambda { Smoke[:feed_preperation_call_order].username("benschwarz").output }.should_not raise_error
151
180
  end
152
181
 
153
- describe "after setting variables" do
154
- it "should output successfully" do
155
- lambda { Smoke[:feed_preperation_call_order].username("benschwarz").output }.should_not raise_error
156
- end
157
-
158
- it "should have used the correct url" do
159
- Smoke[:feed_preperation_call_order].request.uri.should == @url
160
- end
182
+ it "should have used the correct url" do
183
+ Smoke[:feed_preperation_call_order].request.uri.should == @url
161
184
  end
162
185
  end
163
186
  end
187
+
188
+ describe "trasformations" do
189
+ it "should respond to emit" do
190
+ Smoke[:test].should respond_to(:emit)
191
+ end
192
+
193
+ it "should respond to transform" do
194
+ Smoke[:test].should respond_to(:transform)
195
+ end
196
+
197
+ it "should have at least one transformation" do
198
+ Smoke[:test].transformation.size.should == 1
199
+ end
200
+ end
164
201
  end
@@ -22,13 +22,33 @@ describe Smoke::Request do
22
22
 
23
23
  it "should be a pure ruby array response" do
24
24
  # Temporary real request, fakeweb isn't allowing content_type setting as of writing
25
- @request = Smoke::Request.new("http://query.yahooapis.com/v1/public/yql?q=SELECT%20*%20FROM%20search.web%20WHERE%20query%20=%20'ruby'&format=xml")
26
- @request.body.should be_an_instance_of(Hash)
25
+ request = Smoke::Request.new("http://query.yahooapis.com/v1/public/yql?q=SELECT%20*%20FROM%20search.web%20WHERE%20query%20=%20'ruby'&format=xml")
26
+ request.body.should be_an_instance_of(Hash)
27
27
  end
28
28
 
29
29
  it "should be a raw string response" do
30
- @request = Smoke::Request.new(@url, :raw_response)
31
- @request.body.should be_an_instance_of(String)
30
+ request = Smoke::Request.new(@url, :raw_response)
31
+ request.body.should be_an_instance_of(String)
32
+ end
33
+
34
+ describe "gzipped responses" do
35
+ before do
36
+ # class Stream < StringIO
37
+ # def close; rewind; end
38
+ # end
39
+ # output = Stream.new
40
+ # gz = Zlib::GzipWriter.new(output)
41
+ # gz.write(File.read(@gzip_response))
42
+ # gz.close
43
+ #@gzip_response = File.join(SPEC_DIR, 'supports', 'gzip.response')
44
+ #FakeWeb.register_uri(@url, :file => @gzip_response)
45
+ end
46
+
47
+ it "should transparently handle a gzipped response" do
48
+ pending
49
+ request = Smoke::Request.new(@url)
50
+ request.body.should == "gzip_response"
51
+ end
32
52
  end
33
53
 
34
54
  describe "http redirects" do
data/spec/smoke_spec.rb CHANGED
@@ -17,4 +17,31 @@ describe Smoke do
17
17
  Smoke[:b].should be_an_instance_of(Smoke::Origin)
18
18
  end
19
19
  end
20
+
21
+ describe "configuration" do
22
+ it "should be configurable" do
23
+ Smoke.should respond_to(:configure)
24
+ end
25
+
26
+ it "should be accessible" do
27
+ Smoke.should respond_to(:config)
28
+ end
29
+
30
+ it "should take a block and be retrievable" do
31
+ Smoke.configure {|c| c[:spec] = true }
32
+ Smoke.config[:spec].should be_true
33
+ end
34
+
35
+ describe "default configurations" do
36
+ it "should have at least one default configuration" do
37
+ Smoke.config.keys.should_not be_empty
38
+ end
39
+
40
+ it "should allow overwriting default configurations" do
41
+ key = Smoke.config.keys.first
42
+ Smoke.configure {|c| c[key] = true }
43
+ Smoke.config[key].should be_true
44
+ end
45
+ end
46
+ end
20
47
  end
data/spec/spec_helper.rb CHANGED
@@ -13,4 +13,8 @@ $:<< SPEC_DIR
13
13
  require 'smoke'
14
14
 
15
15
  require 'supports/mayo.rb'
16
- require 'supports/test_source.rb'
16
+ require 'supports/test_source.rb'
17
+
18
+ Smoke.configure do |c|
19
+ c[:enable_logging] = false
20
+ end
@@ -2,8 +2,8 @@ module TestSource
2
2
  def self.source(name, &block)
3
3
  source = Smoke::Origin.new(name, &block || Proc.new {})
4
4
  source.items = [
5
- {:head => "Platypus"},
6
- {:head => "Kangaroo"}
5
+ {:head => "Animal: Platypus"},
6
+ {:head => "Animal: Kangaroo"}
7
7
  ]
8
8
  return source
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: benschwarz-smoke
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.6
4
+ version: 0.3.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Schwarz
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-09 00:00:00 -07:00
12
+ date: 2009-06-15 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -100,7 +100,7 @@ requirements: []
100
100
  rubyforge_project:
101
101
  rubygems_version: 1.2.0
102
102
  signing_key:
103
- specification_version: 3
103
+ specification_version: 2
104
104
  summary: smoke is a DSL that allows you to take data from YQL, RSS / Atom
105
105
  test_files: []
106
106