preconditions 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "yard", "~> 0.6.0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.5.2"
12
+ gem "rcov", ">= 0"
13
+ gem "rspec", ">= 2.6.0"
14
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 tucker
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,120 @@
1
+ # Preconditions #
2
+
3
+ A simple package to make the testing of method arguments easier to write and
4
+ easier to read, inspired by <a
5
+ href="http://guava-libraries.googlecode.com/svn-history/r13/trunk/javadoc/com/google/common/base/Preconditions.html">Guava's
6
+ Preconditions</a> class
7
+
8
+ ## Overview ##
9
+
10
+ The Preconditions package provides a single module, Preconditions, with methods for:
11
+
12
+ * Checking if an argument is nil
13
+ * Checking if an argument satisfies a boolean condition (e.g. x > 10)
14
+ * Checking if an argument responds to a certain method (duck typing)
15
+ * Checking if an argument is of a specific type (strict typing)
16
+
17
+ Each of these methods will raise an appropriate exception if the rule it is
18
+ applying is violated.
19
+
20
+ Preconditions can be checked either by using the `Preconditions` module
21
+ directly, as in `Preconditions::check_not_nil(x)`, or by mixing the
22
+ `Preconditions` module into your class to make the methods available without the
23
+ `Preconditions` prefix. If the module is mixed in the precondition checking
24
+ methods will be available to both class and instance methods equivalently.
25
+
26
+ ## Usage ##
27
+
28
+ To check for nil arguments:
29
+
30
+ def my_meth(arg)
31
+ Preconditions.check_not_nil(arg)
32
+ ...
33
+ end
34
+
35
+ If you wish to supply a message simply include a string as your second
36
+ parameter:
37
+
38
+ def my_meth(arg)
39
+ Preconditions.check_not_nil(arg, "nil values are evil!")
40
+ ...
41
+ end
42
+
43
+ You can even use a format if you want to interpolate some variables into your
44
+ message lazily:
45
+
46
+ def my_meth(arg)
47
+ Preconditions.check_not_nil(arg, "Using nil in context of: %s", @bigobj.to_s)
48
+ ...
49
+ end
50
+
51
+ All methods support both a message and a message/format argument pair.
52
+
53
+ To check an argument property:
54
+
55
+ def sqrt(num)
56
+ Preconditions.check_argument(num > 0)
57
+ ...
58
+ end
59
+
60
+ or alternatively
61
+
62
+ def sqrt(num)
63
+ Preconditions.check_block("sqrt doesn't yet support complex numbers") { num > 0 }
64
+ ...
65
+ end
66
+
67
+ To check the type of an object being supplied:
68
+
69
+ def sqrt(num)
70
+ Preconditions.check_type(num, Integer,
71
+ "sqrt is integer only, you supplied a %s", num.class)
72
+ ...
73
+ end
74
+
75
+ To check if an object will respond to a method you intend to call:
76
+
77
+ def sqrt(num)
78
+ Preconditions.check_reponds_to(num, :sqrt,
79
+ "yup, we're that lazy")
80
+ ...
81
+ end
82
+
83
+ If you wish to avoid the `Preconditions` prefix on every call, you can include the `Preconditions` module into your class:
84
+
85
+ class SpiffyClass
86
+ include Preconditions
87
+
88
+ def a(x)
89
+ check_not_nil(x)
90
+ ...
91
+ end
92
+
93
+ def self.b(y)
94
+ check_not_nil(y)
95
+ ...
96
+ end
97
+ end
98
+
99
+ Where possible the `check_` methods will return the object being checked. In
100
+ the cases where this is not possible (`check_argument` and `check_block`) the
101
+ boolean result of the expression is returned.
102
+
103
+ ## Contributing to preconditions ##
104
+
105
+ * Check out the latest master to make sure the feature hasn't been implemented
106
+ or the bug hasn't been fixed yet
107
+ * Check out the issue tracker to make sure someone already hasn't requested it
108
+ and/or contributed it
109
+ * Fork the project
110
+ * Start a feature/bugfix branch
111
+ * Commit and push until you are happy with your contribution
112
+ * Make sure to add tests for it. This is important so I don't break it in a
113
+ future version unintentionally.
114
+ * Please try not to mess with the Rakefile, version, or history. If you want
115
+ to have your own version, or is otherwise necessary, that is fine, but
116
+ please isolate to its own commit so I can cherry-pick around it.
117
+
118
+ ## Copyright ##
119
+
120
+ Copyright (c) 2011 Chris Tucker. See LICENSE.txt for further details.
data/Rakefile ADDED
@@ -0,0 +1,45 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "preconditions"
16
+ gem.homepage = "http://github.com/ctucker/preconditions"
17
+ gem.license = "MIT"
18
+ gem.summary = "Preconditions checking support inspired by Guava"
19
+ gem.description = <<-EOD
20
+ The Preconditions library provides a simple set of methods for checking arguments being passed into a method. Instead of writing custom checks and raising exceptions directly in your code you can use Preconditions to verify basic properties of your arguments (not-nil, satisfying a boolean expression, being of a certain type/duck-type) and raise the appropriate exception for you.
21
+ EOD
22
+ gem.email = "tucker+rubygems@glyde.com"
23
+ gem.authors = ["tucker"]
24
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
25
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
26
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
27
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
28
+ end
29
+ Jeweler::RubygemsDotOrgTasks.new
30
+
31
+ require 'rspec/core'
32
+ require 'rspec/core/rake_task'
33
+ RSpec::Core::RakeTask.new(:spec) do |spec|
34
+ spec.pattern = FileList['spec/**/*_spec.rb']
35
+ end
36
+
37
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
38
+ spec.pattern = 'spec/**/*_spec.rb'
39
+ spec.rcov = true
40
+ end
41
+
42
+ task :default => :spec
43
+
44
+ require 'yard'
45
+ YARD::Rake::YardocTask.new
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,99 @@
1
+ #
2
+ module Preconditions
3
+
4
+ module PreconditionMethods
5
+
6
+ # Check that arg is not nil, raising an ArgumentError with an optional
7
+ # message and format if it is nil
8
+ # @param arg the argument to check
9
+ # @param msg optional format string message to print
10
+ # @param fmt arguments to format into format string
11
+ # @raise [ArgumentError] if the arg is nil
12
+ def check_not_nil(arg, msg = nil, *fmt)
13
+ if arg.nil?
14
+ raise_exception(ArgumentError, msg, *fmt)
15
+ end
16
+ arg
17
+ end
18
+
19
+ # Check that given expression is satisfied. Should be used in the context of
20
+ # an checking an argument, though this is not strictly required.
21
+ # @param exp a boolean expression; if true, the argument is good, if false it is not
22
+ # @param msg optional format string message to print
23
+ # @param fmt arguments to format into format string
24
+ # @raise [ArgumentError] if exp is false
25
+ def check_argument(exp, msg = nil, *fmt)
26
+ if !exp
27
+ raise_exception(ArgumentError, msg, *fmt)
28
+ end
29
+ exp
30
+ end
31
+
32
+
33
+ # Check that given block expression is satisfied. Should be used in the context of
34
+ # an checking an argument, though this is not strictly required.
35
+ # @param msg optional format string message to print
36
+ # @param fmt arguments to format into format string
37
+ # @raise [ArgumentError] if block evaluates to false
38
+ def check_block(msg = nil, *fmt, &block)
39
+ res = yield
40
+ if !res
41
+ raise_exception(ArgumentError, msg, *fmt)
42
+ end
43
+ res
44
+ end
45
+
46
+ # Check that given object is of given type.
47
+ # @param obj object to check
48
+ # @param expected_type type of which object is expected to be an instance
49
+ # @param msg optional format string message to print
50
+ # @param fmt arguments to format into format string
51
+ # @return obj
52
+ # @raise [TypeError] if obj is not an instance of expected_type
53
+ def check_type(obj, expected_type, msg=nil, *fmt)
54
+ if !obj.kind_of?(expected_type)
55
+ raise_exception(TypeError, msg, *fmt)
56
+ end
57
+ obj
58
+ end
59
+
60
+ # Check that given object responds to given method
61
+ # @param obj object to check
62
+ # @param meth_sym symbolic name of method
63
+ # @param msg optional format string message to print
64
+ # @param fmt arguments to format into format string
65
+ # @return obj
66
+ # @raise [NameError] if meth_sym is not a method on obj
67
+ def check_responds_to(obj, meth_sym, msg=nil, *fmt)
68
+ if !obj.respond_to?(meth_sym)
69
+ raise_exception(NameError, msg, *fmt)
70
+ end
71
+ obj
72
+ end
73
+
74
+ def self.included(receiver)
75
+ receiver.extend PreconditionMethods
76
+ end
77
+
78
+ private
79
+
80
+ def raise_exception(e, msg, *fmt)
81
+ message = if !fmt.empty?
82
+ sprintf(msg, *fmt)
83
+ elsif !msg.nil?
84
+ msg
85
+ else
86
+ ''
87
+ end
88
+ raise e, message
89
+ end
90
+ end
91
+
92
+ class << self
93
+ include PreconditionMethods
94
+ end
95
+
96
+ def self.included(receiver)
97
+ receiver.send :include, PreconditionMethods
98
+ end
99
+ end
@@ -0,0 +1,72 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ class IncludingClass
4
+ include Preconditions
5
+ end
6
+
7
+ [Preconditions, IncludingClass, IncludingClass.new].each do |s|
8
+
9
+ describe "precondition checks on #{s}" do
10
+ subject { s }
11
+
12
+ it "raises an ArgumentError when checking for nil on a nil value" do
13
+ expect { subject.check_not_nil(nil) }.to raise_exception ArgumentError
14
+ end
15
+
16
+ it "returns the argument in a nil check when argument is not nil" do
17
+ subject.check_not_nil(1).should == 1
18
+ end
19
+
20
+ it "raises an ArgumentError with message when checking for nil with a supplied message" do
21
+ expect { subject.check_not_nil(nil, "expected message") }.
22
+ to raise_exception(ArgumentError, "expected message")
23
+ end
24
+
25
+ it "raises an ArgumentError with formatted message when checking for nil with a formatted message" do
26
+ expect { subject.check_not_nil(nil, "expected message is %s (%d)", "awesome", 10) }.
27
+ to raise_exception(ArgumentError, "expected message is awesome (10)")
28
+ end
29
+
30
+
31
+ it "raises an ArgumentError when checking an argument expression that is false" do
32
+ expect { subject.check_argument(false) }.
33
+ to raise_exception ArgumentError
34
+ end
35
+
36
+ it "returns the expression result when expression is true" do
37
+ subject.check_argument(true).should == true
38
+ end
39
+
40
+ it "raises an ArgumentError when checking a block that yields false" do
41
+ expect { subject.check_block { false } }.
42
+ to raise_exception ArgumentError
43
+ end
44
+
45
+ it "returns the block evaluation result when evaluation is true" do
46
+ subject.check_block { true }.should == true
47
+ end
48
+
49
+ it "raises a TypeError when argument is not of required type" do
50
+ expect { subject.check_type(1, String) }.
51
+ to raise_exception TypeError
52
+ end
53
+
54
+ it "returns the argument in a type check when the type is equal" do
55
+ subject.check_type(1, Fixnum).should == 1
56
+ end
57
+
58
+ it "returns the argument in a type check when the type is compatible" do
59
+ subject.check_type(1, Integer).should == 1
60
+ end
61
+
62
+ it "raises a NameError when argument does not support requested method" do
63
+ expect { subject.check_responds_to(1, :no_such_method) }.
64
+ to raise_exception
65
+ end
66
+
67
+ it "returns the argument when it supports the requested method" do
68
+ subject.check_responds_to(1, :succ).should == 1
69
+ end
70
+ end
71
+
72
+ end
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'preconditions'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+
12
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ require 'preconditions'
15
+
16
+ class Test::Unit::TestCase
17
+ end
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: preconditions
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - tucker
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-05-19 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ version_requirements: &id001 !ruby/object:Gem::Requirement
22
+ none: false
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ hash: 7
27
+ segments:
28
+ - 0
29
+ - 6
30
+ - 0
31
+ version: 0.6.0
32
+ name: yard
33
+ prerelease: false
34
+ type: :development
35
+ requirement: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ version_requirements: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ hash: 23
43
+ segments:
44
+ - 1
45
+ - 0
46
+ - 0
47
+ version: 1.0.0
48
+ name: bundler
49
+ prerelease: false
50
+ type: :development
51
+ requirement: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ version_requirements: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ~>
57
+ - !ruby/object:Gem::Version
58
+ hash: 7
59
+ segments:
60
+ - 1
61
+ - 5
62
+ - 2
63
+ version: 1.5.2
64
+ name: jeweler
65
+ prerelease: false
66
+ type: :development
67
+ requirement: *id003
68
+ - !ruby/object:Gem::Dependency
69
+ version_requirements: &id004 !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 3
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ name: rcov
79
+ prerelease: false
80
+ type: :development
81
+ requirement: *id004
82
+ - !ruby/object:Gem::Dependency
83
+ version_requirements: &id005 !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 23
89
+ segments:
90
+ - 2
91
+ - 6
92
+ - 0
93
+ version: 2.6.0
94
+ name: rspec
95
+ prerelease: false
96
+ type: :development
97
+ requirement: *id005
98
+ description: |
99
+ The Preconditions library provides a simple set of methods for checking arguments being passed into a method. Instead of writing custom checks and raising exceptions directly in your code you can use Preconditions to verify basic properties of your arguments (not-nil, satisfying a boolean expression, being of a certain type/duck-type) and raise the appropriate exception for you.
100
+
101
+ email: tucker+rubygems@glyde.com
102
+ executables: []
103
+
104
+ extensions: []
105
+
106
+ extra_rdoc_files:
107
+ - LICENSE.txt
108
+ - README.md
109
+ files:
110
+ - .document
111
+ - Gemfile
112
+ - LICENSE.txt
113
+ - README.md
114
+ - Rakefile
115
+ - VERSION
116
+ - lib/preconditions.rb
117
+ - spec/preconditions_spec.rb
118
+ - spec/spec_helper.rb
119
+ - test/helper.rb
120
+ homepage: http://github.com/ctucker/preconditions
121
+ licenses:
122
+ - MIT
123
+ post_install_message:
124
+ rdoc_options: []
125
+
126
+ require_paths:
127
+ - lib
128
+ required_ruby_version: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ hash: 3
134
+ segments:
135
+ - 0
136
+ version: "0"
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ hash: 3
143
+ segments:
144
+ - 0
145
+ version: "0"
146
+ requirements: []
147
+
148
+ rubyforge_project:
149
+ rubygems_version: 1.7.2
150
+ signing_key:
151
+ specification_version: 3
152
+ summary: Preconditions checking support inspired by Guava
153
+ test_files:
154
+ - spec/preconditions_spec.rb
155
+ - spec/spec_helper.rb
156
+ - test/helper.rb