thunk 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,9 @@
1
+ === 0.1.0 / 2010-01-29
2
+
3
+ * Improve command-line option help.
4
+ * Refactor for better testability (thanks, Evan!)
5
+ * Remove debug output.
6
+
1
7
  === 0.0.0 / 2010-01-25
2
8
 
3
9
  * First prerelease. Pretty darn rough.
@@ -5,4 +5,6 @@ README.rdoc
5
5
  Rakefile
6
6
  bin/thunk
7
7
  lib/thunk.rb
8
+ lib/thunk/server.rb
8
9
  test/test_thunk.rb
10
+ test/test_thunk_server.rb
@@ -8,6 +8,8 @@
8
8
  An API for talking to thunk.us, a (soon to be) generally awesome
9
9
  notification service. Thunk lets you share and change simple state.
10
10
 
11
+ == Notes in Progress
12
+
11
13
  We know these docs are rough, but we wanted to get a version of the
12
14
  API out quickly. We'll have it all polished by 1.0, we promise. :)
13
15
 
data/Rakefile CHANGED
@@ -4,7 +4,8 @@ Hoe.plugin :doofus, :git
4
4
  Hoe.plugins.delete :rubyforge
5
5
 
6
6
  Hoe.spec "thunk" do
7
- developer "Eleven Eleven", "hello@3lev3n.com"
7
+ developer "Eleven Eleven", "hello@thunk.us"
8
+ developer "John Barnette", "john@thunk.us"
8
9
 
9
10
  self.extra_rdoc_files = Dir["*.rdoc"]
10
11
  self.history_file = "CHANGELOG.rdoc"
@@ -14,4 +15,5 @@ Hoe.spec "thunk" do
14
15
  extra_deps << %w(json_pure 1.2.0)
15
16
  extra_dev_deps << %w(fakeweb 1.2.8)
16
17
  extra_dev_deps << %w(minitest 1.5.0)
18
+ extra_dev_deps << %w(mocha 0.9.8)
17
19
  end
data/bin/thunk CHANGED
@@ -7,14 +7,15 @@ OptionParser.new do |opts|
7
7
  @payload = nil
8
8
  @poke = nil
9
9
  @raw = false
10
+ @server = Thunk::Server.new
10
11
 
11
- opts.banner =
12
- "Usage: thunk [options] --create [message]\n" +
12
+ opts.banner =
13
+ "Usage: thunk [options] --create [name]\n" +
13
14
  " thunk [options] <uuid>\n" +
14
15
  " thunk [options] {--good, --bad, --iffy, --unknown} <uuid>\n\n"
15
16
 
16
- opts.on "--create [PAYLOAD]", "-c", "Create a thunk, optional payload." do |p|
17
- thunk = Thunk.create p
17
+ opts.on "--create [NAME]", "-c", "Create a thunk, optional name." do |n|
18
+ thunk = @server.create n
18
19
  puts thunk.uuid if thunk.uuid
19
20
  exit thunk.exists? ? 0 : 1
20
21
  end
@@ -25,7 +26,7 @@ OptionParser.new do |opts|
25
26
  end
26
27
 
27
28
  opts.on "--payload PAYLOAD", "-p", "-m",
28
- "An optional poke payload/message." do |p|
29
+ "Add a payload/message to a poke." do |p|
29
30
 
30
31
  @payload = p
31
32
  end
@@ -35,7 +36,7 @@ OptionParser.new do |opts|
35
36
  end
36
37
 
37
38
  opts.on "--url URL", "Use a different base URL." do |url|
38
- Thunk.url = url
39
+ @server = Thunk::Server.new url
39
40
  end
40
41
 
41
42
  opts.on "--version", "-V", "Prints #{Thunk::VERSION}." do
@@ -61,10 +62,9 @@ OptionParser.new do |opts|
61
62
  end
62
63
 
63
64
  abort "#$0: Specify a thunk UUID!" unless uuid = ARGV.shift
64
- thunk = Thunk.for uuid
65
+ thunk = @server.get uuid
65
66
 
66
67
  if @poke
67
- p @payload
68
68
  thunk.send "#{@poke}!", @payload
69
69
  else
70
70
  if @raw
@@ -1,76 +1,32 @@
1
- require "cgi"
2
- require "json/pure"
3
- require "net/http"
4
- require "uri"
1
+ require "thunk/server"
5
2
 
6
3
  class Thunk
7
- VERSION = "0.0.0"
8
- URL = "http://thunk.us".freeze
9
-
10
- class << self
11
- attr_accessor :url
12
- private :new
13
-
14
- def create name = nil
15
- json = request :post, url, :name => name
16
- new "#{url}/#{json["uuid"]}", json
17
- end
18
-
19
- def for url
20
- url = "#{self.url}/#{url}" unless /^http/ =~ url
21
- json = request :get, url
22
- new url, json
23
- end
24
-
25
- def request method, url, options = {}
26
- url = URI.parse url
27
-
28
- unless options.empty?
29
- url.query = options.collect { |k ,v|
30
- "#{CGI.escape k.to_s}=#{CGI.escape v.to_s}"
31
- }.join "&"
32
- end
33
-
34
- # FIX http timeout settings
35
- # FIX exception handing, etc
36
-
37
- http = Net::HTTP.new url.host, url.port
38
- rclass = { :get => Net::HTTP::Get, :post => Net::HTTP::Post }[method]
39
- req = rclass.new url.request_uri
40
- res = http.request req
41
- success = %w(200 201).include? res.code
42
-
43
- unless success
44
- warn "[Thunk] #{res.code}, #{method}, #{url}: #{res.message}"
45
- warn res.body if res.body
46
- end
47
-
48
- return success if res.body.empty?
49
-
50
- data = JSON.parse(res.body) rescue {}
51
-
52
- unless Hash === data
53
- warn "[Thunk] Malformed JSON response: #{data.inspect}"
54
- data = {}
55
- end
56
-
57
- warn warning if warning = data.delete("warn")
58
- abort critical if critical = data.delete("abort")
59
-
60
- data
61
- end
62
- end
63
-
64
- self.url = URL
4
+ VERSION = "0.1.0"
65
5
 
66
6
  attr_reader :name
67
7
  attr_reader :payload
68
8
  attr_reader :puuid
69
9
  attr_reader :state
70
10
  attr_reader :updated
71
- attr_reader :url
72
11
  attr_reader :uuid
73
12
 
13
+ def self.create *args
14
+ server.create *args
15
+ end
16
+
17
+ def self.get *args
18
+ server.get *args
19
+ end
20
+
21
+ def self.server
22
+ @server ||= Thunk::Server.new
23
+ end
24
+
25
+ def initialize server, json
26
+ @server = server
27
+ apply json
28
+ end
29
+
74
30
  def bad?
75
31
  :bad == state
76
32
  end
@@ -80,7 +36,7 @@ class Thunk
80
36
  end
81
37
 
82
38
  def exists?
83
- self.class.request :get, url
39
+ @server.request :get, url
84
40
  end
85
41
 
86
42
  def good?
@@ -99,7 +55,9 @@ class Thunk
99
55
  poke :iffy, payload
100
56
  end
101
57
 
102
- def json
58
+ # Used for the --raw option in the command-line client.
59
+
60
+ def json # :nodoc:
103
61
  json = {
104
62
  :name => name,
105
63
  :payload => payload,
@@ -115,7 +73,7 @@ class Thunk
115
73
  end
116
74
 
117
75
  def poke state, payload = nil
118
- if self.class.request :post, "#{url}/#{state}", :payload => payload
76
+ if @server.request :post, "#{url}/#{state}", :payload => payload
119
77
  @payload = payload
120
78
  @state = state.to_sym
121
79
  @updated = Time.now.utc
@@ -140,13 +98,12 @@ class Thunk
140
98
  poke :unknown, payload
141
99
  end
142
100
 
143
- private
144
-
145
- def initialize url, json
146
- @url = url
147
- apply json
101
+ def url
102
+ "#{@server.url}/#{uuid}"
148
103
  end
149
104
 
105
+ private
106
+
150
107
  def apply json
151
108
  @name = json["name"]
152
109
  @payload = json["payload"]
@@ -0,0 +1,71 @@
1
+ require "cgi"
2
+ require "json/pure"
3
+ require "net/http"
4
+ require "uri"
5
+
6
+ require "thunk"
7
+
8
+ class Thunk
9
+
10
+ class << self
11
+ public :new # FIX
12
+ end
13
+
14
+ class Server
15
+ attr_reader :url
16
+
17
+ def initialize url = "http://thunk.us"
18
+ @url = url
19
+ end
20
+
21
+ def create name = nil
22
+ json = request :post, url, :name => name
23
+ url = "#{self.url}/#{json['uuid']}"
24
+
25
+ Thunk.new self, json
26
+ end
27
+
28
+ def get uuid
29
+ url = "#{self.url}/#{uuid}"
30
+ Thunk.new self, request(:get, url)
31
+ end
32
+
33
+ def request method, url, options = {}
34
+ url = URI.parse url
35
+
36
+ unless options.empty?
37
+ url.query = options.collect { |k ,v|
38
+ "#{CGI.escape k.to_s}=#{CGI.escape v.to_s}"
39
+ }.join "&"
40
+ end
41
+
42
+ # FIX http timeout settings
43
+ # FIX exception handing, etc
44
+
45
+ http = Net::HTTP.new url.host, url.port
46
+ rclass = { :get => Net::HTTP::Get, :post => Net::HTTP::Post }[method]
47
+ req = rclass.new url.request_uri
48
+ res = http.request req
49
+ success = %w(200 201).include? res.code
50
+
51
+ unless success
52
+ warn "[Thunk] #{res.code}, #{method}, #{url}: #{res.message}"
53
+ warn res.body if res.body
54
+ end
55
+
56
+ return success if res.body.empty?
57
+
58
+ data = JSON.parse(res.body) rescue {}
59
+
60
+ unless Hash === data
61
+ warn "[Thunk] Malformed JSON response: #{data.inspect}"
62
+ data = {}
63
+ end
64
+
65
+ warn warning if warning = data.delete("warn")
66
+ abort critical if critical = data.delete("abort")
67
+
68
+ data
69
+ end
70
+ end
71
+ end
@@ -1,29 +1,19 @@
1
1
  require "fakeweb"
2
2
  require "minitest/autorun"
3
+ require "mocha"
3
4
 
4
5
  require "thunk"
5
6
 
6
7
  FakeWeb.allow_net_connect = false
7
8
 
8
- class Thunk
9
- class << self
10
- def abort *; end
11
- def warn *; end
12
-
13
- public :new
14
- end
15
-
16
- public :initialize
17
- end
18
-
19
9
  class TestThunk < MiniTest::Unit::TestCase
20
10
  def setup
21
11
  FakeWeb.clean_registry
22
- Thunk.url = Thunk::URL
12
+ @server = Thunk::Server.new
23
13
  end
24
14
 
25
15
  def test_bangs_and_predicates
26
- t = Thunk.new "http://thunk.us/uuid", {}
16
+ t = Thunk.new @server, { "uuid" => "uuid" }
27
17
 
28
18
  [:good, :iffy, :bad, :unknown].each do |state|
29
19
  FakeWeb.register_uri :post, "http://thunk.us/uuid/#{state}?payload=hi",
@@ -38,8 +28,8 @@ class TestThunk < MiniTest::Unit::TestCase
38
28
  end
39
29
 
40
30
  def test_exists?
41
- good = Thunk.new "http://thunk.us/exists", {}
42
- bad = Thunk.new "http://thunk.us/nonexistent", {}
31
+ good = Thunk.new @server, { "uuid" => "exists" }
32
+ bad = Thunk.new @server, { "uuid" => "nonexistent" }
43
33
 
44
34
  FakeWeb.register_uri :get, "http://thunk.us/exists", :status => 200
45
35
  FakeWeb.register_uri :get, "http://thunk.us/nonexistent", :status => 404
@@ -55,66 +45,22 @@ class TestThunk < MiniTest::Unit::TestCase
55
45
  FakeWeb.register_uri :get, "http://thunk.us/public",
56
46
  :body => JSON.generate({ :uuid => "public" })
57
47
 
58
- t = Thunk.for "pokeable"
48
+ t = @server.get "pokeable"
59
49
  assert t.pokeable?, "pokeable"
60
50
  refute t.public?, "public"
61
51
 
62
- t = Thunk.for "public"
52
+ t = @server.get "public"
63
53
  refute t.pokeable?, "pokeable"
64
54
  assert t.public?, "public"
65
55
  end
66
56
 
67
57
  def test_self_create
68
- response = {
69
- :name => "Hello",
70
- :puuid => "public",
71
- :state => :new,
72
- :uuid => "uuid"
73
- }
74
-
75
- FakeWeb.register_uri :post, "http://thunk.us?name=Hello",
76
- :body => JSON.generate(response)
77
-
78
- t = Thunk.create "Hello"
79
-
80
- response.each do |key, value|
81
- assert_equal value, t.send(key)
82
- end
83
-
84
- assert_equal "http://thunk.us/uuid", t.url
58
+ Thunk.server.expects(:create).with "foo"
59
+ Thunk.create "foo"
85
60
  end
86
61
 
87
- def test_self_create_bad
88
- FakeWeb.register_uri :post, "http://thunk.us?name=Hello",
89
- :status => 500, :body => "[]"
90
-
91
- t = Thunk.create "Hello"
92
- assert_equal :unknown, t.state
93
- end
94
-
95
- def test_self_for
96
- response = {
97
- :name => "Hello",
98
- :payload => "All is well!",
99
- :puuid => "public",
100
- :state => :good,
101
- :uuid => "uuid"
102
- }
103
-
104
- FakeWeb.register_uri :get, "http://thunk.us/uuid",
105
- :body => JSON.generate(response)
106
-
107
- t = Thunk.for "uuid"
108
-
109
- response.each do |key, value|
110
- assert_equal value, t.send(key)
111
- end
112
- end
113
-
114
- def test_self_url
115
- assert_equal "http://thunk.us", Thunk.url
116
-
117
- Thunk.url = "bleh"
118
- assert_equal "bleh", Thunk.url
62
+ def test_self_get
63
+ Thunk.server.expects(:get).with "foo"
64
+ Thunk.get "foo"
119
65
  end
120
66
  end
@@ -0,0 +1,73 @@
1
+ require "fakeweb"
2
+ require "minitest/autorun"
3
+
4
+ require "thunk"
5
+
6
+ FakeWeb.allow_net_connect = false
7
+
8
+ class Thunk::Server
9
+ def abort *; end
10
+ def warn *; end
11
+ end
12
+
13
+ class TestThunkServer < MiniTest::Unit::TestCase
14
+ def setup
15
+ FakeWeb.clean_registry
16
+ @server = Thunk::Server.new
17
+ end
18
+
19
+ def test_create
20
+ response = {
21
+ :name => "Hello",
22
+ :puuid => "public",
23
+ :state => :new,
24
+ :uuid => "uuid"
25
+ }
26
+
27
+ FakeWeb.register_uri :post, "http://thunk.us?name=Hello",
28
+ :body => JSON.generate(response)
29
+
30
+ t = @server.create "Hello"
31
+
32
+ response.each do |key, value|
33
+ assert_equal value, t.send(key)
34
+ end
35
+
36
+ assert_equal "http://thunk.us/uuid", t.url
37
+ end
38
+
39
+ def test_create_bad
40
+ FakeWeb.register_uri :post, "http://thunk.us?name=Hello",
41
+ :status => 500, :body => "[]"
42
+
43
+ t = @server.create "Hello"
44
+ assert_equal :unknown, t.state
45
+ end
46
+
47
+ def test_get
48
+ response = {
49
+ :name => "Hello",
50
+ :payload => "All is well!",
51
+ :puuid => "public",
52
+ :state => :good,
53
+ :uuid => "uuid"
54
+ }
55
+
56
+ FakeWeb.register_uri :get, "http://thunk.us/uuid",
57
+ :body => JSON.generate(response)
58
+
59
+ t = @server.get "uuid"
60
+
61
+ response.each do |key, value|
62
+ assert_equal value, t.send(key)
63
+ end
64
+ end
65
+
66
+ def test_initialize
67
+ s = Thunk::Server.new
68
+ assert_equal "http://thunk.us", s.url
69
+
70
+ s = Thunk::Server.new "http://thunk.local"
71
+ assert_equal "http://thunk.local", s.url
72
+ end
73
+ end
metadata CHANGED
@@ -1,15 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thunk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eleven Eleven
8
+ - John Barnette
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
12
 
12
- date: 2010-01-25 00:00:00 -08:00
13
+ date: 2010-01-29 00:00:00 -08:00
13
14
  default_executable:
14
15
  dependencies:
15
16
  - !ruby/object:Gem::Dependency
@@ -52,6 +53,16 @@ dependencies:
52
53
  - !ruby/object:Gem::Version
53
54
  version: 1.5.0
54
55
  version:
56
+ - !ruby/object:Gem::Dependency
57
+ name: mocha
58
+ type: :development
59
+ version_requirement:
60
+ version_requirements: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - "="
63
+ - !ruby/object:Gem::Version
64
+ version: 0.9.8
65
+ version:
55
66
  - !ruby/object:Gem::Dependency
56
67
  name: hoe
57
68
  type: :development
@@ -65,18 +76,9 @@ dependencies:
65
76
  description: |-
66
77
  An API for talking to thunk.us, a (soon to be) generally awesome
67
78
  notification service. Thunk lets you share and change simple state.
68
-
69
- We know these docs are rough, but we wanted to get a version of the
70
- API out quickly. We'll have it all polished by 1.0, we promise. :)
71
-
72
- Since Thunk gets used in basic infrastructure tools, it works extra
73
- hard to never throw exceptions or cause hangs/timeouts. If it does,
74
- please file a bug! Even a nonexistent or read-only thunk will
75
- successfully respond to pokes, returning stub information. If you need
76
- to make extra sure you're hooked up to a valid thunk, check out
77
- <tt>Thunk#exists?</tt> and <tt>Thunk#pokeable?</tt>.
78
79
  email:
79
- - hello@3lev3n.com
80
+ - hello@thunk.us
81
+ - john@thunk.us
80
82
  executables:
81
83
  - thunk
82
84
  extensions: []
@@ -93,7 +95,9 @@ files:
93
95
  - Rakefile
94
96
  - bin/thunk
95
97
  - lib/thunk.rb
98
+ - lib/thunk/server.rb
96
99
  - test/test_thunk.rb
100
+ - test/test_thunk_server.rb
97
101
  has_rdoc: true
98
102
  homepage: http://github.com/eleven/thunk
99
103
  licenses: []
@@ -125,3 +129,4 @@ specification_version: 3
125
129
  summary: An API for talking to thunk.us, a (soon to be) generally awesome notification service
126
130
  test_files:
127
131
  - test/test_thunk.rb
132
+ - test/test_thunk_server.rb