jeff 0.2.5 → 0.3.0

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.md CHANGED
@@ -1,14 +1,15 @@
1
1
  # Jeff
2
2
 
3
- **Jeff** is a light-weight module that mixes in client behaviour for [Amazon
4
- Web Services (AWS)][aws]. It wraps the HTTP adapter [Excon][excon] and
5
- implements [Signature Version 2][sign].
3
+ **Jeff** is a light-weight module that mixes in client behaviour for
4
+ [Amazon Web Services (AWS)][aws]. It wraps [Excon][excon], parses
5
+ responses with [Nokogiri][nokogiri], and implements [Signature Version
6
+ 2][sign].
6
7
 
7
8
  ![jeff][jeff]
8
9
 
9
10
  ## Usage
10
11
 
11
- Here's a hypothetical client.
12
+ Build a a hypothetical client.
12
13
 
13
14
  ```ruby
14
15
  class Client
@@ -41,13 +42,17 @@ end
41
42
  You should now be able to access the endpoint.
42
43
 
43
44
  ```ruby
44
- client.post query: {},
45
- body: 'data'
45
+ res = client.post query: {},
46
+ body: 'data'
47
+
48
+ puts res.status # => 200
49
+ puts res.body.root # => { 'Foo' => 'Bar' }
46
50
  ```
47
51
 
48
52
  ### Chunked Requests
49
53
 
50
- You can upload large files performantly by passing a proc that delivers chunks.
54
+ You can upload large files performantly by passing a proc that delivers
55
+ chunks.
51
56
 
52
57
  ```ruby
53
58
  file = File.open 'data'
@@ -57,47 +62,13 @@ client.post query: {},
57
62
  request_block: chunker
58
63
  ```
59
64
 
60
- ### Streaming Responses
61
-
62
- Similarly, you can download and parse large files performantly by passing a
63
- block that will receive chunks.
64
-
65
- ```ruby
66
- streamer = ->(chunk, remaining, total) { puts chunk }
67
-
68
- client.get query: {},
69
- response_block: streamer
70
- ```
71
-
72
- ### Instrumentation
73
-
74
- Requests can be instrumented.
75
-
76
- ```ruby
77
- class Logger
78
- def self.instrument(name, params = {})
79
- $stderr.puts name, params
80
- yield if block_given?
81
- end
82
- end
83
-
84
- client.get query: {}, instrumentor: Logger
85
- ```
86
-
87
- ### Miscellaneous
88
-
89
- * HTTP connections are persistent.
90
- * By default, Jeff will retry failed requests 4 times.
91
-
92
- For more detailed configuration options, read [excon][excon].
93
-
94
65
  ## Compatibility
95
66
 
96
- **Jeff** is Ruby 1.9-compatible. It is tested against [MRI 1.9.3 plus JRuby and
97
- Rubinius in 1.9 mode][travis].
67
+ **Jeff** is compatible with [all Ruby 1.9 flavours][travis].
98
68
 
99
- [aws]: http://aws.amazon.com/
100
- [excon]: https://github.com/geemus/excon
101
- [sign]: http://docs.amazonwebservices.com/general/latest/gr/signature-version-2.html
102
- [jeff]: http://f.cl.ly/items/0a3R3J0k1R2f423k1q2l/jeff.jpg
103
- [travis]: http://travis-ci.org/#!/hakanensari/jeff
69
+ [aws]: http://aws.amazon.com/
70
+ [excon]: https://github.com/geemus/excon
71
+ [jeff]: http://f.cl.ly/items/0a3R3J0k1R2f423k1q2l/jeff.jpg
72
+ [nokogiri]: http://nokogiri.org/
73
+ [sign]: http://docs.amazonwebservices.com/general/latest/gr/signature-version-2.html
74
+ [travis]: http://travis-ci.org/#!/hakanensari/jeff
@@ -16,7 +16,8 @@ Gem::Specification.new do |gem|
16
16
  gem.require_paths = ['lib']
17
17
  gem.version = Jeff::VERSION
18
18
 
19
- gem.add_dependency 'excon', '~> 0.14.3'
19
+ gem.add_dependency 'excon', '~> 0.14.0'
20
+ gem.add_dependency 'nokogiri', '~> 1.5'
20
21
  gem.add_development_dependency 'guard-rspec'
21
22
  gem.add_development_dependency 'rake'
22
23
  gem.add_development_dependency 'rspec'
@@ -3,6 +3,7 @@ require 'time'
3
3
  require 'excon'
4
4
 
5
5
  require 'jeff/secret'
6
+ require 'jeff/streamer'
6
7
  require 'jeff/version'
7
8
 
8
9
  module Jeff
@@ -87,9 +88,14 @@ module Jeff
87
88
  # request to Excon.
88
89
  Excon::HTTP_VERBS. each do |method|
89
90
  eval <<-DEF
90
- def #{method}(opts = {}, &block)
91
- opts.update method: :#{method}
92
- connection.request sign opts, &block
91
+ def #{method}(opts = {})
92
+ streamer = Streamer.new
93
+ opts.update method: :#{method},
94
+ response_block: streamer
95
+ res = connection.request sign opts
96
+ res.body = streamer
97
+
98
+ res
93
99
  end
94
100
  DEF
95
101
  end
@@ -0,0 +1,45 @@
1
+ require 'nokogiri'
2
+
3
+ module Jeff
4
+ class Document < Nokogiri::XML::SAX::Document
5
+ def characters(val)
6
+ (node['__content__'] ||= '') << val
7
+ end
8
+
9
+ def end_element(key)
10
+ child = @stack.pop
11
+
12
+ if child.keys == ['__content__']
13
+ child = child['__content__']
14
+ end
15
+
16
+ case node[key]
17
+ when Array
18
+ node[key] << child
19
+ when Hash, String
20
+ node[key] = [node[key], child]
21
+ else
22
+ node[key] = child
23
+ end
24
+ end
25
+
26
+ def start_element(key, attrs = [])
27
+ @stack << {}
28
+ attrs.each { |attr| node.store *attr }
29
+ end
30
+
31
+ def start_document
32
+ @stack = [{}]
33
+ end
34
+
35
+ def root
36
+ @stack.first
37
+ end
38
+
39
+ private
40
+
41
+ def node
42
+ @stack.last
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,22 @@
1
+ require 'jeff/document'
2
+
3
+ module Jeff
4
+ class Streamer
5
+ def initialize
6
+ @parser = Nokogiri::XML::SAX::PushParser.new Document.new
7
+ end
8
+
9
+ def call(chunk, remaining_bytes, total_bytes)
10
+ @parser << chunk.sub(/\n/, '')
11
+ @parser.finish if remaining_bytes == 0
12
+ end
13
+
14
+ def document
15
+ @parser.document
16
+ end
17
+
18
+ def root
19
+ document.root
20
+ end
21
+ end
22
+ end
@@ -1,3 +1,3 @@
1
1
  module Jeff
2
- VERSION = '0.2.5'
2
+ VERSION = '0.3.0'
3
3
  end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ module Jeff
4
+ describe Document do
5
+ let(:io) do
6
+ StringIO.new %{
7
+ <?xml version=\"1.0\" ?>
8
+ <ItemAttributes>
9
+ <Title>Anti-Oedipus</Title>
10
+ <Author>Gilles Deleuze</Author>
11
+ <Author>Felix Guattari</Author>
12
+ <Creator Role="Translator">Robert Hurley</Creator>
13
+ </ItemAttributes>
14
+ }.strip.gsub />\s+</, '><'
15
+ end
16
+
17
+ let(:doc) { described_class.new }
18
+ let(:parser) { Nokogiri::XML::SAX::Parser.new doc }
19
+
20
+ before do
21
+ io.rewind
22
+ parser.parse io
23
+ end
24
+
25
+ describe '#root' do
26
+ subject { doc.root['ItemAttributes'] }
27
+
28
+ it { should be_a Hash }
29
+
30
+ it 'should handle only children' do
31
+ subject['Title'].should eql 'Anti-Oedipus'
32
+ end
33
+
34
+ it 'should hande arrays' do
35
+ subject['Author'].should be_an Array
36
+ end
37
+
38
+ it 'should handle attributes' do
39
+ creator = subject['Creator']
40
+ creator['Role'].should eql 'Translator'
41
+ creator['__content__'].should eql 'Robert Hurley'
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ module Jeff
4
+ describe Streamer do
5
+ let(:streamer) { Streamer.new }
6
+
7
+ let(:xml) do
8
+ %{
9
+ <?xml version="1.0" ?>
10
+ <foo>
11
+ <bar>1</bar>
12
+ </foo>
13
+ }.strip.gsub />\s+</, '><'
14
+ end
15
+
16
+ it 'should parse a stream' do
17
+ bytes_sent = 0
18
+ total_bytes = xml.size
19
+
20
+ xml.scan(/.{1,8}/m).each do |chunk|
21
+ bytes_sent += chunk.size
22
+ streamer.call chunk, total_bytes - bytes_sent, total_bytes
23
+ end
24
+
25
+ streamer.root.should have_key 'foo'
26
+ end
27
+ end
28
+ end
@@ -120,22 +120,18 @@ describe Jeff do
120
120
 
121
121
  Excon::HTTP_VERBS.each do |method|
122
122
  describe "##{method}" do
123
- subject { client.send(method, mock: true).body }
123
+ subject { client.send(method, mock: true).body.root['request'] }
124
124
 
125
125
  before do
126
126
  Excon.stub({ method: method.to_sym }) do |params|
127
- { body: params }
127
+ { body: "<request>#{params[:method]}</request>" }
128
128
  end
129
129
  end
130
130
 
131
131
  after { Excon.stubs.clear }
132
132
 
133
133
  it "should make a #{method.upcase} request" do
134
- subject[:method].should eql method.to_sym
135
- end
136
-
137
- it 'should append a signature' do
138
- subject[:query].should match /.+&Signature=[^&]+$/
134
+ should eql method
139
135
  end
140
136
  end
141
137
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jeff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-06 00:00:00.000000000 Z
12
+ date: 2012-07-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: excon
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 0.14.3
21
+ version: 0.14.0
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +26,23 @@ dependencies:
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- version: 0.14.3
29
+ version: 0.14.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: nokogiri
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '1.5'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '1.5'
30
46
  - !ruby/object:Gem::Dependency
31
47
  name: guard-rspec
32
48
  requirement: !ruby/object:Gem::Requirement
@@ -93,9 +109,13 @@ files:
93
109
  - examples/debug.rb
94
110
  - jeff.gemspec
95
111
  - lib/jeff.rb
112
+ - lib/jeff/document.rb
96
113
  - lib/jeff/secret.rb
114
+ - lib/jeff/streamer.rb
97
115
  - lib/jeff/version.rb
116
+ - spec/jeff/document_spec.rb
98
117
  - spec/jeff/secret_spec.rb
118
+ - spec/jeff/streamer_spec.rb
99
119
  - spec/jeff_spec.rb
100
120
  - spec/spec_helper.rb
101
121
  homepage: https://github.com/hakanensari/jeff
@@ -123,7 +143,9 @@ signing_key:
123
143
  specification_version: 3
124
144
  summary: AWS client
125
145
  test_files:
146
+ - spec/jeff/document_spec.rb
126
147
  - spec/jeff/secret_spec.rb
148
+ - spec/jeff/streamer_spec.rb
127
149
  - spec/jeff_spec.rb
128
150
  - spec/spec_helper.rb
129
151
  has_rdoc: