addressable 2.1.0 → 2.1.1

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/CHANGELOG CHANGED
@@ -1,3 +1,6 @@
1
+ === Addressable 2.1.1
2
+ * fixed some missing type checking
3
+ * fixed issue with unicode normalization
1
4
  === Addressable 2.1.0
2
5
  * refactored URI template support out into its own class
3
6
  * removed extract method due to being useless and unreliable
data/Rakefile CHANGED
@@ -1,7 +1,3 @@
1
- lib_dir = File.expand_path(File.join(File.dirname(__FILE__), "lib"))
2
- $:.unshift(lib_dir)
3
- $:.uniq!
4
-
5
1
  require 'rubygems'
6
2
  require 'rake'
7
3
  require 'rake/testtask'
@@ -10,7 +6,7 @@ require 'rake/packagetask'
10
6
  require 'rake/gempackagetask'
11
7
  require 'spec/rake/spectask'
12
8
 
13
- require File.join(File.dirname(__FILE__), 'lib/addressable', 'version')
9
+ require File.join(File.dirname(__FILE__), 'lib', 'addressable', 'version')
14
10
 
15
11
  PKG_DISPLAY_NAME = 'Addressable'
16
12
  PKG_NAME = PKG_DISPLAY_NAME.downcase
@@ -31,6 +27,38 @@ Ruby's standard library. It more closely conforms to the relevant RFCs and
31
27
  adds support for IRIs and URI templates.
32
28
  TEXT
33
29
 
30
+ desc "generates .gemspec file"
31
+ task :gemspec do
32
+ spec = Gem::Specification.new do |p|
33
+ p.name = 'addressable'
34
+ p.version = PKG_VERSION
35
+
36
+ p.summary = PKG_SUMMARY
37
+ p.description = PKG_DESCRIPTION
38
+
39
+ p.author = 'Bob Aman'
40
+ p.email = 'bob@sporkmonger.com'
41
+ p.homepage = 'http://github.com/mislav/addressable'
42
+ p.rubyforge_project = nil
43
+
44
+ p.files = FileList['Rakefile', '{bin,lib,tasks,spec}/**/*', 'README*', 'LICENSE*', 'CHANGELOG*'] & `git ls-files`.split
45
+
46
+ p.executables = Dir['bin/*'].map { |f| File.basename(f) }
47
+
48
+ p.has_rdoc = true
49
+ end
50
+
51
+ spec_string = spec.to_ruby
52
+
53
+ begin
54
+ Thread.new { eval("$SAFE = 3\n#{spec_string}", binding) }.join
55
+ rescue
56
+ abort "unsafe gemspec: #{$!}"
57
+ else
58
+ File.open("#{spec.name}.gemspec", 'w') { |file| file.write spec_string }
59
+ end
60
+ end
61
+
34
62
  PKG_FILES = FileList[
35
63
  "lib/**/*", "spec/**/*", "vendor/**/*",
36
64
  "tasks/**/*", "website/**/*",
@@ -38,11 +66,7 @@ PKG_FILES = FileList[
38
66
  ].exclude(/database\.yml/).exclude(/[_\.]git$/)
39
67
 
40
68
  RCOV_ENABLED = (RUBY_PLATFORM != "java" && RUBY_VERSION =~ /^1\.8/)
41
- if RCOV_ENABLED
42
- task :default => "spec:verify"
43
- else
44
- task :default => "spec"
45
- end
69
+ task :default => "spec"
46
70
 
47
71
  WINDOWS = (RUBY_PLATFORM =~ /mswin|win32|mingw|bccwin|cygwin/) rescue false
48
72
  SUDO = WINDOWS ? '' : ('sudo' unless ENV['SUDOLESS'])
@@ -4855,15 +4855,15 @@ module Addressable
4855
4855
  delta = firsttime ? delta / PUNYCODE_DAMP : delta >> 1
4856
4856
  # delta >> 1 is a faster way of doing delta / 2
4857
4857
  delta += delta / numpoints
4858
+ difference = PUNYCODE_BASE - PUNYCODE_TMIN
4858
4859
 
4859
4860
  k = 0
4860
- while delta > ((PUNYCODE_BASE - PUNYCODE_TMIN) * PUNYCODE_TMAX) / 2
4861
- delta /= PUNYCODE_BASE - PUNYCODE_TMIN
4861
+ while delta > (difference * PUNYCODE_TMAX) / 2
4862
+ delta /= difference
4862
4863
  k += PUNYCODE_BASE
4863
4864
  end
4864
4865
 
4865
- k + (PUNYCODE_BASE - PUNYCODE_TMIN + 1) *
4866
- delta / (delta + PUNYCODE_SKEW)
4866
+ k + (difference + 1) * delta / (delta + PUNYCODE_SKEW)
4867
4867
  end
4868
4868
  (class <<self; private :punycode_adapt; end)
4869
4869
  end
@@ -22,9 +22,6 @@
22
22
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
  #++
24
24
 
25
- $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '/..')))
26
- $:.uniq!
27
-
28
25
  require "addressable/version"
29
26
  require "addressable/uri"
30
27
 
@@ -39,7 +36,7 @@ module Addressable
39
36
  Addressable::URI::CharacterClasses::UNRESERVED
40
37
  OPERATOR_EXPANSION =
41
38
  /\{-([a-zA-Z]+)\|([#{anything}]+)\|([#{anything}]+)\}/
42
- VARIABLE_EXPANSION = /\{([#{anything}]+?)(=([#{anything}]+))?\}/
39
+ VARIABLE_EXPANSION = /\{([#{anything}]+?)(?:=([#{anything}]+))?\}/
43
40
 
44
41
  ##
45
42
  # Raised if an invalid template value is supplied.
@@ -154,21 +151,23 @@ module Addressable
154
151
  #
155
152
  # @param [Addressable::URI, #to_str] uri
156
153
  # The URI to extract from.
154
+ #
157
155
  # @param [#restore, #match] processor
158
156
  # A template processor object may optionally be supplied.
159
- # The object should respond to either the <tt>restore</tt> or
160
- # <tt>match</tt> messages or both. The <tt>restore</tt> method should
161
- # take two parameters: [String] name and [String] value. The
162
- # <tt>restore</tt> method should reverse any transformations that have
163
- # been performed on the value to ensure a valid URI. The
164
- # <tt>match</tt> method should take a single parameter: [String] name.
165
- # The <tt>match</tt> method should return a <tt>String</tt> containing
166
- # a regular expression capture group for matching on that particular
167
- # variable. The default value is ".*?". The <tt>match</tt> method has
168
- # no effect on multivariate operator expansions.
157
+ #
158
+ # The object should respond to either the <tt>restore</tt> or
159
+ # <tt>match</tt> messages or both. The <tt>restore</tt> method should take
160
+ # two parameters: [String] name and [String] value. The <tt>restore</tt>
161
+ # method should reverse any transformations that have been performed on the
162
+ # value to ensure a valid URI. The <tt>match</tt> method should take a
163
+ # single parameter: [String] name. The <tt>match</tt> method should return
164
+ # a <tt>String</tt> containing a regular expression capture group for
165
+ # matching on that particular variable. The default value is ".*?". The
166
+ # <tt>match</tt> method has no effect on multivariate operator expansions.
167
+ #
169
168
  # @return [Hash, NilClass]
170
- # The <tt>Hash</tt> mapping that was extracted from the URI, or
171
- # <tt>nil</tt> if the URI didn't match the template.
169
+ # The <tt>Hash</tt> mapping that was extracted from the URI, or
170
+ # <tt>nil</tt> if the URI didn't match the template.
172
171
  #
173
172
  # @example
174
173
  # class ExampleProcessor
@@ -212,21 +211,23 @@ module Addressable
212
211
  #
213
212
  # @param [Addressable::URI, #to_str] uri
214
213
  # The URI to extract from.
214
+ #
215
215
  # @param [#restore, #match] processor
216
216
  # A template processor object may optionally be supplied.
217
- # The object should respond to either the <tt>restore</tt> or
218
- # <tt>match</tt> messages or both. The <tt>restore</tt> method should
219
- # take two parameters: [String] name and [String] value. The
220
- # <tt>restore</tt> method should reverse any transformations that have
221
- # been performed on the value to ensure a valid URI. The
222
- # <tt>match</tt> method should take a single parameter: [String] name.
223
- # The <tt>match</tt> method should return a <tt>String</tt> containing
224
- # a regular expression capture group for matching on that particular
225
- # variable. The default value is ".*?". The <tt>match</tt> method has
226
- # no effect on multivariate operator expansions.
217
+ #
218
+ # The object should respond to either the <tt>restore</tt> or
219
+ # <tt>match</tt> messages or both. The <tt>restore</tt> method should take
220
+ # two parameters: [String] name and [String] value. The <tt>restore</tt>
221
+ # method should reverse any transformations that have been performed on the
222
+ # value to ensure a valid URI. The <tt>match</tt> method should take a
223
+ # single parameter: [String] name. The <tt>match</tt> method should return
224
+ # a <tt>String</tt> containing a regular expression capture group for
225
+ # matching on that particular variable. The default value is ".*?". The
226
+ # <tt>match</tt> method has no effect on multivariate operator expansions.
227
+ #
227
228
  # @return [Hash, NilClass]
228
- # The <tt>Hash</tt> mapping that was extracted from the URI, or
229
- # <tt>nil</tt> if the URI didn't match the template.
229
+ # The <tt>Hash</tt> mapping that was extracted from the URI, or
230
+ # <tt>nil</tt> if the URI didn't match the template.
230
231
  #
231
232
  # @example
232
233
  # class ExampleProcessor
@@ -325,19 +326,19 @@ module Addressable
325
326
  #
326
327
  # @param [Hash] mapping The mapping that corresponds to the pattern.
327
328
  # @param [#validate, #transform] processor
328
- # An optional processor object may be supplied. The object should
329
- # respond to either the <tt>validate</tt> or <tt>transform</tt> messages
330
- # or both. Both the <tt>validate</tt> and <tt>transform</tt> methods
331
- # should take two parameters: <tt>name</tt> and <tt>value</tt>. The
332
- # <tt>validate</tt> method should return <tt>true</tt> or
333
- # <tt>false</tt>; <tt>true</tt> if the value of the variable is valid,
334
- # <tt>false</tt> otherwise. An <tt>InvalidTemplateValueError</tt>
335
- # exception will be raised if the value is invalid. The
336
- # <tt>transform</tt> method should return the transformed variable
337
- # value as a <tt>String</tt>. If a <tt>transform</tt> method is used,
338
- # the value will not be percent encoded automatically. Unicode
339
- # normalization will be performed both before and after sending the
340
- # value to the transform method.
329
+ # An optional processor object may be supplied.
330
+ #
331
+ # The object should respond to either the <tt>validate</tt> or
332
+ # <tt>transform</tt> messages or both. Both the <tt>validate</tt> and
333
+ # <tt>transform</tt> methods should take two parameters: <tt>name</tt> and
334
+ # <tt>value</tt>. The <tt>validate</tt> method should return <tt>true</tt>
335
+ # or <tt>false</tt>; <tt>true</tt> if the value of the variable is valid,
336
+ # <tt>false</tt> otherwise. An <tt>InvalidTemplateValueError</tt>
337
+ # exception will be raised if the value is invalid. The <tt>transform</tt>
338
+ # method should return the transformed variable value as a <tt>String</tt>.
339
+ # If a <tt>transform</tt> method is used, the value will not be percent
340
+ # encoded automatically. Unicode normalization will be performed both
341
+ # before and after sending the value to the transform method.
341
342
  #
342
343
  # @return [Addressable::Template] The partially expanded URI template.
343
344
  #
@@ -401,19 +402,19 @@ module Addressable
401
402
  #
402
403
  # @param [Hash] mapping The mapping that corresponds to the pattern.
403
404
  # @param [#validate, #transform] processor
404
- # An optional processor object may be supplied. The object should
405
- # respond to either the <tt>validate</tt> or <tt>transform</tt> messages
406
- # or both. Both the <tt>validate</tt> and <tt>transform</tt> methods
407
- # should take two parameters: <tt>name</tt> and <tt>value</tt>. The
408
- # <tt>validate</tt> method should return <tt>true</tt> or
409
- # <tt>false</tt>; <tt>true</tt> if the value of the variable is valid,
410
- # <tt>false</tt> otherwise. An <tt>InvalidTemplateValueError</tt>
411
- # exception will be raised if the value is invalid. The
412
- # <tt>transform</tt> method should return the transformed variable
413
- # value as a <tt>String</tt>. If a <tt>transform</tt> method is used,
414
- # the value will not be percent encoded automatically. Unicode
415
- # normalization will be performed both before and after sending the
416
- # value to the transform method.
405
+ # An optional processor object may be supplied.
406
+ #
407
+ # The object should respond to either the <tt>validate</tt> or
408
+ # <tt>transform</tt> messages or both. Both the <tt>validate</tt> and
409
+ # <tt>transform</tt> methods should take two parameters: <tt>name</tt> and
410
+ # <tt>value</tt>. The <tt>validate</tt> method should return <tt>true</tt>
411
+ # or <tt>false</tt>; <tt>true</tt> if the value of the variable is valid,
412
+ # <tt>false</tt> otherwise. An <tt>InvalidTemplateValueError</tt>
413
+ # exception will be raised if the value is invalid. The <tt>transform</tt>
414
+ # method should return the transformed variable value as a <tt>String</tt>.
415
+ # If a <tt>transform</tt> method is used, the value will not be percent
416
+ # encoded automatically. Unicode normalization will be performed both
417
+ # before and after sending the value to the transform method.
417
418
  #
418
419
  # @return [Addressable::URI] The expanded URI template.
419
420
  #
@@ -484,55 +485,79 @@ module Addressable
484
485
  #
485
486
  # @return [Array] The variables present in the template's pattern.
486
487
  def variables
487
- @variables ||= (begin
488
- result = []
488
+ @variables ||= ordered_variable_defaults.map { |var, val| var }.uniq
489
+ end
490
+ alias_method :keys, :variables
491
+
492
+ ##
493
+ # Returns a mapping of variables to their default values specified
494
+ # in the template. Variables without defaults are not returned.
495
+ #
496
+ # @return [Hash] Mapping of template variables to their defaults
497
+ def variable_defaults
498
+ @variable_defaults ||= Hash[*ordered_variable_defaults.reject { |k,v| v.nil? }.flatten]
499
+ end
489
500
 
501
+ private
502
+
503
+ def ordered_variable_defaults
504
+ @ordered_variable_defaults ||= begin
490
505
  expansions, expansion_regexp = parse_template_pattern(pattern)
491
- expansions.each do |expansion|
492
- if expansion =~ OPERATOR_EXPANSION
493
- _, _, variables, _ = parse_template_expansion(expansion)
494
- result.concat(variables)
495
- else
496
- result << expansion[VARIABLE_EXPANSION, 1]
506
+
507
+ expansions.inject([]) do |result, expansion|
508
+ case expansion
509
+ when OPERATOR_EXPANSION
510
+ _, _, variables, mapping = parse_template_expansion(expansion)
511
+ result.concat variables.map { |var| [var, mapping[var]] }
512
+ when VARIABLE_EXPANSION
513
+ result << [$1, $2]
497
514
  end
515
+ result
498
516
  end
499
- result.uniq
500
- end)
517
+ end
501
518
  end
502
- alias_method :keys, :variables
503
519
 
504
- private
505
520
  ##
506
521
  # Transforms a mapping so that values can be substituted into the
507
522
  # template.
508
523
  #
509
524
  # @param [Hash] mapping The mapping of variables to values.
510
525
  # @param [#validate, #transform] processor
511
- # An optional processor object may be supplied. The object should
512
- # respond to either the <tt>validate</tt> or <tt>transform</tt> messages
513
- # or both. Both the <tt>validate</tt> and <tt>transform</tt> methods
514
- # should take two parameters: <tt>name</tt> and <tt>value</tt>. The
515
- # <tt>validate</tt> method should return <tt>true</tt> or
516
- # <tt>false</tt>; <tt>true</tt> if the value of the variable is valid,
517
- # <tt>false</tt> otherwise. An <tt>InvalidTemplateValueError</tt>
518
- # exception will be raised if the value is invalid. The
519
- # <tt>transform</tt> method should return the transformed variable
520
- # value as a <tt>String</tt>. If a <tt>transform</tt> method is used,
521
- # the value will not be percent encoded automatically. Unicode
522
- # normalization will be performed both before and after sending the
523
- # value to the transform method.
526
+ # An optional processor object may be supplied.
527
+ #
528
+ # The object should respond to either the <tt>validate</tt> or
529
+ # <tt>transform</tt> messages or both. Both the <tt>validate</tt> and
530
+ # <tt>transform</tt> methods should take two parameters: <tt>name</tt> and
531
+ # <tt>value</tt>. The <tt>validate</tt> method should return <tt>true</tt>
532
+ # or <tt>false</tt>; <tt>true</tt> if the value of the variable is valid,
533
+ # <tt>false</tt> otherwise. An <tt>InvalidTemplateValueError</tt> exception
534
+ # will be raised if the value is invalid. The <tt>transform</tt> method
535
+ # should return the transformed variable value as a <tt>String</tt>. If a
536
+ # <tt>transform</tt> method is used, the value will not be percent encoded
537
+ # automatically. Unicode normalization will be performed both before and
538
+ # after sending the value to the transform method.
524
539
  #
525
540
  # @return [Hash] The transformed mapping.
526
541
  def transform_mapping(mapping, processor=nil)
527
542
  return mapping.inject({}) do |accu, pair|
528
543
  name, value = pair
544
+ value = value.to_s if Numeric === value || Symbol === value
545
+
529
546
  unless value.respond_to?(:to_ary) || value.respond_to?(:to_str)
530
547
  raise TypeError,
531
548
  "Can't convert #{value.class} into String or Array."
532
549
  end
533
550
 
534
- value =
535
- value.respond_to?(:to_ary) ? value.to_ary : value.to_str
551
+ if Symbol === name
552
+ name = name.to_s
553
+ elsif name.respond_to?(:to_str)
554
+ name = name.to_str
555
+ else
556
+ raise TypeError,
557
+ "Can't convert #{name.class} into String."
558
+ end
559
+ value = value.respond_to?(:to_ary) ? value.to_ary : value.to_str
560
+
536
561
  # Handle unicode normalization
537
562
  if value.kind_of?(Array)
538
563
  value.map! { |val| Addressable::IDNA.unicode_normalize_kc(val) }
@@ -796,8 +821,8 @@ module Addressable
796
821
  # @return [Regexp]
797
822
  # A regular expression which may be used to parse a template pattern.
798
823
  def parse_template_pattern(pattern, processor=nil)
799
- # Escape the pattern. The two gsubs restore the escaped curly braces
800
- # back to their original form. Basically, escape everything that isn't
824
+ # Escape the pattern. The two gsubs restore the escaped curly braces
825
+ # back to their original form. Basically, escape everything that isn't
801
826
  # within an expansion.
802
827
  escaped_pattern = Regexp.escape(
803
828
  pattern
@@ -819,7 +844,7 @@ module Addressable
819
844
  parse_template_expansion(expansion)
820
845
  if processor != nil && processor.respond_to?(:match)
821
846
  # We can only lookup the match values for single variable
822
- # operator expansions. Besides, ".*" is usually the only
847
+ # operator expansions. Besides, ".*" is usually the only
823
848
  # reasonable value for multivariate operators anyways.
824
849
  if ["prefix", "suffix", "list"].include?(operator)
825
850
  capture_group = "(#{processor.match(names.first)})"
@@ -22,9 +22,6 @@
22
22
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
  #++
24
24
 
25
- $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '/..')))
26
- $:.uniq!
27
-
28
25
  require "addressable/version"
29
26
  require "addressable/idna"
30
27
 
@@ -66,8 +63,9 @@ module Addressable
66
63
  # Returns a URI object based on the parsed string.
67
64
  #
68
65
  # @param [String, Addressable::URI, #to_str] uri
69
- # The URI string to parse. No parsing is performed if the object is
70
- # already an <tt>Addressable::URI</tt>.
66
+ # The URI string to parse.
67
+ # No parsing is performed if the object is already an
68
+ # <tt>Addressable::URI</tt>.
71
69
  #
72
70
  # @return [Addressable::URI] The parsed URI.
73
71
  def self.parse(uri)
@@ -131,16 +129,17 @@ module Addressable
131
129
  end
132
130
 
133
131
  ##
134
- # Converts an input to a URI. The input does not have to be a valid
132
+ # Converts an input to a URI. The input does not have to be a valid
135
133
  # URI — the method will use heuristics to guess what URI was intended.
136
134
  # This is not standards-compliant, merely user-friendly.
137
135
  #
138
136
  # @param [String, Addressable::URI, #to_str] uri
139
- # The URI string to parse. No parsing is performed if the object is
140
- # already an <tt>Addressable::URI</tt>.
137
+ # The URI string to parse.
138
+ # No parsing is performed if the object is already an
139
+ # <tt>Addressable::URI</tt>.
141
140
  # @param [Hash] hints
142
- # A <tt>Hash</tt> of hints to the heuristic parser. Defaults to
143
- # <tt>{:scheme => "http"}</tt>.
141
+ # A <tt>Hash</tt> of hints to the heuristic parser.
142
+ # Defaults to <tt>{:scheme => "http"}</tt>.
144
143
  #
145
144
  # @return [Addressable::URI] The parsed URI.
146
145
  def self.heuristic_parse(uri, hints={})
@@ -184,16 +183,16 @@ module Addressable
184
183
  end
185
184
 
186
185
  ##
187
- # Converts a path to a file scheme URI. If the path supplied is
188
- # relative, it will be returned as a relative URI. If the path supplied
186
+ # Converts a path to a file scheme URI. If the path supplied is
187
+ # relative, it will be returned as a relative URI. If the path supplied
189
188
  # is actually a non-file URI, it will parse the URI as if it had been
190
- # parsed with <tt>Addressable::URI.parse</tt>. Handles all of the
189
+ # parsed with <tt>Addressable::URI.parse</tt>. Handles all of the
191
190
  # various Microsoft-specific formats for specifying paths.
192
191
  #
193
192
  # @param [String, Addressable::URI, #to_str] path
194
- # Typically a <tt>String</tt> path to a file or directory, but
195
- # will return a sensible return value if an absolute URI is supplied
196
- # instead.
193
+ #
194
+ # Typically a <tt>String</tt> path to a file or directory, but will return
195
+ # a sensible return value if an absolute URI is supplied instead.
197
196
  #
198
197
  # @return [Addressable::URI]
199
198
  # The parsed file scheme URI or the original URI if some other URI
@@ -281,17 +280,17 @@ module Addressable
281
280
  # @param [String, #to_str] component The URI component to encode.
282
281
  #
283
282
  # @param [String, Regexp] character_class
284
- # The characters which are not percent encoded. If a <tt>String</tt>
285
- # is passed, the <tt>String</tt> must be formatted as a regular
286
- # expression character class. (Do not include the surrounding square
287
- # brackets.) For example, <tt>"b-zB-Z0-9"</tt> would cause everything
288
- # but the letters 'b' through 'z' and the numbers '0' through '9' to be
289
- # percent encoded. If a <tt>Regexp</tt> is passed, the value
290
- # <tt>/[^b-zB-Z0-9]/</tt> would have the same effect.
291
- # A set of useful <tt>String</tt> values may be found in the
292
- # <tt>Addressable::URI::CharacterClasses</tt> module. The default value
293
- # is the reserved plus unreserved character classes specified in
294
- # <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>.
283
+ #
284
+ # The characters which are not percent encoded. If a <tt>String</tt> is
285
+ # passed, the <tt>String</tt> must be formatted as a regular expression
286
+ # character class. (Do not include the surrounding square brackets.) For
287
+ # example, <tt>"b-zB-Z0-9"</tt> would cause everything but the letters 'b'
288
+ # through 'z' and the numbers '0' through '9' to be percent encoded. If a
289
+ # <tt>Regexp</tt> is passed, the value <tt>/[^b-zB-Z0-9]/</tt> would have
290
+ # the same effect. A set of useful <tt>String</tt> values may be found in
291
+ # the <tt>Addressable::URI::CharacterClasses</tt> module. The default
292
+ # value is the reserved plus unreserved character classes specified in <a
293
+ # href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>.
295
294
  #
296
295
  # @return [String] The encoded component.
297
296
  #
@@ -343,13 +342,14 @@ module Addressable
343
342
  # The URI or component to unencode.
344
343
  #
345
344
  # @param [Class] returning
346
- # The type of object to return. This value may only be set to
347
- # <tt>String</tt> or <tt>Addressable::URI</tt>. All other values
348
- # are invalid. Defaults to <tt>String</tt>.
345
+ # The type of object to return.
346
+ # This value may only be set to <tt>String</tt> or
347
+ # <tt>Addressable::URI</tt>. All other values are invalid. Defaults to
348
+ # <tt>String</tt>.
349
349
  #
350
350
  # @return [String, Addressable::URI]
351
- # The unencoded component or URI. The return type is determined by
352
- # the <tt>returning</tt> parameter.
351
+ # The unencoded component or URI.
352
+ # The return type is determined by the <tt>returning</tt> parameter.
353
353
  def self.unencode(uri, returning=String)
354
354
  return nil if uri.nil?
355
355
  if !uri.respond_to?(:to_str)
@@ -384,13 +384,14 @@ module Addressable
384
384
  # The URI to encode.
385
385
  #
386
386
  # @param [Class] returning
387
- # The type of object to return. This value may only be set to
388
- # <tt>String</tt> or <tt>Addressable::URI</tt>. All other values
389
- # are invalid. Defaults to <tt>String</tt>.
387
+ # The type of object to return.
388
+ # This value may only be set to <tt>String</tt> or
389
+ # <tt>Addressable::URI</tt>. All other values are invalid. Defaults to
390
+ # <tt>String</tt>.
390
391
  #
391
392
  # @return [String, Addressable::URI]
392
- # The encoded URI. The return type is determined by
393
- # the <tt>returning</tt> parameter.
393
+ # The encoded URI.
394
+ # The return type is determined by the <tt>returning</tt> parameter.
394
395
  def self.encode(uri, returning=String)
395
396
  return nil if uri.nil?
396
397
  if !uri.respond_to?(:to_str)
@@ -426,20 +427,21 @@ module Addressable
426
427
  end
427
428
 
428
429
  ##
429
- # Normalizes the encoding of a URI. Characters within a hostname are
430
+ # Normalizes the encoding of a URI. Characters within a hostname are
430
431
  # not percent encoded to allow for internationalized domain names.
431
432
  #
432
433
  # @param [String, Addressable::URI, #to_str] uri
433
434
  # The URI to encode.
434
435
  #
435
436
  # @param [Class] returning
436
- # The type of object to return. This value may only be set to
437
- # <tt>String</tt> or <tt>Addressable::URI</tt>. All other values
438
- # are invalid. Defaults to <tt>String</tt>.
437
+ # The type of object to return.
438
+ # This value may only be set to <tt>String</tt> or
439
+ # <tt>Addressable::URI</tt>. All other values are invalid. Defaults to
440
+ # <tt>String</tt>.
439
441
  #
440
442
  # @return [String, Addressable::URI]
441
- # The encoded URI. The return type is determined by
442
- # the <tt>returning</tt> parameter.
443
+ # The encoded URI.
444
+ # The return type is determined by the <tt>returning</tt> parameter.
443
445
  def self.normalized_encode(uri, returning=String)
444
446
  if !uri.respond_to?(:to_str)
445
447
  raise TypeError, "Can't convert #{uri.class} into String."
@@ -501,12 +503,12 @@ module Addressable
501
503
  # @option [String, #to_str] user The user component.
502
504
  # @option [String, #to_str] password The password component.
503
505
  # @option [String, #to_str] userinfo
504
- # The userinfo component. If this is supplied, the user and password
506
+ # The userinfo component. If this is supplied, the user and password
505
507
  # components must be omitted.
506
508
  # @option [String, #to_str] host The host component.
507
509
  # @option [String, #to_str] port The port component.
508
510
  # @option [String, #to_str] authority
509
- # The authority component. If this is supplied, the user, password,
511
+ # The authority component. If this is supplied, the user, password,
510
512
  # userinfo, host, and port components must be omitted.
511
513
  # @option [String, #to_str] path The path component.
512
514
  # @option [String, #to_str] query The query component.
@@ -581,6 +583,9 @@ module Addressable
581
583
  # Check for frozenness
582
584
  raise TypeError, "Can't modify frozen URI." if self.frozen?
583
585
 
586
+ if new_scheme && !new_scheme.respond_to?(:to_str)
587
+ raise TypeError, "Can't convert #{new_scheme.class} into String."
588
+ end
584
589
  @scheme = new_scheme ? new_scheme.to_str : nil
585
590
  @scheme = nil if @scheme.to_s.strip == ""
586
591
 
@@ -631,6 +636,9 @@ module Addressable
631
636
  # Check for frozenness
632
637
  raise TypeError, "Can't modify frozen URI." if self.frozen?
633
638
 
639
+ if new_user && !new_user.respond_to?(:to_str)
640
+ raise TypeError, "Can't convert #{new_user.class} into String."
641
+ end
634
642
  @user = new_user ? new_user.to_str : nil
635
643
 
636
644
  # You can't have a nil user with a non-nil password
@@ -689,6 +697,9 @@ module Addressable
689
697
  # Check for frozenness
690
698
  raise TypeError, "Can't modify frozen URI." if self.frozen?
691
699
 
700
+ if new_password && !new_password.respond_to?(:to_str)
701
+ raise TypeError, "Can't convert #{new_password.class} into String."
702
+ end
692
703
  @password = new_password ? new_password.to_str : nil
693
704
 
694
705
  # You can't have a nil user with a non-nil password
@@ -754,6 +765,9 @@ module Addressable
754
765
  # Check for frozenness
755
766
  raise TypeError, "Can't modify frozen URI." if self.frozen?
756
767
 
768
+ if new_userinfo && !new_userinfo.respond_to?(:to_str)
769
+ raise TypeError, "Can't convert #{new_userinfo.class} into String."
770
+ end
757
771
  new_user, new_password = if new_userinfo
758
772
  [
759
773
  new_userinfo.to_str.strip[/^(.*):/, 1],
@@ -816,6 +830,9 @@ module Addressable
816
830
  # Check for frozenness
817
831
  raise TypeError, "Can't modify frozen URI." if self.frozen?
818
832
 
833
+ if new_host && !new_host.respond_to?(:to_str)
834
+ raise TypeError, "Can't convert #{new_host.class} into String."
835
+ end
819
836
  @host = new_host ? new_host.to_str : nil
820
837
 
821
838
  # Reset dependant values
@@ -881,6 +898,9 @@ module Addressable
881
898
  raise TypeError, "Can't modify frozen URI." if self.frozen?
882
899
 
883
900
  if new_authority
901
+ if !new_authority.respond_to?(:to_str)
902
+ raise TypeError, "Can't convert #{new_authority.class} into String."
903
+ end
884
904
  new_authority = new_authority.to_str
885
905
  new_userinfo = new_authority[/^([^\[\]]*)@/, 1]
886
906
  if new_userinfo
@@ -894,10 +914,10 @@ module Addressable
894
914
  end
895
915
 
896
916
  # Password assigned first to ensure validity in case of nil
897
- self.password = new_password
898
- self.user = new_user
899
- self.host = new_host
900
- self.port = new_port
917
+ self.password = defined?(new_password) ? new_password : nil
918
+ self.user = defined?(new_user) ? new_user : nil
919
+ self.host = defined?(new_host) ? new_host : nil
920
+ self.port = defined?(new_port) ? new_port : nil
901
921
 
902
922
  # Reset dependant values
903
923
  @inferred_port = nil
@@ -909,7 +929,7 @@ module Addressable
909
929
  validate()
910
930
  end
911
931
 
912
- # Returns an array of known ip-based schemes. These schemes typically
932
+ # Returns an array of known ip-based schemes. These schemes typically
913
933
  # use a similar URI form:
914
934
  # //<user>:<password>@<host>:<port>/<url-path>
915
935
  def self.ip_based_schemes
@@ -917,7 +937,7 @@ module Addressable
917
937
  end
918
938
 
919
939
  # Returns a hash of common IP-based schemes and their default port
920
- # numbers. Adding new schemes to this hash, as necessary, will allow
940
+ # numbers. Adding new schemes to this hash, as necessary, will allow
921
941
  # for better URI normalization.
922
942
  def self.port_mapping
923
943
  @port_mapping ||= {
@@ -939,7 +959,7 @@ module Addressable
939
959
 
940
960
  ##
941
961
  # The port component for this URI.
942
- # This is the port number actually given in the URI. This does not
962
+ # This is the port number actually given in the URI. This does not
943
963
  # infer port numbers from default values.
944
964
  #
945
965
  # @return [Integer] The port component.
@@ -1054,6 +1074,9 @@ module Addressable
1054
1074
  # Check for frozenness
1055
1075
  raise TypeError, "Can't modify frozen URI." if self.frozen?
1056
1076
 
1077
+ if new_path && !new_path.respond_to?(:to_str)
1078
+ raise TypeError, "Can't convert #{new_path.class} into String."
1079
+ end
1057
1080
  @path = (new_path || "").to_str
1058
1081
  if @path != "" && @path[0..0] != "/" && host != nil
1059
1082
  @path = "/#{@path}"
@@ -1098,11 +1121,19 @@ module Addressable
1098
1121
  def normalized_query
1099
1122
  @normalized_query ||= (begin
1100
1123
  if self.query
1101
- Addressable::URI.encode_component(
1102
- Addressable::IDNA.unicode_normalize_kc(
1103
- Addressable::URI.unencode_component(self.query.strip)),
1104
- Addressable::URI::CharacterClasses::QUERY
1105
- )
1124
+ begin
1125
+ Addressable::URI.encode_component(
1126
+ Addressable::IDNA.unicode_normalize_kc(
1127
+ Addressable::URI.unencode_component(self.query.strip)),
1128
+ Addressable::URI::CharacterClasses::QUERY
1129
+ )
1130
+ rescue ArgumentError
1131
+ # Likely a malformed UTF-8 character, skip unicode normalization
1132
+ Addressable::URI.encode_component(
1133
+ Addressable::URI.unencode_component(self.query.strip),
1134
+ Addressable::URI::CharacterClasses::QUERY
1135
+ )
1136
+ end
1106
1137
  else
1107
1138
  nil
1108
1139
  end
@@ -1117,6 +1148,9 @@ module Addressable
1117
1148
  # Check for frozenness
1118
1149
  raise TypeError, "Can't modify frozen URI." if self.frozen?
1119
1150
 
1151
+ if new_query && !new_query.respond_to?(:to_str)
1152
+ raise TypeError, "Can't convert #{new_query.class} into String."
1153
+ end
1120
1154
  @query = new_query ? new_query.to_str : nil
1121
1155
 
1122
1156
  # Reset dependant values
@@ -1129,8 +1163,8 @@ module Addressable
1129
1163
  #
1130
1164
  # @option [Symbol] notation
1131
1165
  # May be one of <tt>:flat</tt>, <tt>:dot</tt>, or <tt>:subscript</tt>.
1132
- # The <tt>:dot</tt> notation is not supported for assignment.
1133
- # Default value is <tt>:subscript</tt>.
1166
+ # The <tt>:dot</tt> notation is not supported for assignment. Default
1167
+ # value is <tt>:subscript</tt>.
1134
1168
  #
1135
1169
  # @return [Hash] The query string parsed as a Hash object.
1136
1170
  #
@@ -1285,11 +1319,19 @@ module Addressable
1285
1319
  def normalized_fragment
1286
1320
  @normalized_fragment ||= (begin
1287
1321
  if self.fragment
1288
- Addressable::URI.encode_component(
1289
- Addressable::IDNA.unicode_normalize_kc(
1290
- Addressable::URI.unencode_component(self.fragment.strip)),
1291
- Addressable::URI::CharacterClasses::FRAGMENT
1292
- )
1322
+ begin
1323
+ Addressable::URI.encode_component(
1324
+ Addressable::IDNA.unicode_normalize_kc(
1325
+ Addressable::URI.unencode_component(self.fragment.strip)),
1326
+ Addressable::URI::CharacterClasses::FRAGMENT
1327
+ )
1328
+ rescue ArgumentError
1329
+ # Likely a malformed UTF-8 character, skip unicode normalization
1330
+ Addressable::URI.encode_component(
1331
+ Addressable::URI.unencode_component(self.fragment.strip),
1332
+ Addressable::URI::CharacterClasses::FRAGMENT
1333
+ )
1334
+ end
1293
1335
  else
1294
1336
  nil
1295
1337
  end
@@ -1304,6 +1346,9 @@ module Addressable
1304
1346
  # Check for frozenness
1305
1347
  raise TypeError, "Can't modify frozen URI." if self.frozen?
1306
1348
 
1349
+ if new_fragment && !new_fragment.respond_to?(:to_str)
1350
+ raise TypeError, "Can't convert #{new_fragment.class} into String."
1351
+ end
1307
1352
  @fragment = new_fragment ? new_fragment.to_str : nil
1308
1353
 
1309
1354
  # Reset dependant values
@@ -1318,8 +1363,8 @@ module Addressable
1318
1363
  # Determines if the scheme indicates an IP-based protocol.
1319
1364
  #
1320
1365
  # @return [TrueClass, FalseClass]
1321
- # <tt>true</tt> if the scheme indicates an IP-based protocol.
1322
- # <tt>false</tt> otherwise.
1366
+ # <tt>true</tt> if the scheme indicates an IP-based protocol.
1367
+ # <tt>false</tt> otherwise.
1323
1368
  def ip_based?
1324
1369
  if self.scheme
1325
1370
  return self.class.ip_based_schemes.include?(
@@ -1332,8 +1377,7 @@ module Addressable
1332
1377
  # Determines if the URI is relative.
1333
1378
  #
1334
1379
  # @return [TrueClass, FalseClass]
1335
- # <tt>true</tt> if the URI is relative.
1336
- # <tt>false</tt> otherwise.
1380
+ # <tt>true</tt> if the URI is relative. <tt>false</tt> otherwise.
1337
1381
  def relative?
1338
1382
  return self.scheme.nil?
1339
1383
  end
@@ -1342,8 +1386,7 @@ module Addressable
1342
1386
  # Determines if the URI is absolute.
1343
1387
  #
1344
1388
  # @return [TrueClass, FalseClass]
1345
- # <tt>true</tt> if the URI is absolute.
1346
- # <tt>false</tt> otherwise.
1389
+ # <tt>true</tt> if the URI is absolute. <tt>false</tt> otherwise.
1347
1390
  def absolute?
1348
1391
  return !relative?
1349
1392
  end
@@ -1463,9 +1506,9 @@ module Addressable
1463
1506
 
1464
1507
  ##
1465
1508
  # Merges a URI with a <tt>Hash</tt> of components.
1466
- # This method has different behavior from <tt>join</tt>. Any components
1509
+ # This method has different behavior from <tt>join</tt>. Any components
1467
1510
  # present in the <tt>hash</tt> parameter will override the original
1468
- # components. The path component is not treated specially.
1511
+ # components. The path component is not treated specially.
1469
1512
  #
1470
1513
  # @param [Hash, Addressable::URI, #to_hash] The components to merge with.
1471
1514
  #
@@ -1541,8 +1584,8 @@ module Addressable
1541
1584
 
1542
1585
  ##
1543
1586
  # Returns the shortest normalized relative form of this URI that uses the
1544
- # supplied URI as a base for resolution. Returns an absolute URI if
1545
- # necessary. This is effectively the opposite of <tt>route_to</tt>.
1587
+ # supplied URI as a base for resolution. Returns an absolute URI if
1588
+ # necessary. This is effectively the opposite of <tt>route_to</tt>.
1546
1589
  #
1547
1590
  # @param [String, Addressable::URI, #to_str] uri The URI to route from.
1548
1591
  #
@@ -1599,8 +1642,8 @@ module Addressable
1599
1642
 
1600
1643
  ##
1601
1644
  # Returns the shortest normalized relative form of the supplied URI that
1602
- # uses this URI as a base for resolution. Returns an absolute URI if
1603
- # necessary. This is effectively the opposite of <tt>route_from</tt>.
1645
+ # uses this URI as a base for resolution. Returns an absolute URI if
1646
+ # necessary. This is effectively the opposite of <tt>route_from</tt>.
1604
1647
  #
1605
1648
  # @param [String, Addressable::URI, #to_str] uri The URI to route to.
1606
1649
  #
@@ -1651,7 +1694,7 @@ module Addressable
1651
1694
  end
1652
1695
 
1653
1696
  ##
1654
- # Creates a URI suitable for display to users. If semantic attacks are
1697
+ # Creates a URI suitable for display to users. If semantic attacks are
1655
1698
  # likely, the application should try to detect these and warn the user.
1656
1699
  # See <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>,
1657
1700
  # section 7.6 for more information.
@@ -1664,7 +1707,7 @@ module Addressable
1664
1707
  end
1665
1708
 
1666
1709
  ##
1667
- # Returns <tt>true</tt> if the URI objects are equal. This method
1710
+ # Returns <tt>true</tt> if the URI objects are equal. This method
1668
1711
  # normalizes both URIs before doing the comparison, and allows comparison
1669
1712
  # against <tt>Strings</tt>.
1670
1713
  #
@@ -1686,7 +1729,7 @@ module Addressable
1686
1729
  end
1687
1730
 
1688
1731
  ##
1689
- # Returns <tt>true</tt> if the URI objects are equal. This method
1732
+ # Returns <tt>true</tt> if the URI objects are equal. This method
1690
1733
  # normalizes both URIs before doing the comparison.
1691
1734
  #
1692
1735
  # @param [Object] uri The URI to compare.
@@ -1699,7 +1742,7 @@ module Addressable
1699
1742
  end
1700
1743
 
1701
1744
  ##
1702
- # Returns <tt>true</tt> if the URI objects are equal. This method
1745
+ # Returns <tt>true</tt> if the URI objects are equal. This method
1703
1746
  # does NOT normalize either URI before doing the comparison.
1704
1747
  #
1705
1748
  # @param [Object] uri The URI to compare.
@@ -1746,7 +1789,7 @@ module Addressable
1746
1789
  # Unfortunately, because of the memoized implementation of many of the
1747
1790
  # URI methods, the default freeze method will cause unexpected errors.
1748
1791
  # As an alternative, we freeze the string representation of the URI
1749
- # instead. This should generally produce the desired effect.
1792
+ # instead. This should generally produce the desired effect.
1750
1793
  self.to_s.freeze
1751
1794
  return self
1752
1795
  end
@@ -1823,7 +1866,7 @@ module Addressable
1823
1866
  end
1824
1867
 
1825
1868
  ##
1826
- # URI's are glorified <tt>Strings</tt>. Allow implicit conversion.
1869
+ # URI's are glorified <tt>Strings</tt>. Allow implicit conversion.
1827
1870
  alias_method :to_str, :to_s
1828
1871
 
1829
1872
  ##
@@ -28,7 +28,7 @@ if !defined?(Addressable::VERSION)
28
28
  module VERSION #:nodoc:
29
29
  MAJOR = 2
30
30
  MINOR = 1
31
- TINY = 0
31
+ TINY = 1
32
32
 
33
33
  STRING = [MAJOR, MINOR, TINY].join('.')
34
34
  end
@@ -22,9 +22,6 @@
22
22
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
  #++
24
24
 
25
- $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../../lib'))
26
- $:.uniq!
27
-
28
25
  require "addressable/idna"
29
26
 
30
27
  describe Addressable::IDNA, "when converting from unicode to ASCII" do
@@ -22,10 +22,6 @@
22
22
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
  #++
24
24
 
25
- $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../../lib'))
26
- $:.uniq!
27
-
28
- require "addressable/uri"
29
25
  require "addressable/template"
30
26
 
31
27
  if !"".respond_to?("force_encoding")
@@ -1341,6 +1337,54 @@ describe Addressable::URI, "when given a simple mapping" do
1341
1337
  end
1342
1338
  end
1343
1339
 
1340
+ describe Addressable::URI, "extracting defaults from a pattern" do
1341
+ before do
1342
+ @template = Addressable::Template.new("{foo}{bar=baz}{-opt|found|cond}")
1343
+ end
1344
+
1345
+ it "should extract default value" do
1346
+ @template.variable_defaults.should == {"bar" => "baz"}
1347
+ end
1348
+ end
1349
+
1350
+ describe Addressable::URI, "when given a mapping with symbol keys" do
1351
+ before do
1352
+ @mapping = { :name => "fred" }
1353
+ end
1354
+
1355
+ it "should result in 'fred' when used to expand '{foo}'" do
1356
+ Addressable::Template.new(
1357
+ "{name}"
1358
+ ).expand(@mapping).to_s.should == "fred"
1359
+ end
1360
+ end
1361
+
1362
+ describe Addressable::URI, "when given a mapping with bogus keys" do
1363
+ before do
1364
+ @mapping = { Object.new => "fred" }
1365
+ end
1366
+
1367
+ it "should raise an error" do
1368
+ (lambda do
1369
+ Addressable::Template.new(
1370
+ "{name}"
1371
+ ).expand(@mapping)
1372
+ end).should raise_error(TypeError)
1373
+ end
1374
+ end
1375
+
1376
+ describe Addressable::URI, "when given a mapping with numeric values" do
1377
+ before do
1378
+ @mapping = { :id => 123 }
1379
+ end
1380
+
1381
+ it "should result in 'fred' when used to expand '{foo}'" do
1382
+ Addressable::Template.new(
1383
+ "{id}"
1384
+ ).expand(@mapping).to_s.should == "123"
1385
+ end
1386
+ end
1387
+
1344
1388
  describe Addressable::URI, "when given a mapping containing values " +
1345
1389
  "that are already percent-encoded" do
1346
1390
  before do
@@ -1357,18 +1401,6 @@ describe Addressable::URI, "when given a mapping containing values " +
1357
1401
  end
1358
1402
  end
1359
1403
 
1360
- describe Addressable::URI, "when given a mapping containing bogus values" do
1361
- it "should raise a TypeError" do
1362
- (lambda do
1363
- Addressable::Template.new(
1364
- "http://example.com/{bogus}/"
1365
- ).expand({
1366
- "bogus" => 42
1367
- })
1368
- end).should raise_error(TypeError)
1369
- end
1370
- end
1371
-
1372
1404
  describe Addressable::URI, "when given a pattern with bogus operators" do
1373
1405
  it "should raise an InvalidTemplateOperatorError" do
1374
1406
  (lambda do
@@ -22,9 +22,6 @@
22
22
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
  #++
24
24
 
25
- $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../../lib'))
26
- $:.uniq!
27
-
28
25
  require "addressable/uri"
29
26
 
30
27
  if !"".respond_to?("force_encoding")
@@ -72,6 +69,86 @@ describe Addressable::URI, "when created with a non-numeric port number" do
72
69
  end
73
70
  end
74
71
 
72
+ describe Addressable::URI, "when created with a non-string scheme" do
73
+ it "should raise an error" do
74
+ (lambda do
75
+ Addressable::URI.new(:scheme => :bogus)
76
+ end).should raise_error(TypeError)
77
+ end
78
+ end
79
+
80
+ describe Addressable::URI, "when created with a non-string user" do
81
+ it "should raise an error" do
82
+ (lambda do
83
+ Addressable::URI.new(:user => :bogus)
84
+ end).should raise_error(TypeError)
85
+ end
86
+ end
87
+
88
+ describe Addressable::URI, "when created with a non-string password" do
89
+ it "should raise an error" do
90
+ (lambda do
91
+ Addressable::URI.new(:password => :bogus)
92
+ end).should raise_error(TypeError)
93
+ end
94
+ end
95
+
96
+ describe Addressable::URI, "when created with a non-string userinfo" do
97
+ it "should raise an error" do
98
+ (lambda do
99
+ Addressable::URI.new(:userinfo => :bogus)
100
+ end).should raise_error(TypeError)
101
+ end
102
+ end
103
+
104
+ describe Addressable::URI, "when created with a non-string host" do
105
+ it "should raise an error" do
106
+ (lambda do
107
+ Addressable::URI.new(:host => :bogus)
108
+ end).should raise_error(TypeError)
109
+ end
110
+ end
111
+
112
+ describe Addressable::URI, "when created with a non-string authority" do
113
+ it "should raise an error" do
114
+ (lambda do
115
+ Addressable::URI.new(:authority => :bogus)
116
+ end).should raise_error(TypeError)
117
+ end
118
+ end
119
+
120
+ describe Addressable::URI, "when created with a non-string authority" do
121
+ it "should raise an error" do
122
+ (lambda do
123
+ Addressable::URI.new(:authority => :bogus)
124
+ end).should raise_error(TypeError)
125
+ end
126
+ end
127
+
128
+ describe Addressable::URI, "when created with a non-string path" do
129
+ it "should raise an error" do
130
+ (lambda do
131
+ Addressable::URI.new(:path => :bogus)
132
+ end).should raise_error(TypeError)
133
+ end
134
+ end
135
+
136
+ describe Addressable::URI, "when created with a non-string query" do
137
+ it "should raise an error" do
138
+ (lambda do
139
+ Addressable::URI.new(:query => :bogus)
140
+ end).should raise_error(TypeError)
141
+ end
142
+ end
143
+
144
+ describe Addressable::URI, "when created with a non-string fragment" do
145
+ it "should raise an error" do
146
+ (lambda do
147
+ Addressable::URI.new(:fragment => :bogus)
148
+ end).should raise_error(TypeError)
149
+ end
150
+ end
151
+
75
152
  describe Addressable::URI, "when created with a scheme but no hierarchical " +
76
153
  "segment" do
77
154
  it "should raise an error" do
@@ -944,6 +1021,54 @@ describe Addressable::URI, "when parsed from " +
944
1021
  end
945
1022
  end
946
1023
 
1024
+ describe Addressable::URI, "when parsed from " +
1025
+ "'http://example.com/?%F6'" do
1026
+ before do
1027
+ @uri = Addressable::URI.parse("http://example.com/?%F6")
1028
+ end
1029
+
1030
+ it "should not raise an exception when normalized" do
1031
+ (lambda do
1032
+ @uri.normalize
1033
+ end).should_not raise_error(ArgumentError)
1034
+ end
1035
+
1036
+ it "should be considered to be in normal form" do
1037
+ @uri.normalize.should be_eql(@uri)
1038
+ end
1039
+
1040
+ it "should not change if encoded with the normalizing algorithm" do
1041
+ Addressable::URI.normalized_encode(@uri).to_s.should ==
1042
+ "http://example.com/?%F6"
1043
+ Addressable::URI.normalized_encode(@uri, Addressable::URI).to_s.should ===
1044
+ "http://example.com/?%F6"
1045
+ end
1046
+ end
1047
+
1048
+ describe Addressable::URI, "when parsed from " +
1049
+ "'http://example.com/#%F6'" do
1050
+ before do
1051
+ @uri = Addressable::URI.parse("http://example.com/#%F6")
1052
+ end
1053
+
1054
+ it "should not raise an exception when normalized" do
1055
+ (lambda do
1056
+ @uri.normalize
1057
+ end).should_not raise_error(ArgumentError)
1058
+ end
1059
+
1060
+ it "should be considered to be in normal form" do
1061
+ @uri.normalize.should be_eql(@uri)
1062
+ end
1063
+
1064
+ it "should not change if encoded with the normalizing algorithm" do
1065
+ Addressable::URI.normalized_encode(@uri).to_s.should ==
1066
+ "http://example.com/#%F6"
1067
+ Addressable::URI.normalized_encode(@uri, Addressable::URI).to_s.should ===
1068
+ "http://example.com/#%F6"
1069
+ end
1070
+ end
1071
+
947
1072
  describe Addressable::URI, "when parsed from " +
948
1073
  "'http://example.com/%C3%87'" do
949
1074
  before do
@@ -1,14 +1,10 @@
1
- require 'spec/rake/verify_rcov'
2
-
3
1
  namespace :spec do
4
2
  Spec::Rake::SpecTask.new(:rcov) do |t|
3
+ t.libs = %w[lib spec]
5
4
  t.spec_files = FileList['spec/**/*_spec.rb']
6
5
  t.spec_opts = ['--color', '--format', 'specdoc']
7
- if RCOV_ENABLED
8
- t.rcov = true
9
- else
10
- t.rcov = false
11
- end
6
+
7
+ t.rcov = RCOV_ENABLED
12
8
  t.rcov_opts = [
13
9
  '--exclude', 'spec',
14
10
  '--exclude', '1\\.8\\/gems',
@@ -18,27 +14,19 @@ namespace :spec do
18
14
  end
19
15
 
20
16
  Spec::Rake::SpecTask.new(:normal) do |t|
17
+ t.libs = %w[lib spec]
21
18
  t.spec_files = FileList['spec/**/*_spec.rb']
22
19
  t.spec_opts = ['--color', '--format', 'specdoc']
23
20
  t.rcov = false
24
21
  end
25
22
 
26
- if RCOV_ENABLED
27
- RCov::VerifyTask.new(:verify) do |t|
28
- t.threshold = 100.0
29
- t.index_html = 'coverage/index.html'
30
- end
31
-
32
- task :verify => :rcov
33
- end
34
-
35
23
  desc "Generate HTML Specdocs for all specs"
36
24
  Spec::Rake::SpecTask.new(:specdoc) do |t|
37
- specdoc_path = File.expand_path(
38
- File.join(File.dirname(__FILE__), '../specdoc/'))
25
+ specdoc_path = File.expand_path(File.join(File.dirname(__FILE__), '..', 'specdoc'))
39
26
  Dir.mkdir(specdoc_path) if !File.exist?(specdoc_path)
40
27
 
41
28
  output_file = File.join(specdoc_path, 'index.html')
29
+ t.libs = %w[lib spec]
42
30
  t.spec_files = FileList['spec/**/*_spec.rb']
43
31
  t.spec_opts = ["--format", "\"html:#{output_file}\"", "--diff"]
44
32
  t.fail_on_error = false
@@ -53,12 +41,7 @@ namespace :spec do
53
41
  end
54
42
  end
55
43
 
56
- if RCOV_ENABLED
57
- desc "Alias to spec:verify"
58
- task "spec" => "spec:verify"
59
- else
60
- desc "Alias to spec:normal"
61
- task "spec" => "spec:normal"
62
- end
44
+ desc "Alias to spec:normal"
45
+ task "spec" => "spec:normal"
63
46
 
64
47
  task "clobber" => ["spec:clobber_rcov"]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: addressable
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bob Aman
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-05-19 00:00:00 -04:00
12
+ date: 2009-10-31 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -42,7 +42,11 @@ dependencies:
42
42
  - !ruby/object:Gem::Version
43
43
  version: 0.3.2
44
44
  version:
45
- description: Addressable is a replacement for the URI implementation that is part of Ruby's standard library. It more closely conforms to the relevant RFCs and adds support for IRIs and URI templates.
45
+ description: |
46
+ Addressable is a replacement for the URI implementation that is part of
47
+ Ruby's standard library. It more closely conforms to the relevant RFCs and
48
+ adds support for IRIs and URI templates.
49
+
46
50
  email: bob@sporkmonger.com
47
51
  executables: []
48
52
 
@@ -51,16 +55,13 @@ extensions: []
51
55
  extra_rdoc_files:
52
56
  - README
53
57
  files:
54
- - lib/addressable
55
58
  - lib/addressable/idna.rb
56
59
  - lib/addressable/template.rb
57
60
  - lib/addressable/uri.rb
58
61
  - lib/addressable/version.rb
59
- - spec/addressable
60
62
  - spec/addressable/idna_spec.rb
61
63
  - spec/addressable/template_spec.rb
62
64
  - spec/addressable/uri_spec.rb
63
- - spec/data
64
65
  - spec/data/rfc3986.txt
65
66
  - tasks/clobber.rake
66
67
  - tasks/gem.rake
@@ -76,6 +77,8 @@ files:
76
77
  - README
77
78
  has_rdoc: true
78
79
  homepage: http://addressable.rubyforge.org/
80
+ licenses: []
81
+
79
82
  post_install_message:
80
83
  rdoc_options:
81
84
  - --main
@@ -97,9 +100,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
97
100
  requirements: []
98
101
 
99
102
  rubyforge_project: addressable
100
- rubygems_version: 1.3.1
103
+ rubygems_version: 1.3.5
101
104
  signing_key:
102
- specification_version: 2
105
+ specification_version: 3
103
106
  summary: URI Implementation
104
107
  test_files: []
105
108