httparty 0.2.10 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of httparty might be problematic. Click here for more details.

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
@@ -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
@@ -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/response_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