delivered 0.4.0 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd1eeeeaa704a08c1b4c834b24ba5623409da015b9697df7653cd60502edd8c3
4
- data.tar.gz: 7fbce031535260897742c0f38100b23b0e62431f85dcd0f40c5b5a062a1f982a
3
+ metadata.gz: b22fc67aefea021f5a096de509e51e3ab69eb3b256388eebd764d194c23ed72d
4
+ data.tar.gz: 9fe11a083f14b7dba924435d66fce6aff92d93819b7e7ef5a5c1b0c41fb38c9c
5
5
  SHA512:
6
- metadata.gz: 3cca910f20d4d8cc948912346ff1f2c20add1e0fb7b7ba3bdaa42e81702195290b84670220579e6e6359a619e2f94f4bf4460fd0a2c9ad7227d39b2f84c42896
7
- data.tar.gz: 23ad19572356a722b933db7253810b212120f1d9d47242a4fe56b5c6009d51164d6035ede779ee9d37758e9c6d3b235d18c75f553a5b8e09bf80318c59caac64
6
+ metadata.gz: a07fe7c33a96cccc120ec61e999e45704c771c15c170f6b90e263e831bd0f80a93e76d75ff07277447eac18cd9d5defa14d7ea816f6767ecacc7f794eea393ca
7
+ data.tar.gz: 0fcf19ef982ddb7eae98cedac03723d4a66eda8b88411840e4435137bccf467141db2e4b180ed1876e660caaca7d9746e380c55afa79553d559b925840ccb409
data/Gemfile CHANGED
@@ -13,6 +13,5 @@ group :test do
13
13
  end
14
14
 
15
15
  group :development, :test do
16
- gem 'amazing_print'
17
16
  gem 'debug', platforms: %i[mri mingw x64_mingw]
18
17
  end
data/Gemfile.lock CHANGED
@@ -1,62 +1,66 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- delivered (0.4.0)
4
+ delivered (0.5.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- amazing_print (1.6.0)
10
9
  ast (2.4.2)
11
- debug (1.9.2)
10
+ date (3.4.1)
11
+ debug (1.10.0)
12
12
  irb (~> 1.10)
13
13
  reline (>= 0.3.8)
14
- io-console (0.7.2)
15
- irb (1.13.1)
14
+ io-console (0.8.0)
15
+ irb (1.15.1)
16
+ pp (>= 0.6.0)
16
17
  rdoc (>= 4.0.0)
17
18
  reline (>= 0.4.2)
18
- json (2.7.2)
19
- language_server-protocol (3.17.0.3)
20
- parallel (1.24.0)
21
- parser (3.3.1.0)
19
+ json (2.10.1)
20
+ language_server-protocol (3.17.0.4)
21
+ lint_roller (1.1.0)
22
+ parallel (1.26.3)
23
+ parser (3.3.7.1)
22
24
  ast (~> 2.4.1)
23
25
  racc
24
- psych (5.1.2)
26
+ pp (0.6.2)
27
+ prettyprint
28
+ prettyprint (0.2.0)
29
+ psych (5.2.3)
30
+ date
25
31
  stringio
26
- racc (1.8.0)
32
+ racc (1.8.1)
27
33
  rainbow (3.1.1)
28
- rdoc (6.7.0)
34
+ rdoc (6.12.0)
29
35
  psych (>= 4.0.0)
30
- regexp_parser (2.9.2)
31
- reline (0.5.8)
36
+ regexp_parser (2.10.0)
37
+ reline (0.6.0)
32
38
  io-console (~> 0.5)
33
- rexml (3.2.8)
34
- strscan (>= 3.0.9)
35
- rubocop (1.64.0)
39
+ rubocop (1.72.2)
36
40
  json (~> 2.3)
37
- language_server-protocol (>= 3.17.0)
41
+ language_server-protocol (~> 3.17.0.2)
42
+ lint_roller (~> 1.1.0)
38
43
  parallel (~> 1.10)
39
44
  parser (>= 3.3.0.2)
40
45
  rainbow (>= 2.2.2, < 4.0)
41
- regexp_parser (>= 1.8, < 3.0)
42
- rexml (>= 3.2.5, < 4.0)
43
- rubocop-ast (>= 1.31.1, < 2.0)
46
+ regexp_parser (>= 2.9.3, < 3.0)
47
+ rubocop-ast (>= 1.38.0, < 2.0)
44
48
  ruby-progressbar (~> 1.7)
45
- unicode-display_width (>= 2.4.0, < 3.0)
46
- rubocop-ast (1.31.3)
49
+ unicode-display_width (>= 2.4.0, < 4.0)
50
+ rubocop-ast (1.38.0)
47
51
  parser (>= 3.3.1.0)
48
52
  ruby-progressbar (1.13.0)
49
- stringio (3.1.0)
50
- strscan (3.1.0)
51
- sus (0.25.0)
52
- unicode-display_width (2.5.0)
53
+ stringio (3.1.5)
54
+ sus (0.32.0)
55
+ unicode-display_width (3.1.4)
56
+ unicode-emoji (~> 4.0, >= 4.0.4)
57
+ unicode-emoji (4.0.4)
53
58
 
54
59
  PLATFORMS
55
60
  arm64-darwin-22
56
61
  ruby
57
62
 
58
63
  DEPENDENCIES
59
- amazing_print
60
64
  debug
61
65
  delivered!
62
66
  rubocop
data/README.md CHANGED
@@ -26,6 +26,13 @@ end
26
26
  If an invalid argument is given to `User#create`, for example, if `age` is a `String` instead of
27
27
  the required `Integer`, a `Delivered::ArgumentError` exception will be raised.
28
28
 
29
+ Delivered also provides a handy `verify!` method to verify the type of any value.
30
+
31
+ ```ruby
32
+ Delivered.verify! 1, Integer
33
+ Delivered.verify! :yes, T.Any(:yes, :no)
34
+ ```
35
+
29
36
  ### Single and Double Splat Arguments
30
37
 
31
38
  You can use single and double splats in your method signatures, and Delivered will pass them through
@@ -92,6 +99,38 @@ sig name: T.RespondTo(:to_s)
92
99
  def create(name:); end
93
100
  ```
94
101
 
102
+ #### `RangeOf`
103
+
104
+ Value **MUST** be a Range of the given type
105
+
106
+ ```ruby
107
+ sig name: T.RangeOf(Integer)
108
+ def create(name: 1...2); end
109
+ ```
110
+
111
+ #### `ArrayOf`
112
+
113
+ Value **MUST** be an Array of the given type
114
+
115
+ ```ruby
116
+ sig names: T.ArrayOf(String)
117
+ def create(names: ['Joel', 'Ash']); end
118
+ ```
119
+
120
+ #### `Enumerable`
121
+
122
+ Value **MUST** be an Enumerable of the optional given type
123
+
124
+ ```ruby
125
+ sig users: T.Enumerable
126
+ def create(users: [1, 2]); end
127
+ ```
128
+
129
+ ```ruby
130
+ sig users: T.Enumerable(User)
131
+ def create(users: User.all); end
132
+ ```
133
+
95
134
  #### `Any`
96
135
 
97
136
  Value **MUST** be any of the given list of values, that is, the value must be one of the given list.
@@ -18,31 +18,25 @@ module Delivered
18
18
  sig_kwargs = sig_args.pop if sig_args.last.is_a?(Hash)
19
19
  end
20
20
 
21
- # ap(sig_args:, sig_kwargs:)
22
-
23
21
  meta = class << self; self; end
24
22
  sig_check = lambda do |klass, class_method, name, *args, **kwargs, &block| # rubocop:disable Metrics/BlockLength
25
- # ap(args:, kwargs:, params: klass.method(:"__#{name}").parameters)
26
-
27
23
  cname = class_method ? "#{klass.name}.#{name}" : "#{klass.class.name}##{name}"
28
24
 
29
25
  sig_args.each.with_index do |arg, i|
30
26
  args[i] => ^arg
31
- rescue NoMatchingPatternError => e
27
+ rescue NoMatchingPatternError
32
28
  raise Delivered::ArgumentError,
33
- "`#{cname}` expected #{arg.inspect} as argument #{i}, but received " \
34
- "`#{args[i].inspect}`",
35
- caller, cause: e
29
+ "#{cname} expected #{arg.inspect} as argument #{i}, but received " \
30
+ "`#{args[i].inspect}`"
36
31
  end
37
32
 
38
33
  unless sig_kwargs.empty?
39
34
  kwargs.each do |key, value|
40
35
  value => ^(sig_kwargs[key])
41
- rescue NoMatchingPatternError => e
36
+ rescue NoMatchingPatternError
42
37
  raise Delivered::ArgumentError,
43
- "`#{cname}` expected #{sig_kwargs[key].inspect} as keyword argument :#{key}, " \
44
- "but received `#{value.inspect}`",
45
- caller, cause: e
38
+ "#{cname} expected #{sig_kwargs[key].inspect} as keyword argument :#{key}, " \
39
+ "but received `#{value.inspect}`"
46
40
  end
47
41
  end
48
42
 
@@ -54,11 +48,10 @@ module Delivered
54
48
 
55
49
  begin
56
50
  result => ^returns unless returns.nil?
57
- rescue NoMatchingPatternError => e
51
+ rescue NoMatchingPatternError
58
52
  raise Delivered::ArgumentError,
59
53
  "`#{cname}` expected to return #{returns.inspect}, " \
60
- "but returned `#{result.inspect}`",
61
- caller, cause: e
54
+ "but returned `#{result.inspect}`"
62
55
  end
63
56
 
64
57
  result
@@ -13,6 +13,57 @@ module Delivered
13
13
  end
14
14
  end
15
15
 
16
+ class EnumerableType
17
+ def initialize(type)
18
+ @type = type
19
+ end
20
+
21
+ def inspect = "Enumerable(#{@type.inspect})"
22
+
23
+ if Delivered::EXPENSIVE_TYPE_CHECKS
24
+ def ===(value)
25
+ Enumerable === value && value.all? { |item| @type === item }
26
+ end
27
+ else
28
+ def ===(value)
29
+ Enumerable === value && (value.empty? || @type === value.first)
30
+ end
31
+ end
32
+ end
33
+
34
+ class ArrayOfType
35
+ def initialize(type)
36
+ @type = type
37
+ end
38
+
39
+ def inspect = "ArrayOf(#{@type.inspect})"
40
+
41
+ if Delivered::EXPENSIVE_TYPE_CHECKS
42
+ def ===(value)
43
+ Array === value && value.all? { |item| @type === item }
44
+ end
45
+ else
46
+ def ===(value)
47
+ Array === value && (value.empty? || @type === value[0])
48
+ end
49
+ end
50
+ end
51
+
52
+ class RangeOfType
53
+ def initialize(type)
54
+ @type = type
55
+ end
56
+
57
+ def inspect = "Range(#{@type&.inspect})"
58
+
59
+ def ===(value)
60
+ Range === value && (
61
+ (@type === value.begin && (nil === value.end || @type === value.end)) ||
62
+ (@type === value.end && nil === value.begin)
63
+ )
64
+ end
65
+ end
66
+
16
67
  class RespondToType
17
68
  def initialize(*methods)
18
69
  @methods = methods
@@ -53,6 +104,9 @@ module Delivered
53
104
  module_function
54
105
 
55
106
  def Nilable(type = nil) = NilableType.new(type)
107
+ def Enumerable(type = nil) = EnumerableType.new(type)
108
+ def ArrayOf(type) = ArrayOfType.new(type)
109
+ def RangeOf(type) = RangeOfType.new(type)
56
110
  def RespondTo(*methods) = RespondToType.new(*methods)
57
111
  def Any(*types) = AnyType.new(*types)
58
112
  def Boolean = BooleanType.new
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Delivered
4
- VERSION = '0.4.0'
4
+ VERSION = '0.5.0'
5
5
  end
data/lib/delivered.rb CHANGED
@@ -1,9 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Delivered
4
- class ArgumentError < ArgumentError
5
- end
4
+ EXPENSIVE_TYPE_CHECKS = ENV['DELIVERED_EXPENSIVE_TYPE_CHECKS'] != 'false'
5
+
6
+ class ArgumentError < ArgumentError; end
7
+ class VerifyError < StandardError; end
6
8
 
7
9
  autoload :Signature, 'delivered/signature'
8
10
  autoload :Types, 'delivered/types'
11
+
12
+ module_function
13
+
14
+ def verify!(value, type)
15
+ value => ^type
16
+ rescue NoMatchingPatternError => e
17
+ raise Delivered::VerifyError, "Expected `#{value.inspect}` to be #{type.inspect}", cause: e
18
+ end
9
19
  end
metadata CHANGED
@@ -1,16 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: delivered
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Moss
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-05-30 00:00:00.000000000 Z
10
+ date: 2025-02-24 00:00:00.000000000 Z
12
11
  dependencies: []
13
- description:
14
12
  email:
15
13
  - joel@developwithstyle.com
16
14
  executables: []
@@ -34,7 +32,6 @@ metadata:
34
32
  source_code_uri: https://github.com/joelmoss/delivered
35
33
  changelog_uri: https://github.com/joelmoss/delivered/releases
36
34
  rubygems_mfa_required: 'true'
37
- post_install_message:
38
35
  rdoc_options: []
39
36
  require_paths:
40
37
  - lib
@@ -49,8 +46,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
49
46
  - !ruby/object:Gem::Version
50
47
  version: '0'
51
48
  requirements: []
52
- rubygems_version: 3.5.10
53
- signing_key:
49
+ rubygems_version: 3.6.5
54
50
  specification_version: 4
55
51
  summary: Simple runtime type checking for Ruby method signatures
56
52
  test_files: []