mini_sanity 1.1.0 → 2.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.
- checksums.yaml +5 -5
- data/.travis.yml +3 -3
- data/CHANGELOG.md +60 -24
- data/Gemfile +3 -0
- data/README.md +21 -58
- data/Rakefile +0 -14
- data/lib/mini_sanity.rb +4 -6
- data/lib/mini_sanity/assert.rb +163 -0
- data/lib/mini_sanity/change.rb +107 -0
- data/lib/mini_sanity/error.rb +18 -8
- data/lib/mini_sanity/match.rb +57 -0
- data/lib/mini_sanity/results.rb +70 -0
- data/lib/mini_sanity/version.rb +1 -1
- data/mini_sanity.gemspec +11 -12
- metadata +14 -73
- data/lib/mini_sanity/array.rb +0 -63
- data/lib/mini_sanity/enumerable.rb +0 -52
- data/lib/mini_sanity/object.rb +0 -216
- data/lib/mini_sanity/pathname.rb +0 -135
- data/lib/mini_sanity/string.rb +0 -143
- data/lib/mini_sanity/util.rb +0 -3
- data/lib/mini_sanity/util/enumerable.rb +0 -31
- data/lib/mini_sanity/util/regexp.rb +0 -27
- data/lib/mini_sanity/util/string.rb +0 -77
data/lib/mini_sanity/error.rb
CHANGED
@@ -1,11 +1,21 @@
|
|
1
|
-
|
1
|
+
module MiniSanity
|
2
|
+
class Error < RuntimeError
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
"
|
8
|
-
|
9
|
-
|
4
|
+
def initialize(message, details = {})
|
5
|
+
super([
|
6
|
+
message,
|
7
|
+
*details.compact.map{|name, value| "#{name}:\n #{value}" }
|
8
|
+
].join("\n\n"))
|
9
|
+
end
|
10
|
+
|
11
|
+
# @!visibility private
|
12
|
+
def self.describe_block(&block)
|
13
|
+
if (symbol_name = block.to_s[/\(&:(.+)\)>$/, 1])
|
14
|
+
"&:#{symbol_name}"
|
15
|
+
elsif block&.source_location
|
16
|
+
"block@#{block.source_location.join(":")}"
|
17
|
+
end
|
18
|
+
end
|
10
19
|
|
20
|
+
end
|
11
21
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require_relative "error"
|
2
|
+
|
3
|
+
|
4
|
+
class String
|
5
|
+
|
6
|
+
# Like {https://docs.ruby-lang.org/en/master/String.html#method-i-match
|
7
|
+
# +String#match+}, but raises an exception if the match fails.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# "user@example.com".match!(/^([^@]+)@(.+)$/) # === MatchData
|
11
|
+
# "@user".match!(/^([^@]+)@(.+)$/) # raises exception
|
12
|
+
#
|
13
|
+
# @param pattern [Regexp]
|
14
|
+
# Pattern to search for
|
15
|
+
# @param pos [Integer]
|
16
|
+
# Position in the String to search from
|
17
|
+
# @return [MatchData]
|
18
|
+
# @raise [MiniSanity::Error]
|
19
|
+
# if +pattern+ does not match the String
|
20
|
+
def match!(pattern, pos = 0)
|
21
|
+
result = self.match(pattern, pos)
|
22
|
+
|
23
|
+
if result.nil?
|
24
|
+
raise MiniSanity::Error.new("String does not match pattern", {
|
25
|
+
"String" => self.inspect,
|
26
|
+
"Relevant portion (from position #{pos})" => (self[pos..].inspect if pos != 0),
|
27
|
+
"Pattern" => pattern.inspect,
|
28
|
+
})
|
29
|
+
end
|
30
|
+
|
31
|
+
result
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
class Regexp
|
38
|
+
|
39
|
+
# Like {https://docs.ruby-lang.org/en/master/Regexp.html#method-i-match
|
40
|
+
# +Regexp#match+}, but raises an exception if the match fails.
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# /^([^@]+)@(.+)$/.match!("user@example.com") # === MatchData
|
44
|
+
# /^([^@]+)@(.+)$/.match!("@user") # raises exception
|
45
|
+
#
|
46
|
+
# @param str [String]
|
47
|
+
# String to search
|
48
|
+
# @param pos [Integer]
|
49
|
+
# Position in +str+ to search from
|
50
|
+
# @return [MatchData]
|
51
|
+
# @raise [MiniSanity::Error]
|
52
|
+
# if the Regexp does not match +str+
|
53
|
+
def match!(str, pos = 0)
|
54
|
+
str.match!(self, pos)
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require_relative "error"
|
2
|
+
|
3
|
+
|
4
|
+
class Enumerator
|
5
|
+
|
6
|
+
# Iterates the Enumerator with a given +block+, and checks that the
|
7
|
+
# result is an Enumerable that has one or more elements. Raises an
|
8
|
+
# exception if this check fails. Otherwise, returns the Enumerable
|
9
|
+
# result.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# [1, 2, 3].select.results!(&:odd?) # == [1, 3]
|
13
|
+
# [2, 4, 6].select.results!(&:odd?) # raises exception
|
14
|
+
#
|
15
|
+
# @return [Enumerable]
|
16
|
+
# @raise [ArgumentError]
|
17
|
+
# if no +block+ is provided
|
18
|
+
# @raise [MiniSanity::Error]
|
19
|
+
# if iterating does not result in an Enumerable, or if the resulting
|
20
|
+
# Enumerable has no elements
|
21
|
+
def results!(&block)
|
22
|
+
raise ArgumentError, "Enumerator#results! requires a block" unless block
|
23
|
+
|
24
|
+
results = self.each(&block)
|
25
|
+
|
26
|
+
if !results.is_a?(Enumerable)
|
27
|
+
raise MiniSanity::Error.new("Result from Enumerator with block is not an Enumerable", {
|
28
|
+
"Enumerator" => self.inspect,
|
29
|
+
"Block" => MiniSanity::Error.describe_block(&block),
|
30
|
+
"Result" => results.inspect,
|
31
|
+
})
|
32
|
+
elsif !results.any?{ true }
|
33
|
+
raise MiniSanity::Error.new("No results from Enumerator with block", {
|
34
|
+
"Enumerator" => self.inspect,
|
35
|
+
"Block" => MiniSanity::Error.describe_block(&block),
|
36
|
+
})
|
37
|
+
end
|
38
|
+
|
39
|
+
results
|
40
|
+
end
|
41
|
+
|
42
|
+
# Iterates the Enumerator with a given +block+, and checks that the
|
43
|
+
# result is not nil. Raises an exception if the result is nil.
|
44
|
+
# Otherwise, returns the non-nil result.
|
45
|
+
#
|
46
|
+
# @example
|
47
|
+
# [1, 2, 3].find.result!(&:even?) # == 2
|
48
|
+
# [1, 3, 5].find.result!(&:even?) # raises exception
|
49
|
+
#
|
50
|
+
# @return [Object]
|
51
|
+
# @raise [ArgumentError]
|
52
|
+
# if no +block+ is provided
|
53
|
+
# @raise [MiniSanity::Error]
|
54
|
+
# if iterating results in a nil value
|
55
|
+
def result!(&block)
|
56
|
+
raise ArgumentError, "Enumerator#result! requires a block" unless block
|
57
|
+
|
58
|
+
result = self.each(&block)
|
59
|
+
|
60
|
+
if result.nil?
|
61
|
+
raise MiniSanity::Error.new("Nil result from Enumerator with block", {
|
62
|
+
"Enumerator" => self.inspect,
|
63
|
+
"Block" => MiniSanity::Error.describe_block(&block),
|
64
|
+
})
|
65
|
+
end
|
66
|
+
|
67
|
+
result
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
data/lib/mini_sanity/version.rb
CHANGED
data/mini_sanity.gemspec
CHANGED
@@ -1,27 +1,26 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path("../lib", __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require "mini_sanity/version"
|
1
|
+
require_relative "lib/mini_sanity/version"
|
5
2
|
|
6
3
|
Gem::Specification.new do |spec|
|
7
4
|
spec.name = "mini_sanity"
|
8
5
|
spec.version = MiniSanity::VERSION
|
9
6
|
spec.authors = ["Jonathan Hefner"]
|
10
|
-
spec.email = ["jonathan
|
7
|
+
spec.email = ["jonathan@hefner.pro"]
|
11
8
|
|
12
9
|
spec.summary = %q{In-line sanity checks}
|
13
10
|
spec.homepage = "https://github.com/jonathanhefner/mini_sanity"
|
14
11
|
spec.license = "MIT"
|
12
|
+
spec.required_ruby_version = ">= 2.6"
|
15
13
|
|
16
|
-
spec.
|
17
|
-
|
14
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
15
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
16
|
+
spec.metadata["changelog_uri"] = spec.metadata["source_code_uri"] + "/blob/master/CHANGELOG.md"
|
17
|
+
|
18
|
+
# Specify which files should be added to the gem when it is released.
|
19
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
20
|
+
spec.files = Dir.chdir(__dir__) do
|
21
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
22
|
end
|
19
23
|
spec.bindir = "exe"
|
20
24
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
25
|
spec.require_paths = ["lib"]
|
22
|
-
|
23
|
-
spec.add_development_dependency "bundler", "~> 1.15"
|
24
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
-
spec.add_development_dependency "minitest", "~> 5.0"
|
26
|
-
spec.add_development_dependency "yard", "~> 0.9"
|
27
26
|
end
|
metadata
CHANGED
@@ -1,74 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mini_sanity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Hefner
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: bundler
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '1.15'
|
20
|
-
type: :development
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '1.15'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: rake
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '10.0'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '10.0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: minitest
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '5.0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '5.0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: yard
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0.9'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0.9'
|
11
|
+
date: 2020-02-02 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
69
13
|
description:
|
70
14
|
email:
|
71
|
-
- jonathan
|
15
|
+
- jonathan@hefner.pro
|
72
16
|
executables: []
|
73
17
|
extensions: []
|
74
18
|
extra_rdoc_files: []
|
@@ -81,22 +25,20 @@ files:
|
|
81
25
|
- README.md
|
82
26
|
- Rakefile
|
83
27
|
- lib/mini_sanity.rb
|
84
|
-
- lib/mini_sanity/
|
85
|
-
- lib/mini_sanity/
|
28
|
+
- lib/mini_sanity/assert.rb
|
29
|
+
- lib/mini_sanity/change.rb
|
86
30
|
- lib/mini_sanity/error.rb
|
87
|
-
- lib/mini_sanity/
|
88
|
-
- lib/mini_sanity/
|
89
|
-
- lib/mini_sanity/string.rb
|
90
|
-
- lib/mini_sanity/util.rb
|
91
|
-
- lib/mini_sanity/util/enumerable.rb
|
92
|
-
- lib/mini_sanity/util/regexp.rb
|
93
|
-
- lib/mini_sanity/util/string.rb
|
31
|
+
- lib/mini_sanity/match.rb
|
32
|
+
- lib/mini_sanity/results.rb
|
94
33
|
- lib/mini_sanity/version.rb
|
95
34
|
- mini_sanity.gemspec
|
96
35
|
homepage: https://github.com/jonathanhefner/mini_sanity
|
97
36
|
licenses:
|
98
37
|
- MIT
|
99
|
-
metadata:
|
38
|
+
metadata:
|
39
|
+
homepage_uri: https://github.com/jonathanhefner/mini_sanity
|
40
|
+
source_code_uri: https://github.com/jonathanhefner/mini_sanity
|
41
|
+
changelog_uri: https://github.com/jonathanhefner/mini_sanity/blob/master/CHANGELOG.md
|
100
42
|
post_install_message:
|
101
43
|
rdoc_options: []
|
102
44
|
require_paths:
|
@@ -105,15 +47,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
105
47
|
requirements:
|
106
48
|
- - ">="
|
107
49
|
- !ruby/object:Gem::Version
|
108
|
-
version: '
|
50
|
+
version: '2.6'
|
109
51
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
52
|
requirements:
|
111
53
|
- - ">="
|
112
54
|
- !ruby/object:Gem::Version
|
113
55
|
version: '0'
|
114
56
|
requirements: []
|
115
|
-
|
116
|
-
rubygems_version: 2.6.13
|
57
|
+
rubygems_version: 3.1.2
|
117
58
|
signing_key:
|
118
59
|
specification_version: 4
|
119
60
|
summary: In-line sanity checks
|
data/lib/mini_sanity/array.rb
DELETED
@@ -1,63 +0,0 @@
|
|
1
|
-
class Array
|
2
|
-
|
3
|
-
# Checks that the Array matches a given length, and returns the Array
|
4
|
-
# unmodified. If the Array fails this check, an exception is
|
5
|
-
# raised.
|
6
|
-
#
|
7
|
-
# @example
|
8
|
-
# coord = [0, 0, 0]
|
9
|
-
# coord.assert_length(3)! # == [0, 0, 0]
|
10
|
-
#
|
11
|
-
# coord = [0, 0]
|
12
|
-
# coord.assert_length(3)! # raises exception
|
13
|
-
#
|
14
|
-
# coord = [0, 0]
|
15
|
-
# coord.assert_length(2..3)! # == [0, 0]
|
16
|
-
#
|
17
|
-
# @param length [Integer, Range<Integer>]
|
18
|
-
# length to match
|
19
|
-
# @param name [String, Symbol]
|
20
|
-
# optional name to include in the error message
|
21
|
-
# @return [self]
|
22
|
-
# @raise [MiniSanity::Error]
|
23
|
-
# if the Array length does not match +length+
|
24
|
-
def assert_length!(length, name = nil)
|
25
|
-
if !(length === self.length)
|
26
|
-
raise MiniSanity::Error.new(name,
|
27
|
-
"#{self.class} having #{length} elements",
|
28
|
-
self.inspect)
|
29
|
-
end
|
30
|
-
self
|
31
|
-
end
|
32
|
-
|
33
|
-
# Checks that the Array does not match a given length, and returns the
|
34
|
-
# Array unmodified. If the Array fails this check, an exception is
|
35
|
-
# raised.
|
36
|
-
#
|
37
|
-
# @example
|
38
|
-
# some = ["one"]
|
39
|
-
# some.refute_length!(0) # == ["one"]
|
40
|
-
#
|
41
|
-
# some = []
|
42
|
-
# some.refute_length(0)! # raises exception
|
43
|
-
#
|
44
|
-
# many = ["one", "many"]
|
45
|
-
# many.refute_length!(0..1) # == ["one", "many"]
|
46
|
-
#
|
47
|
-
# @param length [Integer, Range<Integer>]
|
48
|
-
# length to not match
|
49
|
-
# @param name [String, Symbol]
|
50
|
-
# optional name to include in the error message
|
51
|
-
# @return [self]
|
52
|
-
# @raise [MiniSanity::Error]
|
53
|
-
# if the Array length matches +length+
|
54
|
-
def refute_length!(length, name = nil)
|
55
|
-
if length === self.length
|
56
|
-
raise MiniSanity::Error.new(name,
|
57
|
-
"#{self.class} not having #{length} elements",
|
58
|
-
self.inspect)
|
59
|
-
end
|
60
|
-
self
|
61
|
-
end
|
62
|
-
|
63
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
module Enumerable
|
2
|
-
|
3
|
-
# Checks that the Enumerable is empty, and returns the Enumerable
|
4
|
-
# unmodified. If the Enumerable fails this check, an exception is
|
5
|
-
# raised.
|
6
|
-
#
|
7
|
-
# @example
|
8
|
-
# errors = []
|
9
|
-
# errors.assert_empty! # == []
|
10
|
-
#
|
11
|
-
# errors = ["something went wrong"]
|
12
|
-
# errors.assert_empty! # raises exception
|
13
|
-
#
|
14
|
-
# @param name [String, Symbol]
|
15
|
-
# optional name to include in the error message
|
16
|
-
# @return [self]
|
17
|
-
# @raise [MiniSanity::Error]
|
18
|
-
# if the Enumerable is not empty
|
19
|
-
def assert_empty!(name = nil)
|
20
|
-
if self.any?{ true }
|
21
|
-
raise MiniSanity::Error.new(name,
|
22
|
-
"empty #{self.class}",
|
23
|
-
self.inspect)
|
24
|
-
end
|
25
|
-
self
|
26
|
-
end
|
27
|
-
|
28
|
-
# Checks that the Enumerable is not empty, and returns the Enumerable
|
29
|
-
# unmodified. If the Enumerable fails this check, an exception is
|
30
|
-
# raised.
|
31
|
-
#
|
32
|
-
# @example
|
33
|
-
# ["result 1"].refute_empty! # == ["result 1"]
|
34
|
-
# [].refute_empty! # raises exception
|
35
|
-
#
|
36
|
-
# @param name [String, Symbol]
|
37
|
-
# optional name to include in the error message
|
38
|
-
# @return [self]
|
39
|
-
# @raise [MiniSanity::Error]
|
40
|
-
# if the Enumerable is empty
|
41
|
-
def refute_empty!(name = nil)
|
42
|
-
# NOTE use #any? instead of #none? because Array#none? seems to be
|
43
|
-
# significantly slower than Array#any? (and likewise for Hash)
|
44
|
-
if !self.any?{ true }
|
45
|
-
raise MiniSanity::Error.new(name,
|
46
|
-
"non-empty #{self.class}",
|
47
|
-
self.inspect)
|
48
|
-
end
|
49
|
-
self
|
50
|
-
end
|
51
|
-
|
52
|
-
end
|