thunk 0.0.0 → 0.1.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.
@@ -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