sorbet-runtime 0.6.12473 → 0.6.12598
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/lib/types/configuration.rb +0 -10
- data/lib/types/private/abstract/data.rb +1 -1
- data/lib/types/private/methods/signature_validation.rb +9 -3
- data/lib/types/private/sealed.rb +1 -1
- data/lib/types/props/_props.rb +5 -8
- data/lib/types/props/decorator.rb +14 -37
- data/lib/types/props/has_lazily_specialized_methods.rb +1 -1
- data/lib/types/props/private/deserializer_generator.rb +10 -6
- data/lib/types/props/private/serializer_generator.rb +9 -5
- data/lib/types/props/serializable.rb +4 -9
- data/lib/types/types/t_enum.rb +2 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ebfe10c877dc0338945dbddb20e6f27e2e4570c951fe1a82f170c48e2d04a954
|
4
|
+
data.tar.gz: 5f73781d8a144940b29b411882aa9aa715b7e8096b649a7aeec5144d9d828199
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0cb2d697f780a36b05d24fecebbd931d03ba0947226f9df95e1ea083c69992fc52d1eb0688ad4ee14adadf370e97d3f334ba7c16a77a9aca310de7ff2e2f711a
|
7
|
+
data.tar.gz: 6876486f827f3e236a8bc7cf3cf323a1a09048ec9cb912d9b57cf30a0ee5b4d21e81915c4a935861fdd6b2982417e3aec23af602051f01181a481fd3ce1fc53b
|
data/lib/types/configuration.rb
CHANGED
@@ -546,16 +546,6 @@ module T::Configuration
|
|
546
546
|
@legacy_t_enum_migration_mode || false
|
547
547
|
end
|
548
548
|
|
549
|
-
@prop_freeze_handler = ->(instance, prop_name) {}
|
550
|
-
|
551
|
-
def self.prop_freeze_handler=(handler)
|
552
|
-
@prop_freeze_handler = handler
|
553
|
-
end
|
554
|
-
|
555
|
-
def self.prop_freeze_handler
|
556
|
-
@prop_freeze_handler
|
557
|
-
end
|
558
|
-
|
559
549
|
@sealed_violation_whitelist = nil
|
560
550
|
# @param [Array] sealed_violation_whitelist An array of Regexp to validate
|
561
551
|
# whether inheriting /including a sealed module outside the defining module
|
@@ -12,7 +12,7 @@
|
|
12
12
|
# modules that override the `hash` method with something completely broken.
|
13
13
|
module T::Private::Abstract::Data
|
14
14
|
def self.get(mod, key)
|
15
|
-
mod.instance_variable_get("@opus_abstract__#{key}")
|
15
|
+
mod.instance_variable_get("@opus_abstract__#{key}")
|
16
16
|
end
|
17
17
|
|
18
18
|
def self.set(mod, key, value)
|
@@ -277,6 +277,9 @@ module T::Private::Methods::SignatureValidation
|
|
277
277
|
end
|
278
278
|
end
|
279
279
|
|
280
|
+
ALLOW_INCOMPATIBLE_VISIBILITY = [:visibility, true].freeze
|
281
|
+
private_constant :ALLOW_INCOMPATIBLE_VISIBILITY
|
282
|
+
|
280
283
|
def self.validate_override_visibility(signature, super_signature)
|
281
284
|
return if super_signature.mode == Modes.untyped
|
282
285
|
# This departs from the behavior of other `validate_override_whatever` functions in that it
|
@@ -284,8 +287,8 @@ module T::Private::Methods::SignatureValidation
|
|
284
287
|
# done because the primary method for silencing these errors (`allow_incompatible: :visibility`)
|
285
288
|
# requires an `override` node to attach to. Once we have static override checking for implicitly
|
286
289
|
# overridden methods, we can remove this.
|
287
|
-
return unless
|
288
|
-
return if
|
290
|
+
return unless Modes::OVERRIDE_MODES.include?(signature.mode)
|
291
|
+
return if ALLOW_INCOMPATIBLE_VISIBILITY.include?(signature.override_allow_incompatible)
|
289
292
|
method = signature.method
|
290
293
|
super_method = super_signature.method
|
291
294
|
mode_noun = super_signature.mode == Modes.abstract ? 'implementation' : 'override'
|
@@ -305,8 +308,11 @@ module T::Private::Methods::SignatureValidation
|
|
305
308
|
end
|
306
309
|
|
307
310
|
# Higher = more restrictive.
|
311
|
+
METHOD_VISIBILITIES = %i[public protected private].freeze
|
312
|
+
private_constant :METHOD_VISIBILITIES
|
313
|
+
|
308
314
|
private_class_method def self.visibility_strength(vis)
|
309
|
-
|
315
|
+
METHOD_VISIBILITIES.find_index(vis)
|
310
316
|
end
|
311
317
|
|
312
318
|
private_class_method def self.base_override_loc_str(signature, super_signature)
|
data/lib/types/private/sealed.rb
CHANGED
@@ -70,7 +70,7 @@ module T::Private::Sealed
|
|
70
70
|
|
71
71
|
def self.validate_inheritance(caller_loc, parent, child, verb)
|
72
72
|
this_file = caller_loc&.path
|
73
|
-
decl_file = parent.instance_variable_get(:@sorbet_sealed_module_decl_file)
|
73
|
+
decl_file = parent.instance_variable_get(:@sorbet_sealed_module_decl_file)
|
74
74
|
|
75
75
|
if !this_file
|
76
76
|
raise "Could not use backtrace to determine file for #{verb} child #{child}"
|
data/lib/types/props/_props.rb
CHANGED
@@ -132,17 +132,14 @@ module T::Props
|
|
132
132
|
end
|
133
133
|
|
134
134
|
# Shorthand helper to define a `prop` with `immutable => true`
|
135
|
-
sig { params(name: Symbol,
|
136
|
-
def const(name,
|
137
|
-
if
|
135
|
+
sig { params(name: Symbol, cls: T.untyped, rules: T.untyped).void }
|
136
|
+
def const(name, cls, **rules)
|
137
|
+
if rules.key?(:immutable)
|
138
138
|
Kernel.raise ArgumentError.new("Cannot pass 'immutable' argument when using 'const' keyword to define a prop")
|
139
139
|
end
|
140
140
|
|
141
|
-
|
142
|
-
|
143
|
-
else
|
144
|
-
self.prop(name, cls_or_args, **args.merge(immutable: true))
|
145
|
-
end
|
141
|
+
rules[:immutable] = true
|
142
|
+
self.prop(name, cls, **rules)
|
146
143
|
end
|
147
144
|
|
148
145
|
def included(child)
|
@@ -174,7 +174,9 @@ class T::Props::Decorator
|
|
174
174
|
.checked(:never)
|
175
175
|
end
|
176
176
|
def prop_get(instance, prop, rules=prop_rules(prop))
|
177
|
-
|
177
|
+
# `instance_variable_get` will return nil if the variable doesn't exist
|
178
|
+
# which is what we want to have happen for the logic below.
|
179
|
+
val = instance.instance_variable_get(rules[:accessor_key])
|
178
180
|
if !val.nil?
|
179
181
|
val
|
180
182
|
elsif (d = rules[:ifunset])
|
@@ -194,7 +196,9 @@ class T::Props::Decorator
|
|
194
196
|
.checked(:never)
|
195
197
|
end
|
196
198
|
def prop_get_if_set(instance, prop, rules=prop_rules(prop))
|
197
|
-
|
199
|
+
# `instance_variable_get` will return nil if the variable doesn't exist
|
200
|
+
# which is what we want to have happen for the return value here.
|
201
|
+
instance.instance_variable_get(rules[:accessor_key])
|
198
202
|
end
|
199
203
|
alias_method :get, :prop_get_if_set # Alias for backwards compatibility
|
200
204
|
|
@@ -238,7 +242,9 @@ class T::Props::Decorator
|
|
238
242
|
end
|
239
243
|
|
240
244
|
if rules.keys.any? { |k| !valid_rule_key?(k) }
|
241
|
-
|
245
|
+
invalid_keys = rules.keys.reject { |k| valid_rule_key?(k) }
|
246
|
+
suffix = invalid_keys.size == 1 ? "" : "s"
|
247
|
+
raise ArgumentError.new("Invalid prop arg#{suffix} supplied in #{self}: #{invalid_keys.inspect}")
|
242
248
|
end
|
243
249
|
|
244
250
|
if !rules[:clobber_existing_method!] && !rules[:without_accessors] && BANNED_METHOD_NAMES.include?(name.to_sym)
|
@@ -259,6 +265,8 @@ class T::Props::Decorator
|
|
259
265
|
end
|
260
266
|
|
261
267
|
SAFE_NAME = T.let(/\A[A-Za-z_][A-Za-z0-9_-]*\z/.freeze, Regexp, checked: false)
|
268
|
+
# Should be exactly the same as `SAFE_NAME`, but with a leading `@`.
|
269
|
+
SAFE_ACCESSOR_KEY_NAME = T.let(/\A@[A-Za-z_][A-Za-z0-9_-]*\z/.freeze, Regexp, checked: false)
|
262
270
|
|
263
271
|
# Used to validate both prop names and serialized forms
|
264
272
|
sig { params(name: T.any(Symbol, String)).void.checked(:never) }
|
@@ -319,9 +327,9 @@ class T::Props::Decorator
|
|
319
327
|
sig(:final) { params(name: Symbol).returns(T::Boolean).checked(:never) }
|
320
328
|
private def method_defined_on_ancestor?(name)
|
321
329
|
(@class.method_defined?(name) || @class.private_method_defined?(name)) &&
|
322
|
-
|
323
|
-
|
324
|
-
|
330
|
+
# Unfortunately, older versions of ruby don't allow the second parameter on
|
331
|
+
# `private_method_defined?`.
|
332
|
+
(!@class.method_defined?(name, false) && !@class.private_method_defined?(name, false))
|
325
333
|
end
|
326
334
|
|
327
335
|
sig(:final) { params(name: Symbol, rules: Rules).void.checked(:never) }
|
@@ -402,8 +410,6 @@ class T::Props::Decorator
|
|
402
410
|
|
403
411
|
# extra arbitrary metadata attached by the code defining this property
|
404
412
|
|
405
|
-
validate_not_missing_sensitivity(name, rules)
|
406
|
-
|
407
413
|
# for backcompat (the `:array` key is deprecated but because the name is
|
408
414
|
# so generic it's really hard to be sure it's not being relied on anymore)
|
409
415
|
if type.is_a?(T::Types::TypedArray)
|
@@ -479,35 +485,6 @@ class T::Props::Decorator
|
|
479
485
|
end
|
480
486
|
end
|
481
487
|
|
482
|
-
# checked(:never) - Rules hash is expensive to check
|
483
|
-
sig { params(prop_name: Symbol, rules: Rules).void.checked(:never) }
|
484
|
-
private def validate_not_missing_sensitivity(prop_name, rules)
|
485
|
-
if rules[:sensitivity].nil?
|
486
|
-
if rules[:redaction]
|
487
|
-
T::Configuration.hard_assert_handler(
|
488
|
-
"#{@class}##{prop_name} has a 'redaction:' annotation but no " \
|
489
|
-
"'sensitivity:' annotation. This is probably wrong, because if a " \
|
490
|
-
"prop needs redaction then it is probably sensitive. Add a " \
|
491
|
-
"sensitivity annotation like 'sensitivity: Opus::Sensitivity::PII." \
|
492
|
-
"whatever', or explicitly override this check with 'sensitivity: []'."
|
493
|
-
)
|
494
|
-
end
|
495
|
-
# TODO(PRIVACYENG-982) Ideally we'd also check for 'password' and possibly
|
496
|
-
# other terms, but this interacts badly with ProtoDefinedDocument because
|
497
|
-
# the proto syntax currently can't declare "sensitivity: []"
|
498
|
-
if /\bsecret\b/.match?(prop_name)
|
499
|
-
T::Configuration.hard_assert_handler(
|
500
|
-
"#{@class}##{prop_name} has the word 'secret' in its name, but no " \
|
501
|
-
"'sensitivity:' annotation. This is probably wrong, because if a " \
|
502
|
-
"prop is named 'secret' then it is probably sensitive. Add a " \
|
503
|
-
"sensitivity annotation like 'sensitivity: Opus::Sensitivity::NonPII." \
|
504
|
-
"security_token', or explicitly override this check with " \
|
505
|
-
"'sensitivity: []'."
|
506
|
-
)
|
507
|
-
end
|
508
|
-
end
|
509
|
-
end
|
510
|
-
|
511
488
|
# Create `#{prop_name}_redacted` method
|
512
489
|
sig do
|
513
490
|
params(
|
@@ -16,6 +16,8 @@ module T::Props
|
|
16
16
|
module DeserializerGenerator
|
17
17
|
extend T::Sig
|
18
18
|
|
19
|
+
CAN_USE_SYMBOL_NAME = T.let(RUBY_VERSION >= "3.3.0", T::Boolean)
|
20
|
+
|
19
21
|
# Generate a method that takes a T::Hash[String, T.untyped] representing
|
20
22
|
# serialized props, sets instance variables for each prop found in the
|
21
23
|
# input, and returns the count of we props set (which we can use to check
|
@@ -29,19 +31,21 @@ module T::Props
|
|
29
31
|
.checked(:never)
|
30
32
|
end
|
31
33
|
def self.generate(props, defaults)
|
32
|
-
|
33
|
-
|
34
|
+
parts = props.filter_map do |prop, rules|
|
35
|
+
next if rules[:dont_store]
|
36
|
+
|
34
37
|
# All of these strings should already be validated (directly or
|
35
38
|
# indirectly) in `validate_prop_name`, so we don't bother with a nice
|
36
39
|
# error message, but we double check here to prevent a refactoring
|
37
40
|
# from introducing a security vulnerability.
|
38
|
-
raise unless T::Props::Decorator::SAFE_NAME.match?(prop.to_s)
|
41
|
+
raise unless T::Props::Decorator::SAFE_NAME.match?(CAN_USE_SYMBOL_NAME ? prop.name : prop.to_s)
|
39
42
|
|
40
43
|
hash_key = rules.fetch(:serialized_form)
|
41
44
|
raise unless T::Props::Decorator::SAFE_NAME.match?(hash_key)
|
42
45
|
|
43
|
-
|
44
|
-
|
46
|
+
key = rules.fetch(:accessor_key)
|
47
|
+
ivar_name = CAN_USE_SYMBOL_NAME ? key.name : key.to_s
|
48
|
+
raise unless ivar_name.start_with?('@') && T::Props::Decorator::SAFE_ACCESSOR_KEY_NAME.match?(ivar_name)
|
45
49
|
|
46
50
|
transformation = SerdeTransform.generate(
|
47
51
|
T::Utils::Nilable.get_underlying_type_object(rules.fetch(:type_object)),
|
@@ -90,7 +94,7 @@ module T::Props
|
|
90
94
|
|
91
95
|
<<~RUBY
|
92
96
|
def __t_props_generated_deserialize(hash)
|
93
|
-
found = #{
|
97
|
+
found = #{parts.size}
|
94
98
|
#{parts.join("\n\n")}
|
95
99
|
found
|
96
100
|
end
|
@@ -16,6 +16,8 @@ module T::Props
|
|
16
16
|
module SerializerGenerator
|
17
17
|
extend T::Sig
|
18
18
|
|
19
|
+
CAN_USE_SYMBOL_NAME = T.let(RUBY_VERSION >= "3.3.0", T::Boolean)
|
20
|
+
|
19
21
|
sig do
|
20
22
|
params(
|
21
23
|
props: T::Hash[Symbol, T::Hash[Symbol, T.untyped]],
|
@@ -24,19 +26,21 @@ module T::Props
|
|
24
26
|
.checked(:never)
|
25
27
|
end
|
26
28
|
def self.generate(props)
|
27
|
-
|
28
|
-
|
29
|
+
parts = props.filter_map do |prop, rules|
|
30
|
+
next if rules[:dont_store]
|
31
|
+
|
29
32
|
# All of these strings should already be validated (directly or
|
30
33
|
# indirectly) in `validate_prop_name`, so we don't bother with a nice
|
31
34
|
# error message, but we double check here to prevent a refactoring
|
32
35
|
# from introducing a security vulnerability.
|
33
|
-
raise unless T::Props::Decorator::SAFE_NAME.match?(prop.to_s)
|
36
|
+
raise unless T::Props::Decorator::SAFE_NAME.match?(CAN_USE_SYMBOL_NAME ? prop.name : prop.to_s)
|
34
37
|
|
35
38
|
hash_key = rules.fetch(:serialized_form)
|
36
39
|
raise unless T::Props::Decorator::SAFE_NAME.match?(hash_key)
|
37
40
|
|
38
|
-
|
39
|
-
|
41
|
+
key = rules.fetch(:accessor_key)
|
42
|
+
ivar_name = CAN_USE_SYMBOL_NAME ? key.name : key.to_s
|
43
|
+
raise unless ivar_name.start_with?('@') && T::Props::Decorator::SAFE_ACCESSOR_KEY_NAME.match?(ivar_name)
|
40
44
|
|
41
45
|
transformed_val = SerdeTransform.generate(
|
42
46
|
T::Utils::Nilable.get_underlying_type_object(rules.fetch(:type_object)),
|
@@ -121,8 +121,8 @@ module T::Props::Serializable
|
|
121
121
|
private def with_existing_hash(changed_props, existing_hash:)
|
122
122
|
serialized = existing_hash
|
123
123
|
new_val = self.class.from_hash(serialized.merge(recursive_stringify_keys(changed_props)))
|
124
|
-
old_extra = self.instance_variable_get(:@_extra_props)
|
125
|
-
new_extra = new_val.instance_variable_get(:@_extra_props)
|
124
|
+
old_extra = self.instance_variable_get(:@_extra_props)
|
125
|
+
new_extra = new_val.instance_variable_get(:@_extra_props)
|
126
126
|
if old_extra != new_extra
|
127
127
|
difference =
|
128
128
|
if old_extra
|
@@ -137,8 +137,7 @@ module T::Props::Serializable
|
|
137
137
|
|
138
138
|
# Asserts if this property is missing during strict serialize
|
139
139
|
private def required_prop_missing_from_serialize(prop)
|
140
|
-
if
|
141
|
-
@_required_props_missing_from_deserialize&.include?(prop)
|
140
|
+
if @_required_props_missing_from_deserialize&.include?(prop)
|
142
141
|
# If the prop was already missing during deserialization, that means the application
|
143
142
|
# code already had to deal with a nil value, which means we wouldn't be accomplishing
|
144
143
|
# much by raising here (other than causing an unnecessary breakage).
|
@@ -353,11 +352,7 @@ module T::Props::Serializable::DecoratorMethods
|
|
353
352
|
private_constant :EMPTY_EXTRA_PROPS
|
354
353
|
|
355
354
|
def extra_props(instance)
|
356
|
-
|
357
|
-
instance.instance_variable_get(:@_extra_props) || EMPTY_EXTRA_PROPS
|
358
|
-
else
|
359
|
-
EMPTY_EXTRA_PROPS
|
360
|
-
end
|
355
|
+
instance.instance_variable_get(:@_extra_props) || EMPTY_EXTRA_PROPS
|
361
356
|
end
|
362
357
|
|
363
358
|
# adds to the default result of T::Props::PrettyPrintable
|
data/lib/types/types/t_enum.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sorbet-runtime
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.12598
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stripe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-09-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|