ruby-changes:30765
From: drbrain <ko1@a...>
Date: Thu, 5 Sep 2013 14:02:25 +0900 (JST)
Subject: [ruby-changes:30765] drbrain:r42844 (trunk): * lib/optparse.rb: The Integer acceptable now allows binary and
drbrain 2013-09-05 14:02:17 +0900 (Thu, 05 Sep 2013) New Revision: 42844 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=42844 Log: * lib/optparse.rb: The Integer acceptable now allows binary and hexadecimal numbers per the documentation. [ruby-trunk - Bug #8865] DecimalInteger, OctalInteger, DecimalNumeric now validate their input before converting to a number. [ruby-trunk - Bug #8865] * test/optparse/test_acceptable.rb: Tests for the above, tests for all numeric acceptables for existing behavior. Added files: trunk/test/optparse/test_acceptable.rb Modified files: trunk/ChangeLog trunk/lib/optparse.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 42843) +++ ChangeLog (revision 42844) @@ -1,3 +1,14 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Thu Sep 5 14:01:22 2013 Eric Hodel <drbrain@s...> + + * lib/optparse.rb: The Integer acceptable now allows binary and + hexadecimal numbers per the documentation. [ruby-trunk - Bug #8865] + + DecimalInteger, OctalInteger, DecimalNumeric now validate their input + before converting to a number. [ruby-trunk - Bug #8865] + + * test/optparse/test_acceptable.rb: Tests for the above, tests for all + numeric acceptables for existing behavior. + Thu Sep 5 13:49:00 2013 Charlie Somerville <charliesome@r...> * include/ruby/ruby.h: add RSTRING_FSTR flag Index: lib/optparse.rb =================================================================== --- lib/optparse.rb (revision 42843) +++ lib/optparse.rb (revision 42844) @@ -1637,15 +1637,22 @@ XXX https://github.com/ruby/ruby/blob/trunk/lib/optparse.rb#L1637 decimal = '\d+(?:_\d+)*' binary = 'b[01]+(?:_[01]+)*' hex = 'x[\da-f]+(?:_[\da-f]+)*' - octal = "0(?:[0-7]*(?:_[0-7]+)*|#{binary}|#{hex})" + octal = "0(?:[0-7]+(?:_[0-7]+)*|#{binary}|#{hex})?" integer = "#{octal}|#{decimal}" - accept(Integer, %r"\A[-+]?(?:#{integer})"io) {|s,| Integer(s) if s} + + accept(Integer, %r"\A[-+]?(?:#{integer})\z"io) {|s,| + begin + Integer(s) + rescue ArgumentError + raise OptionParser::InvalidArgument, s + end if s + } # # Float number format, and converts to Float. # float = "(?:#{decimal}(?:\\.(?:#{decimal})?)?|\\.#{decimal})(?:E[-+]?#{decimal})?" - floatpat = %r"\A[-+]?#{float}"io + floatpat = %r"\A[-+]?#{float}\z"io accept(Float, floatpat) {|s,| s.to_f if s} # @@ -1653,7 +1660,7 @@ XXX https://github.com/ruby/ruby/blob/trunk/lib/optparse.rb#L1660 # for float format, and Rational for rational format. # real = "[-+]?(?:#{octal}|#{float})" - accept(Numeric, /\A(#{real})(?:\/(#{real}))?/io) {|s, d, n| + accept(Numeric, /\A(#{real})(?:\/(#{real}))?\z/io) {|s, d, n| if n Rational(d, n) elsif s @@ -1664,22 +1671,40 @@ XXX https://github.com/ruby/ruby/blob/trunk/lib/optparse.rb#L1671 # # Decimal integer format, to be converted to Integer. # - DecimalInteger = /\A[-+]?#{decimal}/io - accept(DecimalInteger) {|s,| s.to_i if s} + DecimalInteger = /\A[-+]?#{decimal}\z/io + accept(DecimalInteger, DecimalInteger) {|s,| + begin + Integer(s) + rescue ArgumentError + raise OptionParser::InvalidArgument, s + end if s + } # # Ruby/C like octal/hexadecimal/binary integer format, to be converted to # Integer. # - OctalInteger = /\A[-+]?(?:[0-7]+(?:_[0-7]+)*|0(?:#{binary}|#{hex}))/io - accept(OctalInteger) {|s,| s.oct if s} + OctalInteger = /\A[-+]?(?:[0-7]+(?:_[0-7]+)*|0(?:#{binary}|#{hex}))\z/io + accept(OctalInteger, OctalInteger) {|s,| + begin + Integer(s, 8) + rescue ArgumentError + raise OptionParser::InvalidArgument, s + end if s + } # # Decimal integer/float number format, to be converted to Integer for # integer format, Float for float format. # DecimalNumeric = floatpat # decimal integer is allowed as float also. - accept(DecimalNumeric) {|s,| eval(s) if s} + accept(DecimalNumeric, floatpat) {|s,| + begin + eval(s) + rescue SyntaxError + raise OptionParser::InvalidArgument, s + end if s + } # # Boolean switch, which means whether it is present or not, whether it is Index: test/optparse/test_acceptable.rb =================================================================== --- test/optparse/test_acceptable.rb (revision 0) +++ test/optparse/test_acceptable.rb (revision 42844) @@ -0,0 +1,195 @@ https://github.com/ruby/ruby/blob/trunk/test/optparse/test_acceptable.rb#L1 +require_relative 'test_optparse' + +class TestOptionParser::Acceptable < TestOptionParser + + def setup + super + @opt.def_option("--integer VAL", Integer) { |v| @integer = v } + @opt.def_option("--float VAL", Float) { |v| @float = v } + @opt.def_option("--numeric VAL", Numeric) { |v| @numeric = v } + + @opt.def_option("--decimal-integer VAL", + OptionParser::DecimalInteger) { |i| @decimal_integer = i } + @opt.def_option("--octal-integer VAL", + OptionParser::OctalInteger) { |i| @octal_integer = i } + @opt.def_option("--decimal-numeric VAL", + OptionParser::DecimalNumeric) { |i| @decimal_numeric = i } + end + + def test_integer + assert_equal(%w"", no_error {@opt.parse!(%w"--integer 0")}) + assert_equal(0, @integer) + + assert_equal(%w"", no_error {@opt.parse!(%w"--integer 0b10")}) + assert_equal(2, @integer) + + assert_equal(%w"", no_error {@opt.parse!(%w"--integer 077")}) + assert_equal(63, @integer) + + assert_equal(%w"", no_error {@opt.parse!(%w"--integer 10")}) + assert_equal(10, @integer) + + assert_equal(%w"", no_error {@opt.parse!(%w"--integer 0x3")}) + assert_equal(3, @integer) + + assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--integer 0b") + end + + assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--integer 09") + end + + assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--integer 0x") + end + + assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--integer 1234xyz") + end + end + + def test_float + assert_equal(%w"", no_error {@opt.parse!(%w"--float 0")}) + assert_in_epsilon(0.0, @float) + + assert_equal(%w"", no_error {@opt.parse!(%w"--float 0.0")}) + assert_in_epsilon(0.0, @float) + + assert_equal(%w"", no_error {@opt.parse!(%w"--float 1.2")}) + assert_in_epsilon(1.2, @float) + + assert_equal(%w"", no_error {@opt.parse!(%w"--float 1E2")}) + assert_in_epsilon(100, @float) + + assert_equal(%w"", no_error {@opt.parse!(%w"--float 1E-2")}) + assert_in_epsilon(0.01, @float) + + assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--float 0e") + end + + assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--float 1.234xyz") + end + end + + def test_numeric + assert_equal(%w"", no_error {@opt.parse!(%w"--numeric 0")}) + assert_equal(0, @numeric) + + assert_equal(%w"", no_error {@opt.parse!(%w"--numeric 0/1")}) + assert_equal(0, @numeric) + + assert_equal(%w"", no_error {@opt.parse!(%w"--numeric 1/2")}) + assert_equal(Rational(1, 2), @numeric) + + assert_equal(%w"", no_error {@opt.parse!(%w"--numeric 1.2/2.3")}) + assert_equal(Rational(12, 23), @numeric) + + assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--numeric 1/") + end + + assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--numeric 12/34xyz") + end + + assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--numeric 12x/34yz") + end + end + + def test_decimal_integer + assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-integer 0")}) + assert_equal(0, @decimal_integer) + + assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-integer 10")}) + assert_equal(10, @decimal_integer) + + assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--decimal-integer 0b1") + end + + e = assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--decimal-integer 09") + end + + assert_equal("invalid argument: --decimal-integer 09", e.message) + + assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--decimal-integer x") + end + + assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--decimal-integer 1234xyz") + end + end + + def test_octal_integer + assert_equal(%w"", no_error {@opt.parse!(%w"--octal-integer 0")}) + assert_equal(0, @octal_integer) + + assert_equal(%w"", no_error {@opt.parse!(%w"--octal-integer 6")}) + assert_equal(6, @octal_integer) + + assert_equal(%w"", no_error {@opt.parse!(%w"--octal-integer 07")}) + assert_equal(7, @octal_integer) + + assert_equal(%w"", no_error {@opt.parse!(%w"--octal-integer 10")}) + assert_equal(8, @octal_integer) + + assert_equal(%w"", no_error {@opt.parse!(%w"--octal-integer 011")}) + assert_equal(9, @octal_integer) + + assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--octal-integer 09") + end + + assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--octal-integer 0b1") + end + + assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--octal-integer x") + end + + assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--octal-integer 01234xyz") + end + end + + def test_decimal_numeric + assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-numeric 0")}) + assert_equal(0, @decimal_numeric) + + assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-numeric 01")}) + assert_equal(1, @decimal_numeric) + + assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-numeric 1.2")}) + assert_in_delta(1.2, @decimal_numeric) + + assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-numeric 1E2")}) + assert_in_delta(100.0, @decimal_numeric) + + assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--decimal-numeric 0b1") + end + + e = assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--decimal-numeric 09") + end + + assert_equal("invalid argument: --decimal-numeric 09", e.message) + + assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--decimal-integer 1234xyz") + end + + assert_raises(OptionParser::InvalidArgument) do + @opt.parse!(%w"--decimal-integer 12.34xyz") + end + end + +end + -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/