preconditions 0.1.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/.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