scale_rb 0.4.1 → 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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/devcontainer.json +21 -0
  3. data/Dockerfile +16 -0
  4. data/Gemfile +4 -4
  5. data/README.md +19 -6
  6. data/bin/console +0 -0
  7. data/bin/setup +0 -0
  8. data/examples/http_client_1.rb +0 -2
  9. data/examples/http_client_2.rb +0 -2
  10. data/examples/ws_client_1.rb +0 -2
  11. data/examples/ws_client_3.rb +1 -3
  12. data/examples/ws_client_4.rb +0 -2
  13. data/exe/metadata +9 -11
  14. data/lib/address.rb +1 -1
  15. data/lib/custom_assign.rb +92 -0
  16. data/lib/scale_rb/call_helper.rb +42 -0
  17. data/lib/{client → scale_rb/client}/client_ext.rb +12 -13
  18. data/lib/{client → scale_rb/client}/http_client.rb +3 -5
  19. data/lib/{client → scale_rb/client}/ws_client.rb +13 -20
  20. data/lib/scale_rb/codec.rb +25 -0
  21. data/lib/scale_rb/codec_utils.rb +128 -0
  22. data/lib/scale_rb/decode.rb +164 -0
  23. data/lib/scale_rb/encode.rb +150 -0
  24. data/lib/{hasher.rb → scale_rb/hasher.rb} +10 -8
  25. data/lib/scale_rb/metadata/metadata.rb +114 -0
  26. data/lib/{metadata → scale_rb/metadata}/metadata_v10.rb +0 -17
  27. data/lib/{metadata → scale_rb/metadata}/metadata_v11.rb +0 -17
  28. data/lib/{metadata → scale_rb/metadata}/metadata_v12.rb +0 -17
  29. data/lib/{metadata → scale_rb/metadata}/metadata_v13.rb +0 -17
  30. data/lib/{metadata → scale_rb/metadata}/metadata_v14.rb +18 -18
  31. data/lib/{metadata → scale_rb/metadata}/metadata_v9.rb +0 -17
  32. data/lib/scale_rb/metadata/registry.rb +263 -0
  33. data/lib/scale_rb/metadata/type_exp.rb +286 -0
  34. data/lib/scale_rb/portable_registry.rb +133 -0
  35. data/lib/{storage_helper.rb → scale_rb/storage_helper.rb} +16 -4
  36. data/lib/scale_rb/types.rb +233 -0
  37. data/lib/scale_rb/utils.rb +125 -0
  38. data/lib/scale_rb/version.rb +1 -1
  39. data/lib/scale_rb.rb +22 -30
  40. data/lib/type_enforcer.rb +170 -0
  41. data/scale_rb.gemspec +5 -0
  42. metadata +71 -19
  43. data/lib/codec.rb +0 -450
  44. data/lib/metadata/metadata.rb +0 -137
  45. data/lib/monkey_patching.rb +0 -115
  46. data/lib/portable_codec.rb +0 -285
  47. data/lib/registry.rb +0 -13
@@ -0,0 +1,170 @@
1
+ require_relative 'custom_assign'
2
+ require 'benchmark'
3
+
4
+ # rubocop:disable all
5
+ module TypeEnforcer
6
+
7
+ def self.extended(base)
8
+ base.instance_variable_set(:@type_enforcements, {})
9
+ base.instance_variable_set(:@applying_enforcement, false)
10
+ end
11
+
12
+ def __(method_name, param_types, return_type = nil, level: 1, skip: [])
13
+ return unless type_enforcement_enabled?
14
+
15
+ @type_enforcements[method_name] = {
16
+ params: param_types,
17
+ return: return_type,
18
+ level: level,
19
+ skip: skip
20
+ }
21
+ end
22
+
23
+ def method_added(method_name)
24
+ super
25
+ apply_enforcement(method_name)
26
+ end
27
+
28
+ private
29
+
30
+ def apply_enforcement(method_name)
31
+ return unless type_enforcement_enabled?
32
+ return if @applying_enforcement
33
+ return unless @type_enforcements.key?(method_name)
34
+
35
+ @applying_enforcement = true
36
+ begin
37
+ result = @type_enforcements[method_name]
38
+ if result[:level] > type_enforcement_level
39
+ decorate(method_name, result[:params], result[:return], result[:skip])
40
+ end
41
+ ensure
42
+ @applying_enforcement = false
43
+ end
44
+ end
45
+
46
+ def type_enforcement_enabled?
47
+ return true if ENV['ENABLE_TYPE_ENFORCEMENT'] && ENV['ENABLE_TYPE_ENFORCEMENT'] == 'true'
48
+
49
+ false
50
+ end
51
+
52
+ def type_enforcement_level
53
+ ENV['TYPE_ENFORCEMENT_LEVEL'].to_i || 2
54
+ end
55
+
56
+ def decorate(method_name, param_types, return_type, skip)
57
+ target = self
58
+ original_method = target.instance_method(method_name)
59
+ method_parameters = original_method.parameters
60
+
61
+ # only support positional args and keyword args for now
62
+ # TODO: support splat(rest), double splat(keyrest) args, and block
63
+ target.define_method(method_name) do |*args, **kwargs|
64
+ ScaleRb.logger.debug("----------------------------------------------------------")
65
+ ScaleRb.logger.debug("method: #{method_name}")
66
+ ScaleRb.logger.debug("params: args: #{args}, kwargs: #{kwargs}")
67
+ ScaleRb.logger.debug("param kinds: #{method_parameters}")
68
+ ScaleRb.logger.debug("param types: #{param_types}")
69
+
70
+ validated_args = []
71
+ validated_kwargs = {}
72
+
73
+ # build a hash of param_name => value | default_value
74
+ defaults = method_parameters.each_with_object({}) do |(_param_kind, param_name), memo|
75
+ type = param_types[param_name]
76
+ memo[param_name] = type.value if type.respond_to?(:value)
77
+ end
78
+ assigned_params = build_assigned_params(original_method, defaults, args, kwargs)
79
+ ScaleRb.logger.debug("assigned params: #{assigned_params}")
80
+
81
+ # validate each param
82
+ method_parameters.each do |param_kind, param_name|
83
+ case param_kind
84
+ when :req, :opt
85
+ value = assigned_params[param_name]
86
+ if skip.include?(param_name)
87
+ validated_args << value
88
+ else
89
+ type = param_types[param_name]
90
+ validated_args << type[value]
91
+ end
92
+ when :keyreq, :key
93
+ value = assigned_params[param_name]
94
+ if skip.include?(param_name)
95
+ validated_kwargs[param_name] = value
96
+ else
97
+ type = param_types[param_name]
98
+ validated_kwargs[param_name] = type[value]
99
+ end
100
+ when :rest, :keyrest
101
+ raise NotImplementedError, 'rest and keyrest args not supported'
102
+ end
103
+ end
104
+
105
+ result = original_method.bind(self).call(*validated_args, **validated_kwargs)
106
+
107
+ if skip.include?(:returns) && return_type
108
+ return_type[result]
109
+ else
110
+ result
111
+ end
112
+ end
113
+ end
114
+ end
115
+
116
+ # require 'dry-types'
117
+
118
+ # module Types
119
+ # include Dry.Types()
120
+ # end
121
+
122
+ # class Example
123
+ # extend TypeEnforcer
124
+
125
+ # __ :add, { a: Types::Strict::Integer, b: Types::Strict::Integer }, Types::Strict::Integer
126
+ # def self.add(a, b)
127
+ # a + b
128
+ # end
129
+
130
+ # __ :subtract, { a: Types::Strict::Integer, b: Types::Strict::Integer }, Types::Strict::Integer
131
+ # def subtract(a, b)
132
+ # a - b
133
+ # end
134
+
135
+ # __ :my_method, {
136
+ # a: Types::Strict::Integer,
137
+ # b: Types::Strict::Integer.default(2),
138
+ # c: Types::Strict::Integer,
139
+ # d: Types::Strict::Integer.default(4)
140
+ # }, Types::Strict::String
141
+ # def my_method(a, b = 2, c:, d: 4)
142
+ # "a: #{a}, b: #{b}, c: #{c}, d: #{d}"
143
+ # end
144
+ # end
145
+
146
+ # puts Example.add(1, 2) # => 3
147
+
148
+ # puts Example.new.subtract(3, 1) # => 2
149
+
150
+ # begin
151
+ # puts Example.new.subtract(3, '1')
152
+ # rescue StandardError => e
153
+ # puts e.class # => Dry::Types::ConstraintError
154
+ # puts e.message # => "1" violates constraints (type?(Integer, "1") failed)
155
+ # end
156
+
157
+ # puts Example.new.my_method(5, c: 3) # => "a: 5, b: 2, c: 3, d: 4"
158
+ # puts Example.new.my_method(5, 6, c: 3) # => "a: 5, b: 6, c: 3, d: 4"
159
+ # puts Example.new.my_method(5, 6, c: 3, d: 10) # => "a: 5, b: 6, c: 3, d: 10"
160
+ # begin
161
+ # puts Example.new.my_method(5, 6, c: 3, d: '10')
162
+ # rescue StandardError => e
163
+ # puts e.class # => Dry::Types::ConstraintError
164
+ # puts e.message # => "10" violates constraints (type?(Integer, "10") failed)
165
+ # end
166
+ # begin
167
+ # puts Example.new.my_method(5, 6, d: 10)
168
+ # rescue StandardError => e
169
+ # puts e.message # => Missing required keyword argument: c
170
+ # end
data/scale_rb.gemspec CHANGED
@@ -38,4 +38,9 @@ Gem::Specification.new do |spec|
38
38
  spec.add_dependency 'async'
39
39
  spec.add_dependency 'async-http', '~> 0.69.0'
40
40
  spec.add_dependency 'async-websocket', '~> 0.26.2'
41
+ # for logger
42
+ spec.add_dependency 'console'
43
+ # for types restriction
44
+ spec.add_dependency 'dry-struct'
45
+ spec.add_dependency 'dry-types'
41
46
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scale_rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aki Wu
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-08-05 00:00:00.000000000 Z
11
+ date: 2024-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base58
@@ -94,6 +94,48 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: 0.26.2
97
+ - !ruby/object:Gem::Dependency
98
+ name: console
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: dry-struct
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: dry-types
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
97
139
  description: This gem includes a ruby implementation of SCALE Codec, a general Substrate
98
140
  Http JSONRPC Client, and, a general Substrate Websocket JSON-RPC Client.
99
141
  email:
@@ -103,11 +145,13 @@ executables:
103
145
  extensions: []
104
146
  extra_rdoc_files: []
105
147
  files:
148
+ - ".devcontainer/devcontainer.json"
106
149
  - ".gitignore"
107
150
  - ".rspec"
108
151
  - ".rubocop.yml"
109
152
  - ".travis.yml"
110
153
  - CODE_OF_CONDUCT.md
154
+ - Dockerfile
111
155
  - Gemfile
112
156
  - LICENSE.txt
113
157
  - README.md
@@ -123,24 +167,32 @@ files:
123
167
  - examples/ws_client_error_handling.rb
124
168
  - exe/metadata
125
169
  - lib/address.rb
126
- - lib/client/client_ext.rb
127
- - lib/client/http_client.rb
128
- - lib/client/ws_client.rb
129
- - lib/codec.rb
130
- - lib/hasher.rb
131
- - lib/metadata/metadata.rb
132
- - lib/metadata/metadata_v10.rb
133
- - lib/metadata/metadata_v11.rb
134
- - lib/metadata/metadata_v12.rb
135
- - lib/metadata/metadata_v13.rb
136
- - lib/metadata/metadata_v14.rb
137
- - lib/metadata/metadata_v9.rb
138
- - lib/monkey_patching.rb
139
- - lib/portable_codec.rb
140
- - lib/registry.rb
170
+ - lib/custom_assign.rb
141
171
  - lib/scale_rb.rb
172
+ - lib/scale_rb/call_helper.rb
173
+ - lib/scale_rb/client/client_ext.rb
174
+ - lib/scale_rb/client/http_client.rb
175
+ - lib/scale_rb/client/ws_client.rb
176
+ - lib/scale_rb/codec.rb
177
+ - lib/scale_rb/codec_utils.rb
178
+ - lib/scale_rb/decode.rb
179
+ - lib/scale_rb/encode.rb
180
+ - lib/scale_rb/hasher.rb
181
+ - lib/scale_rb/metadata/metadata.rb
182
+ - lib/scale_rb/metadata/metadata_v10.rb
183
+ - lib/scale_rb/metadata/metadata_v11.rb
184
+ - lib/scale_rb/metadata/metadata_v12.rb
185
+ - lib/scale_rb/metadata/metadata_v13.rb
186
+ - lib/scale_rb/metadata/metadata_v14.rb
187
+ - lib/scale_rb/metadata/metadata_v9.rb
188
+ - lib/scale_rb/metadata/registry.rb
189
+ - lib/scale_rb/metadata/type_exp.rb
190
+ - lib/scale_rb/portable_registry.rb
191
+ - lib/scale_rb/storage_helper.rb
192
+ - lib/scale_rb/types.rb
193
+ - lib/scale_rb/utils.rb
142
194
  - lib/scale_rb/version.rb
143
- - lib/storage_helper.rb
195
+ - lib/type_enforcer.rb
144
196
  - scale_rb.gemspec
145
197
  - tea.yaml
146
198
  homepage: https://github.com/wuminzhe/scale_rb
@@ -164,7 +216,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
216
  - !ruby/object:Gem::Version
165
217
  version: '0'
166
218
  requirements: []
167
- rubygems_version: 3.3.7
219
+ rubygems_version: 3.5.16
168
220
  signing_key:
169
221
  specification_version: 4
170
222
  summary: A Ruby SCALE Codec Library, and, Substrate RPC Client