jnunemaker-httparty 0.2.10 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/History CHANGED
@@ -1,3 +1,9 @@
1
+ == 0.3.0 2009-01-31
2
+ * 1 major enhancement, 1 bug fix
3
+ * JSON gem no longer a requirement. It was conflicting with rails json stuff so I just stole ActiveSupport's json decoding and bundled it with HTTParty.
4
+ * Fixed bug where query strings were being duplicated on redirects
5
+ * Added a bunch of specs and moved some code around.
6
+
1
7
  == 0.2.10 2009-01-29
2
8
  * 1 minor enhancement
3
9
  * Made encoding on query parameters treat everything except URI::PATTERN::UNRESERVED as UNSAFE to force encoding of '+' character (Julian Russell)
data/Manifest CHANGED
@@ -22,17 +22,19 @@ httparty.gemspec
22
22
  lib/core_extensions.rb
23
23
  lib/httparty/cookie_hash.rb
24
24
  lib/httparty/exceptions.rb
25
+ lib/httparty/module_inheritable_attributes.rb
26
+ lib/httparty/parsers/json.rb
27
+ lib/httparty/parsers/xml.rb
28
+ lib/httparty/parsers.rb
25
29
  lib/httparty/request.rb
26
30
  lib/httparty/response.rb
27
31
  lib/httparty/version.rb
28
32
  lib/httparty.rb
29
- lib/module_level_inheritable_attributes.rb
30
33
  Manifest
31
34
  MIT-LICENSE
32
35
  Rakefile
33
36
  README
34
37
  setup.rb
35
- spec/as_buggery_spec.rb
36
38
  spec/core_extensions_spec.rb
37
39
  spec/fixtures/delicious.xml
38
40
  spec/fixtures/empty.xml
@@ -40,10 +42,15 @@ spec/fixtures/google.html
40
42
  spec/fixtures/twitter.json
41
43
  spec/fixtures/twitter.xml
42
44
  spec/fixtures/undefined_method_add_node_for_nil.xml
45
+ spec/hash_spec.rb
43
46
  spec/httparty/cookie_hash_spec.rb
47
+ spec/httparty/parsers/json_spec.rb
48
+ spec/httparty/parsers/xml_spec.rb
44
49
  spec/httparty/request_spec.rb
50
+ spec/httparty/response_spec.rb
45
51
  spec/httparty_spec.rb
46
52
  spec/spec.opts
47
53
  spec/spec_helper.rb
54
+ spec/string_spec.rb
48
55
  website/css/common.css
49
56
  website/index.html
data/README CHANGED
@@ -24,11 +24,11 @@ grokking the structure of output). This can also be overridden to output
24
24
  formatted XML or JSON. Execute <tt>httparty --help</tt> for all the
25
25
  options. Below is an example of how easy it is.
26
26
 
27
- httparty "http://twitter.com/statuses/public_timeline.json" -f json
27
+ httparty "http://twitter.com/statuses/public_timeline.json"
28
28
 
29
29
  == REQUIREMENTS:
30
30
 
31
- * JSON ~> 1.1
31
+ * You like to party!
32
32
 
33
33
  == INSTALL:
34
34
 
data/Rakefile CHANGED
@@ -14,7 +14,6 @@ Echoe.new(ProjectName, HTTParty::Version) do |p|
14
14
  p.url = "http://#{ProjectName}.rubyforge.org"
15
15
  p.author = "John Nunemaker"
16
16
  p.email = "nunemaker@gmail.com"
17
- p.extra_deps = [['json', '~> 1.1']]
18
17
  p.need_tar_gz = false
19
18
  p.docs_host = WebsitePath
20
19
  end
data/bin/httparty CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "optparse"
4
4
  require "pp"
5
- require "rexml/document"
6
5
 
7
6
  $:.unshift(File.join(File.dirname(__FILE__), "/../lib"))
8
7
  require "httparty"
@@ -73,27 +72,6 @@ if ARGV.empty?
73
72
  STDERR.puts "USAGE: #{$0} [options] [url]"
74
73
  end
75
74
 
76
- # 1.8.6 has mistyping of transitive in if statement
77
- module REXML
78
- class Document < Element
79
- def write( output=$stdout, indent=-1, transitive=false, ie_hack=false )
80
- if xml_decl.encoding != "UTF-8" && !output.kind_of?(Output)
81
- output = Output.new( output, xml_decl.encoding )
82
- end
83
- formatter = if indent > -1
84
- if transitive
85
- REXML::Formatters::Transitive.new( indent, ie_hack )
86
- else
87
- REXML::Formatters::Pretty.new( indent, ie_hack )
88
- end
89
- else
90
- REXML::Formatters::Default.new( ie_hack )
91
- end
92
- formatter.write( self, output )
93
- end
94
- end
95
- end
96
-
97
75
  if opts[:output_format].nil?
98
76
  response = HTTParty.send(opts[:action], ARGV.first, opts)
99
77
  puts "Status: #{response.code}"
@@ -103,12 +81,18 @@ else
103
81
  response = HTTParty.send(opts[:action], ARGV.first, opts)
104
82
  puts "Status: #{response.code}"
105
83
  case opts[:output_format]
106
- when :json
107
- puts JSON.pretty_generate(response)
108
- when :xml
109
- REXML::Document.new(response.body).write(STDOUT, 2)
110
- puts
111
- else
112
- puts response
84
+ when :json
85
+ begin
86
+ require 'rubygems'
87
+ require 'json'
88
+ puts JSON.pretty_generate(response.delegate)
89
+ rescue LoadError
90
+ puts YAML.dump(response.delegate)
91
+ end
92
+ when :xml
93
+ REXML::Document.new(response.body).write(STDOUT, 2)
94
+ puts
95
+ else
96
+ puts response
113
97
  end
114
98
  end
data/httparty.gemspec CHANGED
@@ -2,17 +2,17 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{httparty}
5
- s.version = "0.2.10"
5
+ s.version = "0.3.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["John Nunemaker"]
9
- s.date = %q{2009-01-29}
9
+ s.date = %q{2009-01-31}
10
10
  s.default_executable = %q{httparty}
11
11
  s.description = %q{Makes http fun! Also, makes consuming restful web services dead easy.}
12
12
  s.email = %q{nunemaker@gmail.com}
13
13
  s.executables = ["httparty"]
14
- s.extra_rdoc_files = ["bin/httparty", "lib/core_extensions.rb", "lib/httparty/cookie_hash.rb", "lib/httparty/exceptions.rb", "lib/httparty/request.rb", "lib/httparty/response.rb", "lib/httparty/version.rb", "lib/httparty.rb", "lib/module_level_inheritable_attributes.rb", "README"]
15
- s.files = ["bin/httparty", "cucumber.yml", "examples/aaws.rb", "examples/basic.rb", "examples/delicious.rb", "examples/google.rb", "examples/rubyurl.rb", "examples/twitter.rb", "examples/whoismyrep.rb", "features/basic_authentication.feature", "features/command_line.feature", "features/deals_with_http_error_codes.feature", "features/handles_multiple_formats.feature", "features/steps/env.rb", "features/steps/httparty_response_steps.rb", "features/steps/httparty_steps.rb", "features/steps/mongrel_helper.rb", "features/steps/remote_service_steps.rb", "features/supports_redirection.feature", "History", "httparty.gemspec", "lib/core_extensions.rb", "lib/httparty/cookie_hash.rb", "lib/httparty/exceptions.rb", "lib/httparty/request.rb", "lib/httparty/response.rb", "lib/httparty/version.rb", "lib/httparty.rb", "lib/module_level_inheritable_attributes.rb", "Manifest", "MIT-LICENSE", "Rakefile", "README", "setup.rb", "spec/as_buggery_spec.rb", "spec/core_extensions_spec.rb", "spec/fixtures/delicious.xml", "spec/fixtures/empty.xml", "spec/fixtures/google.html", "spec/fixtures/twitter.json", "spec/fixtures/twitter.xml", "spec/fixtures/undefined_method_add_node_for_nil.xml", "spec/httparty/cookie_hash_spec.rb", "spec/httparty/request_spec.rb", "spec/httparty_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "website/css/common.css", "website/index.html"]
14
+ s.extra_rdoc_files = ["bin/httparty", "lib/core_extensions.rb", "lib/httparty/cookie_hash.rb", "lib/httparty/exceptions.rb", "lib/httparty/module_inheritable_attributes.rb", "lib/httparty/parsers/json.rb", "lib/httparty/parsers/xml.rb", "lib/httparty/parsers.rb", "lib/httparty/request.rb", "lib/httparty/response.rb", "lib/httparty/version.rb", "lib/httparty.rb", "README"]
15
+ s.files = ["bin/httparty", "cucumber.yml", "examples/aaws.rb", "examples/basic.rb", "examples/delicious.rb", "examples/google.rb", "examples/rubyurl.rb", "examples/twitter.rb", "examples/whoismyrep.rb", "features/basic_authentication.feature", "features/command_line.feature", "features/deals_with_http_error_codes.feature", "features/handles_multiple_formats.feature", "features/steps/env.rb", "features/steps/httparty_response_steps.rb", "features/steps/httparty_steps.rb", "features/steps/mongrel_helper.rb", "features/steps/remote_service_steps.rb", "features/supports_redirection.feature", "History", "httparty.gemspec", "lib/core_extensions.rb", "lib/httparty/cookie_hash.rb", "lib/httparty/exceptions.rb", "lib/httparty/module_inheritable_attributes.rb", "lib/httparty/parsers/json.rb", "lib/httparty/parsers/xml.rb", "lib/httparty/parsers.rb", "lib/httparty/request.rb", "lib/httparty/response.rb", "lib/httparty/version.rb", "lib/httparty.rb", "Manifest", "MIT-LICENSE", "Rakefile", "README", "setup.rb", "spec/core_extensions_spec.rb", "spec/fixtures/delicious.xml", "spec/fixtures/empty.xml", "spec/fixtures/google.html", "spec/fixtures/twitter.json", "spec/fixtures/twitter.xml", "spec/fixtures/undefined_method_add_node_for_nil.xml", "spec/hash_spec.rb", "spec/httparty/cookie_hash_spec.rb", "spec/httparty/parsers/json_spec.rb", "spec/httparty/parsers/xml_spec.rb", "spec/httparty/request_spec.rb", "spec/httparty_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/string_spec.rb", "website/css/common.css", "website/index.html"]
16
16
  s.has_rdoc = true
17
17
  s.homepage = %q{http://httparty.rubyforge.org}
18
18
  s.post_install_message = %q{When you HTTParty, you must party hard!}
@@ -27,14 +27,11 @@ Gem::Specification.new do |s|
27
27
  s.specification_version = 2
28
28
 
29
29
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
30
- s.add_runtime_dependency(%q<json>, ["~> 1.1"])
31
30
  s.add_development_dependency(%q<echoe>, [">= 0"])
32
31
  else
33
- s.add_dependency(%q<json>, ["~> 1.1"])
34
32
  s.add_dependency(%q<echoe>, [">= 0"])
35
33
  end
36
34
  else
37
- s.add_dependency(%q<json>, ["~> 1.1"])
38
35
  s.add_dependency(%q<echoe>, [">= 0"])
39
36
  end
40
37
  end
@@ -21,7 +21,7 @@ require 'time'
21
21
  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
22
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
 
24
- class Object
24
+ class Object #:nodoc:
25
25
  # @return <TrueClass, FalseClass>
26
26
  #
27
27
  # @example [].blank? #=> true
@@ -31,44 +31,44 @@ class Object
31
31
  # Returns true if the object is nil or empty (if applicable)
32
32
  def blank?
33
33
  nil? || (respond_to?(:empty?) && empty?)
34
- end
34
+ end unless method_defined?(:blank?)
35
35
  end # class Object
36
36
 
37
- class Numeric
37
+ class Numeric #:nodoc:
38
38
  # @return <TrueClass, FalseClass>
39
39
  #
40
40
  # Numerics can't be blank
41
41
  def blank?
42
42
  false
43
- end
43
+ end unless method_defined?(:blank?)
44
44
  end # class Numeric
45
45
 
46
- class NilClass
46
+ class NilClass #:nodoc:
47
47
  # @return <TrueClass, FalseClass>
48
48
  #
49
49
  # Nils are always blank
50
50
  def blank?
51
51
  true
52
- end
52
+ end unless method_defined?(:blank?)
53
53
  end # class NilClass
54
54
 
55
- class TrueClass
55
+ class TrueClass #:nodoc:
56
56
  # @return <TrueClass, FalseClass>
57
57
  #
58
58
  # True is not blank.
59
59
  def blank?
60
60
  false
61
- end
61
+ end unless method_defined?(:blank?)
62
62
  end # class TrueClass
63
63
 
64
- class FalseClass
64
+ class FalseClass #:nodoc:
65
65
  # False is always blank.
66
66
  def blank?
67
67
  true
68
- end
68
+ end unless method_defined?(:blank?)
69
69
  end # class FalseClass
70
70
 
71
- class String
71
+ class String #:nodoc:
72
72
  # @example "".blank? #=> true
73
73
  # @example " ".blank? #=> true
74
74
  # @example " hey ho ".blank? #=> false
@@ -78,216 +78,16 @@ class String
78
78
  # Strips out whitespace then tests if the string is empty.
79
79
  def blank?
80
80
  strip.empty?
81
- end
82
- end # class String
83
-
84
- require 'rexml/parsers/streamparser'
85
- require 'rexml/parsers/baseparser'
86
- require 'rexml/light/node'
87
-
88
- # This is a slighly modified version of the XMLUtilityNode from
89
- # http://merb.devjavu.com/projects/merb/ticket/95 (has.sox@gmail.com)
90
- # It's mainly just adding vowels, as I ht cd wth n vwls :)
91
- # This represents the hard part of the work, all I did was change the
92
- # underlying parser.
93
- class REXMLUtilityNode
94
- attr_accessor :name, :attributes, :children, :type
95
-
96
- def self.typecasts
97
- @@typecasts
98
- end
81
+ end unless method_defined?(:blank?)
99
82
 
100
- def self.typecasts=(obj)
101
- @@typecasts = obj
102
- end
103
-
104
- def self.available_typecasts
105
- @@available_typecasts
106
- end
107
-
108
- def self.available_typecasts=(obj)
109
- @@available_typecasts = obj
110
- end
111
-
112
- self.typecasts = {}
113
- self.typecasts["integer"] = lambda{|v| v.nil? ? nil : v.to_i}
114
- self.typecasts["boolean"] = lambda{|v| v.nil? ? nil : (v.strip != "false")}
115
- self.typecasts["datetime"] = lambda{|v| v.nil? ? nil : Time.parse(v).utc}
116
- self.typecasts["date"] = lambda{|v| v.nil? ? nil : Date.parse(v)}
117
- self.typecasts["dateTime"] = lambda{|v| v.nil? ? nil : Time.parse(v).utc}
118
- self.typecasts["decimal"] = lambda{|v| v.nil? ? nil : BigDecimal(v.to_s)}
119
- self.typecasts["double"] = lambda{|v| v.nil? ? nil : v.to_f}
120
- self.typecasts["float"] = lambda{|v| v.nil? ? nil : v.to_f}
121
- self.typecasts["symbol"] = lambda{|v| v.nil? ? nil : v.to_sym}
122
- self.typecasts["string"] = lambda{|v| v.to_s}
123
- self.typecasts["yaml"] = lambda{|v| v.nil? ? nil : YAML.load(v)}
124
- self.typecasts["base64Binary"] = lambda{|v| v.unpack('m').first }
125
-
126
- self.available_typecasts = self.typecasts.keys
127
-
128
- def initialize(name, attributes = {})
129
- @name = name.tr("-", "_")
130
- # leave the type alone if we don't know what it is
131
- @type = self.class.available_typecasts.include?(attributes["type"]) ? attributes.delete("type") : attributes["type"]
132
-
133
- @nil_element = attributes.delete("nil") == "true"
134
- @attributes = undasherize_keys(attributes)
135
- @children = []
136
- @text = false
137
- end
138
-
139
- def add_node(node)
140
- @text = true if node.is_a? String
141
- @children << node
142
- end
143
-
144
- def to_hash
145
- if @type == "file"
146
- f = StringIO.new((@children.first || '').unpack('m').first)
147
- class << f
148
- attr_accessor :original_filename, :content_type
149
- end
150
- f.original_filename = attributes['name'] || 'untitled'
151
- f.content_type = attributes['content_type'] || 'application/octet-stream'
152
- return {name => f}
153
- end
154
-
155
- if @text
156
- return { name => typecast_value( translate_xml_entities( inner_html ) ) }
157
- else
158
- #change repeating groups into an array
159
- groups = @children.inject({}) { |s,e| (s[e.name] ||= []) << e; s }
160
-
161
- out = nil
162
- if @type == "array"
163
- out = []
164
- groups.each do |k, v|
165
- if v.size == 1
166
- out << v.first.to_hash.entries.first.last
167
- else
168
- out << v.map{|e| e.to_hash[k]}
169
- end
170
- end
171
- out = out.flatten
172
-
173
- else # If Hash
174
- out = {}
175
- groups.each do |k,v|
176
- if v.size == 1
177
- out.merge!(v.first)
178
- else
179
- out.merge!( k => v.map{|e| e.to_hash[k]})
180
- end
181
- end
182
- out.merge! attributes unless attributes.empty?
183
- out = out.empty? ? nil : out
184
- end
185
-
186
- if @type && out.nil?
187
- { name => typecast_value(out) }
188
- else
189
- { name => out }
190
- end
191
- end
192
- end
193
-
194
- # Typecasts a value based upon its type. For instance, if
195
- # +node+ has #type == "integer",
196
- # {{[node.typecast_value("12") #=> 12]}}
197
- #
198
- # @param value<String> The value that is being typecast.
199
- #
200
- # @details [:type options]
201
- # "integer"::
202
- # converts +value+ to an integer with #to_i
203
- # "boolean"::
204
- # checks whether +value+, after removing spaces, is the literal
205
- # "true"
206
- # "datetime"::
207
- # Parses +value+ using Time.parse, and returns a UTC Time
208
- # "date"::
209
- # Parses +value+ using Date.parse
210
- #
211
- # @return <Integer, TrueClass, FalseClass, Time, Date, Object>
212
- # The result of typecasting +value+.
213
- #
214
- # @note
215
- # If +self+ does not have a "type" key, or if it's not one of the
216
- # options specified above, the raw +value+ will be returned.
217
- def typecast_value(value)
218
- return value unless @type
219
- proc = self.class.typecasts[@type]
220
- proc.nil? ? value : proc.call(value)
221
- end
222
-
223
- # Convert basic XML entities into their literal values.
224
- #
225
- # @param value<#gsub> An XML fragment.
226
- #
227
- # @return <#gsub> The XML fragment after converting entities.
228
- def translate_xml_entities(value)
229
- value.gsub(/&lt;/, "<").
230
- gsub(/&gt;/, ">").
231
- gsub(/&quot;/, '"').
232
- gsub(/&apos;/, "'").
233
- gsub(/&amp;/, "&")
234
- end
235
-
236
- # Take keys of the form foo-bar and convert them to foo_bar
237
- def undasherize_keys(params)
238
- params.keys.each do |key, value|
239
- params[key.tr("-", "_")] = params.delete(key)
240
- end
241
- params
242
- end
243
-
244
- # Get the inner_html of the REXML node.
245
- def inner_html
246
- @children.join
247
- end
248
-
249
- # Converts the node into a readable HTML node.
250
- #
251
- # @return <String> The HTML node in text form.
252
- def to_html
253
- attributes.merge!(:type => @type ) if @type
254
- "<#{name}#{attributes.to_xml_attributes}>#{@nil_element ? '' : inner_html}</#{name}>"
255
- end
256
-
257
- # @alias #to_html #to_s
258
- def to_s
259
- to_html
260
- end
261
- end
262
-
263
- class ToHashParser
264
- def self.from_xml(xml)
265
- stack = []
266
- parser = REXML::Parsers::BaseParser.new(xml)
267
-
268
- while true
269
- event = parser.pull
270
- case event[0]
271
- when :end_document
272
- break
273
- when :end_doctype, :start_doctype
274
- # do nothing
275
- when :start_element
276
- stack.push REXMLUtilityNode.new(event[1], event[2])
277
- when :end_element
278
- if stack.size > 1
279
- temp = stack.pop
280
- stack.last.add_node(temp)
281
- end
282
- when :text, :cdata
283
- stack.last.add_node(event[1]) unless event[1].strip.length == 0 || stack.empty?
284
- end
285
- end
286
- stack.pop.to_hash
287
- end
288
- end
83
+ def snake_case
84
+ return self.downcase if self =~ /^[A-Z]+$/
85
+ self.gsub(/([A-Z]+)(?=[A-Z][a-z]?)|\B[A-Z]/, '_\&') =~ /_*(.*)/
86
+ return $+.downcase
87
+ end unless method_defined?(:snake_case)
88
+ end # class String
289
89
 
290
- class Hash
90
+ class Hash #:nodoc:
291
91
  # @return <String> This hash as a query string
292
92
  #
293
93
  # @example
@@ -348,6 +148,28 @@ class Hash
348
148
  end
349
149
  end
350
150
 
351
- class BlankSlate
151
+ class BlankSlate #:nodoc:
352
152
  instance_methods.each { |m| undef_method m unless m =~ /^__/ }
353
153
  end
154
+
155
+ # 1.8.6 has mistyping of transitive in if statement
156
+ require "rexml/document"
157
+ module REXML #:nodoc:
158
+ class Document < Element #:nodoc:
159
+ def write( output=$stdout, indent=-1, transitive=false, ie_hack=false )
160
+ if xml_decl.encoding != "UTF-8" && !output.kind_of?(Output)
161
+ output = Output.new( output, xml_decl.encoding )
162
+ end
163
+ formatter = if indent > -1
164
+ if transitive
165
+ REXML::Formatters::Transitive.new( indent, ie_hack )
166
+ else
167
+ REXML::Formatters::Pretty.new( indent, ie_hack )
168
+ end
169
+ else
170
+ REXML::Formatters::Default.new( ie_hack )
171
+ end
172
+ formatter.write( self, output )
173
+ end
174
+ end
175
+ end