typerb 0.1.8 → 0.4.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 +4 -4
- data/.github/workflows/tests.yml +24 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +16 -2
- data/Gemfile.lock +51 -50
- data/README.md +16 -2
- data/lib/typerb/exceptional.rb +8 -0
- data/lib/typerb/variable_name.rb +1 -1
- data/lib/typerb/version.rb +1 -1
- data/lib/typerb.rb +30 -1
- metadata +7 -9
- data/.ruby-version +0 -1
- data/.travis.yml +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 540b60be5aed7792e525d276c23d892343db1ea43db239d5c4b6df3664011d65
|
4
|
+
data.tar.gz: 9176075161a22f47297e406854b58f7420832630a8792c70b8dd0c49a0049860
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68ab68e33e41b5f07790814d387bd74f6924445ee44b5faf78d4a80077466ffd8c323fdff4850e746cb2ed8a08bfc3b11c576fdd6ad29014a7f116d0b758bf2e
|
7
|
+
data.tar.gz: 4bc5f3c347f2a61006e3097af2a96684a80fcc8b3471957be016466844667083092b050a2bebe564ded578365ec901ef5f11a9a1d14dfb86e21a331a2cb97c6a
|
@@ -0,0 +1,24 @@
|
|
1
|
+
name: CI RSpec & Rubocop
|
2
|
+
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
build:
|
7
|
+
runs-on: ubuntu-latest
|
8
|
+
|
9
|
+
strategy:
|
10
|
+
matrix:
|
11
|
+
ruby-version: [2.5.3, 2.6.0, 2.7.4, 3.0.1, 3.1.0]
|
12
|
+
|
13
|
+
steps:
|
14
|
+
- uses: actions/checkout@v2
|
15
|
+
- name: Set up Ruby ${{ matrix.ruby-version }}
|
16
|
+
uses: ruby/setup-ruby@v1
|
17
|
+
with:
|
18
|
+
ruby-version: ${{ matrix.ruby-version }}
|
19
|
+
- name: Install dependencies
|
20
|
+
run: bundle install
|
21
|
+
- name: Run Rubocop
|
22
|
+
run: bundle exec rubocop -DP
|
23
|
+
- name: Run tests
|
24
|
+
run: bundle exec rspec
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
AllCops:
|
2
|
-
TargetRubyVersion:
|
2
|
+
TargetRubyVersion: 3.1
|
3
|
+
NewCops: enable
|
4
|
+
SuggestExtensions: false
|
3
5
|
Exclude:
|
4
6
|
- 'bin/**/*'
|
5
7
|
- 'Guardfile'
|
@@ -17,5 +19,17 @@ Style/Documentation:
|
|
17
19
|
Style/Semicolon:
|
18
20
|
Enabled: false
|
19
21
|
|
20
|
-
|
22
|
+
Style/StringConcatenation:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
Layout/SpaceAroundMethodCallOperator:
|
26
|
+
Enabled: false
|
27
|
+
|
28
|
+
Gemspec/RequiredRubyVersion:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
Layout/LineLength:
|
21
32
|
Max: 170
|
33
|
+
|
34
|
+
Gemspec/RequireMFA:
|
35
|
+
Enabled: false
|
data/Gemfile.lock
CHANGED
@@ -1,24 +1,24 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
typerb (0.
|
4
|
+
typerb (0.4.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
ast (2.4.
|
10
|
-
awesome_print (1.
|
11
|
-
coderay (1.1.
|
12
|
-
diff-lcs (1.
|
13
|
-
ffi (1.
|
14
|
-
formatador (0.
|
15
|
-
guard (2.
|
9
|
+
ast (2.4.2)
|
10
|
+
awesome_print (1.9.2)
|
11
|
+
coderay (1.1.3)
|
12
|
+
diff-lcs (1.5.0)
|
13
|
+
ffi (1.15.5)
|
14
|
+
formatador (0.3.0)
|
15
|
+
guard (2.18.0)
|
16
16
|
formatador (>= 0.2.4)
|
17
17
|
listen (>= 2.7, < 4.0)
|
18
18
|
lumberjack (>= 1.0.12, < 2.0)
|
19
19
|
nenv (~> 0.1)
|
20
20
|
notiffany (~> 0.0)
|
21
|
-
pry (>= 0.
|
21
|
+
pry (>= 0.13.0)
|
22
22
|
shellany (~> 0.0)
|
23
23
|
thor (>= 0.18.1)
|
24
24
|
guard-compat (1.2.1)
|
@@ -26,57 +26,58 @@ GEM
|
|
26
26
|
guard (~> 2.1)
|
27
27
|
guard-compat (~> 1.1)
|
28
28
|
rspec (>= 2.99.0, < 4.0)
|
29
|
-
|
30
|
-
|
31
|
-
rb-
|
32
|
-
|
33
|
-
|
34
|
-
lumberjack (1.0.13)
|
35
|
-
method_source (0.9.2)
|
29
|
+
listen (3.7.1)
|
30
|
+
rb-fsevent (~> 0.10, >= 0.10.3)
|
31
|
+
rb-inotify (~> 0.9, >= 0.9.10)
|
32
|
+
lumberjack (1.2.8)
|
33
|
+
method_source (1.0.0)
|
36
34
|
nenv (0.3.0)
|
37
|
-
notiffany (0.1.
|
35
|
+
notiffany (0.1.3)
|
38
36
|
nenv (~> 0.1)
|
39
37
|
shellany (~> 0.0)
|
40
|
-
parallel (1.
|
41
|
-
parser (
|
42
|
-
ast (~> 2.4.
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
rb-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
rspec-
|
55
|
-
rspec-
|
56
|
-
|
57
|
-
|
58
|
-
|
38
|
+
parallel (1.21.0)
|
39
|
+
parser (3.1.0.0)
|
40
|
+
ast (~> 2.4.1)
|
41
|
+
pry (0.14.1)
|
42
|
+
coderay (~> 1.1)
|
43
|
+
method_source (~> 1.0)
|
44
|
+
rainbow (3.1.1)
|
45
|
+
rake (13.0.6)
|
46
|
+
rb-fsevent (0.11.0)
|
47
|
+
rb-inotify (0.10.1)
|
48
|
+
ffi (~> 1.0)
|
49
|
+
regexp_parser (2.2.0)
|
50
|
+
rexml (3.2.5)
|
51
|
+
rspec (3.10.0)
|
52
|
+
rspec-core (~> 3.10.0)
|
53
|
+
rspec-expectations (~> 3.10.0)
|
54
|
+
rspec-mocks (~> 3.10.0)
|
55
|
+
rspec-core (3.10.1)
|
56
|
+
rspec-support (~> 3.10.0)
|
57
|
+
rspec-expectations (3.10.2)
|
59
58
|
diff-lcs (>= 1.2.0, < 2.0)
|
60
|
-
rspec-support (~> 3.
|
61
|
-
rspec-mocks (3.
|
59
|
+
rspec-support (~> 3.10.0)
|
60
|
+
rspec-mocks (3.10.2)
|
62
61
|
diff-lcs (>= 1.2.0, < 2.0)
|
63
|
-
rspec-support (~> 3.
|
64
|
-
rspec-support (3.
|
65
|
-
rubocop (
|
66
|
-
jaro_winkler (~> 1.5.1)
|
62
|
+
rspec-support (~> 3.10.0)
|
63
|
+
rspec-support (3.10.3)
|
64
|
+
rubocop (1.24.1)
|
67
65
|
parallel (~> 1.10)
|
68
|
-
parser (>=
|
69
|
-
powerpack (~> 0.1)
|
66
|
+
parser (>= 3.0.0.0)
|
70
67
|
rainbow (>= 2.2.2, < 4.0)
|
68
|
+
regexp_parser (>= 1.8, < 3.0)
|
69
|
+
rexml
|
70
|
+
rubocop-ast (>= 1.15.1, < 2.0)
|
71
71
|
ruby-progressbar (~> 1.7)
|
72
|
-
unicode-display_width (
|
73
|
-
|
74
|
-
|
72
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
73
|
+
rubocop-ast (1.15.1)
|
74
|
+
parser (>= 3.0.1.1)
|
75
|
+
ruby-progressbar (1.11.0)
|
75
76
|
shellany (0.0.1)
|
76
77
|
super_awesome_print (0.2.5)
|
77
78
|
awesome_print
|
78
|
-
thor (
|
79
|
-
unicode-display_width (1.
|
79
|
+
thor (1.2.1)
|
80
|
+
unicode-display_width (2.1.0)
|
80
81
|
|
81
82
|
PLATFORMS
|
82
83
|
ruby
|
@@ -93,4 +94,4 @@ DEPENDENCIES
|
|
93
94
|
typerb!
|
94
95
|
|
95
96
|
BUNDLED WITH
|
96
|
-
|
97
|
+
2.3.5
|
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
[](https://badge.fury.io/rb/typerb)
|
2
|
-
[](https://github.com/olegantonyan/typerb/actions/workflows/tests.yml)
|
3
3
|
|
4
4
|
# Typerb
|
5
5
|
|
@@ -17,10 +17,19 @@ class A
|
|
17
17
|
some_arg.respond_to!(:strip)
|
18
18
|
end
|
19
19
|
|
20
|
+
def call_with_enum(arg)
|
21
|
+
arg.enum!(:one, :two)
|
22
|
+
end
|
23
|
+
|
24
|
+
def call_with_subset(arg)
|
25
|
+
arg.subset_of!([:one, :two])
|
26
|
+
end
|
20
27
|
end
|
21
28
|
|
22
29
|
A.new.call(1) #=> TypeError: `some_arg` should be String or Symbol, not Integer
|
23
30
|
A.new.call_with_respond_checks(1) #=> TypeError: 'Integer should respond to all methods: strip'
|
31
|
+
A.new.call_with_enum(:three) #=> TypeError: 'Symbol (`arg`) should be one of: [one, two], not three'
|
32
|
+
A.new.call_with_subset([:one, :three]) #=> TypeError: 'Array (`arg`) should be subset of: [:one, :two], not [:one, :three]'
|
24
33
|
```
|
25
34
|
|
26
35
|
This is equivalent to:
|
@@ -52,6 +61,11 @@ end
|
|
52
61
|
A.new.call(nil) #=> TypeError: expected not nil, but got nil
|
53
62
|
```
|
54
63
|
|
64
|
+
## Why?
|
65
|
+
|
66
|
+
1. Catch error as early as possible (especially nils);
|
67
|
+
2. Additional documentation: you're telling other people more about interfaces.
|
68
|
+
|
55
69
|
## Installation
|
56
70
|
|
57
71
|
Add this line to your application's Gemfile:
|
@@ -100,7 +114,7 @@ end
|
|
100
114
|
|
101
115
|
If you're unfamiliar with `using` keyword - this is refinement - a relatively new feature in Ruby (since 2.0). It's kind of monkey-patch, but with strict scope. Learn more about [refinements](https://ruby-doc.org/core-2.5.3/doc/syntax/refinements_rdoc.html).
|
102
116
|
|
103
|
-
This refinement adds `type!()` and `not_nil!` methods to `
|
117
|
+
This refinement adds `type!()` and `not_nil!` methods to `BasicObject` class so you can call it on any object.
|
104
118
|
|
105
119
|
The method will raise an exception if `self` is not an instance of one of the classes passed as arguments. The tricky part, however, is to get the variable name on which it's called. You need this to get a nice error message telling you exactly which variable has wrong type, not just an abstract `TypeError`. That's why we need Ruby 2.6 with its new `RubyVM::AST` (https://ruby-doc.org/core-2.6.0.preview3/RubyVM/AST.html).
|
106
120
|
|
data/lib/typerb/exceptional.rb
CHANGED
@@ -10,6 +10,14 @@ module Typerb
|
|
10
10
|
def methods_text(methods)
|
11
11
|
methods.join(', ')
|
12
12
|
end
|
13
|
+
|
14
|
+
def elements_text(elements)
|
15
|
+
'[' + elements.join(', ') + ']'
|
16
|
+
end
|
17
|
+
|
18
|
+
def superset_text(enumerable)
|
19
|
+
enumerable.to_s
|
20
|
+
end
|
13
21
|
end
|
14
22
|
|
15
23
|
def raise_with(backtrace, exception_text)
|
data/lib/typerb/variable_name.rb
CHANGED
data/lib/typerb/version.rb
CHANGED
data/lib/typerb.rb
CHANGED
@@ -5,7 +5,7 @@ require 'typerb/variable_name'
|
|
5
5
|
require 'typerb/exceptional'
|
6
6
|
|
7
7
|
module Typerb
|
8
|
-
refine
|
8
|
+
refine BasicObject do
|
9
9
|
def type!(*klasses)
|
10
10
|
raise ArgumentError, 'provide at least one class' if klasses.empty?
|
11
11
|
return self if klasses.any? { |kls| is_a?(kls) }
|
@@ -45,5 +45,34 @@ module Typerb
|
|
45
45
|
|
46
46
|
Typerb::Exceptional.new.raise_with(caller, exception_text)
|
47
47
|
end
|
48
|
+
|
49
|
+
def enum!(*elements)
|
50
|
+
raise ArgumentError, 'provide at least one enum element' if elements.empty?
|
51
|
+
return self if elements.include?(self)
|
52
|
+
|
53
|
+
elements_text = Typerb::Exceptional.elements_text(elements)
|
54
|
+
exception_text = if (var_name = Typerb::VariableName.new(caller_locations(1, 1)).get)
|
55
|
+
"#{self.class} (`#{var_name}`) should be one of: #{elements_text}, not #{self}"
|
56
|
+
else
|
57
|
+
"#{self.class} expected one of: #{elements_text}, got #{self}"
|
58
|
+
end
|
59
|
+
|
60
|
+
Typerb::Exceptional.new.raise_with(caller, exception_text)
|
61
|
+
end
|
62
|
+
|
63
|
+
def subset_of!(superset)
|
64
|
+
raise ArgumentError, 'superset must be Enumerable' unless superset.is_a?(Enumerable)
|
65
|
+
raise ArgumentError, 'provide at least one superset element' if superset.empty?
|
66
|
+
return self if (self - superset).empty?
|
67
|
+
|
68
|
+
superset_text = Typerb::Exceptional.superset_text(superset)
|
69
|
+
exception_text = if (var_name = Typerb::VariableName.new(caller_locations(1, 1)).get)
|
70
|
+
"#{self.class} (`#{var_name}`) should be subset of: #{superset_text}, not #{self}"
|
71
|
+
else
|
72
|
+
"#{self.class} expected subset of: #{superset_text}, got #{self}"
|
73
|
+
end
|
74
|
+
|
75
|
+
Typerb::Exceptional.new.raise_with(caller, exception_text)
|
76
|
+
end
|
48
77
|
end
|
49
78
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: typerb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oleg Antonyan
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -129,11 +129,10 @@ executables: []
|
|
129
129
|
extensions: []
|
130
130
|
extra_rdoc_files: []
|
131
131
|
files:
|
132
|
+
- ".github/workflows/tests.yml"
|
132
133
|
- ".gitignore"
|
133
134
|
- ".rspec"
|
134
135
|
- ".rubocop.yml"
|
135
|
-
- ".ruby-version"
|
136
|
-
- ".travis.yml"
|
137
136
|
- CODE_OF_CONDUCT.md
|
138
137
|
- Gemfile
|
139
138
|
- Gemfile.lock
|
@@ -152,7 +151,7 @@ homepage: https://github.com/olegantonyan/typerb
|
|
152
151
|
licenses:
|
153
152
|
- MIT
|
154
153
|
metadata: {}
|
155
|
-
post_install_message:
|
154
|
+
post_install_message:
|
156
155
|
rdoc_options: []
|
157
156
|
require_paths:
|
158
157
|
- lib
|
@@ -167,9 +166,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
167
166
|
- !ruby/object:Gem::Version
|
168
167
|
version: '0'
|
169
168
|
requirements: []
|
170
|
-
|
171
|
-
|
172
|
-
signing_key:
|
169
|
+
rubygems_version: 3.3.3
|
170
|
+
signing_key:
|
173
171
|
specification_version: 4
|
174
172
|
summary: Typecheck sugar for Ruby.
|
175
173
|
test_files: []
|
data/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
2.6.0-rc1
|