must_be 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -0
- data/README.md +348 -0
- data/Rakefile +27 -0
- data/VERSION +1 -0
- data/doc/readme/examples.rb +262 -0
- data/doc/readme/run_examples.rb +47 -0
- data/lib/must_be/attr_typed.rb +78 -0
- data/lib/must_be/basic.rb +120 -0
- data/lib/must_be/containers.rb +291 -0
- data/lib/must_be/containers_registered_classes.rb +83 -0
- data/lib/must_be/core.rb +247 -0
- data/lib/must_be/nonstandard_control_flow.rb +159 -0
- data/lib/must_be/proxy.rb +62 -0
- data/lib/must_be.rb +9 -0
- data/must_be.gemspec +71 -0
- data/spec/must_be/attr_typed_spec.rb +225 -0
- data/spec/must_be/basic_spec.rb +578 -0
- data/spec/must_be/containers_spec.rb +952 -0
- data/spec/must_be/core_spec.rb +675 -0
- data/spec/must_be/nonstandard_control_flow_spec.rb +845 -0
- data/spec/must_be/proxy_spec.rb +194 -0
- data/spec/notify_matcher_spec.rb +59 -0
- data/spec/spec_helper.rb +180 -0
- data/spec/typical_usage_spec.rb +176 -0
- metadata +98 -0
    
        data/lib/must_be/core.rb
    ADDED
    
    | @@ -0,0 +1,247 @@ | |
| 1 | 
            +
            module MustBe
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              ### Short Inspect ###
         | 
| 4 | 
            +
              
         | 
| 5 | 
            +
              SHORT_INSPECT_CUTOFF_LENGTH = 200
         | 
| 6 | 
            +
              SHORT_INSPECT_WORD_BREAK_LENGTH = 20
         | 
| 7 | 
            +
              SHORT_INSPECT_ELLIPSES = "..."
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              def self.short_inspect(obj)
         | 
| 10 | 
            +
                s = obj.inspect
         | 
| 11 | 
            +
                if s.bytesize > SHORT_INSPECT_CUTOFF_LENGTH
         | 
| 12 | 
            +
                  real_cutoff = SHORT_INSPECT_CUTOFF_LENGTH - SHORT_INSPECT_ELLIPSES.length
         | 
| 13 | 
            +
                  left_side = (real_cutoff + 1) / 2
         | 
| 14 | 
            +
                  right_side = -(real_cutoff / 2)
         | 
| 15 | 
            +
                  
         | 
| 16 | 
            +
                  left_start = left_side - SHORT_INSPECT_WORD_BREAK_LENGTH
         | 
| 17 | 
            +
                  left_word_break_area = s[left_start, SHORT_INSPECT_WORD_BREAK_LENGTH]
         | 
| 18 | 
            +
                  left_word_break = left_word_break_area.rindex(/\b\s/)
         | 
| 19 | 
            +
                  start = left_word_break ? left_start + left_word_break + 1 : left_side
         | 
| 20 | 
            +
                  
         | 
| 21 | 
            +
                  right_start = right_side
         | 
| 22 | 
            +
                  right_word_break_area = s[right_start, SHORT_INSPECT_WORD_BREAK_LENGTH]
         | 
| 23 | 
            +
                  right_word_break = right_word_break_area.index(/\s\b/)
         | 
| 24 | 
            +
                  stop = right_word_break ? right_start + right_word_break : right_side
         | 
| 25 | 
            +
                  
         | 
| 26 | 
            +
                  s[start...stop] = SHORT_INSPECT_ELLIPSES
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
                s
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
              
         | 
| 31 | 
            +
              ### Enable ###
         | 
| 32 | 
            +
              
         | 
| 33 | 
            +
              @@disabled_method_for_method = Hash.new(:must_just_return)
         | 
| 34 | 
            +
              @@disabled_handlers = []
         | 
| 35 | 
            +
              
         | 
| 36 | 
            +
              class <<self
         | 
| 37 | 
            +
                def disable
         | 
| 38 | 
            +
                  return unless enabled?
         | 
| 39 | 
            +
                  
         | 
| 40 | 
            +
                  @disabled_methods = instance_methods.map do |method_name|
         | 
| 41 | 
            +
                    method_name = method_name.to_sym
         | 
| 42 | 
            +
                    method = instance_method(method_name)
         | 
| 43 | 
            +
                    disabled_method_name = @@disabled_method_for_method[method_name]
         | 
| 44 | 
            +
                    alias_method method_name, disabled_method_name
         | 
| 45 | 
            +
                    [method_name, method]
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
                  invoke_disabled_handlers
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
                
         | 
| 50 | 
            +
                def enable
         | 
| 51 | 
            +
                  return if enabled?
         | 
| 52 | 
            +
                  
         | 
| 53 | 
            +
                  @disabled_methods.each do |method_record|
         | 
| 54 | 
            +
                    define_method(*method_record)
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
                  @disabled_methods = nil
         | 
| 57 | 
            +
                  invoke_disabled_handlers
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
                
         | 
| 60 | 
            +
                def enabled?
         | 
| 61 | 
            +
                  @disabled_methods.nil?
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
                
         | 
| 64 | 
            +
                def register_disabled_method(method_name,
         | 
| 65 | 
            +
                    disabled_method_name = method_name)
         | 
| 66 | 
            +
                  @@disabled_method_for_method[method_name.to_sym] = 
         | 
| 67 | 
            +
                    disabled_method_name.to_sym
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
                
         | 
| 70 | 
            +
                def register_disabled_handler(&handler)
         | 
| 71 | 
            +
                  @@disabled_handlers << handler
         | 
| 72 | 
            +
                  handler[enabled?] unless enabled?
         | 
| 73 | 
            +
                end
         | 
| 74 | 
            +
                
         | 
| 75 | 
            +
              private
         | 
| 76 | 
            +
                
         | 
| 77 | 
            +
                def invoke_disabled_handlers
         | 
| 78 | 
            +
                  @@disabled_handlers.each {|handler| handler[enabled?] }
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
              end
         | 
| 81 | 
            +
              
         | 
| 82 | 
            +
              def must_just_return(*args)
         | 
| 83 | 
            +
                self
         | 
| 84 | 
            +
              end
         | 
| 85 | 
            +
              
         | 
| 86 | 
            +
              register_disabled_method(:must_just_return)
         | 
| 87 | 
            +
              
         | 
| 88 | 
            +
              def must_just_yield(*args)
         | 
| 89 | 
            +
                yield
         | 
| 90 | 
            +
              end
         | 
| 91 | 
            +
              
         | 
| 92 | 
            +
              register_disabled_method(:must_just_yield)
         | 
| 93 | 
            +
              
         | 
| 94 | 
            +
              ### Notifiers ###
         | 
| 95 | 
            +
              
         | 
| 96 | 
            +
              NOTIFIERS = {}
         | 
| 97 | 
            +
              
         | 
| 98 | 
            +
              class <<self
         | 
| 99 | 
            +
                attr_accessor :notifier # should respond_to? :call with Note argument.
         | 
| 100 | 
            +
                
         | 
| 101 | 
            +
                def def_notifier(constant_name, key = nil, ¬ifier)
         | 
| 102 | 
            +
                  const_set(constant_name, notifier)
         | 
| 103 | 
            +
                  NOTIFIERS[key] = constant_name if key
         | 
| 104 | 
            +
                end
         | 
| 105 | 
            +
                
         | 
| 106 | 
            +
                def set_notifier_from_env(key = ENV['MUST_BE__NOTIFIER'])
         | 
| 107 | 
            +
                  key = key.to_sym
         | 
| 108 | 
            +
                  
         | 
| 109 | 
            +
                  if key == :disable
         | 
| 110 | 
            +
                    disable
         | 
| 111 | 
            +
                    return
         | 
| 112 | 
            +
                  end
         | 
| 113 | 
            +
                  
         | 
| 114 | 
            +
                  constant_name = NOTIFIERS[key]
         | 
| 115 | 
            +
                  unless constant_name
         | 
| 116 | 
            +
                    raise ArgumentError, "no MustBe::NOTIFIERS called #{key.inspect}"
         | 
| 117 | 
            +
                  end
         | 
| 118 | 
            +
                  self.notifier = const_get(constant_name)
         | 
| 119 | 
            +
                end
         | 
| 120 | 
            +
              end
         | 
| 121 | 
            +
              
         | 
| 122 | 
            +
              def_notifier(:RaiseNotifier, :raise) {|note| true }
         | 
| 123 | 
            +
              
         | 
| 124 | 
            +
              def_notifier(:LogNotifier, :log) do |note|
         | 
| 125 | 
            +
                begin
         | 
| 126 | 
            +
                  raise note
         | 
| 127 | 
            +
                rescue Note
         | 
| 128 | 
            +
                  puts [note.message, *note.backtrace].join("\n\t")
         | 
| 129 | 
            +
                end
         | 
| 130 | 
            +
                false
         | 
| 131 | 
            +
              end
         | 
| 132 | 
            +
              
         | 
| 133 | 
            +
              def_notifier(:DebugNotifier, :debug) do |note|
         | 
| 134 | 
            +
                $must_be__note = note
         | 
| 135 | 
            +
                puts note.message
         | 
| 136 | 
            +
                puts "Starting debugger ($must_be__note stores the note)..."
         | 
| 137 | 
            +
                require 'ruby-debug'
         | 
| 138 | 
            +
                debugger
         | 
| 139 | 
            +
                false
         | 
| 140 | 
            +
              end
         | 
| 141 | 
            +
             | 
| 142 | 
            +
              set_notifier_from_env(ENV['MUST_BE__NOTIFIER'] || :raise)
         | 
| 143 | 
            +
              
         | 
| 144 | 
            +
              ### Note ###
         | 
| 145 | 
            +
              
         | 
| 146 | 
            +
              class Note < StandardError
         | 
| 147 | 
            +
                attr_accessor :receiver, :assertion, :args, :block, :additional_message,
         | 
| 148 | 
            +
                  :prefix
         | 
| 149 | 
            +
                
         | 
| 150 | 
            +
                def initialize(receiver, assertion = nil, args = nil, block = nil,
         | 
| 151 | 
            +
                    additional_message = nil)
         | 
| 152 | 
            +
                  if assertion
         | 
| 153 | 
            +
                    @receiver = receiver
         | 
| 154 | 
            +
                    @assertion = assertion
         | 
| 155 | 
            +
                    @args = args
         | 
| 156 | 
            +
                    @block = block
         | 
| 157 | 
            +
                    @additional_message = additional_message
         | 
| 158 | 
            +
                  else
         | 
| 159 | 
            +
                    super(receiver)
         | 
| 160 | 
            +
                  end
         | 
| 161 | 
            +
                end
         | 
| 162 | 
            +
                
         | 
| 163 | 
            +
                def to_s
         | 
| 164 | 
            +
                  if assertion
         | 
| 165 | 
            +
                    "#{prefix}#{MustBe.short_inspect(receiver)}."\
         | 
| 166 | 
            +
                      "#{assertion}#{format_args_and_block}#{additional_message}"
         | 
| 167 | 
            +
                  else
         | 
| 168 | 
            +
                    super
         | 
| 169 | 
            +
                  end
         | 
| 170 | 
            +
                end
         | 
| 171 | 
            +
                    
         | 
| 172 | 
            +
                alias complete_backtrace backtrace
         | 
| 173 | 
            +
                
         | 
| 174 | 
            +
                def backtrace
         | 
| 175 | 
            +
                  complete_backtrace and complete_backtrace.drop_while do |line|
         | 
| 176 | 
            +
                    line =~ %r{lib/must_be.*\.rb:}
         | 
| 177 | 
            +
                  end
         | 
| 178 | 
            +
                end
         | 
| 179 | 
            +
              
         | 
| 180 | 
            +
              private
         | 
| 181 | 
            +
                
         | 
| 182 | 
            +
                def format_args_and_block
         | 
| 183 | 
            +
                  if args.nil? or args.empty?
         | 
| 184 | 
            +
                    if block.nil?
         | 
| 185 | 
            +
                      ""
         | 
| 186 | 
            +
                    else
         | 
| 187 | 
            +
                      " {}"
         | 
| 188 | 
            +
                    end
         | 
| 189 | 
            +
                  else
         | 
| 190 | 
            +
                    args_format = "(#{args.map{|v| MustBe.short_inspect(v) }.join(", ")})"
         | 
| 191 | 
            +
                    if block.nil?
         | 
| 192 | 
            +
                      args_format
         | 
| 193 | 
            +
                    else
         | 
| 194 | 
            +
                      args_format+" {}"
         | 
| 195 | 
            +
                    end
         | 
| 196 | 
            +
                  end
         | 
| 197 | 
            +
                end
         | 
| 198 | 
            +
              end
         | 
| 199 | 
            +
              
         | 
| 200 | 
            +
              def must_notify(receiver = nil, assertion= nil, args = nil, block = nil,
         | 
| 201 | 
            +
                  additional_message = nil)
         | 
| 202 | 
            +
                note = Note === receiver ? receiver :
         | 
| 203 | 
            +
                  Note.new(receiver, assertion, args, block, additional_message)
         | 
| 204 | 
            +
                if Thread.current[:must_check__is_checking]
         | 
| 205 | 
            +
                  Thread.current[:must_check__found_note] = note
         | 
| 206 | 
            +
                else
         | 
| 207 | 
            +
                  raise note if MustBe.notifier.call(note)
         | 
| 208 | 
            +
                end
         | 
| 209 | 
            +
                note
         | 
| 210 | 
            +
              end
         | 
| 211 | 
            +
              
         | 
| 212 | 
            +
              def must_check(check_block = nil, &block)
         | 
| 213 | 
            +
                if check_block
         | 
| 214 | 
            +
                  result = nil
         | 
| 215 | 
            +
                  note = must_check do |obj|
         | 
| 216 | 
            +
                    result = check_block.arity.zero? ? check_block[] : check_block[obj]
         | 
| 217 | 
            +
                  end
         | 
| 218 | 
            +
                  if note
         | 
| 219 | 
            +
                    must_notify(block[note])
         | 
| 220 | 
            +
                  end
         | 
| 221 | 
            +
                  return result
         | 
| 222 | 
            +
                end
         | 
| 223 | 
            +
                
         | 
| 224 | 
            +
                begin
         | 
| 225 | 
            +
                  was_checking = Thread.current[:must_check__is_checking]
         | 
| 226 | 
            +
                  Thread.current[:must_check__is_checking] = true
         | 
| 227 | 
            +
                
         | 
| 228 | 
            +
                  already_found = Thread.current[:must_check__found_note]
         | 
| 229 | 
            +
                  Thread.current[:must_check__found_note] = nil
         | 
| 230 | 
            +
                
         | 
| 231 | 
            +
                  yield(self)
         | 
| 232 | 
            +
                
         | 
| 233 | 
            +
                  Thread.current[:must_check__found_note]
         | 
| 234 | 
            +
                ensure
         | 
| 235 | 
            +
                  Thread.current[:must_check__is_checking] = was_checking
         | 
| 236 | 
            +
                  Thread.current[:must_check__found_note] = already_found
         | 
| 237 | 
            +
                end
         | 
| 238 | 
            +
              end
         | 
| 239 | 
            +
            end
         | 
| 240 | 
            +
             | 
| 241 | 
            +
            ### Automatically Include in Object ###
         | 
| 242 | 
            +
             | 
| 243 | 
            +
            unless ENV['MUST_BE__DO_NOT_AUTOMATICALLY_INCLUDE_IN_OBJECT']
         | 
| 244 | 
            +
              class Object
         | 
| 245 | 
            +
                include MustBe
         | 
| 246 | 
            +
              end
         | 
| 247 | 
            +
            end
         | 
| @@ -0,0 +1,159 @@ | |
| 1 | 
            +
            module MustBe
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            private
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              def must_raise__body(method, args, &block)
         | 
| 6 | 
            +
                if args.size > 2
         | 
| 7 | 
            +
                  raise ArgumentError, "wrong number of arguments (#{args.size} for 2)"
         | 
| 8 | 
            +
                elsif args.size == 2
         | 
| 9 | 
            +
                  expected_exception = args[0]
         | 
| 10 | 
            +
                  expected_message = args[1]
         | 
| 11 | 
            +
                else
         | 
| 12 | 
            +
                  case args[0]
         | 
| 13 | 
            +
                  when nil, String, Regexp
         | 
| 14 | 
            +
                    expected_exception = Exception
         | 
| 15 | 
            +
                    expected_message = args[0]
         | 
| 16 | 
            +
                  else
         | 
| 17 | 
            +
                    expected_exception = args[0]
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
                
         | 
| 21 | 
            +
                unless expected_exception.is_a?(Class) and
         | 
| 22 | 
            +
                    expected_exception.ancestors.include?(Exception)
         | 
| 23 | 
            +
                  raise TypeError, "exception class expected"
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
                
         | 
| 26 | 
            +
                case expected_message
         | 
| 27 | 
            +
                when nil, String, Regexp
         | 
| 28 | 
            +
                else
         | 
| 29 | 
            +
                  raise TypeError, "nil, string, or regexp required"
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
                
         | 
| 32 | 
            +
                begin
         | 
| 33 | 
            +
                  result = yield
         | 
| 34 | 
            +
                rescue expected_exception => actual_exception
         | 
| 35 | 
            +
                  
         | 
| 36 | 
            +
                  is_match = expected_message.nil? ||
         | 
| 37 | 
            +
                    expected_message === actual_exception.message
         | 
| 38 | 
            +
                  
         | 
| 39 | 
            +
                  if is_match
         | 
| 40 | 
            +
                    if method == :must_not_raise
         | 
| 41 | 
            +
                      must_notify(self, :must_not_raise, args, block,
         | 
| 42 | 
            +
                        ", but raised #{actual_exception.class}"+(
         | 
| 43 | 
            +
                          expected_message ?
         | 
| 44 | 
            +
                            " with message #{actual_exception.message.inspect}" : ""))
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
                  else
         | 
| 47 | 
            +
                    if method == :must_raise
         | 
| 48 | 
            +
                      must_notify(self, :must_raise, args, block,
         | 
| 49 | 
            +
                        ", but #{actual_exception.class} with"\
         | 
| 50 | 
            +
                        " message #{actual_exception.message.inspect} was raised")
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  raise
         | 
| 55 | 
            +
                rescue Exception => actual_exception
         | 
| 56 | 
            +
                  if method == :must_raise
         | 
| 57 | 
            +
                    must_notify(self, :must_raise, args, block,
         | 
| 58 | 
            +
                      ", but #{actual_exception.class} was raised")
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
                  raise
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
                
         | 
| 63 | 
            +
                if method == :must_raise
         | 
| 64 | 
            +
                  must_notify(self, :must_raise, args, block, ", but nothing was raised")
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
                
         | 
| 67 | 
            +
                result
         | 
| 68 | 
            +
              end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
            public
         | 
| 71 | 
            +
              
         | 
| 72 | 
            +
              def must_raise(*args, &block)
         | 
| 73 | 
            +
                must_raise__body(:must_raise, args, &block)
         | 
| 74 | 
            +
              end
         | 
| 75 | 
            +
              
         | 
| 76 | 
            +
              def must_not_raise(*args, &block)
         | 
| 77 | 
            +
                must_raise__body(:must_not_raise, args, &block)
         | 
| 78 | 
            +
              end
         | 
| 79 | 
            +
              
         | 
| 80 | 
            +
              register_disabled_method(:must_raise, :must_just_yield)
         | 
| 81 | 
            +
              register_disabled_method(:must_not_raise, :must_just_yield)
         | 
| 82 | 
            +
             | 
| 83 | 
            +
            private
         | 
| 84 | 
            +
              
         | 
| 85 | 
            +
              @@must_throw__installed = false
         | 
| 86 | 
            +
              
         | 
| 87 | 
            +
              def must_throw__body(method, args, &block)    
         | 
| 88 | 
            +
                if args.size > 2
         | 
| 89 | 
            +
                  raise ArgumentError, "wrong number of arguments (#{args.size} for 2)"
         | 
| 90 | 
            +
                end
         | 
| 91 | 
            +
                tag = args[0]
         | 
| 92 | 
            +
                obj = args[1]
         | 
| 93 | 
            +
                
         | 
| 94 | 
            +
                unless @@must_throw__installed
         | 
| 95 | 
            +
                  original_throw = Kernel.instance_method(:throw)
         | 
| 96 | 
            +
                  Kernel.send(:define_method, :throw) do |*arguments|
         | 
| 97 | 
            +
                    Thread.current[:must_throw__args] = arguments
         | 
| 98 | 
            +
                    original_throw.bind(self)[*arguments]
         | 
| 99 | 
            +
                  end
         | 
| 100 | 
            +
                  @@must_throw__installed = true
         | 
| 101 | 
            +
                end
         | 
| 102 | 
            +
                
         | 
| 103 | 
            +
                begin
         | 
| 104 | 
            +
                  raised = false
         | 
| 105 | 
            +
                  returned_normaly = false
         | 
| 106 | 
            +
                  result = yield
         | 
| 107 | 
            +
                  returned_normaly = true    
         | 
| 108 | 
            +
                  result
         | 
| 109 | 
            +
                rescue Exception => ex
         | 
| 110 | 
            +
                  raised = true
         | 
| 111 | 
            +
                  if method == :must_throw
         | 
| 112 | 
            +
                    must_notify(self, :must_throw, args, block,
         | 
| 113 | 
            +
                      ", but raised #{ex.class}")
         | 
| 114 | 
            +
                  end
         | 
| 115 | 
            +
                  raise
         | 
| 116 | 
            +
                ensure
         | 
| 117 | 
            +
                  if raised
         | 
| 118 | 
            +
                  elsif returned_normaly
         | 
| 119 | 
            +
                    if method == :must_throw
         | 
| 120 | 
            +
                      must_notify(self, :must_throw, args, block, ", but did not throw")
         | 
| 121 | 
            +
                    end
         | 
| 122 | 
            +
                  else
         | 
| 123 | 
            +
                    thrown = Thread.current[:must_throw__args]
         | 
| 124 | 
            +
                    thrown_tag = thrown[0]
         | 
| 125 | 
            +
                    thrown_obj = thrown[1]
         | 
| 126 | 
            +
                    
         | 
| 127 | 
            +
                    if method == :must_throw
         | 
| 128 | 
            +
                      if args.size >= 1 and tag != thrown_tag
         | 
| 129 | 
            +
                        must_notify(self, :must_throw, args, block,
         | 
| 130 | 
            +
                          ", but threw #{thrown.map(&:inspect).join(", ")}")
         | 
| 131 | 
            +
                      elsif args.size == 2 and thrown.size < 2 || obj != thrown_obj
         | 
| 132 | 
            +
                        must_notify(self, :must_throw, args, block,
         | 
| 133 | 
            +
                          ", but threw #{thrown.map(&:inspect).join(", ")}")
         | 
| 134 | 
            +
                      end
         | 
| 135 | 
            +
                    elsif method == :must_not_throw
         | 
| 136 | 
            +
                      if args.size == 0 or args.size == 1 && tag == thrown_tag or
         | 
| 137 | 
            +
                          args.size == 2 && tag == thrown_tag && thrown.size == 2 &&
         | 
| 138 | 
            +
                            obj == thrown_obj
         | 
| 139 | 
            +
                        must_notify(self, :must_not_throw, args, block,
         | 
| 140 | 
            +
                          ", but threw #{thrown.map(&:inspect).join(", ")}")
         | 
| 141 | 
            +
                      end
         | 
| 142 | 
            +
                    end
         | 
| 143 | 
            +
                  end
         | 
| 144 | 
            +
                end
         | 
| 145 | 
            +
              end
         | 
| 146 | 
            +
             | 
| 147 | 
            +
            public
         | 
| 148 | 
            +
              
         | 
| 149 | 
            +
              def must_throw(*args, &block)
         | 
| 150 | 
            +
                must_throw__body(:must_throw, args, &block)
         | 
| 151 | 
            +
              end
         | 
| 152 | 
            +
              
         | 
| 153 | 
            +
              def must_not_throw(*args, &block)
         | 
| 154 | 
            +
                must_throw__body(:must_not_throw, args, &block)
         | 
| 155 | 
            +
              end
         | 
| 156 | 
            +
              
         | 
| 157 | 
            +
              register_disabled_method(:must_throw, :must_just_yield)
         | 
| 158 | 
            +
              register_disabled_method(:must_not_throw, :must_just_yield)
         | 
| 159 | 
            +
            end
         | 
| @@ -0,0 +1,62 @@ | |
| 1 | 
            +
            module MustBe
         | 
| 2 | 
            +
              class Proxy
         | 
| 3 | 
            +
                mandatory_methods = [:__id__, :object_id, :__send__]
         | 
| 4 | 
            +
                
         | 
| 5 | 
            +
                if RUBY_VERSION < "1.9"
         | 
| 6 | 
            +
                  mandatory_methods.map! &:to_s
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
                
         | 
| 9 | 
            +
                (instance_methods - mandatory_methods).each do |method|
         | 
| 10 | 
            +
                  undef_method(method)
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
                
         | 
| 13 | 
            +
                def initialize(delegate, assertion = :must)
         | 
| 14 | 
            +
                  unless assertion == :must or assertion == :must_not
         | 
| 15 | 
            +
                    raise ArgumentError,
         | 
| 16 | 
            +
                      "assertion (#{assertion.inspect}) must be :must or :must_not"
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                  @delegate = delegate
         | 
| 19 | 
            +
                  @assertion = assertion
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
                
         | 
| 22 | 
            +
                def method_missing(symbol, *args, &block)
         | 
| 23 | 
            +
                  result = @delegate.send(symbol, *args, &block)
         | 
| 24 | 
            +
                  assertion = result ? true : false
         | 
| 25 | 
            +
                  unless assertion == (@assertion == :must)
         | 
| 26 | 
            +
                    @delegate.must_notify(@delegate, "#{@assertion}.#{symbol}", args, 
         | 
| 27 | 
            +
                      block)
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                  result
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
              
         | 
| 33 | 
            +
              def must(message = nil, &block)
         | 
| 34 | 
            +
                if block_given?
         | 
| 35 | 
            +
                  unless block.arity > 1 ? yield(self, message) : yield(self)
         | 
| 36 | 
            +
                    if message
         | 
| 37 | 
            +
                      must_notify(message)
         | 
| 38 | 
            +
                    else
         | 
| 39 | 
            +
                      must_notify(self, __method__, nil, block)
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
                  self
         | 
| 43 | 
            +
                else
         | 
| 44 | 
            +
                  Proxy.new(self, :must)
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
              
         | 
| 48 | 
            +
              def must_not(message = nil, &block)
         | 
| 49 | 
            +
                if block_given?
         | 
| 50 | 
            +
                  if block.arity > 1 ? yield(self, message) : yield(self)
         | 
| 51 | 
            +
                    if message
         | 
| 52 | 
            +
                      must_notify(message)
         | 
| 53 | 
            +
                    else
         | 
| 54 | 
            +
                      must_notify(self, __method__, nil, block)
         | 
| 55 | 
            +
                    end
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
                  self
         | 
| 58 | 
            +
                else
         | 
| 59 | 
            +
                  Proxy.new(self, :must_not)
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
              end
         | 
| 62 | 
            +
            end
         | 
    
        data/lib/must_be.rb
    ADDED
    
    | @@ -0,0 +1,9 @@ | |
| 1 | 
            +
            here = File.expand_path(File.dirname(__FILE__))
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require here+'/must_be/core'
         | 
| 4 | 
            +
            require here+'/must_be/basic'
         | 
| 5 | 
            +
            require here+'/must_be/proxy'
         | 
| 6 | 
            +
            require here+'/must_be/containers'
         | 
| 7 | 
            +
            require here+'/must_be/containers_registered_classes'
         | 
| 8 | 
            +
            require here+'/must_be/attr_typed'
         | 
| 9 | 
            +
            require here+'/must_be/nonstandard_control_flow'
         | 
    
        data/must_be.gemspec
    ADDED
    
    | @@ -0,0 +1,71 @@ | |
| 1 | 
            +
            # Generated by jeweler
         | 
| 2 | 
            +
            # DO NOT EDIT THIS FILE DIRECTLY
         | 
| 3 | 
            +
            # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
         | 
| 4 | 
            +
            # -*- encoding: utf-8 -*-
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            Gem::Specification.new do |s|
         | 
| 7 | 
            +
              s.name = %q{must_be}
         | 
| 8 | 
            +
              s.version = "1.0.0"
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
         | 
| 11 | 
            +
              s.authors = ["William Taysom"]
         | 
| 12 | 
            +
              s.date = %q{2010-09-12}
         | 
| 13 | 
            +
              s.description = %q{must_be provides runtime assertions which can easily be disabled in production environments.  Likewise, the notifier can be customized to raise errors, log failure, enter the debugger, or anything else.}
         | 
| 14 | 
            +
              s.email = %q{wtaysom@gmail.com}
         | 
| 15 | 
            +
              s.extra_rdoc_files = [
         | 
| 16 | 
            +
                "README.md"
         | 
| 17 | 
            +
              ]
         | 
| 18 | 
            +
              s.files = [
         | 
| 19 | 
            +
                ".gitignore",
         | 
| 20 | 
            +
                 "README.md",
         | 
| 21 | 
            +
                 "Rakefile",
         | 
| 22 | 
            +
                 "VERSION",
         | 
| 23 | 
            +
                 "doc/readme/examples.rb",
         | 
| 24 | 
            +
                 "doc/readme/run_examples.rb",
         | 
| 25 | 
            +
                 "lib/must_be.rb",
         | 
| 26 | 
            +
                 "lib/must_be/attr_typed.rb",
         | 
| 27 | 
            +
                 "lib/must_be/basic.rb",
         | 
| 28 | 
            +
                 "lib/must_be/containers.rb",
         | 
| 29 | 
            +
                 "lib/must_be/containers_registered_classes.rb",
         | 
| 30 | 
            +
                 "lib/must_be/core.rb",
         | 
| 31 | 
            +
                 "lib/must_be/nonstandard_control_flow.rb",
         | 
| 32 | 
            +
                 "lib/must_be/proxy.rb",
         | 
| 33 | 
            +
                 "must_be.gemspec",
         | 
| 34 | 
            +
                 "spec/must_be/attr_typed_spec.rb",
         | 
| 35 | 
            +
                 "spec/must_be/basic_spec.rb",
         | 
| 36 | 
            +
                 "spec/must_be/containers_spec.rb",
         | 
| 37 | 
            +
                 "spec/must_be/core_spec.rb",
         | 
| 38 | 
            +
                 "spec/must_be/nonstandard_control_flow_spec.rb",
         | 
| 39 | 
            +
                 "spec/must_be/proxy_spec.rb",
         | 
| 40 | 
            +
                 "spec/notify_matcher_spec.rb",
         | 
| 41 | 
            +
                 "spec/spec_helper.rb",
         | 
| 42 | 
            +
                 "spec/typical_usage_spec.rb"
         | 
| 43 | 
            +
              ]
         | 
| 44 | 
            +
              s.homepage = %q{http://github.com/wtaysom/must_be}
         | 
| 45 | 
            +
              s.rdoc_options = ["--charset=UTF-8"]
         | 
| 46 | 
            +
              s.require_paths = ["lib"]
         | 
| 47 | 
            +
              s.rubygems_version = %q{1.3.7}
         | 
| 48 | 
            +
              s.summary = %q{must_be Runtime Assertions}
         | 
| 49 | 
            +
              s.test_files = [
         | 
| 50 | 
            +
                "spec/must_be/attr_typed_spec.rb",
         | 
| 51 | 
            +
                 "spec/must_be/basic_spec.rb",
         | 
| 52 | 
            +
                 "spec/must_be/containers_spec.rb",
         | 
| 53 | 
            +
                 "spec/must_be/core_spec.rb",
         | 
| 54 | 
            +
                 "spec/must_be/nonstandard_control_flow_spec.rb",
         | 
| 55 | 
            +
                 "spec/must_be/proxy_spec.rb",
         | 
| 56 | 
            +
                 "spec/notify_matcher_spec.rb",
         | 
| 57 | 
            +
                 "spec/spec_helper.rb",
         | 
| 58 | 
            +
                 "spec/typical_usage_spec.rb"
         | 
| 59 | 
            +
              ]
         | 
| 60 | 
            +
             | 
| 61 | 
            +
              if s.respond_to? :specification_version then
         | 
| 62 | 
            +
                current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
         | 
| 63 | 
            +
                s.specification_version = 3
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
         | 
| 66 | 
            +
                else
         | 
| 67 | 
            +
                end
         | 
| 68 | 
            +
              else
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
            end
         | 
| 71 | 
            +
             |